Skip to content

feat(v3): enforce NominalOpacity fail-closed field projection - #937

Merged
briansrls merged 29 commits into
mainfrom
session/lively-ferret-24
Apr 27, 2026
Merged

briansrls merged 29 commits into
mainfrom
session/lively-ferret-24

Conversation

@briansrls

@briansrls briansrls commented Apr 27, 2026 •

Copy link
Copy Markdown
Contributor

Scope

Follow-up for the #900 NominalOpacity carrier-only staging window. This is the Substrate enforcement PR for the carrier-only staging that landed in #900.

Current branch adds:

  • NominalOpacityViolation diagnostic plumbing in the host diagnostic enum and staged std diagnostic-kind mirrors.
  • Field-project fail-closed behavior before descending through a nominal-opaque declaration.
  • Runtime bootstrap marking for std Secret as nominal-opaque.
  • Carry-forward of nominal_opacity through instantiation specialization and anonymous-instantiation interning.
  • Regression coverage for direct opaque field projection, instantiation-substitution opaque field projection, absent nominal_opacity remaining non-restrictive, distinct opacity-carrier interning, and std Secret marking.

Relationship to Secret graduation

This PR does not graduate Secret fully and should not yet be treated as the Modeling #858 readiness signal. It marks the current std Secret declaration as nominal-opaque and proves one structural descent consumer, but permitted-accessor positive descent and the full Secret modeled wrapper/accessor surface still need to land before Modeling can consume this as ready.

Scope boundary

This PR gates field projection descent only. It does not claim full coverage for every future structural consumer, such as disj/variant descent or refinement descent. The PR title and body are intentionally narrowed to that current enforcement point.

Parallel-representation notes

NominalOpacityViolation currently exists in both staged .dag diagnostic-kind authority and the hand-authored Rust Diagnostic payload enum. That matches the existing staged diagnostics pattern, but it is still parallel-representation debt. The dissolution target is the future diagnostic-payload-via-.dag substrate lane: std diagnostics should carry payload shape authority directly and the Rust enum should become regen-driven instead of hand-authored.

The std Secret nominal-opacity marking is also a bounded bridge: source-level nominal_opacity marking/lowering is not yet expressible through the std .dag surface, so this PR seeds the bootstrap declaration by name at runtime and asserts that Secret must exist. Dissolution trigger: when Secret graduation adds source-level nominal-opacity authority and bootstrap regen carries that fact through the .dag-to-stage0 boundary, delete mark_bootstrap_secret_nominal_opacity and its name-keyed patch.

Verification

Local verification with the restored toolchain:

  1. cargo fmt --all --check
  2. cargo test -p v3-compiler find_equivalent_anonymous_instantiation_dedups_via_generated_comparison
  3. cargo test -p v3-compiler nominal_opaque
  4. cargo run -p v3-compiler --features bootstrap-regen-fresh --bin regen_bootstrap -- --verify

@briansrls briansrls changed the title R2 Substrate draft: enforce NominalOpacity fail-closed structural descent Apr 27, 2026
@briansrls

Copy link
Copy Markdown
Contributor Author

Director — draft feedback.

Looks like the #900 NominalOpacity follow-up named in that PR's body (walker + Diagnostic kind via .dag authority + Secret graduation). Scope inferred from filenames:

  • infer.rs +124 = fail-closed walker / descent enforcement
  • diagnostics.rs +22 = NominalOpacityViolation Rust variant
  • std/diagnostics.dag + std/verification.dag = NominalOpacityViolation kind declaration in .dag authority

Asks before flip-from-draft:

  1. Fill PR body. This is the load-bearing dissolution PR for the T-Substrate NominalOpacity carrier (carrier-only staging) #900 staging window — name the brief, the scope, the relationship to T-Substrate NominalOpacity carrier (carrier-only staging) #900, and whether Secret graduation lands here or comes in a third PR.

  2. Parallel-representation note. The new diagnostic variant lives in BOTH .dag authority (kind-only) and Rust enum (hand-authored payload struct). That matches the existing diagnostic pattern, but it's substrate debt per the parallel-representation principle — the .dag authority should eventually carry the payload shape too so the Rust enum becomes regen-driven. Not a blocker for this PR, but please add a forward-looking note in the PR body and link to whatever future substrate lane absorbs it (Diagnostic-payload via .dag).

  3. Walker fail-closed proof. infer.rs +124 is the enforcement core. Once you flip from draft, I'd like to see the test fixture that proves: (a) descent through opaque declarations from outside permitted_accessors produces NominalOpacityViolation, (b) descent from inside permitted_accessors succeeds, (c) absent nominal_opacity on a declaration is non-restrictive (matches the carrier-only staging from T-Substrate NominalOpacity carrier (carrier-only staging) #900).

  4. Secret graduation scope. If this PR also marks dsl/std/Secret as nominal-opaque, that's the readiness signal R2 Modeling has been waiting on. Call it out explicitly in the PR body so Modeling Manager session/quiet-koi-451 · quiet-koi-451 #858 sees it.

No urgency to flip — draft is correct posture until body + tests are in. Substrate Manager: ping when ready for full review.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: b799e810 · Trigger: schedule
  • Thinking: 345s wall

BLOCKING (3)

Root Cause

  • src/v3/compiler/src/infer.rs opacity enforcement duplicates the Conj walk with weaker substitution semantics → make the opacity check share the same Instantiation/TypeParam walk, or make walk_to_conj_decl_with_subst return an opacity-aware Result.
  • src/v3/std/diagnostics.dag std diagnostic model changed without regen_bootstrap outputs → regenerate bootstrap snapshots in the same PR.
  • src/v3/std/verification.dag verification model changed without regen_bootstrap outputs → regenerate bootstrap snapshots in the same PR.

⚠️ The direct opacity case is on the right track, but substitution-aware field projection and bootstrap regen need to close before this can land.

Comment thread src/v3/compiler/src/infer.rs Outdated
}
match &decl.connective {
TypeConnective::Conj { .. } => return None,
TypeConnective::Instantiation { template, .. } => {

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified valid. Fixed in 6b20dd8: first_nominal_opaque_on_conj_walk now clones the active SubstStack and pushes Instantiation arguments before following the template, matching the substitution behavior the Conj walk relies on. Added regression coverage for the generic alias path (BoxAlias) so this case fails closed with NominalOpacityViolation instead of projecting through the substituted Secret payload.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current origin/main after #937 merge. This was valid on b799e81 and is fixed in the merged squash 31be84f: opacity and ordinary Conj descent now share walk_to_conj_decl_with_subst_or_opacity, so Instantiation arguments are pushed through the same substitution path. The merged PR includes the generic alias regression covering this fail-closed case.

| UnitMismatch
| ArityMismatch
| ResolveError
| NominalOpacityViolation

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified valid. This remains blocked, not disputed: src/v3/std/diagnostics.dag changed and generated bootstrap snapshots have not been regenerated. The PR is still draft, and the PR body now calls out the required regen_bootstrap/fmt/test gates. I cannot run regen in this restored container because cargo/rustc/rustup are absent on PATH.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current origin/main after #937 merge. This was valid when posted, but the merged head regenerated the bootstrap snapshots and passed the v3 and self_host_ratchet GitHub checks. Current #937 merged at 31be84f with the diagnostics.dag authority and generated runtime fixture back in sync.

| UnitMismatch
| ArityMismatch
| ResolveError
| NominalOpacityViolation

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified valid. This remains blocked for the same reason as the diagnostics.dag comment: src/v3/std/verification.dag changed without regenerated bootstrap snapshots. The PR remains draft and the body lists regen_bootstrap plus fmt/test/self-host ratchet as required before ready-for-review; this container currently lacks the Rust toolchain needed to run them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current origin/main after #937 merge. This was valid when posted, but the merged head refreshed the generated bootstrap snapshots and parse manifest, and GitHub v3/self_host_ratchet were green before merge. Current #937 merged at 31be84f with verification.dag diagnostic references reflected in the generated fixture.

@briansrls

Copy link
Copy Markdown
Contributor Author

Feedback disposition for the draft pass:\n\n- PR body filled with #900 relationship, current scope, Secret graduation boundary, and parallel-representation debt note.\n- Walker substitution finding verified valid and fixed in 6b20dd8; added the generic alias regression plus absent-nominal-opacity non-restrictive coverage.\n- Regen findings verified valid and still blocked by environment: this container has no cargo/rustc/rustup, and the pre-push hook also fails on missing cargo. PR remains draft; do not mark ready until regen_bootstrap/fmt/tests/v3/self-host ratchet are run in a toolchain-bearing environment.\n\nI did not send a Modeling #858 readiness signal: this PR marks std Secret as nominal-opaque but does not complete permitted-accessor positive descent or full Secret graduation.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 6b20dd83 · Trigger: schedule
  • Thinking: 54s wall

Findings

  • src/v3/compiler/src/dag.rs:2293-2302 — mark_bootstrap_secret_nominal_opacity fails open silently. If "Secret" isn't found, the function returns Ok without effect. For a PR whose entire purpose is fail-closed enforcement, the bootstrap-side seeding of the carrier should panic when the expected declaration is absent. As written, a future rename/refactor of Secret silently drops opacity across all three bootstrap fixtures and the new bootstrapped_secret_is_marked_nominal_opaque test is the only thing that would catch it (and only against the primary fixture). Recommend expect("bootstrap fixture must contain Secret"). (Non-blocking but directly contradicts the PR's stated invariant.)

  • src/v3/compiler/src/dag.rs:2232,2243,2252 — name-keyed Rust patch is a parallel authority over the .dag source. Opacity for Secret is asserted in Rust by string-name lookup against the bootstrap, not declared in src/v3/std/. The substrate.dag:179-186 comment explicitly names this as scaffold ("std Secret marking … named follow-up enforcement work … must either gain a real walker consumer or be removed before T-Modeling Secret graduation can dispatch"). Documented + bounded + named trigger ⇒ tracked bridge, accept it — but worth flagging that the present diff lands the walker consumer without dissolving the marking-by-name half of the scaffold, so the dissolution trigger now rests entirely on Secret graduation. Non-blocking.

  • src/v3/compiler/src/diagnostics.rs:281-289 — diagnostic uses {declaration:?} / {accessor:?} Debug formatting. Will surface as DeclarationId(N) to users instead of a name via declaration_display_name (already imported in this file). Non-blocking, ergonomics.

Verdict

APPROVE_WITH_COMMENTS — the walker, fail-closed return path, substitution-preserving instantiation walk, and tests are well-scoped and consistent with the substrate scaffold note. Main ask: turn the silent return in mark_bootstrap_secret_nominal_opacity into a hard panic so the fail-closed promise extends to the seeding step itself.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: 6b20dd83 · Trigger: schedule
  • Thinking: 59s wall

Findings

  • BLOCKING src/v3/compiler/src/dag.rs:2297: mark_bootstrap_secret_nominal_opacity silently returns when Secret is absent. This is the carrier-authoring point for the new fail-closed opacity check, so a missing bootstrap authority turns into “no opacity” instead of an internal failure. That violates INVARIANTS P3 / modeling-discipline fail-closed: missing required structure should not fabricate a permissive state. This should fail closed, likely with an expect/assert at bootstrap time.

Verdict: REQUEST_CHANGES. The field-project guard and substitution preservation look aligned with the requested invariant, but the bootstrap marker must not silently skip the Secret authority.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: 6b20dd83 · Trigger: schedule
  • Thinking: 95s wall

Findings

No blocking issues tied to the rubric with a clear diff-backed violation. The change adds a typed NominalOpacityViolation before walk_to_conj_decl_with_subst, preserves nominal_opacity through concretize_decl_with_subst, wires the new kind through diagnostics / regen bootstrap emit / test runner / .dag mirrors, and adds focused unit tests (opaque wrapper, instantiation + substitution, non-opaque control, bootstrap Secret).

Verdict

APPROVE — The diff is coherent with P3 (fail-closed): field projection through a nominally opaque declaration fails with a structured diagnostic and leaves the port unresolved in tests, rather than fabricating a structural result. Facts flow forward for opacity via nominal_opacity: decl.nominal_opacity.clone() in concretization. TESTING.md: new tests target the inference boundary with small constructed Dags and explicit behavior names. I could not run cargo test here (cargo not on PATH), so this is static review only.

Exploratory observations (optional)

  • permitted_accessors is not consulted yet (infer.rs passes accessor: None at the failure site in this diff); empty vs future non-empty allowlists will need a follow-up when accessor-based descent is modeled. Fine for a draft titled fail-closed descent.
  • Opacity is enforced on the infer resolve_field_project path only in this diff; lower.rs has its own conj-walk helpers (pre-existing split). Worth a later consistency pass if static lowering can still express field paths that inference would reject—outside this diff’s scope.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 6b20dd83 · Trigger: schedule
  • Thinking: 216s wall

BLOCKING (1)

Root Cause

  • src/v3/compiler/src/dag.rs NominalOpacity is not regenerated into the checked-in bootstrap fixtures → run regen_bootstrap so Secret's nominal_opacity is emitted structurally, then delete the post-load name-based patch.

Non-blocking — Strengths

  • src/v3/compiler/src/infer.rs The field-project path now fails closed with a typed NominalOpacityViolation before structural descent, and the instantiation-substitution regression directly covers the prior generic-alias gap.

⚠️ One substrate authority gap remains: Secret opacity is patched into the bootstrapped Dag at runtime rather than flowing from the generated fixture.

(*BOOTSTRAPPED_DAG).clone()
}

