From 52ce64ee7787b62bf015e13cbf663f305513093e Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Sat, 3 Oct 2026 18:45:52 +0000 Subject: [PATCH 01/12] docs: preserve triad migration planning drafts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preserve the existing OpenSpec and Speckit planning files at Brett Heap’s request during repository cleanup. No migration or adoption is executed. --- .../changes/migrate-to-triad/.openspec.yaml | 2 + .../migrate-to-triad/adoption-plan.yaml | 346 ++++++++++++++++++ openspec/changes/migrate-to-triad/design.md | 137 +++++++ openspec/changes/migrate-to-triad/proposal.md | 68 ++++ .../specs/repository-triad-migration/spec.md | 88 +++++ openspec/changes/migrate-to-triad/tasks.md | 22 ++ openspec/config.yaml | 1 + specs/004-migrate-to-triad/data-model.md | 18 + specs/004-migrate-to-triad/inventory.json | 156 ++++++++ specs/004-migrate-to-triad/plan.md | 162 ++++++++ specs/004-migrate-to-triad/quickstart.md | 31 ++ specs/004-migrate-to-triad/research.md | 22 ++ specs/004-migrate-to-triad/spec.md | 85 +++++ specs/004-migrate-to-triad/tasks.md | 124 +++++++ specs/004-migrate-to-triad/verification.md | 42 +++ 15 files changed, 1304 insertions(+) create mode 100644 openspec/changes/migrate-to-triad/.openspec.yaml create mode 100644 openspec/changes/migrate-to-triad/adoption-plan.yaml create mode 100644 openspec/changes/migrate-to-triad/design.md create mode 100644 openspec/changes/migrate-to-triad/proposal.md create mode 100644 openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md create mode 100644 openspec/changes/migrate-to-triad/tasks.md create mode 100644 openspec/config.yaml create mode 100644 specs/004-migrate-to-triad/data-model.md create mode 100644 specs/004-migrate-to-triad/inventory.json create mode 100644 specs/004-migrate-to-triad/plan.md create mode 100644 specs/004-migrate-to-triad/quickstart.md create mode 100644 specs/004-migrate-to-triad/research.md create mode 100644 specs/004-migrate-to-triad/spec.md create mode 100644 specs/004-migrate-to-triad/tasks.md create mode 100644 specs/004-migrate-to-triad/verification.md diff --git a/openspec/changes/migrate-to-triad/.openspec.yaml b/openspec/changes/migrate-to-triad/.openspec.yaml new file mode 100644 index 00000000..6a87d2b2 --- /dev/null +++ b/openspec/changes/migrate-to-triad/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-03 diff --git a/openspec/changes/migrate-to-triad/adoption-plan.yaml b/openspec/changes/migrate-to-triad/adoption-plan.yaml new file mode 100644 index 00000000..c32025d1 --- /dev/null +++ b/openspec/changes/migrate-to-triad/adoption-plan.yaml @@ -0,0 +1,346 @@ +# Preliminary adoption mapping; planning only. Execution needs a refreshed baseline and explicit approval. +# Paths are relative to the source checkout. Generated metadata does not authorize repository creation. +schema_version: 1 +kind: adoption-plan +generated_on: "2026-10-03" +tool: "opensoft/openRepoShape adopt-project.py" +source: + repository: opensoft/openRepoTools + local_path: . + default_branch: main + commit: c1bac0dfc99a62583cb62eafc93a192911b2ff22 + files: 58 + bytes: 4202017 + commits: 77 +mode: in-place +project: openRepoTools +org: opensoft +id: openrepotools +visibility: public +tracking_branch: main +adopt_branch: adopt/three-repo-shape +elected_by: "Brett Heap" +elected_on: "2026-10-03" +reference: "openxFactory docs/project-repo-schema.md" +legs: + assembly: openRepoTools + spec: openRepoTools-spec + code: openRepoTools-code + spec_path: spec + code_path: code +pins: [] +seeding: + spec: + seeded_from_template: false + code: + seeded_from_template: false +allow_empty_legs: [] +paths: + - path: .gitattributes + leg: root + confidence: high + 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: 1857 + review_required: false + - path: .github/ + leg: code + confidence: high + 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: 18419 + review_required: false + - path: .gitignore + leg: root + confidence: high + 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: 38 + review_required: false + - path: .gitmodules + 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: 121 + 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: "Keep existing nested dependency registration with its upstream gitlink in code; assembly spec/code registrations are generated separately." + - path: AGENTS.md + leg: root + confidence: high + 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: 20968 + review_required: false + - path: CLAUDE.md + leg: root + confidence: high + 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: 16 + review_required: false + - path: LICENSE + leg: root + confidence: high + 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: 11357 + review_required: false + - path: README.md + leg: root + confidence: high + 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: 29806 + review_required: false + - path: commands/ + leg: code + 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: 3 + bytes: 5146 + review_required: false + resolution: "These Markdown command files are shipped runtime installer payloads with implementation tests, not OpenSpec or Speckit decisions." + - path: contracts/ + leg: code + 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: 1 + bytes: 3299 + review_required: false + resolution: "At this baseline the only contract is openreposhape-pin.yaml, a dependency lock coupled to the code gitlink and installer; future product governance contracts belong in spec and assembly pins are generated at root." + - path: docs/ + leg: spec + 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: 1 + bytes: 182097 + review_required: false + - path: lane + 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: 83555 + 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-end + 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: 93296 + 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-handoff + 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: 72601 + 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-rename + 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: 17116 + 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-start + 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: 223900 + 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: lanes + 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: 36348 + 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: lanes-edit.sh + leg: code + confidence: medium + 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: 759480 + review_required: false + - path: link-estates + 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: 21694 + 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: openRepoTools + 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: 178500 + 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: openspec/ + leg: spec + 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 + review_required: false + - path: park + 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: 50113 + 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: repos.tsv + 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: 2651 + 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: "Runtime alias data installed beside the lane commands." + - path: resume + 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: 63671 + 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: skills/ + leg: code + 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: 3 + bytes: 77708 + review_required: false + resolution: "These three skills are installed product payloads; project workflow skills remain local root bootstrap artifacts." + - path: specs/ + leg: spec + 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 + review_required: false + - path: status + 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: 347320 + 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: tests/ + leg: code + 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: 12 + bytes: 1880040 + review_required: false + - path: upstream/ + 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: 0 + 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/lanes-edit.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/openRepoTools 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/run.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_install_skill_and_hook.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" + - "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_repo_hygiene.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" + - "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" + - "merge shape/.gitattributes into .gitattributes: the source repository already has that name, so the shape's copy was written beside it and NOTHING was overwritten" + - "merge shape/.gitignore into .gitignore: the source repository already has that name, so the shape's copy was written beside it and NOTHING was overwritten" + - "add the line `Read AGENTS-shape.md first — the rules of this repository's shape.` to the existing AGENTS.md rather than replacing it with shape/AGENTS.md: AGENTS.md is what this project's agents ALREADY read, and `contracts/path-classification.yaml` keeps it at the root (`root-assistant-instructions`) because it addresses the whole project. Then delete shape/AGENTS.md. Nothing was overwritten." + - "add the line `Read AGENTS-shape.md first — the rules of this repository's shape.` to the existing CLAUDE.md rather than replacing it with shape/CLAUDE.md: CLAUDE.md is what this project's agents ALREADY read, and `contracts/path-classification.yaml` keeps it at the root (`root-assistant-instructions`) because it addresses the whole project. Then delete shape/CLAUDE.md. Nothing was overwritten." + - "merge shape/README.md into README.md: the source repository already has that name, so the shape's copy was written beside it and NOTHING was overwritten" + - "open the split as a pull request against the source's default branch; the legs openRepoTools-spec and openRepoTools-code are seeded before it, so review the root's diff and the two new repositories together" + - "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 58-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." +summary: + spec: + files: 17 + bytes: 202997 + file_share: 0.2931 + byte_share: 0.0483 + code: + files: 35 + bytes: 3934978 + file_share: 0.6034 + byte_share: 0.9364 + root: + files: 6 + bytes: 64042 + file_share: 0.1034 + byte_share: 0.0152 + unresolved: + files: 0 + bytes: 0 + file_share: 0.0000 + byte_share: 0.0000 +planning_status: proposed-preliminary-baseline +execution_authorized: false diff --git a/openspec/changes/migrate-to-triad/design.md b/openspec/changes/migrate-to-triad/design.md new file mode 100644 index 00000000..691aeee7 --- /dev/null +++ b/openspec/changes/migrate-to-triad/design.md @@ -0,0 +1,137 @@ +# Design: in-place triad adoption + +## Context + +The preliminary source is main `c1bac0dfc99a62583cb62eafc93a192911b2ff22`: +58 tracked paths, 77 commits, one nested standard submodule. The inspected +standard is `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. There are 12 registered +worktrees including this planning checkout, and four open PRs. Feature 001 has +dirty/untracked work; an extraction of main alone would omit it. The +[inventory](../../../specs/004-migrate-to-triad/inventory.json) is a snapshot. + +## Goals / Non-Goals + +Preserve project identity/history, all user work, installed command behavior +and a reproducible pinned assembly. Separate product decisions from shipped +implementation; migrate unfinished features without restarting specification. +Do not redesign swap, enable its experimental capability, change WIP ownership, +rewrite published source history or remove old worktrees during adoption. + +## Decisions + +### Assembly identity and source baseline + +Use the standard's in-place adoption. `openRepoTools` stays the existing +assembly; `openRepoTools-spec` and `openRepoTools-code` are new legs mounted +at `spec` and `code`. Public visibility is a proposal matching current source +visibility, subject to final approval. A new assembly name would strand +existing issues, URLs and PRs, so is outside this design. + +Run real adoption from a fresh clean default-branch clone with no linked +worktrees attached. Original working clones remain preserved. Freeze the +baseline only after planning and any agreed prerequisite changes land; refresh +the generated plan whenever that commit moves. Approval binds the actual +baseline, standard commit, complete mapping and follow-ups. + +### Placement and dependency custody + +The [resolved adoption plan](adoption-plan.yaml) accounts for all 58 baseline +paths: 17 spec, 35 code, six root, none dropped. It records reasons for all +14 originally unresolved paths and overrides for shipped Markdown payloads +and the dependency lock. Product documentation/OpenSpec/Speckit go to spec. +Root owns front-door guidance, license, project metadata and workflow bootstrap. + +Keep executable files, `repos.tsv`, shipped `commands/` and `skills/`, tests +and implementation CI in code. The original `.gitmodules`, mounted standard +and `contracts/openreposhape-pin.yaml` also stay together in code. At this +baseline that contract is solely a dependency lock, not product governance. +Generated root shape/spec/code pins are distinct. Future governance contracts +belong in spec; regenerate the path plan if the source adds such contracts. + +Keeping the standard in root would move its gitlink away from its dependency +pin and implementation consumers, and mutate the original `.gitmodules` during +the byte-accounted split. Keeping that dependency unit in code preserves its +existing paths. Existing-submodule handling still requires local rehearsal; +plan coverage validation alone is not execution certification. + +### Public installation compatibility + +After successful byte accounting, add a root `openRepoTools` compatibility +entry point. It resolves one assembly revision and its exact code pin, then +loads the implementation at that immutable commit. All install payloads come +from that same code commit. Preserve the existing `gh api .../openRepoTools` +and raw-URL one-liners, local/offline invocation, override/fork behavior, +destination names, artifact counts, permissions, hooks, receipts and atomic +refusal semantics. No request may silently combine root/spec/code main tips. + +The code installer has a self-contained local payload tree; installed commands +must not depend on the developer's assembly checkout. Source/ref resolution +must support the existing monorepo override form, an adopted assembly fork and +explicit code checkout execution. Missing or inconsistent pins refuse before +installation effects. Implementation tests define the compatibility matrix; +this document does not invent a second installer implementation. + +### Development and active work + +The sole executable list is the linked Speckit feature. `.specify/` and agent +links are currently ignored local scaffolding, so baseline blob extraction +does not preserve them. Inventory local configuration and regenerate workflow +at the assembly root with the shape-aware bootstrap. Retain the root guidance +and the named team assignments in feature 001. Leg guidance points back to root. + +Classify each active feature's delta relative to its own reviewed merge base; +translate it into selected spec/code/root changes with old-to-new commit/file +receipts. Include dirty/untracked files in preservation and replay validation. +Preserve original branches and PRs while replacement branches are reviewed. +Paired leg worktrees use the existing feature name under root `worktrees/`. +Do not cherry-pick a mixed monorepo commit wholesale into either leg, or merge +an old feature branch into the adopted assembly. Do not retire/rebind a live +lane until its owner has reached a safe breakpoint and replacement evidence +is reviewed. WIP records remain in their existing private repository and use +the supported estate workflow; public records contain no private backups. + +### CI and exact-pin delivery + +Code CI runs implementation checks; root CI validates manifest/pins and the +exact composed assembly. Supply explicit code/spec/assembly roots to tests +that inspect docs or history; preserve the nested dependency pin assertions +in the code Git repository. Use the canonical serialized `tests/run.sh`, +Bash 3.2 parsing and current platform/fixture timing policies. Missing-spec +context cannot turn a required integration check into a silent skip. + +Land follow-up leg changes before the root pin bump that selects them. Root +gitlinks, leg pins and workflow SHAs move through the standard's bump tool. +The historical upstream dependency remains one-way and unedited; needed +standard fixes land there before a deliberate pin bump here. + +## Risks / Trade-offs + +- Local mapping passes while existing-submodule extraction fails: gate real + execution on an isolated local bare-remote rehearsal with intact gitlink, + module metadata, pin and recursive bootstrap. +- Historical commits/files change or disappear: retain original repository, + bundles/private work backups and migration receipts; require blob accounting + for the frozen baseline and explicit verification of each replayed delta. +- An active lane writes during capture: coordinate a bounded owner-approved + breakpoint, then refresh capture and compare checksums before cutover. +- Installer entry point vanishes or mixes revisions: add compatibility before + root merge; validate exact-ref/fork/offline and all-or-none installation. +- CI cannot read the selected assembly/spec context: publish explicit composed + checkout instructions and preserve the original canonical regression gate. +- New roots make WIP paths stale: use supported park/resume contracts and + reviewed migration records; never overwrite workspace pointers or force a + refusal through with resets. + +## Migration Plan + +The [Speckit plan](../../../specs/004-migrate-to-triad/plan.md) owns sequencing, +gates, active PR decisions, cutover and rollback. This change is planning-only. +`git-filter-repo` is absent in the inspected `py-bench`; make prerequisite +availability an execution gate, without installing it during planning. + +## Approval decisions + +Confirm public new legs, the refreshed frozen baseline/mapping, branch/PR +dispositions, coordinated cutover and repository creation only after the +local rehearsal and compatibility work are reviewable. No approval is inferred +from OpenSpec artifact completeness or the generated election metadata. diff --git a/openspec/changes/migrate-to-triad/proposal.md b/openspec/changes/migrate-to-triad/proposal.md new file mode 100644 index 00000000..8253222b --- /dev/null +++ b/openspec/changes/migrate-to-triad/proposal.md @@ -0,0 +1,68 @@ +# Proposal: migrate openRepoTools to the assembly/spec/code triad + +## Why + +openRepoTools currently keeps product decisions, implementation and project +workflow in one repository. Elect the openRepoShape triad so specifications +and implementation can evolve independently while the existing repository +pins their exact tested combination and preserves its identity and history. + +## What Changes + +- Adopt `opensoft/openRepoTools` in place as the assembly root; extract + `opensoft/openRepoTools-spec` and `opensoft/openRepoTools-code` with history. + Public legs are proposed to match the existing public source; execution + requires explicit approval of the reviewed plan, visibility and follow-ups. +- Put OpenSpec, Speckit specifications and product documentation in `spec/`; + executable tooling, shipped skills/commands, tests, CI and the mounted + standard dependency in `code/`. Root agent guidance and workflow bootstrap + span both legs. No source path is proposed for deletion. +- **BREAKING:** development paths and PR destinations change. Preserve command + names, install artifacts, published one-line installation and installed + behavior through a pinned assembly-to-code compatibility entry point. +- Preserve all open PRs, branch histories, dirty/untracked work, detached + worktrees and workspace records before migration. Continue unfinished + features through explicit paired spec/code branches with migration receipts; + do not merge old monorepo feature branches over the adopted root. +- Validate a local bare-remote rehearsal before any real repository creation. + Keep original clones/worktrees and the installed toolset usable until a + reviewed assembly PR and exact-pin integration checks establish cutover. + +## Capabilities + +### New Capabilities + +- `repository-triad-migration`: history-preserving adoption, placement, + installation compatibility, active-work migration, exact-pin delivery and + evidence-gated cutover/rollback. + +### Modified Capabilities + +None. No canonical capability inventory exists on the inspected source main. +Swap, context, handoff and estate-command semantics remain governed by their +existing changes; this migration does not activate experimental capabilities. + +## Impact + +- `openRepoTools` installer/default source selection and its bare-name payload + lookups; assembly entry point and leg-pin resolution; fork/ref behavior. +- `tests/conftest.py`, pin/status/install/hygiene tests, `tests/run.sh`, + `.github/workflows/tests.yml`, and cross-leg documentation references. +- `.gitmodules`, the mounted `upstream/openRepoShape` dependency and its + `contracts/openreposhape-pin.yaml` lockstep relationship. Keep all three in + code; generated assembly shape/spec/code pins are separate contracts. +- Global OpenSpec/Speckit bootstrap, currently ignored local `.specify/` and + agent links, lane directory bindings, open PR destinations, and WIP records. +- Governing change: this directory. Sole implementation feature: + [004-migrate-to-triad](../../../specs/004-migrate-to-triad/spec.md). + See its [migration plan](../../../specs/004-migrate-to-triad/plan.md) and + executable task list; the OpenSpec checklist records governance only. + +## Planning status + +Requested on October 3, 2026. Planning is authorized; migration execution, +repository creation, software installation, PR merge and lane relocation are +not authorized by this request. The attached adoption plan is a preliminary +mapping of source main `c1bac0dfc99a62583cb62eafc93a192911b2ff22`, not a promise +that this will be the final split commit. Refresh after planning lands and the +cutover baseline is frozen. No runtime or migration success is claimed. diff --git a/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md b/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md new file mode 100644 index 00000000..982c6f73 --- /dev/null +++ b/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md @@ -0,0 +1,88 @@ +# Repository triad migration + +## Purpose + +Convert the existing openRepoTools repository to a pinned assembly/spec/code +project while preserving history, unfinished work and supported installation. + +## ADDED Requirements + +### Requirement: Adoption preserves source identity and accounts for content + +The migration SHALL retain the existing repository name, identity and full +published history. It SHALL freeze a reviewed source commit and account for +each tracked source path by blob or gitlink identity in exactly one leg/root, +or an explicitly approved drop. It SHALL refuse stale/unresolved mappings and +SHALL NOT force-push the original history or weaken verification to pass. + +#### Scenario: Source changes after plan generation +- **WHEN** the default-branch commit differs from the reviewed adoption plan +- **THEN** execution SHALL require regenerated mapping/checks and renewed + approval of the actual baseline before creating real repositories. + +#### Scenario: Existing nested dependency is extracted +- **WHEN** the code leg receives the mounted standard dependency +- **THEN** its registration, exact gitlink and coupled pin SHALL remain valid + and SHALL be demonstrated by local rehearsal and recursive bootstrap. + +### Requirement: Active work is preserved before cutover + +The migration SHALL inventory open PRs, all branches/worktrees, detached work, +dirty/untracked files and local workflow configuration. It SHALL preserve +their contents and recovery evidence before cutover, including work absent +from the default branch. Each continued feature SHALL have a reviewed +old-to-new mapping and validated spec/code/root changes before rebinding. +Original worktrees and installed tools SHALL remain available until acceptance. + +#### Scenario: Swap feature has uncommitted proposal and code work +- **WHEN** source main is extracted without those feature changes +- **THEN** the migration SHALL retain complete original feature contents and + migrate the reviewed delta separately, preserving feature identity and roles +- **AND** absence from the extracted main SHALL NOT imply abandonment. + +### Requirement: Installation retains the public interface and one revision + +Existing one-line installation, command names, payload destinations/modes, +skills/hooks/receipts and supported fork/ref/local invocation SHALL remain +usable. An adopted assembly entry point SHALL resolve one immutable code +revision for the complete installation. Missing/inconsistent pin evidence +SHALL refuse before partial installation. Installed tools SHALL function +without a developer assembly checkout. + +#### Scenario: Assembly code main advances independently +- **WHEN** the operator installs from a selected assembly revision +- **THEN** every payload SHALL come from that revision's selected code commit + rather than whichever code main tip exists at request time. + +#### Scenario: Offline checkout installation +- **WHEN** a complete local adopted checkout is used without network access +- **THEN** installation SHALL use its verified local payload and preserve the + existing all-or-none installation and refusal behavior. + +### Requirement: Project workflow operates across the pinned legs + +The assembly SHALL own project workflow and its manifest/pins; product +OpenSpec/Speckit artifacts SHALL live in spec, implementation in code. +Continued features SHALL use paired leg worktrees with preserved feature IDs. +Delivery SHALL land leg changes and select them through a root pin bump. +CI SHALL test the exact composed state without silently skipping required +cross-leg tests. The standard dependency SHALL remain unedited in place. + +#### Scenario: Implementation and specification land separately +- **WHEN** new leg commits are ready for project delivery +- **THEN** root gitlinks, pin records and workflow commit references SHALL move + together through the established pin-bump procedure and integration checks. + +### Requirement: Execution and cutover require reviewable evidence + +Real execution SHALL require an explicit approved plan, visibility, baseline, +mapping and follow-ups. A local bare-remote rehearsal, preservation receipts, +compatibility checks and required platform/CI checks SHALL precede cutover. +Execution SHALL use a clean isolated source clone without linked worktrees. +Failed verification SHALL retain the source/work and stop landing; rollback +SHALL restore a reviewed prior state without destructive history rewriting. + +#### Scenario: Preparation is complete but approval is absent +- **WHEN** mapping and planning validation have passed without execution approval +- **THEN** the migration SHALL remain a plan and SHALL create no real leg + repositories, move no lanes and change no installed tools. diff --git a/openspec/changes/migrate-to-triad/tasks.md b/openspec/changes/migrate-to-triad/tasks.md new file mode 100644 index 00000000..3738cb5d --- /dev/null +++ b/openspec/changes/migrate-to-triad/tasks.md @@ -0,0 +1,22 @@ +# Governance and Speckit handoff + +The sole executable list is [004-migrate-to-triad/tasks.md](../../../specs/004-migrate-to-triad/tasks.md). +This checklist tracks governance, not duplicate implementation tasks. + +## 1. Proposal and handoff + +- [x] 1.1 Record the migration proposal, design, capability requirements, + preliminary adoption mapping and sole linked Speckit feature; verify all + artifacts exist and planning validation is recorded. +- [ ] 1.2 Approve the frozen source/standard revisions, repository visibility, + final path mapping, follow-ups and active-work dispositions after Gates A/B; + verify approval explicitly names the actual execution plan. + +## 2. Migration evidence and closure + +- [ ] 2.1 Accept exact assembled-head, preservation, feature-transition and + rollback evidence from Speckit Gates C–E; verify required CI and ownership + boundaries without enabling unrelated experimental runtime features. +- [ ] 2.2 Archive only after the adopted assembly and selected leg pins land + and continued work is accounted for; verify root delivery and recorded + old-PR/worktree dispositions before closure. diff --git a/openspec/config.yaml b/openspec/config.yaml new file mode 100644 index 00000000..b4bbeb94 --- /dev/null +++ b/openspec/config.yaml @@ -0,0 +1 @@ +schema: spec-driven diff --git a/specs/004-migrate-to-triad/data-model.md b/specs/004-migrate-to-triad/data-model.md new file mode 100644 index 00000000..b36916ca --- /dev/null +++ b/specs/004-migrate-to-triad/data-model.md @@ -0,0 +1,18 @@ +# Migration records + +These records describe migration evidence; they confer no runtime ownership +and never replace lane claims, workspace pointers or the standard's pins. + +| Record | Required facts | +| --- | --- | +| Adoption plan | Source repository/commit, standard revision evidence, names/visibility, reasoned path owners, follow-ups, coverage result and approval binding. Relative paths only in shared artifacts. | +| Work inventory | Observation time, branch/PR/head identity, detached status, readable/dirty indication and snapshot limits. Public `inventory.json` omits host paths and private work. | +| Private preservation receipt | Exact original worktree/binding, branch refs, staged/unstaged/untracked/ignored content digests, backup location and verified restore result. Stored host-locally or in existing private WIP storage. | +| Feature migration receipt | Original merge base/head and captured content; spec/code/root file mapping; resulting branches/commits/checksums; conflict/replay decisions, roles and approval. | +| Composed candidate evidence | Root/spec/code/standard commits, pin/digest consistency, installer payload revision, platform/CI/rehearsal/rollback results and outstanding findings. | +| Cutover approval | Actual candidate/baseline, visibility, leg names, preservation/rehearsal references, lane breakpoints and authorized actions. | + +Generated `elected_by`/date metadata and `execution_authorized: false` in the +preliminary plan are informational. The adoption script does not enforce the +custom planning flag; the operator must not call real `execute` before the +reviewed approval gate. An inventory snapshot is never proof of backed-up work. diff --git a/specs/004-migrate-to-triad/inventory.json b/specs/004-migrate-to-triad/inventory.json new file mode 100644 index 00000000..77254dad --- /dev/null +++ b/specs/004-migrate-to-triad/inventory.json @@ -0,0 +1,156 @@ +{ + "observed_at": "2026-10-03T17:50:46.499925+00:00", + "source_repository": "opensoft/openRepoTools", + "source_main": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "standard_commit": "39d5c986fcfac1a160474bfe91c5f1c37fccc72c", + "worktrees": [ + { + "identity": "main", + "head": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "layout": "root", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "lclaude-finalize", + "head": "7e4dc31c4571cf8d7b11e24941568edf66f82a94", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "detached-08dad90a67bc", + "head": "08dad90a67bc6699283589c2222c53833a6603cd", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "001-separate-swap-ctx-handoff", + "head": "fc5105b5371082c966c151f4bc08bfdabf64539b", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 22, + "locked": false, + "prunable": false + }, + { + "identity": "002-skip-no-lane-guard", + "head": "a2861bbdf0bf4793108bf3b2da2fc65f38d642bd", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "003-binary-only-guard-runner", + "head": "42860a93be192f025a725708d7a016083ff82923", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "004-migrate-to-triad", + "head": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 2, + "locked": false, + "prunable": false + }, + { + "identity": "chore/preserve-local-planning-20261003", + "head": "135c18b258d02136ed834e5a446e552db385d50c", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "detached-92eab6c4fa2e", + "head": "92eab6c4fa2e68f7e2202d529ee0f2e4bebce874", + "layout": "legacy-nested", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "fix/claim-takeover-and-retire-fork", + "head": "3de40b1865d31d3bb96a52e3822c1386c9e52634", + "layout": "legacy-nested", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "layout": "legacy-nested", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "layout": "legacy-nested", + "readable_here": true, + "dirty_entries": 0, + "locked": false, + "prunable": false + } + ], + "open_prs": [ + { + "headRefName": "feat/claude-current", + "headRefOid": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", + "isDraft": true, + "number": 134, + "title": "claude-current and claude-restart-check: every launch starts the newest published Claude Code by absolute path, and a running session is told when its binary moved (opensoft/workBenches#119)", + "url": "https://github.com/opensoft/openRepoTools/pull/134" + }, + { + "headRefName": "feat/supervised-context-restart", + "headRefOid": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "isDraft": false, + "number": 121, + "title": "`/ctx` writes its restart to disk before it kills anything, and what tmux starts is a supervisor that stays in the pane \u2014 the fresh session was an environment variable the launcher dropped (#94)", + "url": "https://github.com/opensoft/openRepoTools/pull/121" + }, + { + "headRefName": "feat/crash-consistent-lane-worktree-recovery", + "headRefOid": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "isDraft": false, + "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", + "url": "https://github.com/opensoft/openRepoTools/pull/97" + }, + { + "headRefName": "fix/claim-takeover-and-retire-fork", + "headRefOid": "3de40b1865d31d3bb96a52e3822c1386c9e52634", + "isDraft": false, + "number": 61, + "title": "claim --force takes over a dead lane's hold; lane-end --retire ends a duplicate holder", + "url": "https://github.com/opensoft/openRepoTools/pull/61" + } + ], + "limitations": [ + "Snapshot only; refresh before baseline freeze and cutover.", + "Physical paths, credentials, transcript bodies and WIP data are omitted.", + "Dirty/untracked work in feature 001 includes edits from this conversation and concurrent planning; preserve the complete current contents.", + "Raw preservation backups must be host-local or in the designated private WIP repository; public planning records hold identity/digest receipts only." + ] +} diff --git a/specs/004-migrate-to-triad/plan.md b/specs/004-migrate-to-triad/plan.md new file mode 100644 index 00000000..1e17ce07 --- /dev/null +++ b/specs/004-migrate-to-triad/plan.md @@ -0,0 +1,162 @@ +# Migration plan: openRepoTools assembly/spec/code triad + +**Feature**: `004-migrate-to-triad` | **Date**: 2026-10-03 +**State**: Proposed plan; no migration, install or repository creation performed +**Spec**: [spec.md](spec.md) +**Governance**: [proposal](../../openspec/changes/migrate-to-triad/proposal.md) + +## Baseline and deliverables + +The [adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) +is generated from main `c1bac0dfc99a62583cb62eafc93a192911b2ff22` using pinned +openRepoShape `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. All 58 tracked +paths are resolved: 17 spec, 35 code, six root, zero dropped. There are +21 named follow-ups. This is an inspected preliminary baseline; regenerate +after planning lands and the actual cutover source is frozen. + +The [inventory](inventory.json) records 12 worktrees (including migration +planning), four open PRs and dirty feature 001 work. It omits machine paths, +secrets/transcripts and backup contents. Host-local/private preservation +records must capture actual paths, content and digests at the execution gate. + +## Target placement + +| Owner | Existing paths / generated responsibilities | Reason | +| --- | --- | --- | +| Assembly `openRepoTools` | `AGENTS.md`, `CLAUDE.md`, `README.md`, `LICENSE`, `.gitattributes`, `.gitignore`; generated manifest/Makefile/validators and assembly pins | Front door and project coordination across legs. | +| Spec `openRepoTools-spec` | `openspec/`, `specs/`, `docs/`; later feature ideation/governance artifacts | Product requirements, decisions and manual. | +| Code `openRepoTools-code` | All executable tools, `repos.tsv`, `commands/`, `skills/`, `tests/`, implementation CI | Shipped implementation and its installer payload. | +| Code dependency unit | Original `.gitmodules`, `upstream/openRepoShape`, `contracts/openreposhape-pin.yaml` | Keep module registration, exact gitlink and dependency lock together. | +| Root workflow bootstrap | `.specify/`, project agent links and selected feature pointer | Currently local/ignored; capture config and regenerate shape-aware root scaffolding. | + +After byte-preserving extraction, add a root installation entry point that +resolves the exact code pin. The original installer implementation moves to +code; the root entry point selects and invokes it. Preserve the existing user +one-liner and installed command names. Do not duplicate installer mechanics. + +## Phase 1 — Review and preserve work + +Land the planning artifacts through normal review before freezing execution. +Refresh current estate status using `status --fetch`, open PR metadata and +branch/worktree observations. Verify the two proposed leg names are available +and decide visibility. Agree a bounded cutover with current lane owners. +Capture original history, all branch refs, detached HEADs, staged/unstaged and +untracked content, ignored workflow config and installed receipts/config. +Use host-local backups or the existing private WIP repository; public records +hold only safe identities/digests. Prove restoration before declaring capture +complete. Never edit workspace.yaml or recreate estate parking logic. + +Recommended active-work dispositions are proposals, not merge/closure actions: + +| Work | Proposed treatment | +| --- | --- | +| `001-separate-swap-ctx-handoff` | Preserve full branch delta and dirty/untracked additions; migrate to paired `001` spec/code worktrees. Keep tasks, evidence, roles and activation gates. | +| `002-skip-no-lane-guard`, `003-binary-only-guard-runner` | Inspect remaining deltas versus main; migrate useful unfinished work or retain archived branch receipts if already landed. | +| PR #97 | Preserve branch/review; carry useful diagnostics into feature 001 under its service authority. Do not merge unchanged or auto-close as part of adoption. | +| PR #121 | Preserve/review independently; translate selected context-runtime work to code/spec as needed, with its readiness integration still explicit. | +| PR #134 (draft), PR #61 | Keep current heads and review history; continue selected deltas in new legs after owner review. No automatic merge or abandonment. | +| Other branches/detached worktrees/preservation branch | Inspect individually, assign continue/archive decision, retain recovery receipt; no deletion implied. | +| Migration feature `004` | Carry this plan/spec/tasks into the spec leg; assembly/code follow-ups get separate reviewed changes. Keep its own pre-migration recovery receipt. | + +**Gate A:** every preserved object is attributable and restorable; no active +writer can silently invalidate capture. Baseline, visibility and work +dispositions are ready for review, with any unresolved owner decision explicit. + +## Phase 2 — Rehearse locally and make follow-ups reviewable + +Use a fresh isolated source clone at the chosen source commit with no linked +worktrees. Make `git-filter-repo` available through the approved prerequisite +path. Regenerate the mapping, retain reasoned overrides and run standard check. +Rehearse the standard's adoption against temporary local bare remotes with no +real GitHub repository creation or default-branch movement. + +Verify nested dependency extraction, source `.gitmodules` handling, full +baseline accounting, leg histories and recursive bootstrap. Exercise all +actual file-placement collisions. If the standard refuses or misaccounts +content, relay it and resolve through a reviewed standard change/pin bump; +do not patch the pinned submodule or adjust digests to manufacture success. + +Implement and review the necessary installer entry point/resolver, explicit +test-root context, CI layout, agent pointers, docs paths and workflow bootstrap +in the rehearsed arrangement. Record their patches and resulting commits so +real execution can apply the reviewed changes after source verification. +Add leg root guidance without overwriting original root guidance. Preserve +the Bash 3.2 floor and original no-submodule test behavior, while requiring +complete dependencies for composed acceptance. + +**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. + +## Phase 3 — Freeze and approve real adoption + +Coordinate a bounded main landing hold using applicable lane protocol. Re-read +current main and owner state, finalize source commit, mapping, standard pin, +visibility, follow-ups and preservation receipts. Any source drift requires +plan regeneration and check, not editing the commit field by hand. Present +the final plan and follow-ups for explicit approval before real execution. + +**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. Do not infer consent from this planning request. + +## Phase 4 — Create the legs and assemble the reviewed candidate + +Run the standard's approved `execute` from the isolated clone. It creates +the legs, extracts histories, mounts/pins them, opens the root split PR and +prints content accounting. Relay its table and refusals. A nonzero verification +stops landing; preserve source and newly created evidence/branches. Never rerun +over live legs or bypass a ruleset. + +After successful source verification, apply reviewed follow-ups through the +new leg/root PRs. Resolve `shape/` collisions explicitly; do not overwrite +pinned shape files. Put `Read AGENTS-shape.md first...` guidance first in root +agent instructions and bootstrap shape-aware OpenSpec/Speckit only when both +legs exist. Land required leg changes; advance root gitlinks, pin digests and +workflow SHAs together using the standard bump tool. + +**Gate D:** exact assembled commits pass manifest/pin checks, canonical code +tests/platform checks, install compatibility and bootstrap. The existing +source/install remain usable until root adoption review and merge complete. + +## Phase 5 — Continue features and cut over lanes + +Translate each approved retained feature delta into reviewed spec/code/root +changes and dirty/untracked replay with checksums. Use paired feature branches +and worktrees under `worktrees//{spec,code}`; preserve feature IDs and +map old commits to new leg commits. Review conflicts semantically. Account +for completed/landed work before replaying it. Retain original worktrees. + +Prove feature 001's amended service-owned inventory requirements and new +planning work are present without claiming runtime acceptance. Test feature +selection, OpenSpec/Speckit prerequisites and estate park/resume in disposable +fixtures. Apply supported WIP record updates only through their established +contracts; relay refusals. Rebind each lane at its reviewed safe breakpoint, +using the existing binding tools and exact session records. + +**Gate E:** every continued feature has a reviewed migration receipt and +preserved source; bindings and workflow resolve the intended new trees. +Obsolete PR disposition and any old-worktree retirement are separate explicit +decisions after verification, never an automatic cleanup step. + +## Rollback + +Before root merge, leave the reviewed candidate unmerged and keep original +development/install active. Newly created legs/branches remain for diagnosis; +do not delete them automatically. After root merge, restore the last working +assembly/code selection through reviewed revert/pin-bump PRs and the preserved +installer, without force push/resetting user work. Preserve any post-cutover +feature edits and uncertain jobs before changing bindings. Return lanes only +through supported tooling at a safe breakpoint; private workspace pointers +and claims are not rewritten to hide a failure. + +## Technical context and checks + +Implementation remains Bash (macOS 3.2), Python standard-library tooling and +Git/GitHub workflows. Run build/test/CLI work in the project bench, with shared +`tests/run.sh` locking. No real repository is created for a test. The local +constitution is an unfilled template; no ratification is inferred. Preserve +the existing root rules, standard pin checks and global workflow protocols. + +Planning checks: [verification.md](verification.md). Executable work and +requirement coverage: [tasks.md](tasks.md). All execution tasks remain open. diff --git a/specs/004-migrate-to-triad/quickstart.md b/specs/004-migrate-to-triad/quickstart.md new file mode 100644 index 00000000..a63a83b8 --- /dev/null +++ b/specs/004-migrate-to-triad/quickstart.md @@ -0,0 +1,31 @@ +# Review this migration plan + +Read [plan.md](plan.md), then the [resolved adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) +and [work inventory](inventory.json). The mapping is for the recorded source +main only; implementation and live feature transfer have not been attempted. + +From the original source checkout, the planning validation is: + +```sh +python3 upstream/openRepoShape/adopt-project.py check \ + --source . \ + --plan ../openRepoTools-worktrees/004-migrate-to-triad/openspec/changes/migrate-to-triad/adoption-plan.yaml +``` + +From the migration worktree, validate governance artifacts: + +```sh +openspec validate migrate-to-triad --strict +git diff --check +``` + +Route project CLIs through the declared bench. If source main changes, +regenerate the plan using `adopt-project.py plan`, retain reviewed resolutions +and follow-ups, then recheck. Do not change the baseline field to suppress a +stale-plan finding. Do not run real `execute` as a planning check. + +Before execution, complete Gates A/B and review the actual frozen baseline, +visibility, mapping, follow-ups and preservation receipts. The standard requires +explicit approval before repository creation. All execution tasks are open in +[tasks.md](tasks.md); the migration does not require recreating feature 001's +specifications or claiming its unfinished runtime work is complete. diff --git a/specs/004-migrate-to-triad/research.md b/specs/004-migrate-to-triad/research.md new file mode 100644 index 00000000..2a2f1e04 --- /dev/null +++ b/specs/004-migrate-to-triad/research.md @@ -0,0 +1,22 @@ +# Planning evidence and decisions + +October 3, 2026 inspection used the pinned standard's `AGENTS.md`, adoption +implementation, generated CLI reference and placement policy; root installer, +CI and fixture code; local branch/worktree state; read-only GitHub PR metadata. +No external writes, repositories, installation or migration occurred. + +| Finding | Decision / execution consequence | +| --- | --- | +| Source main has 58 tracked paths and one standard gitlink | Use exact preliminary mapping and refresh the final baseline. | +| Classifier treats shipped Markdown skills/commands as specification | Override to code with written reasons; these are installation payloads. | +| Original contract is the implementation's upstream dependency lock | Keep code pin/gitlink/.gitmodules together; generated assembly pins are separate. | +| `.specify` and agent directories are ignored local scaffolding | Preserve local config separately and regenerate root workflow after adoption. | +| Twelve worktrees and four open PRs; feature 001 is dirty | Source-main extraction is insufficient; preserve and map retained feature deltas. | +| Installer fetches bare paths from `openRepoTools` and local sibling payloads | Preserve public root entry point and bind every payload to one code pin. | +| Tests conflate repo, spec and dependency paths | Introduce explicit checkout context and composed CI, preserving nested-pin tests. | +| `git-filter-repo` absent in inspected bench | Execution prerequisite; no software installation was performed for planning. | +| Standard plan `check` covers names/paths, not execution correctness | Local bare-remote rehearsal must cover existing submodule and blob accounting. | + +Existing-submodule behavior, exact installation resolver implementation and +live feature replay are pending measured execution tasks, not assumed successes. +The final creation approval also confirms proposed public visibility. diff --git a/specs/004-migrate-to-triad/spec.md b/specs/004-migrate-to-triad/spec.md new file mode 100644 index 00000000..6799586e --- /dev/null +++ b/specs/004-migrate-to-triad/spec.md @@ -0,0 +1,85 @@ +# Feature specification: migrate openRepoTools to the triad + +**Feature**: `004-migrate-to-triad` +**Created**: 2026-10-03 +**Status**: Proposed; planning complete enough for review, execution gated +**Governing change**: [migrate-to-triad](../../openspec/changes/migrate-to-triad/proposal.md) + +## User scenarios + +### US1 — Preserve history and unfinished work (P1) + +The operator reviews an exact adoption mapping and current branch/worktree +inventory, then converts the existing repository without losing unpublished +or dirty work. Validate byte-accounted baseline extraction, nested dependency +preservation, and replay receipts for a mixed spec/code feature and its new files. +Missing content, stale baseline, unavailable backup or an unresolved placement +blocks execution/cutover. Preserve source branches and local work on refusal. + +### US2 — Install through the existing entry point (P1) + +A user runs the existing raw-URL or `gh api` one-liner, or installs from an +offline local checkout. Every payload comes from one selected immutable code +revision; command names, permissions, artifact counts, hooks and receipts are +preserved. Test forks/ref overrides, missing pins and partial fetch refusal. + +### US3 — Continue feature development and deliver exact pins (P2) + +The operator continues existing feature IDs through paired spec/code worktrees +and lands their changes through leg PRs followed by a validated assembly pin +bump. OpenSpec runs in spec; Speckit runs from the assembly with selected +feature paths. A code-only clone cannot falsely claim composed CI success. +The migration preserves feature 001's model-role assignments and open gates. + +## Functional requirements + +- **FR-001**: Keep `opensoft/openRepoTools` as assembly with full original + history; extract spec/code using the reviewed standard procedure. +- **FR-002**: Pin a source commit; resolve every path with reasons, account + for blobs/gitlinks, and reject a stale or unresolved plan. +- **FR-003**: Preserve and verify all active branches/PRs, detached worktrees, + dirty/untracked content and ignored workflow configuration before cutover. +- **FR-004**: Preserve the code dependency unit: `.gitmodules`, + `upstream/openRepoShape` and `contracts/openreposhape-pin.yaml`; verify nested + extraction/recursive bootstrap and retain the standard's exact pin semantics. +- **FR-005**: Keep original installation entry points and one immutable payload + revision, including forks/ref overrides, local/offline behavior and existing + all-or-none ownership/receipt semantics; do not depend on developer checkouts. +- **FR-006**: Put product OpenSpec/Speckit/docs in spec and implementation plus + shipped skills/commands/tests in code; project workflow stays at root. +- **FR-007**: Continue selected feature deltas with old/new identity and + content receipts, paired leg worktrees and unchanged feature/role meanings. + Do not merge old monorepo branches over the adopted assembly. +- **FR-008**: Run canonical serialized tests and existing platform/CI policies + against explicitly selected compatible roots; preserve required checks and + prohibit silent context/dependency skips from claiming composed acceptance. +- **FR-009**: Land leg changes before the root pin bump; move gitlinks, pin + records/digests and applicable workflow SHAs consistently with standard tools. +- **FR-010**: Require a clean isolated source, available prerequisites, local + bare-remote rehearsal and explicit approval before real repository creation. +- **FR-011**: Preserve original worktrees and installed tools until cutover + acceptance; use non-destructive rollback and existing estate/WIP contracts. +- **FR-012**: Treat visibility, baseline, branch disposition and lane rebinding + as reviewed execution decisions; never infer approval from generated metadata. + +## Success criteria + +- **SC-001**: Every frozen baseline source path is accounted for exactly once; + no unapproved drops or content mismatches. +- **SC-002**: Every retained feature's selected spec/code/root delta and + dirty/untracked work has a verified receipt and preserved original. +- **SC-003**: Installation works through original entry points, offline and + fork/ref scenarios, using one code revision with unchanged artifact behavior. +- **SC-004**: Recursive bootstrap, paired feature workflow, canonical tests and + required CI pass for the selected composed project; no hidden skips. +- **SC-005**: A rehearsed rollback restores usable development/installation + without discarding work, altering private workspace pointers or force pushes. + +## Assumptions and approval + +Public new legs are proposed to match source visibility. Their creation is +not approved. `git-filter-repo` must be made available before rehearsal/execution; +it was absent in the inspected bench. The local constitution remains an +unfilled template and is not a ratified migration rule; repository/global +protocols and the pinned standard govern this plan. Refresh all snapshots +before execution. Source token/swap runtime gates are unaffected. diff --git a/specs/004-migrate-to-triad/tasks.md b/specs/004-migrate-to-triad/tasks.md new file mode 100644 index 00000000..4ce3039b --- /dev/null +++ b/specs/004-migrate-to-triad/tasks.md @@ -0,0 +1,124 @@ +# Implementation tasks: migrate openRepoTools to the triad + +The sole executable task list for the governing OpenSpec change. Planning +artifacts and preliminary mapping validation do not complete these tasks. +Every task remains open. Run implementation from the selected feature +worktrees; actual repository creation/cutover require the approval gates. + +## Phase 1 — Preservation and baseline (Gate A) + +- [ ] T001 [US1] Refresh `inventory.json`, current `status --fetch` output and + PR/branch/worktree metadata; resolve continuation/archive decisions for every + object in a host-local/private migration receipt. Verify no branch, detached + worktree or dirty/untracked/local-workflow content is omitted. +- [ ] T002 [US1] Coordinate owner breakpoints and preserve source refs/content, + ignored workflow configuration and installed receipts/config using the + existing estate/private backup contract. Verify restoration and per-object + digests, including all feature 001 edits and new files, without altering + workspace.yaml or broad process actions. +- [ ] T003 [US1] Confirm proposed leg names/visibility and inspect prerequisite + availability; regenerate `adoption-plan.yaml` for the reviewed preliminary + rehearsal source, retaining reasoned overrides. Verify standard `check` + passes and records all source paths with no unapproved drops. + +## Phase 2 — Local adoption rehearsal (Gate B foundation) + +- [ ] T004 [US1] Prepare a clean isolated source clone with no linked + worktrees and approved `git-filter-repo` availability; rehearse the standard + adoption against temporary local bare remotes. Verify source identity/history, + path/blob accounting and recoverability without real GitHub creation. +- [ ] T005 [US1] Exercise the existing nested submodule path, original + `.gitmodules` extraction/removal, pin integrity and recursive bootstrap. + Verify the code gitlink/pin/registration remain coupled. If standard tooling + refuses, record its refusal and resolve upstream before a tested pin bump; + never patch `upstream/openRepoShape` in place or weaken verification. +- [ ] T006 [US3] Resolve materialized root collisions and new leg guidance in + reviewable patches; bootstrap selected root workflow after manifest/legs + exist. Verify first-line shape guidance, relative paths, actual `.specify` + configuration and paired feature selection without copying machine secrets. + +## Phase 3 — Installation and checks (Gate B completion) + +- [ ] T007 [US2] Add the assembly `openRepoTools` entry point and coherent + payload-source resolution in the code installer after source byte accounting. + Verify gh/raw one-liners resolve one code pin and do not duplicate installer + mechanics or depend on developer checkouts after installation. +- [ ] T008 [US2] Cover local/offline, legacy monorepo overrides, adopted forks, + branch/commit refs, immutable code selection, missing/mismatched pins and + failed partial fetch. Verify unchanged command/artifact names, counts, + destinations/modes, hooks, ownership receipts and all-or-none refusal. +- [ ] T009 [US3] Separate code/spec/assembly/dependency roots in fixture and + hygiene consumers, including docs/OpenSpec/Speckit references. Verify the + existing upstream pin checks run against code Git identity and required + composed checks cannot silently skip absent spec/dependency context. +- [ ] T010 [US3] Adapt implementation CI and root exact-pin integration checks + with explicit compatible checkout context; preserve current Linux/macOS/ + Windows/WSL policies, Bash 3.2 parsing and serialized `tests/run.sh` locking. + Verify the exact rehearsed composed state passes required checks and the + compatibility matrix, recording failures rather than deleting assertions. +- [ ] T011 [US1] Rehearse restoration/rollback of the local candidate and + installed payload using preserved artifacts. Verify user work/jobs/claims + survive and no force push, destructive reset or workspace-pointer rewrite + is needed. Publish Gate A/B evidence and follow-up patch/commit inventory. + +## Phase 4 — Reviewed real adoption (Gates C and D) + +- [ ] T012 [US1] Freeze the coordinated source baseline and regenerate/check + the full plan after any prerequisite/planning landings. Obtain explicit + approval naming revisions, leg repositories/visibility, mapping, follow-ups + and work dispositions. Verify current name availability, preservation and + rehearsal evidence; refuse any source drift before execution. +- [ ] T013 [US1] Execute the approved standard adoption from the isolated + clone. Verify and relay the complete content-accounting table and root PR + details; stop landing on any refusal/mismatch, retaining all source/evidence. +- [ ] T014 [US3] Apply reviewed follow-ups through leg/root PRs, land required + leg commits, and advance root gitlinks/pins/workflow SHAs with standard tools. + Verify no in-place edits to copied pinned shape files or the mounted standard. +- [ ] T015 [US2] Validate the real exact assembled head using canonical tests, + required platform/CI, installed/local/raw compatibility, bootstrap and rollback + checks. Verify all Gate D results belong to the selected commits before root + adoption merge; keep original development/install available until then. + +## Phase 5 — Continue features and controlled cutover (Gate E) + +- [ ] T016 [US1] Translate the complete approved feature 001 delta and preserved + dirty/untracked work into paired `001` spec/code branches/worktrees with + reviewed root changes. Verify content/old-to-new receipts, roles, inventory + amendment and open runtime gates; do not replay completed work or claim new + runtime acceptance from migration. +- [ ] T017 [US1] Translate every other approved continued PR/branch/detached + worktree, including this migration feature, with explicit spec/code/root + mappings and conflict review. Verify each object has a complete receipt or + approved archived-original disposition; preserve original PR review history. +- [ ] T018 [US3] Exercise OpenSpec/Speckit feature selection and estate + park/resume in disposable triad fixtures, then perform reviewed binding/WIP + transitions through supported tools at owner breakpoints. Verify correct + feature roots/session bindings and relay refusals without force repairs. +- [ ] T019 [US3] Publish Gate E/cutover evidence and actual PR dispositions; + verify all continued features are usable and recoverable before requesting + separate old-worktree retirement. Do not auto-close old PRs or delete backups. + +## Dependencies + +T001–T003 precede rehearsal. 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. T013–T015 precede root adoption merge. T016–T018 can be prepared in +the candidate after legs exist, but actual lane rebinding follows reviewed +cutover and safe breakpoints. T019 requires validated retained feature receipts. + +## Requirement coverage + +| Requirement | Tasks | +| --- | --- | +| FR-001, FR-002 | T003–T005, T012–T013 | +| FR-003 | T001–T002, T016–T017 | +| FR-004 | T005, T009, T014 | +| FR-005 | T007–T008, T015 | +| FR-006 | T003, T006, T009 | +| FR-007 | T016–T018 | +| FR-008 | T009–T010, T015 | +| FR-009 | T014–T015 | +| FR-010 | T003–T005, T011–T013 | +| FR-011 | T002, T011, T018–T019 | +| FR-012 | T001, T012, T018–T019 | diff --git a/specs/004-migrate-to-triad/verification.md b/specs/004-migrate-to-triad/verification.md new file mode 100644 index 00000000..8d3a138e --- /dev/null +++ b/specs/004-migrate-to-triad/verification.md @@ -0,0 +1,42 @@ +# Migration planning verification — October 3, 2026 + +## Passing planning checks + +- Pinned openRepoShape `adopt-project.py check` passed for the preliminary + source main `c1bac0dfc99a62583cb62eafc93a192911b2ff22` and resolved mapping: + 58 source paths, 17 spec / 35 code / six root, no unresolved path or drop. + Naming recognizes the existing root as neutral-product/assembly and the + proposed repositories as spec/code legs. The plan lists 21 follow-ups. +- `openspec validate migrate-to-triad --strict` passed in `py-bench`. + `openspec status` reports all four governance planning artifacts complete. +- `git diff --check` passed. Supplemental checks cover newly created planning + files, local Markdown targets, host-absolute path exclusion, valid inventory + JSON, unique task IDs and requirement coverage. +- All 19 executable migration tasks remain open. The main checkout is clean; + planning artifacts live only in feature `004-migrate-to-triad`. + +## Snapshot and interpretation + +`inventory.json` records 12 registered worktrees and open PRs #134, #121, #97 +and #61. Feature 001 has dirty/untracked content, including work from this +conversation and concurrent planning. Preserve its complete current contents +at the execution gate; the public snapshot does not contain a backup. + +The generated adoption plan was resolved with written placement reasons and +normalized to relative source paths. It is a preliminary main-only mapping, +not a mapping of all feature work. Regenerate after planning/prerequisite +landings and before frozen-baseline approval. Custom planning/authorization +fields document scope; the standard does not enforce them as execution guards. + +## Not performed or claimed + +No local history extraction/adoption rehearsal, runtime regression suite, +installer changes, real repository creation, software installation, root/leg +PR creation or merge, lane move, WIP pointer rewrite or migration occurred. +`git-filter-repo` was absent in the inspected bench. Existing nested-submodule +handling and actual composed tests remain required Gate B/D evidence. + +Planning validity does not establish execution readiness or approve proposed +public visibility. The standard's procedure requires the reviewed plan and +follow-ups to receive an explicit yes before real adoption. Original work, +experimental swap gates and existing PR review decisions remain preserved. From 8aa119fd5c4286ff836ee2c9c6ee141859cb3710 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Sat, 3 Oct 2026 22:14:21 +0000 Subject: [PATCH 02/12] docs: refresh triad migration plan after worktree cleanup --- .../migrate-to-triad/adoption-plan.yaml | 24 +- openspec/changes/migrate-to-triad/design.md | 14 +- openspec/changes/migrate-to-triad/proposal.md | 8 +- specs/004-migrate-to-triad/inventory.json | 227 +++++++++++------- specs/004-migrate-to-triad/plan.md | 40 ++- specs/004-migrate-to-triad/research.md | 7 +- specs/004-migrate-to-triad/tasks.md | 15 +- specs/004-migrate-to-triad/verification.md | 36 ++- 8 files changed, 252 insertions(+), 119 deletions(-) diff --git a/openspec/changes/migrate-to-triad/adoption-plan.yaml b/openspec/changes/migrate-to-triad/adoption-plan.yaml index c32025d1..ec7eb3f9 100644 --- a/openspec/changes/migrate-to-triad/adoption-plan.yaml +++ b/openspec/changes/migrate-to-triad/adoption-plan.yaml @@ -8,10 +8,10 @@ source: repository: opensoft/openRepoTools local_path: . default_branch: main - commit: c1bac0dfc99a62583cb62eafc93a192911b2ff22 + commit: "82ecebee13edaa915b68550170faffdf761754d5" files: 58 - bytes: 4202017 - commits: 77 + bytes: 4339687 + commits: 79 mode: in-place project: openRepoTools org: opensoft @@ -126,7 +126,7 @@ 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: 1 - bytes: 182097 + bytes: 187100 review_required: false - path: lane leg: code @@ -144,7 +144,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: 93296 + bytes: 119587 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." @@ -194,7 +194,7 @@ 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: 759480 + bytes: 807509 review_required: false - path: link-estates leg: code @@ -287,7 +287,7 @@ paths: 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: 12 - bytes: 1880040 + bytes: 1938387 review_required: false - path: upstream/ leg: code @@ -324,19 +324,19 @@ follow_ups: summary: spec: files: 17 - bytes: 202997 + bytes: 208000 file_share: 0.2931 - byte_share: 0.0483 + byte_share: 0.0479 code: files: 35 - bytes: 3934978 + bytes: 4067645 file_share: 0.6034 - byte_share: 0.9364 + byte_share: 0.9373 root: files: 6 bytes: 64042 file_share: 0.1034 - byte_share: 0.0152 + byte_share: 0.0148 unresolved: files: 0 bytes: 0 diff --git a/openspec/changes/migrate-to-triad/design.md b/openspec/changes/migrate-to-triad/design.md index 691aeee7..6579bce0 100644 --- a/openspec/changes/migrate-to-triad/design.md +++ b/openspec/changes/migrate-to-triad/design.md @@ -2,11 +2,15 @@ ## Context -The preliminary source is main `c1bac0dfc99a62583cb62eafc93a192911b2ff22`: -58 tracked paths, 77 commits, one nested standard submodule. The inspected -standard is `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. There are 12 registered -worktrees including this planning checkout, and four open PRs. Feature 001 has -dirty/untracked work; an extraction of main alone would omit it. The +The refreshed preliminary source is main `82ecebee13edaa915b68550170faffdf761754d5`: +58 tracked paths, 79 commits, one nested standard submodule. The inspected +standard is `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. Cleanup initially left +five registered worktrees; reopening the preserved planning checkout made +six, then concurrent cleanup removed the merged #146 checkout. There are now +five worktrees including planning. The three open PRs are #134, #121 and #97; +#61 and #146 are included in main and need no separate replay. +Feature 001 at `c0b571c` has dirty/untracked work, so main extraction alone +would omit it. Removed worktrees are not an active replay queue. The [inventory](../../../specs/004-migrate-to-triad/inventory.json) is a snapshot. ## Goals / Non-Goals diff --git a/openspec/changes/migrate-to-triad/proposal.md b/openspec/changes/migrate-to-triad/proposal.md index 8253222b..3ffdd9ba 100644 --- a/openspec/changes/migrate-to-triad/proposal.md +++ b/openspec/changes/migrate-to-triad/proposal.md @@ -63,6 +63,12 @@ existing changes; this migration does not activate experimental capabilities. Requested on October 3, 2026. Planning is authorized; migration execution, repository creation, software installation, PR merge and lane relocation are not authorized by this request. The attached adoption plan is a preliminary -mapping of source main `c1bac0dfc99a62583cb62eafc93a192911b2ff22`, not a promise +mapping regenerated from source main `82ecebee13edaa915b68550170faffdf761754d5`, not a promise that this will be the final split commit. Refresh after planning lands and the cutover baseline is frozen. No runtime or migration success is claimed. + +The cleanup refresh records five worktrees before editing, six after reopening +the planning checkout, then five after concurrent cleanup removed the merged +#146 checkout. It removes retired worktrees from active migration and accounts +for both #61 and #146 through main. Feature 001 and remote-only drafts/preservation refs retain +their explicit preservation/review requirements. diff --git a/specs/004-migrate-to-triad/inventory.json b/specs/004-migrate-to-triad/inventory.json index 77254dad..d9719707 100644 --- a/specs/004-migrate-to-triad/inventory.json +++ b/specs/004-migrate-to-triad/inventory.json @@ -1,156 +1,219 @@ { - "observed_at": "2026-10-03T17:50:46.499925+00:00", + "observed_at": "2026-10-03T22:12:05.918851+00:00", "source_repository": "opensoft/openRepoTools", - "source_main": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "source_main": "82ecebee13edaa915b68550170faffdf761754d5", + "github_main": "82ecebee13edaa915b68550170faffdf761754d5", + "github_main_matches_local": true, "standard_commit": "39d5c986fcfac1a160474bfe91c5f1c37fccc72c", + "cleanup_summary": { + "previous_snapshot_worktrees": 12, + "worktrees_before_refresh": 5, + "local_branches_before_refresh": 6, + "worktrees_after_reopening_before_concurrent_cleanup": 6, + "registered_worktrees_including_reopened_planning_checkout": 5, + "local_branches_after_concurrent_cleanup": 5, + "planning_checkout_reopened": "004-migrate-to-triad", + "removed_before_refresh": [ + { + "identity": "lclaude-finalize", + "previous_head": "7e4dc31c4571cf8d7b11e24941568edf66f82a94", + "local_branch_present": false + }, + { + "identity": "detached-08dad90a67bc", + "previous_head": "08dad90a67bc6699283589c2222c53833a6603cd", + "local_branch_present": false + }, + { + "identity": "002-skip-no-lane-guard", + "previous_head": "a2861bbdf0bf4793108bf3b2da2fc65f38d642bd", + "local_branch_present": false + }, + { + "identity": "003-binary-only-guard-runner", + "previous_head": "42860a93be192f025a725708d7a016083ff82923", + "local_branch_present": false + }, + { + "identity": "004-migrate-to-triad", + "previous_head": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "local_branch_present": true + }, + { + "identity": "chore/preserve-local-planning-20261003", + "previous_head": "135c18b258d02136ed834e5a446e552db385d50c", + "local_branch_present": false + }, + { + "identity": "detached-92eab6c4fa2e", + "previous_head": "92eab6c4fa2e68f7e2202d529ee0f2e4bebce874", + "local_branch_present": false + }, + { + "identity": "fix/claim-takeover-and-retire-fork", + "previous_head": "3de40b1865d31d3bb96a52e3822c1386c9e52634", + "local_branch_present": false + } + ], + "new_worktrees_since_previous_snapshot": [], + "worktrees_after_concurrent_cleanup_excluding_planning_checkout": 4, + "removed_during_refresh": [ + { + "identity": "fix/107-pty-driver-bound-and-lane-per-call-cost", + "previous_head": "da0e5bb257b3b2b60a57ca544b7c75528c97f2a5", + "local_branch_present": false, + "reason": "PR #146 merged into main; concurrent cleanup removed checkout and local branch." + } + ] + }, "worktrees": [ { "identity": "main", - "head": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", + "head": "82ecebee13edaa915b68550170faffdf761754d5", "layout": "root", "readable_here": true, "dirty_entries": 0, + "untracked_entries": 0, "locked": false, "prunable": false }, { - "identity": "lclaude-finalize", - "head": "7e4dc31c4571cf8d7b11e24941568edf66f82a94", - "layout": "legacy-sibling", - "readable_here": true, - "dirty_entries": 0, - "locked": false, - "prunable": false - }, - { - "identity": "detached-08dad90a67bc", - "head": "08dad90a67bc6699283589c2222c53833a6603cd", + "identity": "001-separate-swap-ctx-handoff", + "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b", "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 0, + "dirty_entries": 18, + "untracked_entries": 1, "locked": false, "prunable": false }, { - "identity": "001-separate-swap-ctx-handoff", - "head": "fc5105b5371082c966c151f4bc08bfdabf64539b", + "identity": "004-migrate-to-triad", + "head": "52ce64ee7787b62bf015e13cbf663f305513093e", "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 22, + "dirty_entries": 8, + "untracked_entries": 0, "locked": false, "prunable": false }, { - "identity": "002-skip-no-lane-guard", - "head": "a2861bbdf0bf4793108bf3b2da2fc65f38d642bd", - "layout": "legacy-sibling", + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "layout": "legacy-nested", "readable_here": true, "dirty_entries": 0, + "untracked_entries": 0, "locked": false, "prunable": false }, { - "identity": "003-binary-only-guard-runner", - "head": "42860a93be192f025a725708d7a016083ff82923", - "layout": "legacy-sibling", + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "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": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b" }, { "identity": "004-migrate-to-triad", - "head": "c1bac0dfc99a62583cb62eafc93a192911b2ff22", - "layout": "legacy-sibling", - "readable_here": true, - "dirty_entries": 2, - "locked": false, - "prunable": false + "head": "52ce64ee7787b62bf015e13cbf663f305513093e" }, { - "identity": "chore/preserve-local-planning-20261003", - "head": "135c18b258d02136ed834e5a446e552db385d50c", - "layout": "legacy-sibling", - "readable_here": true, - "dirty_entries": 0, - "locked": false, - "prunable": false + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e" }, { - "identity": "detached-92eab6c4fa2e", - "head": "92eab6c4fa2e68f7e2202d529ee0f2e4bebce874", - "layout": "legacy-nested", - "readable_here": true, - "dirty_entries": 0, - "locked": false, - "prunable": false + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295" }, { - "identity": "fix/claim-takeover-and-retire-fork", - "head": "3de40b1865d31d3bb96a52e3822c1386c9e52634", - "layout": "legacy-nested", - "readable_here": true, - "dirty_entries": 0, - "locked": false, - "prunable": false + "identity": "main", + "head": "82ecebee13edaa915b68550170faffdf761754d5" + } + ], + "remote_only_branches": [ + { + "identity": "chore/preserve-local-planning-20261003", + "head": "135c18b258d02136ed834e5a446e552db385d50c", + "currency": "local remote-tracking observation; not fetched during refresh" }, { - "identity": "feat/supervised-context-restart", - "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", - "layout": "legacy-nested", - "readable_here": true, - "dirty_entries": 0, - "locked": false, - "prunable": false + "identity": "feat/claude-current", + "head": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", + "currency": "local remote-tracking observation; not fetched during refresh" }, { - "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", - "layout": "legacy-nested", - "readable_here": true, - "dirty_entries": 0, - "locked": false, - "prunable": false + "identity": "takeover/ort-a9-dirty-snapshot-20260913", + "head": "607aee7551a5a7db7e57e294aba193fbc8a8a266", + "currency": "local remote-tracking observation; not fetched during refresh" } ], "open_prs": [ { + "number": 134, + "title": "claude-current and claude-restart-check: every launch starts the newest published Claude Code by absolute path, and a running session is told when its binary moved (opensoft/workBenches#119)", "headRefName": "feat/claude-current", "headRefOid": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", "isDraft": true, - "number": 134, - "title": "claude-current and claude-restart-check: every launch starts the newest published Claude Code by absolute path, and a running session is told when its binary moved (opensoft/workBenches#119)", - "url": "https://github.com/opensoft/openRepoTools/pull/134" + "url": "https://github.com/opensoft/openRepoTools/pull/134", + "state": "open" }, { + "number": 121, + "title": "`/ctx` writes its restart to disk before it kills anything, and what tmux starts is a supervisor that stays in the pane \u2014 the fresh session was an environment variable the launcher dropped (#94)", "headRefName": "feat/supervised-context-restart", "headRefOid": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", "isDraft": false, - "number": 121, - "title": "`/ctx` writes its restart to disk before it kills anything, and what tmux starts is a supervisor that stays in the pane \u2014 the fresh session was an environment variable the launcher dropped (#94)", - "url": "https://github.com/opensoft/openRepoTools/pull/121" + "url": "https://github.com/opensoft/openRepoTools/pull/121", + "state": "open" }, { + "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": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", "isDraft": false, - "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", - "url": "https://github.com/opensoft/openRepoTools/pull/97" - }, + "url": "https://github.com/opensoft/openRepoTools/pull/97", + "state": "open" + } + ], + "merged_since_previous_snapshot": [ { - "headRefName": "fix/claim-takeover-and-retire-fork", - "headRefOid": "3de40b1865d31d3bb96a52e3822c1386c9e52634", - "isDraft": false, "number": 61, - "title": "claim --force takes over a dead lane's hold; lane-end --retire ends a duplicate holder", - "url": "https://github.com/opensoft/openRepoTools/pull/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." } ], + "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.", - "Dirty/untracked work in feature 001 includes edits from this conversation and concurrent planning; preserve the complete current contents.", - "Raw preservation backups must be host-local or in the designated private WIP repository; public planning records hold identity/digest receipts only." + "Feature 001 retains dirty/untracked work including current broker/task-recovery planning; preserve its complete current contents.", + "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." ] } diff --git a/specs/004-migrate-to-triad/plan.md b/specs/004-migrate-to-triad/plan.md index 1e17ce07..27bd12b6 100644 --- a/specs/004-migrate-to-triad/plan.md +++ b/specs/004-migrate-to-triad/plan.md @@ -2,22 +2,33 @@ **Feature**: `004-migrate-to-triad` | **Date**: 2026-10-03 **State**: Proposed plan; no migration, install or repository creation performed +**Refresh**: October 3 cleanup; current source main and active-work queue rechecked **Spec**: [spec.md](spec.md) **Governance**: [proposal](../../openspec/changes/migrate-to-triad/proposal.md) ## Baseline and deliverables The [adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) -is generated from main `c1bac0dfc99a62583cb62eafc93a192911b2ff22` using pinned +is regenerated from main `82ecebee13edaa915b68550170faffdf761754d5` using pinned openRepoShape `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. All 58 tracked paths are resolved: 17 spec, 35 code, six root, zero dropped. There are 21 named follow-ups. This is an inspected preliminary baseline; regenerate after planning lands and the actual cutover source is frozen. -The [inventory](inventory.json) records 12 worktrees (including migration -planning), four open PRs and dirty feature 001 work. It omits machine paths, -secrets/transcripts and backup contents. Host-local/private preservation -records must capture actual paths, content and digests at the execution gate. +Cleanup initially reduced the original 12-worktree snapshot to five registered +worktrees. Reopening the preserved `004` branch made six; concurrent cleanup +then removed the merged PR #146 checkout. There are now five worktrees, +including this planning checkout, and five local branches. The +[inventory](inventory.json) records those transitions, three open PRs (#134, +#121, #97), remote-only refs and retired-worktree history. Main includes merged +PRs #61 and #146 and matches the read-only GitHub main observation. Feature 001 at +`c0b571c5fa1c1446f143ce4f00f39db7cb7a166b` still has dirty/untracked broker +and task-recovery planning work. Machine paths, secrets/transcripts and backup +contents are omitted; private receipts must capture them at the execution gate. + +Cleanup does not require recreating removed worktrees. Continue only the +retained work below, and verify existing preservation receipts for retired +objects. Snapshot refresh alone does not complete preservation Gate A. ## Target placement @@ -37,8 +48,11 @@ one-liner and installed command names. Do not duplicate installer mechanics. ## Phase 1 — Review and preserve work Land the planning artifacts through normal review before freezing execution. -Refresh current estate status using `status --fetch`, open PR metadata and -branch/worktree observations. Verify the two proposed leg names are available +Refresh GitHub PR/main observations and local branch/worktree state. This +single repository has no estate manifest yet: `status --fetch openRepoTools` +currently refuses with no estate named openRepoTools and performs no fetch. +Relay that refusal; do not run `resume` to silence it. Use the estate status +surface after a valid adopted root exists. Verify the proposed leg names are available and decide visibility. Agree a bounded cutover with current lane owners. Capture original history, all branch refs, detached HEADs, staged/unstaged and untracked content, ignored workflow config and installed receipts/config. @@ -50,13 +64,15 @@ Recommended active-work dispositions are proposals, not merge/closure actions: | Work | Proposed treatment | | --- | --- | -| `001-separate-swap-ctx-handoff` | Preserve full branch delta and dirty/untracked additions; migrate to paired `001` spec/code worktrees. Keep tasks, evidence, roles and activation gates. | -| `002-skip-no-lane-guard`, `003-binary-only-guard-runner` | Inspect remaining deltas versus main; migrate useful unfinished work or retain archived branch receipts if already landed. | +| `001-separate-swap-ctx-handoff` | Continue from current head `c0b571c`, preserving its full delta and dirty/untracked broker/task-recovery additions; migrate to paired `001` worktrees. Keep tasks, evidence, roles and activation gates. | | PR #97 | Preserve branch/review; carry useful diagnostics into feature 001 under its service authority. Do not merge unchanged or auto-close as part of adoption. | | PR #121 | Preserve/review independently; translate selected context-runtime work to code/spec as needed, with its readiness integration still explicit. | -| PR #134 (draft), PR #61 | Keep current heads and review history; continue selected deltas in new legs after owner review. No automatic merge or abandonment. | -| Other branches/detached worktrees/preservation branch | Inspect individually, assign continue/archive decision, retain recovery receipt; no deletion implied. | -| Migration feature `004` | Carry this plan/spec/tasks into the spec leg; assembly/code follow-ups get separate reviewed changes. Keep its own pre-migration recovery receipt. | +| PR #146 / `fix/107-pty-driver-bound-and-lane-per-call-cost` | Merged as `82ecebe`; checkout and local branch removed during concurrent cleanup. Included by baseline extraction; do not replay separately. | +| PR #134 (draft) | Open at `715b7ac`, with a remote branch but no local worktree. Review retained changes from its branch; no checkout recreation is required just to inventory it. | +| PR #61 | Merged as `14641fd`, an ancestor of current main; included by baseline extraction. Do not replay the retired claim-takeover branch separately. | +| Retired `002`, `003`, lclaude and detached worktrees | Removed from current registrations/local branches by cleanup. Verify cleanup/preservation receipts; remove from the active replay queue and do not recreate them from the old snapshot. | +| Remote-only preservation refs | `chore/preserve-local-planning-20261003` and `takeover/ort-a9-dirty-snapshot-20260913` remain locally observed remote-tracking refs with no checkout; review as preservation history, not active writers. | +| Migration feature `004` | Drafts were preserved at `52ce64e`; its checkout was reopened only for this refresh. Carry current plan/spec/tasks into spec; review assembly/code follow-ups separately. | **Gate A:** every preserved object is attributable and restorable; no active writer can silently invalidate capture. Baseline, visibility and work diff --git a/specs/004-migrate-to-triad/research.md b/specs/004-migrate-to-triad/research.md index 2a2f1e04..0cb77876 100644 --- a/specs/004-migrate-to-triad/research.md +++ b/specs/004-migrate-to-triad/research.md @@ -7,11 +7,14 @@ No external writes, repositories, installation or migration occurred. | Finding | Decision / execution consequence | | --- | --- | -| Source main has 58 tracked paths and one standard gitlink | Use exact preliminary mapping and refresh the final baseline. | +| Source main advanced to `82ecebe` (79 commits), still 58 tracked paths and one standard gitlink | Regenerate the mapping from the source; #61 and #146 are included without replay. | | Classifier treats shipped Markdown skills/commands as specification | Override to code with written reasons; these are installation payloads. | | Original contract is the implementation's upstream dependency lock | Keep code pin/gitlink/.gitmodules together; generated assembly pins are separate. | | `.specify` and agent directories are ignored local scaffolding | Preserve local config separately and regenerate root workflow after adoption. | -| Twelve worktrees and four open PRs; feature 001 is dirty | Source-main extraction is insufficient; preserve and map retained feature deltas. | +| Cleanup initially left five worktrees; reopening planning made six, then merged #146's checkout was removed; now five worktrees and open PRs #134/#121/#97 | Reduce the active replay queue; do not recreate retired `002`/`003`, lclaude, detached, claim-takeover or #146 checkouts. | +| Feature 001 at `c0b571c` still has dirty/untracked broker/task-recovery work | Preserve its current complete delta/content, not the previous snapshot. | +| Draft #134 and preservation refs have no local worktrees | Review retained branch history without treating it as an active writer or requiring recreation. | +| Estate status refuses this manifest-free single repository | Relay no-estate refusal; use local Git and read-only GitHub observations now, then estate status after adoption. | | Installer fetches bare paths from `openRepoTools` and local sibling payloads | Preserve public root entry point and bind every payload to one code pin. | | Tests conflate repo, spec and dependency paths | Introduce explicit checkout context and composed CI, preserving nested-pin tests. | | `git-filter-repo` absent in inspected bench | Execution prerequisite; no software installation was performed for planning. | diff --git a/specs/004-migrate-to-triad/tasks.md b/specs/004-migrate-to-triad/tasks.md index 4ce3039b..40cabc07 100644 --- a/specs/004-migrate-to-triad/tasks.md +++ b/specs/004-migrate-to-triad/tasks.md @@ -4,12 +4,18 @@ The sole executable task list for the governing OpenSpec change. Planning artifacts and preliminary mapping validation do not complete these tasks. Every task remains open. Run implementation from the selected feature worktrees; actual repository creation/cutover require the approval gates. +The cleanup refresh updates the snapshot/mapping portion of T001/T003 only; +owner decisions, private preservation/restore receipts and execution gates +remain pending. Retired checkouts are not instructions to recreate worktrees. ## Phase 1 — Preservation and baseline (Gate A) -- [ ] T001 [US1] Refresh `inventory.json`, current `status --fetch` output and - PR/branch/worktree metadata; resolve continuation/archive decisions for every - object in a host-local/private migration receipt. Verify no branch, detached +- [ ] T001 [US1] Refresh `inventory.json`, PR/main/branch/worktree metadata and + applicable estate-status output; distinguish retained work from retired + cleanup records and remote-only drafts. Until an estate manifest exists, + relay `status --fetch openRepoTools`'s no-estate refusal without invoking + `resume`. Resolve continuation/archive decisions for every retained object + in a host-local/private migration receipt. Verify no branch, detached worktree or dirty/untracked/local-workflow content is omitted. - [ ] T002 [US1] Coordinate owner breakpoints and preserve source refs/content, ignored workflow configuration and installed receipts/config using the @@ -90,6 +96,9 @@ worktrees; actual repository creation/cutover require the approval gates. worktree, including this migration feature, with explicit spec/code/root mappings and conflict review. Verify each object has a complete receipt or approved archived-original disposition; preserve original PR review history. + Current candidates are #97/#121/#134 and feature 004. Account for merged + #61/#146 through the baseline and retired checkout history through its receipts; + do not recreate cleaned worktrees or replay integrated changes. - [ ] T018 [US3] Exercise OpenSpec/Speckit feature selection and estate park/resume in disposable triad fixtures, then perform reviewed binding/WIP transitions through supported tools at owner breakpoints. Verify correct diff --git a/specs/004-migrate-to-triad/verification.md b/specs/004-migrate-to-triad/verification.md index 8d3a138e..56574301 100644 --- a/specs/004-migrate-to-triad/verification.md +++ b/specs/004-migrate-to-triad/verification.md @@ -1,5 +1,37 @@ # Migration planning verification — October 3, 2026 +## Cleanup refresh + +The refreshed source main is `82ecebee13edaa915b68550170faffdf761754d5`, +including merged PRs #61 and #146. Read-only GitHub REST main matched local +main; the live open list is #134, #121 and #97. The initial GraphQL list +returned HTTP 503; the REST list succeeded. This refresh performed no merge/closure. + +Cleanup initially left five registered worktrees and six local branches. The preserved +migration draft branch `004-migrate-to-triad` was retained separately at +`52ce64e` without a checkout; reopening it made six worktrees. During validation, +#146 merged and concurrent cleanup removed its checkout and local branch, +leaving five worktrees (including planning) and five local branches. The +refreshed inventory includes those transitions, current +heads/dirty counts, remote-only refs and retired-worktree history. Removed +checkouts are excluded from active replay and are not recreated by the plan. +Feature 001 at `c0b571c` remains dirty with current broker/task-recovery work. + +The mapping was regenerated by the pinned standard, retaining reasoned +resolutions, rather than editing its source commit. The baseline remains 58 +tracked paths: 17 spec, 35 code, six root, zero dropped, with 79 commits and +21 follow-ups. The first standard `check` detected main moving from `14641fd` +to `82ecebe`; the plan was regenerated again. Standard `check`, OpenSpec strict +validation and supplemental document/inventory checks passed; no runtime suite or +local adoption rehearsal is claimed. All 19 execution tasks remain open. + +`status --fetch openRepoTools` refused: no estate named openRepoTools under +the projects directory (there is no estate manifest yet). It fetched nothing. +The refresh used local Git plus read-only GitHub main/PR observations and did +not run `resume`, change workspace pointers or manually fetch to quiet it. + +The original verification and snapshot below are historical evidence only. + ## Passing planning checks - Pinned openRepoShape `adopt-project.py check` passed for the preliminary @@ -17,8 +49,8 @@ ## Snapshot and interpretation -`inventory.json` records 12 registered worktrees and open PRs #134, #121, #97 -and #61. Feature 001 has dirty/untracked content, including work from this +The original inventory snapshot recorded 12 registered worktrees and open PRs +#134, #121, #97 and #61. Feature 001 had dirty/untracked content, including work from this conversation and concurrent planning. Preserve its complete current contents at the execution gate; the public snapshot does not contain a backup. From dda91f11c68818ebeca4264d88908c85818ff630 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Sun, 4 Oct 2026 16:41:17 +0000 Subject: [PATCH 03/12] docs: refresh triad plan for October 4 feature updates --- .../migrate-to-triad/adoption-plan.yaml | 4 +- openspec/changes/migrate-to-triad/design.md | 16 +- openspec/changes/migrate-to-triad/proposal.md | 13 +- specs/004-migrate-to-triad/inventory.json | 137 +++++++++++++++--- specs/004-migrate-to-triad/plan.md | 46 +++--- specs/004-migrate-to-triad/research.md | 12 +- specs/004-migrate-to-triad/tasks.md | 17 ++- specs/004-migrate-to-triad/verification.md | 32 +++- 8 files changed, 213 insertions(+), 64 deletions(-) diff --git a/openspec/changes/migrate-to-triad/adoption-plan.yaml b/openspec/changes/migrate-to-triad/adoption-plan.yaml index ec7eb3f9..7baf5e8a 100644 --- a/openspec/changes/migrate-to-triad/adoption-plan.yaml +++ b/openspec/changes/migrate-to-triad/adoption-plan.yaml @@ -2,7 +2,7 @@ # Paths are relative to the source checkout. Generated metadata does not authorize repository creation. schema_version: 1 kind: adoption-plan -generated_on: "2026-10-03" +generated_on: "2026-10-04" tool: "opensoft/openRepoShape adopt-project.py" source: repository: opensoft/openRepoTools @@ -20,7 +20,7 @@ visibility: public tracking_branch: main adopt_branch: adopt/three-repo-shape elected_by: "Brett Heap" -elected_on: "2026-10-03" +elected_on: "2026-10-04" reference: "openxFactory docs/project-repo-schema.md" legs: assembly: openRepoTools diff --git a/openspec/changes/migrate-to-triad/design.md b/openspec/changes/migrate-to-triad/design.md index 6579bce0..b8d27815 100644 --- a/openspec/changes/migrate-to-triad/design.md +++ b/openspec/changes/migrate-to-triad/design.md @@ -4,13 +4,15 @@ The refreshed preliminary source is main `82ecebee13edaa915b68550170faffdf761754d5`: 58 tracked paths, 79 commits, one nested standard submodule. The inspected -standard is `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. Cleanup initially left -five registered worktrees; reopening the preserved planning checkout made -six, then concurrent cleanup removed the merged #146 checkout. There are now -five worktrees including planning. The three open PRs are #134, #121 and #97; -#61 and #146 are included in main and need no separate replay. -Feature 001 at `c0b571c` has dirty/untracked work, so main extraction alone -would omit it. Removed worktrees are not an active replay queue. The +standard is `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. The October 4 refresh +found unchanged main, six worktrees including planning and the restored +`feat/claude-current` checkout, and six local branches. The three open PRs +are #134, #121 and #97; #134 is non-draft at `11037f0`. #61 and #146 are +included in main and need no separate replay. Feature 001 is now committed +and clean at `3c26041`, including restored rollover/workspace packets and the +selected local Omnigent launcher contract. Main extraction alone still omits +that branch work. Preserve its contracts, external launcher ownership and +unmet runtime gates during replay. Removed worktrees are not an active replay queue. The [inventory](../../../specs/004-migrate-to-triad/inventory.json) is a snapshot. ## Goals / Non-Goals diff --git a/openspec/changes/migrate-to-triad/proposal.md b/openspec/changes/migrate-to-triad/proposal.md index 3ffdd9ba..5d607d39 100644 --- a/openspec/changes/migrate-to-triad/proposal.md +++ b/openspec/changes/migrate-to-triad/proposal.md @@ -67,8 +67,11 @@ mapping regenerated from source main `82ecebee13edaa915b68550170faffdf761754d5`, that this will be the final split commit. Refresh after planning lands and the cutover baseline is frozen. No runtime or migration success is claimed. -The cleanup refresh records five worktrees before editing, six after reopening -the planning checkout, then five after concurrent cleanup removed the merged -#146 checkout. It removes retired worktrees from active migration and accounts -for both #61 and #146 through main. Feature 001 and remote-only drafts/preservation refs retain -their explicit preservation/review requirements. +The October 4 refresh retains the October 3 cleanup history and records six +current worktrees, including the restored PR #134 checkout. #134 is now +non-draft at `11037f0`; feature 001 is committed and clean at `3c26041` with +restored rollover/workspace packets and the selected local launcher contract. +All checkouts were clean before planning edits. Both #61 and #146 remain +included through unchanged main. Continued feature branches and the two +remote-only preservation refs still require preservation/review receipts; +repository adoption does not implement or activate the feature 001 launch stack. diff --git a/specs/004-migrate-to-triad/inventory.json b/specs/004-migrate-to-triad/inventory.json index d9719707..efdb0aff 100644 --- a/specs/004-migrate-to-triad/inventory.json +++ b/specs/004-migrate-to-triad/inventory.json @@ -1,5 +1,5 @@ { - "observed_at": "2026-10-03T22:12:05.918851+00:00", + "observed_at": "2026-10-04T16:37:26.292668+00:00", "source_repository": "opensoft/openRepoTools", "source_main": "82ecebee13edaa915b68550170faffdf761754d5", "github_main": "82ecebee13edaa915b68550170faffdf761754d5", @@ -64,7 +64,8 @@ "local_branch_present": false, "reason": "PR #146 merged into main; concurrent cleanup removed checkout and local branch." } - ] + ], + "currency": "Historical October 3 cleanup only; use latest_refresh and worktrees for current counts." }, "worktrees": [ { @@ -79,20 +80,30 @@ }, { "identity": "001-separate-swap-ctx-handoff", - "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b", + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5", "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 18, - "untracked_entries": 1, + "dirty_entries": 0, + "untracked_entries": 0, "locked": false, "prunable": false }, { "identity": "004-migrate-to-triad", - "head": "52ce64ee7787b62bf015e13cbf663f305513093e", + "head": "8aa119fd5c4286ff836ee2c9c6ee141859cb3710", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 1, + "untracked_entries": 0, + "locked": false, + "prunable": false + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 8, + "dirty_entries": 0, "untracked_entries": 0, "locked": false, "prunable": false @@ -121,11 +132,15 @@ "local_branches": [ { "identity": "001-separate-swap-ctx-handoff", - "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b" + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5" }, { "identity": "004-migrate-to-triad", - "head": "52ce64ee7787b62bf015e13cbf663f305513093e" + "head": "8aa119fd5c4286ff836ee2c9c6ee141859cb3710" + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12" }, { "identity": "feat/crash-consistent-lane-worktree-recovery", @@ -146,11 +161,6 @@ "head": "135c18b258d02136ed834e5a446e552db385d50c", "currency": "local remote-tracking observation; not fetched during refresh" }, - { - "identity": "feat/claude-current", - "head": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", - "currency": "local remote-tracking observation; not fetched during refresh" - }, { "identity": "takeover/ort-a9-dirty-snapshot-20260913", "head": "607aee7551a5a7db7e57e294aba193fbc8a8a266", @@ -160,10 +170,10 @@ "open_prs": [ { "number": 134, - "title": "claude-current and claude-restart-check: every launch starts the newest published Claude Code by absolute path, and a running session is told when its binary moved (opensoft/workBenches#119)", + "title": "Launch current Claude Code and report stale running sessions", "headRefName": "feat/claude-current", - "headRefOid": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", - "isDraft": true, + "headRefOid": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "isDraft": false, "url": "https://github.com/opensoft/openRepoTools/pull/134", "state": "open" }, @@ -210,10 +220,99 @@ "limitations": [ "Snapshot only; refresh before baseline freeze and cutover.", "Physical paths, credentials, transcript bodies and WIP data are omitted.", - "Feature 001 retains dirty/untracked work including current broker/task-recovery planning; preserve its complete current contents.", + "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." - ] + ], + "previous_refresh_snapshot": { + "observed_at": "2026-10-03T22:12:05.918851+00:00", + "source_main": "82ecebee13edaa915b68550170faffdf761754d5", + "worktrees": [ + { + "identity": "main", + "head": "82ecebee13edaa915b68550170faffdf761754d5", + "dirty_entries": 0, + "untracked_entries": 0 + }, + { + "identity": "001-separate-swap-ctx-handoff", + "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b", + "dirty_entries": 18, + "untracked_entries": 1 + }, + { + "identity": "004-migrate-to-triad", + "head": "52ce64ee7787b62bf015e13cbf663f305513093e", + "dirty_entries": 8, + "untracked_entries": 0 + }, + { + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "dirty_entries": 0, + "untracked_entries": 0 + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "dirty_entries": 0, + "untracked_entries": 0 + } + ], + "local_branches": [ + { + "identity": "001-separate-swap-ctx-handoff", + "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b" + }, + { + "identity": "004-migrate-to-triad", + "head": "52ce64ee7787b62bf015e13cbf663f305513093e" + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e" + }, + { + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295" + }, + { + "identity": "main", + "head": "82ecebee13edaa915b68550170faffdf761754d5" + } + ], + "open_prs": [ + { + "number": 134, + "headRefName": "feat/claude-current", + "headRefOid": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", + "isDraft": true + }, + { + "number": 121, + "headRefName": "feat/supervised-context-restart", + "headRefOid": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "isDraft": false + }, + { + "number": 97, + "headRefName": "feat/crash-consistent-lane-worktree-recovery", + "headRefOid": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "isDraft": false + } + ] + }, + "latest_refresh": { + "previous_observed_at": "2026-10-03T22:12:05.918851+00:00", + "previous_worktrees": 5, + "current_worktrees": 6, + "current_local_branches": 6, + "added_worktrees": [ + "feat/claude-current" + ], + "removed_worktrees": [], + "source_main_changed": false + } } diff --git a/specs/004-migrate-to-triad/plan.md b/specs/004-migrate-to-triad/plan.md index 27bd12b6..7dfa99d8 100644 --- a/specs/004-migrate-to-triad/plan.md +++ b/specs/004-migrate-to-triad/plan.md @@ -2,29 +2,32 @@ **Feature**: `004-migrate-to-triad` | **Date**: 2026-10-03 **State**: Proposed plan; no migration, install or repository creation performed -**Refresh**: October 3 cleanup; current source main and active-work queue rechecked +**Refresh**: 2026-10-04; main, feature heads, worktree state and open PRs rechecked **Spec**: [spec.md](spec.md) **Governance**: [proposal](../../openspec/changes/migrate-to-triad/proposal.md) ## Baseline and deliverables The [adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) -is regenerated from main `82ecebee13edaa915b68550170faffdf761754d5` using pinned +was regenerated on October 4 from main `82ecebee13edaa915b68550170faffdf761754d5` using pinned openRepoShape `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. All 58 tracked paths are resolved: 17 spec, 35 code, six root, zero dropped. There are 21 named follow-ups. This is an inspected preliminary baseline; regenerate after planning lands and the actual cutover source is frozen. -Cleanup initially reduced the original 12-worktree snapshot to five registered -worktrees. Reopening the preserved `004` branch made six; concurrent cleanup -then removed the merged PR #146 checkout. There are now five worktrees, -including this planning checkout, and five local branches. The -[inventory](inventory.json) records those transitions, three open PRs (#134, -#121, #97), remote-only refs and retired-worktree history. Main includes merged -PRs #61 and #146 and matches the read-only GitHub main observation. Feature 001 at -`c0b571c5fa1c1446f143ce4f00f39db7cb7a166b` still has dirty/untracked broker -and task-recovery planning work. Machine paths, secrets/transcripts and backup -contents are omitted; private receipts must capture them at the execution gate. +Main remains at the previous refresh baseline and matches the read-only GitHub +observation; merged PRs #61 and #146 are already included. There are now six +worktrees and six local branches, including this planning checkout and the +newly restored `feat/claude-current` checkout. The three open PRs are #134, +#121 and #97; #134 is now non-draft at `11037f0`. Feature 001 advanced to +`3c26041a4444a10bc240cb64a168ece4d9edf6c5`, committing its broker/task-recovery +changes, restored rollover/workspace packets and October 4 launcher contracts. +Main and all five feature checkouts were clean before this refresh's edits. +The [inventory](inventory.json) keeps the October 3 cleanup as history and +records current heads, dirty counts and the two remote-only preservation refs. +Machine paths, secrets/transcripts and backup contents are omitted; private +receipts must capture them at the execution gate. Clean commits do not replace +verified preservation/restore receipts. Cleanup does not require recreating removed worktrees. Continue only the retained work below, and verify existing preservation receipts for retired @@ -35,7 +38,7 @@ objects. Snapshot refresh alone does not complete preservation Gate A. | Owner | Existing paths / generated responsibilities | Reason | | --- | --- | --- | | Assembly `openRepoTools` | `AGENTS.md`, `CLAUDE.md`, `README.md`, `LICENSE`, `.gitattributes`, `.gitignore`; generated manifest/Makefile/validators and assembly pins | Front door and project coordination across legs. | -| Spec `openRepoTools-spec` | `openspec/`, `specs/`, `docs/`; later feature ideation/governance artifacts | Product requirements, decisions and manual. | +| Spec `openRepoTools-spec` | `openspec/`, `specs/`, `docs/`; feature 001's retained `ideation/` and restored planning packets | Product requirements, decisions and manual; feature-only paths need separate replay accounting. | | Code `openRepoTools-code` | All executable tools, `repos.tsv`, `commands/`, `skills/`, `tests/`, implementation CI | Shipped implementation and its installer payload. | | Code dependency unit | Original `.gitmodules`, `upstream/openRepoShape`, `contracts/openreposhape-pin.yaml` | Keep module registration, exact gitlink and dependency lock together. | | Root workflow bootstrap | `.specify/`, project agent links and selected feature pointer | Currently local/ignored; capture config and regenerate shape-aware root scaffolding. | @@ -64,15 +67,15 @@ Recommended active-work dispositions are proposals, not merge/closure actions: | Work | Proposed treatment | | --- | --- | -| `001-separate-swap-ctx-handoff` | Continue from current head `c0b571c`, preserving its full delta and dirty/untracked broker/task-recovery additions; migrate to paired `001` worktrees. Keep tasks, evidence, roles and activation gates. | +| `001-separate-swap-ctx-handoff` | Continue from committed, clean head `3c26041`; preserve the complete branch delta, restored rollover/workspace packets and launcher/broker contracts. Migrate to paired `001` worktrees; keep tasks, evidence, roles and activation gates. | | PR #97 | Preserve branch/review; carry useful diagnostics into feature 001 under its service authority. Do not merge unchanged or auto-close as part of adoption. | | PR #121 | Preserve/review independently; translate selected context-runtime work to code/spec as needed, with its readiness integration still explicit. | | PR #146 / `fix/107-pty-driver-bound-and-lane-per-call-cost` | Merged as `82ecebe`; checkout and local branch removed during concurrent cleanup. Included by baseline extraction; do not replay separately. | -| PR #134 (draft) | Open at `715b7ac`, with a remote branch but no local worktree. Review retained changes from its branch; no checkout recreation is required just to inventory it. | +| PR #134 / `feat/claude-current` | Non-draft, with a clean sibling worktree at `11037f0`. Preserve/review the resolver and restart checker, installer additions, lane preflight/fencing, timeout containment and tests. Carry implementation/install payloads to code and their manual to spec; if landed before freeze, regenerate the baseline instead of replaying them. | | PR #61 | Merged as `14641fd`, an ancestor of current main; included by baseline extraction. Do not replay the retired claim-takeover branch separately. | | Retired `002`, `003`, lclaude and detached worktrees | Removed from current registrations/local branches by cleanup. Verify cleanup/preservation receipts; remove from the active replay queue and do not recreate them from the old snapshot. | | Remote-only preservation refs | `chore/preserve-local-planning-20261003` and `takeover/ort-a9-dirty-snapshot-20260913` remain locally observed remote-tracking refs with no checkout; review as preservation history, not active writers. | -| Migration feature `004` | Drafts were preserved at `52ce64e`; its checkout was reopened only for this refresh. Carry current plan/spec/tasks into spec; review assembly/code follow-ups separately. | +| Migration feature `004` | Previous refresh committed at `8aa119f`; existing checkout reused for this update. Carry current plan/spec/tasks into spec; review assembly/code follow-ups separately. | **Gate A:** every preserved object is attributable and restorable; no active writer can silently invalidate capture. Baseline, visibility and work @@ -143,8 +146,15 @@ and worktrees under `worktrees//{spec,code}`; preserve feature IDs and map old commits to new leg commits. Review conflicts semantically. Account for completed/landed work before replaying it. Retain original worktrees. -Prove feature 001's amended service-owned inventory requirements and new -planning work are present without claiming runtime acceptance. Test feature +Prove feature 001's service-owned inventory requirements, restored +`add-automatic-context-rollover` governance and lane-set workspace/rollover +brainstorm packets survive the replay. Carry its accepted October 4 launcher +contract and FR-047/T063–T065 without claiming runtime acceptance: workBenches +owns `pclaude`/`oclaude`/`lclaude`, openRepoTools owns LS admission/custody, and +Omnigent owns its local adapter/transport. Required local Omnigent qualification +for the selected lane stack and separate factory-broker admission gates remain +feature 001's delivery conditions. Repository adoption neither implements +those wrappers nor moves their ownership into this repository. Test feature selection, OpenSpec/Speckit prerequisites and estate park/resume in disposable fixtures. Apply supported WIP record updates only through their established contracts; relay refusals. Rebind each lane at its reviewed safe breakpoint, diff --git a/specs/004-migrate-to-triad/research.md b/specs/004-migrate-to-triad/research.md index 0cb77876..acf1eb64 100644 --- a/specs/004-migrate-to-triad/research.md +++ b/specs/004-migrate-to-triad/research.md @@ -1,19 +1,21 @@ # Planning evidence and decisions -October 3, 2026 inspection used the pinned standard's `AGENTS.md`, adoption +October 3 inspection and October 4 refresh used the pinned standard's `AGENTS.md`, adoption implementation, generated CLI reference and placement policy; root installer, CI and fixture code; local branch/worktree state; read-only GitHub PR metadata. No external writes, repositories, installation or migration occurred. | Finding | Decision / execution consequence | | --- | --- | -| Source main advanced to `82ecebe` (79 commits), still 58 tracked paths and one standard gitlink | Regenerate the mapping from the source; #61 and #146 are included without replay. | +| October 4 main still matches GitHub at `82ecebe` (79 commits), 58 tracked paths and one standard gitlink | Regenerate/check the current main mapping; #61 and #146 remain included without replay. | | Classifier treats shipped Markdown skills/commands as specification | Override to code with written reasons; these are installation payloads. | | Original contract is the implementation's upstream dependency lock | Keep code pin/gitlink/.gitmodules together; generated assembly pins are separate. | | `.specify` and agent directories are ignored local scaffolding | Preserve local config separately and regenerate root workflow after adoption. | -| Cleanup initially left five worktrees; reopening planning made six, then merged #146's checkout was removed; now five worktrees and open PRs #134/#121/#97 | Reduce the active replay queue; do not recreate retired `002`/`003`, lclaude, detached, claim-takeover or #146 checkouts. | -| Feature 001 at `c0b571c` still has dirty/untracked broker/task-recovery work | Preserve its current complete delta/content, not the previous snapshot. | -| Draft #134 and preservation refs have no local worktrees | Review retained branch history without treating it as an active writer or requiring recreation. | +| Six current worktrees/local branches; main and all feature checkouts clean before refresh edits; open PRs #134/#121/#97 | Keep retired `002`/`003`, lclaude, detached, claim-takeover and #146 checkouts out of replay. Clean status alone does not complete preservation Gate A. | +| Feature 001 advanced to clean `3c26041`, committing broker/task-recovery work and restoring rollover/workspace packets | Preserve its complete branch delta and restored governance/ideation; remove the stale requirement to capture the previous dirty files as uncommitted work. | +| Feature 001 now selects required local Omnigent for `lclaude → oclaude → profile launch`, with implementation/qualification pending | Carry launcher contract, FR-047/T063–T065, LS custody/input fences and separate factory-broker gates; keep wrapper ownership in workBenches and transport ownership in Omnigent. | +| Non-draft #134 advanced to `11037f0` and has a clean sibling worktree | Carry code installer/resolver/preflight/timeout/test changes and spec manual if unmerged; regenerate baseline if it lands before freeze. | +| Two remaining preservation refs have no local worktrees | Review their history as recovery evidence; do not treat them as active writers or require recreation. | | Estate status refuses this manifest-free single repository | Relay no-estate refusal; use local Git and read-only GitHub observations now, then estate status after adoption. | | Installer fetches bare paths from `openRepoTools` and local sibling payloads | Preserve public root entry point and bind every payload to one code pin. | | Tests conflate repo, spec and dependency paths | Introduce explicit checkout context and composed CI, preserving nested-pin tests. | diff --git a/specs/004-migrate-to-triad/tasks.md b/specs/004-migrate-to-triad/tasks.md index 40cabc07..4c070093 100644 --- a/specs/004-migrate-to-triad/tasks.md +++ b/specs/004-migrate-to-triad/tasks.md @@ -4,7 +4,7 @@ The sole executable task list for the governing OpenSpec change. Planning artifacts and preliminary mapping validation do not complete these tasks. Every task remains open. Run implementation from the selected feature worktrees; actual repository creation/cutover require the approval gates. -The cleanup refresh updates the snapshot/mapping portion of T001/T003 only; +The October 4 refresh updates the snapshot/mapping portion of T001/T003 only; owner decisions, private preservation/restore receipts and execution gates remain pending. Retired checkouts are not instructions to recreate worktrees. @@ -12,7 +12,7 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. - [ ] T001 [US1] Refresh `inventory.json`, PR/main/branch/worktree metadata and applicable estate-status output; distinguish retained work from retired - cleanup records and remote-only drafts. Until an estate manifest exists, + cleanup records and remote-only refs. Until an estate manifest exists, relay `status --fetch openRepoTools`'s no-estate refusal without invoking `resume`. Resolve continuation/archive decisions for every retained object in a host-local/private migration receipt. Verify no branch, detached @@ -87,10 +87,13 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. ## Phase 5 — Continue features and controlled cutover (Gate E) -- [ ] T016 [US1] Translate the complete approved feature 001 delta and preserved - dirty/untracked work into paired `001` spec/code branches/worktrees with +- [ ] T016 [US1] Translate the complete approved feature 001 delta and any + dirty/untracked work captured at cutover into paired `001` spec/code branches/worktrees with reviewed root changes. Verify content/old-to-new receipts, roles, inventory - amendment and open runtime gates; do not replay completed work or claim new + amendment and open runtime gates. Carry the clean `3c26041` checkpoint's + restored rollover/workspace packets, launcher contract and FR-047/T063–T065; + preserve workBenches/Omnigent ownership and required local adapter qualification + separately from factory-broker admission. Do not replay completed work or claim new runtime acceptance from migration. - [ ] T017 [US1] Translate every other approved continued PR/branch/detached worktree, including this migration feature, with explicit spec/code/root @@ -98,7 +101,9 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. approved archived-original disposition; preserve original PR review history. Current candidates are #97/#121/#134 and feature 004. Account for merged #61/#146 through the baseline and retired checkout history through its receipts; - do not recreate cleaned worktrees or replay integrated changes. + do not recreate cleaned worktrees or replay integrated changes. PR #134 is + non-draft at `11037f0` with a clean worktree: account for its resolver/checker, + installer, lane preflight/fencing, timeout containment, manual and tests. - [ ] T018 [US3] Exercise OpenSpec/Speckit feature selection and estate park/resume in disposable triad fixtures, then perform reviewed binding/WIP transitions through supported tools at owner breakpoints. Verify correct diff --git a/specs/004-migrate-to-triad/verification.md b/specs/004-migrate-to-triad/verification.md index 56574301..d2834533 100644 --- a/specs/004-migrate-to-triad/verification.md +++ b/specs/004-migrate-to-triad/verification.md @@ -1,6 +1,34 @@ -# Migration planning verification — October 3, 2026 +# Migration planning verification — October 4, 2026 -## Cleanup refresh +## October 4 repository refresh + +Read-only GitHub main still matches local `82ecebee13edaa915b68550170faffdf761754d5`. +The pinned standard remains `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. +The current open PRs are #134, #121 and #97; #134 is now non-draft at +`11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12` with a clean sibling worktree. +There are six registered worktrees and six local branches. Main and every +feature checkout were clean before this refresh's planning edits; the inventory +records its actual observation time and planning edits present when sampled. + +Feature 001 is committed and clean at `3c26041a4444a10bc240cb64a168ece4d9edf6c5`. +The previous dirty broker/task-recovery edits, restored automatic-rollover and +lane-set workspace packets, and October 4 local launcher contract are retained +in its branch. The migration plan now carries those documents and their owning +implementation/runtime gates. It makes no launcher deployment or swap-readiness +claim. The old dirty-content snapshot and cleanup counts below are historical. + +The main-only mapping was regenerated and checked: 58 paths, 17 spec / 35 code / +six root, no unresolved path or drop, 79 commits and 21 follow-ups. OpenSpec +strict validation, document/inventory checks and `git diff --check` passed. +All 19 execution tasks remain open; no adoption rehearsal or runtime suite +was run for this documentation refresh. + +`status --fetch openRepoTools` again refused with no estate named openRepoTools; +the manifest is still absent and no fetch occurred. Git and read-only GitHub +REST supplied the snapshot instead. No `resume`, manual fetch, workspace-pointer +rewrite, PR merge/closure, lane move or migration was performed. + +## October 3 cleanup refresh — historical The refreshed source main is `82ecebee13edaa915b68550170faffdf761754d5`, including merged PRs #61 and #146. Read-only GitHub REST main matched local From 48934f8d4c662be6ed07ad1b7df96dec22028ab2 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Sun, 4 Oct 2026 17:42:24 +0000 Subject: [PATCH 04/12] docs: align triad migration with adopted amendment protocol --- .../migrate-to-triad/adoption-plan.yaml | 79 +++++++---- openspec/changes/migrate-to-triad/design.md | 44 ++++-- openspec/changes/migrate-to-triad/proposal.md | 21 ++- .../specs/repository-triad-migration/spec.md | 68 ++++++++- openspec/changes/migrate-to-triad/tasks.md | 5 +- specs/004-migrate-to-triad/data-model.md | 5 +- specs/004-migrate-to-triad/inventory.json | 132 ++++++++++++------ specs/004-migrate-to-triad/plan.md | 92 +++++++++--- specs/004-migrate-to-triad/protocol-review.md | 48 +++++++ specs/004-migrate-to-triad/quickstart.md | 12 +- specs/004-migrate-to-triad/research.md | 11 +- specs/004-migrate-to-triad/spec.md | 43 +++++- specs/004-migrate-to-triad/tasks.md | 73 +++++++--- specs/004-migrate-to-triad/verification.md | 44 +++++- 14 files changed, 550 insertions(+), 127 deletions(-) create mode 100644 specs/004-migrate-to-triad/protocol-review.md diff --git a/openspec/changes/migrate-to-triad/adoption-plan.yaml b/openspec/changes/migrate-to-triad/adoption-plan.yaml index 7baf5e8a..cf1678f3 100644 --- a/openspec/changes/migrate-to-triad/adoption-plan.yaml +++ b/openspec/changes/migrate-to-triad/adoption-plan.yaml @@ -8,10 +8,10 @@ source: repository: opensoft/openRepoTools local_path: . default_branch: main - commit: "82ecebee13edaa915b68550170faffdf761754d5" - files: 58 - bytes: 4339687 - commits: 79 + commit: daed20957f2dd2f22cca24053bb5bc8636ff6b3f + files: 64 + bytes: 4490556 + commits: 80 mode: in-place project: openRepoTools org: opensoft @@ -50,7 +50,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: 18419 + bytes: 18501 review_required: false - path: .gitignore leg: root @@ -76,7 +76,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: 20968 + bytes: 20967 review_required: false - path: CLAUDE.md leg: root @@ -100,8 +100,28 @@ 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: 29806 + bytes: 30329 review_required: false + - path: claude-current + 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: 29335 + 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 installer payload added by merged PR #134; keep resolver/checker with commands and their implementation tests in code." + - path: claude-restart-check + 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: 11880 + 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 installer payload added by merged PR #134; keep resolver/checker with commands and their implementation tests in code." - path: commands/ leg: code confidence: medium @@ -125,8 +145,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: 1 - bytes: 187100 + files: 2 + bytes: 201648 review_required: false - path: lane leg: code @@ -174,7 +194,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: 223900 + bytes: 233030 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." @@ -212,7 +232,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: 178500 + bytes: 180034 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." @@ -286,8 +306,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: 12 - bytes: 1938387 + files: 15 + bytes: 2022225 review_required: false - path: upstream/ leg: code @@ -300,12 +320,15 @@ paths: 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" - "code/lanes-edit.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/openRepoTools 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/run.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_install_skill_and_hook.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" - "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_repo_hygiene.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" + - "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/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" @@ -318,25 +341,29 @@ 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 58-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 64-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: 17 - bytes: 208000 - file_share: 0.2931 - byte_share: 0.0479 + files: 18 + bytes: 222548 + file_share: 0.2812 + byte_share: 0.0496 code: - files: 35 - bytes: 4067645 - file_share: 0.6034 - byte_share: 0.9373 + files: 40 + bytes: 4203444 + file_share: 0.6250 + byte_share: 0.9361 root: files: 6 - bytes: 64042 - file_share: 0.1034 - byte_share: 0.0148 + bytes: 64564 + file_share: 0.0938 + byte_share: 0.0144 unresolved: files: 0 bytes: 0 diff --git a/openspec/changes/migrate-to-triad/design.md b/openspec/changes/migrate-to-triad/design.md index b8d27815..fc1e42ee 100644 --- a/openspec/changes/migrate-to-triad/design.md +++ b/openspec/changes/migrate-to-triad/design.md @@ -2,12 +2,12 @@ ## Context -The refreshed preliminary source is main `82ecebee13edaa915b68550170faffdf761754d5`: -58 tracked paths, 79 commits, one nested standard submodule. The inspected +The refreshed preliminary source is main `daed20957f2dd2f22cca24053bb5bc8636ff6b3f`: +64 tracked paths, 80 commits, one nested standard submodule. The inspected standard is `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. The October 4 refresh -found unchanged main, six worktrees including planning and the restored -`feat/claude-current` checkout, and six local branches. The three open PRs -are #134, #121 and #97; #134 is non-draft at `11037f0`. #61 and #146 are +found merged PR #134 on main, six worktrees including planning and the retained +`feat/claude-current` checkout, and six local branches. The two open PRs +are #121 and #97. #134, #61 and #146 are included in main and need no separate replay. Feature 001 is now committed and clean at `3c26041`, including restored rollover/workspace packets and the selected local Omnigent launcher contract. Main extraction alone still omits @@ -41,12 +41,18 @@ baseline, standard commit, complete mapping and follow-ups. ### Placement and dependency custody -The [resolved adoption plan](adoption-plan.yaml) accounts for all 58 baseline -paths: 17 spec, 35 code, six root, none dropped. It records reasons for all -14 originally unresolved paths and overrides for shipped Markdown payloads +The [resolved adoption plan](adoption-plan.yaml) accounts for all 64 baseline +paths: 18 spec, 40 code, six root, none dropped, with 28 follow-ups. It records reasons for all +16 originally unresolved paths and overrides for shipped Markdown payloads and the dependency lock. Product documentation/OpenSpec/Speckit go to spec. Root owns front-door guidance, license, project metadata and workflow bootstrap. +Genuine bounded feature amendment records at +`features//openspec/` are the narrow code exception. Review them +explicitly with reasoned resolutions until the upstream rule is qualified. +No such tracked records were observed in current main/retained feature heads; +do not manufacture them or move full feature-branch proposals into code. + Keep executable files, `repos.tsv`, shipped `commands/` and `skills/`, tests and implementation CI in code. The original `.gitmodules`, mounted standard and `contracts/openreposhape-pin.yaml` also stay together in code. At this @@ -96,6 +102,17 @@ lane until its owner has reached a safe breakpoint and replacement evidence is reviewed. WIP records remain in their existing private repository and use the supported estate workflow; public records contain no private backups. +Retain approved original proposal repository/commit/path provenance and verify +correspondence to the extracted spec history; filtered commits can differ. +Repair links and feature/task references without guessing new approval hashes. +Explicitly select the intended spec checkout for full proposals and the code +feature root for bounded amendments. A local root overrides a docs-store pointer; +verified `--store` support is optional, not assumed. Never edit pinned base +mounts by accidental store selection. Keep manual amendment records and update +working Speckit files immediately; runtime/capability/authority/external scope +changes retain full governance. Schema, command routing, workstation distribution +and shape placement automation are pending, not delivered by this migration. + ### CI and exact-pin delivery Code CI runs implementation checks; root CI validates manifest/pins and the @@ -105,6 +122,17 @@ in the code Git repository. Use the canonical serialized `tests/run.sh`, Bash 3.2 parsing and current platform/fixture timing policies. Missing-spec context cannot turn a required integration check into a silent skip. +Prepare code/spec PRs together. At the first bounded amendment create one spec +reconciliation issue; collect net tested effects, all dispositions, dated +departures, as-built record, evidence and landed code identity in one final +spec batch. Preserve archived approval history through linked records. Code +may land first, but completed assembly advancement waits for reconciled spec +and matching code. Close the issue after spec landing; the feature landing +record tracks assembly. Archive only after implementation and assembly landing +with explicit full-spec root selection, and advance later archive commits by +ordinary pinning. Reopen reconciliation for later behavior changes; cancellation +records abandonment. Local archival cannot satisfy reconciliation. + Land follow-up leg changes before the root pin bump that selects them. Root gitlinks, leg pins and workflow SHAs move through the standard's bump tool. The historical upstream dependency remains one-way and unedited; needed diff --git a/openspec/changes/migrate-to-triad/proposal.md b/openspec/changes/migrate-to-triad/proposal.md index 5d607d39..76718921 100644 --- a/openspec/changes/migrate-to-triad/proposal.md +++ b/openspec/changes/migrate-to-triad/proposal.md @@ -17,6 +17,12 @@ pins their exact tested combination and preserves its identity and history. executable tooling, shipped skills/commands, tests, CI and the mounted standard dependency in `code/`. Root agent guidance and workflow bootstrap span both legs. No source path is proposed for deletion. +- Apply the adopted October 4 manual amendment workflow: full proposals and + canonical specs stay in spec; genuine bounded feature records stay in code. + Preserve verified approved-baseline correspondence, update working Speckit + files immediately and reconcile net tested effects once before completed + assembly advancement. Schema/routing/distribution/placement automation remains + pending with workBenches/openRepoShape. - **BREAKING:** development paths and PR destinations change. Preserve command names, install artifacts, published one-line installation and installed behavior through a pinned assembly-to-code compatibility entry point. @@ -63,15 +69,18 @@ existing changes; this migration does not activate experimental capabilities. Requested on October 3, 2026. Planning is authorized; migration execution, repository creation, software installation, PR merge and lane relocation are not authorized by this request. The attached adoption plan is a preliminary -mapping regenerated from source main `82ecebee13edaa915b68550170faffdf761754d5`, not a promise +mapping regenerated from source main `daed20957f2dd2f22cca24053bb5bc8636ff6b3f`, not a promise that this will be the final split commit. Refresh after planning lands and the cutover baseline is frozen. No runtime or migration success is claimed. -The October 4 refresh retains the October 3 cleanup history and records six -current worktrees, including the restored PR #134 checkout. #134 is now -non-draft at `11037f0`; feature 001 is committed and clean at `3c26041` with +The protocol refresh retains the October 3 cleanup history and records six +current worktrees, including the retained merged PR #134 checkout. #134 is +included in the new main baseline; feature 001 is committed and clean at `3c26041` with restored rollover/workspace packets and the selected local launcher contract. -All checkouts were clean before planning edits. Both #61 and #146 remain -included through unchanged main. Continued feature branches and the two +Feature 001/main remain clean; concurrent #121 work now includes dirty/untracked +feature 005 and its full legacy authority decision. Both #61 and #146 remain +included through main. Open PRs are now #97 and #121. Continued feature branches and the two remote-only preservation refs still require preservation/review receipts; repository adoption does not implement or activate the feature 001 launch stack. +The [protocol review](../../../specs/004-migrate-to-triad/protocol-review.md) +records the adopted manual instructions and the working-draft source snapshots. diff --git a/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md b/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md index 982c6f73..f5ff667b 100644 --- a/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md +++ b/openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md @@ -62,7 +62,11 @@ without a developer assembly checkout. ### Requirement: Project workflow operates across the pinned legs The assembly SHALL own project workflow and its manifest/pins; product -OpenSpec/Speckit artifacts SHALL live in spec, implementation in code. +Full proposals, archives and canonical OpenSpec/Speckit artifacts SHALL live +in spec, implementation in code. Genuine bounded feature amendment records +SHALL remain in code as the narrow reviewed placement exception, not a second +canonical baseline. A feature-branch origin SHALL NOT change a full proposal's +role. Historical features SHALL NOT require manufactured local amendments. Continued features SHALL use paired leg worktrees with preserved feature IDs. Delivery SHALL land leg changes and select them through a root pin bump. CI SHALL test the exact composed state without silently skipping required @@ -73,6 +77,68 @@ cross-leg tests. The standard dependency SHALL remain unedited in place. - **THEN** root gitlinks, pin records and workflow commit references SHALL move together through the established pin-bump procedure and integration checks. +#### Scenario: Bounded amendment folder exists before extraction +- **WHEN** source content contains genuine `features//openspec/` records +- **THEN** the reviewed plan SHALL explicitly assign them to code until upstream + placement is qualified +- **AND** pinned standard copies/digests SHALL NOT be edited to make placement pass. + +### Requirement: Migration retains provenance and explicit planning roots + +The migration SHALL preserve approved original repository/commit/path identities +and verify correspondence to extracted spec identities when filtering changes +hashes. It SHALL repair cross-leg links, baseline references and feature/task +paths without guessing approved commits. Full proposal operations SHALL select +the intended spec feature checkout; local amendments SHALL select their code +root. A store pointer SHALL NOT override explicit local-root verification or +authorize accidental changes to pinned base mounts. Pending schema/routing, +bootstrap distribution and upstream placement automation SHALL remain distinct +from adopted manual use on a target workstation. + +#### Scenario: Extraction changes an approved proposal commit +- **WHEN** the extracted spec history has a different commit identity +- **THEN** original approved provenance SHALL remain recorded +- **AND** migration evidence SHALL establish the corresponding spec repository, + commit and path rather than substituting a guessed hash. + +#### Scenario: Local amendment root and docs store coexist +- **WHEN** an operation could resolve to either planning root +- **THEN** the operator SHALL verify its intended checkout, branch and root +- **AND** a local amendment archive SHALL NOT prove canonical reconciliation. + +### Requirement: Tested reconciliation precedes completed assembly advancement + +Accepted bounded migration adjustments SHALL record unique feature-local IDs, +governing baseline, affected requirements/tasks, authority/source, verification +impact and dispositions. Working Speckit files SHALL update before dependent +implementation. Larger scope/runtime/authority/external changes SHALL use full +spec governance; unnecessary larger ideas SHALL be linked to future-proposal +issues and excluded from current requirements/tasks. Speckit SHALL remain the +only executable task list. + +At the first amendment, the feature SHALL create one spec reconciliation issue. +After implementation and verification, it SHALL reconcile net tested effects +once into governing specs/contracts/design with dated departures/as-built +evidence, every disposition and the landed code identity. Inactive deltas SHALL +be excluded while approved, archived and amendment history remains traceable. +Spec/code PRs SHALL be prepared together. Code MAY land first, but reconciliation +and matching spec/code pins SHALL precede completed assembly advancement. +The issue SHALL close after spec landing; the feature landing record SHALL track +assembly. Full spec archival SHALL explicitly select its root and wait for +implementation/assembly landing; subsequent archive commits SHALL advance by +ordinary pinning. Later behavior changes SHALL reopen reconciliation; +cancellation SHALL record abandonment rather than as-built completion. + +#### Scenario: Code lands before final spec reconciliation +- **WHEN** the code PR lands while final reconciliation remains open +- **THEN** completed assembly advancement SHALL wait for the matching spec landing +- **AND** the reconciliation SHALL reference the actual landed code commit. + +#### Scenario: Amendment was reverted or deferred +- **WHEN** final reconciliation computes the tested semantic effect +- **THEN** the inactive delta SHALL be excluded from governing behavior +- **AND** its disposition, history and any future-proposal issue SHALL remain linked. + ### Requirement: Execution and cutover require reviewable evidence Real execution SHALL require an explicit approved plan, visibility, baseline, diff --git a/openspec/changes/migrate-to-triad/tasks.md b/openspec/changes/migrate-to-triad/tasks.md index 3738cb5d..858e93fc 100644 --- a/openspec/changes/migrate-to-triad/tasks.md +++ b/openspec/changes/migrate-to-triad/tasks.md @@ -17,6 +17,9 @@ This checklist tracks governance, not duplicate implementation tasks. - [ ] 2.1 Accept exact assembled-head, preservation, feature-transition and rollback evidence from Speckit Gates C–E; verify required CI and ownership boundaries without enabling unrelated experimental runtime features. -- [ ] 2.2 Archive only after the adopted assembly and selected leg pins land +- [ ] 2.2 Accept final tested spec reconciliation, amendment dispositions and + approved-baseline correspondence; verify matched spec/code landings before + completed assembly advancement. Close reconciliation after spec landing. +- [ ] 2.3 Archive only after the adopted assembly and selected leg pins land and continued work is accounted for; verify root delivery and recorded old-PR/worktree dispositions before closure. diff --git a/specs/004-migrate-to-triad/data-model.md b/specs/004-migrate-to-triad/data-model.md index b36916ca..2dc89f10 100644 --- a/specs/004-migrate-to-triad/data-model.md +++ b/specs/004-migrate-to-triad/data-model.md @@ -8,7 +8,10 @@ and never replace lane claims, workspace pointers or the standard's pins. | Adoption plan | Source repository/commit, standard revision evidence, names/visibility, reasoned path owners, follow-ups, coverage result and approval binding. Relative paths only in shared artifacts. | | Work inventory | Observation time, branch/PR/head identity, detached status, readable/dirty indication and snapshot limits. Public `inventory.json` omits host paths and private work. | | Private preservation receipt | Exact original worktree/binding, branch refs, staged/unstaged/untracked/ignored content digests, backup location and verified restore result. Stored host-locally or in existing private WIP storage. | -| Feature migration receipt | Original merge base/head and captured content; spec/code/root file mapping; resulting branches/commits/checksums; conflict/replay decisions, roles and approval. | +| Feature migration receipt | Original merge base/head and captured content; approved original proposal repository/commit/path; verified extracted spec correspondence; spec/code/root mapping; resulting branches/commits/checksums; repaired links/task roots, conflict decisions, roles and approval. | +| Bounded amendment record | Feature-local ID, governing proposal/immutable approved baseline, authority/source, affected requirements/tasks, interpretation, verification impact, implementation/evidence references and disposition. Relative code paths; no second canonical spec/task store. | +| Final spec reconciliation | One issue created at first amendment; all dispositions/net effect, dated departures/as-built record, preserved approval/archive history, verification, landed code identity, deferred future issues and matching spec/code/assembly landing references. | +| Workflow qualification | Explicit root/store/branch selection; manual instruction availability on each target workstation; pending schema/routing/distribution/upstream placement owners and any reviewed local exception. | | Composed candidate evidence | Root/spec/code/standard commits, pin/digest consistency, installer payload revision, platform/CI/rehearsal/rollback results and outstanding findings. | | Cutover approval | Actual candidate/baseline, visibility, leg names, preservation/rehearsal references, lane breakpoints and authorized actions. | diff --git a/specs/004-migrate-to-triad/inventory.json b/specs/004-migrate-to-triad/inventory.json index efdb0aff..656b6cef 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-04T16:37:26.292668+00:00", + "observed_at": "2026-10-04T17:40:54.465251+00:00", "source_repository": "opensoft/openRepoTools", - "source_main": "82ecebee13edaa915b68550170faffdf761754d5", - "github_main": "82ecebee13edaa915b68550170faffdf761754d5", + "source_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "github_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", "github_main_matches_local": true, "standard_commit": "39d5c986fcfac1a160474bfe91c5f1c37fccc72c", "cleanup_summary": { @@ -70,7 +70,7 @@ "worktrees": [ { "identity": "main", - "head": "82ecebee13edaa915b68550170faffdf761754d5", + "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", "layout": "root", "readable_here": true, "dirty_entries": 0, @@ -90,11 +90,11 @@ }, { "identity": "004-migrate-to-triad", - "head": "8aa119fd5c4286ff836ee2c9c6ee141859cb3710", + "head": "dda91f11c68818ebeca4264d88908c85818ff630", "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 1, - "untracked_entries": 0, + "dirty_entries": 14, + "untracked_entries": 1, "locked": false, "prunable": false }, @@ -113,14 +113,14 @@ "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", "layout": "legacy-nested", "readable_here": true, - "dirty_entries": 0, - "untracked_entries": 0, + "dirty_entries": 43, + "untracked_entries": 3, "locked": false, "prunable": false }, { "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341", "layout": "legacy-nested", "readable_here": true, "dirty_entries": 0, @@ -136,7 +136,7 @@ }, { "identity": "004-migrate-to-triad", - "head": "8aa119fd5c4286ff836ee2c9c6ee141859cb3710" + "head": "dda91f11c68818ebeca4264d88908c85818ff630" }, { "identity": "feat/claude-current", @@ -144,7 +144,7 @@ }, { "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e" + "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341" }, { "identity": "feat/supervised-context-restart", @@ -152,7 +152,7 @@ }, { "identity": "main", - "head": "82ecebee13edaa915b68550170faffdf761754d5" + "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f" } ], "remote_only_branches": [ @@ -168,15 +168,6 @@ } ], "open_prs": [ - { - "number": 134, - "title": "Launch current Claude Code and report stale running sessions", - "headRefName": "feat/claude-current", - "headRefOid": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", - "isDraft": false, - "url": "https://github.com/opensoft/openRepoTools/pull/134", - "state": "open" - }, { "number": 121, "title": "`/ctx` writes its restart to disk before it kills anything, and what tmux starts is a supervisor that stays in the pane \u2014 the fresh session was an environment variable the launcher dropped (#94)", @@ -210,6 +201,13 @@ "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": { @@ -224,10 +222,11 @@ "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." + "Inventory captures this planning branch before the refresh commit; its final HEAD is recorded by git.", + "PR #121 now contains active staged/unstaged/untracked work including feature 005 legacy-only supervised restart and its full authority decision; preserve current contents and merge hold. Snapshot counts can change while owners continue." ], "previous_refresh_snapshot": { - "observed_at": "2026-10-03T22:12:05.918851+00:00", + "observed_at": "2026-10-04T16:37:26.292668+00:00", "source_main": "82ecebee13edaa915b68550170faffdf761754d5", "worktrees": [ { @@ -238,14 +237,20 @@ }, { "identity": "001-separate-swap-ctx-handoff", - "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b", - "dirty_entries": 18, - "untracked_entries": 1 + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5", + "dirty_entries": 0, + "untracked_entries": 0 }, { "identity": "004-migrate-to-triad", - "head": "52ce64ee7787b62bf015e13cbf663f305513093e", - "dirty_entries": 8, + "head": "8aa119fd5c4286ff836ee2c9c6ee141859cb3710", + "dirty_entries": 1, + "untracked_entries": 0 + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "dirty_entries": 0, "untracked_entries": 0 }, { @@ -264,11 +269,15 @@ "local_branches": [ { "identity": "001-separate-swap-ctx-handoff", - "head": "c0b571c5fa1c1446f143ce4f00f39db7cb7a166b" + "head": "3c26041a4444a10bc240cb64a168ece4d9edf6c5" }, { "identity": "004-migrate-to-triad", - "head": "52ce64ee7787b62bf015e13cbf663f305513093e" + "head": "8aa119fd5c4286ff836ee2c9c6ee141859cb3710" + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12" }, { "identity": "feat/crash-consistent-lane-worktree-recovery", @@ -287,8 +296,8 @@ { "number": 134, "headRefName": "feat/claude-current", - "headRefOid": "715b7ace2f6eeddcf75014e705535fd5c1965ff7", - "isDraft": true + "headRefOid": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "isDraft": false }, { "number": 121, @@ -305,14 +314,59 @@ ] }, "latest_refresh": { - "previous_observed_at": "2026-10-03T22:12:05.918851+00:00", - "previous_worktrees": 5, + "previous_observed_at": "2026-10-04T16:37:26.292668+00:00", + "previous_worktrees": 6, "current_worktrees": 6, "current_local_branches": 6, - "added_worktrees": [ - "feat/claude-current" - ], + "added_worktrees": [], "removed_worktrees": [], - "source_main_changed": false + "source_main_changed": true, + "protocol": "Shared OpenSpec/Speckit workflow: Triad Feature Amendments, adopted 2026-10-04; manual delivery only.", + "concurrent_work": "PR #121 retains staged/unstaged/untracked work including full legacy authority decision and feature 005; recovery branch advanced during refresh. Snapshot only, not a writer freeze." + }, + "protocol_review": { + "adopted_on": "2026-10-04", + "workflow": "Triad Feature Amendments and Single repository to triad migration", + "manual_use": true, + "automation_qualified": false, + "source_record": "specs/004-migrate-to-triad/protocol-review.md", + "amendment_path_observations": [ + { + "identity": "main", + "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", + "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": "dda91f11c68818ebeca4264d88908c85818ff630", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341", + "bounded_amendment_paths": [], + "working_bounded_amendment_paths": [] + } + ] } } diff --git a/specs/004-migrate-to-triad/plan.md b/specs/004-migrate-to-triad/plan.md index 7dfa99d8..7ca2fd2d 100644 --- a/specs/004-migrate-to-triad/plan.md +++ b/specs/004-migrate-to-triad/plan.md @@ -2,27 +2,31 @@ **Feature**: `004-migrate-to-triad` | **Date**: 2026-10-03 **State**: Proposed plan; no migration, install or repository creation performed -**Refresh**: 2026-10-04; main, feature heads, worktree state and open PRs rechecked +**Refresh**: 2026-10-04; adopted amendment protocol and merged PR #134 incorporated **Spec**: [spec.md](spec.md) **Governance**: [proposal](../../openspec/changes/migrate-to-triad/proposal.md) ## Baseline and deliverables The [adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) -was regenerated on October 4 from main `82ecebee13edaa915b68550170faffdf761754d5` using pinned -openRepoShape `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. All 58 tracked -paths are resolved: 17 spec, 35 code, six root, zero dropped. There are -21 named follow-ups. This is an inspected preliminary baseline; regenerate +was regenerated from main `daed20957f2dd2f22cca24053bb5bc8636ff6b3f` using pinned +openRepoShape `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. All 64 tracked +paths are resolved: 18 spec, 40 code, six root, zero dropped. There are +28 named follow-ups, including protocol placement/provenance/reconciliation. +This is an inspected preliminary baseline; regenerate after planning lands and the actual cutover source is frozen. -Main remains at the previous refresh baseline and matches the read-only GitHub -observation; merged PRs #61 and #146 are already included. There are now six +Main advanced with merged PR #134 and matches the read-only GitHub observation; +#61 and #146 remain included. There are six worktrees and six local branches, including this planning checkout and the -newly restored `feat/claude-current` checkout. The three open PRs are #134, -#121 and #97; #134 is now non-draft at `11037f0`. Feature 001 advanced to +retained `feat/claude-current` checkout, whose merged changes need no replay. +The two open PRs are #121 and #97. Feature 001 remains at `3c26041a4444a10bc240cb64a168ece4d9edf6c5`, committing its broker/task-recovery changes, restored rollover/workspace packets and October 4 launcher contracts. -Main and all five feature checkouts were clean before this refresh's edits. +Main and feature 001 remain clean. Concurrent work in PR #121's checkout now +includes staged/unstaged/untracked content and `005-supervised-legacy-ctx`; +the recovery branch also advanced. The inventory is an observation, not a +freeze of active writers. The [inventory](inventory.json) keeps the October 3 cleanup as history and records current heads, dirty counts and the two remote-only preservation refs. Machine paths, secrets/transcripts and backup contents are omitted; private @@ -33,6 +37,12 @@ Cleanup does not require recreating removed worktrees. Continue only the retained work below, and verify existing preservation receipts for retired objects. Snapshot refresh alone does not complete preservation Gate A. +The [protocol review](protocol-review.md) records the October 4 manual default +and source snapshots. Full proposals, archives, canonical specs/contracts and +Speckit files stay in spec. Genuine bounded amendments belong in the code +feature folder and require immediate working-spec updates plus final docs +reconciliation. Schema/routing/distribution/placement automation is pending. + ## Target placement | Owner | Existing paths / generated responsibilities | Reason | @@ -41,6 +51,7 @@ objects. Snapshot refresh alone does not complete preservation Gate A. | Spec `openRepoTools-spec` | `openspec/`, `specs/`, `docs/`; feature 001's retained `ideation/` and restored planning packets | Product requirements, decisions and manual; feature-only paths need separate replay accounting. | | Code `openRepoTools-code` | All executable tools, `repos.tsv`, `commands/`, `skills/`, `tests/`, implementation CI | Shipped implementation and its installer payload. | | Code dependency unit | Original `.gitmodules`, `upstream/openRepoShape`, `contracts/openreposhape-pin.yaml` | Keep module registration, exact gitlink and dependency lock together. | +| Code amendment exception | Genuine bounded `features//openspec/` records, deltas and evidence references | Relative changes against an approved spec baseline; explicitly review placement until upstream qualification. No such tracked paths were observed in the current source or retained feature heads. | | Root workflow bootstrap | `.specify/`, project agent links and selected feature pointer | Currently local/ignored; capture config and regenerate shape-aware root scaffolding. | After byte-preserving extraction, add a root installation entry point that @@ -68,14 +79,14 @@ Recommended active-work dispositions are proposals, not merge/closure actions: | Work | Proposed treatment | | --- | --- | | `001-separate-swap-ctx-handoff` | Continue from committed, clean head `3c26041`; preserve the complete branch delta, restored rollover/workspace packets and launcher/broker contracts. Migrate to paired `001` worktrees; keep tasks, evidence, roles and activation gates. | -| PR #97 | Preserve branch/review; carry useful diagnostics into feature 001 under its service authority. Do not merge unchanged or auto-close as part of adoption. | -| PR #121 | Preserve/review independently; translate selected context-runtime work to code/spec as needed, with its readiness integration still explicit. | +| PR #97 | Preserve its current advanced recovery branch, review history and diagnostic role separately from managed LS authority and PR #121. Carry useful diagnostics under feature 001's service authority without merging unchanged or auto-closing through adoption. | +| PR #121 / feature `005-supervised-legacy-ctx` | Preserve complete staged/unstaged/untracked contents and the full legacy authority decision. Continue paired `005` worktrees for confirmed legacy-only supervised restart; managed/unknown ownership refuses. Keep the existing merge hold and PR #97 ownership separate. The full proposal/decision/specs stay in spec, implementation/tests in code; this authority decision is not a bounded local amendment. | | PR #146 / `fix/107-pty-driver-bound-and-lane-per-call-cost` | Merged as `82ecebe`; checkout and local branch removed during concurrent cleanup. Included by baseline extraction; do not replay separately. | -| PR #134 / `feat/claude-current` | Non-draft, with a clean sibling worktree at `11037f0`. Preserve/review the resolver and restart checker, installer additions, lane preflight/fencing, timeout containment and tests. Carry implementation/install payloads to code and their manual to spec; if landed before freeze, regenerate the baseline instead of replaying them. | +| PR #134 / `feat/claude-current` | Merged as `daed209`; the retained clean checkout at `11037f0` is preservation history. Resolver/checker, installer, preflight/fencing, timeout tests and manual are included by the regenerated baseline. Do not replay separately or retire the checkout as part of planning. | | PR #61 | Merged as `14641fd`, an ancestor of current main; included by baseline extraction. Do not replay the retired claim-takeover branch separately. | | Retired `002`, `003`, lclaude and detached worktrees | Removed from current registrations/local branches by cleanup. Verify cleanup/preservation receipts; remove from the active replay queue and do not recreate them from the old snapshot. | | Remote-only preservation refs | `chore/preserve-local-planning-20261003` and `takeover/ort-a9-dirty-snapshot-20260913` remain locally observed remote-tracking refs with no checkout; review as preservation history, not active writers. | -| Migration feature `004` | Previous refresh committed at `8aa119f`; existing checkout reused for this update. Carry current plan/spec/tasks into spec; review assembly/code follow-ups separately. | +| Migration feature `004` | Previous refresh committed at `dda91f1`; existing checkout reused for this update. This full proposal and canonical feature files stay in spec; any genuine bounded implementation amendments belong in code. | **Gate A:** every preserved object is attributable and restorable; no active writer can silently invalidate capture. Baseline, visibility and work @@ -94,6 +105,13 @@ baseline accounting, leg histories and recursive bootstrap. Exercise all actual file-placement collisions. If the standard refuses or misaccounts content, relay it and resolve through a reviewed standard change/pin bump; do not patch the pinned submodule or adjust digests to manufacture success. +Review genuine amendment paths explicitly as code using a reasoned project-local +resolution until the upstream exception is qualified. Full proposals created +on feature branches remain full proposals in spec; do not manufacture amendments +for historical features. Record original approved repository/commit/path and +verified extracted spec correspondence: filtering may change commit hashes. +Repair relative links, selected roots/stores and task paths without guessing +new baseline identities or replacing approval provenance with the split tip. Implement and review the necessary installer entry point/resolver, explicit test-root context, CI layout, agent pointers, docs paths and workflow bootstrap @@ -103,6 +121,15 @@ Add leg root guidance without overwriting original root guidance. Preserve the Bash 3.2 floor and original no-submodule test behavior, while requiring complete dependencies for composed acceptance. +Operate full proposals from the intended feature spec checkout and bounded +amendments from the code feature folder. Verify checkout, branch and root for +each operation; a local root takes precedence over a docs-store pointer. +Use explicit `--store` only if the installed CLI supports it and resolves the +intended feature checkout. Maintain amendments manually until schema/routing +is qualified. Check workBenches protocol/command distribution on each target +workstation; regeneration of root scaffolding alone does not distribute this +decision. Pending automation remains with workBenches/openRepoShape. + **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. @@ -128,13 +155,33 @@ stops landing; preserve source and newly created evidence/branches. Never rerun over live legs or bypass a ruleset. After successful source verification, apply reviewed follow-ups through the -new leg/root PRs. Resolve `shape/` collisions explicitly; do not overwrite +new leg/root PRs and prepare docs/code review together. For bounded migration +adjustments, record decision authority, approved baseline, unique amendment ID, +affected requirements/tasks and evidence in code; update working Speckit files +in the paired spec worktree before dependent implementation. Create one spec +reconciliation issue at the first amendment and link every later record. Larger +scope, runtime, authority or external-contract changes require full spec +governance; defer unnecessary capabilities to linked future-proposal issues. +Speckit remains the sole executable task list. + +Resolve `shape/` collisions explicitly; do not overwrite pinned shape files. Put `Read AGENTS-shape.md first...` guidance first in root agent instructions and bootstrap shape-aware OpenSpec/Speckit only when both -legs exist. Land required leg changes; advance root gitlinks, pin digests and -workflow SHAs together using the standard bump tool. - -**Gate D:** exact assembled commits pass manifest/pin checks, canonical code +legs exist. Prepare continued-feature translations and disposable workflow +checks from Phase 5 in the candidate before the final migration batch; actual +lane rebinding still waits for reviewed cutover. After implementation and verification, reconcile the net tested +effect in one final spec batch: governing specs/contracts/design, dated departures, +as-built record, all amendment dispositions, evidence, deferred ideas and the +actual landed code commit. Retain superseded/reverted/deferred history while +excluding inactive deltas. Preserve archived approvals through linked records. +Code may land first; completed assembly advancement waits for reconciliation +to land and matching spec/code pins. Close the reconciliation issue after the +spec PR lands; the feature landing record tracks the assembly PR. Advance +gitlinks, pin digests and workflow SHAs together using the standard bump tool. + +**Gate D:** prepared continued-feature receipts and disposable workflow checks +are reviewed; final reconciliation and matching spec/code commits are landed; +exact assembled commits pass manifest/pin checks, canonical code tests/platform checks, install compatibility and bootstrap. The existing source/install remain usable until root adoption review and merge complete. @@ -162,8 +209,15 @@ using the existing binding tools and exact session records. **Gate E:** every continued feature has a reviewed migration receipt and preserved source; bindings and workflow resolve the intended new trees. +Each continued feature retains its governing baseline and reconciliation +obligations; migration does not declare unfinished features implemented. Obsolete PR disposition and any old-worktree retirement are separate explicit decisions after verification, never an automatic cleanup step. +Archive the migration's full spec change only after implementation and assembly +pin landing. Explicitly select that root; a local amendment archive proves no +reconciliation. Pin subsequent archive-record spec commits normally. Reopen +reconciliation if behavior changes afterward; cancellation records abandonment +and dispositions rather than an as-built result. ## Rollback diff --git a/specs/004-migrate-to-triad/protocol-review.md b/specs/004-migrate-to-triad/protocol-review.md new file mode 100644 index 00000000..fe4464df --- /dev/null +++ b/specs/004-migrate-to-triad/protocol-review.md @@ -0,0 +1,48 @@ +# Migration protocol review — October 4, 2026 + +This refresh applies the adopted manual **Triad Feature Amendments** section +of the installed shared OpenSpec/Speckit workflow, including its +single-repository-to-triad migration instructions. Approval/extraction/history, +per-path verification and exact-pin mechanics remain governed by openRepoShape. +The consumer standard remains pinned at `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. + +## Sources read + +| Source identity | Snapshot SHA-256 | +| --- | --- | +| `$AGENT_PROTOCOL_ROOT/protocols/openspec-speckit-workflow.md` | `867b09a1329a2ba1c8005f2fbe43a4857f4eba7dd69c474c4e03d54bb2ecc20c` | +| `$AGENT_PROTOCOL_ROOT/protocols/project-agent-bootstrap.md` | `39341a7d0958e5efb9af5aa69de6e692d03129047cbcad48ad7f32bb8076ee28` | +| workBenches `docs/triad-feature-amendments.md` | `549d35974d42f474f2c7b2004e900b943c9a4543c479b97c541f47de1035f8d7` | +| workBenches `docs/triad-feature-amendment-templates.md` | `43647f4419dac8e28a3f428469ae27acd1444846736e9d388d967bb93c500a5f` | + +The workBenches documents and governing +`openspec/changes/adopt-triad-feature-amendments/` were read from its working +branch, where they were uncommitted at inspection. These content digests identify +the reviewed drafts; they are not landed commit identities or distribution +evidence. The installed protocol records Brett Heap's October 4 adoption of +manual use. Schema, managed root routing, template distribution and upstream +placement automation remain pending in their owning repositories. + +## Application to this migration + +- Keep full proposals, archives, canonical specs/contracts and Speckit files + in spec, including proposals authored on existing feature branches. Do not + manufacture amendments for historical features. +- Put genuine bounded amendment records in the code feature folder + `features//openspec/`. Review them explicitly in the mapping + until the upstream exception is qualified. No tracked amendment folders were + observed in current main or retained feature heads. +- Preserve approved original repository/commit/path provenance and verify + correspondence to extracted spec identities. Repair links/root selection; + filtered hashes cannot be guessed or substituted for approval evidence. +- Update working Speckit instructions immediately for accepted bounded changes; + record authority, requirements/tasks, evidence and dispositions manually. + New runtime/capability/authority/external obligations use full governance. +- At the first amendment, create one spec reconciliation issue. Reconcile all + net tested effects once at completion, linking landed code and evidence. + Completed assembly advancement waits for matching reconciled spec/code pins. + Archive only after implementation and assembly landing; explicitly select + the full spec root and preserve inactive/archived history. + +Implementation remains in [tasks.md](tasks.md); no external issue, schema, +protocol distribution, installation or migration was executed by this refresh. diff --git a/specs/004-migrate-to-triad/quickstart.md b/specs/004-migrate-to-triad/quickstart.md index a63a83b8..7f225487 100644 --- a/specs/004-migrate-to-triad/quickstart.md +++ b/specs/004-migrate-to-triad/quickstart.md @@ -1,7 +1,9 @@ # Review this migration plan Read [plan.md](plan.md), then the [resolved adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) -and [work inventory](inventory.json). The mapping is for the recorded source +and [work inventory](inventory.json). Read the [protocol review](protocol-review.md) +for canonical spec placement, bounded code amendments and final reconciliation. +The mapping is for the recorded source main only; implementation and live feature transfer have not been attempted. From the original source checkout, the planning validation is: @@ -24,6 +26,14 @@ regenerate the plan using `adopt-project.py plan`, retain reviewed resolutions and follow-ups, then recheck. Do not change the baseline field to suppress a stale-plan finding. Do not run real `execute` as a planning check. +After adoption, full proposal commands select the intended spec feature checkout; +bounded amendments use their explicitly verified code-local root. Newer CLI +store selection is optional and must resolve the intended feature branch. +Use manual records until schema/routing/distribution is qualified. Update working +Speckit instructions immediately for accepted amendments; reconcile the net +tested effect once before completed assembly advancement. A local archive +cannot substitute for full spec reconciliation or assembly landing. + Before execution, complete Gates A/B and review the actual frozen baseline, visibility, mapping, follow-ups and preservation receipts. The standard requires explicit approval before repository creation. All execution tasks are open in diff --git a/specs/004-migrate-to-triad/research.md b/specs/004-migrate-to-triad/research.md index acf1eb64..e38cfa29 100644 --- a/specs/004-migrate-to-triad/research.md +++ b/specs/004-migrate-to-triad/research.md @@ -7,14 +7,19 @@ No external writes, repositories, installation or migration occurred. | Finding | Decision / execution consequence | | --- | --- | -| October 4 main still matches GitHub at `82ecebe` (79 commits), 58 tracked paths and one standard gitlink | Regenerate/check the current main mapping; #61 and #146 remain included without replay. | +| Main advanced to `daed209` with merged #134: 80 commits, 64 tracked paths and one standard gitlink; GitHub matches | Regenerate/check the mapping: 18 spec / 40 code / six root, no drops; #61/#146/#134 are included without replay. | | Classifier treats shipped Markdown skills/commands as specification | Override to code with written reasons; these are installation payloads. | | Original contract is the implementation's upstream dependency lock | Keep code pin/gitlink/.gitmodules together; generated assembly pins are separate. | | `.specify` and agent directories are ignored local scaffolding | Preserve local config separately and regenerate root workflow after adoption. | -| Six current worktrees/local branches; main and all feature checkouts clean before refresh edits; open PRs #134/#121/#97 | Keep retired `002`/`003`, lclaude, detached, claim-takeover and #146 checkouts out of replay. Clean status alone does not complete preservation Gate A. | +| Six current worktrees/local branches; open PRs #121/#97; concurrent #121 staged/unstaged/untracked work and advanced #97 head | Preserve current active contents, not the earlier clean observation. Retain merged #134 checkout without replay; retired checkouts stay out of replay. | +| PR #121 now owns feature 005 confirmed-legacy-only restart and a full authority decision; managed/unknown ownership refuses and merge hold remains | Preserve the entire index/working/untracked delta and continue paired `005`; full authority/runtime governance remains spec, independent of #97 and feature 001 managed authority. | | Feature 001 advanced to clean `3c26041`, committing broker/task-recovery work and restoring rollover/workspace packets | Preserve its complete branch delta and restored governance/ideation; remove the stale requirement to capture the previous dirty files as uncommitted work. | | Feature 001 now selects required local Omnigent for `lclaude → oclaude → profile launch`, with implementation/qualification pending | Carry launcher contract, FR-047/T063–T065, LS custody/input fences and separate factory-broker gates; keep wrapper ownership in workBenches and transport ownership in Omnigent. | -| Non-draft #134 advanced to `11037f0` and has a clean sibling worktree | Carry code installer/resolver/preflight/timeout/test changes and spec manual if unmerged; regenerate baseline if it lands before freeze. | +| #134 merged as `daed209`; clean sibling worktree remains at `11037f0` | Installer/resolver/preflight/timeout/test changes and manual are included in the regenerated main baseline; retain checkout as recovery history. | +| Installed protocol now adopts manual Triad Feature Amendments; workBenches source docs are uncommitted drafts | Record source digests in protocol review; preserve full proposals/canonical files in spec and genuine bounded records in code. Do not claim distribution or automated qualification. | +| Pinned upstream classifier has no qualified amendment exception; no amendment paths observed in current source/retained heads | Explicitly review future genuine paths as code with reasoned local resolutions or a later reviewed upstream rule; do not edit pinned consumers or manufacture historical amendments. | +| Filtered commits may change approved spec identity | Preserve original repository/commit/path and verify extracted correspondence; repair links and selected roots without guessed hashes. | +| Bounded amendments require immediate working files and one final docs reconciliation | Extend the existing 19 tasks; create one spec issue at first amendment, reconcile tested net effect, and block completed assembly advancement until matching reconciled spec/code land. | | Two remaining preservation refs have no local worktrees | Review their history as recovery evidence; do not treat them as active writers or require recreation. | | Estate status refuses this manifest-free single repository | Relay no-estate refusal; use local Git and read-only GitHub observations now, then estate status after adoption. | | Installer fetches bare paths from `openRepoTools` and local sibling payloads | Preserve public root entry point and bind every payload to one code pin. | diff --git a/specs/004-migrate-to-triad/spec.md b/specs/004-migrate-to-triad/spec.md index 6799586e..273cbff1 100644 --- a/specs/004-migrate-to-triad/spec.md +++ b/specs/004-migrate-to-triad/spec.md @@ -27,8 +27,10 @@ preserved. Test forks/ref overrides, missing pins and partial fetch refusal. The operator continues existing feature IDs through paired spec/code worktrees and lands their changes through leg PRs followed by a validated assembly pin -bump. OpenSpec runs in spec; Speckit runs from the assembly with selected -feature paths. A code-only clone cannot falsely claim composed CI success. +bump. Full OpenSpec proposals run in the selected spec checkout; genuine +bounded amendments use the code feature folder with explicit root selection. +Speckit runs from assembly with selected feature paths. A code-only clone +cannot falsely claim composed CI success. The migration preserves feature 001's model-role assignments and open gates. ## Functional requirements @@ -45,8 +47,10 @@ The migration preserves feature 001's model-role assignments and open gates. - **FR-005**: Keep original installation entry points and one immutable payload revision, including forks/ref overrides, local/offline behavior and existing all-or-none ownership/receipt semantics; do not depend on developer checkouts. -- **FR-006**: Put product OpenSpec/Speckit/docs in spec and implementation plus - shipped skills/commands/tests in code; project workflow stays at root. +- **FR-006**: Put full proposals, archives, canonical OpenSpec/Speckit/docs in + spec and implementation plus shipped skills/commands/tests in code; project + workflow stays at root. Genuine bounded feature amendments are the narrow + code placement exception under FR-013, not a second spec baseline. - **FR-007**: Continue selected feature deltas with old/new identity and content receipts, paired leg worktrees and unchanged feature/role meanings. Do not merge old monorepo branches over the adopted assembly. @@ -61,6 +65,30 @@ The migration preserves feature 001's model-role assignments and open gates. acceptance; use non-destructive rollback and existing estate/WIP contracts. - **FR-012**: Treat visibility, baseline, branch disposition and lane rebinding as reviewed execution decisions; never infer approval from generated metadata. +- **FR-013**: Explicitly review genuine bounded + `features//openspec/` records as code until upstream placement + is qualified. Full proposals retain their role regardless of source branch; + do not manufacture local amendments for historical features or change pins + to hide an unqualified placement rule. +- **FR-014**: Preserve approved original repository/commit/path provenance and + verify correspondence to extracted spec identities after filtering. Repair + cross-leg links, baseline references and selected feature roots/stores without + guessing new hashes or editing pinned base mounts. Maintain records manually + until schema/routing/distribution is qualified in its owning repositories. +- **FR-015**: Record accepted bounded adjustments with unique feature-local IDs, + approved baseline, authority/source, affected requirements/tasks, verification + impact and dispositions; update working spec/plan/acceptance/tasks before + dependent implementation. Larger scope, runtime/authority or external-contract + changes require full spec governance; unnecessary larger ideas remain deferred + to linked future-proposal issues. Speckit is the only executable task list. +- **FR-016**: Create one spec reconciliation issue at the first amendment. + Reconcile net tested effects once at completion, retaining all dispositions, + approved history, as-built departures, verification and landed code identity. + Completed assembly advancement requires landed reconciliation and matching + spec/code pins. Close the issue after spec landing; explicitly archive the + full spec root only after implementation and assembly landing, advancing any + archive commit normally. Reopen for later behavior changes; cancellation + records abandonment, not as-built completion. ## Success criteria @@ -74,6 +102,13 @@ The migration preserves feature 001's model-role assignments and open gates. required CI pass for the selected composed project; no hidden skips. - **SC-005**: A rehearsed rollback restores usable development/installation without discarding work, altering private workspace pointers or force pushes. +- **SC-006**: Every continued feature has verified baseline correspondence, + explicit root selection and correct artifact roles; local archive cannot + satisfy canonical reconciliation. Manual workflow and pending automation are + separately evidenced on target workstations. +- **SC-007**: The tested migration has a final spec reconciliation and matching + landed code identity before completed assembly advancement, with every + amendment disposition accounted for and inactive deltas excluded. ## Assumptions and approval diff --git a/specs/004-migrate-to-triad/tasks.md b/specs/004-migrate-to-triad/tasks.md index 4c070093..b1a16859 100644 --- a/specs/004-migrate-to-triad/tasks.md +++ b/specs/004-migrate-to-triad/tasks.md @@ -4,7 +4,7 @@ The sole executable task list for the governing OpenSpec change. Planning artifacts and preliminary mapping validation do not complete these tasks. Every task remains open. Run implementation from the selected feature worktrees; actual repository creation/cutover require the approval gates. -The October 4 refresh updates the snapshot/mapping portion of T001/T003 only; +The protocol refresh updates snapshot/mapping and planned workflow follow-ups; owner decisions, private preservation/restore receipts and execution gates remain pending. Retired checkouts are not instructions to recreate worktrees. @@ -25,7 +25,11 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. - [ ] T003 [US1] Confirm proposed leg names/visibility and inspect prerequisite availability; regenerate `adoption-plan.yaml` for the reviewed preliminary rehearsal source, retaining reasoned overrides. Verify standard `check` - passes and records all source paths with no unapproved drops. + passes and records all source paths with no unapproved drops. Explicitly + classify genuine bounded feature amendment folders as code until upstream + qualification; preserve full proposals/archives/canonical Speckit as spec + regardless of branch origin. Record no amendment paths when none exist; + do not manufacture historical amendments or weaken shape pins. ## Phase 2 — Local adoption rehearsal (Gate B foundation) @@ -42,6 +46,11 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. reviewable patches; bootstrap selected root workflow after manifest/legs exist. Verify first-line shape guidance, relative paths, actual `.specify` configuration and paired feature selection without copying machine secrets. + Verify explicit full-spec/local-amendment roots and intended feature branches, + local-root precedence over store pointers and supported CLI store selection. + Keep manual records until schema/routing is qualified; check protocol/command + distribution per target workstation through owning workBenches delivery, + without treating a scaffold bootstrap as distribution of this manual decision. ## Phase 3 — Installation and checks (Gate B completion) @@ -77,13 +86,23 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. - [ ] T013 [US1] Execute the approved standard adoption from the isolated clone. Verify and relay the complete content-accounting table and root PR details; stop landing on any refusal/mismatch, retaining all source/evidence. -- [ ] T014 [US3] Apply reviewed follow-ups through leg/root PRs, land required - leg commits, and advance root gitlinks/pins/workflow SHAs with standard tools. - Verify no in-place edits to copied pinned shape files or the mounted standard. +- [ ] T014 [US3] Apply reviewed follow-ups and prepare code/spec PRs together. + For accepted bounded adjustments, retain authority/baseline/requirements/tasks + and dispositions in manual code-local records, update working Speckit files + before implementation and create one spec reconciliation issue at the first + amendment. Escalate larger current scope to full governance; defer unnecessary + capabilities to linked future issues. Prepare final reconciliation against + tested behavior; code may land first, but completed assembly advancement waits + for matching reconciled spec. Verify no in-place pinned-shape edits. - [ ] T015 [US2] Validate the real exact assembled head using canonical tests, required platform/CI, installed/local/raw compatibility, bootstrap and rollback - checks. Verify all Gate D results belong to the selected commits before root - adoption merge; keep original development/install available until then. + checks, including prepared continued-feature translations and disposable + workflow evidence from T016–T018. Complete one final spec reconciliation batch with net tested effects, + every amendment disposition, dated departures/as-built record, archived approval + provenance, deferred issues and actual landed code/evidence. Land spec, close + its reconciliation issue and advance matching root gitlinks/pins/workflow SHAs + with standard tools; verify final Gate D results at the actual selected commits + before root adoption merge. Keep original development/install available. ## Phase 5 — Continue features and controlled cutover (Gate E) @@ -93,33 +112,49 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. amendment and open runtime gates. Carry the clean `3c26041` checkpoint's restored rollover/workspace packets, launcher contract and FR-047/T063–T065; preserve workBenches/Omnigent ownership and required local adapter qualification - separately from factory-broker admission. Do not replay completed work or claim new + separately from factory-broker admission. Preserve approved original repository/ + commit/path and verify extracted spec correspondence, repairing links/task roots + without guessed hashes. Full feature-branch proposals remain in spec; preserve + any actual bounded records in code and continued reconciliation obligations. + Do not replay completed work or claim new runtime acceptance from migration. - [ ] T017 [US1] Translate every other approved continued PR/branch/detached worktree, including this migration feature, with explicit spec/code/root mappings and conflict review. Verify each object has a complete receipt or approved archived-original disposition; preserve original PR review history. - Current candidates are #97/#121/#134 and feature 004. Account for merged - #61/#146 through the baseline and retired checkout history through its receipts; - do not recreate cleaned worktrees or replay integrated changes. PR #134 is - non-draft at `11037f0` with a clean worktree: account for its resolver/checker, - installer, lane preflight/fencing, timeout containment, manual and tests. + Current candidates are #97/#121 and feature 004. Account for merged + #61/#146/#134 through the baseline and retired/retained merged checkout history + through receipts; do not recreate cleaned worktrees or replay integrated changes. + Verify approved baseline correspondence and artifact roles for every continued + feature, including this migration's full proposal in spec. + Capture PR #121's complete active index/working files and untracked `005` + feature/full legacy authority decision; carry its confirmed-legacy-only scope, + managed/unknown refusal and merge hold into paired `005` continuation. Keep + PR #97's separately owned diagnostics and current branch head independent. - [ ] T018 [US3] Exercise OpenSpec/Speckit feature selection and estate park/resume in disposable triad fixtures, then perform reviewed binding/WIP transitions through supported tools at owner breakpoints. Verify correct feature roots/session bindings and relay refusals without force repairs. - [ ] T019 [US3] Publish Gate E/cutover evidence and actual PR dispositions; verify all continued features are usable and recoverable before requesting - separate old-worktree retirement. Do not auto-close old PRs or delete backups. + separate old-worktree retirement. Verify each continued feature retains its + outstanding reconciliation/runtime gates rather than declaring it implemented. + Archive the migration's full spec change only after implementation and assembly + pin landing; explicitly select its root and pin any later archive commit normally. + Reopen reconciliation for subsequent behavior changes; record cancellation as + abandonment. Do not auto-close old PRs or delete backups. ## Dependencies T001–T003 precede rehearsal. 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. T013–T015 precede root adoption merge. T016–T018 can be prepared in -the candidate after legs exist, but actual lane rebinding follows reviewed -cutover and safe breakpoints. T019 requires validated retained feature receipts. +boundary. T013–T015 precede root adoption merge. Prepare T016–T017 translations +and T018 disposable workflow checks in the candidate after legs exist, before +T015's final reconciliation. Actual T018 lane rebinding follows reviewed root +adoption/cutover and safe breakpoints. T019 requires validated retained feature +receipts; later behavior changes reopen reconciliation before another completed +assembly advancement. ## Requirement coverage @@ -136,3 +171,7 @@ cutover and safe breakpoints. T019 requires validated retained feature receipts. | FR-010 | T003–T005, T011–T013 | | FR-011 | T002, T011, T018–T019 | | FR-012 | T001, T012, T018–T019 | +| FR-013 | T003, T006, T016–T017 | +| FR-014 | T006, T016–T018 | +| FR-015 | T014–T015 | +| FR-016 | T014–T015, T019 | diff --git a/specs/004-migrate-to-triad/verification.md b/specs/004-migrate-to-triad/verification.md index d2834533..57c0a9e4 100644 --- a/specs/004-migrate-to-triad/verification.md +++ b/specs/004-migrate-to-triad/verification.md @@ -1,6 +1,48 @@ # Migration planning verification — October 4, 2026 -## October 4 repository refresh +## Updated migration protocol refresh + +Read the installed shared workflow's **Triad Feature Amendments**, including +**Single repository to triad migration**, the revised bootstrap status and +workBenches source workflow/templates/governance. [protocol-review.md](protocol-review.md) +records their identities and snapshot digests, including the uncommitted draft +state of the workBenches source. Manual adoption does not establish delivered +schema/routing/distribution/placement automation. + +The revised proposal, design, capability requirements and Speckit plan/tasks +now distinguish canonical spec content from genuine bounded code amendments, +retain original approved provenance with verified filtered correspondence, +require explicit root selection and working-spec updates, and require one +final tested reconciliation before completed assembly advancement. No existing +tracked bounded amendment paths were observed in main or retained feature heads; +none were manufactured. All 19 implementation tasks remain open, covering 16 +migration requirements. + +Source main advanced to `daed20957f2dd2f22cca24053bb5bc8636ff6b3f` with #134 +merged at `2026-10-04T16:52:38Z`; read-only GitHub main matched. The two open +PRs are #121 and #97. Six worktrees/local branches remain, including the clean +merged #134 checkout and clean feature 001 at `3c26041`. Main extraction now +includes the resolver/checker installer changes, tests and manual. +The final snapshot check detected concurrent #121 staged/unstaged/untracked +work, including feature 005 and its full legacy authority decision, plus an +advanced #97 recovery head. Inventory/dispositions were refreshed to preserve +those active changes, separate ownership and the existing #121 merge hold; +the earlier all-clean observation is historical, not current readiness. + +The pinned standard regenerated the main-only plan: 64 source paths, 18 spec / +40 code / six root, no unresolved path or drop, 80 commits and 28 follow-ups. +Standard `check`, OpenSpec strict validation, supplemental path/link/inventory/ +requirement checks and `git diff --check` passed. Planning checks do not establish +upstream exception qualification, local rehearsal or runtime acceptance. + +Estate `status --fetch` again refused the manifest-free repository and fetched +nothing; local Git and read-only GitHub supplied current observations. This +refresh created no external issue, moved no lane, rewrote no workspace pointer, +changed no pinned standard, distributed no protocol and performed no adoption. + +The previous refresh sections below are historical evidence only. + +## Earlier October 4 repository refresh — historical Read-only GitHub main still matches local `82ecebee13edaa915b68550170faffdf761754d5`. The pinned standard remains `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. From 5455805d623b6d3e2943606745c4ac812dc40be5 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Sun, 4 Oct 2026 21:33:18 +0000 Subject: [PATCH 05/12] docs: record triad preparation and adopter blocker --- .../migrate-to-triad/adoption-plan.yaml | 2 + openspec/changes/migrate-to-triad/design.md | 5 +- openspec/changes/migrate-to-triad/proposal.md | 6 + openspec/changes/migrate-to-triad/tasks.md | 3 +- specs/004-migrate-to-triad/adopter-blocker.md | 68 ++++++ .../004-migrate-to-triad/installer-design.md | 97 ++++++++ specs/004-migrate-to-triad/inventory.json | 207 +++++++++++++++--- specs/004-migrate-to-triad/plan.md | 28 ++- specs/004-migrate-to-triad/preparation.md | 115 ++++++++++ specs/004-migrate-to-triad/quickstart.md | 5 +- specs/004-migrate-to-triad/research.md | 7 + specs/004-migrate-to-triad/tasks.md | 14 +- specs/004-migrate-to-triad/verification.md | 32 +++ 13 files changed, 547 insertions(+), 42 deletions(-) create mode 100644 specs/004-migrate-to-triad/adopter-blocker.md create mode 100644 specs/004-migrate-to-triad/installer-design.md create mode 100644 specs/004-migrate-to-triad/preparation.md diff --git a/openspec/changes/migrate-to-triad/adoption-plan.yaml b/openspec/changes/migrate-to-triad/adoption-plan.yaml index cf1678f3..f9d26fbe 100644 --- a/openspec/changes/migrate-to-triad/adoption-plan.yaml +++ b/openspec/changes/migrate-to-triad/adoption-plan.yaml @@ -1,4 +1,6 @@ # 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. schema_version: 1 kind: adoption-plan diff --git a/openspec/changes/migrate-to-triad/design.md b/openspec/changes/migrate-to-triad/design.md index fc1e42ee..a51ee15a 100644 --- a/openspec/changes/migrate-to-triad/design.md +++ b/openspec/changes/migrate-to-triad/design.md @@ -63,7 +63,10 @@ belong in spec; regenerate the path plan if the source adds such contracts. Keeping the standard in root would move its gitlink away from its dependency pin and implementation consumers, and mutate the original `.gitmodules` during the byte-accounted split. Keeping that dependency unit in code preserves its -existing paths. Existing-submodule handling still requires local rehearsal; +existing paths. The provisional local rehearsal measured a mounting refusal +after staging deletion of the original `.gitmodules`; see the +[reproduction](../../../specs/004-migrate-to-triad/adopter-blocker.md). +Resolve upstream and repeat before composed acceptance; plan coverage validation alone is not execution certification. ### Public installation compatibility diff --git a/openspec/changes/migrate-to-triad/proposal.md b/openspec/changes/migrate-to-triad/proposal.md index 76718921..1275c04e 100644 --- a/openspec/changes/migrate-to-triad/proposal.md +++ b/openspec/changes/migrate-to-triad/proposal.md @@ -2,6 +2,12 @@ ## Why +Preparation is authorized while PRs #97/#121 are active; real conversion waits +for both to land. The [preparation receipt](../../../specs/004-migrate-to-triad/preparation.md) +records provisional preservation and a local adopter refusal. Resolve that +upstream blocker and refresh the merged baseline, preservation and rehearsal +before the existing real-execution approval gate. + openRepoTools currently keeps product decisions, implementation and project workflow in one repository. Elect the openRepoShape triad so specifications and implementation can evolve independently while the existing repository diff --git a/openspec/changes/migrate-to-triad/tasks.md b/openspec/changes/migrate-to-triad/tasks.md index 858e93fc..6ef4d5bc 100644 --- a/openspec/changes/migrate-to-triad/tasks.md +++ b/openspec/changes/migrate-to-triad/tasks.md @@ -10,7 +10,8 @@ This checklist tracks governance, not duplicate implementation tasks. artifacts exist and planning validation is recorded. - [ ] 1.2 Approve the frozen source/standard revisions, repository visibility, final path mapping, follow-ups and active-work dispositions after Gates A/B; - verify approval explicitly names the actual execution plan. + verify #97/#121 have landed, their content is accounted for through the + refreshed baseline, and approval explicitly names the actual execution plan. ## 2. Migration evidence and closure diff --git a/specs/004-migrate-to-triad/adopter-blocker.md b/specs/004-migrate-to-triad/adopter-blocker.md new file mode 100644 index 00000000..a0b8980e --- /dev/null +++ b/specs/004-migrate-to-triad/adopter-blocker.md @@ -0,0 +1,68 @@ +# Pinned adopter refuses an existing submodule split + +**Upstream:** opensoft/openRepoShape, pinned revision +`39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. +**Consumer:** openRepoTools main +`daed20957f2dd2f22cca24053bb5bc8636ff6b3f`. +**Measured:** October 4, 2026; disposable local remotes only. + +The reviewed mapping moves the existing `.gitmodules` together with +`upstream/openRepoShape` and its dependency contract into code. Plan `check` +passes. Both filtered legs are created, then assembly mounting returns 2: + +```text +REFUSED a git or gh command failed. THE EXACT COMMAND WAS: + git -c protocol.file.allow=always submodule add -q spec + (in ) + exit 128 +--- output --- +fatal: please make sure that the .gitmodules file is in the working tree +--- end output --- +``` + +`adopt-project.py`'s `_mount_the_legs` (line 1201 at this pin) removes moved +paths with `git rm`, then immediately invokes `git submodule add`. `.gitmodules` +is among the moved files; its tracked deletion is still staged when the new +submodule registration is attempted. The root index contains only the six +original front-door files at refusal. The generated assembly registrations +have not been created. Git's missing-file guard is the observed failure; no +assumption about nested dependency correctness substitutes for this evidence. + +## Reproduction for upstream review + +Use a fresh isolated clone of the consumer at the recorded commit, a copy of +the resolved [adoption plan](../../openspec/changes/migrate-to-triad/adoption-plan.yaml), +git-filter-repo 2.47.0, and empty disposable local directories: + +```sh +python3 /adopt-project.py check \ + --source --plan +python3 /adopt-project.py execute \ + --source --plan \ + --local-remote-dir \ + --work-dir --yes +``` + +The yes here covers the reviewed local test only. 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. + +Expected behavior: preserve the original registration in code, create fresh +assembly registrations for spec/code, complete source accounting, and retain +the dependency gitlink/contract identity. The source repository must remain +unchanged if execution refuses. + +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. +Also cover partial registration ownership and no-existing-module inputs so a +fix cannot silently erase retained registrations or create duplicate owners. + +No upstream issue or PR was published. No patch was applied to the pinned +checkout or failing candidate. Resolve through the owning repository's normal +review, then bump to a commit on its main and recompute the dependency digest. +Repeat the consumer rehearsal with fresh remotes. Gate B remains blocked by +this refusal even though extraction content was independently verified. + +Private execution log SHA256: +`ca2a11775ca3b6d179fc038436a28090f65b05feb2a1611d4578b315733b5168`. diff --git a/specs/004-migrate-to-triad/installer-design.md b/specs/004-migrate-to-triad/installer-design.md new file mode 100644 index 00000000..4f174789 --- /dev/null +++ b/specs/004-migrate-to-triad/installer-design.md @@ -0,0 +1,97 @@ +# Installer follow-up design and compatibility matrix + +Prepared for [T007–T010](tasks.md), against main `daed20957f2dd2f22cca24053bb5bc8636ff6b3f`. +Implementation patches wait for successful standard split verification. PRs +#97/#121 can change payloads and tests; refresh this inventory after landing. + +## One implementation, two entry contexts + +Keep the current implementation in code. Add a small assembly `openRepoTools` +entry point that selects that implementation; preserve the documented raw and +gh installation one-liners. Installed `openRepoTools` remains the code +implementation so it runs independently of developer worktrees. The assembly +entry point must delegate all installation, merging, ownership and retirement +mechanics to it. + +The root entry point alone is insufficient: subsequent installed `--install`, +`--skill` and WIP template operations currently fetch from the monorepo's +`REPO`/`REF`. Those code-side consumers need the same payload-source resolution. +Separate the selected assembly source from the resolved code payload source; +keep the existing public `OPENREPOTOOLS_REPO`/`OPENREPOTOOLS_REF` meanings. +Do not infer a code repository by appending `-code` to a fork name. + +For an adopted remote, resolve the requested assembly ref once to an immutable +commit. Read `contracts/code-pin.yaml` at that commit, strictly validate the +code role, repository slug, commit, path and digest grammar, and confirm the +assembly gitlink agrees. Fetch the implementation and all its payloads from +that same code repository/commit. Moving branches cannot mix artifact versions. +A present malformed pin must refuse rather than fall back to the legacy layout. + +For a legacy monorepo with no adoption manifest/pin, retain the established +owner/repository/ref override path. Distinguish an authoritative missing path +from authentication, transport and parse errors; those errors are refusals, +not evidence of a legacy repository. Forks use their selected assembly pin. +gh-first and curl fallback apply to the same resolved identities. Reuse jq +where needed; no new general YAML runtime dependency is justified by a fixed +pin grammar. Do not claim whole-tree digest validation from one downloaded +file: the composed validator checks the complete tree, while remote installation +must at least verify the gitlink and immutable identity it actually consumes. + +For a local adopted checkout, require a consistent assembly/code pin and +materialized selected payload set, then copy those local bytes offline. An +explicit code feature checkout must remain a supported development context; +record its actual code identity without pretending it is the assembled pin. +Incomplete local payloads must refuse or fetch only from the established +matching source; arbitrary local siblings plus unrelated remote bytes must not +form a successful adopted install. Define this distinction in the implementation +and user-facing diagnostics before acceptance. Preserve normal legacy sibling +behavior where the legacy installer currently promises it. + +## Code consumers that change + +| Existing consumer | Required adjustment | +| --- | --- | +| `fetch_from_repo` | Use the resolved payload repository/immutable revision for code assets; retain transport fallback and useful refusal output. | +| `collect_commands`, `collect_skills` | Establish coherent local/remote source before collecting; preserve all-before-placement staging. | +| `wip_shape_ref` | Read/fetch code's `contracts/openreposhape-pin.yaml`, distinct from assembly's code pin. Preserve its existing upstream-standard role. | +| `wip_fetch_template_file` | Continue selecting the template from the upstream standard pinned by code; do not repoint templates to spec or assembly. | +| Root entry point | Resolve/select/delegate; forward arguments, exit status and signal/temporary-file cleanup. It adds no installer mechanics. | +| Installed receipts, settings/hook merge and retire functions | Preserve existing ownership, mode, target and refusal behavior; source routing must finish before placement. | + +Current command/data payloads are the 15 names in `INSTALLABLES`, including +`claude-current` and `claude-restart-check`. Three skills and three command +files each have two destinations: 27 placed files plus two hook entries, 29 +artifacts. Derive counts from the lists; source comments with historical counts +are not the contract. Hooks stay in the user's existing settings, preserving +unrelated entries. No machine-specific config enters a payload archive. + +## Compatibility acceptance + +All rows below are pending measured tests in fresh disposable homes/remotes. +They describe coverage for the existing executable tasks, not completion claims. + +| Scenario | Required observation | +| --- | --- | +| Existing raw/gh one-liners | Root delegates to selected code implementation; same names, help and destinations. | +| Offline local legacy / adopted checkout | Legacy behavior retained; complete adopted payload copied without network and pinned identity checked. | +| Explicit local code feature | Intentional feature bytes selected coherently and actual identity recorded. | +| Installed reinstallation and skill-only operation | Works without the developer checkout and resolves the selected assembly/code source. | +| Legacy override / adopted fork | Existing overrides work; fork follows its actual code pin rather than a guessed repository. | +| Branch, tag, commit and slash-containing refs | Ref resolved once; every remote payload uses one immutable code identity. | +| Branch changes between downloads | No mixed versions; subsequent requests use the frozen identity. | +| Missing pin in valid legacy / partial adopted layout | Valid legacy permitted; adopted missing/malformed/mismatched pin refused. | +| Missing or malformed API response / authorization / transport failure | No silent legacy fallback; actionable refusal, no placed files. | +| Changed local gitlink / changed payload / incomplete local payload | Coherence decision enforced before staging/placement; no unrelated-source mix. | +| Missing command, skill, alias or failed settings merge | Existing all-before-placement guarantee holds; prior install remains unchanged. | +| Modes, ownership receipts and custom target paths | Same modes and computed targets; foreign files and unrelated hook entries preserved. | +| WIP init/template lookup | Code dependency pin selects upstream templates; workspace writer restrictions unchanged. | +| Missing nested dependency in standalone code | Existing documented test skips remain; composed acceptance requires complete dependencies. | +| Linux/macOS Bash 3.2 and Windows/WSL policies | Correct parses/platform gates; no new Bash features or PowerShell implementation. | + +Tests and fixtures need explicit **code**, **spec**, **assembly** and +**dependency** roots. In particular, `tests/test_repo_hygiene.py` reads the root +README/install line and agent guidance, while `tests/test_upstream_pin.py` +reads code Git identity and the nested dependency. CI must supply the matching +contexts rather than delete those checks. Keep `tests/run.sh` as the serialized +test entry point, selecting with pytest filters such as `-k upstream_pin`. +The assembly exact-pin integration job must refuse absent required contexts. diff --git a/specs/004-migrate-to-triad/inventory.json b/specs/004-migrate-to-triad/inventory.json index 656b6cef..cb4dd823 100644 --- a/specs/004-migrate-to-triad/inventory.json +++ b/specs/004-migrate-to-triad/inventory.json @@ -1,5 +1,5 @@ { - "observed_at": "2026-10-04T17:40:54.465251+00:00", + "observed_at": "2026-10-04T21:24:50.021151+00:00", "source_repository": "opensoft/openRepoTools", "source_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", "github_main": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f", @@ -90,17 +90,17 @@ }, { "identity": "004-migrate-to-triad", - "head": "dda91f11c68818ebeca4264d88908c85818ff630", + "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2", "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 14, - "untracked_entries": 1, + "dirty_entries": 0, + "untracked_entries": 3, "locked": false, "prunable": false }, { - "identity": "feat/claude-current", - "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "identity": "feat/supervised-context-restart", + "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed", "layout": "legacy-sibling", "readable_here": true, "dirty_entries": 0, @@ -109,18 +109,18 @@ "prunable": false }, { - "identity": "feat/supervised-context-restart", - "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", - "layout": "legacy-nested", + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "layout": "legacy-sibling", "readable_here": true, - "dirty_entries": 43, - "untracked_entries": 3, + "dirty_entries": 0, + "untracked_entries": 0, "locked": false, "prunable": false }, { "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341", + "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6", "layout": "legacy-nested", "readable_here": true, "dirty_entries": 0, @@ -136,7 +136,7 @@ }, { "identity": "004-migrate-to-triad", - "head": "dda91f11c68818ebeca4264d88908c85818ff630" + "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2" }, { "identity": "feat/claude-current", @@ -144,11 +144,11 @@ }, { "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341" + "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6" }, { "identity": "feat/supervised-context-restart", - "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295" + "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed" }, { "identity": "main", @@ -170,21 +170,25 @@ "open_prs": [ { "number": 121, - "title": "`/ctx` writes its restart to disk before it kills anything, and what tmux starts is a supervisor that stays in the pane \u2014 the fresh session was an environment variable the launcher dropped (#94)", + "title": "Keep supervised manual ctx as legacy compatibility and refuse managed lanes", "headRefName": "feat/supervised-context-restart", - "headRefOid": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "headRefOid": "6c5b74176e9dbf7f9aad5a4ff8ec18ef0cbbb136", "isDraft": false, "url": "https://github.com/opensoft/openRepoTools/pull/121", - "state": "open" + "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": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "headRefOid": "eada5fff495452cf5da47e52d9550fa4b40a4c96", "isDraft": false, "url": "https://github.com/opensoft/openRepoTools/pull/97", - "state": "open" + "state": "open", + "merged": false, + "updated_at": "2026-10-04T21:05:20Z" } ], "merged_since_previous_snapshot": [ @@ -223,7 +227,8 @@ "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.", - "PR #121 now contains active staged/unstaged/untracked work including feature 005 legacy-only supervised restart and its full authority decision; preserve current contents and merge hold. Snapshot counts can change while owners continue." + "#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." ], "previous_refresh_snapshot": { "observed_at": "2026-10-04T16:37:26.292668+00:00", @@ -314,15 +319,19 @@ ] }, "latest_refresh": { - "previous_observed_at": "2026-10-04T16:37:26.292668+00:00", + "previous_observed_at": "2026-10-04T17:40:54.465251+00:00", "previous_worktrees": 6, "current_worktrees": 6, "current_local_branches": 6, "added_worktrees": [], "removed_worktrees": [], - "source_main_changed": true, - "protocol": "Shared OpenSpec/Speckit workflow: Triad Feature Amendments, adopted 2026-10-04; manual delivery only.", - "concurrent_work": "PR #121 retains staged/unstaged/untracked work including full legacy authority decision and feature 005; recovery branch advanced during refresh. Snapshot only, not a writer freeze." + "source_main_changed": false, + "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 + ] }, "protocol_review": { "adopted_on": "2026-10-04", @@ -345,28 +354,164 @@ }, { "identity": "004-migrate-to-triad", - "head": "dda91f11c68818ebeca4264d88908c85818ff630", + "head": "48934f8d4c662be6ed07ad1b7df96dec22028ab2", "bounded_amendment_paths": [], "working_bounded_amendment_paths": [] }, { - "identity": "feat/claude-current", - "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", + "identity": "feat/supervised-context-restart", + "head": "0e4b311dfa33abca55282a4974cb96c7d1c584ed", "bounded_amendment_paths": [], "working_bounded_amendment_paths": [] }, { - "identity": "feat/supervised-context-restart", - "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12", "bounded_amendment_paths": [], "working_bounded_amendment_paths": [] }, { "identity": "feat/crash-consistent-lane-worktree-recovery", - "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341", + "head": "07fb3adb8b4ac1476c641685096f00f0d20593c6", "bounded_amendment_paths": [], "working_bounded_amendment_paths": [] } ] + }, + "preparation_previous_snapshot": { + "observed_at": "2026-10-04T17:40:54.465251+00:00", + "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": "dda91f11c68818ebeca4264d88908c85818ff630", + "layout": "legacy-sibling", + "readable_here": true, + "dirty_entries": 14, + "untracked_entries": 1, + "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/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "layout": "legacy-nested", + "readable_here": true, + "dirty_entries": 43, + "untracked_entries": 3, + "locked": false, + "prunable": false + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341", + "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": "dda91f11c68818ebeca4264d88908c85818ff630" + }, + { + "identity": "feat/claude-current", + "head": "11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12" + }, + { + "identity": "feat/crash-consistent-lane-worktree-recovery", + "head": "8f69e96fbd33d84950b1acdaa2f2f3836c081341" + }, + { + "identity": "feat/supervised-context-restart", + "head": "5164ce1535b0f4f21d6b9e5b48318865a3c74295" + }, + { + "identity": "main", + "head": "daed20957f2dd2f22cca24053bb5bc8636ff6b3f" + } + ], + "open_prs": [ + { + "number": 121, + "title": "`/ctx` writes its restart to disk before it kills anything, and what tmux starts is a supervisor that stays in the pane \u2014 the fresh session was an environment variable the launcher dropped (#94)", + "headRefName": "feat/supervised-context-restart", + "headRefOid": "5164ce1535b0f4f21d6b9e5b48318865a3c74295", + "isDraft": false, + "url": "https://github.com/opensoft/openRepoTools/pull/121", + "state": "open" + }, + { + "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": "64dfd9736b1079c16beda0b1ac53a61e68b21d9e", + "isDraft": false, + "url": "https://github.com/opensoft/openRepoTools/pull/97", + "state": "open" + } + ], + "latest_refresh": { + "previous_observed_at": "2026-10-04T16:37:26.292668+00:00", + "previous_worktrees": 6, + "current_worktrees": 6, + "current_local_branches": 6, + "added_worktrees": [], + "removed_worktrees": [], + "source_main_changed": true, + "protocol": "Shared OpenSpec/Speckit workflow: Triad Feature Amendments, adopted 2026-10-04; manual delivery only.", + "concurrent_work": "PR #121 retains staged/unstaged/untracked work including full legacy authority decision and feature 005; recovery branch advanced during refresh. Snapshot only, not a writer freeze." + } + }, + "preparation_evidence": { + "record": "specs/004-migrate-to-triad/preparation.md", + "backup_id": "prep-20261004T211123Z", + "all_ref_restore_verified": true, + "refs": 18, + "dependency_commit_restore_verified": true, + "captured_worktrees": 6, + "snapshot_git_restores_verified": 6, + "git_restore_summary_sha256": "550d1ce96c8a162c3371f95b53be188217f85fac6491e98e628ae307ea35b31e", + "gate_a_complete": false, + "gate_b_complete": false, + "local_adoption_exit": 2, + "reproduction": "specs/004-migrate-to-triad/adopter-blocker.md" } } diff --git a/specs/004-migrate-to-triad/plan.md b/specs/004-migrate-to-triad/plan.md index 7ca2fd2d..f0df01fc 100644 --- a/specs/004-migrate-to-triad/plan.md +++ b/specs/004-migrate-to-triad/plan.md @@ -1,13 +1,20 @@ # Migration plan: openRepoTools assembly/spec/code triad **Feature**: `004-migrate-to-triad` | **Date**: 2026-10-03 -**State**: Proposed plan; no migration, install or repository creation performed +**State**: Preparation and disposable rehearsal performed; real adoption remains on hold **Refresh**: 2026-10-04; adopted amendment protocol and merged PR #134 incorporated **Spec**: [spec.md](spec.md) **Governance**: [proposal](../../openspec/changes/migrate-to-triad/proposal.md) ## Baseline and deliverables +The user authorized preparation while #97/#121 are active and will notify us +when they land. **Wait for both landings before real triad conversion.** The +[preparation receipt](preparation.md) records verified private preservation, +partial local extraction and a measured pinned-adopter refusal. Gates A/B are +still open. The [installer design](installer-design.md) is ready for follow-up +implementation after successful standard split verification. + The [adoption mapping](../../openspec/changes/migrate-to-triad/adoption-plan.yaml) was regenerated from main `daed20957f2dd2f22cca24053bb5bc8636ff6b3f` using pinned openRepoShape `39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. All 64 tracked @@ -23,10 +30,10 @@ retained `feat/claude-current` checkout, whose merged changes need no replay. The two open PRs are #121 and #97. Feature 001 remains at `3c26041a4444a10bc240cb64a168ece4d9edf6c5`, committing its broker/task-recovery changes, restored rollover/workspace packets and October 4 launcher contracts. -Main and feature 001 remain clean. Concurrent work in PR #121's checkout now -includes staged/unstaged/untracked content and `005-supervised-legacy-ctx`; -the recovery branch also advanced. The inventory is an observation, not a -freeze of active writers. +Main and feature 001 remain clean. PR #121's earlier dirty work, including +`005-supervised-legacy-ctx`, has advanced into newer commits; the recovery +branch also advanced. Local and remote PR heads can differ while owners work. +The inventory is an observation, not a freeze of active writers. The [inventory](inventory.json) keeps the October 3 cleanup as history and records current heads, dirty counts and the two remote-only preservation refs. Machine paths, secrets/transcripts and backup contents are omitted; private @@ -134,9 +141,18 @@ decision. Pending automation remains with workBenches/openRepoShape. follow-up patches, resolved mapping and a passing compatibility test matrix. Mapping `check` alone does not satisfy this gate. +The provisional rehearsal passed mapping check and preserved extracted bytes, +then returned 2 mounting the legs because `.gitmodules` was staged for deletion. +See [adopter-blocker.md](adopter-blocker.md). 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. + ## Phase 3 — Freeze and approve real adoption -Coordinate a bounded main landing hold using applicable lane protocol. Re-read +After #97 and #121 land, account for their final merged content through the +new main baseline instead of replaying it as unfinished work. Review any +remaining local deltas separately. Coordinate a bounded main landing hold +using applicable lane protocol. Re-read current main and owner state, finalize source commit, mapping, standard pin, visibility, follow-ups and preservation receipts. Any source drift requires plan regeneration and check, not editing the commit field by hand. Present diff --git a/specs/004-migrate-to-triad/preparation.md b/specs/004-migrate-to-triad/preparation.md new file mode 100644 index 00000000..11259027 --- /dev/null +++ b/specs/004-migrate-to-triad/preparation.md @@ -0,0 +1,115 @@ +# Preparation while PRs #97 and #121 are active + +**Observed:** October 4, 2026. **State:** provisional preservation and local +rehearsal performed; Gates A/B remain open. Real conversion waits for both PRs +to land and the refreshed execution approval. This evidence belongs to +[T001–T011](tasks.md); it is not another executable task list. + +## Preservation evidence + +Private backup ID: `prep-20261004T211123Z`. Exact locations, file lists, +configuration, indexes, binary patches and restore copies remain host-local, +outside the repository. No backup contents are published here. + +- Source bundle: all 18 refs verified against a restored mirror and the live + ref listing before/after capture. SHA256: + `86213b096b6057a1d0fd64b2a950856a6aa8375f87641f49330d205635909c0e`. +- Dependency bundle: verified and restored the pinned standard commit. + SHA256: `2549703215e77353129ebc4d73a5dc7f1f4fd07079b5d86cf259e91a662a20e4`. +- Six worktrees: copied tracked/untracked files and selected ignored workflow + configuration, saved indexes and binary patches, verified restore-copy bytes + and symlinks, and checked source HEAD/status/content stability during capture. + Restored all six captured heads into independent Git clones, reconstructed + the captured index entries, copied captured working/configuration bytes, and + verified matching porcelain status, including #121's working edits. Preserved + repository-local config/excludes separately; restoring the excludes was + necessary to reproduce ignored workflow configuration. This is a restore + rehearsal of the snapshots, not an owner-coordinated freeze or live rollback. + Private Git restore summary SHA256: + `550d1ce96c8a162c3371f95b53be188217f85fac6491e98e628ae307ea35b31e`. +- Installed files/settings/receipts: captured current configured/default and + PATH locations in host and py-bench contexts. Host: 29 locations checked, + 27 present regular-file copies verified. Bench: 41 checked, 39 present copies + verified. These are locations, not the installer artifact count. Additional + profiles/workstations and actual installer rollback still need receipts. + +| Captured worktree identity | HEAD | Restored files verified | +| --- | --- | ---: | +| main | `daed20957f2dd2f22cca24053bb5bc8636ff6b3f` | 130 | +| 001-separate-swap-ctx-handoff | `3c26041a4444a10bc240cb64a168ece4d9edf6c5` | 309 | +| 004-migrate-to-triad | `48934f8d4c662be6ed07ad1b7df96dec22028ab2` | 73 | +| feat/supervised-context-restart | `a9506724c1526a734b2c1b82990ffbb908c4daa4` | 81 | +| feat/claude-current | `11037f01a45a72fa3fc9a8a2b0e24a64cbf1ed12` | 63 | +| feat/crash-consistent-lane-worktree-recovery | `07fb3adb8b4ac1476c641685096f00f0d20593c6` | 74 | + +All six were stable during their own capture. They are active observations; +heads differ from earlier local/remote snapshots and can change again. +Owner dispositions, retired-object preservation receipts and a final capture +at safe breakpoints remain required. This backup is local to this workstation. + +Read-only GitHub lookups returned HTTP 404 for both proposed leg repository +names. That means they were not visible to the current credentials, not a +guarantee of name availability or creation permission. Recheck at Gate C; +public visibility remains a proposal requiring the final decision. + +## Measured local rehearsal + +Used main `daed20957f2dd2f22cca24053bb5bc8636ff6b3f` and unchanged standard +`39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. A fresh single-branch source clone +had no linked worktrees. `git-filter-repo` 2.47.0 was installed into a private +venv for this rehearsal; existing bench/system installations were unchanged. +The package wheel SHA256 is +`2cd04929b9024e83e65db571cbe36aec65ead0cb5f9ec5abe42158654af5ad83`. + +The standard's `check` passed. `execute --local-remote-dir ... --yes` used only +disposable local remotes. Network protocols were disabled except local file +transport; gh/curl shims refused network calls. The source clone and real main +remained at the recorded commit. No real repository, PR or lane was changed. + +Execution returned **2** before an assembly split commit or final verification: + +```text +git -c protocol.file.allow=always submodule add -q spec +fatal: please make sure that the .gitmodules file is in the working tree +``` + +Both extracted legs exist for diagnosis. Independent comparison of path, +mode and object ID accounts for all 64 original entries: 18 spec, 40 code and +six unchanged root entries in the candidate index; zero missing or duplicated +entries. This is partial extraction evidence, not the standard's completed +adoption report or a composed candidate. + +| Temporary extracted leg | Commit | Kept commits | +| --- | --- | ---: | +| spec | `993d1e1d01c9ba28ecee003e518bc444cef7028b` | 25 | +| code | `ba5f25696ba24012731b356ddb91f10c5386a220` | 77 | + +Code retains the original `.gitmodules`, dependency contract and gitlink at +the pinned SHA. Initializing that nested dependency through a local URL rewrite +passed. The pinned standard's own tree-digest helper recomputed +`a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02`, +matching the unchanged dependency contract. Full recursive assembly bootstrap +is blocked. The canonical +`tests/run.sh -k upstream_pin` remained in its serialization wait; the owned +waiting wrapper was stopped after 45 seconds. No pytest assertion ran and no +test pass is claimed. The preceding unfiltered waiting attempt also never ran +tests. Do not bypass the wrapper to obtain a pass. + +See the [upstream reproduction](adopter-blocker.md) and +[installer design and compatibility matrix](installer-design.md). + +## Resume after the PR landings + +The user's landing notification triggers a fresh read of #97/#121, actual main +and owner state. Landed changes are accounted for through the new baseline; +remaining branch deltas and local edits still need dispositions. Existing +PR holds and review history are preserved until their owners settle them. + +Regenerate the mapping using the standard rather than editing its source SHA. +Resolve the adopter defect through upstream review, a commit on upstream main +and the recomputed pin/gitlink update. Repeat into fresh local remotes, then +prepare and test follow-up patches against the successfully verified split. +Repeat preservation at coordinated breakpoints. Gates A/B and explicit Gate C +approval still precede real repositories, root landing and live lane rebinding. + +No execution task is checked complete by this provisional evidence. diff --git a/specs/004-migrate-to-triad/quickstart.md b/specs/004-migrate-to-triad/quickstart.md index 7f225487..c0b10f9f 100644 --- a/specs/004-migrate-to-triad/quickstart.md +++ b/specs/004-migrate-to-triad/quickstart.md @@ -4,7 +4,10 @@ Read [plan.md](plan.md), then the [resolved adoption mapping](../../openspec/cha and [work inventory](inventory.json). Read the [protocol review](protocol-review.md) for canonical spec placement, bounded code amendments and final reconciliation. The mapping is for the recorded source -main only; implementation and live feature transfer have not been attempted. +main only. A disposable rehearsal extracted both legs and then refused assembly +mounting; [preparation.md](preparation.md) records the measured limits. Live +feature transfer and real conversion remain pending #97/#121 landings and the +execution gates. From the original source checkout, the planning validation is: diff --git a/specs/004-migrate-to-triad/research.md b/specs/004-migrate-to-triad/research.md index e38cfa29..ee1f0958 100644 --- a/specs/004-migrate-to-triad/research.md +++ b/specs/004-migrate-to-triad/research.md @@ -1,5 +1,12 @@ # Planning evidence and decisions +Latest measured preparation is in [preparation.md](preparation.md). Private +git-filter-repo availability now exists for local rehearsal. Existing-submodule +mounting is a measured refusal, documented in [adopter-blocker.md](adopter-blocker.md), +and installer source-routing design is in [installer-design.md](installer-design.md). +The earlier observations below predate that attempt. Both #97/#121 landings +precede real conversion and a new baseline/rehearsal. + October 3 inspection and October 4 refresh used the pinned standard's `AGENTS.md`, adoption implementation, generated CLI reference and placement policy; root installer, CI and fixture code; local branch/worktree state; read-only GitHub PR metadata. diff --git a/specs/004-migrate-to-triad/tasks.md b/specs/004-migrate-to-triad/tasks.md index b1a16859..6a30ed2c 100644 --- a/specs/004-migrate-to-triad/tasks.md +++ b/specs/004-migrate-to-triad/tasks.md @@ -8,6 +8,11 @@ The protocol refresh updates snapshot/mapping and planned workflow follow-ups; owner decisions, private preservation/restore receipts and execution gates remain pending. Retired checkouts are not instructions to recreate worktrees. +Preparation progress is recorded in [preparation.md](preparation.md): partial +T001–T005 evidence, an [upstream blocker reproduction](adopter-blocker.md), +and [T007–T010 installer/test design](installer-design.md). No execution task +is complete. Real conversion waits for the user's #97/#121 landing update. + ## Phase 1 — Preservation and baseline (Gate A) - [ ] T001 [US1] Refresh `inventory.json`, PR/main/branch/worktree metadata and @@ -78,7 +83,9 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. ## Phase 4 — Reviewed real adoption (Gates C and D) -- [ ] T012 [US1] Freeze the coordinated source baseline and regenerate/check +- [ ] T012 [US1] After #97 and #121 land, account for their final merged work + in main and disposition any remaining local deltas. Freeze the coordinated + source baseline and regenerate/check the full plan after any prerequisite/planning landings. Obtain explicit approval naming revisions, leg repositories/visibility, mapping, follow-ups and work dispositions. Verify current name availability, preservation and @@ -146,7 +153,10 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. ## Dependencies -T001–T003 precede rehearsal. T004–T006 precede integration validation; +Reviewed preliminary inventory, mapping and prerequisite availability from +T001–T003 permit disposable provisional rehearsal while writers remain active; +complete Gate A preservation is required before real source freeze. +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. T013–T015 precede root adoption merge. Prepare T016–T017 translations diff --git a/specs/004-migrate-to-triad/verification.md b/specs/004-migrate-to-triad/verification.md index 57c0a9e4..2812273b 100644 --- a/specs/004-migrate-to-triad/verification.md +++ b/specs/004-migrate-to-triad/verification.md @@ -1,5 +1,37 @@ # Migration planning verification — October 4, 2026 +## Preparation authorized while #97/#121 are active + +[preparation.md](preparation.md) records a verified 18-ref bundle restore, +pinned dependency restore, six worktree file/config captures and verified +installed-file/settings/receipt copies in host and bench contexts. All six +snapshots were also restored into independent Git clones with matching index +entries, captured file bytes and worktree status. Active writers remain +unfrozen; installer/live rollback, retired receipts and final preservation +are pending. Gate A is not complete. + +The unchanged pinned standard passed `check` against an isolated source clone, +then local-only execution returned 2 while adding the spec submodule because +the original `.gitmodules` had been staged for deletion. No assembly adoption +commit or final verification was reached. Independent mode/object accounting +passed for 18 spec, 40 code and six unchanged root index entries. Local nested +dependency initialization and the standard's recomputed dependency digest +check passed. Canonical pin tests stayed in serialization +wait and were stopped before pytest ran; no runtime test pass is claimed. +The [upstream reproduction](adopter-blocker.md) is reviewable, and the +[installer compatibility design](installer-design.md) identifies the required +consumers and pending acceptance scenarios. No pinned-standard changes, +external writes, user-tool installs, real repository creation or lane moves occurred. +Gate B remains open. Both PR landings explicitly precede refreshed real +conversion, which still needs Gates A/B and Gate C approval. + +Final pinned mapping check, OpenSpec strict validation and supplemental +document-link/portable-path/inventory/single-task-list checks passed. +All 19 execution tasks remain open; provisional evidence does not replace +their complete acceptance criteria. + +The following refresh sections are historical observations. + ## Updated migration protocol refresh Read the installed shared workflow's **Triad Feature Amendments**, including From ff6f6a7c7b7921ca1e0b0234e898900f98532366 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Tue, 6 Oct 2026 15:26:03 +0000 Subject: [PATCH 06/12] docs: record successful triad adopter candidate rehearsal --- specs/004-migrate-to-triad/adopter-blocker.md | 16 ++- .../004-migrate-to-triad/adopter-rehearsal.md | 103 ++++++++++++++++++ specs/004-migrate-to-triad/preparation.md | 16 ++- specs/004-migrate-to-triad/tasks.md | 5 +- 4 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 specs/004-migrate-to-triad/adopter-rehearsal.md diff --git a/specs/004-migrate-to-triad/adopter-blocker.md b/specs/004-migrate-to-triad/adopter-blocker.md index a0b8980e..d10580b3 100644 --- a/specs/004-migrate-to-triad/adopter-blocker.md +++ b/specs/004-migrate-to-triad/adopter-blocker.md @@ -6,6 +6,12 @@ `daed20957f2dd2f22cca24053bb5bc8636ff6b3f`. **Measured:** October 4, 2026; disposable local remotes only. +**October 6 update:** a fix is published in draft +[openRepoShape PR #162](https://github.com/opensoft/openRepoShape/pull/162). +The [candidate rehearsal](adopter-rehearsal.md) passes against current consumer +main. The unchanged pinned revision still has the refusal documented below; +upstream landing and a tested consumer pin update remain pending. + The reviewed mapping moves the existing `.gitmodules` together with `upstream/openRepoShape` and its dependency contract into code. Plan `check` passes. Both filtered legs are created, then assembly mounting returns 2: @@ -58,11 +64,13 @@ recursive clone/bootstrap, exact mode/object accounting, and failure recovery. Also cover partial registration ownership and no-existing-module inputs so a fix cannot silently erase retained registrations or create duplicate owners. -No upstream issue or PR was published. No patch was applied to the pinned -checkout or failing candidate. Resolve through the owning repository's normal +At the October 4 measurement no upstream issue or PR had been published and +no patch was applied to the pinned checkout or failing candidate. The October 6 +candidate is maintained in its own upstream worktree. Resolve through normal review, then bump to a commit on its main and recompute the dependency digest. -Repeat the consumer rehearsal with fresh remotes. Gate B remains blocked by -this refusal even though extraction content was independently verified. +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. Private execution log SHA256: `ca2a11775ca3b6d179fc038436a28090f65b05feb2a1611d4578b315733b5168`. diff --git a/specs/004-migrate-to-triad/adopter-rehearsal.md b/specs/004-migrate-to-triad/adopter-rehearsal.md new file mode 100644 index 00000000..fd8a3ac2 --- /dev/null +++ b/specs/004-migrate-to-triad/adopter-rehearsal.md @@ -0,0 +1,103 @@ +# Adopter fix and disposable rehearsal — October 6, 2026 + +**Task:** T005, with additional T003/T004 rehearsal evidence. +**Upstream candidate:** [openRepoShape PR #162](https://github.com/opensoft/openRepoShape/pull/162), +draft, commit `91d568563f98ddbe159167d82652d8e85214bb93`, based on +`39d5c986fcfac1a160474bfe91c5f1c37fccc72c`. +**Consumer rehearsal source:** `f5444c5e1f3c6c9ed43aeafcc000b0e78b10497a`. + +The [October 4 refusal](adopter-blocker.md) is reproduced by a new regression +on the unchanged upstream revision. The candidate creates and stages a fresh +assembly `.gitmodules` after extraction only when that file is absent. It +preserves registrations retained in assembly. Original registrations remain +with their dependency gitlinks in the extracted leg. Verification is unchanged. + +## Regression evidence + +Ran inside py-bench with the existing private git-filter-repo 2.47.0 venv: + +```sh +python3 -m pytest tests/test_adopt_*.py -q +``` + +Result: **90 passed, 1 skipped**. A final run of +`tests/test_adopt_submodules.py` after adding explicit gitlink-mode and +bootstrap assertions passed all **4** cases. Those cases cover: + +- A populated dependency moved with its original `.gitmodules` into either + code or spec: registration blob, gitlink mode/identity, dependency bytes and + registration history survive; recursive clone, validators and bootstrap pass. +- A retained assembly registration survives mounting alongside a moved + dependency. This exercises the mount boundary; it does not qualify every + mixed-registration plan for complete adoption. +- A mount failure after the first new leg leaves the original source refs, + registration bytes and worktree intact; mounting from a fresh clone succeeds. + +Existing adopter coverage includes sources without submodules. No full +consumer suite or upstream CI pass is claimed by these local runs. + +## Current-main local rehearsal + +Private receipt ID: `adopter-fix-20261006-c2G9Dp`. Clone paths, local remote +URLs, commands and complete logs stay host-local outside the repository. + +Generated a new plan from a clean, single-branch isolated source clone. +Reapplied the previous reasoned ownership overrides; explicitly assigned the +new `lanes-index` executable to code. The new `ideation/` content is spec. +The only existing dependency contract remains with code's registration/gitlink. +All ownership questions were resolved before `check` and execution. +This private plan is preliminary rehearsal input, not the final cutover plan. + +`check` and `execute --local-remote-dir … --yes` both passed with the candidate. +Git transport was restricted to local files. The two leg remotes, assembly and +adoption branch exist only in the disposable rehearsal; no real leg repository +was created. The source remained clean on its original main commit. + +| Source accounting | Original entries | +| --- | ---: | +| Spec | 45 | +| Code | 43 | +| Assembly root | 6 | +| Dropped | 0 | +| Total | 94 | + +The standard reported every source path in exactly one place and 18 added +assembly paths. An independent comparison also checked **path, mode, object +type and object ID** for every original entry: zero missing or duplicate +owners. This includes the existing dependency gitlink. + +| Disposable repository | Commit | Kept commits | +| --- | --- | ---: | +| Spec | `2374d2ec8f8f448c3d086b4546920f875c392ca6` | 29 | +| Code | `af25d6d9094285aa2f1d540c839518e6610adf89` | 81 | +| Assembly split | `52f0c18f239b3fbda1c0656e2aefd9c387164d26` | — | + +Recursive clone and the generated `scripts/bootstrap.py` passed, including +naming, manifest and exact leg/copy pin validation. Assembly and legs were +clean afterwards. Code's nested openRepoShape remained at +`39d5c986fcfac1a160474bfe91c5f1c37fccc72c`; the recomputed tree digest is +`a44c0165beb9d3b6ddfce46925bf04b8d19934d5327b5a304b5f3f11af699b02`, +matching the original dependency contract. Live consumer main, its gitlink and +that contract were unchanged. + +Private log SHA256s: + +- Execute: `0e25dbec207e34694321c604201fb0437d70cbb0e4aba8314d34fbeae11636b3`. +- Bootstrap: `d83e3ca6b76e13bb6f4ec7d99ee64ea159634079d87015c3cc10b5699f042b9a`. + +## Remaining delivery gates + +T005 remains open: review and land the upstream fix, then use a commit on +upstream main for the tested consumer pin/gitlink update and recomputed digest. +The existing consumer pin has not been changed to the candidate branch. + +PRs #97 and #121 have landed. On October 6 the remaining open consumer PRs +were #168, #169, #174 and draft #172. Refresh the final source mapping, +inventory and coordinated preservation after their landings and any other +baseline changes. The October 4 committed adoption plan and preservation +snapshot remain historical inputs. + +Installer adaptations, composed code/spec tests and CI, rollback receipts, +owner dispositions and explicit execution approval remain required. Gates +A/B/C are not completed by this rehearsal. This evidence authorizes no real +conversion, merge, account move or lane rebinding. diff --git a/specs/004-migrate-to-triad/preparation.md b/specs/004-migrate-to-triad/preparation.md index 11259027..89f343a6 100644 --- a/specs/004-migrate-to-triad/preparation.md +++ b/specs/004-migrate-to-triad/preparation.md @@ -1,8 +1,11 @@ -# Preparation while PRs #97 and #121 are active - -**Observed:** October 4, 2026. **State:** provisional preservation and local -rehearsal performed; Gates A/B remain open. Real conversion waits for both PRs -to land and the refreshed execution approval. This evidence belongs to +# Migration preparation evidence + +**Initial observation:** October 4, 2026. The preservation and failed rehearsal +below are historical receipts. **October 6 update:** #97 and #121 have landed; +a candidate upstream fix and successful disposable current-main rehearsal are +recorded in [adopter-rehearsal.md](adopter-rehearsal.md). Gates A/B remain open. +Real conversion waits for the remaining baseline landings, a tested upstream +pin and refreshed execution approval. This evidence belongs to [T001–T011](tasks.md); it is not another executable task list. ## Preservation evidence @@ -100,7 +103,8 @@ See the [upstream reproduction](adopter-blocker.md) and ## Resume after the PR landings -The user's landing notification triggers a fresh read of #97/#121, actual main +PRs #97/#121 are now merged; #168/#169/#174 and draft #172 remained open on +October 6. Their landing notifications trigger a fresh read of actual main and owner state. Landed changes are accounted for through the new baseline; remaining branch deltas and local edits still need dispositions. Existing PR holds and review history are preserved until their owners settle them. diff --git a/specs/004-migrate-to-triad/tasks.md b/specs/004-migrate-to-triad/tasks.md index 6a30ed2c..2e6ead21 100644 --- a/specs/004-migrate-to-triad/tasks.md +++ b/specs/004-migrate-to-triad/tasks.md @@ -11,7 +11,10 @@ remain pending. Retired checkouts are not instructions to recreate worktrees. Preparation progress is recorded in [preparation.md](preparation.md): partial T001–T005 evidence, an [upstream blocker reproduction](adopter-blocker.md), and [T007–T010 installer/test design](installer-design.md). No execution task -is complete. Real conversion waits for the user's #97/#121 landing update. +is complete. The [October 6 candidate rehearsal](adopter-rehearsal.md) passes; +T005 still needs upstream landing and a tested consumer pin update. PRs #97 +and #121 have landed. Real conversion waits for the remaining baseline PRs, +integration/preservation evidence and refreshed execution approval. ## Phase 1 — Preservation and baseline (Gate A) From 36c03242791963079e6ddf02a124c052e6b89248 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Wed, 7 Oct 2026 11:07:25 +0000 Subject: [PATCH 07/12] Record the October 7 Gate B rehearsal with the merged adopter fix and regenerate the adoption plan from the repin candidate. openRepoShape 7f84ca4 (PR #162 as merged) was rehearsed into disposable local bare remotes, with git transport restricted to local files and gh/curl refused, from fresh single-branch clones of main c4864ac (run A) and of the repin candidate chore/openreposhape-pin-7f84ca4 at e43b243 (run B, #188). Both runs: check ok; execute exit 0; 45 spec / 49 code / 6 root / 0 dropped of 100; independent path/mode/type/oid comparison with zero missing or duplicate owners; recursive clone, bootstrap and validators passed; the nested openRepoShape gitlink and recomputed digest match code's contract (39d5c98/a44c0165 in A, 7f84ca4/3be52767 in B). adoption-plan.yaml is now the resolved run B plan, labelled as rehearsal input and not the cutover plan; the October 4 version stays in history at ff6f6a7. Gate B remains open (T006-T011). Nothing here authorizes a real conversion. Private receipt adopter-fix-20261007-iM20tv. Part of #186. Lane: openRepoTools-1 Co-Authored-By: Claude Opus 5.5 --- .../migrate-to-triad/adoption-plan.yaml | 154 ++++++++---- .../adopter-rehearsal-2026-10-07.md | 223 ++++++++++++++++++ 2 files changed, 335 insertions(+), 42 deletions(-) create mode 100644 specs/004-migrate-to-triad/adopter-rehearsal-2026-10-07.md 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. From 0fced477d95ac2849cbe7dc26812a8bddd75c040 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Wed, 7 Oct 2026 11:09:33 +0000 Subject: [PATCH 08/12] The Gate A refresh records the October 7 inventory of 17 worktrees and a restore-verified preservation of all 33 refs. T001: inventory.json is refreshed from main c4864ac as of 2026-10-07T10:09:03Z, with every worktree's owner, branch, HEAD, upstream, ahead/behind and dirty/untracked/ignored counts, the 19 local branches, remote-only and local-only refs, PR #187 open, 18 PRs merged since October 3, and the read-only `status openRepoTools` refusal. The October 3 cleanup and the October 4 snapshot are kept as history; a `refreshed` block carries the stamp and source commit. T002: preservation-2026-10-07.md records backup prep-20261007T100559Z: source bundle 60db3acd..., dependency bundle aa5a6eca... (39d5c98 and 7f84ca4 with their tree digests), manifest 2a46dff9..., the worktree table, 97 restore checks passed and 0 failed, and 29 of 29 installed files. Gate A stays open: owner dispositions and a final capture at the freeze remain. Part of #186. Lane: openRepoTools-1 Co-Authored-By: Claude Opus 5.5 --- specs/004-migrate-to-triad/inventory.json | 1284 ++++++++++++++++- .../preservation-2026-10-07.md | 111 ++ 2 files changed, 1319 insertions(+), 76 deletions(-) create mode 100644 specs/004-migrate-to-triad/preservation-2026-10-07.md 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. From ae70dc556cca8c7da5d1d594246f677cb86c5086 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Wed, 7 Oct 2026 11:10:13 +0000 Subject: [PATCH 09/12] docs(004): consumer-side reads of openRepoTools's layout and installer, 2026-10-07 Records, for T006/T007/T008 under #186, every place outside this repository found to depend on openRepoTools's single-repository layout or its installer: file:line, what it assumes, what the triad split changes, and whether installer-design.md at ff6f6a7 covers it. Facts only. Read 2026-10-07T10:04:44Z-11:07:10Z (resumed 11:03:49Z after an API-side error), all read-only: - plan files at ff6f6a7 (adoption-plan.yaml, installer-design.md, plan.md, spec.md, tasks.md) from lane 2's worktree - openRepoTools main c4864ac: the installer, repos.tsv, README, lane tools - workBenches 7fd01e3 (dirty: one submodule pointer): image pin, updater, Dockerfile, entrypoint step, setup scripts, launcher, tests, prose - openRepoShape 7f84ca4: the --install pointer line (openRepoShape:280), its copies and tests, templates/workspace-root - brett-wip ab88a10: register rows, object logs, handoffs, repos.tsv; host-local .lane-state tree records - ~/.agents AGENTS.md, protocols, workspace.yaml; the install receipt (29 rows), settings.json hooks, installed skills/commands Findings: 63 rows (workBenches 15, openRepoShape 8, brett-wip and register state 12, ~/.agents and home 13, installer's own assumptions 15). Of these, 33 are not covered by installer-design.md and 7 are partially covered. The plan of record (baseline daed209) leaves lane-worktrees, lanes-index and ideation/ on main unmapped. Lane: openRepoTools-2 Co-Authored-By: Claude Opus 5.5 --- .../consumer-reads-2026-10-07.md | 310 ++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 specs/004-migrate-to-triad/consumer-reads-2026-10-07.md 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..50ca5eb1 --- /dev/null +++ b/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md @@ -0,0 +1,310 @@ +# Consumer-side reads for T006/T007/T008: what outside openRepoTools depends on its layout or its installer + +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. + +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 /home/brett/.agents /home/brett/.agents/protocols /home/brett/.agents/templates +cat -n /home/brett/.agents/workspace.yaml +grep -rn -i -c 'openRepoTools' /home/brett/.agents/AGENTS.md /home/brett/.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]' /home/brett/.agents/{AGENTS.md,protocols,workspace.yaml,templates} # 59 lines +grep -rln -i 'openRepoTools' /home/brett/.agents/skills /home/brett/.agents/templates /home/brett/.agents/.skill-lock.json # none +cat /home/brett/.agents/protocols/project-agent-bootstrap.md +cat /home/brett/.agents/protocols/openspec-speckit-workflow.md +awk -F'\t' '{print NR, $1, $2, substr($3,1,12), $4}' /home/brett/.local/share/openRepoTools/installed.tsv # 29 rows +sha256sum /home/brett/.local/bin/openRepoTools +grep -n 'lanes-edit\|lane-start\|xFactory\|openRepoTools\|\.local/bin' /home/brett/.claude/settings.json +grep -n -i 'openRepoTools' /home/brett/.claude/CLAUDE.md # none +grep -n -i 'projects/openRepoTools\|lane-worktrees\|raw.githubusercontent\|opensoft/openRepoTools\|docs/README-lanes' /home/brett/.claude/skills/{handoff,restart,lane-swap}/SKILL.md /home/brett/.claude/commands/*.md +sed -n '318,336p' /home/brett/.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 /home/brett/projects/openRepoTools`. `/home/brett/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 `/home/brett/.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. From 76dcb9373edfa950f87b93db4e479534a3a45246 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Wed, 7 Oct 2026 11:12:58 +0000 Subject: [PATCH 10/12] docs(004): Gate B checklist walk, 2026-10-07 specs/004-migrate-to-triad/gate-b-checklist.md lists what Gate B requires, read from plan.md (Gate B paragraph), tasks.md T003-T011, spec.md, verification.md, preparation.md, adopter-blocker.md, adopter-rehearsal.md, installer-design.md and the openspec change at ff6f6a7. Each line gives the requirement with a file:line cite, the evidence that would satisfy it, and its status at 2026-10-07T11:06Z. The walk is for lane openRepoTools-1, under opensoft/openRepoTools#186, to use before it asks for Gate C. It approves nothing and leaves every task in tasks.md open. Status counts, 46 lines: EXISTS 4 (3 on ff6f6a7: lines 11, 12, 23; 1 on 004-migrate-to-triad-reads @ ae70dc556: line 24) DECIDED 1 (line 1, leg names and visibility; #186 comment 6035767825) IN PROGRESS 19 (lane 1's rehearsal writer 14, Gate A writer 3, repin PR writer 2) NOBODY 21 (lines 10, 17-22, 25-34, 36, 37, 40, 46) BLOCKED 1 (line 35: GitHub-hosted runs of the rehearsed composed state before Gate C, inferred) Lane: openRepoTools-2 Co-Authored-By: Claude Opus 5.5 --- .../004-migrate-to-triad/gate-b-checklist.md | 299 ++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 specs/004-migrate-to-triad/gate-b-checklist.md 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. From d14b4413a4052fdf0f0d3d309463b32c6bc5b692 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Wed, 7 Oct 2026 11:22:08 +0000 Subject: [PATCH 11/12] docs(004): consumer-reads revision: Gate C follow-up list of outside changes and timing Appends, at lane 1's request, a dated section to consumer-reads-2026-10-07.md. It takes the 33 rows that installer-design.md does not cover and says, for each, whether a change is needed outside openRepoTools and whether it can be additive before cutover or must wait for the real legs. One dated line is added to the header. No existing row, list or count is changed. An erratum for one mis-cited line is recorded inside the new section. Counts: - Outside-change rows: 12 (workBenches 4, openRepoShape 1, brett-wip 3, ~/.agents 2, host-local files in the shared checkout 2). - Timing over all 33 rows: ADDITIVE BEFORE CUTOVER 11, WAITS FOR REAL LEGS 11, no change 11. - Timing over the 12 outside rows: 4 additive, 8 waiting. - None of the 7 partials is judged to need an outside change. New read-only reads: lanes-edit.sh:2440-2470 and repos.tsv at c4864ac, project-agent-bootstrap.md, the installed handoff skill, and the shared checkout's ignored .specify/extensions/git/git-config.yml. Lane: openRepoTools-2 Co-Authored-By: Claude Opus 5.5 --- .../consumer-reads-2026-10-07.md | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) 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 index 50ca5eb1..7ceb77c4 100644 --- a/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md +++ b/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md @@ -13,6 +13,8 @@ The plan files are read at `ff6f6a7c7b7921ca1e0b0234e898900f98532366` from lane 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 @@ -308,3 +310,86 @@ Total: 33 rows not covered. A further 7 are partial: workBenches 3, openRepoShap - **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' /home/brett/.agents/protocols/project-agent-bootstrap.md +grep -n '\[ -d "\$worktree" \]' /home/brett/.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 +``` From 3f7c48f3cd9f7e4572b1f671654307f9215e5244 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:40:35 +0000 Subject: [PATCH 12/12] Write the consumer-reads document's home paths as ~/ so the hygiene test passes on this branch. tests/test_repo_hygiene.py::test_no_committed_file_names_a_host_absolute_path refuses a host-absolute path (`/home//`) in any tracked file, and specs/004-migrate-to-triad/consumer-reads-2026-10-07.md carried 24 of them (/home/brett/...), so guard-launch-mode, tests, tests-no-submodule and tests-windows were red on PR #189. That file was the only tracked file the test's regex matched. Every /home/brett/ is now ~/, the form the document already uses for its other home paths (`~/.agents`, `~/.claude/settings.json`). Each row keeps its meaning: the recorded commands in the "~/.agents and the home directory" and "commands this revision added" blocks, the LANES.md `--dir` row and the settings.json symlink row name the same files. /workspace/... paths are untouched, which the regex does not refuse. One sentence under the title says why, and that the originals are in lane 2's transcript. No row was deleted, renumbered or reworded otherwise. The document is lane openRepoTools-2's. This is a mechanical portability edit on lane 1's combined branch, made with the lane owner's word. Lane: openRepoTools-1 Co-Authored-By: Claude Sonnet 5.5 --- .../consumer-reads-2026-10-07.md | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) 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 index 7ceb77c4..4abffbff 100644 --- a/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md +++ b/specs/004-migrate-to-triad/consumer-reads-2026-10-07.md @@ -1,5 +1,7 @@ # 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: @@ -143,19 +145,19 @@ grep -rn '^path: /workspace/projects/openRepoTools/' /workspace/projects/.lane-s `~/.agents` and the home directory: ```sh -ls -la /home/brett/.agents /home/brett/.agents/protocols /home/brett/.agents/templates -cat -n /home/brett/.agents/workspace.yaml -grep -rn -i -c 'openRepoTools' /home/brett/.agents/AGENTS.md /home/brett/.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]' /home/brett/.agents/{AGENTS.md,protocols,workspace.yaml,templates} # 59 lines -grep -rln -i 'openRepoTools' /home/brett/.agents/skills /home/brett/.agents/templates /home/brett/.agents/.skill-lock.json # none -cat /home/brett/.agents/protocols/project-agent-bootstrap.md -cat /home/brett/.agents/protocols/openspec-speckit-workflow.md -awk -F'\t' '{print NR, $1, $2, substr($3,1,12), $4}' /home/brett/.local/share/openRepoTools/installed.tsv # 29 rows -sha256sum /home/brett/.local/bin/openRepoTools -grep -n 'lanes-edit\|lane-start\|xFactory\|openRepoTools\|\.local/bin' /home/brett/.claude/settings.json -grep -n -i 'openRepoTools' /home/brett/.claude/CLAUDE.md # none -grep -n -i 'projects/openRepoTools\|lane-worktrees\|raw.githubusercontent\|opensoft/openRepoTools\|docs/README-lanes' /home/brett/.claude/skills/{handoff,restart,lane-swap}/SKILL.md /home/brett/.claude/commands/*.md -sed -n '318,336p' /home/brett/.claude/skills/handoff/SKILL.md +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`) @@ -199,7 +201,7 @@ openRepoShape pins nothing of openRepoTools. |---|---|---|---| | `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 /home/brett/projects/openRepoTools`. `/home/brett/projects` → `/workspace/projects`. | The handoff paths are in brett-wip and unaffected. The estate name `openRepoTools` stays. | 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 | @@ -224,7 +226,7 @@ openRepoShape pins nothing of openRepoTools. | `~/.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 `/home/brett/.local/bin/lanes-edit.sh`. These consume the install. | Nothing, if destinations hold. | covered: l.59, l.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 | @@ -388,8 +390,8 @@ 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' /home/brett/.agents/protocols/project-agent-bootstrap.md -grep -n '\[ -d "\$worktree" \]' /home/brett/.claude/skills/handoff/SKILL.md +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 ```