From f36db81076b9d14d9d03baf4311d9b4e3bbe1234 Mon Sep 17 00:00:00 2001 From: Brett Heap <1513478+brettheap@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:44:10 +0000 Subject: [PATCH 1/9] Adopt the three-repository shape: openRepoTools-spec and openRepoTools-code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openRepoTools keeps its name, its identity and its full history and becomes the assembly root of the project. The two legs are NEW repositories extracted with `git filter-repo`, so every moved file keeps the commits that made it. Nothing was deleted: what leaves this tree arrives in a leg at the same path, mounted back here at spec/ and code/. MOVED TO THE SPEC LEG (openRepoTools-spec @ de756faf8797): docs/ ideation/ openspec/ specs/ MOVED TO THE CODE LEG (openRepoTools-code @ d9e7d568011b): .github/ .gitmodules claude-current claude-restart-check commands/ contracts/ lane lane-end lane-handoff lane-rename lane-start lane-worktrees lanes lanes-edit.sh lanes-index link-estates openRepoTools park pyproject.toml repos.tsv resume skills/ src/ status tests/ upstream/ STAYS IN THE ASSEMBLY ROOT: .gitattributes .gitignore AGENTS.md CLAUDE.md LICENSE README.md WRITTEN BESIDE, NOT OVER (this repository had the name first): shape/README.md <- the shape's README.md shape/AGENTS.md <- the shape's AGENTS.md shape/CLAUDE.md <- the shape's CLAUDE.md shape/.gitignore <- the shape's .gitignore shape/.gitattributes <- the shape's .gitattributes APPENDED TO .gitattributes, after this repository's own lines, which are unchanged (each pinned copy outside shape/ checks out with LF, as the pin records it): /scripts/validate-pins.py text eol=lf /scripts/validate-manifest.py text eol=lf /scripts/bootstrap.py text eol=lf /Makefile text eol=lf /.github/workflows/validate.yml text eol=lf /AGENTS-shape.md text eol=lf /scripts/repo_shape.py text eol=lf /scripts/validate-repository-naming.py text eol=lf /contracts/repository-naming.yaml text eol=lf FOLLOW-UPS, which this commit does NOT do: - .github/workflows/release.yml in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - claude-current in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - lane-start in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - lanes-edit.sh in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - openRepoTools in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/conftest.py in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/run.sh in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_install_skill_and_hook.py in the code leg names `docs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `docs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - … and 9 more file(s) under the code leg naming `docs/` - tests/test_release_workflow.py in the code leg names `ideation/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `ideation/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - .github/workflows/release.yml in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - lane-handoff in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - lanes-edit.sh in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/conftest.py in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_lane_helpers.sh in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_release_workflow.py in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_test_roots.py in the code leg names `openspec/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `openspec/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - .github/workflows/release.yml in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - openRepoTools in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/conftest.py in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_install_payload_source.py in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_package_stamp.py in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_park_resume_commands.py in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_release_workflow.py in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - tests/test_repo_hygiene.py in the code leg names `specs/`, which moves to the spec leg: it must read across the assembly root — from the code leg, where the plan's `legs.code_path` mounts it, to `specs/` in the spec leg, where `legs.spec_path` mounts it — or take the path from the environment - … and 1 more file(s) under the code leg naming `specs/` - keep the block at the end of .gitattributes that opens with `# openRepoShape (#471): the pinned shape copies below check out with LF everywhere, as contracts/shape-pin.yaml records their bytes`: the source repository already has a .gitattributes, so the shape's copy was written beside it as shape/.gitattributes, which governs only its own directory, and the split appends one `text eol=lf` line to .gitattributes for each pinned copy outside it. That block is what makes every checkout, Windows included, write those copies with the bytes contracts/shape-pin.yaml records; without it a Windows clone reports shape-copy-drift on each one. None of the source's own lines is changed. Merge the rest of shape/.gitattributes into .gitattributes only if the whole project should check out with LF, and only then remove shape/.gitattributes: `update-shape.py check` reports its pin row `merged-away`, and `apply` drops the row - 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. Then remove shape/.gitignore: `update-shape.py check` reports its pin row `merged-away`, and `apply` drops the row - 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 - review the root's diff together with openRepoTools-spec and openRepoTools-code, the two new repositories `execute` creates and pushes before the split; against GitHub it opens the split's pull request itself, whose base is the plan's `tracking_branch`, the branch the assembly root and both legs track - 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 200-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. - 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. - The wheel declares license-files = ["LICENSE"] relative to pyproject.toml, which moves to the code leg while LICENSE stays in the root: apply T006 code-0001 (the code leg's byte-identical LICENSE, .gitattributes and front door) in openRepoTools-code inside the cutover, right after execute and before the code leg's first package or release run. At the cutover, as the owner's acts: create the testpypi and pypi environments and the tag ruleset in openRepoTools-code, add a test.pypi.org trusted publisher for openRepoTools-code, and add a pypi.org pending publisher naming openRepoTools-code, release.yml and the pypi environment (opensoft/openRepoTools#228). --- .gitattributes | 10 + .github/release-build-requirements.txt | 152 - .github/release-pipx-requirements.txt | 132 - .github/workflows/release.yml | 1736 -- .github/workflows/tests.yml | 535 - .github/workflows/validate.yml | 223 + .gitmodules | 9 +- AGENTS-shape.md | 167 + Makefile | 73 + claude-current | 821 - claude-restart-check | 368 - code | 1 + commands/ctx.md | 88 - commands/handoff.md | 24 - commands/swap.md | 17 - contracts/code-pin.yaml | 42 + contracts/openreposhape-pin.yaml | 62 - contracts/repository-naming.yaml | 507 + contracts/shape-pin.yaml | 64 + contracts/spec-pin.yaml | 42 + docs/README-claude-current.md | 285 - docs/README-lanes.md | 4789 ---- docs/release-notes/v1.0.0.md | 15 - docs/release-notes/v1.1.0.md | 145 - docs/triad-lane-tooling-analysis.md | 712 - ideation/README.md | 10 - ...orktree-recovery-state-canonical-layout.md | 60 - ...covery-state-crash-consistent-lifecycle.md | 68 - .../lane-worktree-recovery-state-overview.md | 98 - ...ee-recovery-state-resume-reconciliation.md | 66 - ...ecovery-state-synthesis-resumable-lanes.md | 64 - ...pervised-context-restart-durable-intent.md | 65 - .../supervised-context-restart-overview.md | 94 - ...ervised-context-restart-pane-supervisor.md | 60 - ...xt-restart-semantic-mechanical-boundary.md | 51 - ...ed-context-restart-startup-confirmation.md | 56 - ...ext-restart-synthesis-reliable-rollover.md | 69 - lane | 1583 -- lane-end | 2546 --- lane-handoff | 3139 --- lane-rename | 337 - lane-start | 4651 ---- lane-worktrees | 6318 ----- lanes | 833 - lanes-edit.sh | 18977 ---------------- lanes-index | 2695 --- link-estates | 448 - openRepoTools | 5244 ----- .../.openspec.yaml | 2 - .../design.md | 574 - .../proposal.md | 39 - .../specs/lane-worktree-recovery/spec.md | 197 - .../tasks.md | 216 - .../.openspec.yaml | 2 - .../add-supervised-context-restart/design.md | 251 - .../legacy-authority-decision.md | 19 - .../proposal.md | 65 - .../specs/supervised-context-restart/spec.md | 92 - .../add-supervised-context-restart/tasks.md | 7 - .../.openspec.yaml | 2 - .../interactive-lane-name-repair/design.md | 77 - .../interactive-lane-name-repair/proposal.md | 37 - .../interactive-lane-name-repair/spec.md | 117 - .../interactive-lane-name-repair/tasks.md | 21 - .../changes/migrate-to-triad/.openspec.yaml | 2 - .../migrate-to-triad/adoption-plan.yaml | 445 - openspec/changes/migrate-to-triad/design.md | 174 - openspec/changes/migrate-to-triad/proposal.md | 92 - .../specs/repository-triad-migration/spec.md | 154 - openspec/changes/migrate-to-triad/tasks.md | 26 - .../changes/release-tags-pypi/.openspec.yaml | 2 - .../release-tags-pypi/clarifications.md | 147 - openspec/changes/release-tags-pypi/design.md | 708 - .../changes/release-tags-pypi/proposal.md | 790 - .../specs/pypi-package/spec.md | 483 - .../specs/release-tags-and-branches/spec.md | 151 - openspec/changes/release-tags-pypi/tasks.md | 117 - .../changes/skip-no-lane-guard/.openspec.yaml | 2 - openspec/changes/skip-no-lane-guard/design.md | 19 - .../changes/skip-no-lane-guard/proposal.md | 22 - .../specs/profile-only-lane-guard/spec.md | 43 - openspec/changes/skip-no-lane-guard/tasks.md | 5 - openspec/config.yaml | 1 - park | 1294 -- project.yaml | 277 + pyproject.toml | 100 - repos.tsv | 57 - resume | 1758 -- scripts/bootstrap.py | 1144 + scripts/repo_shape.py | 3388 +++ scripts/validate-manifest.py | 1043 + scripts/validate-pins.py | 1626 ++ scripts/validate-repository-naming.py | 1095 + shape/.gitattributes | 25 + shape/.gitignore | 4 + shape/AGENTS.md | 15 + shape/CLAUDE.md | 1 + shape/README.md | 167 + skills/handoff/SKILL.md | 953 - skills/lane-swap/SKILL.md | 26 - skills/restart/SKILL.md | 397 - spec | 1 + specs/002-skip-no-lane-guard/plan.md | 7 - specs/002-skip-no-lane-guard/spec.md | 30 - specs/002-skip-no-lane-guard/tasks.md | 12 - specs/003-binary-only-guard-runner/plan.md | 6 - specs/003-binary-only-guard-runner/spec.md | 6 - specs/003-binary-only-guard-runner/tasks.md | 8 - specs/004-migrate-to-triad/adopter-blocker.md | 76 - .../adopter-rehearsal-2026-10-07.md | 229 - .../adopter-rehearsal-2026-10-08.md | 204 - .../004-migrate-to-triad/adopter-rehearsal.md | 103 - .../candidate-2026-10-09.md | 561 - .../consumer-reads-2026-10-07.md | 410 - specs/004-migrate-to-triad/data-model.md | 21 - .../gate-ab-evidence-2026-10-09.md | 705 - .../004-migrate-to-triad/gate-b-checklist.md | 299 - .../gate-b-status-2026-10-09.md | 692 - .../installer-2026-10-08.md | 243 - .../004-migrate-to-triad/installer-design.md | 97 - specs/004-migrate-to-triad/inventory.json | 1649 -- ...t-s-front-door-resolves-the-split-s-.patch | 398 - ...leg-to-39c18877e042-in-openRepoTools.patch | 55 - ...leg-to-6169e8e96164-in-openRepoTools.patch | 55 - ...s-its-own-front-door-the-shape-s-leg.patch | 417 - ...s-its-own-front-door-the-shape-s-leg.patch | 398 - .../patches/t007-assembly-entry-point.patch | 441 - .../patches/t009-assembly-caps.patch | 133 - .../patches/t010-assembly-exact-pin-job.patch | 131 - .../t010-code-leg-tests-workflow.patch | 88 - specs/004-migrate-to-triad/plan.md | 258 - specs/004-migrate-to-triad/preparation.md | 119 - .../preservation-2026-10-07.md | 111 - specs/004-migrate-to-triad/protocol-review.md | 48 - specs/004-migrate-to-triad/quickstart.md | 44 - specs/004-migrate-to-triad/research.md | 39 - .../root-guidance-2026-10-08.md | 478 - specs/004-migrate-to-triad/spec.md | 120 - .../t018-disposable-2026-10-09.md | 253 - specs/004-migrate-to-triad/tasks.md | 190 - .../test-roots-and-ci-2026-10-08.md | 515 - specs/004-migrate-to-triad/verification.md | 176 - specs/005-supervised-legacy-ctx/analysis.md | 67 - specs/005-supervised-legacy-ctx/plan.md | 69 - specs/005-supervised-legacy-ctx/spec.md | 78 - specs/005-supervised-legacy-ctx/tasks.md | 29 - .../checklists/requirements.md | 76 - .../006-release-pypi/contracts/cli-output.md | 204 - specs/006-release-pypi/contracts/pipx-link.md | 190 - specs/006-release-pypi/contracts/stamp.md | 143 - specs/006-release-pypi/contracts/wheel.md | 135 - specs/006-release-pypi/contracts/workflows.md | 372 - specs/006-release-pypi/data-model.md | 199 - specs/006-release-pypi/plan.md | 300 - specs/006-release-pypi/quickstart.md | 144 - specs/006-release-pypi/research.md | 455 - specs/006-release-pypi/spec.md | 955 - specs/006-release-pypi/tasks.md | 465 - src/openrepotools/__init__.py | 16 - src/openrepotools/_release.py | 25 - src/openrepotools/cli.py | 87 - status | 6067 ----- tests/conftest.py | 628 - .../single-repository-decoys.golden | 148 - tests/fixtures/t018/single-repository.golden | 297 - tests/package_layout.py | 329 - tests/run.sh | 458 - tests/test_claude_current.py | 1149 - tests/test_claude_restart_check.py | 435 - tests/test_command_builtin_errexit_292.py | 401 - tests/test_commit_push_published_edit_194.py | 641 - tests/test_deferred_97_findings_157.py | 193 - tests/test_guard_launch_mode.py | 98 - tests/test_handoff_skill_72_80.py | 475 - tests/test_handoff_skill_80_85.py | 450 - tests/test_handoff_skill_98_99_100.py | 435 - tests/test_handoff_skill_commit_block.py | 483 - tests/test_install_by_rename.py | 179 - tests/test_install_hook_gate.py | 663 - tests/test_install_payload_source.py | 2028 -- tests/test_install_pipx.py | 1724 -- tests/test_install_skill_and_hook.py | 1503 -- tests/test_lane_helpers.sh | 17469 -------------- tests/test_lane_helpers_suite.py | 720 - tests/test_lane_helpers_suite_timeout.py | 373 - tests/test_lane_start_claude_current.py | 607 - tests/test_lane_start_hardening_138.py | 358 - tests/test_lane_start_row_stamp.py | 273 - tests/test_lane_worktrees.py | 2815 --- tests/test_lane_worktrees_report.py | 694 - tests/test_lanes_index.py | 3049 --- tests/test_lifecycle_fail_open_113_114_115.py | 474 - tests/test_openrepotools_command.py | 2452 -- tests/test_package.py | 1077 - tests/test_package_stamp.py | 1262 - tests/test_park_resume_commands.py | 3139 --- tests/test_pathspec_check.py | 102 - tests/test_precision_90a_96.py | 286 - tests/test_register_hardening_120_122.py | 778 - tests/test_register_scan_hardening_138.py | 605 - tests/test_release_workflow.py | 4197 ---- tests/test_rename_publication_atomic_158.py | 269 - tests/test_repo_hygiene.py | 4463 ---- tests/test_run_wrapper.py | 482 - tests/test_skill_shell_blocks.py | 274 - tests/test_status_command.py | 8492 ------- tests/test_supervised_restart_regressions.py | 1883 -- tests/test_test_roots.py | 1151 - tests/test_tests_workflow.py | 1226 - tests/test_triad_lane_tooling.py | 1215 - tests/test_triad_lane_tooling_handoff.py | 1293 -- tests/test_upstream_pin.py | 222 - tests/test_wip_init_command.py | 2132 -- tests/test_wrapper_hardening_138.py | 417 - upstream/openRepoShape | 1 - 215 files changed, 9921 insertions(+), 163970 deletions(-) delete mode 100644 .github/release-build-requirements.txt delete mode 100644 .github/release-pipx-requirements.txt delete mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/tests.yml create mode 100644 .github/workflows/validate.yml create mode 100644 AGENTS-shape.md create mode 100644 Makefile delete mode 100755 claude-current delete mode 100755 claude-restart-check create mode 160000 code delete mode 100644 commands/ctx.md delete mode 100644 commands/handoff.md delete mode 100644 commands/swap.md create mode 100644 contracts/code-pin.yaml delete mode 100644 contracts/openreposhape-pin.yaml create mode 100644 contracts/repository-naming.yaml create mode 100644 contracts/shape-pin.yaml create mode 100644 contracts/spec-pin.yaml delete mode 100644 docs/README-claude-current.md delete mode 100644 docs/README-lanes.md delete mode 100644 docs/release-notes/v1.0.0.md delete mode 100644 docs/release-notes/v1.1.0.md delete mode 100644 docs/triad-lane-tooling-analysis.md delete mode 100644 ideation/README.md delete mode 100644 ideation/brainstorm/lane-worktree-recovery-state-canonical-layout.md delete mode 100644 ideation/brainstorm/lane-worktree-recovery-state-crash-consistent-lifecycle.md delete mode 100644 ideation/brainstorm/lane-worktree-recovery-state-overview.md delete mode 100644 ideation/brainstorm/lane-worktree-recovery-state-resume-reconciliation.md delete mode 100644 ideation/brainstorm/lane-worktree-recovery-state-synthesis-resumable-lanes.md delete mode 100644 ideation/brainstorm/supervised-context-restart-durable-intent.md delete mode 100644 ideation/brainstorm/supervised-context-restart-overview.md delete mode 100644 ideation/brainstorm/supervised-context-restart-pane-supervisor.md delete mode 100644 ideation/brainstorm/supervised-context-restart-semantic-mechanical-boundary.md delete mode 100644 ideation/brainstorm/supervised-context-restart-startup-confirmation.md delete mode 100644 ideation/brainstorm/supervised-context-restart-synthesis-reliable-rollover.md delete mode 100755 lane delete mode 100755 lane-end delete mode 100755 lane-handoff delete mode 100755 lane-rename delete mode 100755 lane-start delete mode 100755 lane-worktrees delete mode 100755 lanes delete mode 100755 lanes-edit.sh delete mode 100755 lanes-index delete mode 100755 link-estates delete mode 100755 openRepoTools delete mode 100644 openspec/changes/add-crash-consistent-lane-worktree-recovery/.openspec.yaml delete mode 100644 openspec/changes/add-crash-consistent-lane-worktree-recovery/design.md delete mode 100644 openspec/changes/add-crash-consistent-lane-worktree-recovery/proposal.md delete mode 100644 openspec/changes/add-crash-consistent-lane-worktree-recovery/specs/lane-worktree-recovery/spec.md delete mode 100644 openspec/changes/add-crash-consistent-lane-worktree-recovery/tasks.md delete mode 100644 openspec/changes/add-supervised-context-restart/.openspec.yaml delete mode 100644 openspec/changes/add-supervised-context-restart/design.md delete mode 100644 openspec/changes/add-supervised-context-restart/legacy-authority-decision.md delete mode 100644 openspec/changes/add-supervised-context-restart/proposal.md delete mode 100644 openspec/changes/add-supervised-context-restart/specs/supervised-context-restart/spec.md delete mode 100644 openspec/changes/add-supervised-context-restart/tasks.md delete mode 100644 openspec/changes/interactive-lane-name-repair/.openspec.yaml delete mode 100644 openspec/changes/interactive-lane-name-repair/design.md delete mode 100644 openspec/changes/interactive-lane-name-repair/proposal.md delete mode 100644 openspec/changes/interactive-lane-name-repair/specs/interactive-lane-name-repair/spec.md delete mode 100644 openspec/changes/interactive-lane-name-repair/tasks.md delete mode 100644 openspec/changes/migrate-to-triad/.openspec.yaml delete mode 100644 openspec/changes/migrate-to-triad/adoption-plan.yaml delete mode 100644 openspec/changes/migrate-to-triad/design.md delete mode 100644 openspec/changes/migrate-to-triad/proposal.md delete mode 100644 openspec/changes/migrate-to-triad/specs/repository-triad-migration/spec.md delete mode 100644 openspec/changes/migrate-to-triad/tasks.md delete mode 100644 openspec/changes/release-tags-pypi/.openspec.yaml delete mode 100644 openspec/changes/release-tags-pypi/clarifications.md delete mode 100644 openspec/changes/release-tags-pypi/design.md delete mode 100644 openspec/changes/release-tags-pypi/proposal.md delete mode 100644 openspec/changes/release-tags-pypi/specs/pypi-package/spec.md delete mode 100644 openspec/changes/release-tags-pypi/specs/release-tags-and-branches/spec.md delete mode 100644 openspec/changes/release-tags-pypi/tasks.md delete mode 100644 openspec/changes/skip-no-lane-guard/.openspec.yaml delete mode 100644 openspec/changes/skip-no-lane-guard/design.md delete mode 100644 openspec/changes/skip-no-lane-guard/proposal.md delete mode 100644 openspec/changes/skip-no-lane-guard/specs/profile-only-lane-guard/spec.md delete mode 100644 openspec/changes/skip-no-lane-guard/tasks.md delete mode 100644 openspec/config.yaml delete mode 100755 park create mode 100644 project.yaml delete mode 100644 pyproject.toml delete mode 100644 repos.tsv delete mode 100755 resume create mode 100755 scripts/bootstrap.py create mode 100644 scripts/repo_shape.py create mode 100755 scripts/validate-manifest.py create mode 100755 scripts/validate-pins.py create mode 100755 scripts/validate-repository-naming.py create mode 100644 shape/.gitattributes create mode 100644 shape/.gitignore create mode 100644 shape/AGENTS.md create mode 100644 shape/CLAUDE.md create mode 100644 shape/README.md delete mode 100644 skills/handoff/SKILL.md delete mode 100644 skills/lane-swap/SKILL.md delete mode 100644 skills/restart/SKILL.md create mode 160000 spec delete mode 100644 specs/002-skip-no-lane-guard/plan.md delete mode 100644 specs/002-skip-no-lane-guard/spec.md delete mode 100644 specs/002-skip-no-lane-guard/tasks.md delete mode 100644 specs/003-binary-only-guard-runner/plan.md delete mode 100644 specs/003-binary-only-guard-runner/spec.md delete mode 100644 specs/003-binary-only-guard-runner/tasks.md delete mode 100644 specs/004-migrate-to-triad/adopter-blocker.md delete mode 100644 specs/004-migrate-to-triad/adopter-rehearsal-2026-10-07.md delete mode 100644 specs/004-migrate-to-triad/adopter-rehearsal-2026-10-08.md delete mode 100644 specs/004-migrate-to-triad/adopter-rehearsal.md delete mode 100644 specs/004-migrate-to-triad/candidate-2026-10-09.md delete mode 100644 specs/004-migrate-to-triad/consumer-reads-2026-10-07.md delete mode 100644 specs/004-migrate-to-triad/data-model.md delete mode 100644 specs/004-migrate-to-triad/gate-ab-evidence-2026-10-09.md delete mode 100644 specs/004-migrate-to-triad/gate-b-checklist.md delete mode 100644 specs/004-migrate-to-triad/gate-b-status-2026-10-09.md delete mode 100644 specs/004-migrate-to-triad/installer-2026-10-08.md delete mode 100644 specs/004-migrate-to-triad/installer-design.md delete mode 100644 specs/004-migrate-to-triad/inventory.json delete mode 100644 specs/004-migrate-to-triad/patches/t006/assembly-0001-The-assembly-root-s-front-door-resolves-the-split-s-.patch delete mode 100644 specs/004-migrate-to-triad/patches/t006/assembly-0002-Bump-spec-leg-to-39c18877e042-in-openRepoTools.patch delete mode 100644 specs/004-migrate-to-triad/patches/t006/assembly-0003-Bump-code-leg-to-6169e8e96164-in-openRepoTools.patch delete mode 100644 specs/004-migrate-to-triad/patches/t006/code-0001-The-code-leg-gets-its-own-front-door-the-shape-s-leg.patch delete mode 100644 specs/004-migrate-to-triad/patches/t006/spec-0001-The-spec-leg-gets-its-own-front-door-the-shape-s-leg.patch delete mode 100644 specs/004-migrate-to-triad/patches/t007-assembly-entry-point.patch delete mode 100644 specs/004-migrate-to-triad/patches/t009-assembly-caps.patch delete mode 100644 specs/004-migrate-to-triad/patches/t010-assembly-exact-pin-job.patch delete mode 100644 specs/004-migrate-to-triad/patches/t010-code-leg-tests-workflow.patch delete mode 100644 specs/004-migrate-to-triad/plan.md delete mode 100644 specs/004-migrate-to-triad/preparation.md delete mode 100644 specs/004-migrate-to-triad/preservation-2026-10-07.md delete mode 100644 specs/004-migrate-to-triad/protocol-review.md delete mode 100644 specs/004-migrate-to-triad/quickstart.md delete mode 100644 specs/004-migrate-to-triad/research.md delete mode 100644 specs/004-migrate-to-triad/root-guidance-2026-10-08.md delete mode 100644 specs/004-migrate-to-triad/spec.md delete mode 100644 specs/004-migrate-to-triad/t018-disposable-2026-10-09.md delete mode 100644 specs/004-migrate-to-triad/tasks.md delete mode 100644 specs/004-migrate-to-triad/test-roots-and-ci-2026-10-08.md delete mode 100644 specs/004-migrate-to-triad/verification.md delete mode 100644 specs/005-supervised-legacy-ctx/analysis.md delete mode 100644 specs/005-supervised-legacy-ctx/plan.md delete mode 100644 specs/005-supervised-legacy-ctx/spec.md delete mode 100644 specs/005-supervised-legacy-ctx/tasks.md delete mode 100644 specs/006-release-pypi/checklists/requirements.md delete mode 100644 specs/006-release-pypi/contracts/cli-output.md delete mode 100644 specs/006-release-pypi/contracts/pipx-link.md delete mode 100644 specs/006-release-pypi/contracts/stamp.md delete mode 100644 specs/006-release-pypi/contracts/wheel.md delete mode 100644 specs/006-release-pypi/contracts/workflows.md delete mode 100644 specs/006-release-pypi/data-model.md delete mode 100644 specs/006-release-pypi/plan.md delete mode 100644 specs/006-release-pypi/quickstart.md delete mode 100644 specs/006-release-pypi/research.md delete mode 100644 specs/006-release-pypi/spec.md delete mode 100644 specs/006-release-pypi/tasks.md delete mode 100644 src/openrepotools/__init__.py delete mode 100644 src/openrepotools/_release.py delete mode 100644 src/openrepotools/cli.py delete mode 100755 status delete mode 100644 tests/conftest.py delete mode 100644 tests/fixtures/t018-handoff/single-repository-decoys.golden delete mode 100644 tests/fixtures/t018/single-repository.golden delete mode 100644 tests/package_layout.py delete mode 100755 tests/run.sh delete mode 100644 tests/test_claude_current.py delete mode 100644 tests/test_claude_restart_check.py delete mode 100644 tests/test_command_builtin_errexit_292.py delete mode 100644 tests/test_commit_push_published_edit_194.py delete mode 100644 tests/test_deferred_97_findings_157.py delete mode 100644 tests/test_guard_launch_mode.py delete mode 100644 tests/test_handoff_skill_72_80.py delete mode 100644 tests/test_handoff_skill_80_85.py delete mode 100644 tests/test_handoff_skill_98_99_100.py delete mode 100644 tests/test_handoff_skill_commit_block.py delete mode 100644 tests/test_install_by_rename.py delete mode 100644 tests/test_install_hook_gate.py delete mode 100644 tests/test_install_payload_source.py delete mode 100644 tests/test_install_pipx.py delete mode 100644 tests/test_install_skill_and_hook.py delete mode 100755 tests/test_lane_helpers.sh delete mode 100644 tests/test_lane_helpers_suite.py delete mode 100644 tests/test_lane_helpers_suite_timeout.py delete mode 100644 tests/test_lane_start_claude_current.py delete mode 100644 tests/test_lane_start_hardening_138.py delete mode 100644 tests/test_lane_start_row_stamp.py delete mode 100644 tests/test_lane_worktrees.py delete mode 100644 tests/test_lane_worktrees_report.py delete mode 100644 tests/test_lanes_index.py delete mode 100644 tests/test_lifecycle_fail_open_113_114_115.py delete mode 100644 tests/test_openrepotools_command.py delete mode 100644 tests/test_package.py delete mode 100644 tests/test_package_stamp.py delete mode 100644 tests/test_park_resume_commands.py delete mode 100644 tests/test_pathspec_check.py delete mode 100644 tests/test_precision_90a_96.py delete mode 100644 tests/test_register_hardening_120_122.py delete mode 100644 tests/test_register_scan_hardening_138.py delete mode 100644 tests/test_release_workflow.py delete mode 100644 tests/test_rename_publication_atomic_158.py delete mode 100644 tests/test_repo_hygiene.py delete mode 100644 tests/test_run_wrapper.py delete mode 100644 tests/test_skill_shell_blocks.py delete mode 100644 tests/test_status_command.py delete mode 100644 tests/test_supervised_restart_regressions.py delete mode 100644 tests/test_test_roots.py delete mode 100644 tests/test_tests_workflow.py delete mode 100644 tests/test_triad_lane_tooling.py delete mode 100644 tests/test_triad_lane_tooling_handoff.py delete mode 100644 tests/test_upstream_pin.py delete mode 100644 tests/test_wip_init_command.py delete mode 100644 tests/test_wrapper_hardening_138.py delete mode 160000 upstream/openRepoShape diff --git a/.gitattributes b/.gitattributes index 3560973e..a9ac338e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -30,3 +30,13 @@ # retold for the repository that ships the two commands. * text=auto eol=lf +# openRepoShape (#471): the pinned shape copies below check out with LF everywhere, as contracts/shape-pin.yaml records their bytes +/scripts/validate-pins.py text eol=lf +/scripts/validate-manifest.py text eol=lf +/scripts/bootstrap.py text eol=lf +/Makefile text eol=lf +/.github/workflows/validate.yml text eol=lf +/AGENTS-shape.md text eol=lf +/scripts/repo_shape.py text eol=lf +/scripts/validate-repository-naming.py text eol=lf +/contracts/repository-naming.yaml text eol=lf diff --git a/.github/release-build-requirements.txt b/.github/release-build-requirements.txt deleted file mode 100644 index 2713ff24..00000000 --- a/.github/release-build-requirements.txt +++ /dev/null @@ -1,152 +0,0 @@ -# THE RELEASE BUILD'S OWN TOOLS, LOCKED BY HASH (opensoft/openRepoTools#228, -# research R11). -# -# COPIED FROM openRepoShape v1.1.0: every line below this header is the lock -# at that repository's tag v1.1.0 (`190133d`), byte for byte. Only this -# header is rewritten, for this repository. -# -# `.github/workflows/release.yml`'s `build` job installs exactly the files -# named here, with `--require-hashes --only-binary :all:`, into a virtual -# environment of its own, and builds the wheel with -# `python -m build --wheel --no-isolation` in it. So every program that -# touches the wheel before it is uploaded, the `build` frontend and the -# `hatchling` backend, is a file this list names by its digest, and so is -# each of hatchling's own requirements: packaging, pathspec, pluggy, -# trove-classifiers, and tomli below Python 3.11. `pyproject.toml` pins -# hatchling alone, so a build that installs it the ordinary way, in pip's -# isolated build environment, resolves those five on the day it runs. -# -# `.github/workflows/tests.yml`'s `package` job reads one entry, tomli's: it -# copies the requirement line and every `--hash` line under it into a file -# under `$RUNNER_TEMP`, and installs that by hash, wheels only, before -# pytest. The job holds no digest of its own, but the pipx lock, -# `.github/release-pipx-requirements.txt`, carries this same `tomli` entry, -# byte for byte, and the job installs that lock after this file's `tomli` -# (step 7 after step 4), so its tests run on the pipx lock's `tomli`. The two -# entries must move together, re-resolved in one act. -# The job's own two builds are `pip wheel`, in pip's isolated build -# environment, which this lock does not reach. -# -# `hatchling==1.27.0` IS `pyproject.toml`'s OWN PIN, and must stay so: with -# `--no-isolation`, `build` refuses a backend that does not satisfy -# `[build-system] requires`, and `tests/test_release_workflow.py` holds the -# two equal. -# -# UNIVERSAL: one file for every Python from 3.9, the oldest the package -# supports, on every system. The markers choose what pip installs on each -# Python, which is why tomli's entry serves the `package` job's 3.9. -# -# RESOLVED, NOT WRITTEN BY HAND, by openRepoShape with uv 0.12.18, from PyPI -# as it stood at 2026-10-01T00:00:00Z. The command below, with that date as -# ``, gives every line under this header again (checked with uv -# 0.12.18 on 2026-10-18). To change it, run the command with a newer date, -# put this header back above the output, rewritten for that date, and commit -# the diff as its own act: -# -# printf 'build\nhatchling==1.27.0\n' \ -# | uv pip compile --universal --python-version 3.9 --generate-hashes \ -# --no-header --index-url https://pypi.org/simple --only-binary :all: \ -# --exclude-newer - -o .github/release-build-requirements.txt - -build==1.4.4 ; python_full_version < '3.10' \ - --hash=sha256:8c3f48a6090b39edec1a273d2d57949aaf13723b01e02f9d518396887519f64d \ - --hash=sha256:f832ae053061f3fb524af812dc94b8b84bac6880cd587630e3b5d91a6a9c1703 -build==1.6.1 ; python_full_version >= '3.10' \ - --hash=sha256:51cc11666391ab6f092070437ac747002ff46f3e4113a3622177ee6b488bfc53 \ - --hash=sha256:ecd351a4be9d35a9eaaba244a7687143c9c7d4aea6ac964e7e7ddab20cbcf4e7 -colorama==0.4.6 ; os_name == 'nt' \ - --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ - --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 - # via build -hatchling==1.27.0 \ - --hash=sha256:971c296d9819abb3811112fc52c7a9751c8d381898f36533bb16f9791e941fd6 \ - --hash=sha256:d3a2f3567c4f926ea39849cdf924c7e99e6686c9c8e288ae1037c8fa2a5d937b -importlib-metadata==8.7.1 ; python_full_version < '3.10' \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 - # via build -importlib-metadata==9.0.1 ; python_full_version >= '3.10' and python_full_version < '3.10.2' \ - --hash=sha256:ab830580bc0ef3db61ce8fae716389e5462b67e033018bab6d8f80ef17172f99 \ - --hash=sha256:bba5600596a7e21f3eef53281cf28d6a5195634d2f2b78ff9501a3272c6eaab0 - # via build -packaging==26.3 \ - --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ - --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c - # via - # build - # hatchling -pathspec==1.1.1 \ - --hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \ - --hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 - # via hatchling -pluggy==1.6.0 \ - --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ - --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 - # via hatchling -pyproject-hooks==1.3.3 \ - --hash=sha256:5fc53fdac9f7bd63fbcdc868fb5f90b4784d78a53a3d3388cd738b807441a20b \ - --hash=sha256:defda19b854fa0d3bd4f76ea4ddcba8abd7dcfcdd585a6690ade050744fc5f43 - # via build -tomli==2.4.1 ; python_full_version < '3.11' \ - --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ - --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ - --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ - --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ - --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ - --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ - --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ - --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ - --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ - --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ - --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ - --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ - --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ - --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ - --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ - --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ - --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ - --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ - --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ - --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ - --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ - --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ - --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ - --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ - --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ - --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ - --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ - --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ - --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ - --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ - --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ - --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ - --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ - --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ - --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ - --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ - --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ - --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ - --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ - --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ - --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ - --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ - --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ - --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ - --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ - --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ - --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 - # via - # build - # hatchling -trove-classifiers==2026.9.21.13 \ - --hash=sha256:0a9ebc8d4e2f3e8a22848c5258033035bec17a3012ac3fea16dbaa764489eb71 \ - --hash=sha256:8b1ff4f9c191b1040b71c37f1e445ab99732911e3cd91de52838453a854d7a17 - # via hatchling -zipp==3.23.1 ; python_full_version < '3.10' \ - --hash=sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc \ - --hash=sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110 - # via importlib-metadata -zipp==4.1.0 ; python_full_version >= '3.10' and python_full_version < '3.10.2' \ - --hash=sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f \ - --hash=sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602 - # via importlib-metadata diff --git a/.github/release-pipx-requirements.txt b/.github/release-pipx-requirements.txt deleted file mode 100644 index 7f6c9b1d..00000000 --- a/.github/release-pipx-requirements.txt +++ /dev/null @@ -1,132 +0,0 @@ -# THE pipx THAT INSTALLS THE WHEEL IN CI, LOCKED BY HASH -# (opensoft/openRepoTools#228, research R11). -# -# COPIED FROM openRepoShape v1.1.0: every line below this header is the lock -# at that repository's tag v1.1.0 (`190133d`), byte for byte. Only this -# header is rewritten, for this repository. -# -# Two jobs install exactly the files named here, by hash and wheels only, -# then install the openrepotools wheel with that pipx, as a person does: -# `.github/workflows/release.yml`'s `install` job, the install check, on each -# of its three legs (ubuntu and macOS on Python 3.x, and ubuntu on 3.9), and -# `.github/workflows/tests.yml`'s `package` job, on 3.9, with `PIPX_HOME` -# and `PIPX_BIN_DIR` under `$RUNNER_TEMP`. -# -# UNIVERSAL, for Linux, macOS and Windows, though no job here runs on -# Windows: pipx 1.11.1 below Python 3.10, the newest pipx that installs on -# 3.9 (the package's oldest Python), and 1.17.8 from 3.10, the newest on -# PyPI at the date below. `tests/test_release_workflow.py` holds those two -# versions, and `tests/package_layout.py`'s fixtures mirror their layouts, -# so a resolution that moves pipx must move both with it. pipx then installs -# pip into its own shared environment, which no lock here reaches; the -# install check's `PIP_INDEX_URL` holds every pip it runs to PyPI. -# -# RESOLVED, NOT WRITTEN BY HAND, by openRepoShape with uv 0.12.18, from PyPI -# as it stood at 2026-10-01T00:00:00Z. The command below, with that date as -# ``, gives every line under this header again (checked with uv -# 0.12.18 on 2026-10-18). To change it, run the command with a newer date, -# put this header back above the output, rewritten for that date, and commit -# the diff as its own act: -# -# printf 'pipx\n' \ -# | uv pip compile --universal --python-version 3.9 --generate-hashes \ -# --no-header --index-url https://pypi.org/simple --only-binary :all: \ -# --exclude-newer - -o .github/release-pipx-requirements.txt - -argcomplete==3.7.0 ; python_full_version < '3.10' \ - --hash=sha256:afde224f753f874807b1dc1414e883ab8fe0cda9c04807b6047dcb8e1ac23913 \ - --hash=sha256:d8f0f22d2a8a7caa383be1e22b6caf1ecaf0ebd10d8f83cc125e36540c95830c - # via pipx -argcomplete==3.7.2 ; python_full_version >= '3.10' \ - --hash=sha256:6029205678bdd9c1c728a155f5f9ecf5812393f969eef58807641a2bc2aa5b19 \ - --hash=sha256:aad8b69a0b9969edb62db0d1752354c0d50717b10e0cbb00e2a958381b9fc6b9 - # via pipx -click==8.1.8 ; python_full_version < '3.10' \ - --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ - --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a - # via userpath -click==8.5.0 ; python_full_version >= '3.10' \ - --hash=sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360 \ - --hash=sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34 - # via userpath -colorama==0.4.6 ; sys_platform == 'win32' \ - --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ - --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 - # via - # click - # pipx -filelock==4.0.7 ; python_full_version >= '3.10' \ - --hash=sha256:a93c4d93269b339a6af4848342c7e940d0f9928ad95eff64764699e5f1bf8a6a \ - --hash=sha256:da5915714a70b55d167fdc7e251ad91302b0a36816fb574dfafae8f4f2c9bb21 - # via pipx -packaging==26.3 \ - --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ - --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c - # via pipx -pipx==1.11.1 ; python_full_version < '3.10' \ - --hash=sha256:e57354c3308b0abb75106d3b73a0d1ffa5c25f24f29e9f4a45e575776dbab85c \ - --hash=sha256:f854fbf01c179db4331adcf6e1b95836b524100135b5d35822497a47a3857e89 -pipx==1.17.8 ; python_full_version >= '3.10' \ - --hash=sha256:19387d1ef29f9192dfb084f22a68f5f663c2e80c6c814bef193b3203a4fc2dc3 \ - --hash=sha256:90810ac9a12a5141364294a1abc24bcc8fab4572d18a6dae165895512e336966 -platformdirs==4.4.0 ; python_full_version < '3.10' \ - --hash=sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85 \ - --hash=sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf - # via pipx -platformdirs==4.12.2 ; python_full_version >= '3.10' \ - --hash=sha256:29dbf06d96c500bc6bdbce75fb0a14d63279c93b1842f97e72a135b33e856983 \ - --hash=sha256:eab5f70271a490ef74618bb314fbb86e3c7e82fa3b9c922c2ea0e0a1a155d329 - # via pipx -tomli==2.4.1 ; python_full_version < '3.11' \ - --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ - --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ - --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ - --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ - --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ - --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ - --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ - --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ - --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ - --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ - --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ - --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ - --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ - --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ - --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ - --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ - --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ - --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ - --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ - --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ - --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ - --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ - --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ - --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ - --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ - --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ - --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ - --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ - --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ - --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ - --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ - --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ - --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ - --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ - --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ - --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ - --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ - --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ - --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ - --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ - --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ - --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ - --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ - --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ - --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ - --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ - --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 - # via pipx -userpath==1.9.2 \ - --hash=sha256:2cbf01a23d655a1ff8fc166dfb78da1b641d1ceabf0fe5f970767d380b14e89d \ - --hash=sha256:6c52288dab069257cc831846d15d48133522455d4677ee69a9781f11dbefd815 - # via pipx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 092ddc05..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,1736 +0,0 @@ -name: release - -# --------------------------------------------------------------------------- -# PUBLISH THE openrepotools WHEEL (#228): TestPyPI, AN INSTALL CHECK ON THREE -# LEGS, THEN PyPI, IN ONE DISPATCHED RUN. Adapted step for step from -# openRepoShape v1.1.0's own release.yml (`190133d`, the commit -# `upstream/openRepoShape` is pinned at), whose checks are taken over as they -# are (FR-028) except where design.md Decision 10 names a difference: -# - a pre-release `X.Y.ZrcN` is accepted, for TestPyPI alone; PyPI takes a -# final `X.Y.Z` and nothing else; -# - the repository guard (FR-048, WHERE RELEASES COME FROM below) is new -# here, because the model has none; -# - the stamp has a fifth field, REPOSITORY, the run's `$GITHUB_REPOSITORY`; -# - the digest's definition is held to the literal `sorted-ls-tree-r-v1` -# that `--version` prints and to the pin's `digest_definition`, where the -# model compares it with its package's own constant; -# - the payload's blobs and modes are checked under -# `openrepotools/payload/`, against the commit's own paths; -# - the install check runs on three legs, ubuntu and macOS on Python 3.x -# and ubuntu on 3.9, with no Windows leg, checking `--version` and an -# offline `--install` beside pipx's link, again under macOS's -# `/bin/bash` 3.2, and compiling the payload's two Python commands on -# 3.9; -# - no step reads the release notes (WHAT THIS WORKFLOW NEVER READS). -# It also holds more than the model where FR-029 and contracts/workflows.md -# ask for it: the gate names `tests.yml`'s four jobs, the build checks out -# full history with the submodule, and the ref step fetches the tag again -# without `--depth`. -# -# FOUR JOBS, EACH GATED ON THE ONE BEFORE IT: -# build the version and the repository guard; the tag, the branch, the -# clean checkout, both environments, `tests.yml`'s four jobs on -# this commit, and the digest; then the wheel, built twice from -# two `git archive` extractions of the commit, stamped, compared -# byte for byte, checked against the commit's own files, and its -# sha256 recorded. -# testpypi the guard again; uploads those bytes to TestPyPI, in the -# `testpypi` environment, then requires TestPyPI to serve -# exactly that digest. -# install on ubuntu, macOS and Python 3.9: pipx installs TestPyPI's -# file, taken by the recorded digest (on a branch, the build's -# own wheel), and the one command it places is run. -# pypi the guard again; uploads the same bytes to PyPI, in the `pypi` -# environment, which waits for Brett Heap's approval after the -# install check, then requires PyPI to serve exactly the -# recorded digest. -# -# DISPATCH ONLY. Nothing here runs on a push, a tag or a pull request: an -# upload is an act Brett Heap approves. The version is the tag's: `v1.1.0` -# gives `1.1.0`, which the build writes into the stamp, -# `openrepotools/_release.py`, with the tag, the commit, the digest and the -# repository. A dispatch on a tag refuses unless that tag is `v`, -# annotated, and pointing at the run's own commit, and unless that commit is -# on `main` or on the version's release branch, `release/v.`. -# -# RE-RUN ONLY THE FAILED JOBS ("Re-run failed jobs"), never the whole run -# and never a second dispatch of a version already uploaded. A re-run of a -# failed job reuses the build's artifact and its recorded digest, and each -# upload job requires the index to hold no file of the version but the -# verified wheel at its digest (FR-031), so a re-run after an upload that -# went through uploads nothing new. A second dispatch builds again, and its -# wheel is the same file only while the locks, the runner's Python and the -# commit all stay the same; the index keeps the first file under its name -# for good, and the upload jobs refuse any other. -# -# NO PyPI TOKEN AND NO STORED SECRET, ANYWHERE. Both uploads use trusted -# publishing (OIDC): `id-token: write` is granted to the two upload jobs and -# to no other job. The one other credential is GitHub's automatic -# GITHUB_TOKEN, read-only in every job, which `gh` uses to read this -# repository's own API. -# -# EVERY ACTION IS PINNED BY COMMIT, with its release tag beside it, as -# `tests.yml` pins them: checkout and setup-python at that file's own -# commits, the artifact actions at the model's. One limit carried over from -# the model, where it was accepted: pypa/gh-action-pypi-publish is a -# container action whose image is pulled by a registry tag, so its commit -# pins the action's files and not all the code an upload runs. The digest -# checks before and after each upload bound what that could change. -# -# RELEASING: THE PROCEDURE (FR-034 to FR-040). Brett Heap decides every -# tag, every release-branch cut and every upload, and approves each -# deployment. The release owner, lane openRepoTools-3, carries them out on -# his word: it tags, dispatches and creates the GitHub Release, and no other -# lane does. For each release: -# 1. THE COMMIT'S CI FIRST. A tag waits for its commit's `tests.yml` runs: -# all of them finished, and the newest green, in a push or dispatch run -# (the build's gate counts no `pull_request` run). On `main` the push -# run that landed the commit does that once it has finished green; on -# `release/vX.Y` the branch's own push run does, and for a commit that -# reached the branch by fast-forward the newer of main's run and the -# branch's decides (FR-039). Otherwise, BEFORE TAGGING, dispatch -# `tests.yml` on a branch that points at the release commit, and wait -# for it: -# git push origin :refs/heads/ -# gh workflow run tests.yml --ref -R -# 2. THE TAG, ANNOTATED, on Brett Heap's word, with the message `v1.0.0`'s -# has (FR-036), `