diff --git a/openspec/changes/migrate-to-triad/adoption-plan.yaml b/openspec/changes/migrate-to-triad/adoption-plan.yaml index f9d26fbe..f1067e30 100644 --- a/openspec/changes/migrate-to-triad/adoption-plan.yaml +++ b/openspec/changes/migrate-to-triad/adoption-plan.yaml @@ -1,20 +1,38 @@ -# Preliminary adoption mapping; planning only. Execution needs a refreshed baseline and explicit approval. -# Real conversion waits for PRs #97/#121 to land and the pinned-adopter mounting refusal to be resolved upstream. -# Disposable rehearsal evidence: ../../../specs/004-migrate-to-triad/preparation.md; Gates A/B remain open. -# Paths are relative to the source checkout. Generated metadata does not authorize repository creation. +# Rehearsal input, NOT the cutover plan: regenerated 2026-10-07 from source e43b2432976a22eb3bf8c419c96209399251d375 (chore/openreposhape-pin-7f84ca4) +# with openRepoShape adopt-project.py at 7f84ca42ca86a8902928345109d2bf6bad87bd91. +# The October 4 mapping's 19 reasoned overrides are reapplied verbatim; the new paths lane-worktrees +# and lanes-index (code) and ideation/ (spec) are resolved with reasons. +# Disposable rehearsal evidence: ../../../specs/004-migrate-to-triad/adopter-rehearsal-2026-10-07.md. +# Gate B remains open (T006-T011); execution needs a frozen baseline and explicit Gate C approval. +# Paths are relative to the source checkout (local_path published as "."); generated metadata +# does not authorize repository creation. schema_version: 1 kind: adoption-plan -generated_on: "2026-10-04" -tool: "opensoft/openRepoShape adopt-project.py" + +# Written by `adopt-project.py plan`. IT IS MEANT TO BE EDITED. +# Every entry with `review_required: true` carries a `question:`; a +# human or an AI answers it by setting `leg:` to spec, code, root or +# drop and adding one line of `resolution:` beside it. `check` then +# has to pass, and `execute` REFUSES while any leg is still null. + +generated_on: 2026-10-07 +tool: opensoft/openRepoShape adopt-project.py + source: repository: opensoft/openRepoTools local_path: . - default_branch: main - commit: daed20957f2dd2f22cca24053bb5bc8636ff6b3f - files: 64 - bytes: 4490556 - commits: 80 + default_branch: chore/openreposhape-pin-7f84ca4 + commit: e43b2432976a22eb3bf8c419c96209399251d375 + files: 100 + bytes: 6139047 + commits: 91 + +# The adopted repository KEEPS its name, its identity and +# its history and becomes the assembly root. `new-root` — a new +# root with the source reduced to one leg — is not implemented +# in v0.2; the field records which posture this plan took. mode: in-place + project: openRepoTools org: opensoft id: openrepotools @@ -24,19 +42,39 @@ adopt_branch: adopt/three-repo-shape elected_by: "Brett Heap" elected_on: "2026-10-04" reference: "openxFactory docs/project-repo-schema.md" + legs: assembly: openRepoTools spec: openRepoTools-spec code: openRepoTools-code spec_path: spec code_path: code + +# Neutral products this project declares a pin on. A +# `` assembly root is a DESCENDANT only when +# its `open` is listed here (2026-09-02). pins: [] + +# A leg that NO entry below assigns a path to is SEEDED from the +# shape's own leg template as one initial commit, instead of being +# extracted: `git filter-repo` over an empty path list yields an +# empty HISTORY, which is not an empty repository. The split still +# mounts it. This block RECORDS what the entries said when the plan +# was written; `check` and `execute` re-derive it from the entries, +# which are edited afterwards, and the entries always win. seeding: spec: seeded_from_template: false code: seeded_from_template: false + +# Seeding a leg is EXPLICIT HUMAN INTENT, so `execute` refuses to do +# it unless the leg is named here (or on its own command line) with +# `--allow-empty-leg `. A repository that turns out to have no +# code is a fact worth confirming; a plan that lost every code path +# to a bad edit looks exactly the same from here. allow_empty_legs: [] + paths: - path: .gitattributes leg: root @@ -52,7 +90,7 @@ paths: rule: code-ci-workflows reason: "CI runs the implementation's own gate — build, test, analysis. The assembly root gets its own `validate.yml` from the shape, so a workflow moved here is not a workflow lost." files: 1 - bytes: 18501 + bytes: 18865 review_required: false - path: .gitignore leg: root @@ -78,7 +116,7 @@ paths: rule: root-assistant-instructions reason: "The AI-assistant instruction files and their one-file directories are the same document ten times over, and it addresses the whole project. An assistant that read it from inside the code leg would be told about specifications it cannot see. Root, ruled 2026-09-02." files: 1 - bytes: 20967 + bytes: 21092 review_required: false - path: CLAUDE.md leg: root @@ -102,7 +140,7 @@ paths: rule: root-front-door reason: "What a person or a forge reads BEFORE deciding which leg to open. The licence and the code of conduct govern all three repositories; the README is the front door of the thing an engineer clones." files: 1 - bytes: 30329 + bytes: 31198 review_required: false - path: claude-current leg: code @@ -130,7 +168,7 @@ paths: rule: extension-majority reason: "no rule names this path; the `.md` extension is classified as spec by the policy's extension table" files: 3 - bytes: 5146 + bytes: 8906 review_required: false resolution: "These Markdown command files are shipped runtime installer payloads with implementation tests, not OpenSpec or Speckit decisions." - path: contracts/ @@ -148,8 +186,17 @@ paths: rule: spec-governance reason: "Requirements, decisions, contracts and governance prose — what the project has DECIDED, as opposed to what it currently runs. `contracts/` is here by the 2026-09-02 ruling even where the code reads it: the code reads across the assembly-root mount (`spec/contracts` from the root, `../spec/contracts` from `code/`), which is what the legs are mounted for." files: 2 - bytes: 201648 + bytes: 287738 review_required: false + - path: ideation/ + leg: spec + confidence: medium + rule: extension-majority + reason: "no rule names this path; the `.md` extension is classified as spec by the policy's extension table" + files: 12 + bytes: 49688 + review_required: false + resolution: "Feature ideation and brainstorm packets are planning prose about what the project is deciding, not shipped payload; spec beside openspec/, specs/ and docs/, as the October 6 rehearsal assigned it." - path: lane leg: code confidence: review @@ -166,7 +213,7 @@ paths: rule: default reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." files: 1 - bytes: 119587 + bytes: 141860 review_required: false question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." @@ -176,7 +223,7 @@ paths: rule: default reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." files: 1 - bytes: 72601 + bytes: 153546 review_required: false question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." @@ -196,7 +243,17 @@ paths: rule: default reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." files: 1 - bytes: 233030 + bytes: 270707 + review_required: false + question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." + resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." + - path: lane-worktrees + leg: code + confidence: review + rule: default + reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." + files: 1 + bytes: 277594 review_required: false question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." @@ -206,7 +263,7 @@ paths: rule: default reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." files: 1 - bytes: 36348 + bytes: 45015 review_required: false question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." @@ -216,8 +273,18 @@ paths: rule: extension-majority reason: "no rule names this path; the `.sh` extension is classified as code by the policy's extension table" files: 1 - bytes: 807509 + bytes: 1007136 + review_required: false + - path: lanes-index + leg: code + confidence: review + rule: default + reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." + files: 1 + bytes: 114193 review_required: false + question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." + resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." - path: link-estates leg: code confidence: review @@ -234,7 +301,7 @@ paths: rule: default reason: "No rule matched and the file extensions did not agree. This is the honest answer, not a failure: the tool has said what it does not know, at the exact path where it does not know it." files: 1 - bytes: 180034 + bytes: 193656 review_required: false question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." resolution: "Executable product command; keep with its sibling helpers and installation payload in the code repository." @@ -243,8 +310,8 @@ paths: confidence: high rule: spec-governance reason: "Requirements, decisions, contracts and governance prose — what the project has DECIDED, as opposed to what it currently runs. `contracts/` is here by the 2026-09-02 ruling even where the code reads it: the code reads across the assembly-root mount (`spec/contracts` from the root, `../spec/contracts` from `code/`), which is what the legs are mounted for." - files: 10 - bytes: 16759 + files: 21 + bytes: 135920 review_required: false - path: park leg: code @@ -282,7 +349,7 @@ paths: rule: extension-majority reason: "no rule names this path; the `.md` extension is classified as spec by the policy's extension table" files: 3 - bytes: 77708 + bytes: 80497 review_required: false resolution: "These three skills are installed product payloads; project workflow skills remain local root bootstrap artifacts." - path: specs/ @@ -290,8 +357,8 @@ paths: confidence: high rule: spec-governance reason: "Requirements, decisions, contracts and governance prose — what the project has DECIDED, as opposed to what it currently runs. `contracts/` is here by the 2026-09-02 ruling even where the code reads it: the code reads across the assembly-root mount (`spec/contracts` from the root, `../spec/contracts` from `code/`), which is what the legs are mounted for." - files: 6 - bytes: 4141 + files: 10 + bytes: 20264 review_required: false - path: status leg: code @@ -308,8 +375,8 @@ paths: confidence: high rule: code-source-and-tests reason: "The implementation, the tests that hold it, and the scripts and images that build and run it. `scripts/` moves whole: a harness that reads `contracts/` from beside it reads them across the root mount afterwards, which is a code change the plan records as a follow-up rather than a reason to split the directory." - files: 15 - bytes: 2022225 + files: 22 + bytes: 2637149 review_required: false - path: upstream/ leg: code @@ -321,6 +388,7 @@ paths: review_required: false question: "Which leg owns this path — spec, code, or the assembly root? Answer by editing `leg:` and writing one line into `resolution:` beside it." resolution: "Mounted openRepoShape is the implementation/test dependency; preserve its exact gitlink with the original .gitmodules and dependency pin." + follow_ups: - "code/claude-current names `docs/`, which moves to the spec leg: it must read across the assembly root — `../spec/docs/` relative to `code/` — or take the path from the environment" - "code/lane-start names `docs/`, which moves to the spec leg: it must read across the assembly root — `../spec/docs/` relative to `code/` — or take the path from the environment" @@ -331,6 +399,7 @@ follow_ups: - "code/tests/test_lane_helpers.sh names `docs/`, which moves to the spec leg: it must read across the assembly root — `../spec/docs/` relative to `code/` — or take the path from the environment" - "code/tests/test_lane_start_claude_current.py names `docs/`, which moves to the spec leg: it must read across the assembly root — `../spec/docs/` relative to `code/` — or take the path from the environment" - "… and 1 more file(s) under the code leg naming `docs/`" + - "code/lane-handoff names `openspec/`, which moves to the spec leg: it must read across the assembly root — `../spec/openspec/` relative to `code/` — or take the path from the environment" - "code/lanes-edit.sh names `openspec/`, which moves to the spec leg: it must read across the assembly root — `../spec/openspec/` relative to `code/` — or take the path from the environment" - "code/tests/test_lane_helpers.sh names `openspec/`, which moves to the spec leg: it must read across the assembly root — `../spec/openspec/` relative to `code/` — or take the path from the environment" - "code/tests/test_park_resume_commands.py names `specs/`, which moves to the spec leg: it must read across the assembly root — `../spec/specs/` relative to `code/` — or take the path from the environment" @@ -343,33 +412,34 @@ follow_ups: - "Preserve original .gitmodules, upstream/openRepoShape gitlink and contracts/openreposhape-pin.yaml together in code; rehearse existing-submodule extraction/removal and recursive bootstrap before real execution. Never weaken blob verification or edit the standard in place." - "Add an assembly openRepoTools compatibility entry point after byte-preserving split verification; resolve one immutable code pin for all installer artifacts and preserve OPENREPOTOOLS_REPO/REF forks, raw/gh and offline checkout behavior." - "Separate code, assembly and spec roots in test fixtures and hygiene checks; code CI must supply the exact compatible spec/assembly context where a test reads product documentation." - - "Current .specify and agent links are ignored local bootstrap artifacts, not the 64-file source tree; capture local configuration and regenerate root workflow using setup-openspeckit after manifest/legs are present." + - "Current .specify and agent links are ignored local bootstrap artifacts, not the 100-file source tree; capture local configuration and regenerate root workflow using setup-openspeckit after manifest/legs are present." - "Preserve all branch/PR/worktree and dirty/untracked work; source main extraction does not transport unfinished feature branches. Migrate selected patches to paired feature branches with old-to-new receipts before rebinding lanes." - "Regenerate this preliminary plan after planning lands and baseline freeze; require current coverage check, local bare-remote rehearsal, prerequisite availability and explicit approval before execute." - "Review genuine bounded features//openspec/ amendment records explicitly as code; canonical/full proposals and archives remain spec even when created on a feature branch. No existing bounded amendment paths were observed; do not manufacture them for historical features." - "Preserve approved original repository/commit/path provenance and verify correspondence to extracted spec identities, repairing relative links, selected OpenSpec roots/stores and paired feature paths without guessing filtered commit hashes." - "Use the adopted manual amendment workflow with immediate working Speckit updates and one docs reconciliation issue at the first amendment. Schema, root routing, bootstrap distribution and upstream placement automation are pending in their owners; do not patch pinned shape copies or assume other workstations are updated." - "Reconcile the tested migration net effect and all amendment dispositions in one final docs batch before completed assembly advancement; prepare docs/code PRs together, link landed code/evidence, close reconciliation after docs landing, and archive only after implementation and assembly pins land." + summary: spec: - files: 18 - bytes: 222548 - file_share: 0.2812 - byte_share: 0.0496 + files: 45 + bytes: 493610 + file_share: 0.4500 + byte_share: 0.0804 code: - files: 40 - bytes: 4203444 - file_share: 0.6250 - byte_share: 0.9361 + files: 49 + bytes: 5579879 + file_share: 0.4900 + byte_share: 0.9089 root: files: 6 - bytes: 64564 - file_share: 0.0938 - byte_share: 0.0144 + bytes: 65558 + file_share: 0.0600 + byte_share: 0.0107 unresolved: files: 0 bytes: 0 file_share: 0.0000 byte_share: 0.0000 -planning_status: proposed-preliminary-baseline +planning_status: rehearsal-input-not-cutover execution_authorized: false diff --git a/specs/004-migrate-to-triad/adopter-rehearsal-2026-10-07.md b/specs/004-migrate-to-triad/adopter-rehearsal-2026-10-07.md new file mode 100644 index 00000000..e6e20afe --- /dev/null +++ b/specs/004-migrate-to-triad/adopter-rehearsal-2026-10-07.md @@ -0,0 +1,223 @@ +# Gate B rehearsal with the merged adopter fix — October 7, 2026 + +**Task:** T003–T005 rehearsal evidence under [#186](https://github.com/opensoft/openRepoTools/issues/186). +No task is checked complete by it. +**Tool:** openRepoShape `7f84ca42ca86a8902928345109d2bf6bad87bd91`, the merged +[PR #162](https://github.com/opensoft/openRepoShape/pull/162) adopter fix on its +`main` (`compare main...7f84ca4`: `identical` at measurement). +**Rehearsal sources:** run A, main `c4864ac5e59db49d01f638a80ed38daf1d788182`; +run B, the repin candidate `chore/openreposhape-pin-7f84ca4` +([#188](https://github.com/opensoft/openRepoTools/pull/188)) at +`e43b2432976a22eb3bf8c419c96209399251d375`, whose only change from `c4864ac` +is the `upstream/openRepoShape` gitlink and its contract, both now at `7f84ca4`. +**Private receipt ID:** `adopter-fix-20261007-iM20tv`. + +The [October 6 rehearsal](adopter-rehearsal.md) ran the draft candidate +`91d5685`. This run uses the fix as merged, which is the repeat +[adopter-blocker.md](adopter-blocker.md) asks for after repinning. It uses fresh isolated clones +and fresh disposable local remotes. Clone paths, local remote URLs, exact command lines +and complete logs stay in the private receipt. + +## Setup + +- `git-filter-repo` 2.47.0 in a private venv for this rehearsal only. The + `pip download` wheel SHA256 is + `2cd04929b9024e83e65db571cbe36aec65ead0cb5f9ec5abe42158654af5ad83`, matching + the value recorded in [preparation.md](preparation.md). + `git filter-repo --version` printed `a40bce548d2c`. +- The tool is a fresh clone of openRepoShape checked out at `7f84ca4`. Nothing + in it was edited. The first `plan` run left an ignored `scripts/__pycache__/`, + which was removed; bytecode writing stayed off after that. The clone was + clean, ignored files included, after both runs. +- Each source is a fresh `--single-branch` clone with one worktree and no + linked worktrees. The source's nested `upstream/openRepoShape` was **not** + initialized: the tool's adoption documentation does not ask for it, and + `plan`, `check` and `execute` read the source through `ls-tree` and + non-recursive clones. +- Git transport was restricted to local files (`GIT_ALLOW_PROTOCOL=file`); + `gh` and `curl` shims first on `PATH` logged and refused every call. No + call was logged during `plan`, `check`, `execute`, the recursive clone or + bootstrap. The recursive clone reached code's nested openRepoShape through a + local URL rewrite to a bare mirror of the tool clone. +- Read-only lookups of `opensoft/openRepoTools-spec` and `-code` returned + HTTP 404: not visible to the current credentials, which is not a guarantee + of name availability or creation permission. Recheck at Gate C. + +## Mapping (T003) + +`plan` ran against each source with the committed plan's recorded election +values (`--org opensoft --visibility public --elected-by "Brett Heap" +--elected-on 2026-10-04`). It left 18 paths unresolved: `.gitmodules`, +`upstream/`, `repos.tsv` and fifteen executables. All 19 reasoned overrides of +the [October 4 mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) +were reapplied with their resolution text unchanged. Sixteen answer those +questions; three override the tool: `commands/` and `skills/` (installed +Markdown payloads) and `contracts/` (only the dependency lock) go to code. + +Paths new since the October 4 source `daed209` (36 files) and the October 6 +source `f5444c5` (6 files) were resolved by the same rules: + +| New path | New since | Leg | Reason | +| --- | --- | --- | --- | +| `lane-worktrees` | `f5444c5` | code | Executable lane command in the installer's `INSTALLABLES`; the committed executable resolution text. | +| `lanes-index` | `daed209` | code | Same, as the October 6 rehearsal assigned it. | +| `ideation/` (12 files) | `daed209` | spec | The tool already says spec; a resolution line records the review. | +| 11 files under `openspec/changes/` | `daed209` | spec | Covered by `openspec/`. | +| 4 files under `specs/005-supervised-legacy-ctx/` | `daed209` | spec | Covered by `specs/`. | +| 7 test files under `tests/` (5 since `f5444c5`) | `daed209` | code | Covered by `tests/`. | + +No bounded `features//openspec/` amendment paths exist, so none are +recorded. Nothing is dropped. The follow-ups are the tool's own +`follow_ups_for()` re-derived over the resolved entries (19), then the October +4 plan's ten reasoned follow-ups. One stale count in them changed: "64-file" +became the current source's file count. `check` printed `plan ok` and exited +0 for both runs. + +## Run A — current main `c4864ac` + +`execute --local-remote-dir … --work-dir … --yes` exited **0** and printed +`adoption verified: every source path is in exactly one place`. + +| Source accounting (the standard's table) | Original entries | +| --- | ---: | +| Spec | 45 | +| Code | 49 | +| Assembly root | 6 | +| Dropped | 0 | +| Total | 100 | + +The standard reported 18 added assembly paths: `project.yaml`, `Makefile`, +`AGENTS-shape.md`, `.github/workflows/validate.yml`, four `contracts/` +files (`code-pin.yaml`, `spec-pin.yaml`, `shape-pin.yaml`, +`repository-naming.yaml`), five `scripts/` files and five collision copies +under `shape/` (`.gitattributes`, `.gitignore`, `AGENTS.md`, `CLAUDE.md`, +`README.md`). The assembly also holds the two leg gitlinks and a fresh +`.gitmodules`, which its table does not count as added. + +An independent comparison matched **path, mode, object type and object ID** +for all 100 entries of `ls-tree -r c4864ac`: 45 spec, 49 code, 6 root, with +zero missing owners, zero duplicate owners and zero owners that differ from +the plan's leg. Neither leg holds an entry that is not in the source. The +`160000` gitlink `upstream/openRepoShape` at `39d5c98` has exactly one owner, +code. The original `.gitmodules` blob is in code; the assembly's new one is +a different blob. + +| Disposable repository | Commit | Kept commits | +| --- | --- | ---: | +| Spec | `558a12b674008bc9129e4f5438cdff42053963da` | 34 | +| Code | `48d98cd8793493646adb71163eac15b56fffee9c` | 87 | +| Assembly split | `9e5f934e98122c5da37428b064e044e807c9680e` | — | + +The split commit's only parent is `c4864ac`. A recursive clone of the split +branch passed. The generated `scripts/bootstrap.py` exited 0 (`bootstrap ok`), +and its naming, manifest and pins checks passed. The three validators also +passed when run on their own. The assembly, both legs and the nested +dependency were clean afterwards. Code's nested openRepoShape was checked out +at `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`, matching code's +`contracts/openreposhape-pin.yaml`. That checkout's own `scripts/repo_shape.py` +recomputed the tree digest as +`a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02`, which +matches the contract. + +The source clone's `HEAD`, `status --porcelain --ignored`, existing refs, local +configuration and worktree list were unchanged. Local mode added one ref, as +documented: `refs/heads/adopt/three-repo-shape`, which points at the split +commit. The live checkout gained no `adopt/` ref. + +## Run B — the repin candidate `e43b243` + +`plan` produced the same 18 open questions. The resolved mapping is the same +as run A's, with the same 22 decisions and follow-ups and the same +45/49/6 split. It differs only in the source fields: commit, `commits: 91`, +and `default_branch: chore/openreposhape-pin-7f84ca4`. A single-branch clone +of that branch has no `origin/HEAD`, so the tool takes the checked-out branch +as the default. `check` passed. `execute` exited **0** and printed +`adoption verified: every source path is in exactly one place`. + +| Source accounting (the standard's table) | Original entries | +| --- | ---: | +| Spec | 45 | +| Code | 49 | +| Assembly root | 6 | +| Dropped | 0 | +| Total | 100 | + +The standard again reported 18 added assembly paths, the same set as in +run A. The independent path/mode/type/object comparison of all 100 entries +of `ls-tree -r e43b243` found 45 spec, 49 code and 6 root owners. It found +zero missing, duplicate or misplaced owners and no leg extras. The gitlink +`upstream/openRepoShape` at `7f84ca4` has exactly one owner, code. + +| Disposable repository | Commit | Kept commits | +| --- | --- | ---: | +| Spec | `558a12b674008bc9129e4f5438cdff42053963da` | 34 | +| Code | `6d5216292186b5b2d2e4daa08afa3dd4580db80f` | 88 | +| Assembly split | `2726d3a935369c18472623b904c21ca3a825d09b` | — | + +The spec leg is the same commit as in run A, because its paths and their +history did not change. Code has one more kept commit: the repin. The split +commit's only parent is `e43b243`. The recursive clone, +`scripts/bootstrap.py` (`bootstrap ok`) and the three validators all passed. +Every tree was clean afterwards. Code's nested openRepoShape was checked out +at `7f84ca42ca86a8902928345109d2bf6bad87bd91`, matching code's +`contracts/openreposhape-pin.yaml`. The pinned checkout's own +`scripts/repo_shape.py` recomputed +`3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8`, which +matches the contract. Code still holds the source's original `.gitmodules` +blob, `8043147a`. The source clone was unchanged except for the one new ref +`refs/heads/adopt/three-repo-shape` at the split commit. + +## Notes for review + +- The regenerated follow-ups list nine code files that name `docs/`. The + ninth, shown as "… and 1 more", is `tests/test_repo_hygiene.py`. Three code + files name `openspec/`: `lane-handoff` is new since the October 4 list, at a + `:2439` comment that cites the supervised-restart design. One file names + `specs/`. Neither `lane-worktrees` nor `lane-end` names a spec-leg + directory, so neither needs a follow-up. +- On this branch, the + [mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) is + the regenerated run B plan, with a header saying what it is. The October 4 + version is unchanged in history at `ff6f6a7`. [plan.md](plan.md), + [quickstart.md](quickstart.md) and [preparation.md](preparation.md) still + describe the October 4 version; the plan's owner decides when to refresh + them. +- Each run used a fresh, empty `--local-remote-dir` and `--work-dir`. Without + the first, `execute` calls `gh repo create`. The plan's + `execution_authorized: false` is informational and the tool does not read it. +- The published plan differs from the executed run B plan in only three ways: + the header, `local_path: .` instead of the scratch path, and the October 4 + file's two closing status fields. `check` against the published copy also + passed. + +## Private log SHA256s + +- Run A execute: `885fa0d0f8b00513536683bafcf355ca15e2d26c34908935675c5898361f73a0`. +- Run A bootstrap: `e5d06e2e406d1b6ddae1dceb0b17004ce615c3d044cee4cb36828abdf27949fc`. +- Run A independent comparison: `9ae2fa322360b705761a9ca628a265c610cd7dceaaf29fc369fb1576cc84c5de`. +- Run B execute: `e894b78e1ca4b4ba8a95b2b5d2be428fa30d4a75b894ce48d90a550b0de78839`. +- Run B bootstrap: `6a010feb6a56b190690a097af396a94f29802ef125bf6c544afe0f807c557c0f`. +- Run B independent comparison: `fe933dd169375fb62a09967efb89fcac014d0c8d96868f0d007d0c1ed060a46b`. + +The receipt holds every log with its SHA256. None was over 2 MB, so none was +trimmed. + +## Remaining gates + +**Gate B is not complete.** This evidence covers the extraction, accounting, +nested-pin and bootstrap parts of T003–T005 for both sources. T005's pin +bump is PR #188, which still follows the usual landing rules. T006–T011 +remain open: + +- root collisions and leg guidance; +- the installer entry point; +- composed tests and CI; +- the restore and rollback rehearsal. + +Gate A preservation must be refreshed at a coordinated breakpoint. Before +Gate C, regenerate the plan from the frozen source that is actually chosen. +Brett Heap's explicit Gate C approval must name the revisions, the leg +repositories, their visibility and the final plan. + +This evidence authorizes no real conversion, repository creation, merge, +default-branch move or lane rebinding. diff --git a/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md b/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md new file mode 100644 index 00000000..4abffbff --- /dev/null +++ b/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md @@ -0,0 +1,397 @@ +# Consumer-side reads for T006/T007/T008: what outside openRepoTools depends on its layout or its installer + +Paths under the home directory are written portably (`~/`) because the repository's hygiene test refuses host-absolute paths in committed files; the originals are in lane 2's transcript. + +Read at 2026-10-07T10:04:44Z–11:07:10Z by lane openRepoTools-2's writer, under #186, from ff6f6a7. An API-side error cut the run, and it resumed at 11:03:49Z, when every head was checked again. + +HEADs read: + +- workBenches `7fd01e30816b2f96e20e913208bd07b8682274af`. Dirty: yes, one modified submodule pointer, `sysBenches/cloudBench`. Every read used committed objects at that sha. +- brett-wip `ab88a10347fb605588643e7ea2e528217dab9a67`. It had 215 untracked entries, which were not read. HEAD moved to `466c3a8` by 11:03:49Z and to `349caef` by 11:07:10Z. The line numbers below were checked again at `ab88a10`. +- openRepoShape 7f84ca4 (`7f84ca42ca86a8902928345109d2bf6bad87bd91`). +- openRepoTools main c4864ac (`c4864ac5e59db49d01f638a80ed38daf1d788182`). + +The plan files are read at `ff6f6a7c7b7921ca1e0b0234e898900f98532366` from lane 2's worktree. Brett Heap's 004 worktree was not entered. + +2026-10-07, relayed by the coordinator and not read here: Brett Heap opened PR #187 (planning branch `004-migrate-to-triad` at ff6f6a7 → main; lane 1 lands it). He also confirmed the leg names `openRepoTools-spec` / `openRepoTools-code`, both public, as recorded on #186. + +Revised 2026-10-07T11:21Z at lane 1's request: appended the section "Gate C follow-up list: outside changes and timing" (dated). No existing row, list or count above was changed. + +This document records facts only. "Covered" means installer-design.md at ff6f6a7 names the case; `l.N` cites that file. "(inferred)" marks a statement that was worked out rather than read. + +## Split as read from adoption-plan.yaml at ff6f6a7 + +- **root (6 files):** `.gitattributes` (l.41), `.gitignore` (l.57), `AGENTS.md` (l.75), `CLAUDE.md` (l.83), `LICENSE` (l.91), `README.md` (l.99). +- **spec (18 files):** `docs/` (l.145), `openspec/` (l.241), `specs/` (l.288). +- **code (40 files):** + - `.github/` + - `.gitmodules`, `upstream/` + - the whole `contracts/` directory (l.136–144). Its `rule:` is `spec-governance`, but its `resolution:` puts it in code, because at the baseline it holds only `openreposhape-pin.yaml`. + - `commands/`, `skills/`, `repos.tsv`, `tests/` + - the executables: `claude-current`, `claude-restart-check`, `lane`, `lane-end`, `lane-handoff`, `lane-rename`, `lane-start`, `lanes`, `lanes-edit.sh`, `link-estates`, `openRepoTools`, `park`, `resume`, `status` +- **Baseline:** `daed209` with 64 files (l.13–14). Main c4864ac tracks 100. Three of its top-level paths are under no mapped entry: `lane-worktrees`, `lanes-index` (both are in `INSTALLABLES` at `openRepoTools:338`) and `ideation/` (12 files). plan.md:58 puts "feature 001's retained `ideation/`" in spec. +- **Planned additions at the root** (not in the mapping): + - the assembly `openRepoTools` entry point (installer-design.md:9–14; plan.md:64–67) + - generated manifest, Makefile, validators and assembly pins (plan.md:57) + - the shape's `validate.yml` (adoption-plan.yaml:53) + +## Exact commands + +Plan files (lane 2's worktree, same commit as the planning branch): + +```sh +date -u +%Y-%m-%dT%H:%M:%SZ +git -C /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads rev-parse HEAD +git -C /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads status --short +cat -n /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads/openspec/changes/migrate-to-triad/adoption-plan.yaml +cat -n /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads/specs/004-migrate-to-triad/installer-design.md +cat -n /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads/specs/004-migrate-to-triad/tasks.md +cat -n /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads/specs/004-migrate-to-triad/plan.md +cat -n /workspace/projects/.lane-worktrees/openRepoTools-2/triad-reads/specs/004-migrate-to-triad/spec.md +``` + +openRepoTools main (read-only; no fetch): + +```sh +git -C /workspace/projects/openRepoTools rev-parse main c4864ac +git -C /workspace/projects/openRepoTools ls-tree --name-only c4864ac +git -C /workspace/projects/openRepoTools ls-tree -r --name-only c4864ac | wc -l # 100 +git -C /workspace/projects/openRepoTools ls-tree -r --name-only daed20957f2dd2f22cca24053bb5bc8636ff6b3f | wc -l # 64 +git -C /workspace/projects/openRepoTools diff --name-status daed20957f2dd2f22cca24053bb5bc8636ff6b3f c4864ac +git -C /workspace/projects/openRepoTools ls-tree c4864ac upstream/openRepoShape +git -C /workspace/projects/openRepoTools show c4864ac:.gitmodules +git -C /workspace/projects/openRepoTools ls-tree -r --name-only c4864ac contracts +git -C /workspace/projects/openRepoTools show c4864ac:openRepoTools > /openRepoTools.c4864ac +grep -n 'raw.githubusercontent\|gh api\|OPENREPOTOOLS_REPO\|OPENREPOTOOLS_REF\|^REPO=\|^REF=\|INSTALLABLES\|repos.tsv\|SCRIPT_DIR\|script_dir\|BASH_SOURCE\|\$0' /openRepoTools.c4864ac +grep -n 'selfdir\|skills/\|commands/\|contracts/\|upstream/\|docs/\|^[a-z_]*() *{' /openRepoTools.c4864ac +sed -n '1,135p;136,440p;955,1002p;1210,1222p;1285,1368p;1365,1400p;2490,2545p' /openRepoTools.c4864ac +git -C /workspace/projects/openRepoTools grep -n 'raw.githubusercontent\|gh api repos/opensoft/openRepoTools\|bash -s -- --install\|OPENREPOTOOLS_REF\|OPENREPOTOOLS_REPO' c4864ac -- README.md AGENTS.md docs +git -C /workspace/projects/openRepoTools show c4864ac:repos.tsv +git -C /workspace/projects/openRepoTools show c4864ac:lanes-edit.sh | grep -n 'repos.tsv' +git -C /workspace/projects/openRepoTools show c4864ac:lanes-edit.sh | grep -n '\.lane-state' +git -C /workspace/projects/openRepoTools show c4864ac:lane-worktrees | grep -n 'inventor' +git -C /workspace/projects/openRepoTools show c4864ac:lane-worktrees | sed -n '2120,2128p;2164,2175p;2708,2716p;4808,4822p' +git -C /workspace/projects/openRepoTools show c4864ac:link-estates | grep -n 'handoffs\|PROJECTS\|projects/\|estate' +git -C /workspace/projects/openRepoTools show c4864ac:.gitignore +for c in 2fb854f 5eb3d5f 500687c c4864ac; do git -C /workspace/projects/openRepoTools show $c:openRepoTools | sha256sum; done +git -C /workspace/projects/openRepoTools show c4864ac:lane-worktrees | sha256sum +git -C /workspace/projects/openRepoTools show c4864ac:lanes-edit.sh | sha256sum +ls -la /workspace/projects/openRepoTools +git -C /workspace/projects/openRepoTools status --porcelain=v1 --ignored +cat /workspace/projects/openRepoTools/.git/info/exclude +stat -c '%y' /workspace/projects/openRepoTools/.git/index # 2026-10-07 04:28:20Z, before this read: the status call wrote no index +``` + +workBenches (read-only; committed objects at HEAD `7fd01e3`): + +```sh +git -C /workspace/projects/workBenches rev-parse HEAD +git -C /workspace/projects/workBenches status --porcelain=v1 # " M sysBenches/cloudBench" +git -C /workspace/projects/workBenches worktree list +git -C /workspace/projects/workBenches show HEAD:.gitmodules +git -C /workspace/projects/workBenches submodule status +git -C /workspace/projects/workBenches grep -n -i 'openRepoTools' HEAD -- . # 939 lines; per-file counts via cut | sort | uniq -c +git -C /workspace/projects/workBenches grep -n -e '/workspace/projects/openRepoTools' -e 'openRepoTools-worktrees' -e '\.lane-worktrees' -e 'raw.githubusercontent.com/opensoft/openRepoTools' -e 'repos/opensoft/openRepoTools' -e 'github.com/opensoft/openRepoTools' -e 'opensoft/openRepoTools/' -e 'projects/openRepoTools' HEAD -- . +git -C /workspace/projects/workBenches show HEAD:devBenches/base-image/upstream-pin.yaml +git -C /workspace/projects/workBenches show HEAD:devBenches/base-image/Dockerfile | sed -n '136,285p' +git -C /workspace/projects/workBenches show HEAD:devBenches/base-image/update-upstream.py | sed -n '68,90p;886,960p' +git -C /workspace/projects/workBenches show HEAD:devBenches/base-image/files/estate/estate-commands-start +git -C /workspace/projects/workBenches show HEAD:devBenches/base-image/files/estate/workbench-entrypoint | grep -n 'estate-commands-start\|openrepotools\|exec' +git -C /workspace/projects/workBenches ls-tree -r --name-only HEAD devBenches/base-image/files/openrepotools +git -C /workspace/projects/workBenches show HEAD:scripts/setup-estate-commands.sh | grep -n -i 'openRepoTools\|vendor\|files/\|OPENREPOTOOLS\|INSTALLABLES\|skills/\|commands/\|755\|link-estates' +git -C /workspace/projects/workBenches show HEAD:scripts/setup-estate-commands.sh | sed -n '158,200p;276,330p;370,405p' +git -C /workspace/projects/workBenches show HEAD:setup.sh | sed -n '176,200p' +git -C /workspace/projects/workBenches show HEAD:README.md | sed -n '188p;190p' +stat -c '%y' /workspace/projects/workBenches/.git/index # 2026-10-06 13:08:26Z, before this read +``` + +openRepoShape at 7f84ca4 (bare clone in lane 2's scratchpad, `ors-verify/ors.git`): + +```sh +git -C log -1 --format='%H %cI %s' 7f84ca42ca86a8902928345109d2bf6bad87bd91 +git -C grep -n -i 'openRepoTools' 7f84ca42ca86a8902928345109d2bf6bad87bd91 -- . # 79 lines +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:openRepoShape" | grep -n 'raw.githubusercontent.com/opensoft/openRepoTools\|park and resume are installed by\|^[a-z_]*() *{' +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:openRepoShape" | sed -n '14,22p;76,86p;158,164p;268,290p' +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:README.md" | sed -n '400,410p;1355,1359p' +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:docs/cli.md" | sed -n '143,148p' +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:templates/workspace-root/AGENTS.md" | sed -n '28,34p;68,78p;88,95p' +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:scripts/shape_advisory.py" | sed -n '504,512p' +git -C show "7f84ca42ca86a8902928345109d2bf6bad87bd91:.github/workflows/tests.yml" | sed -n '268,282p' +git -C ls-tree -r --name-only 7f84ca42ca86a8902928345109d2bf6bad87bd91 | grep -i 'pin\|gitmodules' +git -C grep -n -i 'openRepoTools' 7f84ca42ca86a8902928345109d2bf6bad87bd91 -- contracts .gitmodules # 0 lines +``` + +brett-wip (read-only; reads pinned at `ab88a10`): + +```sh +git -C /workspace/projects/brett-wip rev-parse HEAD +git -C /workspace/projects/brett-wip status --porcelain=v1 | wc -l # 215, all untracked +git -C /workspace/projects/brett-wip ls-tree --name-only HEAD +git -C /workspace/projects/brett-wip ls-tree HEAD lanes/ +git -C /workspace/projects/brett-wip ls-tree -r --name-only HEAD | grep -i 'workspace.yaml' # none +git -C /workspace/projects/brett-wip grep -n -e '/workspace/projects/openRepoTools' -e 'openRepoTools-worktrees' -e '\.lane-worktrees/openRepoTools' -e '~/projects/openRepoTools' -e 'projects/openRepoTools' ab88a10347fb605588643e7ea2e528217dab9a67 -- . # 341 lines +git -C /workspace/projects/brett-wip show "ab88a10347fb605588643e7ea2e528217dab9a67:lanes/LANES.md" > /LANES.md +grep -n '^| lane\|^| `openRepoTools' /LANES.md +git -C /workspace/projects/brett-wip show "ab88a10347fb605588643e7ea2e528217dab9a67:lanes/log/openRepoTools-1.md" # likewise -2, -3; sampled lines +git -C /workspace/projects/brett-wip show "ab88a10347fb605588643e7ea2e528217dab9a67:lanes/repos.tsv" | sha256sum +git -C /workspace/projects/brett-wip grep -n -e '\.local/bin/\(openRepoTools\|park\|resume\|status\|lane\|lanes\|lane-handoff\|lane-rename\|lanes-edit\.sh\|lane-start\|lane-end\|link-estates\|repos\.tsv\|claude-current\|claude-restart-check\|lanes-index\|lane-worktrees\)\b' -e 'share/openRepoTools' -e 'raw.githubusercontent.com/opensoft/openRepoTools' -e 'docs/README-lanes' -e 'openRepoTools-\(code\|spec\)' ab88a10347fb605588643e7ea2e528217dab9a67 -- . +git -C /workspace/projects/brett-wip grep -n -i -e 'openRepoTools' -e '\.local/bin' HEAD -- README.md AGENTS.md CLAUDE.md scripts/link-estates +ls -la /workspace/projects/xFactory/lanes-edit.sh /workspace/projects/xFactory/LANES.md +find /workspace/projects/.lane-state/openRepoTools-{1,2,3} -type f +grep -rn '^checkout:' /workspace/projects/.lane-state/openRepoTools-{1,2,3} +grep -rn '^path: /workspace/projects/openRepoTools/' /workspace/projects/.lane-state/openRepoTools-{1,2,3} | wc -l +``` + +`~/.agents` and the home directory: + +```sh +ls -la ~/.agents ~/.agents/protocols ~/.agents/templates +cat -n ~/.agents/workspace.yaml +grep -rn -i -c 'openRepoTools' ~/.agents/AGENTS.md ~/.agents/protocols/* +grep -rn -e 'projects/openRepoTools' -e 'openRepoTools-worktrees' -e 'lane-worktrees/openRepoTools' -e 'raw.githubusercontent.com/opensoft/openRepoTools' -e 'repos/opensoft/openRepoTools' -e 'openRepoTools/installed.tsv' -e 'share/openRepoTools' -e 'openRepoTools/docs' -e 'docs/README-lanes' -e 'openRepoTools --install' -e 'openRepoTools/[A-Za-z]' ~/.agents/{AGENTS.md,protocols,workspace.yaml,templates} # 59 lines +grep -rln -i 'openRepoTools' ~/.agents/skills ~/.agents/templates ~/.agents/.skill-lock.json # none +cat ~/.agents/protocols/project-agent-bootstrap.md +cat ~/.agents/protocols/openspec-speckit-workflow.md +awk -F'\t' '{print NR, $1, $2, substr($3,1,12), $4}' ~/.local/share/openRepoTools/installed.tsv # 29 rows +sha256sum ~/.local/bin/openRepoTools +grep -n 'lanes-edit\|lane-start\|xFactory\|openRepoTools\|\.local/bin' ~/.claude/settings.json +grep -n -i 'openRepoTools' ~/.claude/CLAUDE.md # none +grep -n -i 'projects/openRepoTools\|lane-worktrees\|raw.githubusercontent\|opensoft/openRepoTools\|docs/README-lanes' ~/.claude/skills/{handoff,restart,lane-swap}/SKILL.md ~/.claude/commands/*.md +sed -n '318,336p' ~/.claude/skills/handoff/SKILL.md +``` + +## workBenches (`7fd01e3`) + +| file:line | what it assumes today | what the split changes | installer-design.md coverage | +|---|---|---|---| +| `devBenches/base-image/upstream-pin.yaml:56-125` (and `:30-32`) | Source `openrepotools` = `opensoft/openRepoTools` at `b1015f4`. Its 21 `path:` rows (15 commands, `skills//SKILL.md` ×3, `commands/.md` ×3) sit at the repository root. `path` is "the path in the source repository and the path under `vendor_dir`". | After the split those paths are root files of `openRepoTools-code`. In the assembly they sit behind the `code` gitlink, so a re-vendor against `opensoft/openRepoTools` at a post-split commit would not find them (inferred). The pin is still at `b1015f4` with 15 names; main has 17. | not covered | +| `devBenches/base-image/update-upstream.py:917-938, 941-956, 890-914` | `fetch_file` calls `gh api repos//contents/?ref=`, falling back to `raw.githubusercontent.com///`. `fetch_tree_modes` reads `git/trees/?recursive=1`. `assert_on_default_branch` compares the commit with the source's default branch. All three expect blobs at those paths in that one repository. | Same as the row above. In the assembly tree, `code` is a gitlink, so neither the contents API nor tree modes reach the files (inferred). | not covered | +| `devBenches/base-image/Dockerfile:216-238` (comment `:148-156`) | `COPY files/openrepotools/<15 names>` to `/usr/local/bin`, then `chmod 0755`. The comment says openRepoTools pins openRepoShape "as a submodule in that repository". | The flat vendored layout is unchanged if it is vendored from the code leg, which keeps the same file names at its root (inferred from the mapping). The submodule and its pin move to `openRepoTools-code`. | not covered | +| `devBenches/base-image/Dockerfile:262-269` (`:240-249`) | Copies the whole vendored tree to `/usr/local/share/openrepotools`, then checks `openRepoTools`, `link-estates`, `skills/handoff/SKILL.md` and `commands/handoff.md` there. `--install` runs from that directory and copies every artifact "from its own directory". | That vendored `openRepoTools` must stay the code implementation, with siblings beside it. If the vendored file were an assembly entry point instead, it would have to delegate (inferred). | partial: l.9-14 ("Installed `openRepoTools` remains the code implementation"), l.40-48 ("legacy sibling behavior"). A vendored tree that is not a checkout is not named. | +| `devBenches/base-image/files/estate/estate-commands-start:134, 157-186` | Requires `$ESTATE_VENDOR_DIR/openRepoTools` to be executable. It `sed`-reads the one-line `INSTALLABLES=(`, `SKILLS=(` and `COMMANDS=(` arrays out of that file, derives `skills//SKILL.md` and `commands/.md`, and installs nothing if any file is missing. | The file it parses has to keep those three one-line arrays. An entry point without them stops this step at `:177` ("could not read openRepoTools' own INSTALLABLES/SKILLS/COMMANDS lists") (inferred). | not covered | +| `estate-commands-start:239-240`; `scripts/setup-estate-commands.sh:378-381` | Runs `--install` with `OPENREPOTOOLS_REPO` and `OPENREPOTOOLS_REF` set to the sentinel `pinned-by-workBenches-no-fetch`, so that only sibling copies succeed. | The design resolves remote installs through `contracts/code-pin.yaml` at REPO/REF and refuses on transport or parse errors. A sentinel REPO with siblings and no pin is the legacy-sibling path. Today `wip_shape_ref` falls back to `main` when the pin fetch fails (`openRepoTools:2516`). | partial: l.30-33, l.47-48, l.83. The sentinel case is not named. | +| `scripts/setup-estate-commands.sh:162, 173, 266-268, 285, 312-321, 402, 434` | `TOOLS_SHIM` is the vendored file. `TOOLS_FILES` (15) is checked against the shim's `INSTALLABLES`, `SKILLS` and `COMMANDS` (`check_shim_list`). Every one of the 21 files must have a pin row. After `--install`, each placed file must `cmp` equal to its vendored copy at mode 755. | Depends on the vendored tree mirroring the source root and on the shim's arrays, the same as the two rows above. `check_shim_list` would now see 17 `INSTALLABLES` against 15 (a fact on main, not caused by the split). | not covered | +| `setup.sh:179-186, 208-209` | The host one-liner path: runs `scripts/setup-estate-commands.sh`, then `scripts/setup-workspace-repo.sh` (`openRepoTools wip init`). | Command names and help must hold. The route goes through the vendored tree (rows above). | partial: names and help, l.75. The vendored route is not named. | +| `scripts/setup-workspace-repo.sh:253-265, 271, 361` | Finds `$OPENREPOTOOLS_BIN_DIR/openRepoTools`, otherwise `PATH`. Asks `openRepoTools --help` whether `wip` is documented. Prints `update-upstream.py … --source openrepotools --at --yes`. | The installed name, the `--help` text and `wip init` must hold. The `--source openrepotools` advice points at the pin source in the first row. | covered: l.75, l.87 | +| `base-image/files/claude-profile:54-55, 557, 1649-1653`; `scripts/setup-claude-profiles.sh:213-224` | Matches the guard hook string byte for byte with openRepoTools's `GUARD_COMMAND` (cited as `openRepoTools:460-461`). Parses `openRepoTools --help`. Its install act is the string `openRepoTools --install`. Says `--install` owns the skill and command destinations. | Only installed names, help text, hook strings and destinations are read. The `openRepoTools:` cites point into a file that moves to `code/`. | covered: l.59, l.75, l.86 | +| `README.md:80, 93, 155-156, 172, 188, 190` | "the lane tooling is installed from `opensoft/openRepoTools`" (`:188`); "places fifteen files" (`:190`). | The implementation moves to `openRepoTools-code`. The assembly keeps the slug and the one-liner (installer-design l.9-11). | not covered | +| `devBenches/base-image/files/openreposhape/openRepoShape:83, 280` (openRepoShape pin `71cf5de`) | A vendored copy of openRepoShape's raw-URL pointer `…/opensoft/openRepoTools/main/openRepoTools` (see the openRepoShape table). | The URL resolves only if the assembly root carries an `openRepoTools` file (inferred). | covered: l.9-11, l.75 | +| `devBenches/base-image/files/openrepotools/lane-handoff:813, 913`; `…/lanes-edit.sh:11412, 11939`; `…/skills/handoff/SKILL.md:292` | Vendored openRepoTools code (`b1015f4`) derives `/.lane-worktrees/`. | The same as the code's own assumption (installer table, lane-worktrees row). It holds while lanes keep `dir /workspace/projects/openRepoTools` (inferred). | not covered | +| `devcontainer.test/test-setup-estate-commands.sh` (80 lines), `test-claude-profile-amendment-11.sh` (61), `test-setup-workspace-repo.sh` (52), and 8 more files under `devcontainer.test/` (57, including `README.md:70`); `test-claude-profile-lane-default.sh:282, 293`; `.github/workflows/speckit-git-bash.yml:19, 53` | The suites run or fake the vendored shim and its layout. `:282` and `:293` print `cwd /workspace/projects/openRepoTools`. The CI path filters are `devBenches/base-image/files/openrepotools/**`. | They follow whatever the vendored tree becomes. | not covered | +| `docs/claude-multi-account-profiles.md` (20 lines; `:314` cites `:1559`, `:1568`, `:1579` of openRepoTools `63a74af`), `openspec/**` and `specs/**` (52 lines), `base-image/files/claude-statusline-command.sh:477`, `scripts/wave-container-shell.sh:55`, `files/speckit-worktree/…/resume.sh:451, 465`, `devBenches/devcontainer.test/test-speckit-git-feature.sh:3425, 3487` | Prose that names `opensoft/openRepoTools`, its issues, or file:line inside it. | The slug stays as the assembly. The files named move to `code/`. | not covered | + +## openRepoShape (`7f84ca4`) + +openRepoShape pins nothing of openRepoTools. + +| file:line | what it assumes today | what the split changes | installer-design.md coverage | +|---|---|---|---| +| `openRepoShape:279-280` (inside `install_commands`, which starts at `:250`): **the `--install` pointer line** | Prints `curl -fsSL https://raw.githubusercontent.com/opensoft/openRepoTools/main/openRepoTools`, piped to `bash -s -- --install`. That file must be the installer at the root of `opensoft/openRepoTools` on `main`. | The `openRepoTools` file moves to the code leg. The URL keeps resolving only through the planned assembly root entry point, which must delegate (inferred). | covered: l.9-14, l.75 (T007) | +| `openRepoShape:81-83` (`--help`) | The same line. | Same as the row above. | covered: l.9-11, l.75 | +| `README.md:404-408`, `docs/cli.md:145-147`, `docs/handbook.html:1542` (and `README.md:1357`, `docs/handbook.html:1646`) | The same line, byte for byte. | Same as the row above. | covered: l.9-11, l.75 | +| `tests/test_repo_hygiene.py:1202-1224`; `tests/test_openreposhape_command.py:55-57, 154, 272, 278` | `OPENREPOTOOLS_INSTALL` is pinned byte for byte in `openRepoShape`, `README.md` and `docs/handbook.html`. `:278` asserts that `--install` makes no request naming openRepoTools. | The tests hold only while the URL string is unchanged. | partial: l.10-11 keeps the one-liners. These tests are not named. | +| `templates/workspace-root/AGENTS.md:32, 71-76, 91-95`; `README.md:16, 18, 31, 58`; `handoffs/README.md:24`; `lanes/LANES.md:19, 40`; `lanes/log/README.md:4, 6`; `.gitattributes:8` | The template text that `openRepoTools wip init` copies into a WIP repository. It says the lane tooling (`lanes-edit.sh`, `lane-start`, `lane-end`, `test_lane_helpers.sh`, `link-estates`) and "README-lanes" live in `opensoft/openRepoTools`. | `docs/README-lanes.md` moves to `openRepoTools-spec`. The tools and `tests/` move to `openRepoTools-code`. | not covered: l.57 and l.87 cover only which template is selected, not its text | +| `scripts/shape_advisory.py:509` | `workspace.yaml` is "the shape `opensoft/openRepoTools`' `resume` reads". | `resume` moves to `code/`. The shape of `workspace.yaml` is unchanged (inferred). | not covered | +| `openRepoShape:19-25, 162`; `README.md:246, 1239`; `docs/handbook.html:495, 773, 782, 1538, 1739`; `AGENTS.md:429`; `.github/workflows/tests.yml:274`; the remaining test prose (for example `tests/test_openreposhape_command.py:17, 44`; `tests/test_repo_hygiene.py:70, 1190, 1230-1246`) | Provenance prose: `park` and `resume` are "opensoft/openRepoTools'". `AGENTS.md:429` says to read openRepoTools's `AGENTS.md` (which stays at the root). | The slug stays as the assembly. The named files move to `code/`. | not covered | +| `contracts/**` and `.gitmodules` | No line names openRepoTools (`git grep` returns 0). The pins found in the tree are template pins only. | Nothing; openRepoShape still pins nothing of openRepoTools. | n/a | + +## brett-wip (`ab88a10`) and the host-local register state + +| file:line | what it assumes today | what the split changes | installer-design.md coverage | +|---|---|---|---| +| `lanes/log/openRepoTools-1.md:2`, `openRepoTools-2.md:2`, `openRepoTools-3.md:59` … (52 lines: 11 + 11 + 30) | STARTED, RESUMED and PAUSED records carry `home opensoft/openRepoTools; estate openRepoTools; dir /workspace/projects/openRepoTools`. That is the directory a lane is relaunched in. | In-place adoption keeps the slug as the assembly. The checkout keeps holding only 6 root files plus `spec/` and `code/` (inferred). The executables a lane runs from the checkout root move to `code/`. | not covered (rebinding is plan.md:223-224, T018) | +| `lanes/log/openRepoTools-1.md:19`, `openRepoTools-3.md:291`, `:405`; `openXfactory-3.md:60`, `openXfactory-5.md:390`, `openxfactory-1.md:169` (+ `:253, 324, 411`) — 10 lines | Notes that name `.lane-worktrees/openRepoTools-1` and `-3`, `openRepoTools-cleanup-archives/…`, or `/workspace/projects/openRepoTools` as a working directory. | These are records of past acts. The paths stay valid while the assembly sits at the same path (inferred). | not covered | +| `lanes/LANES.md:1109` (`openRepoTools-3`), `:1303` (`openRepoTools-1`), `:2581` (`openRepoTools-2`) | The rows carry a handoff path `handoffs/openRepoTools/…` and no directory column (header `:76`). Only `:1109` names a checkout: `--dir ~/projects/openRepoTools`. `~/projects` → `/workspace/projects`. | The handoff paths are in brett-wip and unaffected. The estate name `openRepoTools` stays. | not covered | +| `lanes/LANES.md:36` (and `:1305`); 12 `docs/README-lanes` lines in 9 files (first: `handoffs/openRepoTools/brief-lane-openRepoTools-1-2026-09-16.md:9`, `session-handoff-2026-09-16-lane-openRepoTools-1.md:33`, `lanes/log/openRepoTools-1.md:22`) | "the manual lives at `docs/README-lanes.md` in `opensoft/openRepoTools`". | `docs/` moves to `openRepoTools-spec`. | not covered | +| `lanes/repos.tsv:52` | The per-WIP alias override, read by `lanes-edit.sh` as `LANES_REPOS_TSV` (`lanes-edit.sh:2448`). It is byte-identical to the shipped table (sha256 `e4f9160a07ea…`). The only openRepoTools row is `openRepoTools` → `opensoft/openRepoTools`. | There are no `openRepoTools-spec` or `openRepoTools-code` rows, while the IRRS legs have them (`:29-30`, `:34-35`). The table header says an alias not in the table is refused, with a hint to spell owner/repo (shipped `repos.tsv:8`). | not covered | +| handoffs naming the checkout root `/workspace/projects/openRepoTools`: 145 lines (first: `handoffs/openRepoTools/migration-handoff-2026-10-06.md:15, 16, 32`) | Reads, cwd records and commands run in the monorepo checkout. | After cutover, the checkout at that path is the assembly. Code and docs are under `code/` and `spec/` (inferred). | not covered | +| `.lane-worktrees/openRepoTools-1` (50 lines), `-2` (3), `-3` (59) (first: `migration-handoff-2026-10-06.md:202`; `session-handoff-2026-10-02-lane-openRepoTools-2.md:19`; `session-handoff-2026-09-13-lane-openRepoTools-3.md:6`) | Lane worktrees are siblings of the lane directory, as monorepo worktrees. | Worktrees made after cutover would be worktrees of leg repositories. The triad protocol puts Speckit features under `/worktrees//{spec,code}` (inferred from the protocol table below). | not covered | +| `openRepoTools-worktrees`: 16 lines (first: `migration-handoff-2026-10-06.md:204-206`) | The single-repository Speckit worktree root, `../-worktrees`. | It becomes `/worktrees//{spec,code}` (`openspec-speckit-workflow.md:114`). | not covered (plan.md:207-208, T006, T016-T018) | +| `~/projects/openRepoTools/lanes-edit.sh` (and `$HOME/…`): 20 lines (first: `handoffs/xFactory/attachments/opsXfactory-1/briefs/DELTA-land-444-r2.md:9`, `…-r4.md:4`, `…-r5-MERGE-WORKER.md:5`; also `session-handoff-2026-09-13-lane-openRepoTools-3.md:296`) | Runs the helper from the checkout root. | `lanes-edit.sh` moves to `code/` (path `~/projects/openRepoTools/code/lanes-edit.sh`, inferred). | not covered | +| installed-tool paths `~/.local/bin/`: 82 lines in 30 files (first: `README.md:85`, `README.md:86`, `scripts/link-estates:16`); `~/.local/share/openRepoTools/installed.tsv`: 7 lines in 3 files (first: `migration-handoff-2026-10-06.md:17, 57, 114`) | Installed destinations. `README.md:85-86` and `scripts/link-estates:16-17` are the pre-Amendment-9 legacy map from `~/.local/bin/lane-start` and `lane-end` to `brett-wip/lanes/*`. They name no openRepoTools checkout path, and neither do the legacy copies `lanes/{lane-start,lane-end,lanes-edit.sh,test_lane_helpers.sh,README-lanes.md}`. | Destinations are expected to stay the same. | covered: l.75, l.86 | +| host-local `/workspace/projects/.lane-state/openRepoTools-{1,2,3}/trees/*.yaml` (not in git), e.g. `…/openRepoTools-2/trees/c95160057-…-triad-reads.yaml:5` | 37 tree records carry `checkout: /workspace/projects/openRepoTools`. 19 of them have a `path:` under `/workspace/projects/openRepoTools/.claude/worktrees/`, and 18 under `.lane-worktrees/openRepoTools-N`, including lane 1's workBenches worktrees (`…wb-image-rebuild-key.yaml:5`). | After cutover, new worktrees are of leg repositories. The checkout is the assembly root (inferred). | not covered | +| `/workspace/projects/openRepoTools/handoffs` → `/workspace/projects/brett-wip/handoffs/openRepoTools` (symlink placed by `link-estates:399-408`) | The checkout root holds an untracked symlink. It is ignored by `.git/info/exclude` (`/handoffs`), not by the tracked `.gitignore` (3 lines). | The assembly root keeps the path (in place, inferred). Its `.gitignore` gets the shape merge (adoption-plan.yaml:338). | not covered | + +## `~/.agents` and the home directory + +| file:line | what it assumes today | what the split changes | installer-design.md coverage | +|---|---|---|---| +| `~/.agents/AGENTS.md:273-278` | The lane helpers "are commands `openRepoTools --install` places from `opensoft/openRepoTools` — with the alias table `repos.tsv` beside them". | The source of the bytes becomes the code leg, through the root entry point. The names stay. | partial: l.9-14, l.75 | +| `~/.agents/AGENTS.md:327, 347-348, 367, 391-392, 419, 430, 443-444, 462, 488, 498` | "The code lands in `opensoft/openRepoTools`" for each amendment. | Code PRs land in `openRepoTools-code`, followed by an assembly pin bump (`openspec-speckit-workflow.md`, "Landing a feature"; inferred for this repository). | not covered | +| `protocols/lane-collision-protocol-amendment-9.md:735, 943`; `-11.md:1511`; `-12.md:315`; `-14.md:185`; `-17.md:175`; `-18.md:222` | Name `docs/README-lanes.md` as the tooling's manual. | `docs/` moves to `openRepoTools-spec`. | not covered | +| `protocols/lane-collision-protocol.md:659-666`; about 45 lines in amendments 8, 9, 11, 12, 16, 17 and 18 (first: `-8.md:194`, `-9.md:150`, `-11.md:1290`) | Name `openRepoTools --install` as the act that places the lane commands, skills and hooks. | Only the command name and act are read. | covered: l.75 | +| `protocols/lane-collision-protocol-amendment-9.md:673, 1000` | `:673`: `--install` runs from the copies vendored at workBenches' `upstream-pin.yaml`. `:1000`: `gh api repos/opensoft/openRepoTools/contents/` returned 404 for files not yet in the repository. | The contents-API paths at the assembly root change. | partial: l.54 covers the fetch. The protocol text is not covered. | +| `protocols/openspec-speckit-workflow.md:114, 279-309`; `protocols/project-agent-bootstrap.md:96-131` | Single-repository `worktree_root: ../-worktrees`. Three-leg layout: `worktree_root: worktrees`, with `/worktrees//{spec,code}`. | openRepoTools's feature worktrees move from `/workspace/projects/openRepoTools-worktrees/` to under the assembly root. | not covered (plan.md:207-208, T006) | +| `protocols/project-agent-bootstrap.md:138-178, 221-226`; `openspec-speckit-workflow.md:57-66` | `setup-openspeckit` detects a triad from `project.yaml`. It writes `.specify/`, managed blocks, opsx commands and skill links at the root, and OpenSpec scaffolding in the spec leg. The first line of `AGENTS.md` is an invariant. The shared checkout's `.specify/`, `.claude/`, `.agents/` and `.codex/` are local and ignored (`.git/info/exclude`). | The bootstrap must be re-run in the assembly root after the legs exist. | not covered (T006; adoption-plan.yaml:346) | +| `~/.agents/workspace.yaml:4-5` | `repository: opensoft/brett-wip`, `path: ~/projects/brett-wip`. No openRepoTools path. It is read by `openRepoTools:2211` and by `park`/`resume`. | Nothing in the file. | n/a | +| `~/.agents/AGENTS.md:384`; `lane-collision-protocol.md:681`; `-14.md:93` | `${XDG_CONFIG_HOME:-$HOME/.config}/openRepoTools/lanes-index.conf`, a per-workstation configuration path. | Nothing layout-dependent (inferred). | n/a | +| `~/.local/share/openRepoTools/installed.tsv` rows 1-29 (all stamped `2026-10-07T04:26:26Z`) | Rows 1-17 are `~/.local/bin/`. Rows 18-23 are the skills at `~/.claude-profiles/shared/skills/` and `~/.claude/skills/`. Rows 24-29 are the command files at both command dirs. The digests of `openRepoTools`, `lanes-edit.sh` and `lane-worktrees` equal the blobs at c4864ac. These rows consume the install, not the layout. | Names, destinations and receipt semantics are expected to stay the same. | covered: l.59, l.85-86 | +| `~/.claude/settings.json:25, 37` | Hook commands `~/projects/xFactory/lanes-edit.sh guard` and `… session-start \|\| true`. That path is a symlink to `~/.local/bin/lanes-edit.sh`. These consume the install. | Nothing, if destinations hold. | covered: l.59, l.86 | +| installed `~/.claude/skills/handoff/SKILL.md:329` (receipt rows 18-19; the `~/.claude-profiles/shared` copy has the same digest and was not opened) | The writer-poll loop sweeps `"$dir"/.claude/worktrees/*` and `"$(dirname "$dir")"/.lane-worktrees/"$lane"/*`. | Triad feature worktrees under `/worktrees//{spec,code}` are outside both globs (inferred). | not covered | +| `~/.claude/CLAUDE.md`; `~/.agents/skills/**`, `templates/**`; `openspec-speckit-workflow.md` and `project-agent-bootstrap.md` by name | None of them name openRepoTools. | — | n/a | + +## The installer's own assumptions (openRepoTools main `c4864ac`) + +| file:line | what it assumes today | what the split changes | installer-design.md coverage | +|---|---|---|---| +| `openRepoTools:6-11`; `README.md:228, 236-237` | The raw-URL one-liner `…/opensoft/openRepoTools/main/openRepoTools` and `gh api repos/opensoft/openRepoTools/contents/openRepoTools`, both piped to `bash -s -- --install`. | The file moves to code. The assembly root needs the entry point. | covered: l.9-14, l.75 | +| `openRepoTools:70-72, 219-220`; `README.md:336-337` | `REPO="${OPENREPOTOOLS_REPO:-opensoft/openRepoTools}"`, `REF="${OPENREPOTOOLS_REF:-main}"`, `SELF="${BASH_SOURCE[0]:-$0}"`. | The default REPO now names the assembly. Payloads live in `openRepoTools-code`. | covered: l.16-21, l.79 | +| `openRepoTools:258-275` (`fetch_from_repo`) | Fetches `repos/$REPO/contents/$path?ref=$REF`, falling back to `raw.githubusercontent.com/$REPO/$REF/$path`. The path is relative to REPO's root. | Code paths are not at the assembly's root. | covered: l.54 | +| `openRepoTools:282-285, 338, 962-990` (`INSTALLABLES`, `collect_commands`) | "EVERY ONE OF THEM IS RESOLVED BY BARE NAME AT THE REPOSITORY ROOT". It copies `$selfdir/` and fetches `` otherwise. | The names sit at the code root, not the assembly root. | covered: l.40-48, l.55 | +| `openRepoTools:1290, 1303, 1370-1398` (`collect_skills`) | `skills//SKILL.md` and `commands/.md` beside `$SELF`, fetched otherwise. Run from `~/.local/bin`, the 12 skill and command files are fetched from REPO/REF (inferred: they are not in the bin directory). | A fetch from the assembly misses them. | covered: l.16-18, l.55, l.78 | +| `openRepoTools:2502-2517` (`wip_shape_ref`) | Reads `$selfdir/contracts/openreposhape-pin.yaml`, else fetches `contracts/openreposhape-pin.yaml` from REPO/REF, else falls back to `main` (`:2516`). | `contracts/` moves to code. A fetch from the assembly would silently fall back to `main` (inferred from `:2516`). | covered: l.56 | +| `openRepoTools:2519-2523, 2187, 2192` (`wip_fetch_template_file`) | `$selfdir/upstream/openRepoShape/templates/workspace-root/`, else `opensoft/openRepoShape` at the pinned ref. | `upstream/` moves to code. | covered: l.57, l.87 | +| `openRepoTools:1218-1222` (`venv_note` comment) | Names the "convention `docs/README-lanes.md` states". | `docs/` moves to spec. | not covered (adoption-plan.yaml:328 follow-up) | +| `openRepoTools:28-56, 393-396` against installer-design.md:61-64 | Main: 17 `INSTALLABLES`; "31 artifacts, 29 of them files, 29 rows". The design: "15 names … 27 placed files plus two hook entries, 29 artifacts". | The design's numbers are those of `daed209`. | partial: l.64-65 ("Derive counts from the lists") | +| c4864ac tree against adoption-plan.yaml (baseline `daed209`) | `lane-worktrees`, `lanes-index` and `ideation/` (12 files) are tracked on main. | They are under no mapped path in the plan of record. | not covered (regeneration: T003, T012) | +| `repos.tsv:52` (`:8`, `:29-30`) | The only openRepoTools alias is `openRepoTools` → `opensoft/openRepoTools`. Unknown aliases are refused. | There are no leg aliases. | not covered | +| `openRepoTools:1320, 1352, 2211` | Hook commands name `~/projects/xFactory/lanes-edit.sh`. `workspace.yaml` is read from `${AGENT_PROTOCOL_ROOT:-$HOME/.agents}`. Neither depends on the layout. | Nothing (inferred). | covered: l.59, l.86 | +| `lane-worktrees:2164-2172, 2712`; `lanes-edit.sh:12146-12214` | Lane roots are `/.claude/worktrees` and `/.lane-worktrees/`. The inventory is `/.lane-state/`. | There is no `/worktrees` root for triad Speckit features (inferred from `_roots`). | not covered | +| `openRepoTools:291-292, 298-300, 322` | The comments name external consumers: workBenches' `setup-estate-commands.sh` 755 verification, `setup-claude-profiles.sh`, and `claude-profile` calling `claude-current`. | These are the workBenches rows above. | not covered | +| `.gitmodules:1-3`; `upstream/openRepoShape` gitlink `39d5c986`; `contracts/openreposhape-pin.yaml` | The dependency unit read by `wip_shape_ref` and `wip_fetch_template_file`. | All three move to code together (plan.md:60, FR-004). | covered: l.56-57 | + +## Not covered by installer-design.md + +**workBenches (9):** + +1. `upstream-pin.yaml` source rows +2. `update-upstream.py` fetch and tree-mode reads +3. Dockerfile `/usr/local/bin` COPY and submodule comment +4. `estate-commands-start` array parse +5. `setup-estate-commands.sh` shim and pin checks +6. `README.md` "installed from `opensoft/openRepoTools`" +7. vendored lane code's `.lane-worktrees` derivation +8. devcontainer tests and CI path filters +9. prose and spec references + +**openRepoShape (3):** + +1. `templates/workspace-root` text naming README-lanes and the tooling's home +2. `shape_advisory.py:509` +3. provenance prose + +**brett-wip and register state (11):** + +1. lane log `dir` records +2. other path-bearing log lines +3. LANES.md rows +4. README-lanes location lines +5. `repos.tsv` override without leg aliases +6. handoffs naming the checkout root +7. `.lane-worktrees` lines +8. `openRepoTools-worktrees` lines +9. `~/projects/openRepoTools/lanes-edit.sh` lines +10. host-local `.lane-state` tree records +11. the `handoffs` symlink in the checkout root + +**`~/.agents` and the home directory (5):** + +1. "code lands in `opensoft/openRepoTools`" +2. `docs/README-lanes.md` in the protocols +3. the Speckit worktree root +4. the `setup-openspeckit` re-run +5. the installed handoff skill's writer-poll globs + +**Installer, own assumptions (5):** + +1. `venv_note`'s `docs/` reference +2. the paths unmapped against the baseline (`lane-worktrees`, `lanes-index`, `ideation/`) +3. `repos.tsv` leg aliases +4. lane-worktrees and `.lane-state` roots +5. comments naming external consumers + +Total: 33 rows not covered. A further 7 are partial: workBenches 3, openRepoShape 1, `~/.agents` 2, installer 1. + +## Could not read + +- **Brett Heap's worktree `/workspace/projects/openRepoTools-worktrees/004-migrate-to-triad`:** not entered, under the hard rule. The plan files were read from lane 2's worktree at the same commit, ff6f6a7. +- **workBenches submodules** (`sysBenches/cloudBench`, which is modified, and `devBenches/*Bench`, `sysBenches/365Bench`): `git grep` at HEAD does not recurse into them. Not read. +- **Other writers' trees:** workBenches feature worktrees (`speckit-worktrees/012`–`017`) and lane 1's `wb-*` worktrees. Not read. +- **brett-wip:** the 215 untracked entries (`handoffs/xFactory/attachments/lane-opendox/…`) were not read. Commits after `ab88a10` (`466c3a8`, `349caef`) were not read. +- **GitHub, live:** no network read was made. Every statement that a URL or contents path would 404 after the split is marked inferred. PR #187 and the #186 record were not read here. +- **Raven** and any other workstation: not reachable from this bench. +- **`~/.claude-profiles/shared/skills/*` and `shared/commands/*`:** not opened. The receipt shows the same digests as the `~/.claude` copies that were read. +- **`git status` without `--no-optional-locks`** ran in `/workspace/projects/openRepoTools`, `/workspace/projects/workBenches` and `/workspace/projects/brett-wip`. The first two `.git/index` mtimes (`2026-10-07 04:28:20Z`, `2026-10-06 13:08:26Z`) predate this read. brett-wip's (`11:05:49Z`) postdates other writers' commits, and this read ran only `show`, `grep` and `rev-parse` there after 10:06Z. + +## Gate C follow-up list: outside changes and timing (2026-10-07T11:21Z) + +Added at lane 1's request. The table has one row per not-covered item, 33 in all. + +- **`#`** follows the numbering of "Not covered by installer-design.md" above: W = workBenches, S = openRepoShape, B = brett-wip and register state, A = `~/.agents` and home, I = the installer's own assumptions. +- **Outside change?** "yes" names the repository or host file to change. "no" means the change is in openRepoTools only. "no change" means nothing has to change. +- **Timing:** + - ADDITIVE BEFORE CUTOVER: the change works against both today's single repository and the assembly. + - WAITS FOR REAL LEGS: the change needs the real leg repositories, their commits, the real code pin, or a lane rebinding. + - "—" means nothing to time. + +All timings are judged from the reads above. Rows that rest on judgement are marked "(inferred)". + +| # | consumer / file:line | change needed outside openRepoTools? | timing | one-line reason | +|---|---|---|---|---| +| W1 | workBenches `devBenches/base-image/upstream-pin.yaml:56-125` | yes: workBenches, the `openrepotools` source block (`source_repository`, `commit`, rows) | WAITS FOR REAL LEGS | `apply` refuses a commit not on the source's default branch (`update-upstream.py:890-914`) and reads modes from that commit's tree (`:941-956`), so it needs `openRepoTools-code` with the files landed. | +| W2 | workBenches `update-upstream.py:917-956` | no change, if W1 names `opensoft/openRepoTools-code` (inferred) | — | The updater fetches `` at any repository's root; only the pin's source changes. | +| W3 | workBenches `devBenches/base-image/Dockerfile:148-156` (comment), `:216-238` | yes: workBenches, comment `:148-152` only. The COPY lines stay while the vendored tree mirrors the code root (inferred). | WAITS FOR REAL LEGS (inferred) | The comment says where openRepoShape is a submodule, which changes only when the dependency unit moves into the code leg. | +| W4 | workBenches `estate-commands-start:157-186` | no: openRepoTools only. The code implementation that workBenches vendors keeps the one-line `INSTALLABLES`/`SKILLS`/`COMMANDS` arrays. | ADDITIVE BEFORE CUTOVER (inferred) | It is a constraint, and a test of it, that holds for today's file and for the code leg's; nothing in workBenches changes. | +| W5 | workBenches `scripts/setup-estate-commands.sh:162-434` | no change for the split, if W1 keeps the source id `openrepotools` (read at `:285`) and the flat layout (inferred) | — | Its 15 `TOOLS_FILES` against main's 17 `INSTALLABLES` is a gap that exists on main today, not one the split causes. | +| W6 | workBenches `README.md:188, 190` | yes: workBenches (optional prose) | ADDITIVE BEFORE CUTOVER (inferred) | `:188` ("installed from `opensoft/openRepoTools`") stays true through the assembly entry point; a clause naming `openRepoTools-code` after the split is true in both states. | +| W7 | workBenches vendored lane code (`files/openrepotools/lane-handoff:913`, `lanes-edit.sh:11939`, `skills/handoff/SKILL.md:292`) | no: openRepoTools only. The fix lands in openRepoTools and reaches workBenches only through W1's re-vendor. | ADDITIVE BEFORE CUTOVER (inferred) | A worktree search can add `/worktrees/*/{spec,code}` today; a directory that does not exist is skipped. | +| W8 | workBenches `devcontainer.test/*`, `.github/workflows/speckit-git-bash.yml:19, 53` | yes: workBenches, only if W1's re-vendor changes the vendored tree (inferred) | WAITS FOR REAL LEGS | These follow the vendored bytes, which change only with W1. | +| W9 | workBenches prose: `docs/claude-multi-account-profiles.md`, `openspec/**`, `specs/**`, and others | no change (inferred) | — | The cites are pinned to commits (for example `63a74af`) or sit in archived or dated records. | +| S1 | openRepoShape `templates/workspace-root/AGENTS.md:32, 71-76, 91-95`; `README.md:16, 18, 31, 58`; `handoffs/README.md:24`; `lanes/LANES.md:19, 40`; `lanes/log/README.md:4, 6` | yes: openRepoShape (optional template wording) | ADDITIVE BEFORE CUTOVER (inferred) | The text names the project slug, which survives; a clause naming the spec leg after the split reads true before and after. It reaches WIP repositories only once the openRepoShape pin openRepoTools carries moves (`openRepoTools:2502-2517`). | +| S2 | openRepoShape `scripts/shape_advisory.py:509` | no change (inferred) | — | `resume` still reads `workspace.yaml`, so the docstring stays true. | +| S3 | openRepoShape provenance prose (`openRepoShape:19-25, 162`; `README.md:246, 1239`; `docs/handbook.html`; `AGENTS.md:429`; tests) | no change (inferred) | — | The slug survives as the assembly, and the files are still `opensoft/openRepoTools`' at project level. | +| B1 | brett-wip `lanes/log/openRepoTools-{1,2,3}.md` `dir` records (52 lines) | yes: brett-wip, new STARTED/RESUMED lines written by `lane-start`/`lanes-edit.sh`, only if a lane's directory changes at rebinding. In-place adoption keeps `/workspace/projects/openRepoTools` (inferred). | WAITS FOR REAL LEGS | The recorded `dir` changes only through a lane rebinding (T018); past lines are history. | +| B2 | brett-wip other path-bearing log lines (10) | no change | — | The log is append-only history. | +| B3 | brett-wip `lanes/LANES.md:1109, 1303, 2581` | no change (inferred) | — | The rows name brett-wip handoff paths, which do not move. | +| B4 | brett-wip `lanes/LANES.md:36` (the other 11 README-lanes lines are dated records) | yes: brett-wip, the `LANES.md:36` header prose | ADDITIVE BEFORE CUTOVER (inferred) | A pointer naming the manual by project and by its spec-leg `docs/` location after the split is true in both states. Writes follow the file's HAZARD rule (`:1-8`). | +| B5 | brett-wip `lanes/repos.tsv:52` (per-WIP override) | no: openRepoTools only (the shipped table, I3). The override need not change: "an override row … adds rows the shipped table does not carry" (`lanes-edit.sh:2440-2442`). | WAITS FOR REAL LEGS | Same reason as I3. | +| B6 | brett-wip handoffs naming `/workspace/projects/openRepoTools` (145 lines) | no change (inferred) | — | In-place adoption keeps the checkout path, and the lines are dated records. | +| B7 | brett-wip `.lane-worktrees/openRepoTools-{1,2,3}` lines (112) | no change (inferred) | — | The root is derived from the lane `dir`, which stays; the lines are dated records. | +| B8 | brett-wip `openRepoTools-worktrees` lines (16), live in the canonical top blocks `session-handoff-2026-09-13-lane-openRepoTools-3.md:6`, `…-2026-09-16-lane-openRepoTools-1.md:8`, `…-2026-10-02-lane-openRepoTools-2.md:45` | yes: brett-wip, those top blocks, rewritten by each lane at its next handoff | WAITS FOR REAL LEGS | Live feature worktrees move to `/worktrees//{spec,code}` only through T016-T017 translation and T018 rebinding. | +| B9 | brett-wip `~/projects/openRepoTools/lanes-edit.sh` lines (20, all in `handoffs/xFactory/**`) | no change | — | All 20 are dated September records. The live hooks use `~/projects/xFactory/lanes-edit.sh`, which points at the installed copy. | +| B10 | host `/workspace/projects/.lane-state/openRepoTools-{1,2,3}/trees/*.yaml` | no: openRepoTools only. These are host files written by `lanes-edit.sh`/`lane-worktrees`, not by hand. | WAITS FOR REAL LEGS | Records for leg worktrees can be written only once leg worktrees exist. | +| B11 | host symlink `/workspace/projects/openRepoTools/handoffs` | no outside change. The host's `.git/info/exclude` (`/handoffs`) survives in-place adoption (inferred). An optional root `.gitignore` line would be an openRepoTools change. | ADDITIVE BEFORE CUTOVER (inferred) | An ignore line for `/handoffs` is valid in both shapes. | +| A1 | `~/.agents/AGENTS.md:327, 347-348, 367, 391-392, 419, 430, 443-444, 462, 488, 498` | yes: `~/.agents/AGENTS.md`, only the lines whose code has not landed; landed ones are history | WAITS FOR REAL LEGS (inferred) | A landing can name `openRepoTools-code` only once that repository exists and takes PRs. | +| A2 | `~/.agents/protocols/lane-collision-protocol-amendment-9.md:735, 943`; `-11.md:1511`; `-12.md:315`; `-14.md:185`; `-17.md:175`; `-18.md:222` | yes: `~/.agents/protocols` (ratified texts; any edit is the protocol owner's) | ADDITIVE BEFORE CUTOVER (inferred) | A pointer naming the manual's location in both shapes is true before and after. | +| A3 | host `/workspace/projects/openRepoTools/.specify/extensions/git/git-config.yml:83` (`worktree_root: ../openRepoTools-worktrees`, ignored) | yes: that host file. The `~/.agents` protocols already describe both layouts (`openspec-speckit-workflow.md:114`). | WAITS FOR REAL LEGS | `setup-openspeckit` writes `worktree_root: worktrees` only for a detected three-leg root (`project-agent-bootstrap.md:117, 163`). | +| A4 | host: the checkout root's ignored `.specify/`, `.claude/`, `.agents/`, `.codex/` | yes: those host files, through a `setup-openspeckit` re-run | WAITS FOR REAL LEGS | The bootstrap refuses a manifest whose spec leg is missing or empty (`project-agent-bootstrap.md:242-246`). | +| A5 | installed `~/.claude/skills/handoff/SKILL.md:329` | no: openRepoTools only (`skills/handoff/SKILL.md`). It reaches `~/.claude*` through `--install` and workBenches through W1. | ADDITIVE BEFORE CUTOVER (inferred) | A third glob `"$dir"/worktrees/*/*` works today: an absent directory fails `[ -d "$worktree" ]` (`:330`) and is skipped. | +| I1 | `openRepoTools:1218-1222` (`venv_note` comment) | no: openRepoTools only | ADDITIVE BEFORE CUTOVER (inferred) | A comment can name the manual in both places (adoption-plan.yaml:328 follow-up). | +| I2 | c4864ac paths missing from adoption-plan.yaml (`lane-worktrees`, `lanes-index`, `ideation/`) | no: openRepoTools only (regenerate the plan; T003, T012) | ADDITIVE BEFORE CUTOVER | It is a plan-file change with no effect on today's repository, and the regenerated plan is the input to `execute`. | +| I3 | `repos.tsv:52` (no leg aliases) | no: openRepoTools only (the shipped table) | WAITS FOR REAL LEGS | `repos.tsv:10-12` leaves out spellings not resolved to a repository, and `:23` adds a row "when a new repo first appears in a LANDING line". | +| I4 | `lane-worktrees:2164-2172, 2712`; `lanes-edit.sh:12146-12214` | no: openRepoTools only | ADDITIVE BEFORE CUTOVER (inferred) | `_roots` can add `/worktrees` today; an absent directory yields nothing. | +| I5 | `openRepoTools:291-292, 298-300, 322` (comments naming consumers) | no change (inferred) | — | The workBenches files named there keep those roles after the split. | + +**Outside-change rows (12):** + +- workBenches 4 (W1, W3, W6, W8) +- openRepoShape 1 (S1) +- brett-wip 3 (B1, B4, B8) +- `~/.agents` 2 (A1, A2) +- host-local files in the shared checkout 2 (A3, A4) + +**Timing, all 33 rows:** ADDITIVE BEFORE CUTOVER 11, WAITS FOR REAL LEGS 11, no change 11. Of the 12 outside-change rows, 4 are additive (W6, S1, B4, A2) and 8 wait (W1, W3, W8, B1, B8, A1, A3, A4). + +**Partial rows not included.** None of the 7 partials is judged to need an outside change (inferred): + +- workBenches 3 (the `/usr/local/share` vendored tree, the sentinel REPO/REF case, and `setup.sh`): all rest on openRepoTools's code implementation staying the vendored file. +- openRepoShape 1: its install-line tests change only if the URL changes, and installer-design keeps the URL. +- `~/.agents` 2: `AGENTS.md:273-278` stays true through the root entry point, and the `amendment-9.md:673, 1000` text is a dated record. +- installer 1: the stale counts in installer-design.md are an openRepoTools-side fix. + +**Erratum, no row changed.** The brett-wip row for `~/projects/openRepoTools/lanes-edit.sh` in the table above also cites `session-handoff-2026-09-13-lane-openRepoTools-3.md:296`. That line names `/workspace/projects/openRepoTools/handoffs/`, not `lanes-edit.sh`. All 20 `lanes-edit.sh` lines are in `handoffs/xFactory/**`. The command used to check this: + +```sh +git -C /workspace/projects/brett-wip show "ab88a10347fb605588643e7ea2e528217dab9a67:handoffs/openRepoTools/session-handoff-2026-09-13-lane-openRepoTools-3.md" | sed -n '296p' +``` + +The commands this revision added (read-only): + +```sh +git -C /workspace/projects/openRepoTools show c4864ac:lanes-edit.sh | sed -n '2440,2470p' +git -C /workspace/projects/openRepoTools show c4864ac:repos.tsv | sed -n '8,14p;23p' +grep -n 'missing or empty\|worktree_root: worktrees\|exits non-zero when the manifest' ~/.agents/protocols/project-agent-bootstrap.md +grep -n '\[ -d "\$worktree" \]' ~/.claude/skills/handoff/SKILL.md +ls /workspace/projects/openRepoTools/.specify/extensions/git/ +grep -n 'worktree_root\|checkout_mode\|base_branch' /workspace/projects/openRepoTools/.specify/extensions/git/git-config.yml +``` diff --git a/specs/004-migrate-to-triad/gate-b-checklist.md b/specs/004-migrate-to-triad/gate-b-checklist.md new file mode 100644 index 00000000..db9c0ab4 --- /dev/null +++ b/specs/004-migrate-to-triad/gate-b-checklist.md @@ -0,0 +1,299 @@ +# Gate B checklist walk — 2026-10-07 + +**Sources read:** 2026-10-07T10:05Z, from commit +`ff6f6a7c7b7921ca1e0b0234e898900f98532366` (branch `004-migrate-to-triad`, +also the head of PR #187). **Live state rechecked:** 2026-10-07T11:06Z. +**By:** lane openRepoTools-2's writer, under opensoft/openRepoTools#186. +**For:** lane openRepoTools-1, to walk before it asks Brett Heap for Gate C. + +This walk records facts. It approves nothing, and it changes no status in +`tasks.md`, where all 19 tasks remain open. Gate C stays Brett Heap's explicit +approval naming the actual revisions (plan.md:161–163). + +## How it was read + +These commands ran inside lane 2's `triad-reads` worktree, which is checked out +at ff6f6a7. The host path given to `git -C` is left out here because the +feature's public files carry no machine paths (plan.md:38–39). All `gh` calls +were reads. + +```sh +for f in plan tasks spec verification preparation adopter-blocker adopter-rehearsal \ + installer-design quickstart research data-model protocol-review; do + git show ff6f6a7:specs/004-migrate-to-triad/$f.md | cat -n +done +git show ff6f6a7:specs/004-migrate-to-triad/inventory.json # parsed with python3 -I json +git show ff6f6a7:openspec/changes/migrate-to-triad/tasks.md | cat -n +git show ff6f6a7:openspec/changes/migrate-to-triad/design.md | cat -n +git show ff6f6a7:openspec/changes/migrate-to-triad/proposal.md | cat -n +git show ff6f6a7:openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md | cat -n +git show ff6f6a7:openspec/changes/migrate-to-triad/adoption-plan.yaml | cat -n | sed -n '1,80p;325,380p' +git grep -n -i -E 'gate ?b|gates a/b|gate a/b' ff6f6a7 -- . +git show c4864ac:.github/workflows/tests.yml | grep -n -E '^ [a-z][a-z0-9_-]*:$|runs-on' +git show c4864ac:tests/test_upstream_pin.py | sed -n '170,200p' +git ls-tree c4864ac upstream/openRepoShape +git ls-tree -r --name-only c4864ac | wc -l +git ls-tree -r --name-only c4864ac | grep -c '^features/' +git show --stat e43b243; git show --format= e43b243 -- contracts/openreposhape-pin.yaml +git worktree list --porcelain; git for-each-ref refs/heads # branch heads only +gh issue view 186 --repo opensoft/openRepoTools --json body,comments +gh pr list --repo opensoft/openRepoTools --state open --json number,headRefName,title +gh pr view 187 --repo opensoft/openRepoTools --json body,headRefOid,state +gh pr view 188 --repo opensoft/openRepoTools --json statusCheckRollup,labels,reviews,headRefOid +gh pr view 162 --repo opensoft/openRepoShape --json state,mergedAt,mergeCommit,reviews,comments +gh api repos/opensoft/openRepoShape/compare/39d5c986fcfac1a160474bfe91c5f1c37fccc72c...7f84ca42ca86a8902928345109d2bf6bad87bd91 +gh api repos/opensoft/openRepoTools-spec; gh api repos/opensoft/openRepoTools-code +gh api 'repos/opensoft/openRepoTools/branches?per_page=100' --paginate +``` + +Short names used below: **cap-spec** is +`openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md`, +and **#186 first act N** is the numbered "First acts" list in #186's body. +Every `file:line` refers to ff6f6a7 unless another commit is named. + +## State at read time + +- openRepoTools `main` is `c4864ac`. Its gitlink `upstream/openRepoShape` is + still `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`, and it tracks 100 paths. +- Two PRs are open: + - **#187**: `004-migrate-to-triad` at ff6f6a7 into `main`, opened + 10:03:43Z. Lane 1 lands it. + - **#188**: `chore/openreposhape-pin-7f84ca4` at `e43b243`, opened 10:10:43Z. + This is the repin PR. +- openRepoShape PR #162 is MERGED (2026-10-07T01:09:14Z) as `7f84ca4`, which + is still openRepoShape `main`'s head. The compare `39d5c98...7f84ca4` shows + ahead 2, behind 0: `1a9fc53` (#164) and `7f84ca4` (#162). +- The local branches `004-migrate-to-triad-exec` (Gate A writer), + `004-migrate-to-triad-rehearsal` (rehearsal writer) and + `004-migrate-to-triad-reads` (lane 2) all point at ff6f6a7. None of them is + on the remote. Lane 2's reads branch then gained ae70dc556 (line 24). +- `opensoft/openRepoTools-spec` and `opensoft/openRepoTools-code` both return + HTTP 404 to the read-only API. Neither the shared repository nor the remote + has an `adopt/` ref. +- #186 comment + [6035767825](https://github.com/opensoft/openRepoTools/issues/186#issuecomment-6035767825) + (10:11:58Z) records four things: + - Brett Heap's words "open the PR for the planning branch; legs and + visibility confirmed". + - The legs and visibility are CONFIRMED. The comment calls this "a Gate C + input, not Gate C". + - The Gate A backup root is host-local, beside `prep-20261004T211123Z`; the + comment names the path. + - Lane 3's independent recompute of the 7f84ca4 tree digest matches #188's + row. + +## Status legend + +Each line has exactly one status. + +- **EXISTS on ff6f6a7**: the artifact is in the tree at ff6f6a7. The cell + cites it and says what it shows. Line 24 alone reads **EXISTS on + 004-migrate-to-triad-reads @ ae70dc556**: its artifact was committed on top + of ff6f6a7 on this branch. +- **DECIDED**: settled by Brett Heap's word, recorded outside ff6f6a7. Line 1 + is the only line with this status, on the coordinator's instruction. +- **IN PROGRESS by …**: a named writer holds the work at read time. The cell + says what was observed of that work. +- **NOBODY**: no lane writer holds the work at read time. If the work has to + wait for something, the cell names it as "starts after". +- **BLOCKED on …**: lane work alone cannot satisfy the line as the plan + stands. The cell names what it waits on. + +## Gate B in the plan's words + +> **Gate B:** complete local rehearsal evidence, restore rehearsal, reviewed +> follow-up patches, resolved mapping and a passing compatibility test matrix. +> Mapping `check` alone does not satisfy this gate. (plan.md:140–142) + +> Stop adoption on this refusal; resolve upstream and repeat into fresh local +> remotes before treating Gate B as passed. Installer/topology design can +> proceed while that resolution is pending. (plan.md:146–148) + +| Gate B term (plan.md:140–141) | Checklist lines | +| --- | --- | +| complete local rehearsal evidence | 2, 7–16, 39, 41–45 | +| restore rehearsal | 36–37 | +| reviewed follow-up patches | 17–22, 25–26, 29, 32–33, 40, 46 | +| resolved mapping | 1, 3–6 | +| passing compatibility test matrix | 27–28, 30–31, 34–35 | +| inputs and publication (design, consumer reads, Gate A evidence) | 23–24, 38 | + +## Checklist + +### T003: mapping, leg names, prerequisites (tasks.md:33–40) + +T003 sits under the heading "Phase 1 — Preservation and baseline (Gate A)" +(tasks.md:19). Its mapping is Gate B's "resolved mapping" (plan.md:141), and +#186 first act 3 groups it with the rehearsal as "Gate B rehearsal (T003–T005)". + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 1 | "Confirm proposed leg names/visibility" (tasks.md:33). FR-012: "Treat visibility, baseline, branch disposition and lane rebinding as reviewed execution decisions" (spec.md:66–67). "Public new legs are proposed … Their creation is not approved." (spec.md:115–116) | Brett Heap's word naming the legs and their visibility, matching `visibility: public` (adoption-plan.yaml:21) and `legs:` (adoption-plan.yaml:27–30). | **DECIDED.** #186 comment 6035767825 quotes "open the PR for the planning branch; legs and visibility confirmed" and records `openRepoTools-spec`, `openRepoTools-code` and `public` as CONFIRMED, "a Gate C input, not Gate C". Name availability is a separate recheck at Gate C (preparation.md:53–56, plan.md:162–163). | +| 2 | "inspect prerequisite availability" (tasks.md:33–34). "Make `git-filter-repo` available through the approved prerequisite path" (plan.md:105–106). It "must be made available before rehearsal/execution" (spec.md:116–117). | The rehearsal receipt names the git-filter-repo version, its wheel SHA256 and the private venv, and states that bench/system installs were left unchanged. preparation.md:60–65 shows the form. | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3 specifies "`git-filter-repo` 2.47.0 in a private venv". preparation.md:60–65 holds the October 4 receipt, for the 39d5c98 run only. No line on ff6f6a7 says who approved the private-venv path; it was installed "for this rehearsal" (preparation.md:62–63). | +| 3 | "regenerate `adoption-plan.yaml` for the reviewed preliminary rehearsal source, retaining reasoned overrides" (tasks.md:34–35). "Regenerate the mapping using the standard rather than editing its source SHA" (preparation.md:112). "Do not change the baseline field to suppress a stale-plan finding" (quickstart.md:29–30). | A plan produced by `adopt-project.py plan` at 7f84ca4 from the repinned candidate, with `source.commit` set to that candidate. Every earlier `resolution:` is kept or re-reasoned, and every path added since daed209 is resolved with a reason. adopter-rehearsal.md:44–48 shows the October 6 precedent: `lanes-index` to code, `ideation/` to spec. | **IN PROGRESS by lane 1's rehearsal writer.** The plan committed on ff6f6a7 is from daed209 at 39d5c98 and covers 64 paths (adoption-plan.yaml:13–16), marked `proposed-preliminary-baseline` (adoption-plan.yaml:374). Main `c4864ac` tracks 100 paths. | +| 4 | "Verify standard `check` passes and records all source paths with no unapproved drops" (tasks.md:35–36). FR-002 (spec.md:40–41). SC-001 (spec.md:95–96). | `check` exits 0 at 7f84ca4 against the regenerated plan. The plan summary shows `unresolved` 0, and drops are 0 or each one is approved. | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3: "regenerate …, `check`". | +| 5 | "Explicitly classify genuine bounded feature amendment folders as code until upstream qualification; preserve full proposals/archives/canonical Speckit as spec regardless of branch origin" (tasks.md:36–38). FR-006 and FR-013 (spec.md:50–53, 68–72). plan.md:115–118. | The regenerated plan assigns `openspec/`, `specs/`, `docs/` and `ideation/` to spec. Any `features//openspec/` path goes to code with a `resolution:`. | **IN PROGRESS by lane 1's rehearsal writer**, as part of the regeneration in line 3. Observation: `git ls-tree -r --name-only c4864ac \| grep -c '^features/'` prints 0. | +| 6 | "Record no amendment paths when none exist; do not manufacture historical amendments" (tasks.md:39–40). | A per-head record of bounded amendment paths at the rehearsal source and the retained heads, empty where there are none. The form is inventory.json `protocol_review.amendment_path_observations` (inventory.json:342), which on ff6f6a7 covers only daed209 and the October 4 heads. | **IN PROGRESS by lane 1's Gate A writer**, as part of the `inventory.json` refresh. That the refresh keeps this field is (inferred). | + +### T004: isolated clone and local bare-remote rehearsal (tasks.md:44–47) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 7 | "Prepare a clean isolated source clone with no linked worktrees" (tasks.md:44–45), "at the chosen source commit" (plan.md:104). FR-010 (spec.md:62–63). "Execution SHALL use a clean isolated source clone without linked worktrees" (cap-spec:147). | A receipt naming the clone's HEAD (the repinned candidate) and showing a single-branch clone, a clean status and one `git worktree list` entry. | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3: "fresh isolated single-branch clone of the repinned candidate". | +| 8 | "rehearse the standard adoption against temporary local bare remotes" (tasks.md:45–46), "with no real GitHub repository creation or default-branch movement" (plan.md:107–108). | `execute --local-remote-dir … --work-dir … --yes` exits 0 at 7f84ca4, into fresh disposable bare remotes, with network transport disabled except local file transport. preparation.md:67–70 and adopter-rehearsal.md:51–54 show the form. | **IN PROGRESS by lane 1's rehearsal writer.** | +| 9 | "Verify source identity/history, path/blob accounting" (tasks.md:46–47). FR-002 and SC-001. Each tracked path accounted "by blob or gitlink identity in exactly one leg/root" (cap-spec:12–16). "full baseline accounting, leg histories" (plan.md:110–111). | The standard's accounting table (spec, code, root, dropped, total). An independent comparison of path, mode, object type and object ID showing zero missing or duplicate owners. The leg commits with their kept-commit counts. adopter-rehearsal.md:56–73 shows the form. | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3: "Record source accounting, leg commits". #186 does not say whether the independent comparison is part of that writer's scope. | +| 10 | "… and recoverability without real GitHub creation" (tasks.md:46–47). "The source repository must remain unchanged if execution refuses" (adopter-blocker.md:58–59). | Source clone HEAD, refs and status identical before and after. The disposable legs kept for diagnosis. The live consumer's main, gitlink and pin contract unchanged. adopter-rehearsal.md:52–54 and 80–81 show the form. | **NOBODY.** It is not in #186 first act 3's record list ("source accounting, leg commits, recursive bootstrap, nested pin and digest"). | + +### T005: nested dependency and pin (tasks.md:48–52) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 11 | "If standard tooling refuses, record its refusal" (tasks.md:50–51). | The refusal, with the exact command, the exit status and the step that failed. | **EXISTS on ff6f6a7.** adopter-blocker.md:15–35 records `git submodule add` exiting 128 and `execute` returning 2. The same refusal is in preparation.md:72–77 and verification.md:13–16, and adopter-blocker.md:75–76 gives the private log's SHA256. | +| 12 | "resolve upstream" (tasks.md:51). The upstream regression "should cover a populated existing submodule, its registration explicitly assigned to code, the generated assembly registrations, recursive clone/bootstrap, exact mode/object accounting, and failure recovery", plus "partial registration ownership and no-existing-module inputs" (adopter-blocker.md:61–65). | Regression results covering each named case for the fix. | **EXISTS on ff6f6a7, for the candidate only.** adopter-rehearsal.md:15–37 records `tests/test_adopt_*.py` at 90 passed, 1 skipped, and four `test_adopt_submodules.py` cases at draft `91d5685`. The mixed-registration case "does not qualify every mixed-registration plan" (adopter-rehearsal.md:30–32). PR #162 merged at a later head. Its GitHub review list is empty, and its review is a PR comment (2026-10-07T01:08:38Z) titled "Review, and what changed since 91d5685". | +| 13 | "before a tested pin bump" (tasks.md:51). "bump to a commit on its main and recompute the dependency digest" (adopter-blocker.md:70). "use a commit on upstream main for the tested consumer pin/gitlink update and recomputed digest" (adopter-rehearsal.md:90–92). | One consumer commit that moves the gitlink and `contracts/openreposhape-pin.yaml` to a commit on openRepoShape main with `tree_sha256` recomputed, passes the required CI and lands on `main`. | **IN PROGRESS by lane 1's repin PR writer** (PR #188, open, not landed). `e43b243` (parent `c4864ac`) changes 2 files: gitlink to `7f84ca4`, `tree_sha256` to `3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8`. Checks at 11:04Z: `guard-launch-mode`, `tests`, `tests-no-submodule`, `tests-windows` and `parse-macos` SUCCESS; `tests-macos` SKIPPED; no `ready` label. The upstream side is done: #162 MERGED as `7f84ca4`, openRepoShape main's head. Lane 3 holds the adversarial review. | +| 14 | "Exercise the existing nested submodule path, original `.gitmodules` extraction/removal" (tasks.md:48–49). FR-004 (spec.md:44–46). "source `.gitmodules` handling" (plan.md:110). | At 7f84ca4 the mount step that refused at 39d5c98 passes. The code leg carries the original `.gitmodules` bytes with the `upstream/openRepoShape` gitlink and contract. The assembly carries a fresh `.gitmodules` for spec and code only (the expected behavior, adopter-blocker.md:56–59). | **IN PROGRESS by lane 1's rehearsal writer.** | +| 15 | "pin integrity" and "Verify the code gitlink/pin/registration remain coupled" (tasks.md:49–50). "its registration, exact gitlink and coupled pin SHALL remain valid" (cap-spec:23–26). | In the extracted code leg: the gitlink equals the contract's `commit:`, the pinned checkout's own helper recomputes a digest equal to the contract's `tree_sha256`, and the registration is unchanged. preparation.md:90–94 and adopter-rehearsal.md:77–81 show the form. | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3: "nested pin and digest". | +| 16 | "recursive bootstrap" (tasks.md:49). It must be "demonstrated by local rehearsal and recursive bootstrap" (cap-spec:25–26). SC-004 (spec.md:101–102). | A recursive clone of the disposable assembly and the generated `scripts/bootstrap.py` both pass (naming, manifest, exact leg and copy pins), and the trees are clean afterwards. adopter-rehearsal.md:75–77 shows the form. On October 4 this was "blocked" (preparation.md:94–95). | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3: "recursive bootstrap". | + +### T006: root collisions, leg guidance, workflow roots (tasks.md:53–61) + +"T004–T006 precede integration validation" (tasks.md:162). Lane 2's consumer-side +reads for T006 (`consumer-reads-2026-10-07.md`, committed at ae70dc556) are reads. They are +not the patches these lines require. + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 17 | "Resolve materialized root collisions and new leg guidance in reviewable patches" (tasks.md:53–54). "Exercise all actual file-placement collisions" (plan.md:111–112). "Add leg root guidance without overwriting original root guidance" (plan.md:127). | The list of collisions that `execute` at 7f84ca4 actually materializes. At daed209 the plan lists five: `.gitattributes`, `.gitignore`, `AGENTS.md`, `CLAUDE.md` and `README.md` (adoption-plan.yaml:337–341). Then one reviewed patch per resolution against the rehearsed assembly commit, keeping the original root guidance. | **NOBODY.** Starts after line 8. | +| 18 | "bootstrap selected root workflow after manifest/legs exist" (tasks.md:54–55). "regenerate root workflow using setup-openspeckit after manifest/legs are present" (adoption-plan.yaml:346). | The shape-aware bootstrap run at the rehearsed assembly root, with its result recorded. | **NOBODY.** Starts after line 8. | +| 19 | "Verify first-line shape guidance, relative paths, actual `.specify` configuration and paired feature selection without copying machine secrets" (tasks.md:55–56). "Put `Read AGENTS-shape.md first...` guidance first" (plan.md:184–185). | The first lines of the root `AGENTS.md` and `CLAUDE.md`. The `.specify` configuration compared with the captured ignored workflow configuration, with no secret-bearing file copied. Paired feature selection resolving. | **NOBODY.** Its input, the Gate A writer's capture of ignored workflow configuration, is IN PROGRESS. | +| 20 | "Record original approved repository/commit/path and verified extracted spec correspondence … Repair relative links, selected roots/stores and task paths without guessing new baseline identities" (plan.md:118–121). FR-014 (spec.md:73–77), which tasks.md:188 maps to T006. | A correspondence table from original repository, commit and path to extracted spec commit and path. Reviewed patches for the cross-leg references; at daed209 the code files that name `docs/`, `openspec/` and `specs/` are listed at adoption-plan.yaml:325–336. | **NOBODY.** | +| 21 | "Verify explicit full-spec/local-amendment roots and intended feature branches, local-root precedence over store pointers and supported CLI store selection" (tasks.md:57–58, plan.md:131–135). | Runs in the rehearsed topology showing the selected root and branch for each operation, and a local root winning over a store pointer. `--store` is used only after recording that the installed CLI supports it. | **NOBODY.** | +| 22 | "check protocol/command distribution per target workstation through owning workBenches delivery, without treating a scaffold bootstrap as distribution" (tasks.md:59–61, plan.md:136–138). | For each target workstation, the identities and digests of the installed protocol and commands, in the form of protocol-review.md:11–16. | **NOBODY.** | + +### T007: installer entry point (tasks.md:65–68) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 23 | "Installer/topology design can proceed while that resolution is pending" (plan.md:148). The installer design "is ready for follow-up implementation after successful standard split verification" (plan.md:15–16). | A design naming the entry point, the payload-source resolution, the consumers that change and the acceptance matrix. | **EXISTS on ff6f6a7.** installer-design.md:1–97, prepared against daed209 (installer-design.md:3). | +| 24 | "refresh this inventory after landing" (installer-design.md:4–5). "Derive counts from the lists" (installer-design.md:64–65). At daed209 there were 15 `INSTALLABLES` and 29 artifacts (installer-design.md:61–64). | A read of the current source covering `INSTALLABLES`, the skills and commands lists, the destinations and the consumers at installer-design.md:52–59, with line cites. | **EXISTS on 004-migrate-to-triad-reads @ ae70dc556** (`specs/004-migrate-to-triad/consumer-reads-2026-10-07.md`). Its lines 235–239 cover the consumers at installer-design.md:52–59 with `openRepoTools` line cites. Line 241 records that main c4864ac has 17 `INSTALLABLES` and "31 artifacts, 29 of them files, 29 rows", while the design's numbers are those of daed209. | +| 25 | "Add the assembly `openRepoTools` entry point and coherent payload-source resolution in the code installer after source byte accounting" (tasks.md:65–66). FR-005 (spec.md:47–49). "Record their patches and resulting commits" (plan.md:125–126). | Reviewed patches with their resulting commit ids: the entry point in the rehearsed assembly and the resolution in the rehearsed code leg. | **NOBODY.** Starts after line 9 (tasks.md:163). | +| 26 | "Verify gh/raw one-liners resolve one code pin and do not duplicate installer mechanics or depend on developer checkouts after installation" (tasks.md:67–68). cap-spec:52–55. SC-003 (spec.md:99–100). | Runs in fresh disposable homes against disposable remotes, showing every payload coming from one immutable code commit and the installed commands working with the developer checkout absent. | **NOBODY.** | + +### T008: compatibility matrix (tasks.md:69–72) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 27 | "Cover local/offline, legacy monorepo overrides, adopted forks, branch/commit refs, immutable code selection, missing/mismatched pins and failed partial fetch" (tasks.md:69–71). "All rows below are pending measured tests in fresh disposable homes/remotes" (installer-design.md:70–71); the matrix has 15 rows (installer-design.md:75–89). | One measured test per matrix row, with its result recorded. | **NOBODY.** | +| 28 | "Verify unchanged command/artifact names, counts, destinations/modes, hooks, ownership receipts and all-or-none refusal" (tasks.md:71–72). cap-spec:43–50. | A before-and-after comparison against the current installer's derived lists (line 24), and refusal runs that leave the prior install unchanged. | **NOBODY.** | + +### T009: explicit roots in fixtures and hygiene checks (tasks.md:73–76) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 29 | "Separate code/spec/assembly/dependency roots in fixture and hygiene consumers, including docs/OpenSpec/Speckit references" (tasks.md:73–74, installer-design.md:91–94). | Reviewed patches giving the fixtures and hygiene tests explicit roots. `tests/test_repo_hygiene.py` reads the root README, the install line and the agent guidance (installer-design.md:92–94). | **NOBODY.** | +| 30 | "Verify the existing upstream pin checks run against code Git identity" (tasks.md:74–75). "Do not bypass the wrapper to obtain a pass" (preparation.md:99). | `tests/run.sh -k upstream_pin` passing inside the rehearsed code leg, with the output quoted. On October 4 the run stayed in the serialization wait and "No pytest assertion ran" (preparation.md:95–99). | **NOBODY.** #188's Linux `tests` job runs against the monorepo layout, not a code leg. Lane 2's verification pass (#186 comment 6035767825: the eight files `tests/test_upstream_pin.py` mounts are byte-identical between 39d5c98 and 7f84ca4) is evidence for the repin, not for this line. | +| 31 | "required composed checks cannot silently skip absent spec/dependency context" (tasks.md:75–76). "Preserve the Bash 3.2 floor and original no-submodule test behavior, while requiring complete dependencies for composed acceptance" (plan.md:127–129). SC-004, "no hidden skips" (spec.md:101–102). installer-design.md:88, 97. | A run with the spec or dependency context absent in which the composed checks refuse, while the documented standalone no-submodule skips stay as they are. | **NOBODY.** | + +### T010: CI and composed acceptance (tasks.md:77–81) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 32 | "Adapt implementation CI and root exact-pin integration checks with explicit compatible checkout context" (tasks.md:77–78). "The assembly exact-pin integration job must refuse absent required contexts" (installer-design.md:97). design.md:121–126. | Reviewed workflow patches for the code leg and for the assembly root. | **NOBODY.** | +| 33 | "preserve current Linux/macOS/Windows/WSL policies, Bash 3.2 parsing and serialized `tests/run.sh` locking" (tasks.md:78–79). | The patched workflows keep every job of `.github/workflows/tests.yml` at c4864ac and delete no assertion. The jobs are `guard-launch-mode`, `tests` and `tests-no-submodule` (ubuntu-latest), `tests-windows` (windows-latest), and `parse-macos` and `tests-macos` (macos-latest), at tests.yml:52, 72, 126, 157, 232 and 285. | **NOBODY.** | +| 34 | "Verify the exact rehearsed composed state passes required checks and the compatibility matrix, recording failures rather than deleting assertions" (tasks.md:80–81): the part that runs on this host. | `tests/run.sh` and the matrix run against the exact rehearsed assembly, spec, code and standard commits ("Composed candidate evidence", data-model.md:15), with failures recorded. | **NOBODY.** | +| 35 | The same clause (tasks.md:80–81): the part that needs GitHub-hosted runners (the `tests-windows`, `parse-macos` and `tests-macos` jobs). | Those jobs' results against the exact rehearsed commits. | **BLOCKED on somewhere GitHub-hosted runners can check the rehearsed commits out from (inferred).** The rehearsed legs exist only in disposable local bare remotes. The suite's checkouts take `submodules: true` (tests.yml:7). #186 allows "no real leg repository … before Gate C". T015 later validates "the real exact assembled head using … required platform/CI" (tasks.md:107–108). | + +### T011: restore/rollback rehearsal and publication (tasks.md:82–85) + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 36 | "Rehearse restoration/rollback of the local candidate and installed payload using preserved artifacts" (tasks.md:82–83). Gate B's "restore rehearsal" (plan.md:140). Rollback (plan.md:238–247). SC-005 (spec.md:103–104). "Additional profiles/workstations and actual installer rollback still need receipts" (preparation.md:36–37). | A rollback-rehearsal receipt: the candidate left unmerged, original development and installation restored from the preserved artifacts, the installed payload returned to its pre-install receipt state, and digests compared. | **NOBODY.** Its input, the Gate A writer's preserved artifacts, is IN PROGRESS. The October 4 snapshot restores (preparation.md:22–30) are "not an owner-coordinated freeze or live rollback". | +| 37 | "Verify user work/jobs/claims survive and no force push, destructive reset or workspace-pointer rewrite is needed" (tasks.md:83–85, plan.md:243–247). | A before-and-after inventory of branches, worktrees and dirty content; register claims and WIP pointers unchanged; a command log with no force push and no hard reset. | **NOBODY.** | +| 38 | "Publish Gate A/B evidence" (tasks.md:85): the Gate A part. | A refreshed `inventory.json` and public-safe receipt identities and digests on `004-migrate-to-triad-exec`. The private bundle stays host-local beside `prep-20261004T211123Z`, and its receipt goes in the private WIP repository (#186 body, "Rules in force"; #186 comment 6035767825). | **IN PROGRESS by lane 1's Gate A writer.** At 11:06Z its branch is at ff6f6a7 locally and not on the remote. | +| 39 | "Publish Gate A/B evidence" (tasks.md:85): the Gate B rehearsal part. | A receipt for the 7f84ca4 rehearsal, in the form of adopter-rehearsal.md. | **IN PROGRESS by lane 1's rehearsal writer.** At 11:06Z its branch is at ff6f6a7 locally and not on the remote. | +| 40 | "… and follow-up patch/commit inventory" (tasks.md:85). "Record their patches and resulting commits so real execution can apply the reviewed changes after source verification" (plan.md:125–126). | One table of every T006–T010 patch, giving the target leg, the rehearsed base commit, the resulting commit and the review reference. | **NOBODY.** | + +### Cross-cutting conditions that no single task owns + +| # | Requirement (cite) | Evidence that would satisfy it | Status | +| --- | --- | --- | --- | +| 41 | "Stop adoption on this refusal; resolve upstream and repeat into fresh local remotes before treating Gate B as passed" (plan.md:146–148). "Repeat the consumer rehearsal with fresh remotes after repinning. Gate B still requires the reviewed upstream fix and the remaining integration work, even though the separate candidate rehearsal now succeeds" (adopter-blocker.md:71–73). | A rehearsal that runs the consumer's pinned openRepoShape at a commit on its main (7f84ca4) into fresh remotes. The October 6 run against draft `91d5685` (adopter-rehearsal.md:4–7) does not count. | **IN PROGRESS by lane 1's rehearsal writer.** "after repinning" depends on line 13. | +| 42 | "Never use the live consumer as `--source` for this reproduction: local mode still pushes an adoption branch to its source clone if execution reaches that step" (adopter-blocker.md:52–54). | The receipt shows `--source` was the fresh isolated clone. Afterwards neither the live repository nor the remote has an `adopt/three-repo-shape` branch (adoption-plan.yaml:23). | **IN PROGRESS by lane 1's rehearsal writer.** #186 first act 3 restates the rule. At 11:06Z neither the shared repository nor the remote has an `adopt/` ref. | +| 43 | "do not patch the pinned submodule or adjust digests to manufacture success" (plan.md:113–114). "never patch `upstream/openRepoShape` in place or weaken verification" (tasks.md:51–52). "pinned standard copies/digests SHALL NOT be edited to make placement pass" (cap-spec:84). #186 first act 1: "`tree_sha256` RECOMPUTED …, never adjusted". | The repin's `tree_sha256` equals an independent recomputation at 7f84ca4, `tests/test_upstream_pin.py` passes in the required CI, and the submodule has no in-place edit. | **IN PROGRESS by lane 1's repin PR writer** (#188, not landed). #186 comment 6035767825 records that lane 3's independent recompute at 7f84ca4 matches `3be52767…`. Lane 3 holds the adversarial review. | +| 44 | "No real repository is created for a test" (plan.md:253). plan.md:107–108. FR-010 (spec.md:62–63). Without approval the migration "SHALL create no real leg repositories" (cap-spec:151–154). #186 rules: "no real leg repository, PR to a real leg, default-branch move or lane rebinding before Gate C". | A rehearsal receipt recording transport restricted to local files and refusing `gh`/`curl` shims (the form of preparation.md:67–70). Read-only lookups of the leg names. | **IN PROGRESS by lane 1's rehearsal writer.** At 11:06Z both leg names return HTTP 404, which means "not visible to the current credentials, not a guarantee of name availability" (preparation.md:53–55). | +| 45 | "Reviewed preliminary inventory, mapping and prerequisite availability from T001–T003 permit disposable provisional rehearsal while writers remain active" (tasks.md:159–161). | A reviewed, refreshed `inventory.json` (T001), together with lines 2–6. | **IN PROGRESS by lane 1's Gate A writer**, as the T001 inventory refresh. The committed inventory was observed at 2026-10-04T21:24:50Z (`observed_at`). | +| 46 | "reviewed follow-up patches" (plan.md:140–141). Implement "and review" the follow-ups "in the rehearsed arrangement" (plan.md:123–125). | A review record for each T006–T010 patch: reviewer, verdict and the commit reviewed. | **NOBODY.** No reviewer is named for T006–T010; lane 3's review covers #188 only. | + +## What closes Gate B + +The Dependencies section in tasks.md:162–165 says, verbatim: + +> T004–T006 precede integration validation; +> T007–T010 may progress within the rehearsed topology after byte accounting. +> T011 closes Gate B. T012 requires Gate A/B and is the real-creation approval +> boundary. + +The plan adds that "Mapping `check` alone does not satisfy this gate" +(plan.md:142) and that Gate B is not passed until the consumer rehearsal is +repeated into fresh local remotes after the upstream resolution +(plan.md:146–148, adopter-blocker.md:71–73). Gate B is recorded as open in +three places on ff6f6a7: inventory.json:513 `"gate_b_complete": false`, +verification.md:25 "Gate B remains open", and adopter-rehearsal.md:101–102 +"Gates A/B/C are not completed by this rehearsal". + +**Counts (46 lines):** + +| Status | Lines | +| --- | ---: | +| EXISTS (3 on ff6f6a7; 1 on 004-migrate-to-triad-reads @ ae70dc556) | 4 | +| DECIDED | 1 | +| IN PROGRESS | 19 | +| NOBODY | 21 | +| BLOCKED | 1 | + +The 19 IN PROGRESS lines are held as follows: lane 1's rehearsal writer 14, +lane 1's Gate A writer 3, lane 1's repin PR writer 2. + +**NOBODY lines (21):** + +- 10: proof that the rehearsal left the source unchanged and recoverable +- 17: the collisions the rehearsal materializes, with a reviewed patch for each +- 18: the shape-aware root workflow bootstrap in the rehearsed assembly +- 19: first-line guidance, `.specify` and paired feature selection verified +- 20: provenance correspondence and cross-leg link repair +- 21: explicit spec/amendment roots, local-root precedence and store selection +- 22: per-workstation protocol/command distribution check +- 25: the assembly entry point and payload-source resolution patches +- 26: one-liners resolving one code pin with no developer checkout +- 27: the 15-row compatibility matrix measured +- 28: names, counts, modes, hooks, receipts and all-or-none refusal unchanged +- 29: explicit roots in fixtures and hygiene tests +- 30: `tests/run.sh -k upstream_pin` passing in the rehearsed code leg +- 31: composed checks refusing absent context instead of skipping +- 32: code-leg CI and root exact-pin integration patches +- 33: every current CI job and platform policy kept +- 34: the composed state passing the required checks and the matrix locally +- 36: the restore/rollback rehearsal of the candidate and installed payload +- 37: work, jobs, claims and WIP pointers surviving with no force or reset +- 40: the follow-up patch/commit inventory +- 46: a review record for each T006–T010 patch + +**BLOCKED line (1):** + +- 35: the hosted-runner part of T010's verification. It waits on somewhere + GitHub-hosted runners can check out the rehearsed commits before Gate C + (inferred). + +## Outside Gate B (for orientation) + +These conditions sit next to Gate B but belong to other gates: + +- **Gate A completion.** "complete Gate A preservation is required before real + source freeze" (tasks.md:161). Gate A is not a precondition of the + rehearsal, but line 36 uses Gate A's preserved artifacts. +- **Gate C.** "approval names the actual source/standard revisions, leg + repositories, visibility and final plan; prerequisites, Gate A/B evidence and + no-name-collision checks are current" (plan.md:161–163). Governance item 1.2 + runs "after Gates A/B" (openspec/changes/migrate-to-triad/tasks.md:11–14). The + leg names and visibility are a confirmed Gate C input (line 1). The frozen + source commit and the final mapping are not yet approved. diff --git a/specs/004-migrate-to-triad/inventory.json b/specs/004-migrate-to-triad/inventory.json index cb4dd823..17e764df 100644 --- a/specs/004-migrate-to-triad/inventory.json +++ b/specs/004-migrate-to-triad/inventory.json @@ -1,8 +1,8 @@ { - "observed_at": "2026-10-04T21:24:50.021151+00:00", + "observed_at": "2026-10-07T10:09:03.632310+00:00", "source_repository": "opensoft/openRepoTools", - "source_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", - "github_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "source_main": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "github_main": "c4864ac5e59db49d01f638a80ed38daf1d788182", "github_main_matches_local": true, "standard_commit": "39d5c986fcfac1a160474bfe91c5f1c37fccc72c", "cleanup_summary": { @@ -70,165 +70,755 @@ "worktrees": [ { "identity": "main", - "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "worktree_name": "main", + "owner": "shared main checkout (cwd of lanes openRepoTools-1/2/3)", + "head": "c4864ac5e59db49d01f638a80ed38daf1d788182", "layout": "root", + "linked": false, "readable_here": true, + "upstream": "origin/main", + "upstream_configured": "origin/main", + "upstream_state": null, + "ahead_of_upstream": 0, + "behind_upstream": 0, + "ahead_of_origin_main": 0, + "behind_origin_main": 0, "dirty_entries": 0, "untracked_entries": 0, + "ignored_entries": 5, + "ignored_files": 75, + "workflow_config_files_preserved": 71, + "submodule_initialized": true, "locked": false, - "prunable": false + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "Source baseline c4864ac (= GitHub main, PR #175's squash). The migration source; freeze it at Gate C." + }, + { + "identity": "feat/lane-worktrees-residue-tests", + "worktree_name": "ort-179-tests", + "owner": "lane openRepoTools-1", + "head": "6c79121ea0288ac495ea5d0cd856083059c631bb", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": "origin/feat/lane-worktrees-residue-tests", + "upstream_state": "[gone]", + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 98, + "behind_origin_main": 2, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "landed-and-preserved", + "disposition_proposal": "Tip 6c79121 is PR #179's merged head (squash 2fb854f); origin branch gone; tip also on GitHub as refs/pull/179/head. No replay." + }, + { + "identity": "fix/install-marker-on-every-file-and-one-install-lock", + "worktree_name": "ort-install-followups", + "owner": "lane openRepoTools-1", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": "origin/main", + "upstream_configured": "origin/main", + "upstream_state": "[behind 4]", + "ahead_of_upstream": 0, + "behind_upstream": 4, + "ahead_of_origin_main": 0, + "behind_origin_main": 4, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "empty-shell", + "disposition_proposal": "Tip 2080f3d is main's PR #168 squash; no commits of its own; never pushed. Nothing to continue." + }, + { + "identity": "chore/openreposhape-pin-7f84ca4", + "worktree_name": "ort-shape-pin", + "owner": "lane openRepoTools-1", + "head": "e43b2432976a22eb3bf8c419c96209399251d375", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 1, + "behind_origin_main": 0, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": true, + "locked": false, + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "Active writer (T005): one commit e43b243 moving gitlink and pin 39d5c98 -> 7f84ca4 (tree_sha256 3be52767...), unpushed at capture, tests running. Continues through its own PR; this bundle holds the only copy outside the tree at capture." + }, + { + "identity": "004-migrate-to-triad-exec", + "worktree_name": "ort-triad-exec", + "owner": "lane openRepoTools-1", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 6, + "behind_origin_main": 13, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "This Gate A evidence tree (T001/T002), branched from ff6f6a7 at 09:58Z; its commits follow the capture." + }, + { + "identity": "004-migrate-to-triad-rehearsal", + "worktree_name": "ort-triad-rehearsal", + "owner": "lane openRepoTools-1", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 6, + "behind_origin_main": 13, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "Active writer (Gate B rehearsal), branched from ff6f6a7 at 10:01Z; no commits at capture." + }, + { + "identity": "fix/wip-init-step7-guarded-writes-and-step8-refusal-words", + "worktree_name": "ort-wip-init-followups", + "owner": "lane openRepoTools-1", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": "origin/main", + "upstream_configured": "origin/main", + "upstream_state": "[behind 4]", + "ahead_of_upstream": 0, + "behind_upstream": 4, + "ahead_of_origin_main": 0, + "behind_origin_main": 4, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "empty-shell", + "disposition_proposal": "Tip 2080f3d is main's PR #168 squash; no commits of its own; never pushed. Nothing to continue." + }, + { + "identity": "004-migrate-to-triad-reads", + "worktree_name": "triad-reads", + "owner": "lane openRepoTools-2", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 6, + "behind_origin_main": 13, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "Active writer of lane openRepoTools-2, branched from ff6f6a7 at 10:03Z; no commits at capture." + }, + { + "identity": "feat/triad-lane-tooling", + "worktree_name": "triad-lane-tooling", + "owner": "lane openRepoTools-3", + "head": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "layout": "lane-worktrees", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 0, + "behind_origin_main": 0, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, + "locked": false, + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "Active writer of lane openRepoTools-3, branched from c4864ac at 10:03Z; no commits at capture." }, { "identity": "001-separate-swap-ctx-handoff", + "worktree_name": "001-separate-swap-ctx-handoff", + "owner": "Brett Heap", "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5", "layout": "legacy-sibling", + "linked": true, "readable_here": true, + "upstream": "origin/001-separate-swap-ctx-handoff", + "upstream_configured": "origin/001-separate-swap-ctx-handoff", + "upstream_state": null, + "ahead_of_upstream": 0, + "behind_upstream": 0, + "ahead_of_origin_main": 27, + "behind_origin_main": 23, "dirty_entries": 0, "untracked_entries": 0, + "ignored_entries": 4, + "ignored_files": 70, + "workflow_config_files_preserved": 70, + "submodule_initialized": true, "locked": false, - "prunable": false + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "Feature 001 at 3c26041 (= origin), clean; 27 ahead / 23 behind main. Continue into paired 001 worktrees (T016)." }, { "identity": "004-migrate-to-triad", - "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2", + "worktree_name": "004-migrate-to-triad", + "owner": "Brett Heap", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", "layout": "legacy-sibling", + "linked": true, "readable_here": true, + "upstream": "origin/004-migrate-to-triad", + "upstream_configured": "origin/004-migrate-to-triad", + "upstream_state": null, + "ahead_of_upstream": 0, + "behind_upstream": 0, + "ahead_of_origin_main": 6, + "behind_origin_main": 13, "dirty_entries": 0, - "untracked_entries": 3, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, "locked": false, - "prunable": false + "prunable": false, + "classification": "retained-work", + "disposition_proposal": "The migration plan at ff6f6a7 (= origin); PR #187 opened 10:03:43Z. Full proposal stays in spec (T017)." }, { "identity": "feat/supervised-context-restart", - "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed", + "worktree_name": "005-supervised-legacy-ctx", + "owner": "Brett Heap", + "head": "f13d32975d7457d662249385d23ee28a7f713c4c", "layout": "legacy-sibling", + "linked": true, "readable_here": true, + "upstream": "origin/feat/supervised-context-restart", + "upstream_configured": "origin/feat/supervised-context-restart", + "upstream_state": null, + "ahead_of_upstream": 0, + "behind_upstream": 0, + "ahead_of_origin_main": 30, + "behind_origin_main": 8, "dirty_entries": 0, "untracked_entries": 0, + "ignored_entries": 3, + "ignored_files": 24, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, "locked": false, - "prunable": false + "prunable": false, + "classification": "landed-and-preserved", + "disposition_proposal": "Tip f13d329 is PR #121's merged head (squash 00971b9); origin branch present; clean. Any paired 005 continuation is the owner's decision." }, { "identity": "feat/claude-current", + "worktree_name": "feat-claude-current", + "owner": "Brett Heap", "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", - "layout": "legacy-sibling", + "layout": "legacy-nested", + "linked": true, "readable_here": true, + "upstream": "origin/feat/claude-current", + "upstream_configured": "origin/feat/claude-current", + "upstream_state": null, + "ahead_of_upstream": 0, + "behind_upstream": 0, + "ahead_of_origin_main": 19, + "behind_origin_main": 11, "dirty_entries": 0, "untracked_entries": 0, + "ignored_entries": 2, + "ignored_files": 18, + "workflow_config_files_preserved": 0, + "submodule_initialized": false, "locked": false, - "prunable": false + "prunable": false, + "classification": "landed-and-preserved", + "disposition_proposal": "Tip 11037f0 is PR #134's merged head (squash daed209); retained checkout is preservation history; no replay." }, { - "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6", - "layout": "legacy-nested", + "identity": "feat/amendment-22-sql-primary", + "worktree_name": "a22-primary", + "owner": "lane openRepoTools-3", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "layout": "harness-nested", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 0, + "behind_origin_main": 4, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": true, + "locked": false, + "prunable": false, + "classification": "empty-shell", + "disposition_proposal": "Tip 2080f3d is main's PR #168 squash; no commits of its own; never pushed." + }, + { + "identity": "feat/lane-end-closeout-rest", + "worktree_name": "closeout-2", + "owner": "lane openRepoTools-3", + "head": "ed3655184d90e1ac21848aa4c3e294327b9561b6", + "layout": "harness-nested", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": "origin/feat/lane-end-closeout", + "upstream_state": "[gone]", + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 38, + "behind_origin_main": 7, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": true, + "locked": false, + "prunable": false, + "classification": "landed-and-preserved", + "disposition_proposal": "Tip ed36551 is an ancestor of PR #175's merged head 5c05ab6 (squash c4864ac); configured upstream gone; on GitHub as part of refs/pull/175/head." + }, + { + "identity": "feat/shell-suite-wall-time", + "worktree_name": "suite-speed", + "owner": "lane openRepoTools-3", + "head": "d2f80512902bf85b5993134a3cef6913d131565a", + "layout": "harness-nested", + "linked": true, + "readable_here": true, + "upstream": null, + "upstream_configured": null, + "upstream_state": null, + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 36, + "behind_origin_main": 4, + "dirty_entries": 0, + "untracked_entries": 0, + "ignored_entries": 0, + "ignored_files": 0, + "workflow_config_files_preserved": 0, + "submodule_initialized": true, + "locked": false, + "prunable": false, + "classification": "landed-and-preserved", + "disposition_proposal": "Tip d2f8051 is PR #169's merged head (squash 500687c); never pushed under this branch name; on GitHub as refs/pull/169/head." + }, + { + "identity": "feat/lane-worktrees-residue", + "worktree_name": "sweep-170", + "owner": "lane openRepoTools-1", + "head": "4ea84c8c8206347cef3cc5a626e79aee9e12b8c3", + "layout": "harness-nested", + "linked": true, "readable_here": true, + "upstream": null, + "upstream_configured": "origin/feat/lane-worktrees-residue", + "upstream_state": "[gone]", + "ahead_of_upstream": null, + "behind_upstream": null, + "ahead_of_origin_main": 81, + "behind_origin_main": 3, "dirty_entries": 0, "untracked_entries": 0, + "ignored_entries": 1, + "ignored_files": 1, + "workflow_config_files_preserved": 0, + "submodule_initialized": true, "locked": false, - "prunable": false + "prunable": false, + "classification": "landed-and-preserved", + "disposition_proposal": "Tip 4ea84c8 is PR #174's merged head (squash 5eb3d5f); origin branch gone; on GitHub as refs/pull/174/head." } ], "local_branches": [ { "identity": "001-separate-swap-ctx-handoff", - "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5" + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5", + "upstream_configured": "origin/001-separate-swap-ctx-handoff", + "upstream_state": null, + "worktree": "001-separate-swap-ctx-handoff" }, { "identity": "004-migrate-to-triad", - "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2" + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "upstream_configured": "origin/004-migrate-to-triad", + "upstream_state": null, + "worktree": "004-migrate-to-triad" + }, + { + "identity": "004-migrate-to-triad-exec", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "upstream_configured": null, + "upstream_state": null, + "worktree": "ort-triad-exec" + }, + { + "identity": "004-migrate-to-triad-reads", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "upstream_configured": null, + "upstream_state": null, + "worktree": "triad-reads" + }, + { + "identity": "004-migrate-to-triad-rehearsal", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "upstream_configured": null, + "upstream_state": null, + "worktree": "ort-triad-rehearsal" + }, + { + "identity": "chore/openreposhape-pin-7f84ca4", + "head": "e43b2432976a22eb3bf8c419c96209399251d375", + "upstream_configured": null, + "upstream_state": null, + "worktree": "ort-shape-pin" + }, + { + "identity": "feat/amendment-22-sql-primary", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "upstream_configured": null, + "upstream_state": null, + "worktree": "a22-primary" }, { "identity": "feat/claude-current", - "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12" + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "upstream_configured": "origin/feat/claude-current", + "upstream_state": null, + "worktree": "feat-claude-current" + }, + { + "identity": "feat/lane-end-closeout-rest", + "head": "ed3655184d90e1ac21848aa4c3e294327b9561b6", + "upstream_configured": "origin/feat/lane-end-closeout", + "upstream_state": "[gone]", + "worktree": "closeout-2" }, { - "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6" + "identity": "feat/lane-worktrees-residue", + "head": "4ea84c8c8206347cef3cc5a626e79aee9e12b8c3", + "upstream_configured": "origin/feat/lane-worktrees-residue", + "upstream_state": "[gone]", + "worktree": "sweep-170" + }, + { + "identity": "feat/lane-worktrees-residue-tests", + "head": "6c79121ea0288ac495ea5d0cd856083059c631bb", + "upstream_configured": "origin/feat/lane-worktrees-residue-tests", + "upstream_state": "[gone]", + "worktree": "ort-179-tests" + }, + { + "identity": "feat/shell-suite-wall-time", + "head": "d2f80512902bf85b5993134a3cef6913d131565a", + "upstream_configured": null, + "upstream_state": null, + "worktree": "suite-speed" }, { "identity": "feat/supervised-context-restart", - "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed" + "head": "f13d32975d7457d662249385d23ee28a7f713c4c", + "upstream_configured": "origin/feat/supervised-context-restart", + "upstream_state": null, + "worktree": "005-supervised-legacy-ctx" + }, + { + "identity": "feat/triad-lane-tooling", + "head": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "upstream_configured": null, + "upstream_state": null, + "worktree": "triad-lane-tooling" + }, + { + "identity": "fix/install-marker-on-every-file-and-one-install-lock", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "upstream_configured": "origin/main", + "upstream_state": "[behind 4]", + "worktree": "ort-install-followups" + }, + { + "identity": "fix/wip-init-step7-guarded-writes-and-step8-refusal-words", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "upstream_configured": "origin/main", + "upstream_state": "[behind 4]", + "worktree": "ort-wip-init-followups" }, { "identity": "main", - "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f" + "head": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "upstream_configured": "origin/main", + "upstream_state": null, + "worktree": "main" + }, + { + "identity": "review/20261004-review/branch-004-migrate-to-triad-efc637", + "head": "5455805d623b6d3e2943606745c4ac812dc40be5", + "upstream_configured": null, + "upstream_state": null, + "worktree": null, + "classification": "retained-work", + "disposition_proposal": "October 4 review snapshot of 004; ancestor of ff6f6a7; also on origin." + }, + { + "identity": "review/20261004-review/branch-feat-crash-consistent-lane-worktree-recovery-897cfc", + "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6", + "upstream_configured": null, + "upstream_state": null, + "worktree": null, + "classification": "landed-and-preserved", + "disposition_proposal": "Ancestor of PR #97's merged head 8c5958f (squash b1015f4); also on origin." } ], "remote_only_branches": [ { "identity": "chore/preserve-local-planning-20261003", "head": "135c18b258d02136ed834e5a446e552db385d50c", - "currency": "local remote-tracking observation; not fetched during refresh" + "on_origin": true, + "classification": "remote-only-ref", + "disposition_proposal": "Preservation history of the October 3 local planning drafts; no checkout.", + "currency": "origin heads read with git ls-remote at the refresh; matches the local remote-tracking ref" }, { "identity": "takeover/ort-a9-dirty-snapshot-20260913", "head": "607aee7551a5a7db7e57e294aba193fbc8a8a266", - "currency": "local remote-tracking observation; not fetched during refresh" + "on_origin": true, + "classification": "remote-only-ref", + "disposition_proposal": "Preservation snapshot of September 13; no checkout.", + "currency": "origin heads read with git ls-remote at the refresh; matches the local remote-tracking ref" + }, + { + "identity": "fix/install-by-rename-167", + "head": "1905b7984c1f9877569c20971ffcf9ebd08b3e1c", + "on_origin": true, + "classification": "remote-only-ref", + "disposition_proposal": "PR #172's merged head (squash 3660224); no local branch.", + "currency": "origin heads read with git ls-remote at the refresh; matches the local remote-tracking ref" } ], - "open_prs": [ + "local_only_refs": [ { - "number": 121, - "title": "Keep supervised manual ctx as legacy compatibility and refuse managed lanes", - "headRefName": "feat/supervised-context-restart", - "headRefOid": "6c5b74176e9dbf7f9aad5a4ff8ec18ef0cbbb136", - "isDraft": false, - "url": "https://github.com/opensoft/openRepoTools/pull/121", - "state": "open", - "merged": false, - "updated_at": "2026-10-04T21:24:31Z" + "ref": "refs/lanes/a9-move", + "head": "2108ce3ab6f767d993522f96c5e3af58659577b3", + "on_origin": false, + "classification": "landed-and-preserved", + "note": "Ancestor of main; not on origin." }, { - "number": 97, - "title": "Crash-consistent lane worktree recovery: a lane now says WHERE its session stopped \u2014 RUNNING \u2192 SWAPPING \u2192 SWAPPED with a generation/operation fence, a machine-readable worktree inventory taken at every handoff, and a resume reconciliation that reports and resets nothing", - "headRefName": "feat/crash-consistent-lane-worktree-recovery", - "headRefOid": "eada5fff495452cf5da47e52d9550fa4b40a4c96", + "ref": "refs/remotes/pr/24", + "head": "e3d57ddf4f4e77761cd250faf21664a637c3f298", + "on_origin": false, + "classification": "landed-and-preserved", + "note": "Stale remote-tracking ref (no 'pr' remote configured); ancestor of main (PR #24 merged d4b5710)." + }, + { + "ref": "refs/remotes/pr/26", + "head": "dae38be3b28cde7086862738bd8ad56fce406efe", + "on_origin": false, + "classification": "landed-and-preserved", + "note": "Stale remote-tracking ref (no 'pr' remote configured); ancestor of PR #26's merged head (squash 63a74af)." + } + ], + "open_prs": [ + { + "number": 187, + "title": "Triad migration planning (feature 004-migrate-to-triad): proposal, plan, tasks, adoption mapping and the October rehearsal receipts", + "headRefName": "004-migrate-to-triad", + "headRefOid": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", "isDraft": false, - "url": "https://github.com/opensoft/openRepoTools/pull/97", + "url": "https://github.com/opensoft/openRepoTools/pull/187", "state": "open", "merged": false, - "updated_at": "2026-10-04T21:05:20Z" + "created_at": "2026-10-07T10:03:43Z" } ], "merged_since_previous_snapshot": [ { - "number": 61, + "number": 97, + "state": "MERGED", + "merged_at": "2026-10-04T23:36:21Z", + "merge_commit": "b1015f4672f9c107d939803c39846f8dbd3d78f3", + "head_ref": "feat/crash-consistent-lane-worktree-recovery", + "head_oid": "8c5958fcb366b0f749e878f13f10877afce85637", + "disposition": "Merged; recovery branch and checkout gone; included in source main." + }, + { + "number": 164, + "state": "MERGED", + "merged_at": "2026-10-05T19:36:07Z", + "merge_commit": "fea9a2904ce0224ca6a77dff02319bd9656a8fee", + "head_ref": "feat/amendment-14-derived-index", + "head_oid": "20e23a4c680d17f60f61f53dac16770b01c5225d", + "disposition": "Merged; included in source main." + }, + { + "number": 121, "state": "MERGED", - "merged_at": "2026-10-03T17:55:42Z", - "merge_commit": "14641fd67cee2985c215fc820219c9906935bdf3", - "disposition": "Included in current source main; no separate feature replay." + "merged_at": "2026-10-06T09:38:31Z", + "merge_commit": "00971b929f586179828481e7cb34db181f386937", + "head_ref": "feat/supervised-context-restart", + "head_oid": "f13d32975d7457d662249385d23ee28a7f713c4c", + "disposition": "Merged; the 005 checkout at the merged head is preservation history." }, { - "number": 146, + "number": 171, "state": "MERGED", - "merged_at": "2026-10-03T22:07:15Z", - "merge_commit": "82ecebee13edaa915b68550170faffdf761754d5", - "disposition": "Included in current source main; no separate feature replay." + "merged_at": "2026-10-06T15:02:17Z", + "merge_commit": "f5444c5e1f3c6c9ed43aeafcc000b0e78b10497a", + "head_ref": "feat/amendment-14-worktrees-index", + "head_oid": "9b2ec40d465d6ec0a911cb2cbcd836bdff92bb9c", + "disposition": "Merged; included in source main." }, { - "number": 134, + "number": 172, "state": "MERGED", - "merged_at": "2026-10-04T16:52:38Z", - "merge_commit": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", - "disposition": "Included in refreshed source main; retained checkout is preservation only, no separate replay." + "merged_at": "2026-10-06T17:35:06Z", + "merge_commit": "3660224cf32e5217f227cf7a740efec462da5151", + "head_ref": "fix/install-by-rename-167", + "head_oid": "1905b7984c1f9877569c20971ffcf9ebd08b3e1c", + "disposition": "Merged; head survives as remote-only fix/install-by-rename-167." + }, + { + "number": 168, + "state": "MERGED", + "merged_at": "2026-10-06T18:45:29Z", + "merge_commit": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "head_ref": "feat/lane-worktrees-sweep", + "head_oid": "df0d6916f59ac2d3c6f6672b9441a1c73b0a0446", + "disposition": "Merged; included in source main." + }, + { + "number": 169, + "state": "MERGED", + "merged_at": "2026-10-06T20:43:26Z", + "merge_commit": "500687c4b746d038ba14367ae8fca120ab0fbf97", + "head_ref": "feat/lane-worktrees-report", + "head_oid": "d2f80512902bf85b5993134a3cef6913d131565a", + "disposition": "Merged; head kept in lane 3's suite-speed tree." + }, + { + "number": 174, + "state": "MERGED", + "merged_at": "2026-10-07T01:19:18Z", + "merge_commit": "5eb3d5f816f8ef81bda44ee8875bf62c56d95d6a", + "head_ref": "feat/lane-worktrees-residue", + "head_oid": "4ea84c8c8206347cef3cc5a626e79aee9e12b8c3", + "disposition": "Merged; head kept in lane 1's sweep-170 tree." + }, + { + "number": 179, + "state": "MERGED", + "merged_at": "2026-10-07T02:08:55Z", + "merge_commit": "2fb854f12855079874f970eaee2cbee87bd97200", + "head_ref": "feat/lane-worktrees-residue-tests", + "head_oid": "6c79121ea0288ac495ea5d0cd856083059c631bb", + "disposition": "Merged; head kept in lane 1's ort-179-tests tree." + }, + { + "number": 175, + "state": "MERGED", + "merged_at": "2026-10-07T04:26:10Z", + "merge_commit": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "head_ref": "feat/lane-end-closeout", + "head_oid": "5c05ab6272749df5a11ad68835aa3b737b6a4cdf", + "disposition": "Merged as the source commit c4864ac; lane 3's closeout-2 tip is an ancestor of its head." } ], "estate_status": { - "command": "status --fetch openRepoTools", + "command": "status openRepoTools", + "fetch": false, + "observed_at": "2026-10-07T10:09:08Z", "result": "refused-not-an-estate", - "note": "No project.yaml/family.yaml estate root yet; no fetch performed by this refusal. Local refs and read-only GitHub main/PR APIs were checked instead. Do not run resume to silence it." + "exit": 2, + "note": "Read-only and without --fetch: \"REFUSED: no estate named 'openRepoTools' under your projects directory.\" No project.yaml/family.yaml estate root yet. resume was not run to silence it; local refs, git ls-remote and read-only GitHub PR queries were used instead." }, "limitations": [ - "Snapshot only; refresh before baseline freeze and cutover.", - "Physical paths, credentials, transcript bodies and WIP data are omitted.", - "Feature 001 is committed and clean at observation; preserve its current full branch delta, restored rollover/workspace packets and October 4 launcher contracts. Clean status is not a backup/restore receipt.", - "Removed worktrees are cleanup history, not instructions to recreate them; verify retained backup/branch receipts before final cutover.", - "Remote-only preservation refs are local observations, not active worktrees or proof of fresh remote currency.", - "Raw preservation backups belong host-locally or in the designated private WIP repository; public records hold identities/digests only.", - "Inventory captures this planning branch before the refresh commit; its final HEAD is recorded by git.", - "#97/#121 have active writers; capture local and remote heads independently and recapture at cutover. Prior dirty snapshots remain historical evidence.", - "Real conversion waits for both PR landings, upstream adopter resolution, refreshed Gates A/B and explicit Gate C approval." + "Snapshot of a moving estate, not a writer freeze: five worktrees appeared 09:57Z-10:03Z for this migration's writers, PR #187 opened 10:03:43Z (before capture) and PR #188 10:10:43Z (after). Refresh again at the owner-coordinated freeze.", + "Worktree and branch counts are as of the stamp in refreshed.observed_at; capture stability is proven only for 10:05:59Z-10:06:08Z.", + "Physical paths, credentials, transcript bodies, WIP data and backup contents are omitted; worktree_name and layout identify trees, and owner attributes them by path.", + "Classifications and disposition_proposal are proposals; owner decisions for Brett Heap's and lanes 2/3's objects remain pending (private receipt dispositions.tsv). Landed-and-preserved trees need no replay; empty shells hold no commits of their own.", + "Installed files were captured for the host paths in installed.tsv only; py-bench and other profiles/workstations are not in this capture.", + "Real conversion waits for refreshed Gates A/B and explicit Gate C approval; gate_a_complete and gate_b_complete stay false." ], "previous_refresh_snapshot": { "observed_at": "2026-10-04T16:37:26.292668+00:00", @@ -319,19 +909,32 @@ ] }, "latest_refresh": { - "previous_observed_at": "2026-10-04T17:40:54.465251+00:00", + "previous_observed_at": "2026-10-04T21:24:50.021151+00:00", "previous_worktrees": 6, - "current_worktrees": 6, - "current_local_branches": 6, - "added_worktrees": [], - "removed_worktrees": [], - "source_main_changed": false, + "current_worktrees": 17, + "current_local_branches": 19, + "added_worktrees": [ + "004-migrate-to-triad-exec", + "004-migrate-to-triad-reads", + "004-migrate-to-triad-rehearsal", + "chore/openreposhape-pin-7f84ca4", + "feat/amendment-22-sql-primary", + "feat/lane-end-closeout-rest", + "feat/lane-worktrees-residue", + "feat/lane-worktrees-residue-tests", + "feat/shell-suite-wall-time", + "feat/triad-lane-tooling", + "fix/install-marker-on-every-file-and-one-install-lock", + "fix/wip-init-step7-guarded-writes-and-step8-refusal-words" + ], + "removed_worktrees": [ + "feat/crash-consistent-lane-worktree-recovery" + ], + "source_main_changed": true, "protocol": "Triad Feature Amendments adopted manually October 4; automated delivery remains unqualified.", - "concurrent_work": "Owners continue #97/#121; local heads and remote PR heads can differ. Capture is provisional, not a writer freeze.", - "real_conversion_waits_for_prs": [ - 97, - 121 - ] + "concurrent_work": "Migration writers active at capture: lane 1 pin bump (e43b243, unpushed at capture, later PR #188), lane 1 Gate B tree, lane 2 triad-reads, lane 3 triad-lane-tooling; Brett Heap's 004 branch has PR #187. All trees clean at capture.", + "real_conversion_waits_for_prs": [], + "note": "#97 and #121 both merged (2026-10-04T23:36:21Z, 2026-10-06T09:38:31Z); real conversion now waits on Gates A/B and Gate C, not on PR landings." }, "protocol_review": { "adopted_on": "2026-10-04", @@ -513,5 +1116,534 @@ "gate_b_complete": false, "local_adoption_exit": 2, "reproduction": "specs/004-migrate-to-triad/adopter-blocker.md" + }, + "superseded_snapshot_2026_10_04": { + "observed_at": "2026-10-04T21:24:50.021151+00:00", + "source_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "github_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "github_main_matches_local": true, + "worktrees": [ + { + "identity": "main", + "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "layout": "root", + "readable_here": true, + "dirty_entries": 0, + "untracked_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "001-separate-swap-ctx-handoff", + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "untracked_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "004-migrate-to-triad", + "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "untracked_entries": 3, + "locked": false, + "prunable": false + }, + { + "identity": "feat/supervised-context-restart", + "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "untracked_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "untracked_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6", + "layout": "legacy-nested", + "readable_here": true, + "dirty_entries": 0, + "untracked_entries": 0, + "locked": false, + "prunable": false + } + ], + "local_branches": [ + { + "identity": "001-separate-swap-ctx-handoff", + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5" + }, + { + "identity": "004-migrate-to-triad", + "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2" + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12" + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6" + }, + { + "identity": "feat/supervised-context-restart", + "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed" + }, + { + "identity": "main", + "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f" + } + ], + "remote_only_branches": [ + { + "identity": "chore/preserve-local-planning-20261003", + "head": "135c18b258d02136ed834e5a446e552db385d50c", + "currency": "local remote-tracking observation; not fetched during refresh" + }, + { + "identity": "takeover/ort-a9-dirty-snapshot-20260913", + "head": "607aee7551a5a7db7e57e294aba193fbc8a8a266", + "currency": "local remote-tracking observation; not fetched during refresh" + } + ], + "open_prs": [ + { + "number": 121, + "title": "Keep supervised manual ctx as legacy compatibility and refuse managed lanes", + "headRefName": "feat/supervised-context-restart", + "headRefOid": "6c5b74176e9dbf7f9aad5a4ff8ec18ef0cbbb136", + "isDraft": false, + "url": "https://github.com/opensoft/openRepoTools/pull/121", + "state": "open", + "merged": false, + "updated_at": "2026-10-04T21:24:31Z" + }, + { + "number": 97, + "title": "Crash-consistent lane worktree recovery: a lane now says WHERE its session stopped \u2014 RUNNING \u2192 SWAPPING \u2192 SWAPPED with a generation/operation fence, a machine-readable worktree inventory taken at every handoff, and a resume reconciliation that reports and resets nothing", + "headRefName": "feat/crash-consistent-lane-worktree-recovery", + "headRefOid": "eada5fff495452cf5da47e52d9550fa4b40a4c96", + "isDraft": false, + "url": "https://github.com/opensoft/openRepoTools/pull/97", + "state": "open", + "merged": false, + "updated_at": "2026-10-04T21:05:20Z" + } + ], + "merged_since_previous_snapshot": [ + { + "number": 61, + "state": "MERGED", + "merged_at": "2026-10-03T17:55:42Z", + "merge_commit": "14641fd67cee2985c215fc820219c9906935bdf3", + "disposition": "Included in current source main; no separate feature replay." + }, + { + "number": 146, + "state": "MERGED", + "merged_at": "2026-10-03T22:07:15Z", + "merge_commit": "82ecebee13edaa915b68550170faffdf761754d5", + "disposition": "Included in current source main; no separate feature replay." + }, + { + "number": 134, + "state": "MERGED", + "merged_at": "2026-10-04T16:52:38Z", + "merge_commit": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "disposition": "Included in refreshed source main; retained checkout is preservation only, no separate replay." + } + ], + "estate_status": { + "command": "status --fetch openRepoTools", + "result": "refused-not-an-estate", + "note": "No project.yaml/family.yaml estate root yet; no fetch performed by this refusal. Local refs and read-only GitHub main/PR APIs were checked instead. Do not run resume to silence it." + }, + "limitations": [ + "Snapshot only; refresh before baseline freeze and cutover.", + "Physical paths, credentials, transcript bodies and WIP data are omitted.", + "Feature 001 is committed and clean at observation; preserve its current full branch delta, restored rollover/workspace packets and October 4 launcher contracts. Clean status is not a backup/restore receipt.", + "Removed worktrees are cleanup history, not instructions to recreate them; verify retained backup/branch receipts before final cutover.", + "Remote-only preservation refs are local observations, not active worktrees or proof of fresh remote currency.", + "Raw preservation backups belong host-locally or in the designated private WIP repository; public records hold identities/digests only.", + "Inventory captures this planning branch before the refresh commit; its final HEAD is recorded by git.", + "#97/#121 have active writers; capture local and remote heads independently and recapture at cutover. Prior dirty snapshots remain historical evidence.", + "Real conversion waits for both PR landings, upstream adopter resolution, refreshed Gates A/B and explicit Gate C approval." + ] + }, + "refreshed": { + "observed_at": "2026-10-07T10:09:03.632310+00:00", + "capture_window": "2026-10-07T10:05:59Z/2026-10-07T10:06:08Z", + "source_commit": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "inventory_branch": "004-migrate-to-triad-exec", + "inventory_base": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "tasks": [ + "T001", + "T002" + ], + "tracking_issue": "opensoft/openRepoTools#186", + "worktree_entries_at_stamp": 17, + "worktree_count_note": "As of the stamp: main plus 16 linked. The brief expected 12; five were created 09:57Z-10:03Z by this migration's writers (ort-shape-pin, ort-triad-exec, ort-triad-rehearsal under lane 1; triad-reads under lane 2; triad-lane-tooling under lane 3). The count was 17 again at 11:05Z with the same trees.", + "owners_by_path": { + "Brett Heap": 4, + "lane openRepoTools-1": 7, + "lane openRepoTools-2": 1, + "lane openRepoTools-3": 4, + "shared main checkout": 1 + }, + "classification_counts": { + "retained-work": 8, + "landed-and-preserved": 6, + "empty-shell": 3 + }, + "local_branches_at_stamp": 19, + "refs_at_stamp": 33, + "origin_heads": 10, + "origin_tags": 0, + "open_prs_at_stamp": [ + 187 + ], + "merged_since_2026_10_03": [ + { + "number": 119, + "state": "MERGED", + "merged_at": "2026-10-03T00:53:08Z", + "merge_commit": "92bd21fd7dfd91a370f143dc8b89f351ad637461", + "head_ref": "chore/macos-landing-gate-and-cycle-rules", + "head_oid": "a0671ece71dbd78808fb3504e0a5a8b8b215d4c5" + }, + { + "number": 103, + "state": "MERGED", + "merged_at": "2026-10-03T02:08:44Z", + "merge_commit": "a44a4edf3643648f7c573a5dc7f5832df60cbc61", + "head_ref": "feat/install-receipt", + "head_oid": "bade19ba459d2a0d60cc69ea626f007989dff56d" + }, + { + "number": 83, + "state": "MERGED", + "merged_at": "2026-10-03T02:46:00Z", + "merge_commit": "6faed35f418c628f87b33a3e6a5ae4fa1cdd9dfc", + "head_ref": "feat/amendment-18-one-binding", + "head_oid": "400d559f403fae02aad61b1d95bcd692de2cf633" + }, + { + "number": 139, + "state": "MERGED", + "merged_at": "2026-10-03T03:16:12Z", + "merge_commit": "795016ee074ea442030766f0fa17443368b1d757", + "head_ref": "fix/wip-init-refuses-unreviewed-history-ahead-of-main", + "head_oid": "c587c4feded45ace3613a86eff17a807ee37a294" + }, + { + "number": 93, + "state": "MERGED", + "merged_at": "2026-10-03T06:30:34Z", + "merge_commit": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "head_ref": "feat/amendment-19-closed-lanes-leave-the-listing", + "head_oid": "8fc5e1a7f89d82d479e654dce3d969ad304e4e6b" + }, + { + "number": 61, + "state": "MERGED", + "merged_at": "2026-10-03T17:55:42Z", + "merge_commit": "14641fd67cee2985c215fc820219c9906935bdf3", + "head_ref": "fix/claim-takeover-and-retire-fork", + "head_oid": "3de40b1865d31d3bb96a52e3822c1386c9e52634" + }, + { + "number": 146, + "state": "MERGED", + "merged_at": "2026-10-03T22:07:15Z", + "merge_commit": "82ecebee13edaa915b68550170faffdf761754d5", + "head_ref": "fix/107-pty-driver-bound-and-lane-per-call-cost", + "head_oid": "da0e5bb257b3b2b60a57ca544b7c75528c97f2a5" + }, + { + "number": 134, + "state": "MERGED", + "merged_at": "2026-10-04T16:52:38Z", + "merge_commit": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "head_ref": "feat/claude-current", + "head_oid": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12" + }, + { + "number": 97, + "state": "MERGED", + "merged_at": "2026-10-04T23:36:21Z", + "merge_commit": "b1015f4672f9c107d939803c39846f8dbd3d78f3", + "head_ref": "feat/crash-consistent-lane-worktree-recovery", + "head_oid": "8c5958fcb366b0f749e878f13f10877afce85637", + "disposition": "Merged; recovery branch and checkout gone; included in source main." + }, + { + "number": 164, + "state": "MERGED", + "merged_at": "2026-10-05T19:36:07Z", + "merge_commit": "fea9a2904ce0224ca6a77dff02319bd9656a8fee", + "head_ref": "feat/amendment-14-derived-index", + "head_oid": "20e23a4c680d17f60f61f53dac16770b01c5225d", + "disposition": "Merged; included in source main." + }, + { + "number": 121, + "state": "MERGED", + "merged_at": "2026-10-06T09:38:31Z", + "merge_commit": "00971b929f586179828481e7cb34db181f386937", + "head_ref": "feat/supervised-context-restart", + "head_oid": "f13d32975d7457d662249385d23ee28a7f713c4c", + "disposition": "Merged; the 005 checkout at the merged head is preservation history." + }, + { + "number": 171, + "state": "MERGED", + "merged_at": "2026-10-06T15:02:17Z", + "merge_commit": "f5444c5e1f3c6c9ed43aeafcc000b0e78b10497a", + "head_ref": "feat/amendment-14-worktrees-index", + "head_oid": "9b2ec40d465d6ec0a911cb2cbcd836bdff92bb9c", + "disposition": "Merged; included in source main." + }, + { + "number": 172, + "state": "MERGED", + "merged_at": "2026-10-06T17:35:06Z", + "merge_commit": "3660224cf32e5217f227cf7a740efec462da5151", + "head_ref": "fix/install-by-rename-167", + "head_oid": "1905b7984c1f9877569c20971ffcf9ebd08b3e1c", + "disposition": "Merged; head survives as remote-only fix/install-by-rename-167." + }, + { + "number": 168, + "state": "MERGED", + "merged_at": "2026-10-06T18:45:29Z", + "merge_commit": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "head_ref": "feat/lane-worktrees-sweep", + "head_oid": "df0d6916f59ac2d3c6f6672b9441a1c73b0a0446", + "disposition": "Merged; included in source main." + }, + { + "number": 169, + "state": "MERGED", + "merged_at": "2026-10-06T20:43:26Z", + "merge_commit": "500687c4b746d038ba14367ae8fca120ab0fbf97", + "head_ref": "feat/lane-worktrees-report", + "head_oid": "d2f80512902bf85b5993134a3cef6913d131565a", + "disposition": "Merged; head kept in lane 3's suite-speed tree." + }, + { + "number": 174, + "state": "MERGED", + "merged_at": "2026-10-07T01:19:18Z", + "merge_commit": "5eb3d5f816f8ef81bda44ee8875bf62c56d95d6a", + "head_ref": "feat/lane-worktrees-residue", + "head_oid": "4ea84c8c8206347cef3cc5a626e79aee9e12b8c3", + "disposition": "Merged; head kept in lane 1's sweep-170 tree." + }, + { + "number": 179, + "state": "MERGED", + "merged_at": "2026-10-07T02:08:55Z", + "merge_commit": "2fb854f12855079874f970eaee2cbee87bd97200", + "head_ref": "feat/lane-worktrees-residue-tests", + "head_oid": "6c79121ea0288ac495ea5d0cd856083059c631bb", + "disposition": "Merged; head kept in lane 1's ort-179-tests tree." + }, + { + "number": 175, + "state": "MERGED", + "merged_at": "2026-10-07T04:26:10Z", + "merge_commit": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "head_ref": "feat/lane-end-closeout", + "head_oid": "5c05ab6272749df5a11ad68835aa3b737b6a4cdf", + "disposition": "Merged as the source commit c4864ac; lane 3's closeout-2 tip is an ancestor of its head." + } + ], + "register_facts_from_coordinator": { + "as_of": "2026-10-07T09:5xZ", + "open_prs": 0, + "lanes": "openRepoTools-1/2/3 idle, no writers except this migration's", + "installed_main_on_Eagle": "c4864ac5e59db49d01f638a80ed38daf1d788182" + }, + "submodule": { + "path": "upstream/openRepoShape", + "gitlink_at_source": "39d5c986fcfac1a160474bfe91c5f1c37fccc72c", + "main_checkout_initialized": true, + "pinned_tree_sha256": "a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02", + "pinned_digest_matches_contract": true, + "target_commit": "7f84ca42ca86a8902928345109d2bf6bad87bd91", + "target_tree_sha256": "3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8", + "target_on_openreposhape_main": true, + "pin_bump_in_flight": "chore/openreposhape-pin-7f84ca4 at e43b2432976a22eb3bf8c419c96209399251d375 records the same target_tree_sha256; unpushed at capture, PR #188 after it." + }, + "installed": { + "receipt_rows": 29, + "install_stamp": "2026-10-07T04:26:26Z", + "present": 29, + "missing": 0, + "sha256_matches_receipt": 29 + }, + "amendment_path_observations": [ + { + "identity": "main", + "head": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/lane-worktrees-residue-tests", + "head": "6c79121ea0288ac495ea5d0cd856083059c631bb", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "fix/install-marker-on-every-file-and-one-install-lock", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "chore/openreposhape-pin-7f84ca4", + "head": "e43b2432976a22eb3bf8c419c96209399251d375", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "004-migrate-to-triad-exec", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "004-migrate-to-triad-rehearsal", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "fix/wip-init-step7-guarded-writes-and-step8-refusal-words", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "004-migrate-to-triad-reads", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/triad-lane-tooling", + "head": "c4864ac5e59db49d01f638a80ed38daf1d788182", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "001-separate-swap-ctx-handoff", + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "004-migrate-to-triad", + "head": "ff6f6a7c7b7921ca1e0b0234e898900f98532366", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/supervised-context-restart", + "head": "f13d32975d7457d662249385d23ee28a7f713c4c", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/amendment-22-sql-primary", + "head": "2080f3d83520bd1ea5632e754026f8ba3df4eb1f", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/lane-end-closeout-rest", + "head": "ed3655184d90e1ac21848aa4c3e294327b9561b6", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/shell-suite-wall-time", + "head": "d2f80512902bf85b5993134a3cef6913d131565a", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/lane-worktrees-residue", + "head": "4ea84c8c8206347cef3cc5a626e79aee9e12b8c3", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + } + ], + "preservation": { + "record": "specs/004-migrate-to-triad/preservation-2026-10-07.md", + "backup_id": "prep-20261007T100559Z", + "backup_root_pattern": "/prep-/ (host-local on Eagle, beside prep-20261004T211123Z)", + "refs_bundled": 33, + "bundle_heads": 50, + "source_bundle_sha256": "60db3acd0753b3efde1ee6ae48d2c463e10fee57dbadcf8af543f12332c39c03", + "dependency_bundle_sha256": "aa5a6eca83897516331466c2904ec786be3cf423cac3d6647aad5760bfb8d7cb", + "manifest_files": 414, + "manifest_sha256": "2a46dff9c00b0eba300bd0ad49a5cf42578f741b1e4a3cca2568d9c2784e88ed", + "reachable_objects": 2902, + "reachable_object_ids_sha256": "338cb7bdd397076eeced1de0852eeb1510b4f97e02fb3f62de434531c7be327d", + "capture_stable": true, + "captured_worktrees": 17, + "all_worktrees_clean": true, + "workflow_config_files_preserved": 141, + "secret_like_paths_skipped": 0, + "all_ref_restore_verified": true, + "dependency_commits_restore_verified": true, + "worktree_snapshot_restores_verified": 17, + "restore_checks": { + "pass": 97, + "fail": 0 + }, + "private_receipt": "brett-wip migration/openRepoTools/prep-20261007T100559Z/", + "private_receipt_commit": "f0ea2df7d5c6d95c26413b68843451e953a50018" + }, + "previous_private_backup": { + "backup_id": "prep-20261004T211123Z", + "present": true, + "top_level_entries": 25, + "size": "198M", + "git_filter_repo_wheel": "git_filter_repo-2.47.0-py3-none-any.whl", + "git_filter_repo_version_output": "a40bce548d2c", + "note": "Recorded read-only: listing, sizes and one --version print with bytecode writes disabled; no bundle opened; nothing modified." + }, + "gate_a_complete": false, + "gate_b_complete": false, + "gate_a_open_items": [ + "Owner dispositions for every retained object (proposals in the private receipt).", + "A final capture at the owner-coordinated freeze, after the migration's own writers stop.", + "Installed-file receipts for py-bench and any other profile or workstation." + ] } } diff --git a/specs/004-migrate-to-triad/preservation-2026-10-07.md b/specs/004-migrate-to-triad/preservation-2026-10-07.md new file mode 100644 index 00000000..9e12ea49 --- /dev/null +++ b/specs/004-migrate-to-triad/preservation-2026-10-07.md @@ -0,0 +1,111 @@ +# Gate A refresh: inventory and preservation, October 7 + +**Observation:** 2026-10-07. Inventory stamp 10:09:03Z; capture 10:05:59Z–10:06:08Z. +This is evidence for [T001–T002](tasks.md) on tracking issue opensoft/openRepoTools#186; +it does not complete them, and Gate A stays open. The +[October 4 receipt](preparation.md) remains historical evidence; the refreshed +[inventory](inventory.json) keeps the October 3 cleanup and the October 4 snapshot as history. + +## Breakpoint + +The coordinator's register facts at 09:5xZ: zero open PRs; lanes openRepoTools-1/2/3 idle with +no writers except this migration's; main `c4864ac5e59db49d01f638a80ed38daf1d788182` installed on +Eagle. This capture is a snapshot of that breakpoint while the migration's own writers were +starting, not an owner-coordinated freeze. Between 09:57Z and 10:03Z the migration's writers +added five worktrees (lane 1's pin, evidence and rehearsal trees; one tree each under lanes 2 +and 3), and PR #187 (`004-migrate-to-triad` at `ff6f6a7`) opened at 10:03:43Z. Every worktree's +HEAD and `status --porcelain --ignored`, the worktree list and the ref listing were identical +before and after the capture, and refs were unchanged across bundle creation. After the +capture, the pin commit reached origin and PR #188 opened at 10:10:43Z. + +## Inventory (T001) + +Source main `c4864ac5e59db49d01f638a80ed38daf1d788182` equals GitHub main (PR #175's squash). +Seventeen worktrees as of the stamp: main plus 16 linked; the brief's expectation of 12 predates +the five migration trees. 19 local branches, 33 refs under `refs/`; origin has 10 heads and no +tags. No worktree is locked, prunable or detached. Eighteen PRs merged from October 3 to the +stamp; one PR (#187) was open at the stamp. The submodule gitlink is +`39d5c986fcfac1a160474bfe91c5f1c37fccc72c`, initialized in the main checkout. + +Classes: 8 retained work (the source baseline, feature 001, the 004 plan and five migration +writer trees), 6 landed and preserved (trees and refs at the heads of merged PRs #121, #134, +#169, #174, #175 and #179), 3 empty shells (at main's #168 squash, no commits of their own). +Remote-only refs: `chore/preserve-local-planning-20261003`, `takeover/ort-a9-dirty-snapshot-20260913` +and `fix/install-by-rename-167` (PR #172's head). Local-only refs: `refs/lanes/a9-move` and two +stale `refs/remotes/pr/*`, all of merged history. Dispositions are proposals; owner decisions +are pending in the private receipt. + +`status openRepoTools` (read-only, no fetch) still refuses: "no estate named 'openRepoTools' +under your projects directory", exit 2. `resume` was not run. + +## Preservation evidence (T002) + +Private backup ID: `prep-20261007T100559Z`, host-local on Eagle under the private prep +directory (`.openrepotools-private-prep/prep-/`) beside `prep-20261004T211123Z`. +File lists, ref listings, manifests and logs are in the private WIP repository's receipt. +No backup contents are published here. + +- Source bundle (`git bundle create --all`): all 33 refs, `HEAD` and 16 per-worktree + `HEAD`s; every ref present with the same SHA. SHA256: + `60db3acd0753b3efde1ee6ae48d2c463e10fee57dbadcf8af543f12332c39c03`. +- Dependency bundle: the pinned standard `39d5c986fcfac1a160474bfe91c5f1c37fccc72c` and the + migration's target `7f84ca42ca86a8902928345109d2bf6bad87bd91` (current openRepoShape main), + from a fresh scratch clone. SHA256: + `aa5a6eca83897516331466c2904ec786be3cf423cac3d6647aad5760bfb8d7cb`. The standard's own + `tree_digest` gives `a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02` + for the pin (matching the contract) and + `3be52767e727d924dd05f9e78b18eb70f1682fe48614fab519f85331eeff5fa8` for the target. +- Manifest: 414 files, `sha256sum -c` passes; manifest SHA256 + `2a46dff9c00b0eba300bd0ad49a5cf42578f741b1e4a3cca2568d9c2784e88ed`. +- Worktrees: for all 17, HEAD, porcelain status with ignored entries, index entries, and full + untracked and ignored lists. 141 ignored workflow-configuration entries were copied (main 71, + feature 001 70); caches were listed but not copied; no path had a secret-like name. + Repository-local config and excludes were preserved separately. +- Installed files: 29 receipt rows (install stamp 2026-10-07T04:26:26Z); 29 present, 0 missing, + 29 copies verified, 29 SHA256s match the install receipt. + +| Worktree | Owner | Branch | HEAD | Dirty | Untracked | Ignored | Class | +| --- | --- | --- | --- | ---: | ---: | ---: | --- | +| main | shared main checkout | `main` | `c4864ac5e59db49d01f638a80ed38daf1d788182` | 0 | 0 | 5 | retained-work | +| ort-179-tests | lane openRepoTools-1 | `feat/lane-worktrees-residue-tests` | `6c79121ea0288ac495ea5d0cd856083059c631bb` | 0 | 0 | 0 | landed-and-preserved | +| ort-install-followups | lane openRepoTools-1 | `fix/install-marker-on-every-file-and-one-install-lock` | `2080f3d83520bd1ea5632e754026f8ba3df4eb1f` | 0 | 0 | 0 | empty-shell | +| ort-shape-pin | lane openRepoTools-1 | `chore/openreposhape-pin-7f84ca4` | `e43b2432976a22eb3bf8c419c96209399251d375` | 0 | 0 | 0 | retained-work | +| ort-triad-exec | lane openRepoTools-1 | `004-migrate-to-triad-exec` | `ff6f6a7c7b7921ca1e0b0234e898900f98532366` | 0 | 0 | 0 | retained-work | +| ort-triad-rehearsal | lane openRepoTools-1 | `004-migrate-to-triad-rehearsal` | `ff6f6a7c7b7921ca1e0b0234e898900f98532366` | 0 | 0 | 0 | retained-work | +| ort-wip-init-followups | lane openRepoTools-1 | `fix/wip-init-step7-guarded-writes-and-step8-refusal-words` | `2080f3d83520bd1ea5632e754026f8ba3df4eb1f` | 0 | 0 | 0 | empty-shell | +| triad-reads | lane openRepoTools-2 | `004-migrate-to-triad-reads` | `ff6f6a7c7b7921ca1e0b0234e898900f98532366` | 0 | 0 | 0 | retained-work | +| triad-lane-tooling | lane openRepoTools-3 | `feat/triad-lane-tooling` | `c4864ac5e59db49d01f638a80ed38daf1d788182` | 0 | 0 | 0 | retained-work | +| 001-separate-swap-ctx-handoff | Brett Heap | `001-separate-swap-ctx-handoff` | `3c26041a4444a10bc240cb64a168ece4d9edf6c5` | 0 | 0 | 4 | retained-work | +| 004-migrate-to-triad | Brett Heap | `004-migrate-to-triad` | `ff6f6a7c7b7921ca1e0b0234e898900f98532366` | 0 | 0 | 0 | retained-work | +| 005-supervised-legacy-ctx | Brett Heap | `feat/supervised-context-restart` | `f13d32975d7457d662249385d23ee28a7f713c4c` | 0 | 0 | 3 | landed-and-preserved | +| feat-claude-current | Brett Heap | `feat/claude-current` | `11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12` | 0 | 0 | 2 | landed-and-preserved | +| a22-primary | lane openRepoTools-3 | `feat/amendment-22-sql-primary` | `2080f3d83520bd1ea5632e754026f8ba3df4eb1f` | 0 | 0 | 0 | empty-shell | +| closeout-2 | lane openRepoTools-3 | `feat/lane-end-closeout-rest` | `ed3655184d90e1ac21848aa4c3e294327b9561b6` | 0 | 0 | 0 | landed-and-preserved | +| suite-speed | lane openRepoTools-3 | `feat/shell-suite-wall-time` | `d2f80512902bf85b5993134a3cef6913d131565a` | 0 | 0 | 0 | landed-and-preserved | +| sweep-170 | lane openRepoTools-1 | `feat/lane-worktrees-residue` | `4ea84c8c8206347cef3cc5a626e79aee9e12b8c3` | 0 | 0 | 1 | landed-and-preserved | + +## Restore rehearsal + +97 checks passed, 0 failed, repeated from the backup's final location: + +- A working clone and an independent mirror restored from the source bundle each list the same + 33 refs with the same SHA as the live listing at bundle time; `git fsck --full` is clean. +- The 2902 object IDs reachable from the 50 bundled tips are identical live and restored + (sorted-list SHA256 `338cb7bdd397076eeced1de0852eeb1510b4f97e02fb3f62de434531c7be327d`). +- For each of the 17 worktrees, the HEAD commit resolves, its tree ID is unchanged, every + index object exists, a worktree checked out from the restore has a byte-identical index, and + after copying the captured configuration back, its tracked status and untracked and ignored + lists match the capture (less the caches that were not copied). +- Both dependency commits resolve from the dependency bundle, and their tree digests, + recomputed with each commit's own helper, match the values above. + +The previous private backup `prep-20261004T211123Z` is still present (25 top-level entries, +including its `git-filter-repo` 2.47.0 wheel and venv, whose `--version` prints `a40bce548d2c`). +It was recorded read-only. + +## What remains for Gate A + +Owner dispositions for every retained object, and a final capture at an owner-coordinated freeze +after the migration's own writers stop. Installed-file receipts are still needed for py-bench and +any other profile or workstation. This backup is local to this workstation. No execution task is +checked complete by this evidence.