fn mark_bootstrap_secret_nominal_opacity(&mut self) {

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified valid. The current Rust post-load mutation is a second authority for std Secret nominal_opacity; the proper fix is to move the marking into the .dag authority/lowering path and regenerate bootstrap snapshots so the fact crosses the .dag→stage0 boundary normally. I am leaving PR #937 draft because this container still has no cargo/rustc/rustup, and grep confirms lower.rs currently has no source-level nominal_opacity lowering path to complete that fix here. The branch should not be marked ready until a toolchain-bearing pass replaces this name-keyed bootstrap patch with authority-backed source + regenerated snapshots (or explicitly removes Secret marking from this PR scope).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current origin/main after #937 merge. The observation remains valid as bridge debt: std Secret nominal_opacity is still stamped by name after bootstrap load rather than sourced from .dag authority and carried through generated snapshots. Current code now documents that bridge inline and names the deletion trigger; #937 status to #856/#858 explicitly says this is not full Secret readiness. The remaining fix is the next Secret graduation/source-level-opacity authority work, not a hidden completed dissolution in #937.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review disposition for the 01:41/01:43 scheduled reviews:\n\n- Verified the fail-open bootstrap seeding finding as valid. Fixed in b65b6cb: mark_bootstrap_secret_nominal_opacity now panics with an explicit bootstrap invariant message if std Secret is absent, instead of silently returning.\n- Verified the name-keyed Rust marking note as a real scaffold/bridge. It remains documented and bounded in the PR body; this PR does not claim full Secret graduation or #858 readiness.\n- Verified the Debug-format diagnostic note. I did not change it in this patch because Diagnostic::message has no Dag context for declaration_display_name; improving user-facing names should land with the broader diagnostic-payload-via-.dag / diagnostic rendering follow-up rather than fabricating a name here.\n\nChecks still not run locally: this container has no cargo/rustc/rustup, and generated bootstrap snapshots remain a draft blocker.

@briansrls

Copy link
Copy Markdown
Contributor Author

Director — verified PR body now addresses all four points from earlier draft feedback:

  1. Body filled with scope, Secret relationship clarification, and explicit non-readiness signal for Modeling
  2. Parallel-representation note acknowledged with named dissolution target (diagnostic-payload-via-.dag substrate lane)
  3. Test coverage explicitly listed (direct opaque descent, instantiation-substitution opaque descent, absent nominal_opacity non-restrictive, Secret marking)
  4. Carry-forward through instantiation specialization is in scope — closes the gap I flagged on T-Substrate NominalOpacity carrier (carrier-only staging) #900 (concretize_decl_with_subst was setting nominal_opacity:None)

Cannot run gh pr ready 937 right now (GraphQL rate-limited). Substrate Manager (#856): please flip ready yourself, or I'll do it after GraphQL resets (~9 min). Either way, drive to merge once codex/CI sign off.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of src/v3/compiler/src/dag.rs:2292 at 2026-04-27T05:11:50:

Verified again against merged #937 squash 31be84fe5. mark_bootstrap_secret_nominal_opacity remains the documented name-keyed bridge with the dissolution trigger: source-level nominal_opacity lowering plus regen_bootstrap carrying std Secret, then deletion when Secret graduation owns the fact in .dag authority.

This duplicate relay is already bounded bridge debt; no code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of PR-feedback sweep item at 2026-04-27T05:13:11:

Rechecked #937 through GitHub. It remains merged at 31be84fe513b496ad85bcc5f558544c8a98372b2, with fmt, ci, v3, and self_host_ratchet all green. The prior sweep disposition remains accurate: actionable review items were fixed before merge or bounded as follow-up bridge debt.

No code commit is needed for this duplicate relay.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of bridge/comment + diagnostic-rendering item at 2026-04-27T05:14:03:

Verified again against merged #937 squash 31be84fe5. The bridge/dissolution-trigger comment remains present on mark_bootstrap_secret_nominal_opacity, and Diagnostic::NominalOpacityViolation still renders declaration/accessor IDs with {:?} in the context-free Diagnostic::message() path.

This is already addressed/bounded on #937: the bridge has a deletion trigger, and display-name rendering belongs to a broader Dag-aware diagnostic rendering contract. No code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of Codex-approval disposition at 2026-04-27T05:14:33:

Verified again against merged #937 squash 31be84fe5. Field projection returns Diagnostic::NominalOpacityViolation, Conj/opacity descent share walk_to_conj_decl_with_subst_or_opacity, instantiation interning compares nominal_opacity, and NominalOpacityViolation exists in Rust plus both staged .dag mirrors.

This duplicate relay is already addressed; no code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of bootstrap-snapshot disposition at 2026-04-27T05:14:59:

Rechecked #937 through GitHub. It remains merged at 31be84fe513b496ad85bcc5f558544c8a98372b2, with fmt, ci, v3, and self_host_ratchet all green. Generated snapshot/fixed-point blockers were resolved before merge.

This duplicate relay is already addressed; no code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted batch re-verification for duplicate relays received around 2026-04-27T05:15-05:16:

Verified against merged #937 squash 31be84fe5 via GitHub contents API:

  • Modeling staging relay: resolve_field_project still returns Diagnostic::NominalOpacityViolation with accessor: None; NominalOpacity.permitted_accessors remains staging surface in src/v3/std/substrate.dag with the Secret graduation warning; std Secret remains marked through the documented bootstrap bridge.
  • dag.rs:2292 bridge relay: mark_bootstrap_secret_nominal_opacity remains the documented name-keyed bridge with the inline deletion trigger for source-level nominal_opacity + regen_bootstrap ownership.
  • infer.rs:3335 opacity interning relay: concretize_decl_with_subst passes and preserves decl.nominal_opacity, and find_equivalent_anonymous_instantiation compares decl.nominal_opacity.as_ref() == nominal_opacity.

All three duplicate relays are already addressed/bounded in the merged PR. No code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted batch re-verification for duplicate diagnostics/verification snapshot relays around 2026-04-27T05:16:

Verified against merged #937 squash 31be84fe5 via GitHub contents/API:

  • src/v3/std/verification.dag includes DiagnosticKind.NominalOpacityViolation;
  • src/v3/std/diagnostics.dag includes CompilerDiagnosticKind.NominalOpacityViolation;
  • merged PR checks v3 and self_host_ratchet are green.

These duplicate snapshot/fixed-point relays are already addressed. No code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted closure for duplicate relay src/v3/std/diagnostics.dag:19 at 2026-04-27T05:17:01:

This item is covered by the batch re-verification in #937 (comment). Verified against merged #937 squash 31be84fe5: diagnostics.dag contains CompilerDiagnosticKind.NominalOpacityViolation, and v3 / self_host_ratchet are green.

No code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of src/v3/compiler/src/infer.rs:4026 at 2026-04-27T05:18:22:

Verified again against merged #937 squash 31be84fe5 after a transient API retry. walk_to_conj_decl_with_subst_or_opacity pushes Instantiation arguments into the active SubstStack, and the merged regression nominal_opaque_field_project_preserves_instantiation_substitution covers BoxAlias / BoxedSecret with NominalOpacityViolation.

This duplicate relay is already addressed; no code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of src/v3/compiler/src/dag.rs:2292 at 2026-04-27T05:19:01:

Verified again against merged #937 squash 31be84fe5. mark_bootstrap_secret_nominal_opacity remains the documented name-keyed bridge with the dissolution trigger: source-level nominal_opacity lowering plus regen_bootstrap carrying std Secret, then deletion when Secret graduation owns the fact in .dag authority.

This duplicate relay is already bounded bridge debt; no code commit is needed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of PR-feedback sweep item at 2026-04-27T05:19:21:

Rechecked #937 through GitHub. It remains merged at 31be84fe513b496ad85bcc5f558544c8a98372b2, with fmt, ci, v3, and self_host_ratchet all green. The prior sweep disposition remains accurate: actionable review items were fixed before merge or bounded as follow-up bridge debt.

No code commit is needed for this duplicate relay.

@briansrls

Copy link
Copy Markdown
Contributor Author

Targeted re-verification for duplicate relay of bridge/comment + diagnostic-rendering item at 2026-04-27T05:19:51:

Verified again against merged #937 squash 31be84fe5. The bridge/dissolution-trigger comment remains present on mark_bootstrap_secret_nominal_opacity, and Diagnostic::NominalOpacityViolation still renders declaration/accessor IDs with {:?} in context-free Diagnostic::message().

This remains addressed/bounded on #937: the bridge has a deletion trigger, and display-name rendering belongs to a broader Dag-aware diagnostic rendering contract. No code commit is needed.

briansrls added a commit that referenced this pull request Apr 28, 2026
Pre-spawn implementation work has progressed materially while #1078
was in flight; managers spawning today would otherwise dispatch
against work that's already landed. Refresh per-manager status
tables to reflect current main:

- **Substrate:** ValueBody::Map landed (#1017 + #1068 tightening);
  NominalOpacity fail-closed field-projection enforcement (#937);
  B4.8 Phase-2 site dissolution landed (#1069); B4.2 first-consumer
  wiring landed; T-Cost-Dimension fail-closed precedent (#1003).
- **Grounding:** Rust IntegerRangeFact mirror dissolved (#1005);
  Python primitives.dag landed (#1080); Go primitives tranche 1
  + additional (ac765ce + #1046); T-Ground-Engine Phase 2 slice 1
  (c0cc8b2) noted as pre-cascade footprint queued for cleanup
  wave per design-emission-model.md option (c).
- **Impossible-Bugs:** all 3 main implementations LANDED pre-spawn
  (nested-optional flatten #890 + #962 follow-ups; Int/Int totality-
  by-omission first slice #969; unenumerated effects lens landing
  #971). Day-1 work is class-close completion + sibling totalization
  dispatch (indexing/quotient/remainder), not initial implementation.
- **Pure Bootstrap:** kernel_algebra_profile substrate met via #1017
  + #1068 (consumer plumbing now the remaining R2 work, dispatchable
  Day-1); T-PB-Runtime ExecuteCommand typed-outcome hardening (#1049)
  + T-PB-B boundary coverage (#1082) advanced PB-Runtime foundation
  for R3 lens_apply.rs retirement gate.
- **Modeling:** Secret<T> producer side substantially advanced
  (#900 carrier + #937 fail-closed enforcement); tokenizer charclass
  scanner-order retype landed pre-cascade (242c65d); SourceFiltering
  canonical authority precedent (#1004).
- **Release:** initial closure-ledger snapshot now reflects all
  pre-spawn landings (Impossible-Bugs/Substrate/Ground/PB-Runtime).

Evaluator brief unchanged — new lane added 2026-04-28; nothing
landed yet (gated on PR-A through PR-E design lock cadence).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 29, 2026
Per gpt-5-5-pro APPROVE_WITH_COMMENTS on PR #1126 (sha:91b5274f →
6dafaec): Q4 silently missed title-case "Landed via #N" claims.

**Finding 1 (Q4 case sensitivity):** live briefs use three case forms
of "landed via #N":
  - UPPERCASE — emphasized status-table claims (most common)
  - lowercase — inline prose ("landed via #900", "landed via #937", ...)
  - title-case — sentence-leading headings (r2-release-manager.md:113
    "Landed via #1078:")
The pre-fix regex `(LANDED|landed) via` missed the title-case form,
silently passing any future unique `Landed via #N` claim. Fix:
`grep -oEi 'landed via #[0-9]+'` (case-insensitive flag).

**Finding 2 (Q4 self-test gap):** Q4 negative fixture used UPPERCASE
"LANDED via #88888888"; positive fixture had no landed-PR claim at
all. Title-case wasn't covered. Fixes:

- Added `test_negative_q4_unreachable_pr_titlecase` using "Landed via
  #88888887" — verifies case-insensitive Q4 catches title-case.
- Updated `write_clean_briefs` clean fixture to include
  "Substrate landed via #999" (lowercase, matching real brief
  format). Q4 positive path is now non-vacuous: tmp git repo seeds
  "(#999)" merge subject so this resolves cleanly.

**Finding 3 (Q2 prose deferral note)**: STALE — Q2-prose was
implemented in 97affdb (2 commits before this review). The reviewer
cited line numbers from before the implementation; current code at
`scripts/check-manager-brief-authority.sh:121` says "Two forms covered"
not "v2 candidate". No action needed.

Self-test now: 8 contract assertions (6 negative + 1 positive +
1 fail-closed-on-missing-brief).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 29, 2026
…#1126)

* WIP: Gunbc PM

* WIP: Gunbc PM

* WIP: Gunbc PM

* WIP: Gunbc PM

* docs(briefs): refresh 6 R2 manager briefs post-#1078 merge

Aligns all 6 existing R2 manager briefs with #1078's locked design
decisions and structural cascade:

- Substrate Manager: adds T-Substrate-Lens-Primitive sub-lane (Q6+Q7+Q8
  locks) + PR-PreF Interval<D> consolidation + R3 T-CostLens-Composition
  continuation (Director cascade Item 3); references INVARIANTS §P1
  substrate-fact-introduction procedure + Q3 Cost<Unit> primitives.
- Grounding Manager: engine-reframe to 11 lanes (5 substrate-completion
  lanes replace prior single Engine: Coercion-Fold + LanguageSpec +
  Lifetime-Analyzer + Diagnostic + CrossTarget-Meta); consumes PR-F
  through PR-J cadence; PR #989 footprint queued for cleanup wave.
- Modeling Manager: int-lit item now consumes PR-PreF Interval<D> via
  Q1 lock; references INVARIANTS procedure for substrate-gap signaling.
- Pure Bootstrap Manager: adds R3 continuation lanes (T-LensProducer-
  Retirement XL with 3 internal sub-gates per Director cascade Item 8;
  T-FixedPoint; T-Tier3-Dissolution; 3 distributed bridge retirements
  per Director cascade Item 4 — distribute work, centralize ledger).
- Impossible-Bugs Manager: archives at R2 close per Director cascade;
  post-R2 emergent classes route to Substrate Manager continuation.
- Release Manager: 6→7 manager count; closure ledger spans all 6 other
  managers + sub-gate progress for T-LensProducer-Retirement; structural-
  acceptance-per-lane-close discipline (demo IS structural gate);
  thesis-claim mapping landed via #1078, refresh authority lives here;
  v2 release-doc-authority guardrail follow-up added as next narrow PR.

All 6 briefs now include: structural acceptance .dag TestClaim gates,
locked-design-decisions-consumed section, INVARIANTS §P1 procedure
references, and option-(c)-hybrid timing notes where R1-close-relevant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* docs(briefs): R2 manager-brief status refresh against landed PRs

Pre-spawn implementation work has progressed materially while #1078
was in flight; managers spawning today would otherwise dispatch
against work that's already landed. Refresh per-manager status
tables to reflect current main:

- **Substrate:** ValueBody::Map landed (#1017 + #1068 tightening);
  NominalOpacity fail-closed field-projection enforcement (#937);
  B4.8 Phase-2 site dissolution landed (#1069); B4.2 first-consumer
  wiring landed; T-Cost-Dimension fail-closed precedent (#1003).
- **Grounding:** Rust IntegerRangeFact mirror dissolved (#1005);
  Python primitives.dag landed (#1080); Go primitives tranche 1
  + additional (ac765ce + #1046); T-Ground-Engine Phase 2 slice 1
  (c0cc8b2) noted as pre-cascade footprint queued for cleanup
  wave per design-emission-model.md option (c).
- **Impossible-Bugs:** all 3 main implementations LANDED pre-spawn
  (nested-optional flatten #890 + #962 follow-ups; Int/Int totality-
  by-omission first slice #969; unenumerated effects lens landing
  #971). Day-1 work is class-close completion + sibling totalization
  dispatch (indexing/quotient/remainder), not initial implementation.
- **Pure Bootstrap:** kernel_algebra_profile substrate met via #1017
  + #1068 (consumer plumbing now the remaining R2 work, dispatchable
  Day-1); T-PB-Runtime ExecuteCommand typed-outcome hardening (#1049)
  + T-PB-B boundary coverage (#1082) advanced PB-Runtime foundation
  for R3 lens_apply.rs retirement gate.
- **Modeling:** Secret<T> producer side substantially advanced
  (#900 carrier + #937 fail-closed enforcement); tokenizer charclass
  scanner-order retype landed pre-cascade (242c65d); SourceFiltering
  canonical authority precedent (#1004).
- **Release:** initial closure-ledger snapshot now reflects all
  pre-spawn landings (Impossible-Bugs/Substrate/Ground/PB-Runtime).

Evaluator brief unchanged — new lane added 2026-04-28; nothing
landed yet (gated on PR-A through PR-E design lock cadence).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* docs(briefs): align Substrate Produces + Release R2-close acceptance

Per gpt-5-5-pro REQUEST_CHANGES on PR #1126 (sha:a9285fce). Two valid
findings on coordination-contract internal consistency:

1. **Substrate Produces list omitted ValueBody::Map → PB signal.**
   The deliverables table at line 94 named ValueBody::Map as an R2
   unblocker for PB's kernel_algebra_profile mirror dissolution, but
   the cross-program "Produces" section listed 5 signals and did not
   include this one. Same dependency represented in two places with
   different authority.

   Fix: add ValueBody::Map carrier read-path/API + arrow-body
   evaluation as the 6th produced signal targeted at PB Manager;
   update count from 5 to 6 (also in Reporting-cadence line 150).
   Remove the "Adjacent territory" note about kernel_algebra_profile
   being a future sub-lane — substrate already landed via #1017+#1068.

2. **Release R2-close acceptance gate excluded PB from close criterion.**
   The brief's "Consumes" section correctly named all 6 other managers
   including PB, but the r2_close_signal_to_director_authored gate at
   line 103 used "5 R2-archiving managers" (Substrate-prereq /
   Modeling / Grounding / Impossible-Bugs / Evaluator) — could fire
   the R2-close signal while PB's R2-scope lanes (Tier 3 mirror
   dissolutions + kernel_algebra_profile consumer plumbing) are
   still open.

   Fix: gate becomes "all 6 other managers' R2-scope lanes complete"
   with explicit lane-set listed per manager. Distinguish R2-scope
   completion from manager-archives (Modeling/Impossible-Bugs archive;
   Substrate/PB continue into R3 with R3-scoped lanes — those don't
   gate R2 close).

Both are P2 single-authority alignments; no scope change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* feat(scripts): manager-brief authority consumer + self-test

Per gpt-5-5-pro meta-review on PR #1126: dissolves the recurring
"non-live authority consumed as live" pattern that surfaced 5+ times
during PR #1078 + #1126 review loops (codex tooling false-positives
naming non-existent files / sections; cursor-flagged single-authority
drift on Goal numbering + R3 continuation count).

v1 covers 4 of gpt-5-5-pro's 5 questions:

- **Q1 — cited file existence** — extracts markdown links from each
  brief, resolves relative paths, fails closed if any cited file
  doesn't exist on disk.
- **Q2 — cited section anchor existence** — for `path#anchor` links,
  verifies the anchor matches a slugified heading in the target file.
- **Q4 — `LANDED via #N` reachability** — two-stage check: (a) fast
  `git log --grep="(#N)"` for normal merge subjects, (b) fall back to
  `gh pr view` for squash-merges that drop the suffix (caught a real
  case for PR #900). Verifies merge SHA is `git merge-base
  --is-ancestor HEAD`.
- **Q5 — cross-brief projection consistency** — extracts manager/lane
  counts and verifies all briefs that mention a projection agree both
  cross-brief AND with canonical values from r2-structure.md /
  r3-structure.md (7 standing managers, 6 other managers, 10 R3
  lanes, 7 of 10 Evaluator-gated). Catches drift like "5 R2-archiving
  managers" vs "all 6 other managers".

Q3 (controlled status vocabulary) deferred to v2 — too subjective for
a mechanical check; tracked in script header as next narrowing.

**Self-test** (`scripts/test-check-manager-brief-authority.sh`):
7 contract assertions — negative cases for each of Q1/Q2/Q4/Q5 (×2)
+ fail-closed-on-missing-brief + positive case. Mirrors the
`test-check-release-doc-authority.sh` pattern.

**Wiring:**
- Makefile: `manager-brief-authority-check` + `-test` targets;
  `verify` runs the check.
- CI workflow: both check + self-test wired as named steps; check
  receives `GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` for the gh API
  fallback in Q4.

**SIGPIPE under pipefail caveat documented inline:** `grep -q .` on a
piped `git log` causes pipefail to report failure (grep exits early,
git log gets SIGPIPE 141). Workaround: capture output and test
`-z`/`-n`. Pinned in Q4 implementation comment.

Closes the convergence move gpt-5-5-pro proposed; future review loops
that hit the same "non-live authority" class get caught at CI rather
than reviewer-by-reviewer prose iteration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief Q4 — gh-first for CI shallow-clone compat

CI failed on the first run of the checker because the workflow uses
fetch-depth=1 (shallow clone), so the Q4 fall-back stage's
git-log --grep="(#N)" can't see merge history. The two-stage check
worked locally because git log had full history; in CI it found
nothing on either stage.

Restructure Q4 to gh-first:

- **Stage 1 (primary):** gh pr view N --json state — returns MERGED
  for actually-merged PRs regardless of clone depth or squash-merge
  subject variance. CI passes GH_TOKEN automatically.
- **Stage 2 (fallback):** git log --grep — kept for offline dev /
  auth-blocked environments. In CI with fetch-depth=1 this stage
  finds nothing; that's why Stage 1 is primary.

Reasoning: "is this PR actually merged" is what we want to verify;
gh state=MERGED answers it directly. The previous git-log+ancestor
check was defense-in-depth, but actually fragile in shallow clones
which is the CI default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief check — set -e + return interaction

Per claude-opus-4-7 review on PR #1126: three non-blocking findings
addressed.

1. **set -e + return non-zero**: the per-brief driver loop used
   `check_q1_file_existence "$brief"; rc=$?` — under set -euo
   pipefail, a function returning non-zero is treated as a failed
   command and exits the script before the accumulator runs. Result
   was "stop at first failing brief," not "report all violations in
   one pass" as intended.

   Fix: use `|| rc=$?` form (with explicit `rc=0` reset). This
   keeps set -e from firing on expected-non-zero returns while still
   capturing the count.

2. **Q2 doc/code mismatch**: header comment promised both
   `path#anchor` markdown form AND `§"section name"` prose form.
   Implementation only handled markdown. Trim the comment to
   match the code; track prose-form in v2 follow-up alongside
   Q3 status-vocabulary as next narrowing.

3. **Q5 pattern overlap (exploratory)**: claude-opus-4-7 flagged
   that "standing managers" might substring-match "standing R2
   managers". Empirical check shows it doesn't (POSIX regex
   requires the exact "standing managers" sequence; "R2 " breaks
   the match). Documented inline; no pattern change needed.

8-bit return-code truncation noted by reviewer is theoretical at
current scale (briefs typically have <10 violations) and is now
moot since the global `violations` accumulator is plain bash
arithmetic; only the per-function `return` is uint8-bounded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief Q4 — explicit --repo for CI gh detection

CI failed Q4 even after gh-first restructure: actions/checkout@v4's
shallow clone exposes the remote in a form 'gh pr view' doesn't always
auto-detect, so the stage-1 gh call returned empty (no error message
in v1 because stderr was redirected to /dev/null) and the stage-2
git-log fallback also failed (shallow clone has no merge history).

Three fixes in this commit:

1. **Derive REPO_SLUG from `git config remote.origin.url`** at script
   start. Falls back to "gunb-ai/gunbc" if origin isn't readable
   (self-test runs in tmpdir with no remote).

2. **Pass `--repo "$REPO_SLUG"` explicitly to `gh pr view`** so it
   doesn't have to infer from the cwd's git remote.

3. **Capture gh stderr** to a temp file and surface it in the
   violation diagnostic. If gh is auth-failing or rate-limited,
   the violation message now shows why instead of looking like
   "PR doesn't exist."

Both checker + self-test still pass locally. CI should now succeed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci): grant pull-requests:read for manager-brief authority check

The check uses `gh pr view --json state` to verify "LANDED via #N"
claims map to MERGED PRs. Default GITHUB_TOKEN scopes only include
contents:read; pull-request access fails with:

  GraphQL: Resource not accessible by integration (repository.pullRequest)

Surfaced when the script's stderr-capture fix (ea33aeb) made the
actual error message visible — diagnostic improvement paid off
immediately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* fix(scripts): manager-brief checker — markdown-bold + heading-strip + Q3 trigger

Per gpt-5-5-pro REQUEST_CHANGES on PR #1126 (sha:ea33aeb9). Three
findings — one BLOCKING (Q5 was ceremonial on its load-bearing
projection), one secondary (heading-strip glob bug), one coverage gap.

1. **Q5 markdown-bold mismatch (BLOCKING).** Live briefs use
   `Names this manager one of **7** standing R2 managers` — markdown
   emphasis around the count. The pre-fix regex `[0-9]+ standing R2
   managers` required a bare leading digit, so it matched zero claims
   on every brief. Counts_seen stayed empty → "0 counts seen → silent
   OK" branch fired → check passed ceremonially. A future drift to
   `**6** standing R2 managers` would have been invisible.

   Fix: regex now optionally accepts `**` before and after the digit:
   `\*?\*?[0-9]+\*?\*? standing R2 managers`. Extraction strips
   asterisks (`tr -d '*'`) before parsing. Verified on live briefs:

   $ grep -oE '\*?\*?[0-9]+\*?\*? standing R2 managers' docs/briefs/r2-*-manager.md
   docs/briefs/r2-evaluator-manager.md:**7** standing R2 managers
   docs/briefs/r2-grounding-manager.md:**7** standing R2 managers
   docs/briefs/r2-impossible-bugs-manager.md:**7** standing R2 managers
   docs/briefs/r2-modeling-manager.md:**7** standing R2 managers
   docs/briefs/r2-pure-bootstrap-manager.md:**7** standing R2 managers
   docs/briefs/r2-release-manager.md:**7** standing R2 managers
   docs/briefs/r2-substrate-manager.md:**7** standing R2 managers

   Now actually catches all 7 briefs' projections.

2. **Heading-strip glob bug (Q2 secondary).** `${heading##\#* }` is
   a Bash glob that strips through the LAST space, so
   "## Goal 7 — Evaluator XL" becomes "XL" instead of "Goal 7 —
   Evaluator XL". Multi-word heading anchors silently false-fail.

   Fix: introduced `strip_heading_marker()` helper using sed regex
   `^#{1,6}[[:space:]]+` for accurate prefix-only stripping.

3. **Self-test fixture format mismatch (coverage gap).** Self-test
   used bare-digit form ("7 standing R2 managers"); live briefs use
   markdown-bold ("**7** standing R2 managers"). Fixture proved Q5
   for a format the live docs don't use, masking finding 1.

   Fix: updated all clean + drift fixtures in self-test to use
   markdown-bold form. Verifies Q5 catches the actual format.

4. **Q3 dissolution trigger (per debt-tracking discipline).** Previous
   "v2; the next narrowing opportunity" was a future bucket without
   a checkable trigger. Replaced with concrete trigger: "first
   reviewer-flagged status-string drift class that Q1/Q2/Q4/Q5
   don't catch." Until that surfaces, status vocabulary is captured
   indirectly via Q5 count-projection consistency.

Local checker + self-test still pass after fixes; Q5 now actually
fires on live brief content rather than silently passing ceremonial.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts+briefs): manager-brief Q2 prose-form check + align 7 citations

Per gpt-5-5-pro BLOCKING on PR #1126 (sha:91b5274fc): Q2 explicitly
excluded prose §"section name" citations, but live briefs use those
for load-bearing INVARIANTS / r2-structure / design authority claims.
The exclusion left 12 real authority drifts uncheckable.

**Implements Q2-prose** (in addition to Q2-markdown-anchor):

For each `§"quoted section"` or `§AnchorToken` in a brief:

1. Compute the prefix BEFORE this citation (running prefix; the bug
   in v0 was using before-first-§ for every iteration, so subsequent
   citations on the same line resolved against the first link's
   target instead of their own).
2. Find the most recent markdown link `[text](path)` in the prefix —
   that's the cited file. Fall back to bare `<NAME>.md` token via
   `resolve_authority_file()` (tries `$ROOT/`, `$ROOT/docs/`,
   `$ROOT/docs/thesis/`, `$ROOT/docs/briefs/`).
3. `grep -F` for the section text in the cited file. Permissive
   substring match (vs Q2-markdown's slug match) — accepts
   paraphrased section names while still catching the load-bearing
   "section deleted" failure mode.

**Caught 12 real drifts on first run** — all now fixed:

- r2-evaluator-manager.md: §"Goal 7 — Evaluator XL" + §"Evaluator
  Manager (added 2026-04-28 as Goal 7)" → §"Evaluator Manager
  (added 2026-04-28 amendment)" (matches r2-structure.md:159 actual
  heading)
- r2-grounding-manager.md: §"Tier 1 — Structural correctness —
  Grounding completeness" → §"Tier 1 — Structural correctness"
  (matches THESIS.md:168 actual prose)
- r2-impossible-bugs-manager.md (×2): §"R2 manager continuation"
  → §"Manager structure" (matches r3-structure.md:103 actual heading)
- r2-impossible-bugs-manager.md: §Q1-Q3 + §Q6 → §Q1, §Q2, §Q3 + §Q6
  (range citation didn't match anything literal; expand to discrete)
- r2-release-manager.md (×2): §"R2 manager continuation"
  → §"Manager structure"
- r2-release-manager.md (×2): §v2-guardrail-requirement-3
  → §"v2 guardrail requirements" (matches r2-structure.md:490 body)
- r2-substrate-manager.md: §"R3 lane structure" → §"Lane structure"
  (matches r3-structure.md:86 actual heading)

Local checker + self-test still pass after fixes.

Reinforces gpt-5-5-pro's earlier meta-observation: a checker that
names a discipline but doesn't enforce it on the live format is
documented cheating. Q2-prose closes that gap; the briefs' authority
citations now have to match section text that actually exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(scripts): manager-brief — mktemp gh-stderr + Q1 false-pos trigger

Per claude-opus-4-7 APPROVE-with-exploratory-observations on PR #1126
(sha:91b5274f). Two non-blocking cleanups landed.

1. **gh-stderr capture: $$ → mktemp.** Previous form used
   `/tmp/gh-stderr-$$` which is fine in CI but a crashed run on a
   shared dev box could leak the file. `mktemp` gives a unique path
   + paired cleanup in scope.

2. **Q1 false-positive trigger documented.** Q1 currently treats
   every `](path)` as a filesystem reference. Markdown reference-
   style link definitions and code-block examples containing
   `](foo)` would false-positive. No briefs use either form today;
   added DISSOLUTION TRIGGER comment naming the condition that
   would force context-aware extraction (skip fenced code blocks
   + reference definitions).

The third observation (squash-merge for the WIP: Gunbc PM commits)
is a merge-time decision; PR-level chore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* fix(scripts): manager-brief Q4 case-insensitive + title-case test

Per gpt-5-5-pro APPROVE_WITH_COMMENTS on PR #1126 (sha:91b5274f →
6dafaec): Q4 silently missed title-case "Landed via #N" claims.

**Finding 1 (Q4 case sensitivity):** live briefs use three case forms
of "landed via #N":
  - UPPERCASE — emphasized status-table claims (most common)
  - lowercase — inline prose ("landed via #900", "landed via #937", ...)
  - title-case — sentence-leading headings (r2-release-manager.md:113
    "Landed via #1078:")
The pre-fix regex `(LANDED|landed) via` missed the title-case form,
silently passing any future unique `Landed via #N` claim. Fix:
`grep -oEi 'landed via #[0-9]+'` (case-insensitive flag).

**Finding 2 (Q4 self-test gap):** Q4 negative fixture used UPPERCASE
"LANDED via #88888888"; positive fixture had no landed-PR claim at
all. Title-case wasn't covered. Fixes:

- Added `test_negative_q4_unreachable_pr_titlecase` using "Landed via
  #88888887" — verifies case-insensitive Q4 catches title-case.
- Updated `write_clean_briefs` clean fixture to include
  "Substrate landed via #999" (lowercase, matching real brief
  format). Q4 positive path is now non-vacuous: tmp git repo seeds
  "(#999)" merge subject so this resolves cleanly.

**Finding 3 (Q2 prose deferral note)**: STALE — Q2-prose was
implemented in 97affdb (2 commits before this review). The reviewer
cited line numbers from before the implementation; current code at
`scripts/check-manager-brief-authority.sh:121` says "Two forms covered"
not "v2 candidate". No action needed.

Self-test now: 8 contract assertions (6 negative + 1 positive +
1 fail-closed-on-missing-brief).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(briefs): strip trailing whitespace at r2-evaluator-manager.md:46

Per codex review on PR #1126 (sha:3ba4f2c1): `git diff --check
origin/main...HEAD` flagged trailing whitespace inside the
PR-A-through-PR-E dependency-graph ASCII art. Removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 29, 2026
…1156)

* WIP: Gunbc PM

* WIP: Gunbc PM

* WIP: Gunbc PM

* WIP: Gunbc PM

* docs(briefs): refresh 6 R2 manager briefs post-#1078 merge

Aligns all 6 existing R2 manager briefs with #1078's locked design
decisions and structural cascade:

- Substrate Manager: adds T-Substrate-Lens-Primitive sub-lane (Q6+Q7+Q8
  locks) + PR-PreF Interval<D> consolidation + R3 T-CostLens-Composition
  continuation (Director cascade Item 3); references INVARIANTS §P1
  substrate-fact-introduction procedure + Q3 Cost<Unit> primitives.
- Grounding Manager: engine-reframe to 11 lanes (5 substrate-completion
  lanes replace prior single Engine: Coercion-Fold + LanguageSpec +
  Lifetime-Analyzer + Diagnostic + CrossTarget-Meta); consumes PR-F
  through PR-J cadence; PR #989 footprint queued for cleanup wave.
- Modeling Manager: int-lit item now consumes PR-PreF Interval<D> via
  Q1 lock; references INVARIANTS procedure for substrate-gap signaling.
- Pure Bootstrap Manager: adds R3 continuation lanes (T-LensProducer-
  Retirement XL with 3 internal sub-gates per Director cascade Item 8;
  T-FixedPoint; T-Tier3-Dissolution; 3 distributed bridge retirements
  per Director cascade Item 4 — distribute work, centralize ledger).
- Impossible-Bugs Manager: archives at R2 close per Director cascade;
  post-R2 emergent classes route to Substrate Manager continuation.
- Release Manager: 6→7 manager count; closure ledger spans all 6 other
  managers + sub-gate progress for T-LensProducer-Retirement; structural-
  acceptance-per-lane-close discipline (demo IS structural gate);
  thesis-claim mapping landed via #1078, refresh authority lives here;
  v2 release-doc-authority guardrail follow-up added as next narrow PR.

All 6 briefs now include: structural acceptance .dag TestClaim gates,
locked-design-decisions-consumed section, INVARIANTS §P1 procedure
references, and option-(c)-hybrid timing notes where R1-close-relevant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* docs(briefs): R2 manager-brief status refresh against landed PRs

Pre-spawn implementation work has progressed materially while #1078
was in flight; managers spawning today would otherwise dispatch
against work that's already landed. Refresh per-manager status
tables to reflect current main:

- **Substrate:** ValueBody::Map landed (#1017 + #1068 tightening);
  NominalOpacity fail-closed field-projection enforcement (#937);
  B4.8 Phase-2 site dissolution landed (#1069); B4.2 first-consumer
  wiring landed; T-Cost-Dimension fail-closed precedent (#1003).
- **Grounding:** Rust IntegerRangeFact mirror dissolved (#1005);
  Python primitives.dag landed (#1080); Go primitives tranche 1
  + additional (ac765ce + #1046); T-Ground-Engine Phase 2 slice 1
  (c0cc8b2) noted as pre-cascade footprint queued for cleanup
  wave per design-emission-model.md option (c).
- **Impossible-Bugs:** all 3 main implementations LANDED pre-spawn
  (nested-optional flatten #890 + #962 follow-ups; Int/Int totality-
  by-omission first slice #969; unenumerated effects lens landing
  #971). Day-1 work is class-close completion + sibling totalization
  dispatch (indexing/quotient/remainder), not initial implementation.
- **Pure Bootstrap:** kernel_algebra_profile substrate met via #1017
  + #1068 (consumer plumbing now the remaining R2 work, dispatchable
  Day-1); T-PB-Runtime ExecuteCommand typed-outcome hardening (#1049)
  + T-PB-B boundary coverage (#1082) advanced PB-Runtime foundation
  for R3 lens_apply.rs retirement gate.
- **Modeling:** Secret<T> producer side substantially advanced
  (#900 carrier + #937 fail-closed enforcement); tokenizer charclass
  scanner-order retype landed pre-cascade (242c65d); SourceFiltering
  canonical authority precedent (#1004).
- **Release:** initial closure-ledger snapshot now reflects all
  pre-spawn landings (Impossible-Bugs/Substrate/Ground/PB-Runtime).

Evaluator brief unchanged — new lane added 2026-04-28; nothing
landed yet (gated on PR-A through PR-E design lock cadence).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* docs(briefs): align Substrate Produces + Release R2-close acceptance

Per gpt-5-5-pro REQUEST_CHANGES on PR #1126 (sha:a9285fce). Two valid
findings on coordination-contract internal consistency:

1. **Substrate Produces list omitted ValueBody::Map → PB signal.**
   The deliverables table at line 94 named ValueBody::Map as an R2
   unblocker for PB's kernel_algebra_profile mirror dissolution, but
   the cross-program "Produces" section listed 5 signals and did not
   include this one. Same dependency represented in two places with
   different authority.

   Fix: add ValueBody::Map carrier read-path/API + arrow-body
   evaluation as the 6th produced signal targeted at PB Manager;
   update count from 5 to 6 (also in Reporting-cadence line 150).
   Remove the "Adjacent territory" note about kernel_algebra_profile
   being a future sub-lane — substrate already landed via #1017+#1068.

2. **Release R2-close acceptance gate excluded PB from close criterion.**
   The brief's "Consumes" section correctly named all 6 other managers
   including PB, but the r2_close_signal_to_director_authored gate at
   line 103 used "5 R2-archiving managers" (Substrate-prereq /
   Modeling / Grounding / Impossible-Bugs / Evaluator) — could fire
   the R2-close signal while PB's R2-scope lanes (Tier 3 mirror
   dissolutions + kernel_algebra_profile consumer plumbing) are
   still open.

   Fix: gate becomes "all 6 other managers' R2-scope lanes complete"
   with explicit lane-set listed per manager. Distinguish R2-scope
   completion from manager-archives (Modeling/Impossible-Bugs archive;
   Substrate/PB continue into R3 with R3-scoped lanes — those don't
   gate R2 close).

Both are P2 single-authority alignments; no scope change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* feat(scripts): manager-brief authority consumer + self-test

Per gpt-5-5-pro meta-review on PR #1126: dissolves the recurring
"non-live authority consumed as live" pattern that surfaced 5+ times
during PR #1078 + #1126 review loops (codex tooling false-positives
naming non-existent files / sections; cursor-flagged single-authority
drift on Goal numbering + R3 continuation count).

v1 covers 4 of gpt-5-5-pro's 5 questions:

- **Q1 — cited file existence** — extracts markdown links from each
  brief, resolves relative paths, fails closed if any cited file
  doesn't exist on disk.
- **Q2 — cited section anchor existence** — for `path#anchor` links,
  verifies the anchor matches a slugified heading in the target file.
- **Q4 — `LANDED via #N` reachability** — two-stage check: (a) fast
  `git log --grep="(#N)"` for normal merge subjects, (b) fall back to
  `gh pr view` for squash-merges that drop the suffix (caught a real
  case for PR #900). Verifies merge SHA is `git merge-base
  --is-ancestor HEAD`.
- **Q5 — cross-brief projection consistency** — extracts manager/lane
  counts and verifies all briefs that mention a projection agree both
  cross-brief AND with canonical values from r2-structure.md /
  r3-structure.md (7 standing managers, 6 other managers, 10 R3
  lanes, 7 of 10 Evaluator-gated). Catches drift like "5 R2-archiving
  managers" vs "all 6 other managers".

Q3 (controlled status vocabulary) deferred to v2 — too subjective for
a mechanical check; tracked in script header as next narrowing.

**Self-test** (`scripts/test-check-manager-brief-authority.sh`):
7 contract assertions — negative cases for each of Q1/Q2/Q4/Q5 (×2)
+ fail-closed-on-missing-brief + positive case. Mirrors the
`test-check-release-doc-authority.sh` pattern.

**Wiring:**
- Makefile: `manager-brief-authority-check` + `-test` targets;
  `verify` runs the check.
- CI workflow: both check + self-test wired as named steps; check
  receives `GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` for the gh API
  fallback in Q4.

**SIGPIPE under pipefail caveat documented inline:** `grep -q .` on a
piped `git log` causes pipefail to report failure (grep exits early,
git log gets SIGPIPE 141). Workaround: capture output and test
`-z`/`-n`. Pinned in Q4 implementation comment.

Closes the convergence move gpt-5-5-pro proposed; future review loops
that hit the same "non-live authority" class get caught at CI rather
than reviewer-by-reviewer prose iteration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief Q4 — gh-first for CI shallow-clone compat

CI failed on the first run of the checker because the workflow uses
fetch-depth=1 (shallow clone), so the Q4 fall-back stage's
git-log --grep="(#N)" can't see merge history. The two-stage check
worked locally because git log had full history; in CI it found
nothing on either stage.

Restructure Q4 to gh-first:

- **Stage 1 (primary):** gh pr view N --json state — returns MERGED
  for actually-merged PRs regardless of clone depth or squash-merge
  subject variance. CI passes GH_TOKEN automatically.
- **Stage 2 (fallback):** git log --grep — kept for offline dev /
  auth-blocked environments. In CI with fetch-depth=1 this stage
  finds nothing; that's why Stage 1 is primary.

Reasoning: "is this PR actually merged" is what we want to verify;
gh state=MERGED answers it directly. The previous git-log+ancestor
check was defense-in-depth, but actually fragile in shallow clones
which is the CI default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief check — set -e + return interaction

Per claude-opus-4-7 review on PR #1126: three non-blocking findings
addressed.

1. **set -e + return non-zero**: the per-brief driver loop used
   `check_q1_file_existence "$brief"; rc=$?` — under set -euo
   pipefail, a function returning non-zero is treated as a failed
   command and exits the script before the accumulator runs. Result
   was "stop at first failing brief," not "report all violations in
   one pass" as intended.

   Fix: use `|| rc=$?` form (with explicit `rc=0` reset). This
   keeps set -e from firing on expected-non-zero returns while still
   capturing the count.

2. **Q2 doc/code mismatch**: header comment promised both
   `path#anchor` markdown form AND `§"section name"` prose form.
   Implementation only handled markdown. Trim the comment to
   match the code; track prose-form in v2 follow-up alongside
   Q3 status-vocabulary as next narrowing.

3. **Q5 pattern overlap (exploratory)**: claude-opus-4-7 flagged
   that "standing managers" might substring-match "standing R2
   managers". Empirical check shows it doesn't (POSIX regex
   requires the exact "standing managers" sequence; "R2 " breaks
   the match). Documented inline; no pattern change needed.

8-bit return-code truncation noted by reviewer is theoretical at
current scale (briefs typically have <10 violations) and is now
moot since the global `violations` accumulator is plain bash
arithmetic; only the per-function `return` is uint8-bounded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief Q4 — explicit --repo for CI gh detection

CI failed Q4 even after gh-first restructure: actions/checkout@v4's
shallow clone exposes the remote in a form 'gh pr view' doesn't always
auto-detect, so the stage-1 gh call returned empty (no error message
in v1 because stderr was redirected to /dev/null) and the stage-2
git-log fallback also failed (shallow clone has no merge history).

Three fixes in this commit:

1. **Derive REPO_SLUG from `git config remote.origin.url`** at script
   start. Falls back to "gunb-ai/gunbc" if origin isn't readable
   (self-test runs in tmpdir with no remote).

2. **Pass `--repo "$REPO_SLUG"` explicitly to `gh pr view`** so it
   doesn't have to infer from the cwd's git remote.

3. **Capture gh stderr** to a temp file and surface it in the
   violation diagnostic. If gh is auth-failing or rate-limited,
   the violation message now shows why instead of looking like
   "PR doesn't exist."

Both checker + self-test still pass locally. CI should now succeed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci): grant pull-requests:read for manager-brief authority check

The check uses `gh pr view --json state` to verify "LANDED via #N"
claims map to MERGED PRs. Default GITHUB_TOKEN scopes only include
contents:read; pull-request access fails with:

  GraphQL: Resource not accessible by integration (repository.pullRequest)

Surfaced when the script's stderr-capture fix (ea33aeb) made the
actual error message visible — diagnostic improvement paid off
immediately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* fix(scripts): manager-brief checker — markdown-bold + heading-strip + Q3 trigger

Per gpt-5-5-pro REQUEST_CHANGES on PR #1126 (sha:ea33aeb9). Three
findings — one BLOCKING (Q5 was ceremonial on its load-bearing
projection), one secondary (heading-strip glob bug), one coverage gap.

1. **Q5 markdown-bold mismatch (BLOCKING).** Live briefs use
   `Names this manager one of **7** standing R2 managers` — markdown
   emphasis around the count. The pre-fix regex `[0-9]+ standing R2
   managers` required a bare leading digit, so it matched zero claims
   on every brief. Counts_seen stayed empty → "0 counts seen → silent
   OK" branch fired → check passed ceremonially. A future drift to
   `**6** standing R2 managers` would have been invisible.

   Fix: regex now optionally accepts `**` before and after the digit:
   `\*?\*?[0-9]+\*?\*? standing R2 managers`. Extraction strips
   asterisks (`tr -d '*'`) before parsing. Verified on live briefs:

   $ grep -oE '\*?\*?[0-9]+\*?\*? standing R2 managers' docs/briefs/r2-*-manager.md
   docs/briefs/r2-evaluator-manager.md:**7** standing R2 managers
   docs/briefs/r2-grounding-manager.md:**7** standing R2 managers
   docs/briefs/r2-impossible-bugs-manager.md:**7** standing R2 managers
   docs/briefs/r2-modeling-manager.md:**7** standing R2 managers
   docs/briefs/r2-pure-bootstrap-manager.md:**7** standing R2 managers
   docs/briefs/r2-release-manager.md:**7** standing R2 managers
   docs/briefs/r2-substrate-manager.md:**7** standing R2 managers

   Now actually catches all 7 briefs' projections.

2. **Heading-strip glob bug (Q2 secondary).** `${heading##\#* }` is
   a Bash glob that strips through the LAST space, so
   "## Goal 7 — Evaluator XL" becomes "XL" instead of "Goal 7 —
   Evaluator XL". Multi-word heading anchors silently false-fail.

   Fix: introduced `strip_heading_marker()` helper using sed regex
   `^#{1,6}[[:space:]]+` for accurate prefix-only stripping.

3. **Self-test fixture format mismatch (coverage gap).** Self-test
   used bare-digit form ("7 standing R2 managers"); live briefs use
   markdown-bold ("**7** standing R2 managers"). Fixture proved Q5
   for a format the live docs don't use, masking finding 1.

   Fix: updated all clean + drift fixtures in self-test to use
   markdown-bold form. Verifies Q5 catches the actual format.

4. **Q3 dissolution trigger (per debt-tracking discipline).** Previous
   "v2; the next narrowing opportunity" was a future bucket without
   a checkable trigger. Replaced with concrete trigger: "first
   reviewer-flagged status-string drift class that Q1/Q2/Q4/Q5
   don't catch." Until that surfaces, status vocabulary is captured
   indirectly via Q5 count-projection consistency.

Local checker + self-test still pass after fixes; Q5 now actually
fires on live brief content rather than silently passing ceremonial.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts+briefs): manager-brief Q2 prose-form check + align 7 citations

Per gpt-5-5-pro BLOCKING on PR #1126 (sha:91b5274fc): Q2 explicitly
excluded prose §"section name" citations, but live briefs use those
for load-bearing INVARIANTS / r2-structure / design authority claims.
The exclusion left 12 real authority drifts uncheckable.

**Implements Q2-prose** (in addition to Q2-markdown-anchor):

For each `§"quoted section"` or `§AnchorToken` in a brief:

1. Compute the prefix BEFORE this citation (running prefix; the bug
   in v0 was using before-first-§ for every iteration, so subsequent
   citations on the same line resolved against the first link's
   target instead of their own).
2. Find the most recent markdown link `[text](path)` in the prefix —
   that's the cited file. Fall back to bare `<NAME>.md` token via
   `resolve_authority_file()` (tries `$ROOT/`, `$ROOT/docs/`,
   `$ROOT/docs/thesis/`, `$ROOT/docs/briefs/`).
3. `grep -F` for the section text in the cited file. Permissive
   substring match (vs Q2-markdown's slug match) — accepts
   paraphrased section names while still catching the load-bearing
   "section deleted" failure mode.

**Caught 12 real drifts on first run** — all now fixed:

- r2-evaluator-manager.md: §"Goal 7 — Evaluator XL" + §"Evaluator
  Manager (added 2026-04-28 as Goal 7)" → §"Evaluator Manager
  (added 2026-04-28 amendment)" (matches r2-structure.md:159 actual
  heading)
- r2-grounding-manager.md: §"Tier 1 — Structural correctness —
  Grounding completeness" → §"Tier 1 — Structural correctness"
  (matches THESIS.md:168 actual prose)
- r2-impossible-bugs-manager.md (×2): §"R2 manager continuation"
  → §"Manager structure" (matches r3-structure.md:103 actual heading)
- r2-impossible-bugs-manager.md: §Q1-Q3 + §Q6 → §Q1, §Q2, §Q3 + §Q6
  (range citation didn't match anything literal; expand to discrete)
- r2-release-manager.md (×2): §"R2 manager continuation"
  → §"Manager structure"
- r2-release-manager.md (×2): §v2-guardrail-requirement-3
  → §"v2 guardrail requirements" (matches r2-structure.md:490 body)
- r2-substrate-manager.md: §"R3 lane structure" → §"Lane structure"
  (matches r3-structure.md:86 actual heading)

Local checker + self-test still pass after fixes.

Reinforces gpt-5-5-pro's earlier meta-observation: a checker that
names a discipline but doesn't enforce it on the live format is
documented cheating. Q2-prose closes that gap; the briefs' authority
citations now have to match section text that actually exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(scripts): manager-brief — mktemp gh-stderr + Q1 false-pos trigger

Per claude-opus-4-7 APPROVE-with-exploratory-observations on PR #1126
(sha:91b5274f). Two non-blocking cleanups landed.

1. **gh-stderr capture: $$ → mktemp.** Previous form used
   `/tmp/gh-stderr-$$` which is fine in CI but a crashed run on a
   shared dev box could leak the file. `mktemp` gives a unique path
   + paired cleanup in scope.

2. **Q1 false-positive trigger documented.** Q1 currently treats
   every `](path)` as a filesystem reference. Markdown reference-
   style link definitions and code-block examples containing
   `](foo)` would false-positive. No briefs use either form today;
   added DISSOLUTION TRIGGER comment naming the condition that
   would force context-aware extraction (skip fenced code blocks
   + reference definitions).

The third observation (squash-merge for the WIP: Gunbc PM commits)
is a merge-time decision; PR-level chore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

* fix(scripts): manager-brief Q4 case-insensitive + title-case test

Per gpt-5-5-pro APPROVE_WITH_COMMENTS on PR #1126 (sha:91b5274f →
6dafaec): Q4 silently missed title-case "Landed via #N" claims.

**Finding 1 (Q4 case sensitivity):** live briefs use three case forms
of "landed via #N":
  - UPPERCASE — emphasized status-table claims (most common)
  - lowercase — inline prose ("landed via #900", "landed via #937", ...)
  - title-case — sentence-leading headings (r2-release-manager.md:113
    "Landed via #1078:")
The pre-fix regex `(LANDED|landed) via` missed the title-case form,
silently passing any future unique `Landed via #N` claim. Fix:
`grep -oEi 'landed via #[0-9]+'` (case-insensitive flag).

**Finding 2 (Q4 self-test gap):** Q4 negative fixture used UPPERCASE
"LANDED via #88888888"; positive fixture had no landed-PR claim at
all. Title-case wasn't covered. Fixes:

- Added `test_negative_q4_unreachable_pr_titlecase` using "Landed via
  #88888887" — verifies case-insensitive Q4 catches title-case.
- Updated `write_clean_briefs` clean fixture to include
  "Substrate landed via #999" (lowercase, matching real brief
  format). Q4 positive path is now non-vacuous: tmp git repo seeds
  "(#999)" merge subject so this resolves cleanly.

**Finding 3 (Q2 prose deferral note)**: STALE — Q2-prose was
implemented in 97affdb (2 commits before this review). The reviewer
cited line numbers from before the implementation; current code at
`scripts/check-manager-brief-authority.sh:121` says "Two forms covered"
not "v2 candidate". No action needed.

Self-test now: 8 contract assertions (6 negative + 1 positive +
1 fail-closed-on-missing-brief).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(briefs): strip trailing whitespace at r2-evaluator-manager.md:46

Per codex review on PR #1126 (sha:3ba4f2c1): `git diff --check
origin/main...HEAD` flagged trailing whitespace inside the
PR-A-through-PR-E dependency-graph ASCII art. Removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): manager-brief Q2-prose digit-leading + negative test

Per gpt-5-5-pro REQUEST_CHANGES on PR #1126 (sha:b9f7a1c1): Q2-prose
extractor required §-followed-by-letter, silently skipping the
digit-leading citation forms used in the same diff.

Live brief usage caught:
  §4   — r2-evaluator/grounding/impossible-bugs/modeling/pure-bootstrap
  §6a  — r2-modeling-manager.md (cite of design-substrate-carrier-port-program §6a)
  §0.7 — r2-pure-bootstrap-manager.md (cite of debt-paydown-synthesis §0.7)
  §5   — r2-release-manager.md

All previously skipped → "Q2 (prose §) resolved" was vacuously true
on those lines.

Fix: regex `§[A-Za-z][A-Za-z0-9._-]*[A-Za-z0-9]|§[A-Za-z]`
     →    `§[A-Za-z0-9][A-Za-z0-9._-]*[A-Za-z0-9]|§[A-Za-z0-9]`
(extends [A-Za-z]-leading to [A-Za-z0-9]-leading; quoted form
unchanged).

Documented limitation: short digit-only tokens like §4 resolve
permissively because grep -F "4" matches anywhere; multi-character
tokens like §6a are discriminating.

Self-test gap (also flagged): added
`test_negative_q2_missing_prose_numeric_section` using §99zzz
(digit-leading, multi-char so substring match doesn't trivially
pass). Verifies regex extraction triggers Q2-prose violation on
digit-leading citation drift.

Self-test now: 9 contract assertions (7 negative + 1 positive +
1 fail-closed-on-missing-brief).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(briefs): consume Tier 1 design locks 1+2+3 from #1129

Director landed Items 1+2+3 design locks together via #1129
(`e1afabe47`):
- Item 1 (Q1 asymmetric bound algebra) — `docs/design-emission-model.md`
  §"Q1 — `BoundDeclaration` substrate type"
- Item 2 (reflection completeness) — NEW
  `docs/design-reflection-completeness.md`
- Item 3 (Q6.5 two-layer diagnostic-kind) — `docs/design-lens-framework.md`
  §"Q6.5 — Two-layer authority for diagnostic kinds"

Per agreed PM role on inbox #828: as each design-lock doc lands, PM
consumes the lock into worker brief updates (statuses move from
PENDING/gated → LIVE; cited authority anchors verified by the
manager-brief authority checker). Mostly mechanical.

Brief updates:

- **Substrate** (3 sites): T-Substrate-Lens-Primitive flips from
  "gated on PR-K" to "Q6/Q6.5/Q7/Q8 LANDED via #1129; ready to
  dispatch"; "Diagnostic-kind extensibility (Q6 lock)" replaced
  with the locked Q6.5 two-layer authority cite (Layer 1 closed sum
  Substrate-owned; Layer 2 lens-instance via inhabitance; additive
  widening of `Diagnostic.kind` named).
- **Evaluator** (5 sites): "Lens application gated on PR-C" → cites
  the landed reflection-completeness doc; PR-C row in cadence table
  flips to LANDED; Q6 disposition becomes Q6+Q6.5 with explicit
  cite to design-lens-framework.md §Q6.5; "Reflection completeness
  lives in PR-C" → "lives in design-reflection-completeness.md
  (LANDED via #1129)"; PR-C worker brief in pending list crossed
  out as superseded.
- **Modeling** (1 site): status header now cites Q1 lock landing
  with explicit anchor; int-lit item already references Interval<D>
  via PR-PreF.
- **Grounding** (2 sites): T-Ground-Diagnostic lane and Substrate-
  Manager-cross-program-dependency cite Q6.5 — clarifies lane is
  Layer-1 consumer (not Layer-2 author), no cross-manager handoff.
- **Pure Bootstrap** (1 site): Q6 disposition becomes Q6+Q6.5 +
  reflection-completeness cite added (load-bearing for R3-T-
  LensProducer-Retirement per design-reflection-completeness.md
  §"Cascade and gates" §7.3).
- **Impossible-Bugs** (1 site): Q6 cite becomes Q6+Q6.5; classes
  consume Layer 1, not author Layer 2.

Verified: `bash scripts/check-manager-brief-authority.sh` passes
all 7 briefs (Q1/Q2-md/Q2-prose/Q4/Q5); 9 contract assertions in
self-test still pass.

Note: one brief edit required restructuring (modeling-manager.md:3)
because the original cite put §"section" inside the markdown link's
display text, while the heuristic finds the rightmost `](path)` BEFORE
the §. Moved cite outside the link to align: `[file.md](path) §"section"`.
Same pattern as other landed cites; the checker enforces it
structurally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(scripts): manager-brief — concrete dissolution trigger for short-digit § limitation

Per codex APPROVE_WITH_COMMENTS on PR #1156 (sha:00540f36): the
short digit-only § resolve-permissively limitation was documented
and bounded but lacked a concrete dissolution trigger.

Updated to match Q3 dissolution-trigger discipline: trigger fires
on first reviewer-flagged stale `§N` (single-digit) citation that
survives the substring check because the digit appears elsewhere
in the target file. At that point the check tightens to require
structural context — match `§N` only if the target has a heading
`## N`, `### N`, etc. or numbered-list item at column 0.

Until that surfaces, multi-character disambiguation is the
load-bearing discriminator (and live briefs predominantly use
multi-char forms — §P1, §Q6, §Q6.5, §"Lane structure" — so
single-digit `§4` citations are uncommon).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(design): consume Q6.5 lock in worked examples + r2-structure Q6 row

Per Director (zesty-bear-812) endorsement on inbox #828: fold the
design-doc Q6.5-consumption edits originally drafted in PR #1137
(jolly-ram-908) into the canonical consumption PR. Single-sourced
consumption story; #1137 ends up as a clean no-op redirect.

8 lens-framework worked-example reframes + 1 r2-structure Q6 row
update. All consume the Q6.5 two-layer authority disposition
landed via #1129:

**design-lens-framework.md (8 sites):**
- §"Lens<TenantFlow>" `validate(dag, set)`: "new
  CompilerDiagnosticKind variant" → "lens-local diagnostic-kind
  declaration"
- §"Lens<IFC>" `validate(dag, label)`: same reframe for
  IFCDowngradeViolation
- §"D5 Failure modes": "appropriate CompilerDiagnosticKind variant
  (lens instances may extend CompilerDiagnosticKind...)" →
  "appropriate lens-local diagnostic-kind declaration"
- §Q6 alternative (d): "pushes structural failure data into
  Diagnostic.kind (which is CompilerDiagnosticKind sum type —
  already extends per-instance per
  feedback_state_space_vs_behavioral_invariants)" → "pushes
  structural failure data into lens-local Diagnostic.kind
  declarations"
- §Q6 anti-bridge claim renaming `no_string_parsing_in_witness_consumers`
  description: "Diagnostic.kind extensions" → "lens-local
  Diagnostic.kind declarations"
- §Q6 Recommendation (d): "encode into Diagnostic.kind sum-type
  variants. Lens instances ... extend CompilerDiagnosticKind
  with their own variants" → "encode into lens-local Diagnostic.kind
  declarations. Lens instances ... declare their own kinds beside
  the lens instance"
- §Q6 DECISION line: "(c)/(d) hybrid — Witness<C> stays as-is;
  rich structural validation failures encode into Diagnostic.kind
  extensions via the lens-framework's structural inhabitance" →
  same with "lens-local Diagnostic.kind declarations"; date stamp
  augmented with "refined 2026-04-29"
- §Q6 Director's framing #1: "CapabilityViolation as a
  CompilerDiagnosticKind variant is uniform" →
  "CapabilityViolation as a lens-local diagnostic-kind declaration
  is uniform"

**r2-structure.md (1 site):** §"Q1-Q8 disposition" Q6 row updated
to match design-lens-framework's locked language: "encode into
Diagnostic.kind extensions via lens-framework's structural
inhabitance" → "encode into lens-local Diagnostic.kind declarations
via lens-framework structural inhabitance, not into the closed
compiler-core CompilerDiagnosticKind sum".

These edits are *editorial* — the Q6.5 lock at design-lens-framework.md
§"Q6.5 — Two-layer authority for diagnostic kinds" remains the
canonical authority; this just aligns the worked examples + r2-
structure summary row with that canonical phrasing so future
readers don't see the older "extends CompilerDiagnosticKind"
framing in worked examples and assume it survived.

Verified: manager-brief authority check passes (7 briefs / 0
violations); 9 contract assertions in self-test pass; release-doc
authority check passes.

Per inbox #828 + #1130 coordination: jolly-ram-908 confirmed PR
#1137 will close as redundant once #1156 lands (the brief edits
were already absorbed by my prior consumption pass; these
design-doc edits are the residual that's now folded in).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: Gunbc PM

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 30, 2026
… fail-closed name field

Codex BLOCKING(3) on PR #1314 sha b5f7dd5:

1. Authority document: external doc anchor was generic. Made
   bridge_ledger.dag the explicit substrate authority for rows; per-row
   'authority' field now points at the concrete ratchet (test, PR, or
   gating doc-anchor) that establishes that row's status, not a generic
   taxonomy heading. Status flips from Open to Retired are gated on the
   named ratchet reaching zero residual:
   - source_span_file_participation -> ROADMAP.md#lens-fold-file-path-semantics
   - mark_bootstrap_secret_nominal_opacity -> PR #937
   - canonical_lens_name_dispatch -> canonical_lens_bridge_ratchet_test.rs
   - include_str_side_channels -> PR #1171
   - exact_string_patching_residual -> bridge_lower_helpers_patch_zero_residual_test.rs

2. Predicate schema typing: TestPredicate::BridgeLedgerZero.ledger now
   typed as BridgeLedgerRef (typed wrapper { decl: DeclarationRef }),
   mirror of MethodRef / CallableRef. Adds bridge_ledger.dag::BridgeLedgerRef
   with the same #1175 substrate-gap dissolution trigger. Runner unwraps
   the record at the predicate boundary.

3. Runner row validation: missing or non-String name field now fails
   closed instead of using a placeholder, even before status partition.
   Defensive at the claim boundary, complementing the carrier ratchet
   that already guards bridge_ledger.dag's substrate-side shape.

10/10 tests pass on the new payload shape: predicate-shape ratchet
updated to require BridgeLedgerRef wrapper (not bare DeclarationRef);
runner tests use BridgeLedgerZero { ledger: { decl: <ref> } } literal
construction; sibling-canonical-shape and wrong-type negative tests
still fire fail-closed.
briansrls added a commit that referenced this pull request May 1, 2026
…edicate + runner (#1314)

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* regen bootstrap after std.effects import path fix

* WIP: sharp-raven-604

* chore: apply cargo fmt

* WIP: sharp-raven-604

* regen bootstrap + refresh parse manifest after merge

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* WIP: sharp-raven-604

* PR-α: wrap Operation.callable in CallableRef (typed wrapper, mirrors MethodRef)

* chore: apply cargo fmt

* doc: align test comments with CallableRef wrapper (cosmetic)

* regen bootstrap after merge main

* T-Substrate-AnthropicSchemaMirror: v3 typed mirror for Anthropic Messages signature

- src/v3/std/anthropic_schema.dag: type-authority-only mirror of provider-domain
  types reachable from operation Messages signature in
  dsl/extdeps/llm/anthropic.dag (AnthropicChatMessage + content block variants,
  AnthropicStopReason, AnthropicMessages200{TextBlock,Usage,Body}).
- AnthropicErrorShape deferred (4xx/5xx response slot only; not on the typed
  return reach for fn anthropic_messages -> AnthropicMessages200Body).
- src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs:
  8 ratchets pinning v3 mirror against v2 source (variant labels, field labels,
  type-name presence in v2). Discipline mirrors method_registry_test.rs.
- Type authority only — no fn anthropic_messages, no Operation rows. Those
  are the next substrate precursor that consumes these types.

* WIP: sharp-raven-604

* chore: apply cargo fmt

* anthropic_schema lockstep: couple expected labels to v2 source + optionality

Manager review on PR #1261: the prior lockstep tests asserted v3 labels
against hard-coded constants and only checked v2 type-name presence. They
would NOT catch v2 source drift on field/variant labels themselves.

This commit:
- Extracts the v2 type-block text via v2_type_block(name).
- assert_lockstep_record / assert_lockstep_disj now verify each expected
  label appears literally in the v2 block, fail-closed on either-side drift.
- New anthropic_optional_fields_remain_optional_in_v2_source asserts the
  '?' suffix on is_error: Bool? and stop_sequence: String? in the v2
  source, with comment explaining structural inspection of v3 optionality
  is deferred to the operation-row precursor (per manager guidance).

* anthropic_schema lockstep: bidirectional set equality + structural optionality

OpenAI-Pro REQUEST_CHANGES on PR #1261: prior ratchet only checked v3 set
== expected and expected ⊆ v2. v2 additions silently passed; v3 optionality
was text-only on the v2 side, not structurally checked on v3.

Strengthened:
- v2_record_fields(name) parses the v2 type block and extracts (label,
  is_optional) tuples directly from the source. v2_disj_variants(name)
  extracts variant labels (including from inline 'A | B | C' and
  multi-line '= Foo {} | Bar {}' shapes).
- assert_record_lockstep / assert_disj_lockstep assert SET EQUALITY
  between v2-extracted set and v3 bootstrap set (BTreeSet diff in the
  failure message names v3-only and v2-only labels).
- Optionality is structural on v3: v3_field_is_optional walks the field
  declaration's TypeConnective and matches Cardinality(AtMostOne, _).
  Each v2 'T?' field must lower optional; each v2 'T' field must NOT.
- New test anthropic_user_content_block_user_tool_result_block_optionality
  reaches the variant payload Conj for UserToolResultBlock and asserts
  is_error: Bool? lowers as Cardinality(AtMostOne, Bool) on the
  inner declaration (variant payloads aren't reached by the
  record-level ratchet).

* chore: apply cargo fmt

* fix clippy: use char array in split (manual char comparison lint)

* WIP: sharp-raven-604

* anthropic_schema lockstep: per-variant payload field+optionality coverage

OpenAI-Pro REQUEST_CHANGES on PR #1261: assert_disj_lockstep compared
only variant labels, leaving variant payload field labels and
optionality unguarded — UserToolResultBlock.content / tool_use_id and
AssistantToolUseBlock.id / name / input could drift between v2 and v3
while the test passed.

This commit:
- v2_disj_variants now returns (label, Option<Vec<(field_label,
  is_optional)>>), parsing variant payload bodies via the same logic
  v2_record_fields uses (extracted as parse_v2_brace_body_fields).
- v3_variant_payload_fields walks the v3 variant target's Conj
  declaration and projects (label, Cardinality(AtMostOne, _)?) tuples.
- assert_disj_lockstep extends to per-variant payload set equality and
  optionality: bare-on-bare passes; record-on-record requires set
  equality + optionality match; mismatched (one-side bare,
  other-side payload) fails closed.
- Drops the redundant special-case is_error optionality test — now
  subsumed by structural per-variant payload coverage on
  AnthropicUserContentBlock.

* chore: apply cargo fmt

* WIP: sharp-raven-604

* chore: apply cargo fmt

* WIP: sharp-raven-604

* anthropic_schema lockstep: type-expression equality (records + variant payloads)

OpenAI-Pro REQUEST_CHANGES on PR #1261 (sha 1e08a24): label + optionality
weren't enough to catch field type drift — content: List<X> could become
content: String while tests stayed green.

Adds:
- v3_canonical_ty(dag, ty): walks declarations to produce a canonical
  type-expression string. Named decls (String, Bool, AnthropicStopReason,
  AnthropicMessages200TextBlock, …) canonicalize as their surface name
  even though their underlying connective unfolds to Instantiation
  (e.g. String = FreeMonoid<Int>). Anonymous Instantiation sites
  (List<X>, Map<K, V>) and Cardinality(AtMostOne, T) get unfolded.
- normalize_ty_text(raw): strips trailing '?' and compresses internal
  whitespace so v2 source text matches v3 canonical form.
- v2_record_fields and parse_v2_brace_body_fields now return
  (label, normalized_ty_text, is_optional); v3_variant_payload_fields
  returns (label, canonical_ty, is_optional).
- assert_record_lockstep and assert_disj_lockstep added type-expression
  equality assertions in addition to label-set equality and optionality.
  Optionality is checked separately, so the type comparison strips
  the trailing '?' on both sides and compares inner-element forms only.

Coverage: every mirrored field across AnthropicChatMessage,
AnthropicUserContentBlock (incl. UserToolResultBlock.content/tool_use_id),
AnthropicAssistantContentBlock (incl. AssistantToolUseBlock.input: Json),
AnthropicMessages200TextBlock, AnthropicMessages200Usage (input_tokens: Int),
and AnthropicMessages200Body (content: List<...>, stop_sequence: String?)
now fails closed if v2 carrier type changes.

* anthropic_schema lockstep: also reject Arrow declarations (fn leak guard)

Codex non-blocking improvement on PR #1261: prior anthropic_schema_authors_no_data_rows
test rejected only declarations with value_body: Some(...), so a future
fn anthropic_messages would lower as TypeConnective::Arrow with
value_body: None and bypass the guard. Renamed to ..._or_fns and
extended the filter to also reject TypeConnective::Arrow declarations
authored in src/v3/std/anthropic_schema.dag.

* chore: apply cargo fmt

* T-Substrate-AnthropicMessagesCallable: fn anthropic_messages declaration

Service-operation callable declaration precursor for the Anthropic
Messages REST operation, the substrate slice Grounding PR-β #1252 is
waiting on per parent #1130 dispatch.

Adds:
- src/v3/std/anthropic_messages.dag: top-level fn anthropic_messages
  with honest signature consuming v3.std.anthropic_schema mirror types
  (#1261). Returns AnthropicMessages200Body. host body lowers as
  ArrowBody::Unparsed (no producerless realization carrier minted).
- src/v3/compiler/tests/integration/anthropic_messages_callable_test.rs:
  5 ratchets — Arrow shape, parameter type list matches v2 source via
  v3 mirror, return type is AnthropicMessages200Body, callable is
  acceptable as Operation.callable.decl target, no Operation/data rows
  leak (those are PR-β scope).

Two intentional simplifications vs v2 (documented in file header):
- max_tokens: Int (v2 'Int = 4096'); v3 has no parameter defaults so
  the default is a caller-side fold, not a v3 contract change.
- Return is the 200 body only; AnthropicErrorShape is PR-β response/
  wire lockstep concern.

Out of scope: anthropic_operations: List<Operation> data row, sibling
binding/realization data rows. Grounding owns those.

* chore: apply cargo fmt

* chore: restore comment/test adjacency in SG-0 census (cosmetic)

Reviewer (claude opus 4.7) non-blocking exploratory observation on PR
#1266: the alphabetical insertion of anthropic_messages_callable_test.rs
and anthropic_schema_lockstep_test.rs split the PB Tier-2 #1014 comment
block from the test it describes. Moving the comment two lines down
restores adjacency. No behavior change.

* anthropic_messages: pin Unparsed body + correct file header prose

OpenAI-Pro REQUEST_CHANGES on PR #1266: the file header claimed 'host
anthropic_messages' lowers to ArrowBody::ExternalRealization, but the
generated substrate has ArrowBody::Unparsed(span). Prose did not match
the substrate fact, and no test pinned the body class so a silent
rewrite was invisible.

Fixes:
- File header rewritten to honestly describe the actual lowered state:
  body remains Unparsed because the pipeline-stage post-processing
  patch in bootstrap.rs:256 is pipeline-specific and does not fire
  for service-operation callables. The patch is intentionally not
  added (would require a producerless CompilerHostRealization-style
  data row, the parallel surface the #1130 dispatch rejects).
- New ratchet anthropic_messages_body_is_unparsed pins
  ArrowBody::Unparsed; a silent rewrite to ExternalRealization /
  UserDefined / Pending / NoBody fails closed.
- File header explicitly bounds the unparsed-body state to the same
  dissolution trigger as the schema mirror.

* regen bootstrap: re-sync byte spans after anthropic_messages.dag header rewrite

* T-Verification-BridgeLedger: substrate carrier for bridge-retirement ledger

Adds:
- src/v3/std/bridge_ledger.dag: substrate authority for the bridge-
  retirement ledger Verification's BridgeLedgerZero TestClaim folds.
  - BridgeStatus = Retired | Open (closed two-variant coproduct;
    structural partition, no stringly status).
  - BridgeLedgerRow { name, owner, status, authority } per dispatch
    contract.
  - data bridge_ledger: List<BridgeLedgerRow> = [...] populates the
    five canonical bridge rows from docs/r3-structure.md:79-83.
  - Per-row status rationale documented in file header: source-span-
    file-participation Open, mark-bootstrap-secret-nominal-opacity
    Retired, canonical-lens-name-dispatch Retired, include-str-side-
    channels Open, exact-string-patching-residual Open.
- src/v3/compiler/tests/integration/bridge_ledger_carrier_test.rs:
  6 ratchets — BridgeLedgerRow field set, BridgeStatus closed two-
  variant coproduct, bridge_ledger lowers as List<BridgeLedgerRow>,
  five canonical names in document order, name uniqueness, status
  field resolves structurally to a BridgeStatus constructor (not a
  string).
- bootstrap regen + parse manifest refresh + integration mod entry +
  SG-0 census entry.

Single substrate authority — no parallel Rust Vec, no test-side
ledger table. Verification's BridgeLedgerZero fold is out of scope
for this PR per dispatch.

* regen bootstrap + manifest after merging origin/main

* T-Verification-BridgeLedger: predicate variant + runner branch (Director scope extension)

Per parent #1130 dispatch (#4356094666) extending #1314: substrate
authority for BridgeLedgerZero gate, not just the carrier.

Adds:
- src/v3/std/verification.dag: TestPredicate variant
  BridgeLedgerZero { ledger: DeclarationRef }. Single payload field
  preserves typed-edge discipline; structural identity, not stringly
  ledger reference.
- src/v3/compiler/src/test_runner.rs: eval_bridge_ledger_zero branch.
  Resolves the ledger DeclarationRef, walks ValueBody::List rows,
  reads each row's status Variant, partitions by structural
  comparison against BridgeStatus::Retired's variant id (not by
  name). Returns Pass iff every row is Retired; Fail names the
  open rows in declaration order.
- src/v3/compiler/tests/integration/bridge_ledger_carrier_test.rs:
  Two new tests:
  - bridge_ledger_zero_predicate_carries_only_ledger_declaration_ref:
    pins the variant's payload set to {ledger} and asserts ledger's
    type is DeclarationRef from v3.spec.v3_l1.
  - bridge_ledger_zero_runner_fails_with_named_open_rows_at_head:
    compiles a TestClaim referencing the ledger via DeclarationRef
    and runs it through TestRunner. At HEAD with three Open rows
    (source_span_file_participation, include_str_side_channels,
    exact_string_patching_residual), expects Fail with all three
    named and the two Retired rows excluded. Re-arms as Pass once
    all five flip to Retired.
- bootstrap regen + parse manifest refresh.

8/8 tests pass; clippy clean. Verification's #1310 can now author the
.dag TestClaim consuming this predicate.

* chore: apply cargo fmt

* doc: bridge_ledger comment cites correct canonical-lens ratchet test (cosmetic)

Reviewer (cursor) NON-BLOCKING finding on PR #1314: per-row rationale for
bridge_canonical_lens_name_dispatch_retired cited
bridge_lower_helpers_patch_zero_residual_test (lower-helper exact-string
patch lane) instead of the canonical-lens-name-dispatch ratchet at
canonical_lens_bridge_ratchet_test.rs. Comment text only; bootstrap +
manifest re-synced for the byte-span shift.

* WIP: sharp-raven-604

* eval_bridge_ledger_zero: enforce canonical ledger identity (single-authority)

Codex REQUEST_CHANGES on PR #1314: the previous type-check accepted any
List<BridgeLedgerRow> declaration, so a sibling list could become a
parallel ledger authority and pass the gate independently of the
canonical bridge_ledger. INVARIANTS P2 / single-authority violation.

Adds:
- Canonical-identity check before the type-check guard: the resolved
  ledger DeclarationId must match dag.declaration_by_name('bridge_ledger').id.
  Sibling List<BridgeLedgerRow> declarations fail closed with a
  diagnostic naming the canonical authority. Type-check stays as
  defense-in-depth (catches a future carrier-shape drift).
- New test bridge_ledger_zero_runner_fails_closed_on_sibling_canonical_
  shape_ledger: compiles a sibling 'data sibling_ledger:
  List<BridgeLedgerRow> = []' and asserts BridgeLedgerZero fails
  closed because the declaration identity isn't the canonical one
  (even though the type IS compatible).
- Existing wrong-type test updated: identity check fires first for
  any non-canonical ledger, so the assertion now expects the
  canonical-identity diagnostic.

* chore: apply cargo fmt

* WIP: sharp-raven-604

* BridgeLedgerZero: tighten payload typing, per-row authority pointers, fail-closed name field

Codex BLOCKING(3) on PR #1314 sha b5f7dd5:

1. Authority document: external doc anchor was generic. Made
   bridge_ledger.dag the explicit substrate authority for rows; per-row
   'authority' field now points at the concrete ratchet (test, PR, or
   gating doc-anchor) that establishes that row's status, not a generic
   taxonomy heading. Status flips from Open to Retired are gated on the
   named ratchet reaching zero residual:
   - source_span_file_participation -> ROADMAP.md#lens-fold-file-path-semantics
   - mark_bootstrap_secret_nominal_opacity -> PR #937
   - canonical_lens_name_dispatch -> canonical_lens_bridge_ratchet_test.rs
   - include_str_side_channels -> PR #1171
   - exact_string_patching_residual -> bridge_lower_helpers_patch_zero_residual_test.rs

2. Predicate schema typing: TestPredicate::BridgeLedgerZero.ledger now
   typed as BridgeLedgerRef (typed wrapper { decl: DeclarationRef }),
   mirror of MethodRef / CallableRef. Adds bridge_ledger.dag::BridgeLedgerRef
   with the same #1175 substrate-gap dissolution trigger. Runner unwraps
   the record at the predicate boundary.

3. Runner row validation: missing or non-String name field now fails
   closed instead of using a placeholder, even before status partition.
   Defensive at the claim boundary, complementing the carrier ratchet
   that already guards bridge_ledger.dag's substrate-side shape.

10/10 tests pass on the new payload shape: predicate-shape ratchet
updated to require BridgeLedgerRef wrapper (not bare DeclarationRef);
runner tests use BridgeLedgerZero { ledger: { decl: <ref> } } literal
construction; sibling-canonical-shape and wrong-type negative tests
still fire fail-closed.

* verification ratchet: include BridgeLedgerZero variant after main rebase

m1_5_verification_test::bootstrap_loads_verification_authority_types
expected variant list still ended at SubstrateResearchDeferredClaim;
appended ('BridgeLedgerZero', vec!['ledger']) to match the live
bootstrap. Bootstrap+manifest re-synced from the post-merge regen.
10/10 bridge_ledger_carrier tests + 1/1 verification ratchet pass.

* doc: align eval_bridge_ledger_zero rustdoc with BridgeLedgerRef payload (cosmetic)

Reviewer (cursor) NON-BLOCKING on PR #1314: rustdoc on
eval_bridge_ledger_zero still described the predicate as
{ ledger: DeclarationRef } even though the substrate surface (and the
implementation) now requires the BridgeLedgerRef { decl: DeclarationRef }
wrapper. INVARIANTS 'documentation describes live state' alignment.
Comment-only; no behavior change; .rs file edit so no bootstrap regen
needed.

* bridge_ledger tests: derive row set + open/retired partition from live ledger (single-authority)

Codex BLOCKING on PR #1314: CANONICAL_BRIDGES + expected_open/retired
arrays copied the ledger row set and status partition into Rust,
creating exactly the test-side parallel table bridge_ledger.dag rules
out (single-authority / M7).

- Removed the CANONICAL_BRIDGES const and the
  bridge_ledger_carries_canonical_five_names_in_doc_order test (the
  test re-asserted ledger content from a hardcoded copy; row content
  authority lives only in bridge_ledger.dag).
- bridge_ledger_lowers_as_list_with_at_least_one_row replaces the
  earlier exact-five-rows assertion: pins the structural shape
  (List value_body, every entry a Record, non-empty) without
  duplicating the row count.
- bridge_ledger_zero_runner_fails_with_named_open_rows_at_head no
  longer hardcodes expected_open_rows / expected_retired_rows. It
  reads the live ledger from the bootstrap, partitions by structural
  comparison against BridgeStatus::Retired's variant id, and asserts:
  every Open row's name appears in the failure diagnostic and every
  Retired row's name does not. Re-arms automatically as upstream rows
  flip status — the test does not need an update each time.

9/9 tests pass; clippy clean. The only authority for ledger row
content is now src/v3/std/bridge_ledger.dag.

* bridge_ledger: repoint umbrella row authority at open-scope prose, not closed sub-slice ratchet

OpenAI-Pro REQUEST_CHANGES on PR #1314: the
bridge_exact_string_patching_residual_retired row's authority pointed
at bridge_lower_helpers_patch_zero_residual_test.rs, the receipt for
the RETIRED lower-helper sub-slice (#1014). The row stays Open because
*other* exact-string patching classes remain outside that receipt's
scope, so the closed-slice test was misleading as the row's authority.

Repointed authority at docs/r3-structure.md:83 — the prose row where
the umbrella's open-scope framing ('Other exact-string patching classes
... keep their own dissolution triggers') is defined. Each 'other class'
has its own trigger; the umbrella row retires when those triggers all
fire. Per-row inline comment in bridge_ledger.dag explains the
distinction.

* WIP: sharp-raven-604

* regen bootstrap + manifest after main rebase (clean conflicts)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant