Repository navigation
T087, phase 3's openDox root pin: code → dede32b4 (plan 034, T090 steps 1–2) - #18
Conversation
…anded; plan 034) Move the `code` gitlink and `contracts/code-pin.yaml` (`commit:` and `digests.tree_sha256`) to dede32b4, the commit openDox-code#79's squash landed (T101's version bump to 0.1.0), which carries every phase-3 openDox-code landing (22 on the first-parent line above 047bb4fa). T099 publishes exactly the commit this root pins (RULED 5963162921). Made by openRepoShape's scripts/bump-leg.py: tree c2672463b4d8cf834026e2faae23478105d9e98650fcc07d971c19e387e7e0a7. No `.github/workflows/*.yml` references the code leg by `@<sha>`, so none moves. Falsifier: `make pins` in the openDox root -- pins ok. Arc: neutral-product-standalone-operability Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis PR performs the phase-3 openDox root pin update by moving the code gitlink and matching contract commit from 047bb4fa to dede32b4, and replacing the code tree digest with the digest verified for that commit. The spec leg and repository wiring remain untouched; the supplied validation confirms lockstep pin and digest integrity. Flow diagram for the lockstep openDox code pin updateflowchart LR
A[code gitlink: 047bb4fa to dede32b4] --> C[make pins]
B[contracts/code-pin.yaml commit and tree_sha256 updated] --> C
C --> D[validate-pins.py]
D --> E[code pin and digest verified]
F[spec leg unchanged] -.-> E
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The gitlink and pin metadata are synchronized, and the lockstep validation completed successfully.
Review effort: Balanced
Findings: None
What changed in this PR
Advances the openDox code leg to the phase-3 release commit while preserving pin integrity.
Changes:
- Updates the
codegitlink todede32b4. - Updates the matching commit and verified tree digest.
| File | Description |
|---|---|
code |
Advances the code-leg gitlink. |
contracts/code-pin.yaml |
Records the matching commit and tree digest. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
READY at f451f68 — Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Holder: T087, phase 3's openDox root pin (T090 steps 1–2). It is an arc landing, with Claim
|
… (plan 034 T094, T090 step 5) (#22) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Plan 034, task **T094**, step 5 of **T090**'s pin procedure: *"The openXdox root moves its `code` gitlink and `code-pin.yaml`, and moves `contracts/opendox-pin.yaml` to step 2's root commit."* The plan is `specs/034-opendox-standalone-operation/tasks.md` at opensoft/openxFactory `main`. Precedent: #21 (T064), which landed as `f257e021` and was followed by opensoft/openxFactory#1215. - **Claim:** opensoft/openxFactory#656 (comment) (it covers T087 and T094). - **Landing word:** the holder's lander merges; this writer does not. T094's openxFactory half is a separate PR. It re-points openxFactory's `openXdox` gitlink to this PR's LANDED sha, and moves its `openDox` pair to `e1e3a3c3` in the same commit, with phase 3's host wiring. ## The lockstep | site | before | after | | --- | --- | --- | | `code` gitlink | `6a3b93b9` | **`56e1c238`** | | `contracts/code-pin.yaml` `commit:` (line 24) | `6a3b93b93cd6…` | **`56e1c238681a7693a4d8d42a62c1523cf4d4ab91`** | | `contracts/code-pin.yaml` `digests.tree_sha256` (line 39) | `4ef2b4f7…aeb3` | **`f4bddb506119132441637be32bc801c8ad4f95b8157a692c0a4567224c693ce3`** | | `contracts/opendox-pin.yaml` `commit:` (line 34) | `d5098297…` | **`e1e3a3c3f8dd38214510412b71a2e858c6179532`** | | `contracts/opendox-pin.yaml` `digests.tree_sha256` (line 40) | `2815ca23…57cc` | **`55a110f49d268e22d382d47d778dfaf9298c93b555e3c4fcb621afc99f9d011b`** | No `.github/workflows/*.yml` names the code leg by `@<sha>` (`grep -rnE "openXdox-code[^ ]*@[0-9a-f]{40}" .github` finds nothing), so the README's third site does not exist here. **Each gitlink and its pin file move in one commit.** `2fa15af5` moves `code` with `code-pin.yaml` (openRepoShape's `scripts/bump-leg.py`), and moves `contracts/opendox-pin.yaml`. `make pins` passes there. `db6cc2a4` changes prose only: the opendox-pin file's comments, `contracts/manifest.yaml` and `contracts/CHANGELOG.md`. **Both moves are ancestor moves.** `6a3b93b9` is an ancestor of `56e1c238`, and `d5098297` is an ancestor of `e1e3a3c3` (`git merge-base --is-ancestor`, both exit 0). `56e1c238` is openXdox-code `main`, and `e1e3a3c3` is openDox `main`'s parent: openDox#17 (T076, the root README only) landed after it as `504324de`. **What the code leg's advance carries.** `6a3b93b9..56e1c238` is one first-parent commit, a squash landing of plan 034's phase 3 that carries the `Arc:` trailer: - `56e1c23`: T086, openXdox contributes its columns: the governed gate, scope, kickoff and register at openDox's seams, the two route columns through the facet, the direction at (0, 0) (plan 034) (opensoft/openXdox-code#37) Its `pyproject.toml` pins `opendox @ git+https://github.com/opensoft/openDox-code@dede32b4…`, the openDox-code commit openDox's root pins at `e1e3a3c3`. **What the openDox pin's advance carries.** `d5098297..e1e3a3c3` is one commit: - `e1e3a3c`: T087, phase 3's openDox root pin: code → dede32b4 (plan 034, T090 steps 1–2) (opensoft/openDox#18) It moves `code` `047bb4fa` → `dede32b4` with `contracts/code-pin.yaml`, and changes no other path. So openDox's `contracts/manifest.yaml`, its `spec` gitlink and `contracts/spec-pin.yaml` are byte-unchanged, and the openDox bundle this one composes over is still `dox-v1.1`. ## The digests, three ways | tree | records | `scripts/repo_shape.py` `tree_digest` | independent `ls-tree` + `sha256` | `repo_shape.tree_digest_from_gh` (the forge's tree) | | --- | ---: | --- | --- | --- | | openXdox-code `56e1c238` | 191 | `f4bddb50…3ce3` | `f4bddb50…3ce3` | `f4bddb50…3ce3` | | openDox `e1e3a3c3` | 28 | `55a110f4…011b` | `55a110f4…011b` | `55a110f4…011b` | Controls: the same three methods recompute the recorded `4ef2b4f7…aeb3` at `6a3b93b9` (187 records) and `2815ca23…57cc` at `d5098297` (28 records). ## `contracts/opendox-pin.yaml`, edited in place It stays at 164 lines, with every line in its position. Lines 34, 40, 55, 56, 57, 58, 143 change: - line 34, `commit:`; - line 40, `tree_sha256`; - lines 55-58, the per-file paragraph. It was checked at `dc7aa08f`, `663ac683` and `d5098297`, and is unchanged at `e1e3a3c3`: `dox-v1.1` and FOUR `entries:`, all at openDox-spec `f7ee3c76`; - line 143, the migration triple's `runbook`, which names "the pinned code leg". That is `dede32b4` now. **The migration triple.** No migration path changes over openDox-code `047bb4fa..dede32b4`, and `migrations/` holds the same two files. So `range: "0001..0002"` and `reversible: false` stay, and only `runbook`'s leg changes. openxFactory's own `contracts/opendox-pin.yaml` takes the identical block in T094's openxFactory PR. `tests/opendox_pin/test_opendox_pin_verifier.py` asserts the two blocks are equal. ## Prose kept true in the same PR - **`contracts/manifest.yaml`.** - "THE CODE LEG CONTRIBUTES NO ENTRY" now covers `56e1c238`. The leg's packaged copies under `src/openxdox/contracts/` are unchanged from `6a3b93b9` (`git diff --quiet 6a3b93b9 56e1c238 -- src/openxdox/contracts contracts` exits 0), so none of the five rows moves. - "WHAT THIS BUNDLE DEPENDS ON" names `e1e3a3c3` and opensoft/openDox#18, and keeps #21's advance as history. - The tag paragraph adds `d5098297` from #21 and `e1e3a3c3` from this commit forward. - The lockstep paragraph's openxFactory reading is `f257e021`, whose blob names `d5098297`. - **`contracts/CHANGELOG.md`, `## Unreleased`.** It records the code leg's sixth advance and the openDox pin's advance. Its closing sentence is true as written: both legs' `main` are exactly the commits this root pins. - **No tag moves.** `xdox-v1.0` stays where it is. No advance cuts a bundle. ## Validators, as `validate.yml` runs them (at `db6cc2a4`) | check | result | | --- | --- | | `python3 scripts/validate-repository-naming.py --project project.yaml` | exit 0 | | `python3 scripts/validate-manifest.py` | exit 0: `manifest ok: openXdox (openxdox), 3 legs` | | `make pins` (`python3 scripts/validate-pins.py`) | exit 0: `ok spec: gitlink == contracts/spec-pin.yaml commit f088b09732e2`, `ok spec: tree digest recomputes (b7dbd5456a1a…)`, `ok code: gitlink == contracts/code-pin.yaml commit 56e1c238681a`, `ok code: tree digest recomputes (f4bddb506119…)`, `ok contracts/shape-pin.yaml: 10 copied shape file(s) match their digests`, `ok openDox: pin commit e1e3a3c3f8dd digest recomputes (gh-api-tree-recursive)`, `pins ok` | | `make validate` | exit 0 | `make pins` passes at `2fa15af5` too. ## Falsifier `make pins` is step 5's falsifier. Each half-move is refused, measured in a scratch clone of this branch: | case | `validate-pins.py` | | --- | --- | | this head, then the lockstep commit `2fa15af5` alone | `pins ok`, exit 0, both | | the `code` gitlink back at `6a3b93b9`, the pin files at this head | `FINDING pin-gitlink-mismatch`, exit 1 | | the gitlink at `56e1c238`, `contracts/code-pin.yaml` back at `main`'s | `FINDING pin-gitlink-mismatch`, exit 1 | | one hex digit of `code-pin.yaml`'s `tree_sha256` altered | `FINDING pin-digest-mismatch`, exit 1 | | one hex digit of `opendox-pin.yaml`'s `tree_sha256` altered | `FINDING neutral-pin-digest-mismatch`, exit 1 | | restored | `pins ok`, exit 0 | A fresh clone of this branch from GitHub, with `git submodule update --init --recursive` (CI's own step), passes CI's three steps (naming, manifest, pins), each with exit 0. No check here reads openDox's `main` tip: `validate-pins.py` recomputes the pinned commit's digest from the forge's tree, so `e1e3a3c3` verifies although openDox#17 (T076, the root README) has since landed as `504324de`. Step 5 pins step 2's root commit, as T090's text says. ## What this does to openxFactory `verify-opendox-pin.py` check 5 reads this root's `contracts/opendox-pin.yaml` as a blob, at whatever commit openxFactory's `openXdox` gitlink names. This PR changes that file's `commit:` to `e1e3a3c3`. So when openxFactory's `openXdox` gitlink moves here, its own `openDox` pair must move to `e1e3a3c3` in the SAME commit (measured: with the openDox pair alone moved, `verify-opendox-pin.py` refuses `opendox-pin-lockstep-mismatch`). T094's openxFactory PR does exactly that. Until it lands, openxFactory keeps reading `f257e021`. Measured before this PR, in an openxFactory staging clone with both pairs moved in ONE commit, over a rehearsal of these two commits whose code leg was opensoft/openXdox-code#37's last pre-squash head `69997db7`: `verify-opendox-pin.py` and `verify-openxdox-pin.py` both print OK, and openxFactory's composition, host-wiring, carve-mapping and pin suites pass (410 passed). `56e1c238` differs from `69997db7` in three files: `pyproject.toml`'s `opendox` pin (`c4b55cc4` → `dede32b4`), `tests/test_doxchat_model_intake.py` and `.github/workflows/validate.yml`. T094's openxFactory PR measures again at this PR's LANDED sha. ## Landing (forced order) 1. ~~T087, opensoft/openDox#18, lands.~~ Landed → `e1e3a3c3`. 2. ~~T086, opensoft/openXdox-code#37, lands.~~ Landed → `56e1c238`. 3. This PR lands. Squash or merge, never rebase, and the landing carries the `Arc:` line. 4. Lane openXfactory-3's ahead PR (the CLI help golden, the usage line and the rebound-Host case) lands in opensoft/openxFactory. 5. T094's openxFactory PR moves BOTH pin pairs in one commit, to this PR's LANDED sha and to `e1e3a3c3`, records the landed tree's digest, and carries phase 3's host wiring. Plain gate: this repository has no `openspec/changes/`, so there is no Rule 6 window. **This PR is not merged by the actor that opened it.** Arc: neutral-product-standalone-operability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Arc: neutral-product-standalone-operability Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Host case hold at both pins (T066's form; not an arc landing) (plan 034) (#1234) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Authored by lane openXfactory-3, delegated by lane openxfactory-4 (#656 5984809313) Plan 034, **T094's ahead PR** (`specs/034-opendox-standalone-operation/tasks.md` at openxFactory `main` `ba6bb870`, T094's **After** line: *"the ahead PR (E1 (a), a non-arc PR with no task of its own: the golden, the usage line and the rebound-Host case)"*). The rulings are E1 (a) and E3 (a), recorded with `5970369724`; the tree at 32, `5970917267`; and E3 (a)'s reading, E5 (a) and the rebound-Host case, `5972924576`. This PR makes three openxFactory test surfaces hold at BOTH openDox legs: - **the current pins**: openDox `d5098297` (code `047bb4fa`) and openXdox `f257e021` (code `6a3b93b9`); - **phase 3's leg**: openDox-code `dede32b4`, the commit that T087's openDox root `e1e3a3c3` (opensoft/openDox#18) pins. **Not an arc landing.** Per T091 and plan.md § "The trailer, the guard and Rule 6", no commit of this PR and no line of this body carries the arc trailer. It touches no `openspec/` path, so no Rule 6 window applies. No commit and no line here carries a closing keyword. It moves no pin and carries no host wiring (E3 (a)): T094 moves both pin pairs. The three commits were prepared by lane openxfactory-4 in its T094 prep and are carried onto `main` unchanged (the same patch ids). Their "Measured:" paragraphs are that prep's runs; this body's are below. `1661c63d` merges `main`'s one later commit (T007 batch P, #1230), which touches none of these files. ## What it changes | file | change | both-pins form | | --- | --- | --- | | `tests/domain_profile/fixtures/cli-help-tree.phase3.golden.txt` (new) | The assembled `--help` tree at phase 3's leg, 32 sections: T070's `generate-and-open --local`; T079's and T080's `--model`, the `none` auth kind and the optional credential reference on `model-binding add` and `edit`; T084's program name `opendox` in every usage line, with openDox's own root description and epilog; and T100's `model-binding trust`, the 32nd entry point (research R8). It lives outside `tests/ideation-dashboard/`, a `moved_paths:` prefix of the carve manifest, where a new file is `carve-file-undeclared`. | Read only where the pinned parser has phase 3's layout. | | `tests/ideation-dashboard/test_extension_point_parity.py` | `pinned_help_golden` picks the golden off the pinned parser, never off the text compared: its `prog` (`ideation-dashboard` before T084, `opendox` from it) and whether `model-binding` offers `trust` (T100). A leg with one change and not the other is refused by name. Two new cases: the two goldens hold the same entry points plus `model-binding trust`, and the selector's negative control. | Both layouts, each held byte for byte. | | `tests/ideation-dashboard/test_cli_column_split.py` | `test_a_contributed_verb_is_reachable_in_both_documented_invocations` reads the usage line's program off the pinned leg, `cli.PROG` (T084), and `ideation-dashboard` where the leg has no `PROG` (E5 (a)). | Both program names. | | `tests/ideation-dashboard/test_doxbench_routes.py` | `test_console_gate_refuses_host_not_naming_the_bound_port` expects `403 invalid_host`, from `serve.FOREIGN_HOST_*`, where the leg has T103's Host gate (openDox-code#80), and `console_required` where it does not. Either way the request is refused and the model port is never asked. | Read off the leg (`serve.FOREIGN_HOST_ERROR`), never off the answer. | None of the four files is one of F11.1's declared surfaces (`HOST`, `HOST_TESTS`, `PIN_PAIRS`, `COMPOSITION_TESTS`, `ADMITTED_ARC_EDITS`), which is why they move here and not in T094's arc landing. ## The golden, regenerated from T087's commit The tree is the parity test's own walk (`walk_parser` and `help_tree`, at `COLUMNS=100`), printed by a probe that makes the suite's two set-up calls (`carved_reach.install(tests=True)`, `register_openxfactory()`) with the openDox code leg at the named commit: | openDox-code leg | sections | bytes | sha256 | against this PR's golden | | --- | ---: | ---: | --- | --- | | `047bb4fa`, the current pin (the control) | 31 | 53425 | `9cbeca99…` | byte for byte `tests/ideation-dashboard/fixtures/cli-help-tree.golden.txt`, the golden `main` already holds | | **`dede32b4`, T087's** (root `e1e3a3c3`) | 32 | 52827 | `9cc6e383…` | **identical** | | `38d3350e` with #84 `af2a2efb` and #86 `96ae8816` merged (the drift check before they landed) | 32 | 52827 | `9cc6e383…` | identical | - openDox-code#79's `0.1.0` changes `pyproject.toml` only. The parser has no version flag and the tree carries no version string. - The openXdox leg does not move the tree: the same bytes come out with openXdox-code at its pin `6a3b93b9` and at T086's head (openXdox-code#37, `69997db7`). ## The measurements Every local run follows `pytest-suite`'s own steps: a checkout named `openxFactory` with `openXwallet`, and `openDox` and `openXdox` recursively, initialized; Python 3.12.3; the hash-pinned lock; node 24; the pinned OpenSpec CLI 1.12.0; `PINNED_CORE_CHECKOUT` at codexFactory `b21f0100`; then `python3 -m pytest tests/ -q -m "not postgres"`. | run | head | legs | result | | --- | --- | --- | --- | | **CI** | `1661c63d` | the pins | All 14 check-runs at the head succeeded. `pytest-suite` (run `37311052114`): **8929 passed, 6 skipped, 0 failed**: `selected=9347 passed=9341 skipped=6 failures=0 errors=0`, margin 2297, `skipped==6`; the freshness verifier and the vector replay passed. | | P | `1661c63d` | the pins | The parity, doxbench-routes, CLI column split and carve test mapping suites: **324 passed**. `validate-carve-manifest`: OK, 456 rows, none undeclared. Full suite **8930 passed, 5 skipped, 0 failed**: `selected=9347 passed=9342 skipped=5 failures=0 errors=0`; the freshness verifier and the vector replay passed. | | P0 | `7657cc3e`, before the merge of `main` | the pins | the same four suites, 324 passed; `validate-carve-manifest` OK; full suite **8930 passed, 5 skipped, 0 failed**: `selected=9347 passed=9342 skipped=5 failures=0 errors=0`, the freshness verifier and the vector replay passed | | X3 | this PR's files, openDox code at `dede32b4` and openXdox code at T086's head `69997db7`, overlaid with no pin moved | phase 3 | The parity file, the rebound-Host case and the usage-line case: **14 passed, 2 failed**. The two are T094's own composition cases (next list). | | X2 | the same, with openXdox code at its pin `6a3b93b9` | mixed | 13 passed, 3 failed: the same two, and the rebound-Host case refused at server build (`RouteBindingError`: no `_serve_index`, no `_handle_gate_action`), because phase 3's openDox leg no longer carries `consumer_reach` for phase 2's openXdox leg. No phase pins this mix; T094 moves both pairs together. | - **The two reds at phase 3 are T094's.** `test_the_core_dispatch_table_is_unchanged[_route-pinned0]` (the `/capabilities` arm reaches `_serve_bytes`, `_session_repository` and `install_report` from T103) and `test_the_mixins_precede_simplehttprequesthandler_in_the_mro` (`consumer_reach` is gone). Both are named composition tests under R1Q2 (a), and T094's arc landing updates them. - **Why a local run skips 5, not CI's 6.** The work tree sits inside an xFactory aggregation checkout, so `tests/domain_profile/test_session_worktree_book_scan.py::test_worktree_container_is_gitignored_in_the_aggregation_repo` finds the aggregation, runs and passes, where a runner skips it. CI's 8929 passed + 6 skipped and P's 8930 passed + 5 skipped are the same 8935 tests. The local five are the two `tests/notebooklm` module skips, the two conformance-gate self-gate skips and the LedgerxFactory fixture-drift guard. ## Review | Copilot at | verdict | threads | answered in | | --- | --- | --- | --- | | `1661c63d` | Approval recommended; findings: none | none | nothing to answer | ## Landing - No arc trailer, no closing keyword, no `openspec/` path, so there is no Rule 6 window. - It opens as a DRAFT. With its gates and Copilot clean at its head it leaves draft and READY-CANDIDATE is posted on #656; the holder marks it READY, and the landers merge it. - It lands **before T094**, whose **After** line names it. T094 then moves both pin pairs, with the host wiring and its composition tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Lane: openxfactory-4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, with phase 3's host wiring: openXdox's columns and the governed binding-trust policy (plan 034) (#1236) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Plan 034, task **T094**: phase 3's consumer pins (T090 step 6) with phase 3's host wiring, `specs/034-opendox-standalone-operation/tasks.md` at openxFactory `main`. The precedents are T047 (opensoft/openXdox#20, then #1181) and T064 (opensoft/openXdox#21, then #1215). - **Claim:** #656 (comment) (it covers T087 and T094). - **Landing order, done:** - T087: opensoft/openDox#18 → `e1e3a3c3` (openDox-code `dede32b4`, the 0.1.0 commit T099 publishes). - T086: opensoft/openXdox-code#37 → `56e1c238`. - T090 step 5: opensoft/openXdox#22 → `9564d5d9`. - Lane openXfactory-3's ahead PR (D2, non-arc: the CLI help golden, the usage line and the rebound-Host case at both pins) → #1234, `ca1c148646f1111bc8049bc9cceb3c14ef276967`. This branch merges `main` in at `9cd1bf23` (a merge, never a rebase). - **Holder decisions in force (2026-10-05):** - (a) both pin pairs move in ONE commit, as in T047 and T064 (below); - (b) T092's phase-3 `edits[].note` annotations ride in T089's checkpoint PR (lane openXfactory-3's D3; #656 comment `5987195870`, D5), NOT here. This PR touches no manifest note; - (c) the stale `src/opendox/consumer_reach.py` admission is removed and asserted ABSENT; - (d) the 4 + 3 carve-time files the walk still names stay as T064 left them; - (e) the merge of `main` (`9cd1bf23`) carries the `Lane:` line and no `Arc:` line. T091's trailer belongs on realization commits and on the landing, and the squash landing writes `Arc:` from this body. On the merge, F11.1's guard would charge #1234's non-arc files to the arc. - It stays a DRAFT until the holder marks it READY. ## The pins: both pairs in ONE commit (`caa8d377`) | pair | gitlink | pin file `commit:` | `digests.tree_sha256` | | --- | --- | --- | --- | | openDox | `d5098297` → **`e1e3a3c3`** | same (`contracts/opendox-pin.yaml`:118) | `2815ca23…57cc` → **`55a110f49d268e22d382d47d778dfaf9298c93b555e3c4fcb621afc99f9d011b`** (28 records) | | openXdox | `f257e021` → **`9564d5d9`** | same (`contracts/openxdox-pin.yaml`:109) | `52f0598e…6959` → **`11585eadf4fef2ffcb4419194fa6a52444f56759cfc427d41c352a6b8803cbd2`** (29 records) | - **`e1e3a3c3` is opensoft/openDox#18's squash (T087), one commit above `d5098297`.** It moves `code` `047bb4fa` → `dede32b4` with `contracts/code-pin.yaml` and changes no other path, so openDox's `contracts/manifest.yaml`, its `spec` gitlink and the bundle (`dox-v1.1`) are unchanged. openDox's `main` has since moved to `504324de` (opensoft/openDox#17, T076, the root README only). Step 2's root commit is the one T090 pins, and no check reads `main`'s tip. - **`9564d5d9` is opensoft/openXdox `main`, where #22 squash-landed** (its tree equals #22's head `db6cc2a4`). It moves `code` `6a3b93b9` → `56e1c238`, which is openXdox-code `main` after #37 (T086), and `contracts/opendox-pin.yaml` `d5098297` → `e1e3a3c3` (T090 step 5). - Every digest was recomputed three ways: `repo_shape.tree_digest`, an independent `ls-tree` + `sha256`, and the forge's tree listing (`repo_shape.tree_digest_from_gh`). Controls: the same three methods reproduce the recorded `52f0598e…6959` at `f257e021` and `2815ca23…57cc` at `d5098297`. - **Why one commit and not "one commit each" (T090 step 6).** #22 changes the openDox pin that `verify-opendox-pin.py` check 5 reads through the openXdox gitlink, and `docs/openxdox-pin-resync-runbook.md` § 4 prints DIFFERENT. Each split order was measured on this branch's base, and `verify-opendox-pin.py` exits 2 in both: - the openDox pair alone: `REFUSE opendox-pin-lockstep-mismatch: this pin names openDox@e1e3a3c3f8dd38214510412b71a2e858c6179532, but openXdox's own openXdox/contracts/opendox-pin.yaml names openDox@d5098297a5c262f9977193305210bccb4ec51e89; two direct declarations of one product's bytes disagree.` - the openXdox pair alone: `REFUSE opendox-pin-lockstep-mismatch: this pin names openDox@d5098297a5c262f9977193305210bccb4ec51e89, but openXdox's own openXdox/contracts/opendox-pin.yaml names openDox@e1e3a3c3f8dd38214510412b71a2e858c6179532; two direct declarations of one product's bytes disagree.` So "one commit each" cannot be met without an intermediate red commit. **The holder ruled the single commit for phase 3 on 2026-10-05**, as for phase 1 (T047, #1181) and phase 2 (T064, #1215, decided 2026-09-28). This PR therefore departs from T090 step 6's "one commit each" for the third time. Each pair still moves as one unit (box 9.5). - Both pin files are edited in place, keeping their line counts (216 and 154). The openDox `migration:` block keeps `range` (`0001..0002`) and `reversible` (`false`): no migration path changes over openDox-code `047bb4fa..dede32b4`. Its `runbook` names the new code leg `dede32b4`, and the block is identical to openXdox's derived copy at `9564d5d9`, which `tests/opendox_pin` asserts. - **Gates.** - `verify-opendox-pin.py`: `OK opendox-pin verified: openDox@e1e3a3c3f8dd38214510412b71a2e858c6179532, gitlink read from HEAD, sorted-ls-tree-r-v1 tree digest recomputed (55a110f4…011b), lockstep with openXdox confirmed`. - `verify-openxdox-pin.py`: `OK openxdox-pin verified: openXdox@9564d5d9462ffd1a3155d9177206368e5061efa8, gitlink read from HEAD, sorted-ls-tree-r-v1 tree digest recomputed (11585ead…cbd2)`. ## What else it carries | commit | what | F11.1 surface | | --- | --- | --- | | `3c1c1146` | **The host wiring.** `scripts/opendox_host.register_openxfactory()` calls `openxdox.column_contributions.register()` (T086) after the projection line, and refuses by name when it registers nothing. **`GovernedBindingTrust`** (RULED #656 `5970369724`, "Governance approval (Recommended)") is the sixth `seams()` entry, before the home seam, with its take-back row. Its verdicts: a binding pending in the governed declarations is untrusted (host basis, the governed reason); an unreadable declarations document admits nothing; otherwise trusted, host basis. It answers the console intake's own question, `intake_verdict`, as plan 034's T100 entry says a host policy must. Its `record()` writes nothing and returns None, which openDox-code#86 reads as "no record" (`doxbench_trust.recording_for`; #656 `5986391296`, applied to T094 by `5988088910`), so a failed `add` or `edit` write is refused as the write's own failure and never with `REASON_NO_WITHDRAWAL`. `tests/domain_profile/test_host_registers_binding_trust.py` (new, 9 tests, 11 cases at `7e31eca1`) and `test_openxfactory_host_wiring.py` (six seams; the three columns the facet composes; each declared once) cover it. They pin openDox-code#86's final `REMEDY_NOT_BY_TRUST` and `INTAKE_HOST_NOT_ADMITTED` strings. Planted mutants, measured over the draft rounds of this same code, are each killed: M1-M3 and M5 by `test_host_registers_binding_trust.py`, the column line removed (M4) by `test_doxbench_routes`, `intake_verdict` removed or admitting everything (M6, M7), and `record()` returning the verdict, returning True, or writing MachineTrust's store (M8, M9, M11). | HOST, HOST_TESTS | | `3c1c1146` | **Composition tests**, amended in the arc: `test_extension_point_parity.py` (the `/capabilities` arm of T073 and T103, and the MRO's T084 layout), `test_serve_column_split.py` (the snapshot arm's four handlers are the core's own after T086's trim; every column method is the column's own), and `test_doxbench_status_exemption.py` (T085's `register_default_status_exemption` joins the readers of the registered rail). | COMPOSITION_TESTS | | `1c5f8edb` | The render lane's `RENDER_LEG_MODULES` and the seal test's `RENDER_UNIT_IMPORTS` gain `opendox/doxbench_trust.py`, `opendox/doxbench_intake.py` and `openxdox/column_contributions.py`, which the host bootstrap now imports. The seal carries a leg's whole `src/`, so no sealed artifact changes. `scripts/profile_openxfactory.py`'s note on the two openXdox columns moves to the past tense. | ADMITTED_ARC_EDITS (both paths); HOST | | `24215223` | `test_ruling_q7_two_direct_upstreams_in_lockstep`'s snapshot literal moves `d5098297` → `e1e3a3c3`, as its comment says it does on every bump. | ADMITTED_ARC_EDITS | | `eda75977` | **The lane route's predicate check** (T086's Q8 (a)). openXdox-code's `test_the_hosted_session_arrival_path_is_recorded_and_not_built` no longer reads openxFactory's `_handle_refresh_action` (opensoft/openXdox-code#37 narrowed its loop to the leg's own routes), so `tests/domain_profile/test_lane_route_asks_the_hosted_ref_predicate.py` (new, 2 tests) asserts it here: the route's body calls `hosted_ref_refused(` (openXdox's predicate), and on a hosted plane a refresh naming a session ref is refused with `session_unavailable` before it runs, while a ref-less one runs. Three planted mutants are each killed: the check removed, the call kept but not deciding, and the call asked as loopback. | HOST_TESTS | | `b3a4b6e0` | **29 `created:` admissions** in `docs/opendox-carve-admissions.yaml`, pinned in `tests/carve_arrival` by path, `since` and count, as T047's 37 and T064's 129 are, **and one removed** (below). | ADMITTED_ARC_EDITS (both paths) | | `16136990` | The admissions test's ordinal paragraph and its sixteenth-bump docstring and comment name this PR, #1236 (a follow-up commit: the number did not exist before the PR). | ADMITTED_ARC_EDITS | | `9cd1bf23` | Merge of `main` at `ca1c1486` (lane openXfactory-3's ahead PR). It merged with no conflict, and its four files are byte-identical to the ahead commits this branch was measured over. It is not a realization commit, so it carries the `Lane:` line and no `Arc:` line (T091): F11.1's guard selects commits by that line, and walked over this branch it would otherwise charge #1234's two non-arc files to the arc. | (not on `main`'s first-parent line) | | `7e31eca1` | **Copilot's finding at `16136990`, and the pre-review's six fix-now findings.** (Copilot) A refusal now gives back the unread defaults this call replaced: `_DEFAULTS` names the two globals and the default-registration call of each default-holding seam (T085's doxBench pair, T100's trust default). A write that replaced an unread default is recorded with it, and the take-back registers it again as the unread default, as `openxdox.column_contributions` does. The pre-review's six: (1) the no-columns refusal is tested, and no host seam is written; (2) a refusal at the trust seam is tested on fakes and on the pinned leg; (3) "five seams" becomes six where the count is meant; (4) `GovernedBindingTrust`'s docstring names the one case that changed; (5) the failed-write case skips as root; (6) `__all__` is in ASCII order and names `GOVERNED_PENDING_REASON`. The give-back case, the six-seam message and the exports case each failed before the fix. Planted mutants M12-M19 are each killed. | HOST, HOST_TESTS | The 29 admissions, each `since` the leg's own squash landing (`git log --diff-filter=A`), each path present at the new pin, and none placed by a row or declared before: - **`opendox_code`, 25**: #65 (T088) 1, #67 (T070) 1, #69 (T072) 1, #71 (T085) 2, #72 (T073) 1, #74 (T081) 1, #77 (T084) 9, #78 (T099) 1, #80 (T103) 1, #81 (T102) 1, #82 (T100) 2, #84 (T104) 3, #85 (T102 follow-on) 1. All are openDox-code landings over `047bb4fa..dede32b4`. - **`openxdox_code`, 4**: #37 (T086) at `56e1c238`: `src/openxdox/column_contributions.py`, `tests/test_column_contributions.py`, `tests/test_column_contributions_governed.py` and `tests/test_host_plane.py`. - **One leaves: `src/opendox/consumer_reach.py`** (openDox-code#9, `da8aae96`). openDox-code#77 (T084) deleted it at `e49b17c3` when it retired the reach module, so the walk at `dede32b4` never consumes the admission and the verifier would report it stale (`declared_admissions_unused`). It is removed, as split-opendox § 3.4 slice S5 removed its two re-homed modules', and `tests/carve_arrival` asserts it ABSENT. openXdox-code's own `src/openxdox/consumer_reach.py` (the RULED seed) is still at `56e1c238`, and its entry stays. - Neither spec leg moved (`f7ee3c76`, `f088b097`), so neither admits anything. - **Derived, not run green, for the `-code` legs**, as at T047 and T064: the walk, with every rule `verify-carve-arrival.py` applies, reports stale 0 and only the carve-time files that are unchanged since the old pins (4 at `opendox_code`, 3 at `openxdox_code`), which T064 left as well (decision (d)). ## T094's "Owed elsewhere" list from opensoft/openXdox-code#37, each item to the file that carries it - [x] `scripts/opendox_host.register_openxfactory()` calls `column_contributions.register()` after T064's projection line (Q6 (a)): `scripts/opendox_host.py` (`3c1c1146`). - [x] The module seals: `scripts/ideation_dashboard/dashboard_refresh_lane.py` and `tests/ideation-dashboard/test_dashboard_source_seal.py` (`1c5f8edb`). The carve admissions (`created:` gains `src/openxdox/column_contributions.py`, `tests/test_column_contributions.py`, `tests/test_column_contributions_governed.py` and `tests/test_host_plane.py`): `docs/opendox-carve-admissions.yaml` and `tests/carve_arrival/test_verify_carve_arrival.py` (`b3a4b6e0`). - [x] The parity test's MRO layout and `test_serve_column_split.py`'s four snapshot rows, which move to the core: `tests/ideation-dashboard/test_extension_point_parity.py` and `tests/ideation-dashboard/test_serve_column_split.py` (`3c1c1146`). - [x] `test_openxfactory_host_wiring.py`'s "second copy of the column" check and its contributed tuple, which now has three entries: `tests/domain_profile/test_openxfactory_host_wiring.py` (`3c1c1146`): `test_no_route_extension_declares_a_second_copy_of_the_column` holds each column to one declaration, and `CONTRIBUTED_COLUMNS` is `LaneRoutes`, `GateRoutes`, `ProjectionRoutes`. - [x] The lane route's `hosted_ref_refused(` check (Q8 (a)): `tests/domain_profile/test_lane_route_asks_the_hosted_ref_predicate.py` (`eda75977`). - [x] The trust policy at T100's seam (openXdox registers none; "Governance approval", #656 comment `5970369724`): `GovernedBindingTrust` in `scripts/opendox_host.py`, tested by `tests/domain_profile/test_host_registers_binding_trust.py` (`3c1c1146`). ## F11.1, on the real commits `PACKET_MERGE=94b6f7f1… ARC_TIP=<this branch's head>` over the guard extracted from `openspec/changes/add-neutral-product-standalone-operability/tasks.md` prints: > `requirement 1 holds: 0 note(s) annotated, every other path a declared surface (11.1)` Every path this PR touches is on a declared surface: - PIN_PAIRS: `openDox`, `contracts/opendox-pin.yaml`, `openXdox`, `contracts/openxdox-pin.yaml`; - HOST: `scripts/opendox_host.py`, `scripts/profile_openxfactory.py`; - HOST_TESTS: `tests/domain_profile/test_host_registers_binding_trust.py`, `tests/domain_profile/test_lane_route_asks_the_hosted_ref_predicate.py`, `tests/domain_profile/test_openxfactory_host_wiring.py`; - COMPOSITION_TESTS: `tests/ideation-dashboard/test_extension_point_parity.py`, `tests/ideation-dashboard/test_serve_column_split.py`, `tests/ideation-dashboard/test_doxbench_status_exemption.py`; - ADMITTED_ARC_EDITS: `scripts/ideation_dashboard/dashboard_refresh_lane.py`, `tests/ideation-dashboard/test_dashboard_source_seal.py`, `tests/openxdox_pin/test_openxdox_pin_verifier.py`, `docs/opendox-carve-admissions.yaml` and `tests/carve_arrival/test_verify_carve_arrival.py`. The admitted list does not grow, and no manifest note is annotated here (decision (b)). ## The falsifiers, at the COMMITTED pins | run | head | verifiers | `pytest-suite` | other checks | | --- | --- | --- | --- | --- | | **CI** | `16136990` | OK, OK | **`selected=9362 passed=9356 skipped=6 failures=0 errors=0`**, floors met (margin 2312), run `37315023063` | all success, `openxdox-consumer-gate` included | | local | `eda75977` (`16136990` changes only a docstring and a comment) | OK, OK | **8943 passed, 7 skipped, 0 failed** (`pytest tests/ -q -m "not postgres"`) | the composition, `domain_profile`, carve-mapping, both pin dirs and `carve_arrival`: 569 passed | | **CI** | `7e31eca1` | | PENDING | PENDING | | local | `7e31eca1` | OK, OK | PENDING | `domain_profile`, the seal and the carve mapping: 626 passed; mutants M12-M19 killed | Each local run uses Python 3.12.3, with `TMPDIR` and `--basetemp` under `~/.local/state`, outside the aggregation tree, in a checkout named `openxFactory`. A local run skips 7 where CI skips 6: the work tree sits inside an aggregation checkout, so the aggregation ignore-file case runs and passes there (#1215's reason). - `validate-carve-manifest.py` prints OK (456 rows), and `validate-former-id-arrival.py --base origin/main --head HEAD` passes. ## Accepted limits - A leg from before T100 now fails with an ImportError, because `seams()` imports `doxbench_trust`, rather than with `HostSeamsIncomplete` by name. The pins only move forward. - A directory at the declarations path reads as "no document". That is openDox's own store rule (`document_present` checks for a regular file), and the change opens no new hole. - Under the governed host, `model-binding trust` prints `trusted "m1" on this machine` although `record()` records nothing. That wording is openDox-code's (`cli_model_binding._trusted_line` ignores `recording.recorded`), and it is deferred to an openDox-code follow-on after release 1. - The trust seam's take-back entry cannot fire today. Only the home seam follows it, and the home seam refuses nothing. Nit: `_TAKE_BACK` is keyed by the bare call name `"register"`. ## What this leaves for the aggregation This PR does not do the opensoft/xFactory root pin-sync. When it runs, it needs: - the root `openDox` gitlink → `e1e3a3c3f8dd38214510412b71a2e858c6179532`; - the root `openXdox` gitlink → `9564d5d9462ffd1a3155d9177206368e5061efa8`; - the root `openxFactory` gitlink → this PR's landed sha, with `.github/clearing/openxfactory/PIN.yaml` in the same commit (CLAUDE.md rule 2); - `.github/workflows/dashboard-image-worker.yml`'s `RENDER_LEG_MODULES` and its mirror in `tests/test_dashboard_image_worker_contract.py` gain the same three modules as this PR's `1c5f8edb`. Arc: neutral-product-standalone-operability 🤖 Generated with [Claude Code](https://claude.com/claude-code) Lane: openxfactory-4 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>



Plan 034, task T087, the openDox root pin, phase 3. The plan is
specs/034-opendox-standalone-operation/tasks.mdat opensoft/openxFactorymain. This PR realizes box9.5 (part) of the ratified
add-neutral-product-standalone-operability, as T090 steps 1-2.Arc: neutral-product-standalone-operability
5992552627.What changes -- THE PIN THIS PR DELIVERS IS
dede32b4b6f3d0f147d599776f83628c5af8ff3dONE commit (
f451f68c, this PR's head), made by openRepoShape'sscripts/bump-leg.py(the tool CONTRIBUTING.md names), moves exactly two things, as T062 (#16) did:code(gitlink)047bb4fa394f3e1bf42466062a67ef18e99f8d6adede32b4b6f3d0f147d599776f83628c5af8ff3dcontracts/code-pin.yamlcommit:047bb4fa394f3e1bf42466062a67ef18e99f8d6adede32b4b6f3d0f147d599776f83628c5af8ff3dcontracts/code-pin.yamldigests.tree_sha25697536dbe7454ac062cc8fd3e34fd15a32eee52213f0292042b243f7e5c699a02c2672463b4d8cf834026e2faae23478105d9e98650fcc07d971c19e387e7e0a7Diffstat: 2 files changed, 3 insertions(+), 3 deletions(-). The
specleg andcontracts/spec-pin.yamlare untouched.No workflow file moves. No
.github/workflows/*.ymlreferences the code leg by@<sha>:bump-leg.pyreported"no
@<sha>reference names this leg", andgrep -rnE "openDox-code[^ ]*@[0-9a-f]{40}" .githubfinds nothing.The commit pinned
dede32b4b6f3d0f147d599776f83628c5af8ff3dis the commit openDox-code#79's squash landed: T101's version bump to 0.1.0, the last phase-3 openDox-codelanding that changes the shipped package, right after openDox-code#78's release workflow. T099 publishes exactly the commit this root
pins (RULED
5963162921), and the release workflow's build job refuses a commit this root does not pin.047bb4fais an ancestor ofdede32b4, so this is an ancestor move. Its first-parent history above the phase-2 pin is22 landings (
git log --first-parent 047bb4fa..dede32b4in thecodesubmodule):dede32bd59f3f2651c35f32943cb38d3350ca9e1bdc4b55cc0116293390e2c2e49b17c90ac7038e377829197ccd5e7ab001130e999a490402fc714d66ff7258a98e317ff434dd0d3cee2680eb5T087's
After:line is T074, T077, T083, T084, T085, T088, T100, T101, T062 and T007 batch P. The openDox-code onesare in the table above. T074, T077 and T083 are runs recorded in openxFactory (openxFactory#1224, openxFactory#1223 and openxFactory#1231). T062 landed as
openDox#16 ->
d5098297. T007 batch P landed as openxFactory#1230. The chat rail's follow-on (openDox-code#85) and T100'sfollow-on (openDox-code#86) are in the table too.
Falsifier
make pinsat this PR's head (f451f68c):make validate(naming, manifest, lockstep pins; what CI runs) also passes, exit 0:Each half-move is refused, measured in a copy of this tree:
FINDING pin-gitlink-mismatch, exit 1;tree_sha256givesFINDING pin-digest-mismatch, exit 1.A fresh
git cloneof this branch withgit submodule update --init --recursive, CI's own step, passes the three CIsteps (naming, manifest, pins), each with exit 0.
The digest, recomputed independently
c2672463b4d8cf834026e2faae23478105d9e98650fcc07d971c19e387e7e0a7issorted-ls-tree-r-v1overdede32b4b6f3d0f147d599776f83628c5af8ff3d(329 records). Four methods gave the same value:repo_shape, in thecodesubmodule's own object storec2672463...e0a7, 329 recordsgit ls-tree -r -z <sha> | tr '\0' '\n' | sed '/^$/d' | LC_ALL=C sort | sha256sumbump-leg.py, which usesrepo_shape.tree_digest, andvalidate-pins.py's recomputegh api repos/opensoft/openDox-code/git/trees/<sha>?recursive=1(not truncated), tree rows dropped,mode type sha TAB pathsorted and hashedSanity check first. Method A reproduced the trusted value for
047bb4fa,97536dbe7454ac062cc8fd3e34fd15a32eee52213f0292042b243f7e5c699a02(299 records),before it was applied to
dede32b4.Not this PR
contracts/CHANGELOG.mdis not edited. A code-pin move carries no CHANGELOG line (T062's reason: thecodelegcarries no contract bytes).
specleg,contracts/spec-pin.yaml,contracts/manifest.yamland every workflow file are untouched.opendox @pin to this same openDox-codecommit. T094 (T090 steps 5-6) then moves the openXdox root, and openxFactory's pin pairs and host wiring with it.
Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
🤖 Generated with Claude Code
Summary by Sourcery
Enhancements: