You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 main91e4685f), 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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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.
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:
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:
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.
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 mainc41063d6 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.
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:
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.
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.
…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>
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
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!
… 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>
…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>
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.
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.
… 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>
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.
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>
…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>
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.
…(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>
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>
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>
…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>
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.
#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>
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>
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Arc: neutral-product-standalone-operability
DRAFT. T062 has landed, and this PR is pinned to its commit.
d5098297. It pins openDox-code047bb4fa(047bb4fa394f3e1bf42466062a67ef18e99f8d6a), the head of openDox-codemainafter T058.pyproject.toml'sopendox @pin now names that commit, at25414afc. Before that it named814516b7, openDox-code#59's head while that PR was a draft.047bb4fa. They are insrc/openxdox/view_extensions.py,tests/test_dependency_direction.py,tests/test_gate_loop_probes.py,tests/integration/test_assembled_bundle.pyandvalidate.yml.fa140875). Between the two pins sit T057 (#58,8ec08e91), T055's follow-up (#70,75bd8703), T056 (#66,a23e4224) and T058 (#68,047bb4fa).mainbefore this PR goes READY. A--delete-branchlanding would close it.What this is
This PR carries plan 034's T059 (
specs/034-opendox-standalone-operation/tasks.md, read at openxFactorymain91e4685f), 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).5817152735; R1Q10 (a), R1Q23 (a),5850003126; R1Q26 (a),5851950767.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.pyandcorpus_root.py. The newopenxdox.projection_contributionsregisters what they provide at openDox's seams:opendox.generator_seamGENERATOR, aSnapshotGeneratorovergenerator.generate_snapshot, declaring its two inputs (project_register_source,possibles_source)projection_seams.registrysnapshot_registrymoduleprojection_seams.corpus_rootCORPUS_ROOT:corpus_scan_defect,corpus_root_refusal,change_rowsandSCANNED_ROOTSprojection_seams.writersnapshotmodule (write_snapshot)projection_seams.validatorsVALIDATOR, for the three governed kinds (ideation-dashboard-snapshot,-index,gate-action-record). openDox's own kinds keep openDox's validator.generator,corpus_rootandcompletenessimport openxFactory'sdoc_healthat 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 needsdoc_health, and a subprocess case holds that withdoc_healthblocked.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()andunregister()complete the API.The holder's rulings on this PR
Each of these is the holder's reading, given on this PR's questions.
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 fromload()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).scripts/opendox_host.register_openxfactory()never callsopenxdox.domain_profile.register(): it callsopenxdox.domain_profile.load(PROFILE_PATH)and registers the composite with openDox alone (opendox.domain_profile.register(composite)).openxdox.projection_contributions.register()inregister_openxfactory(). T064's line "It composes openXdox's profile, so none is expected" no longer holds.scripts/opendox_host.pyis on F11.1's host surface, so its guard admits the change.The home corpus in the test harness: (c). openDox's
authoring.create_scaffoldasks 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:That rules out (a), a fallback inside the seam, and (b) would amend a ruled falsifier environment. So
tests/conftest.pyregisters the same factory openxFactory's host registers,corpus_adapter_openxfactory.home_corpus, found where F5.2's environment composes openxFactory'sscripts/onPYTHONPATH. Where it is absent, it registers nothing, and a lone checkout refuses as 4.1a says.tests/conftest.pyis 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.doc_health, so each is already declared. The lone whole suite is green with nothing registered.e3ef506athere were 69. At814516b7there are 71, the same 69 plus the 2 T054's final head routes through the home corpus. All 71 pass here.The respelling: accepted as an R1Q7 (a) entry citing T055's
r4136863569. The expected call intests/test_session_snapshot.py::test_the_session_source_read_is_the_existing_confinement_mechanismis respelled fromself.source.registry.resolve_source(toresolve_source_path(Path(root), rest), the route's one entry point, which applies the registered registry'sresolve_within. The second assertion is unchanged.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.py4,test_snapshot_determinism.py1 andtest_snapshot_registry.py2. They are deselected in T059's F5.2 run with R1Q25 (b)'s reason. A supplementary run with a composedCONTRACTS_DIRshows all seven green (below).test_snapshot_validation_launch.py's 5 reds are C3's, so they are T061's.The exclusion entry: accepted. T059 removes
tests/test_seam_assembly_beside_gate_and_projection.pyfromtests/declared_exclusion.yaml, taking it from 67 to 66 files. The file was declared underdoc_healthonly becauseserve_projectionreacheddoc_healththroughsnapshot_registryat import.snapshot_registry's one read ofdoc_health(pin_sentinels) now happens where the sentinel is written, so the file passes alone in a lone checkout, and T041'stest_declared_exclusionwould refuse it as declared. T059 joins the exclusion file's single-writer chain between T044 and T061: T044 → T059 → T061.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.servehas noSNAPSHOT_INDEX_ROUTE. The constant moved toopenxdox.serve_projectionin split-opendox § 2.4 PR-3 (#761).test_a_session_key_is_validated_against_the_roster_before_url_composition: the node probe copies onlyrepo-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_actionis not on openXdox's serve surface. It moved to openxFactory'sserve_openxfactory_lanes.pyin § 2.4 PR 3.What changes
src/openxdox/projection_contributions.pysrc/openxdox/domain_profile.pyregister()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.pypin_sentinelsonly where it writes the sentinel, for an entry with no revision. Seals gaps 1, 2 and 4 below.index_documentandcompose_aggregateeach take one reading.src/openxdox/snapshot.pySnapshotNotWritableis aProjectionSeamErrorand aValueError.scripts/protected_suites.pytests/test_projection_contributions.pytests/test_governed_registry_and_writer.pytests/test_protected_suite_check.pytests/test_gate_loop_views.pytests/test_session_snapshot.pytests/protected_suite_respellings.yamltests/conftest.pytests/test_generated_at_anchor.pysnapshot._locate_validator, which openDox's generate verb no longer reaches. It now patches the registered validator'slocate().tests/test_dependency_direction.pycliandserveleaveOPENDOX_BACK_IMPORTS, andbranch_sessiongoes from (0, 7) to (0, 2).DOC_HEALTH_SURFACErecordssnapshot_registryas (0, 1).tests/declared_exclusion.yaml,tests/test_declared_exclusion.py, the four seam filespyproject.toml2d116415→047bb4fa, T062's commit. In the drafts it named814516b7, #59's head..github/workflows/validate.ymlsrc/openxdox/view_extensions.py,tests/test_gate_loop_probes.py,tests/integration/test_assembled_bundle.py814516b7and again at047bb4fa, where each claim still holds.ViewBindingstill hasstylesandexports.web/,view_extension.pyand the copied stylesheet helpers are unchanged from2d116415.tests/test_projection_contributions.py(at047bb4fa)default_projection.VALIDATOR, one stand-in for all of openDox's own kinds, becameVALIDATORS, one validator per own kind. The two cases that name it readVALIDATORS[kind]. This file is this PR's own, not a protected suite.src/openxdox/projection_contributions.py(ataa0a2c5d)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: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.
resolve_within's symlink escape (r4125556296). The hidden-name rule was applied only to the path as the URL spelled it, solink -> .gitserved/source/link/config, andnotes.md -> .envserved.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).dropleft a dangling active key. Dropping the active entry now clears the key. Left set, it also kept every later entry from becoming active.os.replace. A failed move leaves the old snapshot and no sibling.canonical_jsonwroteNaNandInfinity(r4125900060). A value JSON cannot carry is now refused, with nothing written.SnapshotRegistryread 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:tests/test_gate_loop_views.py::test_the_overlay_changes_four_words_and_the_named_absence_and_nothing_elsevaluesblock's six leaves beside the five it pinneda56906c6→a5ce00cc, chained on entry 1tests/test_session_snapshot.py::test_the_session_source_read_is_the_existing_confinement_mechanismb5e1be02→f78c4452Each is its own commit on this branch (
81a01cd,614f79f), so each entry also holds at its commit.scripts/protected_suites.pyis 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:oldoccurs once, and replacing it withnewgives the after text byte for byte;oldstarts a line, as it ends one;argv, S8707.Evidence
Every run here used
LANG=C.UTF-8, in the foreground.AT THE FINAL PIN,
047bb4fa, headaa0a2c5d.36782773982readstriple: selected=993 passed=989 skipped=4 failures=0 errors=0, which is the same triple as at814516b7. So the floors, 993 and 989, already sit on CI's reading at margin 0, and do not move.main, withOPENDOX_CODEat047bb4fa,OPENXFACTORYat91e4685fandARC_BASEate28930bf, with the same deselects as below:test_generator41 passed, 4 deselected;test_session_snapshot20 passed, 3 deselected;test_snapshot15 passed, 2 deselected;test_snapshot_determinism5 passed, 1 deselected;test_snapshot_registry38 passed, 2 deselected;test_snapshot_validation_launch5 failed, 4 passed. These are T061's, as below.test_snapshot_validator_home12 passed.tests/test_session_snapshot.pyby entry 3, then printsok: 1 protected edit(s).tests/test_gate_loop_views.pyby entries 1 and 2, and exits 0.CONTRACTS_DIRcomposed, and no both-pins deselect:test_generator45/45,test_snapshot_determinism6/6 andtest_snapshot_registry40/40. So the seven reds at both pins are still only the consumer's schemas.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
4feb8009with openDox-code at814516b7, the drafts' pin, and are kept as they were.The required check (9.2), CI's reading. Run
36741174322at4feb8009:mainc41063d6reads 896/892/4. Compared test by test:test_protected_suite_check43,test_governed_registry_and_writer27,test_projection_contributions22, andtest_seam_assembly_beside_gate_and_projection6;test_declared_exclusion's case for the seam-assembly file;The floors are raised to 993 and 989 (T060's 11 and T059's 97), with
EXPECT_SKIPPED4, 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", withPYTHONPATH="$OPENXFACTORY/scripts".OPENDOX_CODEis openDox-code814516b7,OPENXFACTORYis openxFactory91e4685f, andARC_BASEise28930bf. The deselects are the task's twotest_snapshot.pyschema cases plus rulings 4 and 6.At this head (
4feb8009):The same block, before:
mainc41063d6withOPENDOX_CODEat814516b7(the realized openDox, pins only):test_session_snapshot.py20 failed (SeamNotRegistered, adapter-not-registered),test_snapshot_validation_launch.py9 failed;mainwith openDox2d116415(the old pin):test_session_snapshot.py3 failed (ruling 6's three),test_snapshot_validation_launch.py6 failed.The five
validation_launchreds left here are:test_the_default_shaped_launch_validates_from_the_repo_roottest_a_run_dir_beside_a_checkout_still_uses_that_one_firsttest_the_dependency_warning_carries_the_pip_remedy_and_clears_the_corpustest_a_non_conformant_snapshot_still_blocks_and_blames_the_snapshottest_the_classifier_reads_the_exit_code_not_the_dependency_sentenceSupplementary, with a composed
CONTRACTS_DIR(ruling 4). The directory holds openXdox-specf088b09's three schemas, openDox-specf7ee3c7's three and openxFactory91e4685f's four. The run does not deselect ruling 4's seven: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
81a01cdby entry 2 andc41063d6(#34) by entry 1. A squash landing of this branch onmainwas simulated withgit commit-tree HEAD^{tree} -p origin/main, carrying theArc:line. It is admitted by entry 3 (the F5.2 set) and by entry 2 (the 12.5 set). Withmain'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 is7321b04d, and the suite before the landing isa56906c6;tests/test_session_snapshot.py: "no entry names this suite".The 23 protected suites in composition (openxFactory
scripts/onPYTHONPATH, each suite alone), compared test by test withmainat the old pin:mainat the old pin was greenmainwith openDox814516b7(pins only)SeamNotRegistered)conftest.pyMutants, at this head. Each ran against its suites, and the file was restored and checked clean after each. All 21 were killed:
_holdsalways true / reads nothingdomain_profile.registerwithout the contributionsresolve_withinwithout the canonical checkdropkeeps the active keygetwithout the lockallow_nan=Truepin_sentinelsback at module levelvaluesblock loses one governed wordresolve_source_pathMore checks were each shown red before the commit that added them and green after:
schema_version: 1.0;edit: []and a sequence key;oldtext that is the tail of a line;doc_health, where a revisionless one still fails on it.Under a global
commit.gpgsign=true,tests/test_protected_suite_check.pyread 16 passed and 19 errors before its fixture disabled signing, and 37 passed after.For the tasks that follow
validation_launchreds above are its to clear;tests/test_snapshot.py's exclusion entry, next in the exclusion file's single-writer chain after this PR;pyproject.tomlpin's single-writer order.d5098297). The pin names its commit,047bb4fa(see the top).test_session_snapshot.pycases stay open for F5.2 whole.openxdox.projection_contributions.register()inscripts/opendox_host.register_openxfactory()(ruling 1);created:admissions underopenxdox_codeindocs/opendox-carve-admissions.yamlfor 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.pyandtests/test_protected_suite_check.py. Alsotests/protected_suite_respellings.yaml, which T060, openXdox's facet carries the governed snapshot values (5.3a) (plan 034) #34 created.valuesblock. T060, openXdox's facet carries the governed snapshot values (5.3a) (plan 034) #34's note on a page that fetches no/capabilitiesstill stands: this PR serves nothing new there.Review
Copilot. It reviewed each head from
f0f7f41con. 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:oldstarts a line;a1b75f3a:doc_healthread only for the sentinel;1885aee1,f22c73b0,0fdd65c1and4feb8009: the floors.aa0a2c5d: after the re-pin, Copilot's review at25414afcfound that a refused registration dropped the unread defaults it had replaced, instead of giving them back. That finding was taken.At
4feb8009its 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 ataa0a2c5dreads "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 at619684c9; the replies quote the check admitting them. The pin thread is this PR's stated gate. There are 0 unresolved threads, including r4149710491 at25414afc.SonarCloud. The first analysis failed the gate on Security Rating C (S8707). It passes from
7815c2daon, including ataa0a2c5d.🤖 Generated with Claude Code