Skip to content

T059, openXdox contributes its governed generator, registry and source through openDox's seams (5.4a) (plan 034) - #35

Merged
brettheap merged 25 commits into
mainfrom
build/034-p2k-t059-governed-contributions
Sep 30, 2026
Merged

brettheap merged 25 commits into
mainfrom
build/034-p2k-t059-governed-contributions

Conversation

@brettheap

@brettheap brettheap commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability

DRAFT. T062 has landed, and this PR is pinned to its commit.

  • T062 landed as T062, phase 2's openDox root pin: code → 047bb4fa (plan 034, T090 steps 1–2) openDox#16, merge commit d5098297. It pins openDox-code 047bb4fa (047bb4fa394f3e1bf42466062a67ef18e99f8d6a), the head of openDox-code main after T058.
  • pyproject.toml's opendox @ pin now names that commit, at 25414afc. Before that it named 814516b7, openDox-code#59's head while that PR was a draft.
  • The comments that name the pin were each re-measured at 047bb4fa. They are in src/openxdox/view_extensions.py, tests/test_dependency_direction.py, tests/test_gate_loop_probes.py, tests/integration/test_assembled_bundle.py and validate.yml.
  • T055 landed as openDox-code#59 (fa140875). Between the two pins sit T057 (#58, 8ec08e91), T055's follow-up (#70, 75bd8703), T056 (#66, a23e4224) and T058 (#68, 047bb4fa).
  • The holder retargets T061 (openXdox-code#36, stacked on this branch) to main before this PR goes READY. A --delete-branch landing would close it.

What this is

This PR carries plan 034's T059 (specs/034-opendox-standalone-operation/tasks.md, read at openxFactory main 91e4685f), slice P2-K: 5.4a, openXdox contributes its governed generator, registry and source through openDox's seams. It is the governed half of R1Q10 (a).

  • Realizes: 5.4a, and 9.5 (step 3, part).
  • Ruled: R1Q6 (d), R1Q7 (a), 5817152735; R1Q10 (a), R1Q23 (a), 5850003126; R1Q26 (a), 5851950767.
  • After: T052 (landed, openDox-code#54 → fa8862cc), T055 (landed, openDox-code#59 → fa140875), T060 (landed, openXdox-code#34 → c41063d6), T062 (landed, openDox#16 → d5098297), T067 and T007's batches C and I (landed; batch I is openxFactory#1180 → 8421603a), and T040 (landed, openXdox-code#29), for the ratchet's single-writer order.

openXdox keeps generator.py, snapshot.py, snapshot_registry.py, completeness.py and corpus_root.py. The new openxdox.projection_contributions registers what they provide at openDox's seams:

seam openXdox's contribution
opendox.generator_seam GENERATOR, a SnapshotGenerator over generator.generate_snapshot, declaring its two inputs (project_register_source, possibles_source)
projection_seams.registry the snapshot_registry module
projection_seams.corpus_root CORPUS_ROOT: corpus_scan_defect, corpus_root_refusal, change_rows and SCANNED_ROOTS
projection_seams.writer the snapshot module (write_snapshot)
projection_seams.validators VALIDATOR, for the three governed kinds (ideation-dashboard-snapshot, -index, gate-action-record). openDox's own kinds keep openDox's validator.

generator, corpus_root and completeness import openxFactory's doc_health at module level, and a lone checkout does not carry it (R1Q6 (d); the direction arc is T008). So the contributions reach those modules late, when they are used. Registering reaches no module that needs doc_health, and a subprocess case holds that with doc_health blocked.

register() is explicit, idempotent, and all or none. A seam's refusal (GeneratorAlreadyRegistered, SeamAlreadyRegistered) reaches the caller unchanged, after every seam that call wrote has been taken back, in reverse. is_registered() and unregister() complete the API.

The holder's rulings on this PR

Each of these is the holder's reading, given on this PR's questions.

  1. Where the contributions register: (c), not (a).

    • openxdox.projection_contributions.register() is an explicit call.
    • openxdox.domain_profile.register() calls it too, so openXdox standalone gets its governed projection from its own registration path.
    • domain_profile.load() stays free of side effects. Registering from load() was option (a), and it was ruled out: it would fire in every process that only reads a profile (the verifiers, the NotebookLM sync, tests).
    • This revises the holder decision in openDox-code#54's body (2026-09-27). That decision read: "T059 registers openXdox's generator from openXdox's own profile-registration path, the hook openxFactory already calls. So T064's line stays true, and T064 needs no host line." It rested on a misread. openxFactory's scripts/opendox_host.register_openxfactory() never calls openxdox.domain_profile.register(): it calls openxdox.domain_profile.load(PROFILE_PATH) and registers the composite with openDox alone (opendox.domain_profile.register(composite)).
    • So T064 owes one host line: openxdox.projection_contributions.register() in register_openxfactory(). T064's line "It composes openXdox's profile, so none is expected" no longer holds. scripts/opendox_host.py is on F11.1's host surface, so its guard admits the change.
  2. The home corpus in the test harness: (c). openDox's authoring.create_scaffold asks the registered home corpus which fields it obliges (scaffold_lead_fields(), T054). With nothing registered it refuses, as #1144's 4.1a has every seam do:

    "A process in which no entry point was built and nothing registered anything — an import, a test, a library caller — still refuses with 4.2's ADAPTER_NOT_REGISTERED, so the default is a registration the entry point makes and never a fallback inside the seam."

    That rules out (a), a fallback inside the seam, and (b) would amend a ruled falsifier environment. So tests/conftest.py registers the same factory openxFactory's host registers, corpus_adapter_openxfactory.home_corpus, found where F5.2's environment composes openxFactory's scripts/ on PYTHONPATH. Where it is absent, it registers nothing, and a lone checkout refuses as 4.1a says.

    • tests/conftest.py is not a protected suite. It matches neither F5.2's glob (tests/test_generator.py, tests/test_snapshot*.py, tests/test_session_snapshot.py) nor 12.5's computed set (git grep -l -e open-pr -e open_pr -e FakePullRequests -- 'tests/test_*.py'). So it has no allow-list entry.
    • The declared-exclusion accounting is unchanged by it. Every suite that reaches the home corpus also reaches doc_health, so each is already declared. The lone whole suite is green with nothing registered.
    • The cases are green again, measured in composition (below). At e3ef506a there were 69. At 814516b7 there are 71, the same 69 plus the 2 T054's final head routes through the home corpus. All 71 pass here.
  3. The respelling: accepted as an R1Q7 (a) entry citing T055's r4136863569. The expected call in tests/test_session_snapshot.py::test_the_session_source_read_is_the_existing_confinement_mechanism is respelled from self.source.registry.resolve_source( to resolve_source_path(Path(root), rest), the route's one entry point, which applies the registered registry's resolve_within. The second assertion is unchanged.

  4. The consumer-schema reds: (a). In F5.2's environment, seven cases are red at BOTH pins because the consumer's schemas are not in a lone tree: test_generator.py 4, test_snapshot_determinism.py 1 and test_snapshot_registry.py 2. They are deselected in T059's F5.2 run with R1Q25 (b)'s reason. A supplementary run with a composed CONTRACTS_DIR shows all seven green (below). test_snapshot_validation_launch.py's 5 reds are C3's, so they are T061's.

  5. The exclusion entry: accepted. T059 removes tests/test_seam_assembly_beside_gate_and_projection.py from tests/declared_exclusion.yaml, taking it from 67 to 66 files. The file was declared under doc_health only because serve_projection reached doc_health through snapshot_registry at import. snapshot_registry's one read of doc_health (pin_sentinels) now happens where the sentinel is written, so the file passes alone in a lone checkout, and T041's test_declared_exclusion would refuse it as declared. T059 joins the exclusion file's single-writer chain between T044 and T061: T044 → T059 → T061.

  6. Three pre-arc reds in tests/test_session_snapshot.py: (a), ruled after this PR opened. They are deselected in T059's F5.2 run with the reason "red at both pins; pre-arc carve residue; not the arc's", and this PR does not edit them. They stay open for F5.2 whole (T061/T063).

    • test_a_new_serve_process_re_registers_the_session_at_startup: opendox.serve has no SNAPSHOT_INDEX_ROUTE. The constant moved to openxdox.serve_projection in split-opendox § 2.4 PR-3 (#761).
    • test_a_session_key_is_validated_against_the_roster_before_url_composition: the node probe copies only repo-selector-model.js, which imports ./display.js (since openDox-code#21, § 3.4 S7).
    • test_the_hosted_session_arrival_path_is_recorded_and_not_built: _handle_refresh_action is not on openXdox's serve surface. It moved to openxFactory's serve_openxfactory_lanes.py in § 2.4 PR 3.

What changes

path what changes
src/openxdox/projection_contributions.py Created. The contributions, as above.
src/openxdox/domain_profile.py register() also registers the contributions, after its own refusals and before the profile is held, so a refused contribution leaves no profile registered. unregister()'s docstring says why the contributions stay (below).
src/openxdox/snapshot_registry.py Reads pin_sentinels only where it writes the sentinel, for an entry with no revision. Seals gaps 1, 2 and 4 below. index_document and compose_aggregate each take one reading.
src/openxdox/snapshot.py Seals gap 3 below. SnapshotNotWritable is a ProjectionSeamError and a ValueError.
scripts/protected_suites.py Created. Batch C's subtraction (below).
tests/test_projection_contributions.py Created, 22 cases.
tests/test_governed_registry_and_writer.py Created, 27 cases, one or more per gap.
tests/test_protected_suite_check.py Created, 43 cases, over scratch git histories.
tests/test_gate_loop_views.py Protected (12.5). Batch I's second admitted edit, entered.
tests/test_session_snapshot.py Protected (F5.2). The respelling, entered.
tests/protected_suite_respellings.yaml Entries 2 and 3. The header now says who reads the file and states the named-test condition.
tests/conftest.py The home corpus, as ruled (2 above).
tests/test_generated_at_anchor.py Patched snapshot._locate_validator, which openDox's generate verb no longer reaches. It now patches the registered validator's locate().
tests/test_dependency_direction.py The ratchet is lowered for T055's reaches: cli and serve leave OPENDOX_BACK_IMPORTS, and branch_session goes from (0, 7) to (0, 2). DOC_HEALTH_SURFACE records snapshot_registry as (0, 1).
tests/declared_exclusion.yaml, tests/test_declared_exclusion.py, the four seam files The exclusion entry leaves (5 above), and the prose follows.
pyproject.toml The pin: 2d116415 → 047bb4fa, T062's commit. In the drafts it named 814516b7, #59's head.
.github/workflows/validate.yml Floors raised to CI's reading, with the reason. The prose that named the old pin or the declared file is updated.
src/openxdox/view_extensions.py, tests/test_gate_loop_probes.py, tests/integration/test_assembled_bundle.py Comments that name the pin follow it, each measured at 814516b7 and again at 047bb4fa, where each claim still holds. ViewBinding still has styles and exports. web/, view_extension.py and the copied stylesheet helpers are unchanged from 2d116415.
tests/test_projection_contributions.py (at 047bb4fa) One seam moved in T058: default_projection.VALIDATOR, one stand-in for all of openDox's own kinds, became VALIDATORS, one validator per own kind. The two cases that name it read VALIDATORS[kind]. This file is this PR's own, not a protected suite.
src/openxdox/projection_contributions.py (at aa0a2c5d) A refused registration gives back each unread default it replaced, as the default it was, instead of leaving the seam empty (Copilot, r4149710491).

A kept decision on teardown. Copilot asked whether domain_profile.unregister() should release the contributions. It does not. The contributions belong to the process, not the profile:

  • a host registers them without this module too (T064);
  • openDox's seams refuse a governed registration once a default has been read.

So a teardown that took them back could not be undone wherever anything was served from a default in between, and a test fixture that takes the profile away for one case could not put it back. projection_contributions.unregister() is their teardown. The docstring says so, and a case pins both halves.

The four gaps

openDox's own defaults sealed each of these in openDox-code#59's review rounds, and #59's body names them as openXdox-code's to seal before T059 registers this leg's mechanisms.

  1. resolve_within's symlink escape (r4125556296). The hidden-name rule was applied only to the path as the URL spelled it, so link -> .git served /source/link/config, and notes.md -> .env served .env. The rule is now applied to the canonical path too. The source root is resolved under the same guard, so a root that is a symlink loop refuses instead of raising (Copilot).
  2. drop left a dangling active key. Dropping the active entry now clears the key. Left set, it also kept every later entry from becoming active.
  3. The writer.
    • It wrote in place (r4126138808). It now writes an exclusive temporary sibling, keeps the target's permission bits, fsyncs, and moves the sibling over the target in one os.replace. A failed move leaves the old snapshot and no sibling.
    • canonical_json wrote NaN and Infinity (r4125900060). A value JSON cannot carry is now refused, with nothing written.
  4. SnapshotRegistry read without its lock (r4136863481). Every read now holds it, and the index and an aggregate's composition are each one reading (Copilot, r4139816732).

The protected edits, and batch C's wiring

Both edits are entered in tests/protected_suite_respellings.yaml, naming this PR:

entry suite and test edit blobs
2 tests/test_gate_loop_views.py::test_the_overlay_changes_four_words_and_the_named_absence_and_nothing_else admitted (R1Q26 (a), batch I): the test expects the values block's six leaves beside the five it pinned a56906c6 → a5ce00cc, chained on entry 1
3 tests/test_session_snapshot.py::test_the_session_source_read_is_the_existing_confinement_mechanism respelling (R1Q7 (a), T055's r4136863569) b5e1be02 → f78c4452

Each is its own commit on this branch (81a01cd, 614f79f), so each entry also holds at its commit.

scripts/protected_suites.py is batch C's subtraction (RULED R1Q7 (a), 5817152735). It is the last step of F5.2 and of 12.5's falsifier, in place of the inline intersection each ended with:

python3 scripts/protected_suites.py --landings="$(cat "$W/x-arc.txt")" --suites="$(cat "$W/gen-suites.txt")"   # F5.2
python3 scripts/protected_suites.py --landings="$(cat "$W/x-arc.txt")" --suites="$(cat "$W/governed.txt")"     # 12.5
  • The falsifier still lists the landings and the protected suites itself.
  • The script admits a touched suite only where one entry holds at that landing. An entry holds when:
    • the before and after blobs are the entry's;
    • old occurs once, and replacing it with new gives the after text byte for byte;
    • old starts a line, as it ends one;
    • both lie inside the named test.
  • Each entry admits one landing. The landings are taken oldest first, so a later landing that repeats a spent entry's edit is refused.
  • Renames are not detected, so a protected suite renamed away counts as a deletion.
  • It exits 2, subtracting nothing, when its input or the allow-list breaks the rules, or when the checkout does not hold a landing's history.
  • The lists are passed as values, never as paths: SonarCloud's first analysis flagged a path read from argv, S8707.

Evidence

Every run here used LANG=C.UTF-8, in the foreground.

AT THE FINAL PIN, 047bb4fa, head aa0a2c5d.

  • The required check (9.2). Run 36782773982 reads triple: selected=993 passed=989 skipped=4 failures=0 errors=0, which is the same triple as at 814516b7. So the floors, 993 and 989, already sit on CI's reading at margin 0, and do not move.
  • F5.2 in its environment, on a simulated squash landing of this head on main, with OPENDOX_CODE at 047bb4fa, OPENXFACTORY at 91e4685f and ARC_BASE at e28930bf, with the same deselects as below:
    • test_generator 41 passed, 4 deselected;
    • test_session_snapshot 20 passed, 3 deselected;
    • test_snapshot 15 passed, 2 deselected;
    • test_snapshot_determinism 5 passed, 1 deselected;
    • test_snapshot_registry 38 passed, 2 deselected;
    • test_snapshot_validation_launch 5 failed, 4 passed. These are T061's, as below.
    • test_snapshot_validator_home 12 passed.
    • The arc check admits tests/test_session_snapshot.py by entry 3, then prints ok: 1 protected edit(s).
    • 12.5's call admits tests/test_gate_loop_views.py by entries 1 and 2, and exits 0.
  • The supplementary run with CONTRACTS_DIR composed, and no both-pins deselect: test_generator 45/45, test_snapshot_determinism 6/6 and test_snapshot_registry 40/40. So the seven reds at both pins are still only the consumer's schemas.
  • Whole suite alone (CI's command): 989 passed, 4 skipped, 1 deselected.
  • Mutants: 22 of 22 killed at aa0a2c5d. That is the 21 below, plus "a displaced unread default is not given back", which fails 1 case.

The sections below were measured at 4feb8009 with openDox-code at 814516b7, the drafts' pin, and are kept as they were.

The required check (9.2), CI's reading. Run 36741174322 at 4feb8009:

triple: selected=993 passed=989 skipped=4 failures=0 errors=0
pins:   selected>=993 (margin 0) passed>=989 (margin 0) skipped==4

main c41063d6 reads 896/892/4. Compared test by test:

  • added 98: test_protected_suite_check 43, test_governed_registry_and_writer 27, test_projection_contributions 22, and test_seam_assembly_beside_gate_and_projection 6;
  • removed 1: test_declared_exclusion's case for the seam-assembly file;
  • changed outcome 0, and the same four skips.

The floors are raised to 993 and 989 (T060's 11 and T059's 97), with EXPECT_SKIPPED 4, margin zero. Each later case moved them again, in its own commit, from CI's reading of the head before.

F5.2 in its environment, as batch G amends it. That is a fresh venv, pip install ".[test]", then --force-reinstall --no-deps "$OPENDOX_CODE", with PYTHONPATH="$OPENXFACTORY/scripts". OPENDOX_CODE is openDox-code 814516b7, OPENXFACTORY is openxFactory 91e4685f, and ARC_BASE is e28930bf. The deselects are the task's two test_snapshot.py schema cases plus rulings 4 and 6.

At this head (4feb8009):

tests/test_generator.py                   rc=0  41 passed, 4 deselected
tests/test_session_snapshot.py            rc=0  20 passed, 3 deselected
tests/test_snapshot.py                    rc=0  15 passed, 2 deselected
tests/test_snapshot_determinism.py        rc=0  5 passed, 1 deselected
tests/test_snapshot_registry.py           rc=0  38 passed, 2 deselected
tests/test_snapshot_validation_launch.py  rc=1  5 failed, 4 passed        <- C3's, T061's (ruling 4)
tests/test_snapshot_validator_home.py     rc=0  12 passed
landings: 29
admitted: 614f79f05c7d tests/test_session_snapshot.py, by entry 3 of tests/protected_suite_respellings.yaml
ok: 1 protected edit(s), each entered and holding

The same block, before:

  • at main c41063d6 with OPENDOX_CODE at 814516b7 (the realized openDox, pins only): test_session_snapshot.py 20 failed (SeamNotRegistered, adapter-not-registered), test_snapshot_validation_launch.py 9 failed;
  • at main with openDox 2d116415 (the old pin): test_session_snapshot.py 3 failed (ruling 6's three), test_snapshot_validation_launch.py 6 failed.

The five validation_launch reds left here are:

  • test_the_default_shaped_launch_validates_from_the_repo_root
  • test_a_run_dir_beside_a_checkout_still_uses_that_one_first
  • test_the_dependency_warning_carries_the_pip_remedy_and_clears_the_corpus
  • test_a_non_conformant_snapshot_still_blocks_and_blames_the_snapshot
  • test_the_classifier_reads_the_exit_code_not_the_dependency_sentence

Supplementary, with a composed CONTRACTS_DIR (ruling 4). The directory holds openXdox-spec f088b09's three schemas, openDox-spec f7ee3c7's three and openxFactory 91e4685f's four. The run does not deselect ruling 4's seven:

tests/test_generator.py             rc=0  45 passed
tests/test_snapshot_determinism.py  rc=0  6 passed
tests/test_snapshot_registry.py     rc=0  40 passed

The rest reads as above, and ruling 6's three stay red.

12.5's set, and a simulated landing. Over 12.5's 16 governed suites, the check admits 81a01cd by entry 2 and c41063d6 (#34) by entry 1. A squash landing of this branch on main was simulated with git commit-tree HEAD^{tree} -p origin/main, carrying the Arc: line. It is admitted by entry 3 (the F5.2 set) and by entry 2 (the 12.5 set). With main's allow-list (entry 1 only), the same landing is refused on both paths:

  • tests/test_gate_loop_views.py: entry 1's before blob is 7321b04d, and the suite before the landing is a56906c6;
  • tests/test_session_snapshot.py: "no entry names this suite".

The 23 protected suites in composition (openxFactory scripts/ on PYTHONPATH, each suite alone), compared test by test with main at the old pin:

state red where main at the old pin was green green where it was red
main with openDox 814516b7 (pins only) 150 (130 SeamNotRegistered) 0
this head 0 3
this head with the home registration removed from conftest.py 71, all adapter-not-registered 0

Mutants, at this head. Each ran against its suites, and the file was restored and checked clean after each. All 21 were killed:

mutant killed by
take-back removed 3 failed
_holds always true / reads nothing 11 / 8 failed
domain_profile.register without the contributions 5 failed
resolve_within without the canonical check 2 failed
drop keeps the active key 2 failed
get without the lock 1 failed
allow_nan=True 3 failed
write in place 2 failed
no mode copy 1 failed
pin_sentinels back at module level collection error, plus the ratchet
the check skips each of: the before blob, the after blob, the exact text, occurs-once, old inside the test, new inside the test, input shapes, chaining 1 to 3 failed each
the facet's values block loses one governed word 2 failed (the protected facet and overlay tests)
the installed openDox route confines beside resolve_source_path 1 failed (the respelled assertion)

More checks were each shown red before the commit that added them and green after:

  • the one-window index and aggregate;
  • the rename;
  • schema_version: 1.0;
  • the single-use entry and input order, plus edit: [] and a sequence key;
  • a source root that is a symlink loop;
  • a landing the checkout does not hold (exit 2);
  • an old text that is the tail of a line;
  • a versioned entry indexed without doc_health, where a revisionless one still fails on it.

Under a global commit.gpgsign=true, tests/test_protected_suite_check.py read 16 passed and 19 errors before its fixture disabled signing, and 37 passed after.

For the tasks that follow

  • T061 (stacked on this branch):
    • F5.2's five validation_launch reds above are its to clear;
    • it removes tests/test_snapshot.py's exclusion entry, next in the exclusion file's single-writer chain after this PR;
    • it is next in the pyproject.toml pin's single-writer order.
  • T062. Landed (openDox#16 → d5098297). The pin names its commit, 047bb4fa (see the top).
  • T063. F5.2 whole runs again there. Ruling 6's three test_session_snapshot.py cases stay open for F5.2 whole.
  • T064 (openxFactory):
    • the one host line, openxdox.projection_contributions.register() in scripts/opendox_host.register_openxfactory() (ruling 1);
    • created: admissions under openxdox_code in docs/opendox-carve-admissions.yaml for the files this PR creates: src/openxdox/projection_contributions.py, scripts/protected_suites.py, tests/test_projection_contributions.py, tests/test_governed_registry_and_writer.py and tests/test_protected_suite_check.py. Also tests/protected_suite_respellings.yaml, which T060, openXdox's facet carries the governed snapshot values (5.3a) (plan 034) #34 created.
  • T066. Unchanged by this PR. openxFactory's facet still has to compose the values block. T060, openXdox's facet carries the governed snapshot values (5.3a) (plan 034) #34's note on a page that fetches no /capabilities still stands: this PR serves nothing new there.
  • T086. The ratchet goes from here to (0, 0). The eleven remaining reaches are T084's.

Review

  • Copilot. It reviewed each head from f0f7f41c on. Every thread is answered, and every finding in its overviews is either taken or answered in this body. The code findings were taken:

    • c34c0de6: one-window registry reads, renames, the schema integer, and unsigned fixtures;

    • 11c02cf4: single-use entries, malformed keys and edits, and the teardown rule stated;

    • 62a1b0d4: the root under the guard, and the seam-assembly docstring;

    • e7860056: missing history is exit 2;

    • f70ed5d1: write_snapshot's refusal order, stated;

    • 9d315537: old starts a line;

    • a1b75f3a: doc_health read only for the sentinel;

    • 1885aee1, f22c73b0, 0fdd65c1 and 4feb8009: the floors.

    • aa0a2c5d: after the re-pin, Copilot's review at 25414afc found that a refused registration dropped the unread defaults it had replaced, instead of giving them back. That finding was taken.

    At 4feb8009 its review read "Changes recommended", with Findings: None, and gave the gate as its only reason: T055/T062 had not landed and the provisional pin had not been replaced. Both are now done. Its review at aa0a2c5d reads "Needs a closer look", with Findings: None, and asked for this description to state the final pin and gate, which it now does.

    Two threads named allow-list entries as missing. They were left on f0f7f41c, and the entries were added at 619684c9; the replies quote the check admitting them. The pin thread is this PR's stated gate. There are 0 unresolved threads, including r4149710491 at 25414afc.

  • SonarCloud. The first analysis failed the gate on Security Rating C (S8707). It passes from 7815c2da on, including at aa0a2c5d.

🤖 Generated with Claude Code

brettheap and others added 8 commits September 30, 2026 00:46
…an 034 T059

T059 moves the opendox pin to the phase-2 openDox-code commit (5.4a, 9.5 step
3). That commit is T062's, and it lands after every phase-2 openDox-code
landing, so this draft builds against openDox-code#59's head, the last of the
seams T059 registers at, and re-points to T062's commit before it lands.

The comments that named the old pin as the one this leg declares are brought
to the new one, each measured there: ViewBinding at e3ef506a still has styles
and exports (dataclasses.fields in a venv at that pin), and the tuple and
helpers tests/integration/test_assembled_bundle.py copies are unchanged
between 2d116415 and e3ef506a.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e registered (plan 034 T059)

openDox's own defaults sealed each of these in openDox-code#59's review rounds,
and #59's body names them as openXdox-code's to seal before T059 registers
this leg's mechanisms at the same seams:

1. snapshot_registry.resolve_within applied the hidden-name rule only to the
   path as the URL spells it, so a symlink inside the root led to what the
   rule refuses by name (r4125556296). It now applies the rule to the
   canonical path too.
2. SnapshotRegistry.drop left the active key naming a dropped entry, which
   also kept every later entry from becoming active. Dropping the active
   entry now clears the key.
3. snapshot.write_snapshot wrote in place (r4126138808), and canonical_json
   wrote NaN and Infinity (r4125900060). The write now goes to an exclusive
   temporary sibling, keeps the target's permission bits, is fsynced, and
   moves over the target in one os.replace; a value JSON cannot carry is
   refused as SnapshotNotWritable, a ProjectionSeamError, with nothing
   written.
4. SnapshotRegistry read without its lock (r4136863481). Every read now
   holds it.

snapshot_registry also reads doc_health's pin_sentinels where it writes the
sentinel, in SnapshotEntry.index_entry, rather than at module level, so the
registration at openDox's registry seam can be made in a lone checkout.

tests/test_governed_registry_and_writer.py holds each gap, red before this
commit.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ugh openDox's seams (plan 034 T059, 5.4a)

The governed half of R1Q10 (a). openxdox.projection_contributions registers
openXdox's generator at opendox.generator_seam, and its snapshot registry,
corpus-root predicate, writer and validators for the three governed kinds at
opendox.projection_seams. openXdox keeps generator.py, snapshot.py,
snapshot_registry.py, completeness.py and corpus_root.py; the contributions
reach generator, corpus_root and completeness, which read openxFactory's
doc_health at module level, only when they are used.

register() is explicit, idempotent, and all or none: a seam's refusal takes
back every seam it wrote, in reverse, and reaches the caller.
openxdox.domain_profile.register() calls it; load() registers nothing. This is
the holder's ruling on T059 (option (c)): a host that registers openXdox's
profile with openDox alone, as openxFactory does, calls register() itself,
which is T064's one line in openxFactory's opendox_host.register_openxfactory().

tests/test_generated_at_anchor.py patched snapshot._locate_validator, which
openDox's generate verb no longer reaches; it now patches the registered
validator's locate().

tests/conftest.py registers the home corpus openxFactory's host registers
(corpus_adapter_openxfactory.home_corpus) where F5.2's environment composes
openxFactory's scripts/, and nothing where it is absent, as #1144's 4.1a has
every seam refuse unregistered (holder's ruling on T059).

The ratchet is lowered for T055's reaches: cli and serve leave
OPENDOX_BACK_IMPORTS, and branch_session goes to (0, 2). snapshot_registry's
doc_health read is deferred, so DOC_HEALTH_SURFACE records it as (0, 1).

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tests/test_seam_assembly_beside_gate_and_projection.py was declared under
doc_health (R1Q6 (d)) by T044 because serve_projection reached doc_health
through snapshot_registry at import. That read is now deferred to where the
sentinel is written, so the file passes alone in a lone checkout, and T041's
test_declared_exclusion would refuse it as declared. Its entry leaves (67 -> 66
files), and its six cases run in this leg's required check (holder's ruling on
T059). T059 joins the exclusion file's single-writer chain between T044 and
T061.

The four seam files' docstrings and validate.yml's paragraphs stop saying the
file is declared, and validate.yml's pin prose names the new openDox pin.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rc check (plan 034 T059, T007 batch C)

F5.2 and 12.5's falsifier each end by refusing any protected suite an arc
landing touched. Batch C (RULED R1Q7 (a), openxFactory#656 comment 5817152735)
has the check subtract the edits entered in tests/protected_suite_respellings.yaml,
and only after validating that the landing's diff for that suite is exactly
the entry's recorded text.

scripts/protected_suites.py is that last step. The falsifier still lists the
landings and the protected suites; the script admits a touched suite only
where one entry holds at the landing (before and after blobs, old occurring
once and giving the after text byte for byte, and both inside the named
test), and exits 2, subtracting nothing, when the allow-list breaks its own
rules. tests/test_protected_suite_check.py holds each rule against scratch
histories. The allow-list's header now says who reads it and states the
named-test condition.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ond admitted edit (plan 034 T059)

At this pin openDox's SNAPSHOT_VALUES defaults are its neutral snapshot's
values (T054), so openXdox's DISPLAY facet's values block (T060) changes six
values.* leaves of the served display beside the four stage words and the
named absence. test_the_overlay_changes_four_words_and_the_named_absence_and_nothing_else
now expects eleven changed leaves, and no other assertion of the suite
changes (RULED R1Q26 (a), openxFactory#656 comment 5851950767, on R1Q11 (a),
comment 5850003126; batch I). The edit is entered in
tests/protected_suite_respellings.yaml with its reason, as an admitted edit,
in this pull request.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…055 moved (plan 034 T059, R1Q7 (a))

openDox-code#59 (T055) routes /source through resolve_source_path over the
resolved entry's own root (r4136863569), where the route used to call
self.source.registry.resolve_source. The test's expected call is respelled
to the route's one entry point, and its second assertion, that the
registry's resolve_source reaches resolve_within exactly once, is unchanged
(holder's ruling on T059). The respelling is entered in
tests/protected_suite_respellings.yaml in this pull request.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d (plan 034 T059)

openDox-code#59 merged main a691e4e4 (T054, openDox-code#57) after this branch
pinned e3ef506a, so the pin follows it to 814516b7, and the comments that name
the pin follow it too. The pin is still a draft's: it re-points to T062's
commit before T059 lands.

Measured at 814516b7: ViewBinding has styles and exports; web/,
view_extension.py and tests/test_binding_stylesheets.py are unchanged from
e3ef506a; tests/test_consumer_reach.py is unchanged, so NEUTRAL_MODULES still
holds thirteen; the census returns the same three rows; and 2d116415..814516b7
is twenty-five first-parent commits. The whole suite reads the same at both
heads (967 passed, 4 skipped, 1 deselected).

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 00:52
@sourcery-ai

sourcery-ai Bot commented Sep 30, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR pins the openDox seam APIs and makes openXdox a governed contributor for generation, projection, validation, registry, and writing, while hardening the underlying snapshot/registry behavior and replacing protected-suite enforcement with a validated allow-list mechanism; extensive tests and evidence updates document the composed checkout and reduced dependency reach.

Sequence diagram for atomic governed snapshot generation

sequenceDiagram
    participant Host
    participant Contributions as projection_contributions
    participant Seam as openDox seams
    participant Generator as generator.generate_snapshot
    participant Writer as snapshot.write_snapshot
    participant Boundary as OutputBoundary
    Host->>Contributions: register()
    Contributions->>Seam: register governed generator, writer and validator
    Host->>Seam: generate snapshot
    Seam->>Generator: generate(repo_root, repository)
    Generator->>Writer: write_snapshot(snapshot, path, boundary)
    Writer->>Boundary: permit_output(path)
    Writer->>Writer: canonical_json(snapshot)
    Writer->>Writer: write temporary sibling and os.replace
    Writer-->>Host: complete snapshot or refusal
Loading

State diagram for governed seam registration

stateDiagram-v2
    [*] --> Unregistered
    Unregistered --> Registered: register()
    Registered --> Registered: register() [same contributions]
    Registered --> Unregistered: unregister()
    Unregistered --> Unregistered: register() [seam refusal]
    Registered --> Unregistered: register() [partial write rolled back]
Loading

File-Level Changes

Change Details Files
Contribute openXdox’s governed projection mechanisms through openDox’s registration seams with transactional, idempotent lifecycle handling.
  • Add generator, registry, corpus-root, writer, and product-validator contributions.
  • Register contributions from domain-profile registration while keeping profile loading side-effect-free.
  • Defer openxFactory-dependent imports until use and roll back partial seam registration on refusal.
src/openxdox/projection_contributions.py
src/openxdox/domain_profile.py
tests/test_projection_contributions.py
tests/conftest.py
Harden snapshot writing, registry concurrency, source confinement, and validation behavior to satisfy the governed seam contracts.
  • Make snapshot serialization reject non-JSON values and writes atomic with permission preservation and cleanup.
  • Lock registry reads and correctly clear the active entry when dropped.
  • Apply hidden-path restrictions after symlink resolution and defer doc_health access in the registry.
  • Route validator lookup and session source resolution through the updated openDox interfaces.
src/openxdox/snapshot.py
src/openxdox/snapshot_registry.py
tests/test_governed_registry_and_writer.py
tests/test_generated_at_anchor.py
tests/test_session_snapshot.py
Replace inline protected-suite enforcement with a validated, test-scoped allow-list checker.
  • Validate allow-list schema, unique keys, blob chains, exact edits, and named-test containment.
  • Return distinct refusal and invalid-allow-list statuses and integrate the checker’s intended falsifier contract.
  • Add coverage for unentered, malformed, out-of-scope, and chained edits.
scripts/protected_suites.py
tests/protected_suite_respellings.yaml
tests/test_protected_suite_check.py
Advance the openDox dependency pin and update composition, exclusion, and provenance evidence for the new seam implementation.
  • Pin openDox-code to commit 814516b7 and revise compatibility documentation.
  • Remove the resolved seam suite from declared exclusions and register the host corpus in test setup.
  • Update dependency-direction, integration, view, and workflow evidence to reflect the new pin and test counts.
pyproject.toml
.github/workflows/validate.yml
tests/declared_exclusion.yaml
tests/test_dependency_direction.py
tests/test_declared_exclusion.py
tests/test_evidence_provenance_surface_seam.py
tests/test_gate_loop_probes.py
tests/test_gate_loop_views.py
tests/test_model_scenario_workbench_seam.py
tests/test_role_authority_projection_seam.py
tests/test_seam_assembly_beside_gate_and_projection.py
tests/integration/test_assembled_bundle.py
src/openxdox/view_extensions.py

Tips and commands

Interacting with Sourcery

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

Customizing Your Experience

Access your dashboard to:

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

Getting Help

… T059)

Entry 2 is batch I's second admitted edit, to the overlay test in
tests/test_gate_loop_views.py (R1Q26 (a)); it chains on entry 1, T060's,
from a56906c to a5ce00c. Entry 3 is the respelling in
tests/test_session_snapshot.py of the route's call into the confinement, as
T055 moved it (R1Q7 (a), r4136863569), from b5e1be0 to f78c445. Both name
#35, this pull request, since the landing's commit is
not known inside it (T019's rule).

scripts/protected_suites.py admits each at its commit on this branch, and
entry 1 at T060's landing.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Protected-suite bypasses, missing allow-list entries, incomplete registry locking, and the gated dependency pin remain unresolved.

Review effort: Balanced
Findings: 3 High severity · 5 Medium severity

Open (8)
What changed in this PR

Routes openXdox’s governed projection components through openDox seams and strengthens snapshot safety, registry synchronization, and protected-suite validation.

Changes:

  • Registers governed generators, registries, writers, validators, and corpus predicates.
  • Adds atomic snapshot writes, confinement checks, and synchronized registry reads.
  • Introduces protected-suite enforcement and extensive seam-focused tests.
File Description
.github/​workflows/​validate.yml Updates validation commentary.
pyproject.toml Advances the openDox dependency pin.
scripts/​protected_suites.py Adds protected-suite allow-list enforcement.
src/​openxdox/​domain_profile.py Registers projection contributions with profiles.
src/​openxdox/​projection_contributions.py Implements governed seam adapters and registration.
src/​openxdox/​snapshot.py Adds strict JSON and atomic writes.
src/​openxdox/​snapshot_registry.py Hardens confinement and registry synchronization.
src/​openxdox/​view_extensions.py Updates dependency-pin provenance.
tests/​conftest.py Registers the optional host corpus adapter.
tests/​declared_exclusion.yaml Removes the now-runnable seam suite.
tests/​integration/​test_assembled_bundle.py Updates bundle provenance.
tests/​protected_suite_respellings.yaml Documents active allow-list enforcement.
tests/​test_declared_exclusion.py Updates exclusion-count history.
tests/​test_dependency_direction.py Updates dependency-direction ratchets.
tests/​test_evidence_provenance_surface_seam.py Updates standalone-import documentation.
tests/​test_gate_loop_probes.py Updates the declared openDox pin.
tests/​test_gate_loop_views.py Extends governed overlay expectations.
tests/​test_generated_at_anchor.py Uses the registered validator seam.
tests/​test_governed_registry_and_writer.py Tests registry and writer hardening.
tests/​test_model_scenario_workbench_seam.py Updates seam extraction documentation.
tests/​test_projection_contributions.py Tests contribution registration and rollback.
tests/​test_protected_suite_check.py Tests protected-suite enforcement.
tests/​test_role_authority_projection_seam.py Updates seam extraction documentation.
tests/​test_seam_assembly_beside_gate_and_projection.py Marks standalone seam assembly runnable.
tests/​test_session_snapshot.py Updates source-confinement assertions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/protected_suites.py Outdated
Comment thread tests/test_gate_loop_views.py
Comment thread tests/test_session_snapshot.py
Comment thread .github/workflows/validate.yml
Comment thread pyproject.toml Outdated
Comment thread scripts/protected_suites.py Outdated
Comment thread src/openxdox/snapshot_registry.py
Comment thread tests/test_protected_suite_check.py
Copilot AI balanced review requested due to automatic review settings September 30, 2026 00:58
…Cloud's analysis of #35 (plan 034 T059)

SonarCloud's quality gate failed #35 on Security Rating C, from one finding:
pythonsecurity:S8707, path injection through a CLI argument, at
protected_suites._lines, which opened whatever file argv named. The check
now opens no file a caller names. --landings and --suites each carry the
list itself, one item per line, and each item is held to its shape before
any of it reaches git: a landing is a full commit id, a suite is
tests/test_<name>.py in ASCII. An item of neither shape is refused with exit
2. The falsifier's call becomes
--landings="$(cat "$W/x-arc.txt")" --suites="$(cat "$W/gen-suites.txt")".
The one file read is still the allow-list, at its fixed path.

The same analysis flagged code smells, which are taken too:
- load_allow_list and check are split into named rule checks, which brings
  each under the cognitive-complexity limit;
- the character classes use \w and \d under re.ASCII;
- composite assertions are split in the three new test files;
- each pytest.raises block holds one call.

tests/test_protected_suite_check.py gains the input-shape cases: a revision,
an option, a path outside tests/, and a non-ASCII name.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The required T062 pin is outstanding, and allow-list validation and workflow test-count pinning have unresolved defects.

Review effort: Balanced
Findings: 3 High severity · 5 Medium severity

Open (8)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Validate edit type before dictionary membership check

scripts/​protected_suites.py:151

A malformed entry such as edit: [] raises TypeError during dictionary membership instead of AllowListInvalid. The command then bypasses its controlled “allow-list invalid” exit-2 path and emits a traceback; validate the field type before membership.

Medium severity Synchronize test with observable reader lock attempt

tests/​test_governed_registry_and_writer.py:236

This delay does not establish that the reader has attempted the read: a slow scheduler can leave the thread before READS[read](registry) for the full 0.2 seconds, making the assertion pass even if the read does not lock. Synchronize on an observable lock-acquisition attempt (for example via an instrumented lock) before asserting that the reader remains blocked.

Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

… of its own (plan 034 T059)

Two mutants of scripts/protected_suites.py survived the suite: skipping the
before-blob check, and skipping the check that the replaced text lies inside
the named test. Each was masked by its twin (the after-blob check, and the
replacement's check). New cases hold each side alone: an entry naming another
blob on either side; an edit whose replaced text is module code and whose
replacement becomes the test's last line; and the reverse, an assertion moved
out of the test.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Registry reads remain partially unlocked, allow-list validation has malformed-input gaps, CI floors are stale, and the required final dependency pin is pending.

Review effort: Balanced
Findings: 3 High severity · 5 Medium severity

Open (8)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Validate edit type before dictionary lookup

scripts/​protected_suites.py:163

A YAML value such as edit: [] raises an uncaught TypeError at this membership test because lists are unhashable. That bypasses AllowListInvalid and the documented exit-2 validation path; validate that edit is a string before the dictionary lookup.

…names, the schema integer, unsigned fixtures (plan 034 T059)

- r4139816732: SnapshotRegistry.index_document read the entries, the
  aggregates and the active key in three windows, so a writer between them
  could leave the index naming an active key its entries did not carry;
  compose_aggregate read _aggregates unlocked and looked each member up in a
  window of its own. Each is now one hold of the lock, with the document
  composed and the snapshots read after it. Two cases hold it, each running
  a writer on another thread between the reads; both are red before this
  commit.
- r4139816490: the arc check's git diff detected renames, so a protected
  suite renamed to an unprotected path showed only the destination and was
  never checked. It now diffs with --no-renames, and a case holds it.
- r4139816690: schema_version 1.0 passed, since 1.0 == 1. The check is now
  for the integer itself, and the rules' table gains the case.
- r4139816759: the scratch-repository fixture inherited the developer's git
  configuration, so commit.gpgsign=true failed every case. It passes
  -c commit.gpgsign=false, as tests/test_trust_gaps.py does. Under a signing
  configuration the file read 16 passed, 19 errors before, and 37 passed after.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:26
…on (plan 034 T059)

Run 36655105352 measured c34c0dea, the head before this change, at
openDox-code 814516b7: selected 984, passed 980, skipped 4, failures 0,
errors 0. The +99 on both floors is T060's 11 (openXdox-code#34 named the
raise as the next writer's) and T059's 88: three new test files of 37, 26
and 20 cases, and the six seam-assembly cases that run here now that their
file left the declaration, less the declaration check's case for that file.
EXPECT_SKIPPED stays 4, the same four skips. The floors sit on the reading,
margin zero, as #25 set them (Copilot, r4139816631).

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

A reviewed allow-list entry can be reused to admit a later unreviewed protected-suite landing.

Review effort: Balanced
Findings: 2 High severity · 1 Medium severity

Open (3)
Resolved since last review (5)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Allow-list entries can be reused across multiple landings

scripts/​protected_suites.py:295

An allow-list entry can currently admit more than one arc landing because a successful match is never consumed or bound to the current landing. For example, after reviewed entries change X→Y and later Y→X, a third unreviewed X→Y landing reuses the first entry's blobs/text and is reported as admitted. That bypasses the per-landing review guarantee; track which entry admitted a landing and refuse any second use (or bind entries to an immutable landing commit), with a replay regression test.

Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:32
…(plan 034 T059)

Copilot at 0fdd65c (r4146580826): index_entry imported pin_sentinels on
every call, so an index of entries that carry their own source_revision
failed where doc_health is absent, although the sentinel was never needed.
The import now happens only for an entry with no revision. A blocked-module
subprocess case holds both halves: a versioned entry is indexed without
doc_health, and a revisionless one still fails on doc_health (red before
this commit). DOC_HEALTH_SURFACE still reads one deferred import here.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 15:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The declared T062 gate has not landed, so the final dependency pin and associated provenance updates remain outstanding.

Review effort: Balanced
Findings: None

Resolved since last review (1)

Run 36740358207 measured a1b75f3, the head before this change, at
openDox-code 814516b7: selected 993, passed 989, skipped 4, failures 0,
errors 0. The versioned-entry case a1b75f3 added takes the raise to +108:
T060's 11 and T059's 97. Margin zero again.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 16:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The draft remains explicitly gated on T055/T062 landing and replacing the provisional openDox pin with the final commit.

Review effort: Balanced
Findings: None

brettheap added a commit that referenced this pull request Sep 30, 2026
Run 36759713758 measured 708cdd28, the head before this change, at
openDox-code 814516b7: selected 1076, passed 1072, skipped 4, failures 0,
errors 0. The +83 on both floors, file by file against #35's head 4feb800:
+47 tests/test_packaged_validator.py (new); +18 tests/test_snapshot.py,
leaving the declaration; +11 tests/test_protected_suite_check.py; +5
tests/test_validator_schema_home.py; +2 tests/test_dependency_direction.py;
+1 tests/test_projection_contributions.py; -1 tests/test_declared_exclusion.py
(test_snapshot.py's case). The skips are the same four. The margin is zero
again.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t (plan 034 T059)

T062 (opensoft/openDox#16) landed as d5098297. It pins openDox-code
047bb4fa394f3e1bf42466062a67ef18e99f8d6a, the head of openDox-code main
after T058 (#68). So this leg's `opendox @` pin moves from 814516b7 (the
head of openDox-code#59) to that commit. The pin crosses, first-parent: T057
(#58, 8ec08e9), T055 (#59, fa14087) and its follow-up (#70, 75bd870), T056
(#66, a23e422) and T058 (#68, 047bb4f). The repository has no lock or
constraints file, so pyproject.toml is the one place the pin lives.

One seam moved. T058 replaced default_projection.VALIDATOR, one stand-in for
all of openDox's own kinds, with VALIDATORS, one validator per own kind. So
tests/test_projection_contributions.py reads VALIDATORS[kind] in its two
cases. That file is T059's own and not a protected suite.

The pin comments were re-measured at 047bb4fa, and each measurement holds:
* ViewBinding still takes exports and styles (dataclasses.fields);
* _back_import_census() returns the same three rows as the ratchet table;
* openDox's NEUTRAL_MODULES is still thirteen, with STILL_REACHING empty;
* the vendored stylesheet helpers and GATE_EXCLUSIVE are byte-unchanged in
  tests/test_binding_stylesheets.py.

The whole suite, alone at the new pin, gives 989 passed, 4 skipped and 1
deselected (CI's command), the triple unchanged.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 21:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Failed contribution registration removes previously installed openDox defaults instead of restoring the prior seam state.

Review effort: Balanced
Findings: 1 High severity

Open (1)

Comment thread src/openxdox/projection_contributions.py Outdated
…lan 034 T059)

Copilot on #35 at 25414af (r4149710491). When openDox's entry points had
installed their unread defaults, register() replaced them seam by seam. If
a later seam then refused, the rollback emptied the earlier seams, so a
caller that caught the refusal lost its neutral generator, registry and
corpus root, despite the all-or-none contract.

Before each write, register() now records the unread default the seam
holds. It reads the default where the seam keeps it, as _holds does, because
current() would close the default's window. A refusal then empties what the
call wrote and gives the displaced default back with the seam's own
register_default, so each seam holds what it held before, and a default
stays an unread default. The case that pinned the old emptying,
test_a_replaced_unread_default_is_given_back_as_a_default, asserts the
restoration now, with the seams' private names pinned. It also shows the
default is still replaceable: once the writer's reader lets go, register()
lands.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 21:58
@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The PR description still presents the obsolete provisional pin and unresolved gate despite the final dependency pin now being present.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity PR description conflicts with final pin and validation status

pyproject.toml:106

The implementation now pins 047bb4fa, but the PR description still says this branch builds against provisional 814516b7 and is waiting for T055/T062. That makes the stated merge gate and the evidence section disagree with the code being reviewed. Please update the description to state whether T062 is now satisfied and identify the validation measured at this final pin.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Cross-repository seam coupling, transactional rollback, and concurrency-sensitive registry changes warrant final human review despite comprehensive passing tests.

Review effort: Balanced
Findings: None

@brettheap
brettheap marked this pull request as ready for review September 30, 2026 22:09
@brettheap

Copy link
Copy Markdown
Contributor Author

READY at aa0a2c5 — T062 landed (openDox#16 → d5098297; code pin 047bb4fa). Lane: openxfactory-4 (openXfactory-4-openDox_extraction)

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @brettheap, your pull request is larger than the review limit of 150,000 diff characters

@brettheap
brettheap merged commit 839492d into main Sep 30, 2026
5 checks passed
@brettheap

Copy link
Copy Markdown
Contributor Author

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)

LANDED — lane openxfactory-4, 2026-09-30T22:10:04Z, PR #35 → 839492d (opensoft/openXdox-code main; plain gate)

Brett: land the phase 1 PRs when green

brettheap added a commit that referenced this pull request Sep 30, 2026
#35 (T059) landed on main as 839492d, a squash of its head aa0a2c5, and
the two trees are identical. This branch was built on #35's earlier head,
4feb800, so a plain merge of main met T059's files twice: once as this
branch's history of them and once as the squash. That gave add/add and
content conflicts in twelve files.

The merged tree is the three-way merge of this branch and aa0a2c5, with
4feb800, their real common state, as the base
(`git merge-tree --merge-base=4feb8009`). It merges with no conflict:
* this branch's side of every T059 file it had already changed;
* main's side of everything #35 added after 4feb800: the openDox-code
  047bb4fa re-pin (25414af) with its re-measured comments and the
  VALIDATORS respelling, and the give-back of displaced defaults
  (aa0a2c5).
The commit's parents are this branch and main, so the history records the
merge.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Sep 30, 2026
With #35 landed (839492d) and merged in (8d89165), the openDox-code pin is
047bb4fa, T062's commit. Run 36784210624 read 1076 selected, 1072 passed and 4
skipped, the triple the floors already name, so they stand. The floor
paragraph says so, and nothing moves.

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Sep 30, 2026
…tion (7.3) (plan 034) (#36)

Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability

Plan 034 **T061** (P2-C), in openxFactory `specs/034-opendox-standalone-operation/`: **#1144 7.3, the consumer's half.**

> "openXdox's validator and its three schemas (7.1's openXdox-spec three) are located through the INSTALLED openXdox distribution, and no parent walk remains." (RULED R1Q14 (a))

As T007's batch I amends it (R1Q27 (a), opensoft/openxFactory#656 comment 5851950767), the validator validates:
- its own three kinds from its installed distribution, wherever it runs;
- the family's other seven kinds only where the running tree supplies them, reading that tree's own `contracts/` first.

**Based on `main`. Every gate this PR named has landed:**
- **#35 (T059)** landed as `839492d9`, a squash of its head `aa0a2c5d`. The holder retargeted this PR to `main` first. `main` is merged in at `8d891652` (see "The merge from main" below).
- **T007's batch K** landed as openxFactory#1210 → `39f19145`. It records the ten reworded cases, and F5.2's `--chains` step, in #1144.
- **T062** landed as openDox#16 → `d5098297`. It pins openDox-code `047bb4fa`, and #35 carried this leg's pin to that commit, so this branch has it through the merge.

This PR stays DRAFT until the holder marks it READY.

**The merge from main.** A plain merge met T059's files twice: once as this branch's own history of them (it was stacked on `4feb8009`) and once as #35's squash. That gave add/add and content conflicts in twelve files. The merged tree is therefore the three-way merge of this branch and `aa0a2c5d`, with `4feb8009` as the base (`git merge-tree --merge-base=4feb8009`), and it merges cleanly:
- this branch's side of every T059 file it had already changed;
- `main`'s side of all that #35 added after `4feb8009`: the `047bb4fa` re-pin with its re-measured comments, the `VALIDATORS` respelling, and the give-back of displaced defaults.

The merge commit's parents are this branch and `main`.

## What changes

**1. The validator and its own three schemas ship as package data** (`openxdox.contracts`, new).
- `schemas/`: the three schemas, byte copies of opensoft/openXdox-spec at `f088b097`. That is the commit the openXdox root pins, through its `spec` gitlink and `contracts/spec-pin.yaml` at `main` 57e2b8f2.
- `copies.yaml`: records each copy's sha256. These are the digests the root's `contracts/manifest.yaml` records.
- `validate-ideation-dashboard-contracts.py`: byte for byte the same as `scripts/validate-ideation-dashboard-contracts.py`. A test holds the two equal.
- A copy is read only after its digest is checked against the record. The pattern mirrors openDox's T057 (openDox-code#58).
- The `pyproject.toml` package-data line ships the record, the three copies and the validator, and nothing else. I measured this by building a wheel with and without the line. Without it, the wheel carries only the package's two `.py` files, and neither the record nor any copy.

**2. The validator finds each schema in one of three places, in this order.**
- First, the running tree's own `contracts/schemas/`, as before. openxFactory's farm composes the whole family that way. The packaged validator also finds its copies this way, since they sit beside it.
- Second, for the three only: the installed distribution, found through `importlib.util.find_spec("openxdox.contracts")`, never by position.
- Third, for the other seven only: `CONTRACTS_DIR`. It never supplies the three.

A copy that differs from its record is refused by name with a harness error (exit 2) and is never read.

**2a. A packaged copy is held to its record, fail closed.**
- The packaged layout is recognized by where the script sits, inside the `contracts/` it reads, never by whether `copies.yaml` is present. A missing record or copy there is refused with exit 2.
- The script checks the whole record against the same contract as `openxdox.contracts.record()` before it takes any digest.
- An installed validator that links out of its package is never run, in both `snapshot._packaged_validator` and `contracts.validator_path`. That follows Copilot's review.

**3. `find_validator` ignores `start`.**
- It keeps its declared signature, because openDox's `consumer_reach` binds it by name.
- From this product's source tree, it answers the tree's `scripts/` validator. That is the path openxFactory's lanes read.
- From an install, it answers the packaged copy.
- An enclosing tree's validator is never adopted.
- A start outside the tree is validated. Before, it was confined to None. This supersedes split-opendox 8.9 residue (iii) (#28) for the start.
- `GovernedValidator.locate` asks once, with no start.

**4. The runtime dependencies gain `referencing>=0.28.4` and `rfc3339-validator>=0.1.4`.** Brett ruled "Keep as runtime deps" at opensoft/openxFactory#656 comment 5916000030.
- The package now ships a validator that imports `referencing` at module level.
- The validator refuses to run without `rfc3339-validator`, because jsonschema registers its `date-time` checker only when that package is importable.
- Without both, a plain install would carry a validator it cannot run.
- **Proof, from F7.1's own fresh environment:** with `rfc3339-validator` left undeclared, F7.1 goes red. `test_the_validator_is_the_installed_consumers_own` reads `validator-unavailable`: "ERROR jsonschema is missing its date/date-time format checkers; install rfc3339-validator".
- `referencing>=0.28.4` is the floor that `jsonschema>=4.18` itself requires (checked on PyPI), so declaring it adds nothing to an install.
- `rfc3339-validator` leaves the `test` extra.
- `tests/test_dependency_direction.py` now names each `.py` under `src/` that is not a module, and holds its imports to the declared dependencies.

**5. The allow-list check (batch C's, which T059 wired) learns two things.**
- **An added test** (batch F's rule). Where the named test is absent before the landing, `new` must be `old`, then that test's whole definition and blank lines, and nothing else.
- **A chain of entries**, for F5.2's call alone. This follows the holder's decision under Brett's ruling at comment 5916000030, which batch K records.
  - One landing that edits one suite in several tests enters each edit as its own entry. The entries apply in list order, each to the text the one before it leaves.
  - The first entry's `before_blob` is the suite before the landing, and the last entry's `after_blob` is the suite at it. Each entry in between records the git blob id of the text it leaves.
  - Each entry holds on its own texts, inside its own test, and all of them name one landing.
  - The flag is `--chains`. F5.2's call passes it; 12.5's call does not, and keeps one entry per suite per landing.
  - Neither of the two suites is among 12.5's sixteen governed files. I checked with `git grep -l -e open-pr -e open_pr -e FakePullRequests -- 'tests/test_*.py'` at `main` and at this head: the same 16 files both times.
  - A new case shows 12.5's call refusing a chain that F5.2's call admits.

## The protected edits, each in its own commit, each an allow-list entry

| commit | suite :: test | admitted by |
|---|---|---|
| `3dc4a4c` | `tests/test_snapshot.py::test_the_validator_is_the_installed_consumers_own` (**added**) | batch F (R1Q14 (a)) |
| `08b03b9` | `tests/test_snapshot_validator_home.py::test_a_start_outside_the_product_is_refused_not_walked` (its answer is now 7.3's) | batch F |
| `5c2ef23` | the nine tests of `tests/test_snapshot_validation_launch.py` | batch K (Brett, comment 5916000030) |
| `8a89bc7` | `tests/test_snapshot.py::test_a_missing_validator_is_unavailable_not_a_verdict` | batch K |

In the ten batch K cases the real assertions stay. Those are: SKIPPED on stderr naming both roots, the pip remedy, `--strict` fatal, a non-conformant snapshot blocked and blamed, and UNAVAILABLE rather than a verdict. Only the walk premise changes.
- Each stub is now planted as the distribution's own validator: `product_root` is None and `_packaged_validator` is the stub, both set with `monkeypatch`, and the real `find_validator` answers it.
- "No validator" is now a distribution that carries none of its own.
- **One expected answer inverts**, as C3's did under batch F: `test_a_run_dir_beside_a_checkout_still_uses_that_one_first`. The validator beside the run dir is never adopted. Its name is kept, because an entry admits an edit inside one named test.
- The launch suite's helper `_corpus_with_a_reachable_validator` sits outside every test, so no entry can admit an edit to it. It is unchanged, and its docstring's "where `find_validator` expects it" is now stale. That is recorded here rather than edited.

The allow-list entries themselves are in the commit after the PR number was known. There are twelve:
- batch F's two;
- batch K's ten, as a chain of two for `tests/test_snapshot.py` and a chain of nine for the launch suite.

## The declared exclusion: 66 → 65

`tests/test_snapshot.py` leaves, and its reason, `consumer-schemas` (R1Q25 (b), "until 7.3 finds them through the installed distribution"), leaves with it. The suite now passes alone, 18 of 18.
- `tests/test_snapshot_validation_launch.py` keeps its `doc_health` entry. Alone, all nine of its tests fail for `doc_health` only. Composed, the suite goes from 5 failed and 4 passed to 9 passed.
- The root conftest's table of admitted reasons keeps R1Q25 (b)'s row. A reason leaves the declaration, not the record of what the rulings admitted.

**Single-writer order of `tests/declared_exclusion.yaml`: T044 → T059 → T061.**
- T044 wrote the doc_health skips into a declared file.
- T059 removed `seam_assembly` (67 → 66).
- T061 removes `tests/test_snapshot.py` (66 → 65).

No other open PR touches the file.

## For T008: excluded files that validate a kind the narrowed validator gives up

In a lone checkout, with no `contracts/` of its own and no `CONTRACTS_DIR`, the validator now validates only its three kinds. These files validate one of the other seven kinds. I measured the first two with a temporary trace of the validator's calls, whole suite and composed; the trace has been reverted. I read the rest from content.

| file | declared reason | kind(s) given up |
|---|---|---|
| `tests/test_notebook_action.py` | doc_health | `ideation-workbench` |
| `tests/test_register_edit_lane.py` | doc_health | `project-register` |
| `tests/test_validate_ideation_dashboard_contracts.py` | openxfactory-contracts | `workbench-model-catalog`, `workbench-chat-turn-v2` |
| `tests/test_project_action_contracts.py` | openxfactory-contracts | `gate-intent` |
| `tests/test_wheel_action_contracts.py` | openxfactory-contracts | `gate-intent` |
| `tests/test_project_schema_election.py` | openxfactory-contracts | `project-register` |
| `tests/test_doxbench_blank_reason.py` | doc_health, openxfactory-contracts | `workbench-chat-turn-v2` |

Also:
- `tests/test_aggregation_register_instance.py` is not excluded. It validates `project-register` and **skips** alone; those are the four `EXPECT_SKIPPED` cases.
- The other declared validator users validate only the three kinds, so the narrowing gives up nothing there: `test_generator`, `test_generated_at_anchor`, `test_snapshot_determinism`, `test_snapshot_registry`, `test_doxbench_share`, `test_kickoff` and `test_session_records`.

## Falsifiers, before and after

**F7.1, exactly as #1144 writes it:**
- The block ran verbatim: a fresh venv, `pip install ".[test]"`, the planted pre-shed tree, and both named tests.
- The host has no `python`, so a shim maps it to `/usr/bin/python3` 3.12.3 for the block's first line. After activation, `python` is the venv's.
- **Before, at #35's head `4feb8009`:** rc 1, `AssertionError: the consumer found no validator of its own`. The two named tests do not exist yet (pytest rc 4).
- **After:** rc 0, `2 passed`. The install is non-editable (`direct_url` `dir_info {}`). `find_validator()` answers `site-packages/openxdox/contracts/validate-ideation-dashboard-contracts.py`, and `product_root()` is None.

**F5.2 whole, exactly as #1144 writes it with no deselect, in batch G's environment,** at the merged tree (`e3985b91`). The simulated history is `main` with #35's real landing `839492d9`, then this PR squash-landed. The results equal those at the earlier tree (`34dc603`, openDox-code `814516b7`).
- The environment: a fresh venv, then `pip install ".[test]"`, then openDox-code `047bb4fa` force-reinstalled, with openxFactory `91e4685f` `scripts/` on `PYTHONPATH`.
- Suites: `test_generator` 45/45, `test_snapshot` 18/18, `test_snapshot_determinism` 6/6, `test_snapshot_registry` 40/40, `test_snapshot_validation_launch` 9/9 and `test_snapshot_validator_home` 12/12.
- `test_session_snapshot` is 20 passed, 3 failed. The 3 are exactly the holder's ruled pre-arc reds ("red at both pins; pre-arc carve residue; not the arc's"), left open for F5.2 whole at T063: `test_a_new_serve_process_re_registers_the_session_at_startup`, `test_a_session_key_is_validated_against_the_roster_before_url_composition` and `test_the_hosted_session_arrival_path_is_recorded_and_not_built`.
- Every deselect T059's F5.2 run needed besides those 3 is now gone. Those were test_snapshot's 2 and the 7 reds that failed at both pins in test_generator, test_snapshot_determinism and test_snapshot_registry.
- **The arc check:** F5.2's step (`--chains`) runs over the arc's landings. It admits all four protected suites: `839492d9` (#35's real landing) for test_session_snapshot by entry 3, and this PR's simulated landing for test_snapshot by the chain 4, 5, for test_snapshot_validator_home by entry 6, and for the launch suite by the chain 7-15. It exits 0. The entries needed no re-recording, because #35 does not touch these three suites.
- 12.5's call, without `--chains`, exits 0 over its governed set.
- F5.2's call without `--chains` refuses both chains (exit 1).

**Whole suite alone (CI's command):**
- `validate` run 36759713758 at `708cdd27` read selected 1076, passed 1072, skipped 4, failures 0, errors 0. The floors were set to 1076 and 1072, on that reading (`71187f7`).
- At the merged head `8d891652`, with openDox-code `047bb4fa`, run 36784210624 reads the same triple. So the floors stand, and the floor paragraph records it (`5c2b134`).
- The declared exclusion is 65 files.

**Composition,** 38 suites (the protected 23, the 12.5 set, and every validator user), each run alone with openxFactory `scripts/` on `PYTHONPATH`, #35's head against this one: **0 newly red, 24 newly green.** It was measured at openDox-code `814516b7`, and measured again at `047bb4fa` as `main` (`839492d9`'s tree) against the merged head, with the same result. The newly green cases include test_generator's 4, test_snapshot_determinism's 1 and test_snapshot_registry's 2 (the reds at both pins), test_snapshot's 2 schema cases, the launch suite's 4, and the validator users in test_doxbench_share, test_kickoff, test_session_records and test_generated_at_anchor.

**Mutants of the new checks: 29 of 29 killed** at `29f058e`, and again at the merged head `8d891652`. They cover:
- the lookup: C3's confinement back, the pre-shed walk back, no packaged validator, a packaged validator linking out, and `locate` reading the roots;
- the validator: digest not compared, `CONTRACTS_DIR` supplying the three, no distribution lookup, the packaged layout told by its record, and the record's spec leg, row path and fourth kind;
- `openxdox.contracts`: five record and digest checks, and `validator_path` following a link;
- the package-data line, and `referencing` undeclared;
- a hyphenated module hiding from the census;
- the added-test rule (three mutants) and the chain (five mutants).

The mutant that drops `rfc3339-validator` from the dependencies survives the unit suite. F7.1 kills it, as shown above.

**The review rounds:**
- **SonarCloud's gate** failed at `8015a565` on 63.1% duplication and a C security rating, both from the packaged validator copy. `.sonarcloud.properties` now excludes that copy, so the validator is analysed once, at `scripts/`, and this PR's own smells are taken. The gate has been green since `bbe17165`.
- **Copilot**, at five heads. What was taken:
  - the entries were entered;
  - the packaged layout now fails closed when its record or a copy is missing;
  - an installed validator that links out of the package is refused, in `find_validator` and in `validator_path`;
  - the script holds `copies.yaml` to the package's full contract, with every one of the package's 15 record refusals run through the installed validator;
  - two stale docstrings, in the launch suite and `build_registry`, and one diagnostic were corrected.
  - All threads are resolved.

## Owed elsewhere

**T064's `created:` admissions** (openxFactory's carve manifest records what leaves openxFactory; these files were created here, RULED OQ-C):
- `src/openxdox/contracts/__init__.py`, `copies.yaml`, `schemas/*.schema.yaml` (3) and `validate-ideation-dashboard-contracts.py`;
- `tests/test_packaged_validator.py`;
- together with T059's (`src/openxdox/projection_contributions.py`, `scripts/protected_suites.py`, `tests/test_projection_contributions.py`, `tests/test_protected_suite_check.py`, `tests/test_governed_registry_and_writer.py`) and the allow-list, `tests/protected_suite_respellings.yaml`.

**Not changed:** `tests/conftest.py::find_openxfactory_validator` keeps its fallback walk. It is a test helper, not 7.3's lookup, and here it always returns the tree's own `scripts/` validator first, so the walk is never reached.

🤖 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants