Repository navigation
T026, U-7: the allow-list for 12.5's governed suites, with R-1 (a)'s span kind (plan 038, H-2) - #43
Conversation
…038) R-1 (a), ruled by Brett Heap with plan 038 (opensoft/openxFactory#656 comment 6013547504, "Admitted edit kind (Recommended)") and recorded at 12.5's falsifier by T005's batch Q: an admitted entry may name a SPAN, one module-level constant of a protected suite, in place of its test. scripts/protected_suites.py's _inside_the_test rule is amended to admit that kind, and nothing wider: * the entry's old text lies inside that one constant's statement before the landing, and its new text inside it at the landing; * a span is one module-level assignment to one bare name that nothing else in module scope binds, so a function, a class, an import or a second binding is never one, and no span is ever added; * only an admitted entry names a span, and an entry naming both a test and a span is refused. Refs opensoft/openxFactory#656 (CLAIMED 6015602254). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Reviewer's GuideAdds R-1 (a)'s span-kind support to the protected-suite allow-list, allowing admitted edits inside pre-existing module-level constants while enforcing strict schema, naming, AST scope, and before/after containment checks. Flow diagram for validating an admitted span editflowchart TD
A[Allow-list entry] --> B[_check_keys]
B --> C{admitted entry names span?}
C -->|No| D[_check_spellings validates test]
C -->|Yes| E[_check_spellings validates module-level name]
E --> F[_span_lines parses before text]
F --> G{Exactly one module-level assignment?}
G -->|No| H[Reject entry]
G -->|Yes| I[_inside_the_span checks old text]
I --> J[_inside_the_span checks new text]
J --> K{Both contained in span?}
K -->|No| H
K -->|Yes| L[Admit edit]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
…ach with its respelling (plan 038) Eighteen edits to five of 12.5's governed suites, one per test, each entered in tests/protected_suite_respellings.yaml with its exact old and new text and chained by blob in the order it applies: * the 17 that CF-4 (H-2) admits, respelling names the split-opendox carve moved before the arc: cmd_gate_* 7 (test_session_gates.py 3, test_session_verbs.py 4: the verbs now read from openxdox.cli_gate), hosted_index 3 (test_session_confinement.py: serve_projection's), share paths 2 (test_doxbench_share.py: each swept module at its one home, the record schema at the packaged copy), Group W 1 (test_session_verbs.py: openxdox.generator) and Group S2 4 (test_staging_workbench.py: the S5 spellings of the create and session columns); * test_staged_scope_adds_cluster_neighbourhood_section, R-1 (a)'s in-test entry: the label is the neutral grouping word, since S7 spells labels in the registered domain's vocabulary and that probe sets none. No assertion is weakened: each entry's review says what stays. The file's header now names the CF-4 respellings and R-1 (a)'s span kind. Refs opensoft/openxFactory#656 (CLAIMED 6015602254; questions 6016415390). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
R-1 (a), ruled with plan 038 (opensoft/openxFactory#656 comment 6013547504), names the two route claims of tests/test_staging_workbench.py among its admitted edits. RULED Q3 (comment 5642758731) moved the session routes from the pure model into the session column, swb-session.js, the binding that POSTs them, so each claim is relocated with them and entered as an admitted edit with its reason: * test_the_session_surface_added_no_transport_to_the_view_or_the_model: each route is one constant of the session column, and neither the view nor the model names it; the view reaches the column the gate column contributes (the S5 respelling beside it); * test_session_transport_uses_the_injected_fetcher_spelling: every route literal in the transport is its one export const declaration, each route declared once; the model arrives as ctx.model (the S5 respelling beside it). The staging suite's entries chain again by blob, now seven. Refs opensoft/openxFactory#656 (CLAIMED 6015602254; questions 6016415390). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Span validation has confinement gaps, lacks tests and manifest entries, and leaves contradictory test documentation.
Review effort: Balanced
Findings: 1
Open (6)
Account for all module-scope binding forms · New Prevent spans from including adjacent same-line statements · New Add automated coverage for span allow-list validation · New Record admitted span edits in the allow-list · New Update docstring to reflect route ownership · New Correct documentation for relocated route constants · New
What changed in this PR
Implements plan 038’s protected-suite allow-list updates and repairs governed tests after the openDox/openXdox split.
Changes:
- Adds module-level
spanallow-list validation. - Records governed test respellings and relocated ownership assertions.
- Updates tests for relocated CLI, projection, schema, and web modules.
| File | Description |
|---|---|
scripts/protected_suites.py |
Adds span validation. |
tests/protected_suite_respellings.yaml |
Records governed edits. |
tests/test_staging_workbench.py |
Updates web ownership assertions. |
tests/test_session_verbs.py |
Respells relocated CLI/generator references. |
tests/test_session_gates.py |
Respells gate verb references. |
tests/test_session_confinement.py |
Uses the relocated projection module. |
tests/test_doxbench_share.py |
Locates split modules and packaged schema. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…'s cases (plan 038) Brett Heap's ruling at opensoft/openxFactory#656 comment 6016648451 ("Widen the spans, served display (Recommended)") widens R-1 (a)'s named spans to six: _CREATE_HARNESS, _SESSION_HARNESS and _HOSTILE_HARNESS, and the helpers _run_create, _run_session and _hostile_descriptors. The helpers copy the model's siblings and hand each harness the SERVED governed display. * scripts/protected_suites.py: a span may now be one module-level helper function as well as one module-level constant. A function's span starts at its first decorator, as a test's does. A class, an import, a test or a name bound twice is still never a span, and no span is added. * tests/test_staging_workbench.py, ten entries chained after the seven: - the three helpers copy display.js and the siblings the harness imports (swb-create.js or swb-session.js, with the helpers.js and dispose.js they import), with a package.json that makes node read them as modules, and hand the harness /capabilities["display"], by the statement serve.build_server() makes under the registered host; - the three harnesses install it (setDisplay(readDisplay(...))) before anything derives, as the shell does, and import CREATE_ROUTE and sessionRoute from the columns RULED Q3 moved them to; - three in-test respellings of the CF-4 kind, which T026's measurement found outside the seventeen (comment 6016415390 point 2): the gate verbs read from openxdox.cli_gate in two tests, and the sync script read at its one home on the import path. * tests/test_protected_suite_check.py: the span kind's cases (T026's Files gain it, the holder's answer on the same ruling). * tests/protected_suite_respellings.yaml: the header names the six spans, the helper-function form, and batch Q's --chains for 12.5's call. T020's registration of tests/test_staging_workbench.py (its tests/conftest.py and the scan in tests/test_host_plane.py) is not in this commit: it is made after #39 lands. Refs opensoft/openxFactory#656 (CLAIMED 6015602254; questions 6016415390; ruling 6016648451). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…alone on their lines, the route docstrings, --chains for 12.5 (plan 038) Copilot's reviews at 5fb475f and 856047a, each finding taken: * scripts/protected_suites.py, a span's one binding is now counted FAIL-CLOSED (review comment 4195507077): every binding form, in every scope of the module (an assignment, augmented or annotated assignment, for or with target, walrus or del; a function or class; an import or a star import; an except alias; a match capture; a type parameter; a parameter). A name bound twice anywhere is never one span. * A span holds its lines alone (review comment 4195507191): where another module-level statement starts or ends on the span's lines (HARNESS = "..."; OTHER = 1), the name is not a span, because an entry's whole-line text would change that statement too. * --chains is F5.2's and, from batch Q, 12.5's (review comment 4196188614): Brett Heap's ruling at opensoft/openxFactory#656 comment 6016648451. The module's usage block, the chain paragraph, check()'s docstring and the option's help say so, and the no-flag case is renamed test_a_chain_is_refused_in_a_call_without_chains, its assertions kept. * tests/test_staging_workbench.py, two admitted entries chained after the seventeen (review comments 4195507364 and 4195507428): the docstrings of the two R-1 (a) relocations now place the session routes in swb-session.js, as their assertions do. * tests/test_protected_suite_check.py: the eight binding forms, the shared line and its control, two targets and an annotation without a value. Refs opensoft/openxFactory#656 (CLAIMED 6015602254; ruling 6016648451). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…its scan reads a gate command line (plan 038) Brett Heap's ruling at opensoft/openxFactory#656 comment 6016648451 has T026 make this edit to T020's two files once #39 landed (c6d15b2): * tests/conftest.py: test_staging_workbench.py joins GOVERNED_HOST_SUITES. It parses its gate-off CLI descriptors with the real parser, and its node harnesses run in the display /capabilities serves, which openDox reads off the registered host. With no host, every harness helper refuses ProfileNotRegistered and the descriptors read invalid choice: 'gate'. * tests/test_host_plane.py: the scan that holds the list to the governed suites also reads a gate verb spelled as a command line (a string that opens with gate and the verb), as this suite's descriptors spell it. Over the 16 governed suites only test_staging_workbench.py matches it and not the argument-vector spelling. Refs opensoft/openxFactory#656 (CLAIMED 6015602254; ruling 6016648451). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The staging-workbench harnesses derive display data without registering the required openDox host, causing ProfileNotRegistered.
Review effort: Balanced
Findings: 1
Open (1)
Resolved since last review (7)
Account for all module-scope binding forms Update chain-enabled caller model and documentation for F12.1/12.5 Prevent spans from including adjacent same-line statements Correct documentation for relocated route constants Update docstring to reflect route ownership Record admitted span edits in the allow-list Add automated coverage for span allow-list validation
…fied_bytes (plan 038) Copilot's finding on #43 at 3226d5c (review comment 4198603899): the packaged copies' contract is that a copy is read only through openxdox.contracts.verified_bytes() or verified_path(), each of which checks its sha256 against copies.yaml before it is used. The CF-4 entry in tests/test_doxbench_share.py (test_the_action_is_in_the_pinned_schema_enum) built the copy's path beside gate_console and read it directly, so it could pass on a modified copy that a runtime consumer would refuse. The entry's new text now reads the schema with contracts.verified_bytes("gate-action-record"). Its assertion is unchanged. The suite's chain is regenerated: entry 32's text, and the suite's final blob. Refs opensoft/openxFactory#656 (CLAIMED 6015602254; ruling 6016648451). Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Sorry @brettheap, your pull request is larger than the review limit of 150,000 diff characters |
|
READY at 9c29855 Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Holder, at READY: T026 (U-7), the allow-list for 12.5's governed suites, with R-1 (a)'s span kind. Lane openXfactory-3's READY-CANDIDATE is
|
Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings T024 (#38), T023 (#42), T021 (#40), T026 (#43) and T095 (#46). In tests/conftest.py, T095's composed harness and T073's rail block were both appended after T021's lines. Both are kept, T095's as main has it and T073's after it, so this branch's diff against main is a pure append there. Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…erved facet (plan 038, T094's R2-INV-R9) (#51) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Authored by lane openXfactory-3, delegated by lane openxfactory-4 (#656 6021862323) Arc: neutral-product-standalone-operability ## T098: display harnesses (A), and the server's scope labels from the served facet (plan 038) This is a slice of T094's map R2-INV-R9 (opensoft/openxFactory#656 `6021830607`). `tasks.md` has no entry for it yet: lane 4 records the T095 to T104 entries after T002 (#1251). Until then, its contract is the map's slice-outline row plus the holder's rulings, `6021830531`. - **Realizes:** 21 of the composed reds outside 12.5's set in the declared exclusion, toward requirement 9's declared composed tests (T073, F9.1): - canvas: DJ 8 and DJ + HR 1; - explorer: DJ 5 and CP 2; - the 5 nodes held by R9-R1: canvas 2, explorer 2, scope 1. - **Falsifier (the outline row):** the composed run of the three files, each alone, at `main` + T095, takes the named 21 to 0 red. These read unchanged: - 12.5's 16 governed suites; - F5.2's 5 suites; - `test_column_contributions_governed.py` (9 passed). `tests/test_declared_exclusion.py` reads green when run lone. - **Ruled:** - **R9-R1 (a):** `doxbench_scope.py`'s labels and notes derive from the facet the browser reads, and every pin that asserts words is respelled through VR to the SERVED words. - **R9-W1 (A″):** the harnesses copy `display.js` beside the module they copy, as #43 does. - Both are in `6021830531`. They conform to the ruled overlay (`5784683830`, `5801057769`) and to the served-display rule for the staging suite (`6016648451`). - **After:** T095 (#46), LANDED as `e2340bb6`. The served display needs the governed host that T095's `DECLARED_HOST_SUITES` registers for these three files when the run is composed. This branch merges `main` `e2340bb6`, and every number below is measured over it. ## What changes **`src/openxdox/doxbench_scope.py`** is this slice's under R9-R1 (a), as claim `6021862323` names it. - **The labels now come from the facet.** The section labels and notes were one domain's words ("cluster documents", "topic folder documents"). They are now built from the facet by `_section_meta(_served_display())` once per `resolve_scope` call. - The six sentences are word for word the ones openDox's staging model has built since § 3.4 slice S7 (`views/staging-workbench-model.js` `SECTION_META`). - Keys, flags and paths are unchanged. - **Where the words come from.** `_served_display()` is the `display` block that `/capabilities` serves: `display_manifest(host_display())`. - It is read at call time, never at import and never cached, as `opendox.canvas_drafts` reads its one shared sentence. - **Decision: no host means neutral words.** With no host registered there is no served page. The browser model given no facet speaks openDox's neutral words, so the server answers with those too rather than refusing. - The words label sections of an authorization answer and never decide it. - A library or test caller with no host therefore keeps its paths. - **Who reads the labels.** Server-side, no module reads a section's label or note except the parity test: no prompt and no wire field carries them. **`tests/test_doxbench_scope.py`** - The browser harness copies `display.js` beside the two models and writes a `package.json` with `"type": "module"` (DJ). It installs the display through `setDisplay(readDisplay(...))`, as the shell does at mount. - The parity test hands the browser the served display (VR). - **Two new cases**, because the parity test alone cannot catch one thing. The composite serves openDox's neutral stage words for these three roles, since openXdox overlays only `completion` and the `values`. So parity cannot tell a server that reads the facet from one that always speaks neutral words. The new cases can: - **A host that declares its own stage words.** It declares openxFactory's pre-S7 words. The server labels read "cluster documents", "topic folder documents" and so on, and match the browser byte for byte. - **No host.** The server reads the neutral words, which equal the browser's with no facet. **`tests/test_canvas.py`** - `_run_node` copies `display.js` and writes the `package.json` (DJ). It hands the harness the served display, so every canvas derivation runs under the words the page is served (VR). - The two gap pins now read the kind canvas-model.js emits under every host, `unsupported-candidate`, where they read `unsupported-possible` before (R9-R1). - `test_js_and_python_draft_constants_agree` also cross-checks the seed state of a new draft. Both halves read it off one facet: the composer plan's `state` against `canvas_drafts.register_state("captured")`. This assertion is what makes the served-display hand-off observable (mutant H4 below). **`tests/test_explorer_viewer.py`** - **DJ:** each explorer harness copies `display.js` and writes the `package.json`. - **VR:** `_EXPLORER_HARNESS` is handed the served display. - **R9-R1, the served words.** The two label pins read the words the page is served, from the composite's artifact axis: - groups `proposal.md` and `tasks.md`; - classification `proposal.md`, `design.md`, `tasks.md`, `Spec deltas`, `Supporting docs`, `other`. - **CP: the import-free pin**, respelled to S7's design: - no import names the viewer; - the only module imported is `./display.js`; - import statements spread over several lines are read whole. - **CP: the wheel pin**, respelled to `opts.wheelKey === SOURCE`, with `SOURCE` held to be `STAGE_ROLES[0]`. ## The falsifier (composed, each file alone; quoted) **The composed form, R1Q23 (a):** - openxFactory `92010d3e` (`tests/composed_host_pin.yaml`), with `openDox`, `openXdox` and `openXwallet` initialized recursively, and its `scripts/` on `PYTHONPATH`; - openDox installed from openDox-code `main` `84f8ed83` (force-reinstalled); - the colour variables unset and `TERM=dumb`; - per file: `python -m pytest -q -p no:cacheprovider -rfE --junitxml=<file>.xml tests/<file>.py < /dev/null`. T022's `scripts/composed_placements.py` (taken from #44's tree) refuses to place in these checkouts: its `.gitignore` entry is not on `main` until #41 lands. None of these files reads the runbook it places. Every checkout read clean after every run. **Measured over real `main`** (`e2340bb6`, carrying T095 #46 and T026 #43): the base is `main` itself, and the head is this PR's `c935f2a0` (this branch merged with `main`). | run | test_canvas.py | test_explorer_viewer.py | test_doxbench_scope.py | named reds | |---|---|---|---|---| | base: `main` `e2340bb6` | 10 passed, 11 failed | 15 passed, 9 failed | 34 passed, 1 failed | **21** | | head: `c935f2a0` | **21 passed, 0 failed** | **24 passed, 0 failed** | **37 passed, 0 failed** | **0** | Before T095 landed, the same 21 were measured at a local integration that was never pushed (`main` `f70bc9c3` + #46 `c2192e3` + this branch): 21 red at its base and 0 at its head. At `main` `d45a0939`, before T095 existed, these files read 19, 9 and 1 red. The 21 nodes that flipped: - **canvas (11):** `test_member_pane_is_exactly_the_topics_document_edges`, `test_downstream_artifacts_are_in_the_lineage_strip_never_members`, `test_evidence_board_carries_section_ref_and_passage_hash`, `test_missing_cluster_degrades_to_null`, `test_gap_unclaimed_member`, `test_gap_unsupported_possible`, `test_gap_both_kinds_on_one_cluster`, `test_option_set_grouping`, `test_js_and_python_draft_constants_agree`, `test_esc_escapes_markup`, `test_model_passes_prose_through_as_data_not_html`; - **explorer (9):** `test_explorer_js_exists_and_is_importable_standalone`, `test_staged_tile_lists_the_topic_folder_with_headers`, `test_aggregate_folder_entry_keeps_its_member_source_key`, `test_aggregate_folder_entry_disambiguates_same_repository_refs`, `test_aggregate_wheel_navigation_threads_the_owning_member_key`, `test_proposal_tile_groups_proposal_and_tasks`, `test_realized_tile_lists_the_archived_change_folder`, `test_unresolvable_tile_and_kind_degrade_to_null`, `test_change_file_classification`; - **scope (1):** `test_server_and_actual_browser_projection_are_byte_shape_equivalent`. Two nodes are new: `test_the_server_labels_follow_the_facet_a_host_declares` and `test_with_no_host_registered_the_labels_are_openDoxs_neutral_words`. No node regressed. **The unchanged set** was compared node for node, base against head over `main`: **974 nodes, 10 red at both, 0 nodes changed outcome.** | set | base | head | |---|---|---| | 12.5's 16 governed suites | 832 passed, 10 failed (pre-existing: `session_runbook` 9 and `session_notebook` 1, which read the runbook T022 places) | identical, file for file | | F5.2's 5 suites | 123 passed | identical, file for file | | `test_column_contributions_governed.py` | 9 passed | 9 passed | ## Mutants Each mutant was applied at the integration (`main` `f70bc9c3` + T095 `c2192e3` + this branch), its file run alone composed, and the file restored byte for byte. **11 of 12 killed:** | mutant | site | killed by | |---|---|---| | S1 | src: ignores the host's facet (always neutral) | `test_the_server_labels_follow_the_facet_a_host_declares` | | S2 | src: no-host fallback dropped | `test_with_no_host_registered_the_labels_are_openDoxs_neutral_words` | | S3 | src: members label hard-coded "cluster documents" | parity (served) + no-host | | S4 | src: folder label one/many swapped | parity + declaring host + no-host | | S5 | src: neighbourhood note drops a facet word | declaring host | | H1 | scope harness: no `display.js` | all three browser cases | | H2 | scope harness: browser ignores the display | declaring host | | H3 | canvas: no `display.js` | the 11 canvas Node cases | | H4 | canvas: neutral display instead of served | `test_js_and_python_draft_constants_agree` | | H5 | explorer: no `display.js` | 7 explorer Node cases | | H6 | explorer: neutral display instead of served | `test_proposal_tile_groups_proposal_and_tasks`, `test_change_file_classification` | | H7 | scope harness: no `package.json` | **SURVIVES** (37 passed) | **H7 is an equivalent mutant on the measured runtime.** Node v24 detects module syntax in a `.js` file with no `"type"` declared, so `package.json` changes nothing there. It is kept for runtimes without that detection, as #43's harness keeps it. T097 measured the same survivor. ## The lone CI form (`validate.yml`'s exact step, at `c935f2a0`) `python -m pytest -q --junitxml=pytest-report.xml --deselect "$LEFT_OUT"`, run locally, read: ``` SELECTED=1165 PASSED=1161 SKIPPED=4 FAILURES=0 ERRORS=0 (floors MIN_SELECTED=1099 MIN_PASSED=1095 EXPECT_SKIPPED=4) 1161 passed, 4 skipped, 1 deselected in 169.43s ``` - `tests/test_declared_exclusion.py` run alone: rc 0. Each of the three files still fails lone on its declared reason (`doc_health`, at collection). - The floors are untouched; only T029 raises them. ## CI and Copilot at `c935f2a0` - **`validate`:** success, run `37548181742`. The triple is `selected=1165 passed=1161 skipped=4 failures=0 errors=0`, with pins `selected>=1099` (margin 66), `passed>=1095` (margin 66) and `skipped==4`. - **SonarCloud Code Analysis:** success. - **Copilot**, review `5435780547` at `c935f2a0`: - **"Needs a closer look", Findings: None.** Its stated reason is that "final composed validation after integration remains unverified". This PR's CI cannot run the composed form until `composed.yml` lands (T029 #44, then T073 #45). The composed validation over real `main` `e2340bb6` is the local run quoted above: 21 to 0 red, and the unchanged set identical node for node. - The earlier review at `588d4c15` (`5435186246`) gave the same verdict, with no findings, for the then-unmerged #46. - 0 review threads, 0 unresolved. ## Files changed - `src/openxdox/doxbench_scope.py` - `tests/test_canvas.py` - `tests/test_explorer_viewer.py` - `tests/test_doxbench_scope.py` No protected suite is edited: none of the four is in 12.5's 16 or F5.2's 7. No allow-list entry is needed, and `tests/declared_exclusion.yaml` is untouched. ## Not done - **Composed CI:** `composed.yml` is not on `main` yet (T029 #44, then T073 #45), so this PR's CI is `validate` and SonarCloud. The composed numbers above are local runs, quoted. 🤖 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>
…e identity response shape and the single-writer chains (plan 038) (#1257) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) **T002, second bookkeeping batch, plan 038: T094 and the slice entries T095 to T104, the identity response shape, the single-writer chains, and the ticks.** Bookkeeping, so this PR carries no `Arc:` line. It touches no `openspec/changes/` path, so no Rule 6 window applies. It began stacked on #1251's head; #1251 has landed (`1837ea75`) and `main` is merged in (`543f6ce1`), so the diff against `main` is this batch alone. ## From plan 038's `tasks.md`, T002 - **Task**: T002, "Release-2 base, and the re-measure at the ruling" (landed in #1251; this is its second batch of bookkeeping, the brief of the holder's `T002b`). - **Realizes**: none (bookkeeping; FR-025). **Falsifier**: T002 names none. Its gates are the brief's, quoted under "Review and gates". - **Ruled / Decisions**: none of its own. Every item is a ruling already posted on `#656`, or a landing already merged, encoded as worded and cited by comment id or merge commit. ## The items | # | Where | What changed | Record | |---|---|---|---| | 1 | tasks.md: T094, T095 to T104, T073 | T094 ticked, with its result quoted: 436 composed reds over 51 files, outside 12.5's set (Base 2; 533 at Base 1). The `T095+` placeholder becomes ten entries, T095 to T104, each with its slice name, Files, After and Falsifier from R2-INV-R9's outline and the holder's rulings, `Lane: 3 (openXfactory-3)`. T073's After and Files name them. The map's means, the rulings (R9-R1 (a), R9-R2 (a), W1 to W7) and the OQ defaults are recorded once, above the entries | map `R2-INV-R9.md`; `6021830607`; claim `6021862323`; rulings `6021830531` | | 2 | T095, T101, T104, T097 | T095: the two confirmed departures from OQ-R9-1 (`plane_host_for` untouched, an autouse fixture registers the declared host; `DECLARED_HOST_SUITES` guarded structurally). T101: `tests/declared_exclusion.yaml` for ONE entry (reasons `[doc_health]`, note dropped, the `only` list loses the file, count stays 66). T104: `tests/test_binding_stylesheets.py`, the pin 572 to 574. T097: its served-display respelling is R9-R1 (a) applied | `6022291206`; the T097 line is `6023517122` (the holder confirmed the citation, `6026622117`) | | 3 | plan.md: the single-writer table; tasks.md Files and After lines | W7's chains: `tests/conftest.py` T020, then T021 and T026 in landing order, then T095, T073, T074; `tests/test_host_plane.py` T020, T026, T095; `declared_exclusion.yaml` T101, T073, T074; the four T074 test files T103 then T074; the census T025, T104, T015, T016, T057 (the row splits, so `test_web_boundary.py` keeps its own chain). T015's and T074's After gain T104 and T103 | `6021830531`, `6022291206` | | 4 | tasks.md: T072, T074, T075 falsifiers | The four folds of #1253, in the arc change's own wording: T072 asserts that ONLY CR, LF and CRLF split rows; T074's seam tests assert that an empty-seam read names the seam AND its registrar; T075's host-wiring test shows a leg declaring only SOME of the four seams refused, and a leg declaring the six and none of the four accepted; T074's protected-suite oracle computes 12.5's set as 12.5 does (`git grep -l -e 'open-pr' -e 'open_pr' -e 'FakePullRequests'`), from the pre-arc and the final tree, the floor of 16 on each, and takes the union | openxFactory#1253 to `fc4fa0ff`; Copilot `5427373153` | | 5 | spec.md FR-011; tasks.md T041 | FR-011's JSON shape gains `identity`, emitted and bounded as openDox-spec's finding schema bounds it (no `excerpt`, `text`, `content` or `quote` key, no number, strings of at most 200 characters, `{category, entry}` for a pathless finding, `{collided_id}` for a collision). T041's falsifier gains a response-shape test asserting exactly that bound. The coverage row for FR-011 names T041. The serialized-size cap was already T041's at the base (T041's text says so, and T042 "stores what T041 bounds"), so nothing moved | holder `6018624750` | | 6 | tasks.md ticks | T011, T014, T021, T023, T025, T026 and T060 ticked, T070's tick gains #1253, and T002's own landing is recorded. Each merge commit was verified with `gh pr view <n> -R <repo> --json mergeCommit` (listed below) | the landings | | 7 | tasks.md: T072 | A Files line (`src/opendox/lines.py`, `tests/test_lines.py`); the Ruled line gains `6023517122`: `head_sha` (a), its own public `head_sha` parity-tested against `serve._head_of`, `serve.py` untouched; the line split (a), `doxbench_defaults.py` untouched. Folding either private helper is recorded as unscheduled and optional, and is not scheduled | holder `6023517122` | | 8 | contracts/health-finding.md:91 | The sentence reads: a stored `identity` makes a cross-run collision between STORED findings detectable; an exception-only finding is never stored; whether the engine reports it remains T046's concern. Nothing else on the line changed | holder `6018624750`; Copilot `5433292692` | | 9 | plan.md; tasks.md | Copilot's three items at #1251's head `1eb8e9eb`, accepted by the holder at its landing: (a) the pin and landing-order row for T073 names T005 and T095 to T104 as prerequisites, and `T095+` reads T095 to T104 at the critical path, the lane table and the revision note; (b) the combined `conftest.py` and `test_host_plane.py` row splits, and the cross-lane summary gains T026 (and the other chains of item 3); (c) the same split in T020's, T021's and T026's Files lines | holder replies `4201056969`, `4201057311`, `4201057577`; READY note `6026651962` | ### The ticks, verified | task | pull request | merge commit | merged | |---|---|---|---| | T011 | opensoft/openDox-code#92 | `09b8d44a` | 2026-10-06T19:15:55Z | | T014 | opensoft/openDox-code#93 | `a7a1c4d3` | 2026-10-06T22:23:06Z | | T021 | opensoft/openXdox-code#40 | `f70bc9c3` | 2026-10-06T19:07:10Z | | T023 | opensoft/openXdox-code#42 | `d45a0939` | 2026-10-06T17:45:33Z | | T025 | opensoft/openDox-code#91 | `84f8ed83` | 2026-10-06T17:33:31Z | | T026 | opensoft/openXdox-code#43 | `36bbef79` | 2026-10-06T22:35:40Z | | T060 | opensoft/openDox#20, the tag `dox-v1.2` (tag object `58538ff3`, on `6a9f4902`), opensoft/openDox#21 | `6a9f4902`, `c7f75845` | 17:46:59Z, tag 17:58:45Z, 19:02:39Z | | T070 | openxFactory#1253 (T070b, added to its tick) | `fc4fa0ff` | 2026-10-06T18:56:42Z | | T002 | openxFactory#1251 (its own landing) | `1837ea75` | 2026-10-06T22:31:42Z | - **T021** landed with Copilot r4199337845 an ACCEPTED LIMIT (holder READY note `6023492215`); T021's entry records it. - **T025's** entry says its 34 nodes are "quoted at T029"; that stays T029's, and the entry says so. - **T011's** server node is T014's, as its own Falsifier says. **Skipped, because already present at the base:** T020's and T024's ticks (#1251 item 13) and T004's tick (#1245, `260234b5`), all confirmed with `git show <commit>:<tasks.md> | grep`. **T071 is NOT ticked.** Brett's word, "Ratify it (Recommended)" (`#656` `6023375303`), is recorded on T071's entry, but the change's ratification-record PR has not landed (no such PR is open or merged on `opensoft/openxFactory` at this writing). The box stays open. ## Readings the holder accepted (`6026622117`), disclosed as the brief requires - **W7 omits T026 from the openXdox-code chains.** The single-writer table keeps T026 where its own ruling (`6016648451`) puts it, and lane 3's claim (`6021862323`) says T026's PR lands before T095. So the conftest chain reads T020, then T021 and T026 in landing order, then T095, T073, T074; and `test_host_plane.py` reads T020, T026, T095, as W7 gives it with T026 added. - **R9-R2's last sentence** ("If the re-scoped test runs alone, it leaves the declaration, and the count moves with it, as the declaration's own rules require") is recorded in T100 as worded. `declared_exclusion.yaml` is NOT added to T100's Files: the holder's file list at `6022291206` names it for T101 only. - **Edits outside tasks.md**, ruled in scope as each item names its place: plan.md (items 3, 9), spec.md FR-011 (item 5) and `contracts/health-finding.md:91` (item 8). ## Other notes on where an item needed a reading - **Counting.** The task count reads 90 rows: the placeholder `T095+` is replaced by T095 to T104 (81 - 1 + 10). - **Plan 034's task numbers.** The entries cite plan 034's T103 (#80, in T099's `Host` header) and plan 034's T086 (W2, in the rulings) as "plan 034's", because plan 038 now has its own T103. - **OQ-R9-3.** The map did not measure the respelled gate-console and wheel-model skips; T097 and T103 say so, and the map's 127 passed and 5 skipped is quoted as the measurement. - **Counts of slices** are copied in the map's own form (for example "16 nodes, and +5 on R9-R1 (a)"), not summed. - **T095's chain after T026.** T095's After names T021 and T026, both landed. - **Not mirrored from the arc's 4.1:** T075's falsifier gains the some-of-four refusal and the six-and-none acceptance, which #1253 folded. The arc's two older refusals (part-way through the seams; at the column call) are not in T075, since #1253 did not add them. - **T046 and T057** carry no response-shape falsifier for `identity`: item 5 names T041's. ## Review and gates - **`python3 scripts/validate-openspec-cli-pin.py --all`**, in the clone named `openxFactory`, at `691648c6`: exit 0, `Totals: 113 passed, 1 failed (114 items)`, `0 UNDISPOSITIONED failures`. The one failure is the dispositioned `add-chain-attestation` finding, the same on `main`. - **openxFactory pytest.** The full local run was stopped at about 44% at a coordinator drain, so it is NOT a result and is not claimed. The repository's own gate, `pytest-suite` in CI at `691648c6`, completed `SUCCESS` (2026-10-06T23:32:38Z to 23:58:56Z). - **Doc-health**, `scripts/doc-health.py --single-repo . --as-of 2026-10-07`, branch `691648c6` against `origin/main` `0992369a` in the same clone: the two reports are byte-identical (sha256 `ce17aadd6d96e484170e2ec4784e44972e33c7d1a6c65830ea14a1035f2ae976`; `Findings: 31 critical, 26 error, 69 warning, 20 info. New regressions vs previous report: 0.`). So no new error. - **CI at `691648c6`**: all 14 check runs are `SUCCESS` (rollup `SUCCESS`): `pytest-suite`, `merge-master-approval` (the red inherited from `main` since #1252 was cleared by #1138), `openspec-cli-pin`, `doc-health-py314`, `openxdox-consumer-gate`, `wallet-validation`, `clearing-dispatch-gate`, `signed-execution-chain-gate`, `former-id-arrival-gate`, `release-tag-gate`, `openreposhape-pin`, the two `lane-line` runs and SonarCloud. - **`main`** has moved to `0992369a` since the last merge (`543f6ce1`). GitHub reports this PR `MERGEABLE`, and the ruleset is not strict, so `main` is not merged in again (a merge would restart the 27-minute gate). | Copilot at | verdict | findings | answered | |---|---|---|---| | `691648c6` (final; review `5435686665`) | Changes recommended | 1 (thread `4201443690`): T041's falsifier cannot verify what T046's `health list --json` and T057's HTTP route emit; the review summary adds that the new T095 to T104 collide with plan 034's task numbers cited unqualified at `spec.md:662`, `spec.md:1222` and `clarify-questions.md:437` | accepted limit (#656 `5988818366`): plan-record accuracy, not a bypass, and the T041 placement is the holder's own instruction (item 5). Answered (`4201487553`) and resolved | 1 thread, 0 unresolved. The holder ruled both points YES at `6027706377` and has them encoded in a THIRD batch, not here: the `identity` falsifier split across T041, T046 and T057, and the plan 034 references qualified. This PR therefore carries T041's wording as the brief gave it. ## Files changed - `specs/038-opendox-document-tool-self-maintenance/tasks.md`, `plan.md`, `spec.md` - `specs/038-opendox-document-tool-self-maintenance/contracts/health-finding.md` ## What is NOT done - T071 stays open (its ratification record has not landed). No box of #1144 is ticked, and no task other than those listed is ticked. - No scenario or spec delta beyond FR-011's JSON-shape bullet is touched, and nothing is under `openspec/changes/`. `README.md` is untouched. - The T095 to T104 entries record the slices; none of their work is done here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lane: openXfactory-3 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… CP, PI) (plan 038) (#47) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Authored by lane openXfactory-3, delegated by lane openxfactory-4 (#656 6021862323) Arc: neutral-product-standalone-operability ## T099: `tests/test_renderer.py`, the renderer's 21 composed reds (plan 038) This is slice T099 of T094's map (R2-INV-R9). It works under the holder's rulings at opensoft/openxFactory#656 comment `6021830531` and lane 3's CLAIMED comment `6021862323`. Plan 038's `tasks.md` has no entry for it yet: lane 4 records T094's slices after openxFactory#1251. Until then, the contract is the map's outline row plus those rulings. - **Realizes** (the outline row): DJ + VR 5, HH 12, CP 3 and PI 1, all in `tests/test_renderer.py`. That is 20 nodes, plus 1 on R9-W3. They are among requirement 9's declared composed tests (T073, F9.1). Each slice clears its own reds so that T073's composed step 5a can read green. - **Falsifier** (the outline row): the composed run of `tests/test_renderer.py`, alone, reads 0 for the 21 named reds. Its 3 LI nodes arrive with T095 (R9-W2), and its 1 SF node with T104's openDox pin. The unchanged set reads unchanged, and `tests/test_declared_exclusion.py` reads green lone. - **Ruled** (`6021830531`; and `6028383410` for the accepted limit below): - W1 is (A″): the harness copies `display.js` beside the module it copies, as #43 does. - W3: `test_dynamic_import_is_absent` is INVERTED, so it now asserts the ruled dynamic import of contributed bindings. - R9-R1 (a): where a test asserts words, they are the SERVED words. - **Decisions:** - No node of this file asserts a display WORD, so R9-R1 (a) needs no served display here (point 1 below). - Every node keeps its name, the inverted pin's (point 4 below) and the collapse node's (Copilot's rename finding, declined below), so the 21 nodes T094's map and T073's declared run account for keep their identity. - **After:** none. Nothing here waits on T095. ### What changed: one file, `tests/test_renderer.py` 1. **DJ + VR, 5 nodes: the `model.js` harness.** - Since § 3.4 slice S7 (openDox-code `1e46971`), `model.js` imports `./display.js`, which is itself import-free. The harness copied `model.js` alone, so node read `ERR_MODULE_NOT_FOUND`. It now copies `display.js` beside it, as #43's harness copies the staging model's siblings, and writes a `package.json` of `{"type": "module"}`. - The six columns are keyed BY ROLE since S7: `source`, `grouping`, `candidate`, `selection`, `submission` and `completion`, where they were `docs`, `clusters`, `possibles`, `staged`, `proposals` and `realized`. The harness and its assertions now read the role keys. Only the keys moved: every count is the one the test always pinned (6/6/5/2/1/1; 16 topic, 1 pick and 1 flow; 8 left after the collapse). - No assertion reads a display word, so the harness hands `buildFunnelModel` no display, and the model takes openDox's neutral one. 2. **HH, 12 nodes: ONE `Host` line.** `_raw_get` sent two `Host` lines: `putrequest(..., skip_host=False)` added one, then `putheader("Host", ...)` added a second. openDox-code `390e2c2` (T103, openDox-code#80) admits a loopback request only with exactly one, and answered every request with `403 invalid_host` ahead of every route. `putrequest` now skips its own line. 3. **CP, 3 nodes: pinned claims, respelled to the carve's ruled design.** - **The fetch-bearing set** (`test_data_fetches_target_only_snapshot_and_source_passthrough`, and its arithmetic in `test_the_session_transport_stays_out_of_the_fetch_bearing_set`). - Slice S4 (openDox-code `69d2760`) split `repo-selector.js` under RULED Q3 (openxFactory#656 `5642758731`): "a route constant travels with the binding that calls it". So the set gains `projection-index.js` (the index read, count 1). - `repo-selector.js` falls from 6 call sites to 2: the refresh POST and the register-projection read, which stay class A. - The create-project and edit-project POSTs went with `gate-projects.js`, which slice S5 leg B (`8efb3cf`) then moved into this leg's own views. That puts them outside openDox's class-A surface, which is what this pin covers. - The apply POST left the bundle: it is openxFactory's own fulfilment lane. - The map traced only the new file. The count change was measured here, against openDox-code `84f8ed83`. - The sibling test's self-quoting guard (its own "finding 24") now quotes six files and six counts, each needle still assembled at runtime. - **The collapse modifier** (`test_six_column_default_and_five_column_collapse_marker`). openDox-code `3c3a9e3` (openDox-code#35) renamed `.collapsed-docs` / `.only-docs` to the role, `.collapsed-source` / `.only-source`. 4. **PI, 1 node, W3: `test_dynamic_import_is_absent` INVERTED.** - The old pin asserted that no bundle file spelled `import(` anywhere. It read red on a COMMENT in `app.js`. - The pin now asserts that the bundle's dynamic imports, in CODE, are exactly the carve's ruled loaders of contributed bindings, each argument exactly as written: - `views/view_extension.js`: `new URL(binding.module, bundleRoot).href`. This is the view registry's loader, written by slice S3 (`c5edac8`); slice S5 leg B (`8efb3cf`, RULED Q1 to Q12) mounts the contributed gate loop through it. - `views/repo-selector.js`: `"./projection-index.js"`, from slice S4 (`69d2760`, RULED Q3). - `views/intent-binding.js`: `"./intent-feed.js"`, from slice S2 (`c7ab3d8`, RULED Q5). - The pin also asserts that the registry's loader resolves against the bundle's own root (`new URL("../", import.meta.url)`), read from executable code. - So none of the three can pull a URL: - Two name a bundle-relative sibling literally. - The third is bounded where a binding is declared: openDox's `viewBinding()` refuses an absolute URL, a root-relative path and a `..` climb. openDox-code's own `tests/test_view_registry.py` holds that refusal. - **How the scan reads code** (`_without_comments`, shaped by Copilot's two findings): - It reads each file WHOLE, as a JavaScript lexer reads it. It tracks string, template and regular-expression literal state, and replaces each comment with one space. It KEEPS the literals, so an `import(` spelled inside one still counts: the scan may over-count, but it never hides a call. - So none of these hides a call: a line break or a comment between `import` and `(`; a generator method's line that opens with `*`; a `//` comment ended by CR, U+2028 or U+2029; a spread (`...import(`); or U+FEFF before `(`. Only a member call (`a.import(`) is skipped. - It reads `.js`, `.mjs`, `.cjs`, `.html`, `.htm` and `.css` files. - **Two readings.** The default reading keeps every spelling, so it can only over-count: it refuses an unknown import. The `executable_only` reading skips a spelling inside a literal, and it must equal the same three sites: it proves each ruled loader is an executable call, so a decoy string cannot stand in for a removed loader. - **The loader's base** is read as every executable assignment to `bundleRoot` (plain or compound, comments not read, literals skipped). It must be exactly `bundleRoot = new URL("../", import.meta.url)`, so neither the old line kept in a comment or a string nor a later reassignment passes. - **The scan's own regression cases**, committed: - `test_the_dynamic_import_scan_reads_code_as_a_lexer_does`: 21 probe modules, each written as exact bytes, with the site map the scan must read; - `test_the_dynamic_import_scan_reads_every_script_suffix`; - `test_the_executable_reading_counts_only_calls`: 6 cases; - `test_the_loader_base_is_read_from_executable_code`: 5 cases. - **Stated limit:** the lexer tells a regular-expression literal from a division by the token before the `/`, not by a full parse. So a regex literal straight after `)` (as in `if (x) /re/.test(y)`) reads as a division. That is the limit the holder accepted for openDox-code's import-free scan (opensoft/openDox-code#91, r4198449977): closing it needs a JavaScript parser. - The name is kept on purpose. The node T094's map and T073's declared run account for keeps its identity, and the name still reads true: a dynamic import is absent from every line of code but these three. ### The falsifier, composed (R1Q23 (a)), each file alone **The form:** - openxFactory `92010d3e` (the commit `tests/composed_host_pin.yaml` names), with `openDox`, `openXdox` and `openXwallet` initialized recursively, and its `scripts/` on `PYTHONPATH`; - openDox installed from openDox-code `main` `84f8ed83` (T025), over the pin; - T022's one placement: the session runbook, linked from the composed tree's openDox-spec at `f7ee3c76` before the run and removed after it. T022's script is on #41, not `main`, and it refuses a checkout whose `.gitignore` lacks its line. So the run makes that one link itself, with the script's own checks (the source tracked and unmodified, and nothing already at the destination). The checkout read clean after each run; - the colour variables unset and `TERM=dumb`; - each file alone, with its own short TMPDIR (38 bytes, under the PostgreSQL socket limit): `python -m pytest -q -p no:cacheprovider -rfE --junitxml=… <file> < /dev/null` from the checkout root. | `tests/test_renderer.py`, alone | result | |---|---| | base: `main` `fc1115d6` | `exit 1; 28 passed, 22 failed, 0 errors, 0 skipped` | | head: `99508076` (`main` merged) | `exit 1; 82 passed, 1 failed, 0 errors, 0 skipped` | - **Red to green: 21, and 0 green to red.** The head's other 33 nodes are the scan's new regression cases, all green. The 21 are exactly the named nodes: - DJ + VR: `test_model_derives_the_six_columns`, `test_model_edge_derivation`, `test_model_tally_equals_edge_count_through_the_real_js`, `test_five_column_collapse_drops_doc_edges`, `test_model_degrades_on_empty_snapshot`; - HH: `test_serve_snapshot_route_and_alignment`, `test_serve_static_bundle`, `test_serve_source_passthrough`, `test_serve_divergence_diverged`, `test_serve_divergence_unknown_without_head`, and `test_serve_rejects_path_traversal` × 7; - CP: `test_data_fetches_target_only_snapshot_and_source_passthrough`, `test_the_session_transport_stays_out_of_the_fetch_bearing_set`, `test_six_column_default_and_five_column_collapse_marker`; - PI: `test_dynamic_import_is_absent`. - **The 3 LI nodes cleared with T095 (#46), at the base:** `test_generate_and_open_generates_and_always_prints_url`, `test_generate_and_open_respects_no_open` and `test_generated_snapshot_is_schema_shaped` were red at `36bbef79` and are green at `e2340bb6` and since. They were T095's under R9-W2, not this slice's. - **Still red: 1, not this slice's.** SF, which arrives with T104's openDox pin (`doxchat-no-model` and `doxchat-untrusted` have no `styles.css` rule in the openDox these runs install, openDox-code `84f8ed83`): `test_every_constructed_doxbench_class_has_a_styles_rule`. - **Every base and head along the way read the same way.** The bases `8b64fae0`, `d45a0939` (T023), `f70bc9c3` (T021) and `36bbef79` (T026) read the same 25 failures, and `e2340bb6` (T095) read the same 22. Every head of this PR, from `f82abd40` to `99508076`, read the same 21 flips with 0 green to red. ### The unchanged set (the same runs, each file alone) | set | base `fc1115d6` | head `99508076` | |---|---|---| | 12.5's 16 governed suites (`git grep -l -e open-pr -e open_pr -e FakePullRequests -- 'tests/test_*.py'`) | 842 passed, 0 failed | 842 passed, 0 failed | | F5.2's 5 (`test_generator`, `test_session_snapshot`, `test_snapshot_determinism`, `test_snapshot_registry`, `test_snapshot_validation_launch`) | 123 passed, 0 failed | 123 passed, 0 failed | | `tests/test_column_contributions_governed.py` | 9 passed | 9 passed | - All 22 files read node for node identical at base and head. - `tests/test_declared_exclusion.py` **lone**, with CI's install (openDox at its pin `dede32b4`) and no composed tree, at `99508076`: `207 passed in 27.51s`. Run lone, `tests/test_renderer.py` still fails on its declared reason, `doc_health`. ### Mutants: 32 of 32 killed The bundle mutants run over a fresh copy of the installed openDox bundle, which a test-only plugin hands to the suite as its `WEB`. The plugin is not committed. The control run, with the copy unmutated, read `4 passed`. | mutant | what goes red | |---|---| | M1: an extra `await import("https://cdn.example/x.js")` in `views/wheel.js` | `test_dynamic_import_is_absent` | | M2: the ruled projection-column import removed from `repo-selector.js` | `test_dynamic_import_is_absent` | | M3: `"./intent-feed.js"` made an absolute URL | `test_dynamic_import_is_absent` | | M4: a spaced `import ("./display.js")` added to `views/model.js` | `test_dynamic_import_is_absent` | | M5: `/* a note */ const x = import("https://…")`, code after a block comment, in `app.js` | `test_dynamic_import_is_absent` | | M6: the registry loader's base moved off the bundle (`new URL("https://cdn.example/")`) | `test_dynamic_import_is_absent` | | M7: the registry loader's `import()` removed | `test_dynamic_import_is_absent` | | M8: an extra `fetch(` in `projection-index.js` | both fetch-set pins | | M9: the old `.collapsed-docs` spelling restored in `styles.css` | `test_six_column_default_and_five_column_collapse_marker` | | M12: `import`, a line break, then `("https://…")` | `test_dynamic_import_is_absent` | | M13: a generator method, `*load() { yield import("https://…"); }` | `test_dynamic_import_is_absent` | | M14: `import /* why */ ("https://…")` | `test_dynamic_import_is_absent` | | M15: a string holding `//` ahead of a call on the same line | `test_dynamic_import_is_absent` | | M16: a regex literal holding a quote and `//` ahead of a call | `test_dynamic_import_is_absent` | | M17: `// c` CR `import("https://…")` | `test_dynamic_import_is_absent` | | M18: `// c` U+2028 `import("https://…")` (the previous scanner missed it) | `test_dynamic_import_is_absent` | | M19: `[...import("https://…")]` (the previous scanner missed it) | `test_dynamic_import_is_absent` | | M20: `import` U+FEFF `("https://…")` (the previous scanner missed it) | `test_dynamic_import_is_absent` | | M21: a CR LF line continuation in a string, then a URL string and a call | `test_dynamic_import_is_absent` | | M31: the real projection loader replaced by a decoy string, `'import("./projection-index.js")'` | `test_dynamic_import_is_absent` | | M32: the loader's base moved to `new URL("../../", import.meta.url)`, with the old line kept in a comment | `test_dynamic_import_is_absent` | | M10: the test's own `repo-selector.js` count pin relaxed from `==` to `>=` (in a copy of this file) | `test_the_session_transport_stays_out_of_the_fetch_bearing_set` | | M11: the test's own `projection-index.js` count pin deleted (in a copy of this file) | `test_the_session_transport_stays_out_of_the_fetch_bearing_set` | The SCANNER mutants (M22 to M30) each run in a temporary copy of this file, and each is killed by a named regression case: | mutant | the case that goes red | |---|---| | M22: U+2028 and U+2029 dropped from the line ends | `u2028-ends-line-comment`, `u2029-ends-line-comment` | | M23: a lookbehind that skips any dot | `spread` | | M24: U+FEFF dropped | `ufeff-before-paren` | | M25: the member-call skip removed | `member-call-is-not-one`, `optional-member-call-is-not-one` | | M26: string state removed | `slashes-in-string`, `slashes-in-template`, `crlf-continuation-in-string` | | M27: regex-literal state removed | `escaped-slash-then-slash-in-regex`, `in-a-regex` | | M28: the executable reading ignores literals | `in-a-string`, `in-a-template`, `in-a-regex`, `call-beside-a-decoy` | | M29: the loader's base ignores literals | `changed-with-the-old-line-in-a-string` | | M30: the loader's base reads plain assignments only | `a-later-compound-assignment` | DJ's own mutant is the base: the same harness without the `display.js` copy reads `ERR_MODULE_NOT_FOUND` on all five model nodes. ### CI at the head At the head `99508076`, every check passed: - `validate`, run 37553249790: CI's own pytest step reads `triple: selected=1107 passed=1103 skipped=4 failures=0 errors=0`, against `pins: selected>=1099 (margin 8) passed>=1095 (margin 8) skipped==4`. This is the lone CI form, and it is unchanged: `tests/test_renderer.py` is a declared file, so the step never collects it. - SonarCloud Code Analysis. - `copilot-pull-request-reviewer`. ### Copilot Reviews at each head, all requested through the reviewer API: | head | review | verdict | findings | |---|---|---|---| | `f82abd40` | 5433258934 | Changes recommended | 1: the line scan missed `import` + newline + `(` and generator lines (fixed, `19be4997`) | | `19be4997` | 5433357731 | Changes recommended | 1: `//` ends at CR, U+2028 and U+2029 too (fixed, `8081f9ff`, with spread, U+FEFF and CR LF found by audit) | | `8081f9ff` | 5435170341 | Changes recommended | 2: regression tests for the scanner (fixed, `ec1486ca`); rename `test_five_column_collapse_drops_doc_edges` (declined, below) | | `ec1486ca` | 5435232658 | Needs a closer look | None | | `75eb3779` | 5435680993 | Needs a closer look | None | | `a95900c0` | 5435796042 | Changes recommended | 2: prove the ruled loaders are executable calls, and read the loader's base from executable code (both fixed, `781c7917`) | | `99508076` | 5436219525 | Changes recommended | 1: a shadowing `bundleRoot` binding at the import site (an ACCEPTED LIMIT, ruled, below) | **Threads: 7, all answered and resolved, 0 unresolved.** - **The rename, declined (r4200975189).** `test_five_column_collapse_drops_doc_edges` keeps its name. It is one of the 21 nodes that T094's map and T073's declared run account for BY NAME, so a rename would turn a red-to-green flip into a vanished node and a new one. The name still holds: the edges the collapse drops are the source station's edges, built from the snapshot's `document_edges` and checked against `document_links`. Only the column KEY became the role. - **The accepted limit (r4201878108), RULED by the holder** under the convergence rule (`5988818366`) at opensoft/openxFactory#656 comment `6028383410`. The pin is a static, whole-source lexer check, so it cannot resolve scopes. A parameter or inner binding named `bundleRoot` that shadows the base at the import site would not be seen. That payload needs a structural edit of reviewed openDox code, not a simple one. The head's review therefore still reads "Changes recommended" for this one ruled limit. ### Files changed `tests/test_renderer.py`, and nothing else. ### What is NOT done - **The 1 node still red:** SF, which is T104's. T104 is on openDox-code `main` (`d616da3`), and the node clears composed once its openDox pin pair moves. - **A stale comment in a file that is not this slice's:** `src/openxdox/web/views/swb-session.js:9` still says `test_renderer.py:130` pins the set "to five". The set is six now, and the line number has moved. It is a comment, so no test reads it. - **`validate.yml`'s floors are untouched.** `tests/test_renderer.py` is a declared file that the lone CI step never collects, and only T029 raises the floors. 🤖 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>
…s role keys and the served words (plan 038) (#50) Lane: openxfactory-4 (openXfactory-4-openDox_extraction) Authored by lane openXfactory-3, delegated by lane openxfactory-4 (#656 6021862323) Arc: neutral-product-standalone-operability ## T097, display harnesses (B): `display.js` beside the copied module, S7's role keys, the served words (plan 038) - **Contract:** there is no `tasks.md` entry yet; lane 4 records T094's slices after T002 (opensoft/openxFactory#1251). Until then the contract is the slice outline row of T094's map (R2-INV-R9, posted as opensoft/openxFactory#656 comment 6021830607) and the holder's rulings (comment 6021830531). The row reads: **T097, display harnesses (B): DJ (A″) + VR keys; files `tests/test_wheel_model.py`, `tests/test_grouping.py`, `tests/test_project_aggregates.py`; depends on R9-W1; 87 reds (wheel_model 76, grouping 7, project_aggregates 4).** - **Realizes:** requirement 9's declared composed tests (#1144, through T073's composed step 5a, F9.1). This slice repairs 87 of the composed reds T094 mapped. - **Falsifier:** the composed run of the three files, each alone, red at the base and green at the head; plus the unchanged set (12.5's 16 governed suites, F5.2's 5 protected files, `test_column_contributions_governed.py` at 9 passed, `tests/test_declared_exclusion.py` green run lone). - **Ruled:** - **R9-W1 (A″)** (comment 6021830531): each harness copies `display.js` beside the module it copies, as #43 does. No openDox module is made import-free. - **R9-R1 (a)** (same comment): "every word-asserting pin is respelled, through VR, to the SERVED words". It is given under Brett Heap's served-display ruling for the staging suite (comment 6016648451: "the helpers … hand each harness the SERVED governed display"). The holder's record line for this slice (comment 6023517122): "T097's served-display respelling is R9-R1 (a) applied (6021830531 ...). It needs no new ruling." - **Decisions:** none of this slice's own. No After dependency; it needs nothing from T095. ### What this PR does **DJ, R9-W1 (A″).** Since § 3.4 slice S7, `wheel-model.js` and `grouping.js` import `./display.js`. Each harness copied its module ALONE, so node failed with `ERR_MODULE_NOT_FOUND … display.js`. That is the cause of every one of the 87 reds at the base, and of nothing else. Each harness now copies `display.js` beside its module, under its own name (`display.js` imports nothing), and writes a `package.json` so that node reads `.js` as a module, as #43's harness does. `test_wheel_model.py`'s ten copy sites go through one helper, `_copy_wheel_model`. **VR, the keys.** - The model's wheel keys are S7's six stage roles (`WHEEL_KEYS = STAGE_ROLES`). The old wheel names map to them as follows: `documents` → `source`, `clusters` → `grouping`, `possibles` → `candidate`, `staged` → `selection`, `active` → `submission`, `archived` → `completion`. - Every wheel key the cases pass in or the assertions read is respelled: the deck order, edge endpoints, the second-degree and gather cases, the expand events, the 48 action cases, and `test_project_aggregates.py`'s three `actionsFor` calls. - `grouping.js` keys its tallies `"tally:" + role`, so the tally keys are respelled to `tally:source`, `tally:grouping`, `tally:candidate`, `tally:submission` and `tally:completion`. - Snapshot FIELD names (`documents`, `clusters`, `staged_topics`, …) are schema and are unchanged, and so are the action cases' ids. **VR, the words, under R9-R1 (a): the SERVED words.** - **What reads the facet.** Since S7, three things the expanded tile's cases assert come from the display facet: - a verb row's label is `display.act(role)`; - the possibles wheel's promotability matches `display.registerState(...)`; - the packet flyout's labels and its ordered front matter are the facet's artifact axis. - **Where the display comes from.** The page hands every one of them the served display: `wheel.js` puts `display: vocab` in each action env and passes `vocab` to `packetGroups`. So the two harnesses whose cases assert those words or values, the expand harness and the staged harness, are handed the display the GOVERNED host serves. They install it with `readDisplay({ display: cases.display })`, as #43's harnesses do. - The helper `_served_display()` reads the host from the conftest's `governed_host()` (T020), through `display_profile.host_display`'s injected-profile seam. - Nothing is registered, and no conftest or host-plane file is touched. - Composed, the host is openxFactory's composite (`OpenxFactoryProfile`, `host_facet: declared`, `host_profile: openxfactory-engineering`). A probe measured the manifest read this way as equal to the one served when the governed host is registered. - A case that supplies no env keeps none. - **The respelled words, as measured:** | assertion | was | served | |---|---|---| | the staged tile's propose row | `▶ draft proposal` | `▶ Propose` | | the four commission verbs | `▲ promote to staging`, `✻ research brief`, `✦ derive possibles`, `◀ demote` | `▲ Promote to staging`, `✻ Research brief`, `✦ Derive possibles`, `◀ Demote` | | the packet flyout's group labels | `packet`, `spec deltas` | `packet files`, `Spec deltas` | - **The values.** The served `register_state` values (`latent` is the captured role) keep the live-captured possibles fixtures promotable. The served packet order (`proposal.md`, `design.md`, `tasks.md`) keeps the review-order claim. **OQ-R9-3, after T095 (#46).** `test_landed_parses_a_real_archived_change_delta` read `REPO_ROOT.parent.parent / "openxFactory"`, which a runner's layout never holds, so it skipped there. It now reads the composed tree through T095's `openxfactory_root()` (OQ-R9-4) and skips only where the run is not composed. Composed it passes, reading this run's own openxFactory checkout. The skip's mutant is not killable: lone, the module stops at collection on `doc_health` before the case runs. ### The falsifier, composed (R1Q23 (a)), each file alone The composed form: - openXdox-code at the commit named; - openDox installed from openDox-code `main` `84f8ed83` (`pip install -e ".[test]"`, then that commit force-reinstalled); - openxFactory at `92010d3e` (`tests/composed_host_pin.yaml`), with `openDox`, `openXdox` and `openXwallet` initialized recursively and its `scripts/` on `PYTHONPATH`; - the colour variables unset and `TERM=dumb`; - each run: `python -m pytest -q -p no:cacheprovider -rfE --junitxml=… <file> < /dev/null` from the checkout root; - Python 3.12, pytest 8.4.2, Node v24.21.0. T022's placement script is not on `main` (#41 is open). Run from #41's bytes, it refuses at `main` for want of its `.gitignore` line, so nothing was placed. It places only the session runbook, which none of these files reads. **Base, `main` `fc1115d6`:** ``` tests/test_wheel_model.py rc=1 77 failed, 3 passed tests/test_grouping.py rc=1 7 failed, 4 passed tests/test_project_aggregates.py rc=1 4 failed, 8 passed ``` - 88 failed: the map's 87, every one of them on `ERR_MODULE_NOT_FOUND … display.js`, plus `test_wheel_model.py::test_landed_parses_a_real_archived_change_delta`. - That 88th node reads `REPO_ROOT.parent.parent / "openxFactory"`. It runs only because the local clone's layout happens to hold an openxFactory checkout two levels up; on a runner it skips (OQ-R9-3). **Head, `c16c05eb`** (the T097 commits `b401bc0e` and `9a0704a6`, with `main` merged in): ``` tests/test_wheel_model.py rc=0 80 passed tests/test_grouping.py rc=0 11 passed tests/test_project_aggregates.py rc=0 12 passed ``` The 87 read 0 red. The 88th now reads the composed tree (below) and passes; it no longer skips on a runner. ### Mutants (each applied alone, run composed, file restored byte-identical) | mutant | result | |---|---| | no `display.js` copy, `test_wheel_model.py` | killed: 77 failed | | no `display.js` copy, `test_grouping.py` | killed: 7 failed | | no `display.js` copy, `test_project_aggregates.py` | killed: 4 failed | | the neutral display in place of the served one (`"display": None`) | killed: 8 failed (the word and value nodes) | | no `package.json`, each of the three files | killed with node's module-syntax detection off (`NODE_OPTIONS=--no-experimental-detect-module`): 77, 7 and 4 failed. The unmutated head passes in that mode (80, 11, 12). Node 24's detection otherwise reads `display.js` as a module unaided. | | the expand harness hands the display to a case with NO env too | survives, and it is equivalent: with no env, `actionsFor` offers only rows with no `visible` predicate, and every one of those carries a literal label | ### The unchanged set, composed, base `fc1115d6` against head `c16c05eb` Node-for-node identical: 974 nodes at both, the same 10 failed at both, and `diff` empty. - **12.5's 16 governed suites:** 14 green at both (`branch_session` 132, `doxbench_mutation_boundary` 80, `doxbench_share` 34, `gate_loop_views` 74, `gateway_provenance` 24, `hosted_actor` 5, `session_commits` 22, `session_confinement` 53, `session_gates` 81, `session_lifecycle` 53, `session_records` 29, `session_transaction` 57, `session_verbs` 65, `staging_workbench` 83 passed); failing identically at both (open slices own these, not this one): `session_notebook` 1 and `session_runbook` 9. - **F5.2's 5:** `generator` 45, `session_snapshot` 23, `snapshot_determinism` 6, `snapshot_registry` 40 and `snapshot_validation_launch` 9 passed, at both. - **`test_column_contributions_governed.py`:** 9 passed, at both. - **Run lone** (no openxFactory): `tests/test_declared_exclusion.py` 207 passed at both. Each of the three files still stops at collection on its declared reason, `ModuleNotFoundError: No module named 'doc_health'`, at both. - **The lone CI form:** `validate.yml` collects the suite less the declared exclusion, and all three files are declared. So its floors cannot move. ### Files changed - `tests/test_wheel_model.py` - `tests/test_grouping.py` - `tests/test_project_aggregates.py` ### CI and review at `c16c05eb` - `validate`: run 37554225217, success. - Copilot: review 5440546734 at `c16c05eb`, "Needs a closer look", **Findings: None**. Its one note is the merge of current `main` and the composed run after it, which the next section covers. 0 review threads, 0 unresolved. Earlier heads read the same: `b3c2d04e` and `489081e2`, Findings: None, 0 threads. ### NOT done - Nothing in this slice's scope. - `main` has moved past the measured base `fc1115d6`. The branch is not merged again here: the holder's landing loop brings each lane-3 PR up to date (update-branch) before it lands. This PR changes only the three declared test files above, and none of the commits since `fc1115d6` touches them. 🤖 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>






Lane: openxfactory-4 (openXfactory-4-openDox_extraction)
Authored by lane openXfactory-3, delegated by lane openxfactory-4 (#656 6015602254)
Arc: neutral-product-standalone-operability
T026, U-7: the allow-list for 12.5's governed suites, with R-1 (a)'s span kind (plan 038)
The After set has landed:
T020 (T020, U-1: the governed host for the governed suites that drive the gate verbs (plan 038, P4F-5) #39, at c6d15b2). This branch is up to date with
mainf70bc9c, which also holds T024 (T024, U-5: the H-1 shim, ideation_dashboard.session_git answers with opendox.session_git (plan 038, CF-3) #38), T023 (T023, U-4: swb-session.js spells the model's two names at its call sites again (plan 038) #42) and T021 (T021, U-2: the gate console's schemas, each read where its owner keeps it, nothing vendored (plan 038, P4F-4) #40).mainwas merged in at e6d99691, 3226d5c, 9e0979c and 9c29855, never by rebase;T004 (Feature 038: the Speckit specification for release 2 of add-neutral-product-standalone-operability (#1144) openxFactory#1245, at 260234b5);
T005's batch Q (T005: batch Q, the release-2 answers' amendments in #1144 (plan 038) openxFactory#1248, at 91e961a0), which gives 12.5's oracle call
--chains. openxFactorymain'sadd-neutral-product-standalone-operability/tasks.md:3055now readspython3 scripts/protected_suites.py --chains --landings="$(cat "$W/x-arc.txt")" --suites="$(cat "$W/governed.txt")".Realizes: 12.5 (part).
Falsifier (tasks.md): the oracle prints
ok: … each entered and holding; the nodes, composed, quoted.Ruled:
--chains, and T026 lands as one PR.tests/test_staging_workbench.py, edited by T026 in T020's two files once T020, U-1: the governed host for the governed suites that drive the gate verbs (plan 038, P4F-5) #39 landed.tests/test_protected_suite_check.py.group neighbourhood, as measured.What this PR does
32 entries are appended to
tests/protected_suite_respellings.yaml, giving 51 in all. Each is one edit inside its named test or span, with its exact old and new text, and the entries for each suite are chained by blob.test_session_gates.pycmd_gate_*read fromopenxdox.cli_gatetest_session_verbs.pycmd_gate_*4, and Group Wopenxdox.generator.live_topic_healthtest_session_confinement.pyserve_projection.hosted_indextest_doxbench_share.pyopenxdox.contracts.verified_bytes, digest-checked againstcopies.yaml(Copilot's finding)test_staging_workbench.pyThe 19 staging entries, in chain order (allow-list entries 33 to 51):
group neighbourhood.:1291and:1333. Each route is oneexport const …_ROUTEofswb-session.js, and neither the view nor the model names one.span:entries) and three in-test respellings:_CREATE_HARNESS(two entries),_SESSION_HARNESSand_HOSTILE_HARNESS: each imports its route from the column RULED Q3 moved it to (CREATE_ROUTEfromswb-create.js,sessionRoutefromswb-session.js) and the reader fromdisplay.js. Each installssetDisplay(readDisplay({ display: cases.display }))before anything derives, as the shell does.BRAINSTORM_AREAandSTAGING_AREAbecome the model'scapturedArea()andorganizedArea()._run_create,_run_sessionand_hostile_descriptors: each copies the sibling files its harness imports (and what they import), with apackage.jsonthat makes node read them as modules, astest_session_confinement.py's harness does. Each hands its harness/capabilities["display"], by the statementserve.build_server()makes, replayed astest_gate_loop_views.py's_served_displayreplays it.scripts/protected_suites.py, R-1 (a)'s span kind. Anadmittedentry may name, in place oftest, aspan: one module-level constant, or one module-level helper function (its decorators included). The entry'soldtext must lie inside that statement before the landing, and itsnewtext inside it at the landing. Three further rules apply:fororwithtarget, walrus,del,deforclass, an import or a star import, anexcept … asalias, amatchcapture, a type parameter and a parameter.The module's usage block and help now give 12.5's call with
--chains, as batch Q has it.tests/test_protected_suite_check.py: 33 span cases (87 in the module).FLAGGED for the holder's word: three in-test respellings beyond the plan's 17
These are CF-4's kind. T026's measurement reported them at comment 6016415390 (point 2), and comment 6016648451 ruled that point. They close the last three of the suite's nodes, which the served display alone does not reach. Each is entered as a
respellingnaming that history, and each stands or falls on your word:test_gate_off_descriptor_is_the_real_cli_invocation:cli.cmd_gate_create_documentbecomescli_gate.cmd_gate_create_document, imported in the test fromopenxdox.cli_gate. The old spelling raisedAttributeError.test_gate_off_session_affordances_are_the_real_cli_invocations:cli.cmd_gate_edit_document,cmd_gate_open_prandcmd_gate_abandon_sessionbecomecli_gate.…, likewise.test_the_notebook_refresh_is_a_descriptor_in_BOTH_gate_postures:REPO_ROOT / "scripts" / "sync-notebooklm-books.py"becomes the one directory on the import path that holds the script, which is openxFactory'sscripts/in the composed run (R1Q23 (a)). A run that finds it in none, or in more than one, fails. The old path raisedFileNotFoundError.No assertion is weakened in any of the three, and every argument and flag assertion stays.
T020's two files, edited once #39 landed (commit 242889b)
T020's registration has to cover
tests/test_staging_workbench.py. Without it every harness helper refusesProfileNotRegistered, as measured below. The edit is to T020'stests/conftest.pyand to the scan intests/test_host_plane.py:"test_staging_workbench.py"joinsGOVERNED_HOST_SUITES, with a comment giving the reason, kept as a block of its own apart from T021's lines;gateverb spelled as a command line (_GATE_COMMAND = re.compile(r"""["']gate ([a-z][a-z-]*)""")), the way this suite's descriptors spell it. Measured over the 16 governed suites, onlytest_staging_workbench.pymatches it and not the argument-vector spelling.T021 (#40) also edits
tests/conftest.py. Whichever of the two lands second mergesmain.The falsifier
The oracle, in 12.5's call as
mainnow has it (--chains), at a simulated squash landing of this head. The landing is one local commit onmainf70bc9c carrying exactly this branch's tree and theArc:trailer, and it is never pushed. The inputs are 12.5's own:git grep: 16, the same 16;Arc:landings sincee28930bf: 14, T020's, T024's, T023's and T021's among them.rc=0. In the pre-batch-Q form, which passes no
--chains, a landing of this branch readsFAIL: the arc edited protected suites outside the reviewed allow-list: tests/test_doxbench_share.py, …with rc=1. That is why batch Q was ruled.The oracle on mutants of the real list (
--chains), each refused:R-1 (a)'s span guards: 22 mutants of
scripts/protected_suites.py, each run against the committedtests/test_protected_suite_check.py. 21 are killed. M4 survives because it is equivalent: a nested binder also lies inside its compound statement's lines, so the shared-line guard refuses it too. M22, which removes both guards, is killed.The served display, measured in the test process (Brett's (2)+(3): "INFERRED … MEASURE it"). This was an uncommitted probe test, run composed at 3eead0fe (242889b on the integration of that time; the helpers' statement is unchanged since):
ProfileNotRegistered;OpenxFactoryProfile), it readshost_facet: declaredandhost_profile: openxfactory-engineering, with areascaptured: ideation/brainstorm/andorganized: ideation/staging/;displayof a liveGET /capabilitiesfromserve.build_server()under the same registration:EQUAL: True, 3163 bytes of sorted JSON.The nodes, composed, in R1Q23 (a)'s form:
main92010d3e, with its submodules initialized recursively and itsscripts/onPYTHONPATH;TERM=dumb;mainf70bc9c (T020, T021, T023 and T024 landed) as the base, and this head merged onto it on a local branch that is never pushed (0478b5f1).test_host_plane.pytest_protected_suite_check.pymainf70bc9c)main56e1c23 with #41 and #42 merged)test_staging_workbench.py: 37 failed, 46 passed, every failureProfileNotRegistered42 nodes go red to green, none goes green to red, and none is still red.
CI at the head 9c29855
validatesuccess (run 37517336710), SonarCloud success,copilot-pull-request-reviewersuccess.selected=1146 passed=1142 skipped=4 failures=0 errors=0, against the floorsMIN_SELECTED 1099andMIN_PASSED 1095andEXPECT_SKIPPED 4. The holder ruled (lane log, 13:57Z) that T029 raises the floors once, and T020 to T026 leave them.Files changed
scripts/protected_suites.py,tests/protected_suite_respellings.yaml,tests/test_session_gates.py,tests/test_session_verbs.py,tests/test_session_confinement.py,tests/test_doxbench_share.py,tests/test_staging_workbench.py(T026's seven), plus three files the ruling at comment 6016648451 adds to T026's Files:tests/test_protected_suite_check.py, the holder's answer to point 4;tests/conftest.pyandtests/test_host_plane.py, Brett's points 2 and 3, edited once T020, U-1: the governed host for the governed suites that drive the gate verbs (plan 038, P4F-5) #39 landed.What remains, and its trigger
mainmoves before landing, the lander merges it, never by rebase.🤖 Generated with Claude Code