Skip to content

Prefer the Triad: the work-start advisory, the optional single-repository.yaml, and the posture text (prefer-triad-project-shape 5.2) - #164

Merged
brettheap merged 3 commits into
mainfrom
feat/prefer-triad-project-shape
Oct 6, 2026
Merged

brettheap merged 3 commits into
mainfrom
feat/prefer-triad-project-shape

Conversation

@brettheap

@brettheap brettheap commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Lane: codeXfactory-5

Refs #163

What this realizes

Task 5.2 of openxFactory's ratified change prefer-triad-project-shape, "opensoft/openRepoShape, the mechanics", as it reads in openspec/changes/prefer-triad-project-shape/tasks.md on openxFactory main e63809650d39586134c4ec4fdb6e9effc87a7860. The Triad, an assembly root with a spec leg and a code leg, is now this standard's PREFERRED project shape. It stays elective and confers nothing. A person starting work in a repository that has not elected it is told so once and is never stopped.

  • The advisory. scripts/shape_advisory.py (new; deliberately NOT a shape copy, so no project's pinned repo_shape.py moves) says it and decides where it is silent. It reads only declared facts:

    • an elected Triad root, by the ratified detector: project.yaml, kind: project-manifest, schema: project-repo-schema, a spec and a code leg;
    • a family holder;
    • a leg clone, by the leg template's own AGENTS.md (which names its assembly root) or, failing that, the -spec/-code form of contracts/repository-naming.yaml (told it is "named as" a leg, "if it is one");
    • a <user>-wip workspace, by the naming policy's workspace form on the directory's name or origin's, or by the person's own workspace.yaml;
    • a single-repository.yaml of the right kind.

    No other class is guessed.

  • scaffold-project.py has no single-repository mode, so "offers the Triad first" is the tool itself. Its plan now names the Triad as the preferred shape, with the posture, on two lines above the shape revision.

  • adopt-project.py plan and check print the advisory once, in the conversion's own words, and write none of it into the plan file. They read the record, the manifests and a leg's AGENTS.md out of the commit being planned, not the working tree. A leg clone gets the move-to-root note instead. The hunks are clear of fix(adopt): preserve existing gitmodules through leg extraction #162's _mount_the_legs hunk, and fix(adopt): preserve existing gitmodules through leg extraction #162's patch still applies cleanly on this tree.

  • shape-doctor.py gains one Triad row with the new status advisory, asked only of a directory with no manifest. The row is absent where the rule makes the advisory silent. A leg clone gets n/a with the move-to-root instruction, and the way in offers it no adoption. A silent record that leaves a field out gets a note. The verdict never reads the row: NOT A SHAPE ROOT stays exit 2, as the ratified D3 says ("This packet changes nothing about the doctor's exits").

  • The optional record. contracts/single-repository-record.yaml is its schema (data, with a validated example) and templates/single-repository/single-repository.yaml its template. The fields are schema_version: 1, kind: single-repository-record, decided_by, decided_on, reason and an optional revisit_on. kind: decides: an unreadable record, or one of the wrong kind, silences nothing and is reported beside the advisory, failing nothing. The advisory is its only reader, so it has no validator script of its own.

  • Posture text, preference beside posture everywhere.

    • The README [!IMPORTANT] box: "elective and confers nothing" stays, and the ruling is recorded as "Ruled by Brett Heap on 2026-10-06: "ratify 1249 as recommended"". It is followed by the advisory's scope and the record.
    • AGENTS.md's "What you must not tell them" gains, inside it, "What you DO tell them instead": the Triad is preferred, a single repository is reviewed identically, and the shape confers nothing. The section's existing two paragraphs stay word for word.
    • The posture section of templates/assembly-root/AGENTS-shape.md, and the header comment of templates/assembly-root/project.yaml.
    • docs/handbook.html regenerated for all of it, with its README blob hash.
  • Tests.

    • New tests/test_shape_advisory.py (40 tests): a single repository hears it, and every exit is unchanged; silence for a Triad root, a family holder, a <user>-wip (four ways), and a valid record; the move-to-root instruction for a leg clone; advisory plus report for a wrong-kind, unparsable, non-mapping or directory record; no class guessed; schema, template and module agree; only the three tools import the advisory; nothing is written; and the review round's cases below.
    • tests/test_repo_hygiene.py: new module lists, plus the AGENTS.md cap (446 to 464) and the README cap (1376 to 1416), each raised with a dated reason.
    • tests/test_shape_doctor.py: two exact row-set assertions gain the new row.

docs/cli.md does not change, because no --help text moved: render-cli-reference.py --check reports [ok] docs/cli.md is what the generator produces.

Review round (F1-F9)

An independent review of ce2d84d raised nine findings. All nine are taken; F8 is a disclosure rather than a code change.

  • F1, the advisory can never crash a run or change its exit. shape_advisory.read() wraps its body in except Exception and answers NOT_ANSWERED, which is silent. KeyboardInterrupt and SystemExit are not Exceptions and still propagate. The doctor's check_triad_advisory returns no row rather than raising. adopt-project.py flattens every advisory line to ASCII, as the doctor already does for its rows, and swallows anything left. New tests, each asserting the exit is unchanged (doctor 2, adopt-project.py plan 0) and that no traceback is printed: an undecodable record; a record nested 600 deep (RecursionError); a NUL byte in workspace.yaml's path:; and a non-ASCII kind: under PYTHONIOENCODING=ascii. On the old code, the last three failed: the doctor crashed (--json was not JSON), read() raised ValueError: embedded null byte, and adopt-project.py plan exited 1 with a UnicodeEncodeError. The undecodable case was already handled, so it now guards against a regression.
  • F2, mutations. The single-repository doctor test now also runs the text report and asserts no REFUSED on stderr and no CANNOT ANSWER on stdout. A new test on a project.yaml root that is short of a Triad asserts the verdict and exit are identical with and without a valid record, and that there is no Triad row.
    • Mutation (a), detail["environment"] = True on the advisory row: killed by test_a_single_repository_hears_it_once_and_its_exit_is_unchanged. 1 failed, 39 passed.
    • Mutation (b), dropping UnicodeDecodeError from read_record's except: the clause is now except Exception, so the literal mutation no longer exists. The equivalent narrowing, except (Refusal, OSError, YamlError), is killed by test_a_record_nobody_can_read_fails_nothing[undecodable] and [nested-past-the-recursion-limit]. 2 failed, 38 passed.
  • F3, a leg clone. the way in no longer offers adopt-project.py plan to a leg clone: it has no NEXT, and its reason sends the person to the Triad row. A leg known by its name alone is told "<name> is named as the leg of <X> under contracts/repository-naming.yaml ...; if it is one, work from its assembly root ...". A leg whose own AGENTS.md says so keeps the plain wording. The AGENTS.md route is checked first. Tests cover the name-only wording (Atlas-spec, billing-code), the AGENTS.md route, and the absence of the adopt NEXT on both.
  • F4, project roots. The Triad row is now asked only on NOT A SHAPE ROOT, so a project.yaml that is short of a Triad keeps its manifest finding and is never called "a single repository". F2's new test asserts the row is absent and the verdict and exit are unchanged.
  • F5, the documentation. The README and the handbook now say the Triad row names no command in any status. Before, they said only the advisory status lacked one, when the leg's n/a and the record's note rows lack one too.
  • F6, byte-order mark. A leading UTF-8 BOM is stripped before the record's first key and before a leg AGENTS.md's opening sentence. One test covers both.
  • F7, AGENTS.md. The statement of what to tell them now sits INSIDE "What you must not tell them", after its two unchanged paragraphs. It says the Triad is preferred, a project choosing a single repository is reviewed identically, and the shape confers nothing. The cap is 464, with its dated reason rewritten. The handbook mirrors the change.
  • F8, disclosed (see below).
  • F9, the planned commit. adopt-project.py plan and check now read the record, both manifests and a leg's AGENTS.md from the commit the plan is written against (git cat-file), not from the working tree. The doctor still reads the disk, which is its contract. A test covers an uncommitted record: adopt still advises, the doctor is silent, and both are silent once the record is committed.

Left unchanged on purpose:

  • adopt-project.py's own ambiguous-top-level-yaml question about a single-repository.yaml.
  • Unattended --json behaviour.
  • A pre-existing crash on a non-UTF-8 origin URL. It is present at base 39d5c986, it is not this pull request's, and it is out of scope here.

F8 disclosure: existing Triads will show AGENTS-shape.md as upstream-changed

This pull request edits templates/assembly-root/AGENTS-shape.md, a shape copy. Until each project runs update-shape.py apply on its own word, every existing Triad will report that file as upstream-changed in update-shape.py check and in the doctor's shape-currency row. That covers openDox, openXdox and MedxEHR. It is a note, not a finding: it moves no verdict, and nothing here touches those projects.

Merge method

Squash-merge this pull request. The branch carries the account-swap WIP checkpoint d8331ea, and main is squash-style.

Copilot review not requested (Brett Heap, 2026-10-06). Codex review not requested either: it is out of quota.

Brett Heap's words, verbatim

  • 2026-10-06T10:20:12Z: "the triad should be the prefered structure and should prompt or warn the user if working on a non Triad repo."
  • 2026-10-06T16:02:16Z: "ratify 1249 as recommended", which ratified openxFactory PR #1249.
  • 2026-10-06T17:31:10Z: "merge 1249", which merged it.
  • 2026-10-06T17:41:18Z: "usage is fine, launch all four", which launched the realization.

None of these is a merge word for this pull request.

Validation evidence

  • Full suite, python3 -m pytest tests -q -rs:
    • clean main 39d5c986: 1159 passed, 33 skipped (1192), exit 0;
    • this branch, at ce2d84d (before the review round): 1191 passed, 33 skipped (1224), exit 0;
    • this branch, at ff73958 (after the review round): 1200 passed, 33 skipped (1233), exit 0. The 41 more passing than main are the 40 advisory tests, plus one new parametrized case in the hygiene suite for scripts/shape_advisory.py.
    • The skips are the same environmental ones on both trees: 32 for git-filter-repo not being installed on the measuring machine, and 1 for the MedxEHR-backed plan test, which needs a read-only clone.
  • New tests: tests/test_shape_advisory.py, 40 passed. Against the pre-round code at ce2d84d, the same file fails 11 of them: the F1, F3, F4, F6 and F9 cases.
  • Lint, as CI runs it: actionlint on .github/workflows/tests.yml and the two template validate.yml files exits 0. CI does not run pyflakes. Run locally on every touched Python file, it reports nothing that main does not already report.
  • CLI reference: scripts/render-cli-reference.py --check exits 0.
  • Overlap with fix(adopt): preserve existing gitmodules through leg extraction #162: git apply --check of PR fix(adopt): preserve existing gitmodules through leg extraction #162's diff on this tree is clean.
  • Before each push to this public repository: the diff was scanned for tokens, keys and workstation-absolute paths with no hits, and test_no_committed_file_names_a_host_absolute_path passes.

What follows, and is not this pull request's act

openxFactory's pin advance, contracts/openreposhape-pin.yaml (task 5.3), follows after this lands. It is not this pull request's act.

The edit to templates/assembly-root/AGENTS-shape.md reaches existing projects only through update-shape.py check and apply, on each project's own word. No project is touched here.

Held for Brett Heap's merge word; do not merge.

🤖 Generated with Claude Code

Summary by Sourcery

Introduce the Triad as the preferred but elective project shape with a non-blocking work-start advisory and an optional single-repository declaration.

New Features:

  • Add a shared advisory that identifies repositories which should hear the Triad preference while remaining silent for declared Triad roots, family holders, leg clones, workspaces, and recorded single repositories.
  • Add an optional single-repository record schema and template for projects that choose to remain in one repository.
  • Surface the Triad preference in scaffold and adoption plans and add a non-blocking Triad advisory row to the shape doctor.

Enhancements:

  • Preserve existing conversion and doctor verdict behavior by ensuring advisories are informational, unwritten, and never affect exit statuses.
  • Centralize advisory classification and reporting across the scaffold, adoption, and doctor tools.
  • Document the Triad preference, its non-governance posture, advisory scope, and single-repository opt-out across user and agent guidance.

Documentation:

  • Regenerate the handbook with the new Triad preference, advisory behavior, record guidance, and repository layout entries.

Tests:

  • Add comprehensive coverage for advisory classification, silence rules, malformed records, leg guidance, output behavior, non-mutating operation, and unchanged exits.
  • Update hygiene and shape-doctor expectations for the new advisory module and status.

brettheap and others added 2 commits October 6, 2026 18:12
…schema and template, and the doctor's advisory row

Partial realization of openxFactory prefer-triad-project-shape task 5.2
(Refs #163). Checkpointed mid-task for an account swap; NOT complete.

In this commit:
- scripts/shape_advisory.py: the one module that says the advisory and
  decides where it is silent (elected Triad, family holder, leg clone,
  <user>-wip workspace, a single-repository.yaml of the right kind), from
  declared facts only; the only reader of single-repository.yaml. Not a
  shape copy, so no project's pinned repo_shape.py moves.
- contracts/single-repository-record.yaml: the record's schema, as data.
- templates/single-repository/single-repository.yaml: its template.
- shape-doctor.py: an `advisory` status and a `triad-advisory` row (absent
  where silent; n/a with the move-to-root instruction for a leg clone; a
  note for a silent record missing a field). Never moves the verdict; NOT A
  SHAPE ROOT stays exit 2.

Not yet done: scaffold and adopt advisory lines, README / AGENTS.md /
AGENTS-shape.md / project.yaml template posture text, handbook regeneration,
hygiene caps and module lists, new tests and the two updated row-set
assertions. Tests are expected to be red at this commit.

Lane: codeXfactory-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… optional single-repository.yaml, and the posture text

Realizes task 5.2 of openxFactory's ratified prefer-triad-project-shape
(Refs #163): the Triad -- an assembly root with a spec leg and a code
leg -- is the PREFERRED project shape, it stays elective and confers
nothing, and a person starting work outside one is told so once and never
stopped.

- scaffold-project.py: the plan names the Triad, the only thing it
  creates, as the preferred shape, with the posture, above the revision.
- adopt-project.py: plan and check print the advisory once in the
  conversion's own words; nothing of it is written into the plan.
- shape-doctor.py: the module docstring and the `what is here` row name
  the new row and the record.
- README posture box (ruled by Brett Heap on 2026-10-06, "ratify 1249 as
  recommended"), the advisory's scope and the optional record; AGENTS.md
  "What you do tell them" beside "What you must not tell them", which
  stays; the assembly-root AGENTS-shape.md and project.yaml posture
  comment; docs/handbook.html regenerated with its README blob.
- tests: test_shape_advisory.py (31), the hygiene module lists and the
  AGENTS.md 446 -> 465 and README 1376 -> 1416 caps with dated reasons,
  and the two doctor row sets that now carry the advisory row.

Suite: 1191 passed, 33 skipped on this tree; clean main 39d5c98 is 1159
passed, 33 skipped. The skips are environmental on both: 32 for a missing
git-filter-repo, 1 for the MedxEHR-backed plan test.

Lane: codeXfactory-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

@codex review

@sourcery-ai

sourcery-ai Bot commented Oct 6, 2026

Copy link
Copy Markdown

Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 3 days and 2 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@sourcery-ai

sourcery-ai Bot commented Oct 6, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR implements the Triad as the preferred but strictly elective project shape by centralizing a declaration-based, non-blocking advisory, integrating it into scaffolding, adoption, and doctor reporting, adding an optional single-repository record, and updating guidance, generated documentation, and regression coverage without changing review gates or doctor exit semantics.

Sequence diagram for the non-blocking work-start advisory

sequenceDiagram
    actor Person
    participant Tool as scaffold/adopt/doctor
    participant Advisory as shape_advisory.py
    participant Repo as Repository facts

    Person->>Tool: Start planning or checking work
    Tool->>Advisory: read(repository)
    Advisory->>Repo: Read declared manifests, naming, workspace, record
    Repo-->>Advisory: Declared facts
    alt Triad, family, leg, workspace, or valid record
        Advisory-->>Tool: Silent or leg move-to-root instruction
    else Unclassified repository
        Advisory-->>Tool: Triad preference and posture
    end
    Tool-->>Person: Print once and continue
    Tool-->>Person: Preserve plan, verdict, and exit status
Loading

State diagram for advisory silence and reporting

stateDiagram-v2
    [*] --> ReadRepository
    ReadRepository --> Silent: Triad root / family holder / workspace
    ReadRepository --> LegInstruction: Leg clone
    ReadRepository --> Silent: Valid single-repository record
    ReadRepository --> Advisory: No declared class
    ReadRepository --> AdvisoryWithReport: Invalid or wrong-kind record
    Silent --> [*]
    LegInstruction --> [*]
    Advisory --> [*]
    AdvisoryWithReport --> [*]

    note right of Advisory
      Non-blocking advisory row or message
    end note
    note right of AdvisoryWithReport
      Record problem reported; nothing fails
    end note
Loading

File-Level Changes

Change Details Files
Add a centralized, declaration-based Triad preference advisory with explicit silence and leg-clone rules.
  • Detect elected Triad roots, family holders, leg clones, workspaces, valid single-repository records, and otherwise advise without guessing repository classes.
  • Keep advisory text non-blocking, non-persistent, and outside review or gate behavior.
  • Share advisory wording and classification across scaffold, adoption, and doctor surfaces.
scripts/shape_advisory.py
scaffold-project.py
adopt-project.py
shape-doctor.py
Introduce an optional single-repository decision record and expose its status without adding validation or enforcement.
  • Define the record schema, fields, example, and hand-filled template.
  • Treat only a parseable mapping with the expected kind as silencing the advisory.
  • Report malformed, wrong-kind, or incomplete records as informational output without failing commands.
contracts/single-repository-record.yaml
templates/single-repository/single-repository.yaml
shape-doctor.py
README.md
Update project guidance and generated documentation to establish the Triad as preferred while preserving its elective, non-conferring posture.
  • Document when assistants should state the preference and when they must remain silent.
  • Add preference/posture text to README, assembly-root guidance, manifest comments, and the handbook.
  • List the new advisory module, schema, and template in repository layout documentation.
AGENTS.md
README.md
templates/assembly-root/AGENTS-shape.md
templates/assembly-root/project.yaml
docs/handbook.html
Extend test and hygiene coverage for advisory behavior, record handling, doctor rows, and repository metadata.
  • Add 31 advisory tests covering classifications, output, exit-code preservation, malformed records, schema/template agreement, import boundaries, and write protection.
  • Update doctor row-set assertions and hygiene module/line-count expectations.
  • Preserve CLI reference validation and document that the pin advance is out of scope.
tests/test_shape_advisory.py
tests/test_shape_doctor.py
tests/test_repo_hygiene.py

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

… leg, read the planned commit

The #164 review round (F1-F9):

- F1: the advisory can no longer crash a run or change an exit status.
  shape_advisory.read() answers NOT_ANSWERED (silent) on any Exception;
  the doctor's Triad row is dropped rather than raised; adopt flattens
  its lines to ASCII and swallows the rest. KeyboardInterrupt and
  SystemExit still propagate. Tests: an undecodable record, a record
  nested past the recursion limit, a NUL byte in workspace.yaml's path,
  and a non-ASCII kind on an ascii console -- exit unchanged, no
  traceback.
- F2: the single-repository doctor test now also runs the text report
  and asserts no REFUSED / CANNOT ANSWER, which kills the
  detail["environment"] mutation; a broken assembly root's verdict and
  exit are asserted identical with and without a valid record.
- F3: `the way in` offers no adoption for a leg clone, and a leg known
  by its name alone is told it is "named as" a leg, "if it is one".
- F4: the Triad row is asked only where there is no manifest; a
  project.yaml short of a Triad keeps its manifest finding instead.
- F5: README and handbook say the Triad row names no command in any
  status.
- F6: a leading UTF-8 BOM is dropped before the record's first key and
  before a leg AGENTS.md's opening sentence.
- F7: "What you DO tell them instead" now sits inside AGENTS.md's
  "What you must not tell them" (Triad preferred, a single repository
  reviewed identically, the shape confers nothing); AGENTS.md cap
  465 -> 464.
- F9: adopt-project.py plan/check read the record, manifests and leg
  AGENTS.md from the commit being planned, not the working tree.

Handbook regenerated for the README change (README.md blob
095a1b9).

Refs #163

Lane: codeXfactory-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@brettheap
brettheap merged commit 1a9fc53 into main Oct 6, 2026
5 checks passed
@brettheap
brettheap deleted the feat/prefer-triad-project-shape branch October 6, 2026 22:52
@brettheap

Copy link
Copy Markdown
Contributor Author

LANDED — lane codeXfactory-5, session ed23f049-7e99-4601-8a6d-760b6aeb5f26@Eagle, 2026-10-06T22:52:05Z, PR #164 into opensoft/openRepoShape main → squash 1a9fc537bcce37301c85fc108fabd8a599b02000

Merged on Brett Heap's word "merge 164 when green", at head ff739588 after the independent review's fix round F1-F9, with tests, tests-macos, tests-windows and SonarCloud all green. The squash folds away the WIP checkpoint d8331ea. Next: openxFactory's task 5.3 advances contracts/openreposhape-pin.yaml onto this commit, held for its own merge word. openDox, openXdox and MedxEHR will show AGENTS-shape.md as upstream-changed until each runs update-shape.py apply.

Copilot review not requested (Brett Heap, 2026-10-06).

Lane: codeXfactory-5

brettheap added a commit to opensoft/openxFactory that referenced this pull request Oct 7, 2026
…ged evidence

Records the realization lane's own merged acts in tasks.md, on 5.1's pattern
(PR #1254). Edits only the 5.2-5.5 lines; 5.6 stays unticked, and 5.7 is left
exactly as #1255 merged it.

- 5.2: opensoft/openRepoShape#164 -> 1a9fc537 (squash, 2026-10-06T22:52:05Z);
  tests, tests-macos, tests-windows and SonarCloud green; full suite 1159 ->
  1200 passed, 33 skipped.
- 5.3: this PR (#1260) -> 9af2207, the pin advance; openreposhape-pin-gate
  green on it (run 37550154276).
- 5.4: opensoft/openBenches#139 -> 9fbe609c and #140 -> d86ba59b; post-merge
  main CI green; bootstrap suite 1042 PASS; workBenches#138 closed completed.
- 5.5: the private brettheap/new-workstation, cited by merged sha and file
  name only: #52 -> e081c5ab, #53 -> cb411460; no CI there; the live
  ~/.agents files are byte-identical to cb411460.

Each tick holds on main only through this pull request's merge, which waits on
Brett Heap's merge word and its required checks.

Lane: codeXfactory-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit to opensoft/openRepoTools that referenced this pull request Oct 8, 2026
…adopter fix for a source with an existing submodule and opensoft/openRepoShape#164's prefer-triad advisory; none of the eight mounted files moved (#188)

The triad migration (#186, first act; the plan's
T005) rehearses adopt-project.py against this repository, which carries
a submodule of its own. At 39d5c98 the adopter refused that source at
the first leg mount (adopter-blocker.md on 004-migrate-to-triad);
opensoft/openRepoShape#162 fixed it and landed on that repository's main as
7f84ca4. The rehearsal must run the tool at a commit this repository
pins, so the pin moves first.

On openRepoShape's main, as AGENTS.md's rule 2 requires:
  gh api repos/opensoft/openRepoShape/compare/main...7f84ca42ca86a8902928345109d2bf6bad87bd91 --jq .status
  -> identical (7f84ca4 is main's head)

39d5c98...7f84ca4: ahead 2, behind 0, 15 files (1a9fc53 is
opensoft/openRepoShape#164, 7f84ca4 is opensoft/openRepoShape#162):
AGENTS.md, README.md, adopt-project.py,
contracts/single-repository-record.yaml, docs/handbook.html,
scaffold-project.py, scripts/shape_advisory.py, shape-doctor.py,
templates/assembly-root/AGENTS-shape.md,
templates/assembly-root/project.yaml,
templates/single-repository/single-repository.yaml,
tests/test_adopt_submodules.py, tests/test_repo_hygiene.py,
tests/test_shape_advisory.py, tests/test_shape_doctor.py. None of the
eight files this suite mounts (the two root Makefiles, their two
.gitignores, the two bootstrap.py, siblings.py, scripts/repo_shape.py)
is among them; `git diff --stat 39d5c98 7f84ca4 -- <the eight>` in the
submodule is empty.

Bump run exactly as contracts/openreposhape-pin.yaml states:
  git -C upstream/openRepoShape fetch origin
  git -C upstream/openRepoShape checkout 7f84ca42ca86a8902928345109d2bf6bad87bd91
  python3 -c "import sys; sys.path.insert(0, 'upstream/openRepoShape/scripts'); from repo_shape import tree_digest; print(tree_digest('upstream/openRepoShape', 'HEAD'))"

Old commit:      39d5c986fcfac1a160474bfe91c5f1c37fccc72c
Old tree_sha256: a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02
New commit:      7f84ca42ca86a8902928345109d2bf6bad87bd91
New tree_sha256: 3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8

The digest is recomputed, not adjusted. The same 7f84ca4 helper, asked
for 39d5c98's tree, prints the old row a44c0165... back, so
sorted-ls-tree-r-v1 means the same thing on both sides of the bump. The
pin file and the gitlink move together in this one commit.

Part of #186

Lane: openRepoTools-1

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant