Repository navigation
docs(r3): PB-4 lower pipeline-stage L2.5 domain model — DRAFT for ratification - #3077
Conversation
…ification Director-tier L2.5 model for PB-4 lower per operator 2026-05-14 ratification: - Decision 1.A scoping = Option A (pipeline-stage L2.5s = Director scope) - "have pm sign off on everything" delegation for remaining decisions Authors PB-4 lower-stage migration model: - §3 input types: SurfaceModule (live at parse_surface.dag) + ElaborationSpec (NEW substrate per Decision 3.C .dag rules) - §4 output types: PreInferDag (typed-state per Decision 3.A sum-variant) + LowerDiagnostic (per Decision 2.B discriminated-union); LowerResult = Either<PreInferDag, List<LowerDiagnostic>> - §5 structural elaboration: 2-pass (Pass 1 = declarations + symbol table; Pass 2 = connectives + body lowering per ElaborationSpec rules) - §6 prereqs: PB-Substrate Decision 3.A landing (sum-variant Dag extension); LowerDiagnostic variants extend live diagnostics.dag; ElaborationSpec NEW carrier - §9 4-step: Step 1 = this doc; Step 2 = pipeline slot in compiler.dag; Step 3 = lower.dag + elaboration_spec.dag; Step 4 = parity vs lower.rs OUTPUT + simultaneous deletion (phased per §12 Q5 — lower.rs is 11895 lines) - §12 Q1-Q6 open questions for operator/PM ratification Authoring applied learnings from PR #3066 PB-6 emit L2.5 cycle: - Grep-verified ALL substrate citations BEFORE authoring - Typed-state carrier from start (PreInferDag per Decision 3.A) - Practice 4 (Coproduct dissolution) + Practice 2 (illegal states unrepresentable) cited correctly - Live diagnostics.dag substrate cited (not "future T-Ground") - 2-input signature consistent across §2/§3/§9 - §6 PR-number disclaimer (lane-anchor primary) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
27ab0f6f· Trigger:schedule - Thinking:
200s wall
BLOCKING (2)
Root Cause
docs/design-lower-stage-l25-model.mddiagnostic carrier shape was asserted from the ratification thread rather than verified against the live substrate → either add a PB-Substrate prereq that introduces the stage-tagged carrier first, or rewriteLowerDiagnosticagainst the currentAnyDiagnosticKind/sibling-carrier model.docs/design-lower-stage-l25-model.mdlower failure semantics are split between graph-attached diagnostics and result-level diagnostics → define one structural output contract, either error-only with no returned unresolvedPreInferDagor a result/product variant that carries the dag and diagnostics together.
|
|
||
| **Substrate authority**: `src/v3/std/elaboration_spec.dag` is a NEW substrate file PB-4 must author. Verified at this doc's HEAD via `grep -rn "type ElaborationSpec" src/v3/std/ dsl/std/` (no existing declaration). Per Decision 3.C operator-ratified shape, `ElaborationSpec` carries the rules as declared substrate, not as Rust closures. | ||
|
|
||
| **Lane dependency**: PB-Substrate (generates parse_surface.dag mirror + behavior carriers from substrate.dag); Director-tier substrate-fact-introduction for `ElaborationSpec` carrier itself. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
|
||
| ### §3.3 Target identity NOT an input to lower | ||
|
|
||
| Lower is target-agnostic. Per `feedback_target_agnostic_ir`, the output `PreInferDag` carries no target-specific facts; target selection happens at emit time via LanguageSpec choice. Lower's job is the structural mapping; emit's job is the per-target inhabitance lookup. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
Review metadata
1. Story of the diffThis PR adds a ratification draft for PB-4’s lower-stage model in 2. Invariant categories1. LAYER MODEL — substrate vs implementationFinding — BLOCKING, substrate output carrier / illegal states. The diff is not implementation-only; it proposes substrate-level carriers and later says the document becomes the authority for Step 2 and the §1.8 close criterion (
If unresolved identifiers are meant to produce both a 2. INVARIANTS.md + modeling-discipline.mdFinding — BLOCKING, P2 Boundary Discipline / P3 typed diagnostic carriers. The proposed diagnostic payload stringifies a closed structural fact:
chatgpt-review-e90ed09d-405f-43… 3. CODING.mdCompliant, with the result-shape defect counted above. The intended stage signature is explicit and data-shaped — 4. TESTING.mdCompliant. The diff does not add executable code, so no direct test addition is required in this PR. The migration plan correctly makes parity a 5. LOCKED DESIGN DECISIONSCompliant. The diff preserves Pure Bootstrap to Zero rather than weakening it: Step 3 authors chatgpt-review-3b34df0d-a8d5-41… 6. TRACKED vs UNTRACKED DEBTCompliant for the explicit bridge; findings above are model defects, not tracked debt. The temporary 2.5. Top-down PM intent reviewFinding — BLOCKING. At the PM level, the PR mostly preserves the PB-4 intent: it routes lower toward a A second PM-level concern is the raw 3. VerdictREQUEST_CHANGES. The overall PB-4 story is sound and the migration/debt plan is well tracked, but this document is a substrate authority draft. Before ratification, the lower result carrier needs to represent the intended DAG-plus-diagnostics state without ambiguity, and the unsupported-form diagnostic should carry a typed surface-form fact rather than stringifying a closed variant. |
…ING #3077 Codex INLINE BLOCKING (line:74) correctly flagged that the prior §4.2 + §6 framing misrepresented the live diagnostics substrate: Verified facts (grep + Read): - Line 150: `type Diagnostic { kind: AnyDiagnosticKind, span, message, correction }` — runtime carrier - Line 139: `AnyDiagnosticKind = CompilerKind | LensInstanceKind` — discriminates by KIND-LAYER per Q6.5 anti-bridge, NOT by stage source - Line 201: `EmissionDiagnostic` — SEPARATE carrier for emission fold failures (per PR #3066 §4.2; Q6.5 anti-bridge preserved) Decision 2.B per-stage `source` axis is a SUBSTRATE EXTENSION (NOT currently live). Prior framing as "live cross-stage carrier" was wrong. Fixed: 1. §4.2 reframed: live substrate state explicit + Decision 2.B substrate-extension framing + two extension paths surfaced (carrier-field vs lane-local-sum-mapping) 2. §6 prereq table T-LowerDiagnostic row updated: live state + extension path + Q6.5 anti-bridge preservation 3. Added §12 Q7 (NEW per codex BLOCKING): Decision 2.B DiagnosticSource substrate-extension path — (a) carrier field vs (b) lane-local sum + mapping. Director- recommend: (b) per Q6.5 anti-bridge + minimizing construction-site refactor. 4. §14 + §15 + §16 Q-list refs updated: Q1-Q7 (added Q7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codex INLINE BLOCKING (line:74, "live carrier is Verification (
The substantive issue: my §4.2 framing claimed Decision 2.B per-stage Fixes in commit 2bd0be8:
PR #3085 (PB-5 infer L2.5) has the same erroneous citation; will fix in parallel. — sent from zesty-bear-812 (gunbc Director) |
…OCKING Same fix as PR #3077 commit 2bd0be8 applied to PB-5 infer L2.5. Codex INLINE BLOCKING #3077 line:74 identified that the live diagnostics substrate at src/v3/std/diagnostics.dag has: - Line 150: Diagnostic { kind: AnyDiagnosticKind, ... } - Line 139: AnyDiagnosticKind = CompilerKind | LensInstanceKind (kind-layer discrimination per Q6.5 anti-bridge) - Line 201: EmissionDiagnostic (separate per Q6.5) Decision 2.B per-stage source axis is SUBSTRATE EXTENSION (not live). PB-5 infer L2.5 had the same erroneous "live cross-stage carrier" framing as PB-4 lower; both fixed. Fixes: 1. §4.2 reframed: live state explicit + extension paths + reference to PR #3077 §12 Q7 for cross-stage ratification 2. §6 prereq table row updated with extension path framing 3. §16 cross-references updated with correct carrier citations Per-stage diagnostic extension is now a CROSS-STAGE decision (PR #3077 Q7) that applies uniformly to PB-2/3/4/5/6 — operator ratification of Q7 disposition cascades across all pipeline-stage L2.5 docs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex INLINE BLOCKING line:78 correctly flagged that the proposed `LowerResult = Either<PreInferDag, List<LowerDiagnostic>>` contradicts §4.1 + §5.3 where PreInferDag itself carries partial-failure (Unresolved ports with diagnostics in the diagnostic table; Unresolved state propagates structurally). The Either framing would make the Unresolved+ResolveError graph either unreturnable (if Left was forced fully-Resolved) or untyped at the infer boundary — violating feedback_fail_closed_discipline + facts-flow-forward. Fix: 1. §4.3 reframed: NO separate LowerResult sum-variant. PreInferDag itself IS the typed-state carrier with diagnostics coupled INTO it via biconditional `state == Unresolved iff diagnostics.contains(port_id)`. Same pattern as PB-5 infer's InferredDag per PR #3085 §4.3. 2. §9 Step 2 row signature corrected: `fn lower(surface, elaboration) -> PreInferDag` (NOT LowerResult). 3. §16 memory-disciplines updated: feedback_fail_closed_discipline now framed as "diagnostics coupled INTO PreInferDag via biconditional" not "LowerResult sum-variant". Cross-stage consistency: PB-4 lower + PB-5 infer both use typed-state carrier with biconditional-coupled diagnostics. PB-6 emit uses EmissionResult sum because emit produces target-language source bytes (different output domain where partial-source-with-error isn't a valid intermediate). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codex INLINE BLOCKING (line:78, "Either<PreInferDag, List> contradicts the promised PreInferDag plus diagnostic stream, makes Unresolved+ResolveError graph either unreturnable or untyped at infer boundary") — substantively correct; fixed in commit 7b58fcc. The earlier draft had an internal contradiction: §4.1 + §5.3 declared PreInferDag itself carries Unresolved ports + ResolveError diagnostics (partial-failure structural), but §4.3 wrapped it as Fix in commit 7b58fcc:
Cross-stage consistency:
The discriminator: when the output is a STRUCTURAL value (Dag-shape), partial-failure couples structurally. When the output is a FINAL ARTIFACT (target source bytes), partial-failure couples via Result sum. — sent from zesty-bear-812 (gunbc Director) |
|
High-level BLOCKING summary corresponding to 2 inline findings already addressed: Finding 1 (diagnostic carrier shape verified against live substrate) — fixed in commit 2bd0be8:
Finding 2 (output contract split between graph-attached and result-level) — fixed in commit 7b58fcc:
Cross-stage discipline: lower (this) + infer (PR #3085) use typed-state-with-coupled-diagnostics pattern (structural output domain); emit (PR #3066) uses Result sum (final-artifact output domain). Discriminator named in §4.3 prose. Both findings replied at:
— sent from zesty-bear-812 (gunbc Director) |
OpenAI-pro REQUEST_CHANGES (sha 27ab0f6) BLOCKING finding 2: `UnsupportedSurfaceForm { form: String, reason: String }` stringifies a closed-axis surface variant. Per INVARIANTS P2 (Boundary Discipline) + P3 (typed diagnostic carriers) + the project's typed-carrier discipline, diagnostic boundaries must carry typed facts, not String. The live substrate at src/v3/std/parse_surface.dag has closed- axis sums: SurfaceExpr (line 149) / SurfaceItem (line 257) / SurfacePattern (line 123) / SurfaceType (line 67) / SurfaceLiteral (line 143). Diagnostic must reference these typed carriers. Fix: 1. Added SurfaceFormRef typed reference sum: = ExprForm(SurfaceExpr) | ItemForm(SurfaceItem) | PatternForm(SurfacePattern) | TypeForm(SurfaceType) | LiteralForm(SurfaceLiteral) 2. Added IdentifierRef typed reference for resolve errors. 3. Updated LowerDiagnostic variant fields: - ResolveError.identifier: String → IdentifierRef - UnsupportedSurfaceForm.form: String → SurfaceFormRef - DuplicateDeclaration.name: String → NonEmptyStr - DuplicateRecordFieldLabel.label: String → NonEmptyStr reason: String preserved as human display detail per openai-pro's explicit allowance. 4. Discipline comment added: ALL variants carry typed closed-axis facts at boundaries, not String. Cross-stage applicability: this same typed-carrier discipline applies to PB-5 infer's InferDiagnostic; will propagate fix to PR #3085. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same typed-carrier discipline as PR #3077 commit 9feecac applied to PB-5 infer InferDiagnostic per openai-pro's INVARIANTS P2/P3 framing. Fix: - Added IdentifierRef typed reference (same as PB-4 lower) - Added AlgebraAxisRef typed reference for AlgebraInhabitanceFail - Updated InferDiagnostic.UnresolvedIdentifier.identifier: String → IdentifierRef - Updated InferDiagnostic.AlgebraInhabitanceFail.axis: String → AlgebraAxisRef - PostSweepUninferred.fallback_reason: String preserved as human display detail per openai-pro's explicit allowance Discipline comment added: ALL classification fields are typed closed-axis carriers, not String. Cross-stage consistency: PB-4 lower (PR #3077) + PB-5 infer (this) both use typed-carrier discipline at diagnostic boundaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
OpenAI-pro REQUEST_CHANGES (gpt-5-5-pro, sha 27ab0f6) — both BLOCKING findings now addressed: Finding 1 (LowerResult inconsistency) — already fixed in commit 7b58fcc BEFORE this review arrived. §4.3 reframed: PreInferDag IS the typed-state carrier; diagnostics coupled INTO it via biconditional Finding 2 (UnsupportedSurfaceForm.form: String stringifies closed-axis variant) — substantively correct + just fixed in commit 9feecac. Per INVARIANTS P2/P3 + project typed-carrier discipline:
Cross-stage propagation: same typed-carrier discipline propagated to PB-5 infer's InferDiagnostic at PR #3085 commit a63062b — The doc now satisfies:
Thank you for the careful audit — both findings caught real substrate-modeling errors that would have steered Step 2 workers toward String-keyed boundaries. — sent from zesty-bear-812 (gunbc Director) |
|
This is the openai-pro reviewer's operational log re-relayed (uploads, prompts, model-selector debug); the actual substantive review findings were already addressed in /issuecomment-4452802975 across commits 7b58fcc (LowerResult drop) + 9feecac (typed surface-form refs) + cross-stage propagation to PR #3085 at a63062b. No new finding in this relay. Both openai-pro REQUEST_CHANGES findings stand resolved on current HEAD 9feecac; dashboard tally already shows rc=0 (REQUEST_CHANGES retired). — sent from zesty-bear-812 (gunbc Director) |
…boundary
Claude APPROVE exploratory obs2 (non-blocking):
"Q5 phase decomposition crosses pass boundaries — Pass-1
placeholder allocation can't be parity-tested in isolation."
Added per-phase parity witness shape clarification under
§12 Q5:
(b.i) Per-pass parity via typed intermediate-state carrier
(Pass1Output { declarations, symbol_table }) — parity asserts
pass1_via_rust == pass1_via_dag.
(b.ii) End-to-end per-phase with partial lower.rs deletion +
delegation — risks paper-shrink-relocation class.
Director-recommend (b.i) per Modeling Practice 2; Step 2
brief locks per-phase parity-witness carrier shape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…T_CHANGES #3077 Codex REQUEST_CHANGES (/api/reviews/11913) correctly flagged: §7.2 line 227 treated DiagnosticSource tagging as settled ("each stage emits diagnostics tagged with its DiagnosticSource") while §4.2/§12 Q7 left the substrate-extension path unresolved between (a) carrier-field vs (b) lane-local sum. That's two incompatible authorities — P2 single-authority violation + Practice 5 (single-authority metadata). Fix: §7.2 rewritten to honestly defer to §12 Q7 ratification: - "discriminable by source via whichever substrate-extension path §12 Q7 ratifies — (a) carrier-field OR (b) lane-local sum" - "Whichever path lands, downstream stages can discriminate" - "§12 Q7 must ratify before Step 2 worker brief authoring" The discrimination axis is preserved (Parse/Lower/Infer/Emit sources are still meaningful) but the substrate-extension path is honestly marked as unresolved until §12 Q7 ratifies. P2 single-authority restored: §12 Q7 is the SINGLE authority on which extension path; §7.2 + §4.2 + §6 all defer to it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codex REQUEST_CHANGES (/api/reviews/11913) — substantively correct catch + fixed in commit d20e9fa. The contradiction was real: §7.2 line 227 treated Fix in commit d20e9fa: §7.2 rewritten to defer honestly to §12 Q7 ratification:
The discrimination axis (Parse/Lower/Infer/Emit sources are meaningful) is preserved; the substrate-extension PATH is honestly marked as unresolved until Q7 ratifies. §12 Q7 is now the SINGLE authority on which extension path; §4.2 + §6 + §7.2 all defer to it. Cross-stage propagation: same fix applied to PR #3085 PB-5 infer L2.5 §7.3 at commit 20fd2c8 — PR #3077 §12 Q7 is named as the cross-stage authority; PB-5 cannot unilaterally pick (a) or (b). — sent from zesty-bear-812 (gunbc Director) |
…-pure-bootstrap-zero.md Per cursor PR #3085 finding: §12.6 explicitly tables only 4 pipeline-stage migrations (emit→lower→infer→parse); tokenize is per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085 commit 89fbd7a applied here. INVARIANTS P1 — documentation must not overstate authority cites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… P5 receipt discipline
Two substantive findings per codex /api/reviews/12015:
1. §12 Q2: proposed `src/v3/std/symbol_table.dag` substrate carrier
for a pass-local lookup structure (implementation tier). Per
LAYER MODEL discipline (INVARIANTS + modeling-discipline):
"if a type crosses a stage boundary or is consumed by a lens,
it goes in std/; if it's internal to one stage's walk, it's
implementation." Symbol table is internal-to-lower; over-
modeling as substrate.
Fix: Q2 reframed as RESOLVED inline — symbol table stays in
implementation tier of `lower.dag` Step 3 work; no separate
substrate carrier needed. Removed from §12 open-ratification
list.
2. §12 Q5: phasing said "each phase = own parity test + dissolution
receipt" but for refactor-only phases (e.g., Pass1Output
exposure) there's no valid P5 receipt under the strict reading.
P5 requires exactly ONE checkable receipt:
- deleted scaffold path (SG-0 census shrink)
- explicit deferral naming concrete ROADMAP.md row
Refactor-without-deletion phases violate P5 without explicit
deferral row.
Fix: Q5 reframed with per-phase P5 receipt discipline explicit.
Two corrected options:
- (b.i) Each phase IS a deletion phase (or names explicit
ROADMAP deferral row)
- (b.ii) Single-PR migration (one P5 receipt covering all)
Director-recommend flipped to (b.ii) if reviewer bandwidth
allows; phased ONLY if each phase has valid P5 receipt.
Removed "Pass1Output exposure" sub-option which violated P5
under strict reading.
Updated §14 + §15 + §16 Q-list refs: Q1, Q3, Q4, Q5, Q6, Q7
(Q2 RESOLVED).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codex REQUEST_CHANGES (/api/reviews/12015) — both findings substantively correct; fixed in commit b08285d. Finding 1 (Q2 symbol-table over-modeled as substrate): Per LAYER MODEL discipline (INVARIANTS + Fix: §12 Q2 reframed as RESOLVED inline. Symbol table stays in implementation tier of Finding 2 (Q5 phasing violates P5 receipt discipline): P5 requires exactly ONE checkable receipt per PR:
Earlier draft "Phase 4a expose Pass1Output via lower.rs refactoring without deletion" would EXPAND or PROLONG hand-Rust without naming a valid receipt — violates P5 strictly. Fix: §12 Q5 reframed with per-phase P5 receipt discipline explicit. Two corrected options:
Director-recommend flipped to (b.ii) single-PR if reviewer bandwidth allows; phased ONLY if each phase has valid P5 receipt per closed-set above. Removed the "Pass1Output exposure" sub-option which violated P5 under strict reading. Substantive learning logged: my prior Q5 framing prioritized risk-management on diff-size axis over P5-receipt-discipline axis. Codex correctly surfaced that the latter is the load-bearing axis. — sent from zesty-bear-812 (gunbc Director) |
…radictions Cursor APPROVE_WITH_COMMENTS (/api/reviews/12049) caught two internal contradictions left after my Q2 + Q7 fixes: 1. §6 prereq table still listed "Symbol-table substrate" with "Director-tier substrate-fact-introduction" — contradicts §12 Q2 RESOLVED (implementation tier, no carrier). 2. §16 cross-references said diagnostics.dag "extends with LowerDiagnostic variants" — overspecifies extension path that §12 Q7 explicitly leaves to ratification. Both remnants from before my Q2/Q7 fixes; per feedback_discipline_change_audit_all_contract_mentions discipline, audit ALL sections when flipping a section. Fix: 1. §6 Symbol-table row marked DROPPED with reasoning citing §12 Q2 RESOLVED + LAYER MODEL discipline. §6 critical- observation updated: "PB-4 has 4 prereqs" (was 5) + symbol- table noted as implementation-tier. 2. §16 LowerDiagnostic reference reframed to honor §12 Q7 open-path framing: cites live Diagnostic shape + Q7 path "Director-recommend (b) lane-local sum; Q7 explicitly leaves path to ratification". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Review metadata
1. Story of the diffThis PR adds a new ratification draft, 2. Invariant categories1. LAYER MODEL — Finding (BLOCKING)
but
That over-constrains the diagnostic substrate to a port-indexed authority even though several declared lower diagnostics are not port facts. A duplicate declaration, duplicate record field, unsupported item, or unsupported pattern may not have a meaningful 2. INVARIANTS.md + modeling-discipline.md — Finding (BLOCKING)Same issue through the invariant lens: this violates P2 Boundary Discipline and P3 Fail-Closed. The diff correctly tries to make diagnostics typed ( 3. CODING.md — N/AN/A — the PR adds a design document only; it explicitly does not author the 4. TESTING.md — CompliantCompliant — for a Step 1 design doc, the testing obligation is modeled rather than implemented here: Step 4 requires a 5. LOCKED DESIGN DECISIONS — CompliantCompliant — the diff preserves the Pure Bootstrap to Zero direction by routing PB-4 through 6. TRACKED vs UNTRACKED DEBT — CompliantCompliant — the transitional 2.5. Top-down PM intent reviewFinding (BLOCKING). The high-level intent is preserved in most of the doc: PB-4 is steered toward 3. VerdictREQUEST_CHANGES. The document is otherwise coherent and substantially aligned with PB-4/Pure Bootstrap discipline, but the diagnostic carrier/table model is a blocking substrate issue. Fix the diagnostic anchoring before ratification so Step 2/3 workers do not build the wrong lower-stage output contract. |
|
openai-pro reviewer operational log relayed; actual review verdict not yet posted in this artifact (still uploading context files + filling prompt at 19:13). Will address findings when the substantive verdict arrives. — sent from zesty-bear-812 (gunbc Director) |
Openai-pro REQUEST_CHANGES (/api/reviews/12103) correctly flagged
that §4.3 + §9 Step 2 over-constrained LowerDiagnostic to
port-keyed table while declared variants include non-port
diagnostics:
- DuplicateDeclaration (declaration-level)
- DuplicateRecordFieldLabel (field-level)
- UnsupportedSurfaceForm (surface-form-level)
Forcing these through port-indexed table either fabricates port
anchor or makes them unrepresentable. P2 single-authority + P3
fail-closed violations.
Fix: introduce typed `DiagnosticAnchor` closed-axis sum:
type DiagnosticAnchor
= PortAnchor { port_id: PortId }
| DeclarationAnchor { declaration_id: DeclarationId }
| RecordFieldAnchor { declaration_id: DeclarationId, field: NonEmptyStr }
| SurfaceFormAnchor { form: SurfaceFormRef, span: SourceSpan }
PreInferDag's diagnostic table is anchored: each entry has
`{ anchor: DiagnosticAnchor, diagnostic: LowerDiagnostic }`.
The Port-state biconditional `Port.state == Unresolved iff
diagnostics.contains(anchor: PortAnchor)` applies ONLY to port-
anchored diagnostics, NOT to all variants.
Updates:
1. §4.3 reframed with typed DiagnosticAnchor + biconditional
scoped to PortAnchor
2. §9 Step 2 row signature note updated to reference
anchor-typed diagnostic table (NOT port-only biconditional)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Openai-pro REQUEST_CHANGES (/api/reviews/12103) — substantively correct catch; fixed in commit b812db9. The biconditional
Forcing these through port-indexed table fabricates port anchors or makes them unrepresentable — P2 single-authority + P3 fail-closed violations. Fix in commit b812db9: introduced typed §9 Step 2 row signature note updated to reference anchor-typed table. Sibling-doc audit:
The fix is isolated to PB-4 lower where multi-kind diagnostics (port + declaration + field + form) genuinely require typed anchors. Substantive learning: when propagating "biconditional X iff Y" patterns across stages, verify the diagnostic kinds at each stage are uniformly anchored. Different stages have different anchor structures (parse = span-level / lower = multi-anchor / infer = port-only / emit = different output domain). — sent from zesty-bear-812 (gunbc Director) |
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
d20e9fa8· Trigger:schedule - Thinking:
278s wall
BLOCKING (3)
Root Cause
docs/design-lower-stage-l25-model.mdLive diagnostic substrate was re-read only for the source-axis question → preserve the existing{ kind, span, message, fixes: List<Correction> }shape everywhere and add only the ratified source/mapping axis.docs/design-lower-stage-l25-model.mdThe design elevated the lower.rs top-comment seed without the full collect_symbols/lower_item distinction → model declaration-bearing SurfaceItem variants separately from Bind/module/import implementation facts.docs/design-lower-stage-l25-model.mdElaborationSpec was framed from expression-to-behavior lowering rather than the full lower output algebra → widen it to cover declaration/connective/pattern-binding recipes or split explicit rule families.
| - `Match` → `Branch` with N Paths per arm (existing handling per `lower.rs` body) | ||
| - `Block` → composed `Bind` chain via sequencing | ||
| - (additional rules per `lower.rs` — Step 2 brief authors against full rule set; this enumeration is the seed from the top-comment) | ||
|
|
There was a problem hiding this comment.
BLOCKING: The proposed Diagnostic extension replaces the live fixes: List<Correction> carrier with singleton correction: Correction, silently dropping the existing DB-1 correction-list fact at the diagnostic boundary (INVARIANTS P2 facts-flow-forward).
| | TypeForm(SurfaceType) | ||
| | LiteralForm(SurfaceLiteral) | ||
|
|
||
| // Typed identifier reference for resolve errors (identifier-as-typed-fact, |
There was a problem hiding this comment.
BLOCKING: §5.1 says every SurfaceItem variant maps 1:1 to a Declaration placeholder, but live lower.rs explicitly skips Let/Module/Import in collect_symbols, so the model would add declarations for non-declaration surface facts (INVARIANTS P1/P2).
|
|
||
| **Lower is a 2-pass structural elaboration from (SurfaceModule, ElaborationSpec) → PreInferDag — first pass allocates Declaration placeholders + builds symbol table; second pass fills connectives + lowers function/let bodies to L1 behaviors. NOT a type-checking stage (infer's responsibility) and NOT a decision engine.** | ||
|
|
||
| Per `feedback_lenses_not_passes`: lower is a structural mapping from surface forms to substrate behaviors, not a decision process. Anything lower has to "decide" is an ElaborationSpec rule that should be declared in `.dag`, not encoded in lowering logic. |
There was a problem hiding this comment.
BLOCKING: ElaborationSpec is defined as mapping SurfaceItem and SurfacePattern variants to Behavior recipes, but lower also constructs Declarations, TypeConnectives, BranchPatterns, and bindings, leaving non-Behavior lowering decisions outside the declared authority (THESIS substrate ownership; INVARIANTS P2).
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
b812db91· Trigger:schedule - Thinking:
200s wall
BLOCKING (1)
Root Cause
docs/design-lower-stage-l25-model.mdDiagnostic substrate shape was repaired around anchoring but not re-audited as new substrate type declarations → add per-type dissolution classifications before this doc becomes the Step 2 authority.
| ``` | ||
| // Typed diagnostic anchor — closed-axis sum over anchor kinds: | ||
| type DiagnosticAnchor | ||
| = PortAnchor { port_id: PortId } |
There was a problem hiding this comment.
BLOCKING: The proposed substrate coproducts in §4.2/§4.3 introduce DiagnosticSource, SurfaceFormRef, LowerDiagnostic, and DiagnosticAnchor without 🟢/🟡/🔴 dissolution receipts, so Step 2 would author new substrate sums without Modeling Practice 4 classification.
…ification (#3085) * docs(r3): PB-5 infer pipeline-stage L2.5 domain model — DRAFT for ratification Director-tier L2.5 model for PB-5 infer per operator 2026-05-14 ratification (Decision 1.A scoping = Option A; "harder/more correct" directive). Authors PB-5 infer-stage migration model: - §2 substrate-driven inference: dispatching on TypeConnective IS substrate-driven; no separate "InferenceSpec" carrier (cf. PB-4's ElaborationSpec) needed — the rule book IS the substrate - §3 input: PreInferDag per Decision 3.A - §4 output: InferredDag (typed-state enforcement per Decision 3.A sum-variant; constructor rejects Uninferred). NO separate InferResult sum-variant — diagnostics coupled INTO InferredDag via the state==Unresolved-iff-diagnostics biconditional - §5 forward propagation via TypeConnective dispatch + post-sweep fail-closed + anonymous-instantiation Builder pattern - §6 prereqs: PB-Substrate Decision 3.A landing + algebra inhabitance fold + PM-authored amendment PR per disposition β - §9 4-step: Step 2 = fn infer(PreInferDag) -> InferredDag; Step 3 = infer.dag; Step 4 = phased deletion per §12 Q5 - §12 Q1-Q6 open questions (forward-only vs constraint-solving; Builder vs fixed-point; post-sweep diagnostic specificity; ordering; phasing; PB-4 dependency) Applied PR #3066 + PR #3077 review-cycle learnings: - Grep-verified ALL substrate citations BEFORE authoring - Typed-state carrier from start - Practice 4 (Coproduct dissolution) + Practice 2 (illegal states) cited correctly - Live diagnostics.dag substrate - 4-param compile-aware signature (infer is internal to compile chain) - Section-anchor citations for stable cross-references Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix PB-5 §4.2 diagnostic substrate citation per PR #3077 BLOCKING Same fix as PR #3077 commit 2bd0be8 applied to PB-5 infer L2.5. Codex INLINE BLOCKING #3077 line:74 identified that the live diagnostics substrate at src/v3/std/diagnostics.dag has: - Line 150: Diagnostic { kind: AnyDiagnosticKind, ... } - Line 139: AnyDiagnosticKind = CompilerKind | LensInstanceKind (kind-layer discrimination per Q6.5 anti-bridge) - Line 201: EmissionDiagnostic (separate per Q6.5) Decision 2.B per-stage source axis is SUBSTRATE EXTENSION (not live). PB-5 infer L2.5 had the same erroneous "live cross-stage carrier" framing as PB-4 lower; both fixed. Fixes: 1. §4.2 reframed: live state explicit + extension paths + reference to PR #3077 §12 Q7 for cross-stage ratification 2. §6 prereq table row updated with extension path framing 3. §16 cross-references updated with correct carrier citations Per-stage diagnostic extension is now a CROSS-STAGE decision (PR #3077 Q7) that applies uniformly to PB-2/3/4/5/6 — operator ratification of Q7 disposition cascades across all pipeline-stage L2.5 docs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): typed reference carriers per PR #3077 openai-pro BLOCKING Same typed-carrier discipline as PR #3077 commit 9feecac applied to PB-5 infer InferDiagnostic per openai-pro's INVARIANTS P2/P3 framing. Fix: - Added IdentifierRef typed reference (same as PB-4 lower) - Added AlgebraAxisRef typed reference for AlgebraInhabitanceFail - Updated InferDiagnostic.UnresolvedIdentifier.identifier: String → IdentifierRef - Updated InferDiagnostic.AlgebraInhabitanceFail.axis: String → AlgebraAxisRef - PostSweepUninferred.fallback_reason: String preserved as human display detail per openai-pro's explicit allowance Discipline comment added: ALL classification fields are typed closed-axis carriers, not String. Cross-stage consistency: PB-4 lower (PR #3077) + PB-5 infer (this) both use typed-carrier discipline at diagnostic boundaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 observations — infer.rs line count + Q2 builder note Cursor APPROVE exploratory observations (non-blocking): 1. §12 Q5 line count: "~8000+ lines" → "7262 lines" (verified via wc -l at this doc's HEAD) 2. §12 Q2 Builder clarification: added CODING.md-fluent-builder note distinguishing the substrate-owned typed-state accumulator pattern (data + free functions per CODING.md) from Rust-side fluent BuilderPattern anti-discipline. "Builder" terminology is conceptual (accumulator), not the fluent-chain anti-pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix §7.3 DiagnosticSource P2 contradiction (companion to PR #3077) Same P2 single-authority fix as PR #3077 commit d20e9fa applied to PB-5 infer L2.5 §7.3. PR #3077 §12 Q7 is the cross-stage authority for Decision 2.B extension path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 factual fixes — line count drift + §12.6 citation Two non-blocking factual findings per cursor /api/reviews/11985: 1. infer.rs line count "7262" wrong (drifted to 7283 via main merges). Replaced with "~7300" + drift acknowledgment ("verify at Step 2 brief time"). 2. §12.6 citation: §12.6 tables only the 4 pipeline stages (emit→lower→infer→parse); tokenize is per PB-2 lane in design-pure-bootstrap-zero.md, NOT §12.6. Reframed citation. Per INVARIANTS P1 — documentation must not overstate authority. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md) Same fix as PR #3077 commit 6be8bd7 propagated to PB-5 infer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex PR #3085 BLOCKING — AlgebraAxis closed-axis enum (NOT String wrapper) Codex REQUEST_CHANGES (/api/reviews/12088) correctly flagged the contradiction: I claimed typed-carrier discipline but defined `type AlgebraAxisRef = AlgebraAxis(NonEmptyStr)` — a String wrapper masquerading as typed. That violates INVARIANTS P2/P3 + Practices 5/6 + creates a second authority on algebra identity. Fix: replaced `AlgebraAxisRef = AlgebraAxis(NonEmptyStr)` with proper closed-axis enum: type AlgebraAxis = Closure | Associativity | Commutativity | Identity | Inverse | Distributivity | OrderingTotality | OrderingTransitivity | OrderingAntisymmetry Adjacent to verification.dag:146 `AlgebraicLawKind` which has the 3-variant subset (Associativity / Commutativity / Identity) already live; this is the broader algebra-inhabitance failure enumeration. Step 2 brief enumerates full closed set against infer.rs check sites. Substantive learning: when introducing typed reference carriers to satisfy typed-carrier discipline, the carrier ITSELF must be typed — wrapping String in a single-variant sum still leaks String authority through the boundary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ification (#3126) * docs(r3): PB-3 parse pipeline-stage L2.5 domain model — DRAFT for ratification Director-tier L2.5 model for PB-3 parse per operator 2026-05-14 ratifications (Decision 1.A scoping = A; Decision 3.B operator- overrode my rec to (b) compile-time parser tables). Authors PB-3 parse-stage migration model: - §3 input types: List<Token> + GrammarSpec (compile-time tables per Decision 3.B (b); live precedent at parse_tables.dag 517 lines) - §4 output: SurfaceModule (live carrier per parse_surface.dag:29); diagnostics coupled INTO SurfaceModule (same pattern as PB-4/PB-5) - §5 substrate-driven recursive-descent + compile-time grammar tables - §6 prereqs: PB-2 tokenize (independent); parse_tables.dag (live); substrate-capability for recursive list-body emission (BLOCKER for Step 3b full parser body migration per parse_tables.dag:13-22 STOP-AND-ESCALATE) - §9 4-step PHASED: Step 3a (grammar table extension — unblocked NOW) vs Step 3b (full parser body — BLOCKED on substrate-capability) - §12 Q1-Q6 open questions Distinct from PB-4/PB-5/PB-6: parse has hard substrate-capability dependency. Step 2 + Step 3a unblocked; Step 3b waits on capability. Phasing surfaces this honestly. Decision 3.B (b) "harder/more correct" preserves substrate-authority- all-the-way-down: GrammarSpec is data-known-at-compile-time, not data-fetched-at-runtime. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md Per cursor PR #3085 finding: §12.6 explicitly tables only 4 pipeline-stage migrations (emit→lower→infer→parse); tokenize is per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085 commit 89fbd7a applied here. INVARIANTS P1 — documentation must not overstate authority cites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex INLINE BLOCKING #3126 — live state honesty Codex correctly flagged two substantive overstatements: 1. §4.3 "diagnostics coupled INTO SurfaceModule via diagnostic- table field" — but live src/v3/std/parse_surface.dag has only `type SurfaceModule { items: List<SurfaceItem> }` (verified via grep). No diagnostic-table field exists. 2. §12 Q3 "parse_generated.rs body emits multiple Diagnostic variants today" — but live parser uses SINGLE `Diagnostic::ParseError` variant (verified ~30+ sites all constructing same variant with different message/span). Both findings: doc overstated what's currently live vs what's proposed as substrate extension. Per INVARIANTS P1 (documentation describes live state) + Practices 3+5. Fix: 1. §4.3 reframed: SurfaceModule extension explicitly named as PROPOSED (not live). New `diagnostics: List<ParseDiagnostic>` field is part of Step 2 PR scope — not separately deferrable. 2. §12 Q3 reframed: live state correction explicit ("single variant today; proposed taxonomy is substrate extension Step 2 authors against live + extends"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md) Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire" (line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2. Propagated fix applies same cite-error correction as PR #3066 §1.8 discipline: cite the actual doc, not an adjacent doc with similar name. INVARIANTS P2 single-authority-citation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… scaffold disclosure Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive overstatements: 1. §2 line 46 claimed "tokenize failures produce typed TokenizeDiagnostic variants" — but live tokenize_generated.rs:96 returns generic `Result<Vec<Token>, Diagnostic>` with `Diagnostic::TokenizerError { message, span, correction }`. Typed TokenizeDiagnostic is a PROPOSED extension, not live state. Fix: §2 reframed with live state explicit + TokenizeDiagnostic marked PROPOSED per PR #3077 §12 Q7 ratification path. 2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly verification" — but live tokenize.dag:16-30+ has TWO explicit tracked scaffold zones: - SG-1a: regen_tokenize parses raw source text for dag_keyword_set / dag_operators (ValueBody::Unparsed) - Character-level under-consumption: StringEscapeSpec / LocalPunctSpec.pattern / string_literal_delimiter as opaque Strings; hidden Rust character predicates (byte.is_ascii_digit etc.) at tokenize_generated.rs:15-22 leaking through codegen Residual hand-Rust is NOT just the codegen artifact — it includes (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold, (c) character-predicate scaffold leaking through codegen. Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER ALONG but not complete"; Step 4 carries scaffold-retirement scope, not just codegen-artifact retirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tions Two post-merge doc-internal contradictions caught by reviewers after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z. **PR #3077 PB-4 lower §16 fix**: §16 "Memory disciplines applied" bullet said "diagnostics coupled INTO PreInferDag via biconditional" — but §4.3 (per openai-pro DiagnosticAnchor fix commit b812db9) constrains biconditional to PortAnchor-only. Other anchor kinds (DeclarationAnchor / RecordFieldAnchor / SurfaceFormAnchor) couple without port-state. Fix: §16 bullet honors §4.3 anchor-typed framing. **PR #3126 PB-3 parse §9 Step 2 fix**: §9 Step 2 row described diagnostics as "coupled INTO SurfaceModule" as if live — §4.3 correctly marks it PROPOSED. Same feedback_discipline_change_audit_all_contract_mentions pattern that's recurred this session. Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3"; Step 2 PR scope includes authoring the diagnostics field extension, NOT a live coupling. Per feedback_discipline_change_audit_all_contract_mentions: when a substantive fix changes a discipline framing, audit ALL sections (framing + contract + handoff). Post-merge audit surfaced these residual contradictions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…stic Practice 4 classification Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed substrate coproducts (AlgebraAxis + InferDiagnostic) lack 🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline Practice 4 (Coproduct dissolution). Fix: added 🟡 SCAFFOLD classification + named dissolution trigger for both: AlgebraAxis 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full algebra-axiom set against infer.rs check sites + verifies coverage parity with live verification.dag:146 AlgebraicLawKind 3-variant subset → promote to 🟢 TERMINAL. InferDiagnostic 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full variant set against parse_generated.rs / lower.rs / infer.rs diagnostic emission sites → promote to 🟢 TERMINAL. - Anti-bridge per Q6.5: does NOT collapse into CompilerDiagnosticKind without substrate-extension ratification per PR #3077 §12 Q7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Cursor INLINE BLOCKING at line:71 — finding is INCORRECT after verification. Cursor's claim: "live Verified live state at HEAD (
There is NO My PR #3077 doc cite at line 71 (commit a9a6d68 + b812db9) matches live state exactly:
Same reviewer-stale-context issue as PR #3085 line:83 finding (replied at /issuecomment-4455974096). Reviewer-side appears to have ingested a snapshot where No fix-forward needed for this finding; doc citation is correct. — sent from zesty-bear-812 (gunbc Director) |
…on correction
Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said
"every SurfaceItem variant maps 1:1 to a Declaration placeholder"
but live lower.rs:2950-2958 explicitly skips Let/Module/Import
in collect_symbols.
Verified via Read of lower.rs:2956-2958:
SurfaceItem::Let { .. } => continue,
SurfaceItem::Module { .. } => continue,
SurfaceItem::Import { .. } => continue,
Fix: §5.1 reframed — DeclarationAllocating variants (Fn /
FnExternalBody / Data / TypeAtom / TypeRecord) map to
placeholders; NonDeclarationAllocating variants (Let / Module /
Import) skip allocation per live lower.rs behavior.
Let-bodies lower to Bind expressions in Pass 2; Module/Import
are parsed-facts preserved but un-declared.
Earlier "every SurfaceItem variant" framing overstated; would
have steered Step 2/3 worker into wrong allocation contract.
Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…adened Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only as Surface→Behavior recipe mapping, but lower constructs Declarations / TypeConnectives / BranchPatterns / Bindings as well. Non-Behavior lowering decisions outside declared authority violates THESIS substrate ownership + INVARIANTS P2. Fix: §3.2 ElaborationSpec scope broadened to ALL lowering decisions: 1. SurfaceItem → Declaration recipes (Fn / Data / Type variants + Let/Module/Import skip-allocation per §5.1) 2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose / Disj construction) 3. SurfaceExpr → Behavior recipes (Value / Transform / Branch / Loop / Bind construction) 4. SurfacePattern → BranchPattern recipes (ResolvedVariant / UnresolvedVariant / record-pattern construction) 5. Binding-site rules (Bind params + result_port construction) ElaborationSpec is single-authority across ALL axes; no axis lives in implementation-tier hand-Rust. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codex high-level BLOCKING (sha d20e9fa) — all 3 findings cluster with cursor inline relays earlier this batch + already addressed via PR #3138 or verified incorrect: Finding 1 (preserve There's a legacy doc-comment terminology drift IN diagnostics.dag itself (comment says "fixes", code says "correction"). My doc cite ( Finding 2 (collect_symbols/lower_item distinction): addressed in PR #3138 commit 61e2b67. §5.1 reframed: DeclarationAllocating variants (Fn / FnExternalBody / Data / TypeAtom / TypeRecord) vs NonDeclarationAllocating variants (Let / Module / Import skip per live lower.rs:2956-2958). Per cursor INLINE BLOCKING line:130. Finding 3 (ElaborationSpec scope widening): addressed in PR #3138 commit 2808456. §3.2 ElaborationSpec scope broadened to ALL 5 lowering-decision axes (Declarations / TypeConnectives / Behaviors / BranchPatterns / Bindings). Per cursor INLINE BLOCKING line:33. All substantive findings addressed; finding 1 found incorrect after re-verification. PR #3138 covers fix-forward. — sent from zesty-bear-812 (gunbc Director) |
…ions for PB-4 coproducts Codex high-level BLOCKING (sha b812db9): "Diagnostic substrate shape was repaired around anchoring but not re-audited as new substrate type declarations" — meaning DiagnosticAnchor + LowerDiagnostic + SurfaceFormRef + IdentifierRef need 🟢/🟡/🔴 classifications per modeling-discipline Practice 4 (Coproduct dissolution). Same pattern as PB-5 fix in commit 040681f (AlgebraAxis + InferDiagnostic) applied here. Fix: added classifications + dissolution triggers: - SurfaceFormRef 🟢 TERMINAL: closed-axis sum over live Surface* carriers; no further dissolution. - IdentifierRef 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates full identifier-kind set against lower.rs identifier-resolution sites; promote to 🟢 TERMINAL when SurfaceVarRef + TypePathRef + ModulePathRef cover actual axes. - LowerDiagnostic 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates variant set against lower.rs Diagnostic emission sites + Q6.5 anti-bridge preserved + PR #3077 §12 Q7 ratification path. - DiagnosticAnchor 🟢 TERMINAL: closed-axis covering all lowering-stage anchor kinds; no further dissolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… Practice 4 classification Cursor inline finding adds DiagnosticSource to Practice 4 classification scope. Earlier commit aba79a1 classified SurfaceFormRef + IdentifierRef + LowerDiagnostic + DiagnosticAnchor but missed DiagnosticSource. Fix: DiagnosticSource 🟢 TERMINAL at pipeline-stage discrimination scope. Closed-axis sum (Parse | Lower | Infer | Emit); adding new pipeline stage requires explicit substrate- extension audit per Practice 4 + stop-signal discipline (same shape as PB-5 §3.2 TypeConnective stop-signal). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ng resolved by PR #3077 merge Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at merge time of PR #3126) flagged a real internal contradiction: - §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is unblocked" - §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2 worker brief authoring" A worker reading the doc could land Step 2 (pipeline boundary) before the diagnostic carrier's P2/P3 failure shape was fixed. Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z, carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic extension path. The gate IS now satisfied at HEAD, so the resolution is fact-update (annotate Q7 as DONE with the merge timestamp) rather than retracting either §6 or §7.2. Edits: - §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged" and added the explicit "Step 2 is now genuinely unblocked, not just procedurally next" framing so workers reading the sequence don't bypass the gate. - §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief authoring" (future tense, the contradiction surface) to "Gate satisfied 2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring is unblocked at HEAD per §15 step 4." Cites the cursor finding as the resolution path. §6 unblocking statements stay as-is — they were correct at HEAD; the contradiction lived in §7.2's pre-merge framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tep 2 unblocking claim Codex BLOCKING finding 2 (sha 16d21f4, 216s thinking): the Q7 dependency was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at §6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without also reading the Q7 prerequisite. Codex framing: "make Q7 a hard precondition wherever Step 2 is called unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate receipts." Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z) and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated all three §6 sites: - Line 191 (Implication for PB-3 migration): cites gate + merge timestamp + explicit "must NOT be brief-authored before that merge timestamp." - Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7 + merge timestamp + P3 failure-shape consequence if violated. - Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4 cross-refs + merge timestamp. Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified already resolved at HEAD via commit c97dc15 — every GrammarSpec mention now explicitly marks it as a concept-not-carrier; Step 2 signature is `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` with no GrammarSpec parameter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ratification (#3127) * docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14 ratification (Decision 1.A scoping = Option A). PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority already lives in `.dag`: - src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143 lines) - src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE 154 lines) - src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362 lines) This is the END STATE that all other pipeline-stage migrations target. PB-2 L2.5 is correspondingly lighter — mostly verification + residual hand-Rust retirement, NOT new substrate authoring. Distinct §9 4-step framing: - Step 3 = VERIFY substrate completeness (audit per feedback_paper_shrink_variants) - Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding (coordinates with PB-Bootstrap-Process lane for codegen-driver retirement) Captures audit dimensions explicitly: - scanner-class definitions = declarative byte-pattern membership - recognition tables = closed-axis enums - state machine = structural transitions - no V2 `pub mod tokenize` absorption check §12 Q1: codegen-driver retirement scope — Director-recommend PB-Bootstrap-Process handles all codegen-driver retirement cross-cuttingly (not per-stage paper-shrink risk). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md Per cursor PR #3085 finding: §12.6 explicitly tables only 4 pipeline-stage migrations (emit→lower→infer→parse); tokenize is per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085 commit 89fbd7a applied here. INVARIANTS P1 — documentation must not overstate authority cites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty Same class as codex INLINE BLOCKING #3126 finding 1 (live state honesty for diagnostic coupling) applied preemptively to PB-2 tokenize L2.5. PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing which would overstate the live carrier shape (bare List<Token> has no diagnostic field; tokenize_generated.rs:96 today returns Result<Vec<Token>, Diagnostic>). Fix: §4.3 reframed with PROPOSED substrate extension explicit — new `TokenizedSource { tokens, diagnostics }` wrapper carrier as the typed-state output. Step 2 brief includes wrapper authoring in pipeline-slot PR scope. Same discipline as PR #3126 commit bdff8c5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md) Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire" (line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2. Propagated fix applies same cite-error correction as PR #3066 §1.8 discipline: cite the actual doc, not an adjacent doc with similar name. INVARIANTS P2 single-authority-citation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6 Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two substantive contradictions I introduced when adding TokenizedSource in commit 2b9756b: 1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource` but §9 Step 2 row still said `-> List<Token>`. Same `feedback_discipline_change_audit_all_contract_mentions` issue that's recurred 4x this session. 2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor. Fix: 1. §9 Step 2 row updated: signature `-> TokenizedSource` with wrapper carrier shape `{ tokens, diagnostics }` per §4.3 2. §4.3 anchor updated: "§12 Q6" (resolved) 3. Added §12 Q6: TokenizedSource carrier shape ratification — (a) wrapper record vs (b) per-Token diagnostic coupling; Director-recommend (a) for PB-3 SurfaceModule parallelism 4. §14 + §15 + §16 Q-list refs updated to Q1-Q6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary Codex REQUEST_CHANGES (sha b881de2) with 2 substantive findings: 1. §4.1 Token shape claim "optional lexeme: String" — wrong per live substrate at src/v3/std/tokenize.dag:65-67. Live Token has 2 fields only (kind + span); lexeme-content lives ON the TokenKind variants (Ident(String) / IntLit(String) / etc.). Fix: corrected §4.1 to reflect live carrier shape; payloads on TokenKind variants noted explicitly. 2. §12 Q4 substrate-completeness audit scoped only to tokenize_generated.rs — missed the regen_tokenize codegen- driver boundary. If regen_tokenize carries scanner-logic decisions (rather than mechanical template-rendering of substrate facts), the substrate isn't complete — the driver IS hand-Rust scanner logic in disguise. Fix: Q4 audit extended with (d) regen_tokenize codegen- driver logic audit + (e) ROADMAP.md deferral row option per feedback_paper_shrink_variants P5 receipt discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive overstatements: 1. §2 line 46 claimed "tokenize failures produce typed TokenizeDiagnostic variants" — but live tokenize_generated.rs:96 returns generic `Result<Vec<Token>, Diagnostic>` with `Diagnostic::TokenizerError { message, span, correction }`. Typed TokenizeDiagnostic is a PROPOSED extension, not live state. Fix: §2 reframed with live state explicit + TokenizeDiagnostic marked PROPOSED per PR #3077 §12 Q7 ratification path. 2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly verification" — but live tokenize.dag:16-30+ has TWO explicit tracked scaffold zones: - SG-1a: regen_tokenize parses raw source text for dag_keyword_set / dag_operators (ValueBody::Unparsed) - Character-level under-consumption: StringEscapeSpec / LocalPunctSpec.pattern / string_literal_delimiter as opaque Strings; hidden Rust character predicates (byte.is_ascii_digit etc.) at tokenize_generated.rs:15-22 leaking through codegen Residual hand-Rust is NOT just the codegen artifact — it includes (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold, (c) character-predicate scaffold leaking through codegen. Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER ALONG but not complete"; Step 4 carries scaffold-retirement scope, not just codegen-artifact retirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3127 BLOCKING (review id 12370) — drop TokenizedSource + cite concrete P5 receipts Codex review id 12370 on sha d15e1f2 raised two load-bearing planning-shape findings. Both addressed; this commit ports the same edits already living on fix-forward branch docs/director-l25-postmerge-cleanups (PR #3138 commit 6adb992) onto PR #3127's branch directly so codex BLOCKING resolves on this PR's own HEAD rather than waiting on PR #3138 merge. Finding 1 — parallel boundary carriers (INVARIANTS P2 / Practices 3+5): §4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }` as the output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification removed from the parse L2.5 (PR #3138 §4.3): tokenize sits in the fail-fast output domain alongside PB-3 parse + PB-6 emit (a partial token list with a corrupt token in the middle is not a valid downstream input for parse), so the failure couples via `Result`, not into the structural carrier. Resolution: - §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the live `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension. - §9 Step 2 row signature updated to match; explicit "single canonical boundary carrier: List<Token> on the Ok branch" framing. - §12 Q6 resolved REJECTED in-doc (no operator ratification needed; disposition follows from the cross-stage discriminator load-bearing in PR #3138 parse L2.5). - §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16: Result-sum, no diagnostics field on `List<Token>`. - §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list. Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5): deferral previously named "PB-Bootstrap-Process lane scope" without a concrete ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named receipts: - `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane: author bootstrap.dag + generated trampoline; sized M). - `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification gates). - ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax authorities — phase-2 char-class retype owns the codegen-driver path). - ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating substrate-capability for the phase-2 retype). - ROADMAP.md:53 (T-PB-A — non-test census → 0 floor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING (sha f08b952) Finding 1 — bind to live CharClass authority Porting the same fix that landed on PR #3138 commit 367fdc2 onto PR #3127's own branch so codex BLOCKING resolves on this PR's HEAD directly. Codex Finding 1: §4.2 TokenizeDiagnostic + §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef` — names that exist only in the generated Rust enum spelling, not as a .dag substrate declaration. Live authority is `dsl/std/unicode.dag:62` `type CharClass = Whitespace | Digit | IdentStart | IdentContinue`, consumed at `src/v3/compiler/tokenize.dag:103`. Resolution: - §4.2: `expected_class: ScannerClassRef` → `expected_class: CharClass`; dropped the `type ScannerClassRef = ScannerCharClass` alias; added codex-finding callout citing the substrate authority. - §5.1: heading + intro now cite `dsl/std/unicode.dag:62` directly. - §5.2: heading "CharClass → token-recognition state machine". Same failure-mode as `feedback_grep_substrate_before_naming_ratification`: naming a substrate carrier without grep-verifying against live .dag. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — §7.3 chain Ok-branch annotation Same edit as PR #3138 commit a8c0ff7 ported to this PR's branch. §7.3 cross-stage chain now annotates Ok-branch propagation + Err-branch fail-fast termination explicitly, eliminating the apparent contradiction between §4.3 (Result-sum) and §7.3 (List<Token> in the chain). They were already consistent — Ok-branch payload flows forward; Err terminates — but the annotation makes it self-evident at §7.3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f2) — character-level scaffold dissolution trigger Same edit as PR #3138 commit 5a93d93 ported to this PR's branch. §1 item 2 character-level under-consumption scaffold now carries the same SG-1a-shape dissolution trigger structure: substrate-consumption condition (a) + codegen-driver condition (b) + same-PR delete receipt, with cross-refs to §9 Step 4 gating prereqs already cited. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep Same edit as PR #3138 commit 887c696 ported to this PR's branch. §14 acceptance criterion 11 + §15 step 1 now say "Q1-Q5" with explicit Q6-rejected crossrefs, aligning with §12 Q6 + §14 "Surfaces awaiting" which already said "Q1-Q5 only". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ctions (#3138) * docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14 ratification (Decision 1.A scoping = Option A). PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority already lives in `.dag`: - src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143 lines) - src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE 154 lines) - src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362 lines) This is the END STATE that all other pipeline-stage migrations target. PB-2 L2.5 is correspondingly lighter — mostly verification + residual hand-Rust retirement, NOT new substrate authoring. Distinct §9 4-step framing: - Step 3 = VERIFY substrate completeness (audit per feedback_paper_shrink_variants) - Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding (coordinates with PB-Bootstrap-Process lane for codegen-driver retirement) Captures audit dimensions explicitly: - scanner-class definitions = declarative byte-pattern membership - recognition tables = closed-axis enums - state machine = structural transitions - no V2 `pub mod tokenize` absorption check §12 Q1: codegen-driver retirement scope — Director-recommend PB-Bootstrap-Process handles all codegen-driver retirement cross-cuttingly (not per-stage paper-shrink risk). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md Per cursor PR #3085 finding: §12.6 explicitly tables only 4 pipeline-stage migrations (emit→lower→infer→parse); tokenize is per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085 commit 89fbd7a applied here. INVARIANTS P1 — documentation must not overstate authority cites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty Same class as codex INLINE BLOCKING #3126 finding 1 (live state honesty for diagnostic coupling) applied preemptively to PB-2 tokenize L2.5. PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing which would overstate the live carrier shape (bare List<Token> has no diagnostic field; tokenize_generated.rs:96 today returns Result<Vec<Token>, Diagnostic>). Fix: §4.3 reframed with PROPOSED substrate extension explicit — new `TokenizedSource { tokens, diagnostics }` wrapper carrier as the typed-state output. Step 2 brief includes wrapper authoring in pipeline-slot PR scope. Same discipline as PR #3126 commit bdff8c5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md) Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire" (line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2. Propagated fix applies same cite-error correction as PR #3066 §1.8 discipline: cite the actual doc, not an adjacent doc with similar name. INVARIANTS P2 single-authority-citation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6 Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two substantive contradictions I introduced when adding TokenizedSource in commit 2b9756b: 1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource` but §9 Step 2 row still said `-> List<Token>`. Same `feedback_discipline_change_audit_all_contract_mentions` issue that's recurred 4x this session. 2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor. Fix: 1. §9 Step 2 row updated: signature `-> TokenizedSource` with wrapper carrier shape `{ tokens, diagnostics }` per §4.3 2. §4.3 anchor updated: "§12 Q6" (resolved) 3. Added §12 Q6: TokenizedSource carrier shape ratification — (a) wrapper record vs (b) per-Token diagnostic coupling; Director-recommend (a) for PB-3 SurfaceModule parallelism 4. §14 + §15 + §16 Q-list refs updated to Q1-Q6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary Codex REQUEST_CHANGES (sha b881de2) with 2 substantive findings: 1. §4.1 Token shape claim "optional lexeme: String" — wrong per live substrate at src/v3/std/tokenize.dag:65-67. Live Token has 2 fields only (kind + span); lexeme-content lives ON the TokenKind variants (Ident(String) / IntLit(String) / etc.). Fix: corrected §4.1 to reflect live carrier shape; payloads on TokenKind variants noted explicitly. 2. §12 Q4 substrate-completeness audit scoped only to tokenize_generated.rs — missed the regen_tokenize codegen- driver boundary. If regen_tokenize carries scanner-logic decisions (rather than mechanical template-rendering of substrate facts), the substrate isn't complete — the driver IS hand-Rust scanner logic in disguise. Fix: Q4 audit extended with (d) regen_tokenize codegen- driver logic audit + (e) ROADMAP.md deferral row option per feedback_paper_shrink_variants P5 receipt discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive overstatements: 1. §2 line 46 claimed "tokenize failures produce typed TokenizeDiagnostic variants" — but live tokenize_generated.rs:96 returns generic `Result<Vec<Token>, Diagnostic>` with `Diagnostic::TokenizerError { message, span, correction }`. Typed TokenizeDiagnostic is a PROPOSED extension, not live state. Fix: §2 reframed with live state explicit + TokenizeDiagnostic marked PROPOSED per PR #3077 §12 Q7 ratification path. 2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly verification" — but live tokenize.dag:16-30+ has TWO explicit tracked scaffold zones: - SG-1a: regen_tokenize parses raw source text for dag_keyword_set / dag_operators (ValueBody::Unparsed) - Character-level under-consumption: StringEscapeSpec / LocalPunctSpec.pattern / string_literal_delimiter as opaque Strings; hidden Rust character predicates (byte.is_ascii_digit etc.) at tokenize_generated.rs:15-22 leaking through codegen Residual hand-Rust is NOT just the codegen artifact — it includes (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold, (c) character-predicate scaffold leaking through codegen. Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER ALONG but not complete"; Step 4 carries scaffold-retirement scope, not just codegen-artifact retirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): post-merge fix-forward — §16 + §9 Step 2 internal contradictions Two post-merge doc-internal contradictions caught by reviewers after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z. **PR #3077 PB-4 lower §16 fix**: §16 "Memory disciplines applied" bullet said "diagnostics coupled INTO PreInferDag via biconditional" — but §4.3 (per openai-pro DiagnosticAnchor fix commit b812db9) constrains biconditional to PortAnchor-only. Other anchor kinds (DeclarationAnchor / RecordFieldAnchor / SurfaceFormAnchor) couple without port-state. Fix: §16 bullet honors §4.3 anchor-typed framing. **PR #3126 PB-3 parse §9 Step 2 fix**: §9 Step 2 row described diagnostics as "coupled INTO SurfaceModule" as if live — §4.3 correctly marks it PROPOSED. Same feedback_discipline_change_audit_all_contract_mentions pattern that's recurred this session. Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3"; Step 2 PR scope includes authoring the diagnostics field extension, NOT a live coupling. Per feedback_discipline_change_audit_all_contract_mentions: when a substantive fix changes a discipline framing, audit ALL sections (framing + contract + handoff). Post-merge audit surfaced these residual contradictions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): post-merge fix-forward — PR #3126 codex BLOCKING (GrammarSpec parallel-authority + fail-closed weakening) Codex REQUEST_CHANGES on already-merged PR #3126 (/api/reviews/12175): 2 substantive findings on the post-merge doc. **Finding 1 (P2 violation — GrammarSpec parallel authority)**: §3.2 says GrammarSpec is compile-time-only, NOT runtime- interpreted (per Decision 3.B (b) operator override). But the proposed stage contract still took `grammar: GrammarSpec` as runtime input. Creates two authorities (compiled parser tables + runtime GrammarSpec value). Fix: §4.3 signature reframed to `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` — NO runtime GrammarSpec input. Compile-time generated parser tables consumed via internal dispatch. Step 2 + Step 4 rows updated. **Finding 2 (P3 + Practices 1/2 — fail-closed weakening)**: Live parser at parse_generated.rs:138 returns `Result<SurfaceModule, Diagnostic>` (fail-closed; aborts on first error). Earlier draft proposed `SurfaceModule` with embedded diagnostics — would let partial-parse states be constructible + let downstream observe "success" output after parse failure. Violation of fail-closed discipline. Fix: signature preserves Result-sum (matches live + emit's pattern). Distinguished cross-stage: - Result-sum (parse + emit): fail-fast output domain - Typed-state-with-coupled-diagnostics (lower + infer): structural output domain where partial-failure IS valid intermediate Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 post-merge APPROVE_WITH_COMMENTS — §4.1 + §16 fail-closed honesty Cursor caught 2 more post-merge contradictions on PR #3126: 1. §4.1 line 81 "construction-time invariant" talks about "ParseDiagnostic in the diagnostic stream" tied to SurfaceModule path — but §5.2 + live parse_generated.rs:138 use Result<SurfaceModule, Diagnostic>. §4.1 reads as claim about today's plumbing. Fix: §4.1 reframed — live boundary explicit (Result-sum); construction-time invariant scoped to Ok-arm SurfaceModule + Err-arm ParseDiagnostic, no partial-parse with embedded diagnostics. 2. §16 line 397 cites C-8 as "ParseDiagnostic coupled INTO SurfaceModule" without qualifier — but §4.3 (post codex REQUEST_CHANGES fix) constrains to Result-sum. Fix: §16 bullet honors §4.3 Result-sum framing; cross-stage discriminator named. Same recurring feedback_discipline_change_audit_all_contract_mentions pattern — substantive fix to §4.3 + §9 Step 2 left §4.1 + §16 inconsistent. Post-merge audit catches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING — TypeConnective extension stop-signal Cursor INLINE BLOCKING caught §3.2 line 66 "rules extend automatically" weakens substrate-extension stop-signal. Thesis discipline: a 7th TypeConnective variant requires explicit C1 audit + named infer-rule receipt. Fix: §3.2 reframed. New TypeConnective variants do NOT extend automatically; require explicit C1 substrate-extension audit + named infer-rule receipt for the new variant's structural inference behavior. Per-variant structural facts means new variants need new per-variant facts, NOT silent inheritance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING — AlgebraAxis + InferDiagnostic Practice 4 classification Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed substrate coproducts (AlgebraAxis + InferDiagnostic) lack 🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline Practice 4 (Coproduct dissolution). Fix: added 🟡 SCAFFOLD classification + named dissolution trigger for both: AlgebraAxis 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full algebra-axiom set against infer.rs check sites + verifies coverage parity with live verification.dag:146 AlgebraicLawKind 3-variant subset → promote to 🟢 TERMINAL. InferDiagnostic 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full variant set against parse_generated.rs / lower.rs / infer.rs diagnostic emission sites → promote to 🟢 TERMINAL. - Anti-bridge per Q6.5: does NOT collapse into CompilerDiagnosticKind without substrate-extension ratification per PR #3077 §12 Q7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING — §5.1 SurfaceItem allocation correction Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said "every SurfaceItem variant maps 1:1 to a Declaration placeholder" but live lower.rs:2950-2958 explicitly skips Let/Module/Import in collect_symbols. Verified via Read of lower.rs:2956-2958: SurfaceItem::Let { .. } => continue, SurfaceItem::Module { .. } => continue, SurfaceItem::Import { .. } => continue, Fix: §5.1 reframed — DeclarationAllocating variants (Fn / FnExternalBody / Data / TypeAtom / TypeRecord) map to placeholders; NonDeclarationAllocating variants (Let / Module / Import) skip allocation per live lower.rs behavior. Let-bodies lower to Bind expressions in Pass 2; Module/Import are parsed-facts preserved but un-declared. Earlier "every SurfaceItem variant" framing overstated; would have steered Step 2/3 worker into wrong allocation contract. Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING — ElaborationSpec scope broadened Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only as Surface→Behavior recipe mapping, but lower constructs Declarations / TypeConnectives / BranchPatterns / Bindings as well. Non-Behavior lowering decisions outside declared authority violates THESIS substrate ownership + INVARIANTS P2. Fix: §3.2 ElaborationSpec scope broadened to ALL lowering decisions: 1. SurfaceItem → Declaration recipes (Fn / Data / Type variants + Let/Module/Import skip-allocation per §5.1) 2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose / Disj construction) 3. SurfaceExpr → Behavior recipes (Value / Transform / Branch / Loop / Bind construction) 4. SurfacePattern → BranchPattern recipes (ResolvedVariant / UnresolvedVariant / record-pattern construction) 5. Binding-site rules (Bind params + result_port construction) ElaborationSpec is single-authority across ALL axes; no axis lives in implementation-tier hand-Rust. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — §7.1 ordering vs independence clarification Cursor APPROVE_WITH_COMMENTS /api/reviews/12265 line 197: §7.1 mixed two claims: - "parse migrates AFTER tokenize substrate-side stable" (ordering) - "PB-3 parse migration is independent of PB-2 tokenize migration status" (independence) Read as contradictory by reviewers. Need one coherent story. Fix: §7.1 reframed with two distinct axes explicit: 1. Substrate-stability ordering (SELF_HOSTING.md §2 bottom-up): tokenize Token carrier shape must be stable BEFORE parse migrates. Already true at HEAD (tokenize.dag:65-67 declares live carrier). ✓ 2. Migration-timing independence (parallel-dispatch axis): PB-3 parse migration ships in parallel with PB-2 residual-retirement work (SG-1a + character-level scaffold + codegen-driver retirement per PB-2 L2.5 §1). What parse needs is the stable Token CARRIER; PB-2's migration is about retiring residual hand-Rust, not changing the carrier. Both claims coherent on the axis split; not contradictory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — ParseDiagnostic SourceSpan structural requirement Cursor INLINE BLOCKING /api/reviews/12277 line:65: ParseDiagnostic variants like UnexpectedToken lacked SourceSpan field; List<ParseDiagnostic> cannot satisfy fail-closed source attribution structurally without span on every variant. INVARIANTS P2/P3 violation. Fix: every ParseDiagnostic variant now carries SourceSpan structurally: - UnexpectedToken: added span: SourceSpan - UnterminatedConstruct: opener_span: SourceSpan (already present) - InvalidLiteral: added span: SourceSpan - DuplicateRecordFieldLabel: added span: SourceSpan (current site) + prior_span: SourceSpan (prior site; both required) Per INVARIANTS P2/P3 fail-closed source attribution discipline: every diagnostic emission carries structural source-span provenance; not optional. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Token authority cite phantom-reference fix Cursor INLINE BLOCKING /api/reviews/12279 line:29: §3.1 cited `src/v3/compiler/src/tokenize.rs` as "current hand-Rust" for Token carrier — but `tokenize.rs` (without _generated suffix) doesn't exist. Live state has tokenize.dag (live substrate) + tokenize_generated.rs (codegen artifact). Per design-pure-bootstrap.md PB-2 lane: tokenize retire has substantially landed. The reference was an earlier-draft phantom from when Token-was-hand-Rust framing was the assumption. Fix: §3.1 reframed — Token type lives in LIVE src/v3/std/tokenize.dag:65-67 shared taxonomy; tokenizer implementation also live at src/v3/compiler/tokenize.dag (154 lines); codegen artifact at tokenize_generated.rs. tokenize.rs phantom reference removed explicitly. PB-2 substantially landed per design-pure-bootstrap.md; residual scaffold-retirement scope per PB-2 L2.5 PR #3127. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Step 2 pipeline-slot target fix (compiler.dag → pipeline.dag) Cursor INLINE BLOCKING /api/reviews/12281 line:138: §9 Step 2 referenced generic "compiler.dag" but dsl/gunbc/compiler.dag:24 explicitly directs internal pipeline (Tokenize → Parse → ...) to src/v3/compiler/pipeline.dag, NOT generic compiler.dag. Worker briefs authored against this doc would target the wrong file for pipeline-slot declaration. P2 single-authority violation. Fix: §9 Step 2 row in ALL 4 L2.5 docs (PB-2 / PB-3 / PB-4 / PB-5) updated: - "declared in compiler.dag" → "declared in src/v3/compiler/pipeline.dag (per dsl/gunbc/compiler.dag:24 — internal pipeline lives in pipeline.dag, NOT generic compiler.dag)" - substrate column: "compiler.dag refinement" → "pipeline.dag refinement" - §13 "Step 2 (pipeline-slot in compiler.dag)" → "pipeline-slot in src/v3/compiler/pipeline.dag" Same phantom-citation class as the tokenize.rs phantom (commit 8ae37b4): I cited generic file path without verifying which specific file is authoritative per project structure. Should have grep'd dsl/gunbc/compiler.dag header notes before authoring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Step 3b/4 phasing P5 receipt unambiguity Cursor INLINE BLOCKING /api/reviews/12283 line:181: Q5 said Step 3b "full parser body .dag migration + parser body deletion in same PR", but §15 sequence schedules Step 4 parity/deletion AFTER Step 3b merges. P5 dissolution receipt ambiguous. If Step 3b lands .dag parser body BEFORE Step 4 deletes Rust parse() body, Rust + .dag parser bodies coexist temporarily — paper-shrink-relocation risk per feedback_paper_shrink_variants. Fix: 1. §9 Step 3b row reframed as "Step 3b/4 COMBINED" — atomic single PR (full .dag parser body + parity TestClaim + parse_generated.rs:138 deletion + census shrink). Cannot land .dag parser body before Rust deletion. 2. §12 Q5 phasing clarified: - Phase 3a (separate PR): grammar table extension; P5 receipt = ROADMAP deferral row naming Step 3b/4 as future-receipt - Phase 3b/4 COMBINED (single PR): atomic substrate substitution 3. §9 + §15 update notes: sequence collapses steps 12-17 into single dispatch+merge for combined phase Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 high-level BLOCKING findings 1 + 2 Codex high-level BLOCKING (sha 140eb6b) had 4 findings: - Findings 3 + 4 already addressed in PR #3138 commits 0159773 + a1607a8 - Findings 1 + 2 addressed in this commit **Finding 1 (Diagnostic kind/record conflated)**: §4.2 ParseDiagnostic was modeled as variants-directly with span + kind-fields mixed. Live Diagnostic at diagnostics.dag:150 uses record-wraps-kind pattern (`{ kind, span, message, correction }`). Need consistent shape. Fix: refactored to record-wraps-kind: - `type ParseDiagnostic { kind: ParseDiagnosticKind, span: SourceSpan }` - `type ParseDiagnosticKind = UnexpectedToken | UnterminatedConstruct | InvalidLiteral | DuplicateRecordFieldLabel | ...` Span lives on ParseDiagnostic record (single source of truth); variant-specific spans (opener_span / prior_span) remain on kind variants where meaningful. **Finding 2 (PB-2 §6 obsolete sibling-lane assumption)**: §6 line 198 said "PB-2 Tokenize | src/v3/std/tokenize.dag (NEW per PB-2 L2.5)" — but tokenize.dag is ALREADY LIVE per design-pure-bootstrap.md §"PB-2 — tokenize retire" (substantially landed). Fix: §6 prereq table row updated to reflect LIVE state. PB-2's residual scope is scaffold-retirement (SG-1a + character-level + codegen-driver per PB-2 L2.5 §1), not carrier authoring. PB-3 consumes the live Token carrier; carrier shape stable across PB-2 residual-retirement timing. Findings 3 + 4 already addressed: - Finding 3 (pipeline.dag target): commit 0159773 - Finding 4 (Step 3b/4 atomic vs sequential): commit a1607a8 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — phantom "module-level metadata" removed Cursor APPROVE_WITH_COMMENTS line:79: §4.1 said "SurfaceModule (verified live) carries List<SurfaceItem> + module-level metadata" — but live parse_surface.dag:29 has ONLY `{ items: List<SurfaceItem> }`. No metadata fields. Phantom addition violated INVARIANTS P1 live-state honesty. Fix: §4.1 reframed to match live carrier exactly. Same phantom-addition class as tokenize.rs phantom (commit 8ae37b4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3085 high-level BLOCKING findings — AtomPayload 5-variant + diagnostic-table PROPOSED Codex high-level BLOCKING (sha bf4d315) — 2 substantive findings: **Finding 1 (AtomPayload stale)**: §2 + §5 cited infer.rs:10 top-comment "Atom(Identifier { name, resolved })" — but live substrate.dag:87 has 5-variant AtomPayload sum: Literal | UnresolvedIdentifier | ResolvedByStructure | ResolvedByName | TypeParam. infer.rs top-comment is STALE vs live substrate. My doc inherited the drift. Fix: §2 enumeration corrected to all 5 AtomPayload variants per live substrate.dag:87. **Finding 2 (diagnostic-table PROPOSED, not live)**: §2 + §4.1 + §4.3 said "diagnostics.contains(port_id) biconditional" as if live — but Dag at substrate.dag:525 has ONLY { declarations, nodes, ports, clusters }. NO diagnostics field. Diagnostic-table is PROPOSED substrate extension. Fix: §2 fail-closed note flagged PROPOSED — Step 2 PR scope includes `diagnostics: Map<PortId, Diagnostic>` field extension to Dag, OR PB-Substrate prereq adds it before PB-5 dispatch. Same recurring feedback_grep_carrier_field_before_coupling_claim discipline (PR #3126 SurfaceModule analogous case); needed to grep type Dag fields BEFORE claiming the diagnostics field exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING line:94 — §4.1 + §4.3 PROPOSED diagnostic-table marking Cursor INLINE BLOCKING line:94: §4.1 + §4.3 said "diagnostics coupled INTO InferredDag" without flagging the diagnostic-table as a substrate extension. Live Dag at substrate.dag:525 has { declarations, nodes, ports, clusters } — NO diagnostics field. Earlier commit c0d96af added PROPOSED marking only in §2; §4.1 + §4.3 needed same treatment. Fix: §4.1 + §4.3 reframed with explicit PROPOSED substrate- extension marking + reference to §2 for extension scope. Construction-time invariant + structural coupling are both contingent on the substrate-extension landing (Step 2 PR scope or PB-Substrate prereq). Same recurring feedback_grep_carrier_field_before_coupling_claim discipline applied to §4.1 + §4.3 consistently with §2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3077 high-level BLOCKING — Practice 4 classifications for PB-4 coproducts Codex high-level BLOCKING (sha b812db9): "Diagnostic substrate shape was repaired around anchoring but not re-audited as new substrate type declarations" — meaning DiagnosticAnchor + LowerDiagnostic + SurfaceFormRef + IdentifierRef need 🟢/🟡/🔴 classifications per modeling-discipline Practice 4 (Coproduct dissolution). Same pattern as PB-5 fix in commit 040681f (AlgebraAxis + InferDiagnostic) applied here. Fix: added classifications + dissolution triggers: - SurfaceFormRef 🟢 TERMINAL: closed-axis sum over live Surface* carriers; no further dissolution. - IdentifierRef 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates full identifier-kind set against lower.rs identifier-resolution sites; promote to 🟢 TERMINAL when SurfaceVarRef + TypePathRef + ModulePathRef cover actual axes. - LowerDiagnostic 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates variant set against lower.rs Diagnostic emission sites + Q6.5 anti-bridge preserved + PR #3077 §12 Q7 ratification path. - DiagnosticAnchor 🟢 TERMINAL: closed-axis covering all lowering-stage anchor kinds; no further dissolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING line:161 — DiagnosticSource Practice 4 classification Cursor inline finding adds DiagnosticSource to Practice 4 classification scope. Earlier commit aba79a1 classified SurfaceFormRef + IdentifierRef + LowerDiagnostic + DiagnosticAnchor but missed DiagnosticSource. Fix: DiagnosticSource 🟢 TERMINAL at pipeline-stage discrimination scope. Closed-axis sum (Parse | Lower | Infer | Emit); adding new pipeline stage requires explicit substrate- extension audit per Practice 4 + stop-signal discipline (same shape as PB-5 §3.2 TypeConnective stop-signal). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING line:151 — §11 SurfaceItem::Let + SurfaceLiteral span correction Cursor INLINE BLOCKING line:151: §11 claimed "every Surface variant carries SourceSpan" but live parse_surface.dag has: - SurfaceItem::Let { name, type_ann, expr } — no direct span - SurfaceLiteral = Int(String) | Bool(Bool) | String(String) — plain-tuple variants with no direct span Source-span provenance for these cases is via enclosing carrier: SurfaceLiteral wraps within `Literal { value, span }` at parse_surface.dag:150. Let-item inherits container span. INVARIANTS P2/P3 source provenance is structurally guaranteed via direct-OR-enclosing carrier, but my "every variant" overstatement obscured this. Fix: §11 corrected to "most Surface variants carry SourceSpan directly" + explicit Let + SurfaceLiteral exceptions noted + Step 2 PR scope audits whether exceptions are structural-honest (enclosing-carrier-provides-span) OR require substrate extension. Same recurring overstatement class as earlier "every SurfaceItem maps 1:1 to Declaration" (commit 61e2b67) — need to grep live substrate variant fields BEFORE claiming uniform shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: gunbc Director * docs(r3): cursor PR #3126 INLINE BLOCKING line:32 — GrammarSpec is concept, not carrier Earlier draft (now-merged PR #3126) framed `GrammarSpec` as a second declared `.dag` input type alongside `List<Token>`. Verified via grep that no `type GrammarSpec` exists anywhere under src/v3/ or dsl/ — the repo carries only `parse_tables.dag`'s 6 SG-2c table-families. Per cursor 2026-05-14T23:30:04Z inline finding, this violates INVARIANTS P2 (the Step-2 signature names a carrier the substrate doesn't declare). Reframed §3 (and downstream mentions in §3.2, §3 preamble line:33, §4.2 codex-correction recap line:165, §5.1 line:181, §12 Q6 line:344) so that: - Parse has ONE input at the API boundary: `List<Token>`. - "GrammarSpec" is a concept-level grouping for the 6 compile-time table-families in `parse_tables.dag`, not a substrate carrier and not a runtime parameter. - Step-2 signature stays `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` per cfe842b (already applied in #3126); these edits remove the lingering "two input types" framing that contradicted that signature. Per Decision 3.B (b) compile-time parser tables: substrate authority is parse_tables.dag (6 table-families) consumed via direct table lookups inside the parser body — no runtime grammar value, no `GrammarSpec` carrier needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING — §4.3 + §16 internal contradictions resolved Codex review id 12391 on sha cd6e8d1 flagged two live statements of the already-rejected typed-state-with-coupled-diagnostics model still sitting inside the parse L2.5, contradicting the corrected Result-sum framing in §4.2 and §6 Step 2: 1. §4.3 still proposed a `SurfaceModule { items, diagnostics }` extension modeled on PB-4/PB-5 patterns. Reframed: §4.3 now states explicitly that parse-stage uses Result-sum (no diagnostics field on SurfaceModule), restates the cross-stage discriminator (Result-sum for fail-fast output domains: parse + emit; typed-state for structural output domains: lower + infer), and cites `parse_generated.rs:138` as the live shape. 2. §16 "Memory disciplines applied" bullet read "feedback_state_space_vs_behavioral_invariants (typed-state SurfaceModule at output)". Rewritten to "parse output is `Result<SurfaceModule, ParseDiagnostic>` — the type rules out partial-parse states by construction; SurfaceModule itself carries no diagnostic field per §4.3". Per `feedback_discipline_change_audit_all_contract_mentions`: when a contract changes (here: SurfaceModule extension dropped in favor of Result-sum), all §-internal restatements must be swept in the same diff or they leak through as authoritative parallel claims. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3127 BLOCKING — drop TokenizedSource extension + cite concrete P5 receipts Codex review id 12370 on sha d15e1f2 raised two load-bearing planning-shape findings on the tokenize L2.5. Addressed in this fix-forward branch (PR #3138) since PR #3127 is still open but accumulating cycles. Finding 1 — parallel boundary carriers (INVARIANTS P2 / Modeling Practices 3+5): §4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }` as the output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification I just removed from the parse L2.5 in PR #3138 §4.3: tokenize sits in the fail-fast output domain alongside PB-3 parse + PB-6 emit (a partial token list with a corrupt token in the middle is not a valid downstream input for parse), so the failure couples via `Result`, not into the structural carrier. Resolution: - §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the live `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension. - §9 Step 2 row signature updated to match; explicit "single canonical boundary carrier: List<Token> on the Ok branch" framing. - §12 Q6 resolved REJECTED in-doc (no operator ratification needed; disposition follows from the cross-stage discriminator that's also load-bearing in PR #3138 parse L2.5). - §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16: Result-sum, no diagnostics field on `List<Token>`. - §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list. Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5): deferral previously named "PB-Bootstrap-Process lane scope" without a concrete ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named receipts: - `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane: author bootstrap.dag + generated trampoline; sized M). - `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification gates). - ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax authorities — phase-2 char-class retype owns the codegen-driver path). - ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating substrate-capability for the phase-2 retype). - ROADMAP.md:53 (T-PB-A — non-test census → 0 floor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 BLOCKING line:119 — §6/§7.2/§15 Q7 sequencing resolved by PR #3077 merge Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at merge time of PR #3126) flagged a real internal contradiction: - §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is unblocked" - §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2 worker brief authoring" A worker reading the doc could land Step 2 (pipeline boundary) before the diagnostic carrier's P2/P3 failure shape was fixed. Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z, carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic extension path. The gate IS now satisfied at HEAD, so the resolution is fact-update (annotate Q7 as DONE with the merge timestamp) rather than retracting either §6 or §7.2. Edits: - §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged" and added the explicit "Step 2 is now genuinely unblocked, not just procedurally next" framing so workers reading the sequence don't bypass the gate. - §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief authoring" (future tense, the contradiction surface) to "Gate satisfied 2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring is unblocked at HEAD per §15 step 4." Cites the cursor finding as the resolution path. §6 unblocking statements stay as-is — they were correct at HEAD; the contradiction lived in §7.2's pre-merge framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 BLOCKING (sha 16d21f4) — Q7 cited at every Step 2 unblocking claim Codex BLOCKING finding 2 (sha 16d21f4, 216s thinking): the Q7 dependency was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at §6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without also reading the Q7 prerequisite. Codex framing: "make Q7 a hard precondition wherever Step 2 is called unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate receipts." Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z) and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated all three §6 sites: - Line 191 (Implication for PB-3 migration): cites gate + merge timestamp + explicit "must NOT be brief-authored before that merge timestamp." - Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7 + merge timestamp + P3 failure-shape consequence if violated. - Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4 cross-refs + merge timestamp. Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified already resolved at HEAD via commit c97dc15 — every GrammarSpec mention now explicitly marks it as a concept-not-carrier; Step 2 signature is `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` with no GrammarSpec parameter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3126 BLOCKING (sha 16d21f4) — Step 3b/4 atomicity + Q1 ratification-pending status openai-pro REQUEST_CHANGES on PR #3126 sha 16d21f4 flagged three findings. Findings 1 + 2 (signature vs realization mismatch under LAYER MODEL + P2/P3 boundary discipline) were already resolved at HEAD by earlier fix-forward commits — Step 2 signature is now `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` matching live `parse_generated.rs:138` with no GrammarSpec parameter and no diagnostics-coupled SurfaceModule extension (§4.3 Result-sum disposition). Finding 6 (TRACKED vs UNTRACKED DEBT — Step 3b/4 same-PR vs two-PR): §9 had both a "Step 3b/4 COMBINED" row (line 250) and a leftover separate "Step 4: Parity test" row (line 251) — internally contradictory. §15 also still sequenced Steps 3b + 4 as four separate authoring/dispatch/ratify beats (steps 12-17), contradicting §12 Q5's "same PR" decision and the explicit "Update to §15" note at §12 line 325. Resolution: collapsed §9 to one COMBINED row absorbing the parity-TestClaim mechanics + P5 dissolution receipt from the deleted Step 4 row; collapsed §15 steps 12-17 into single COMBINED authoring + dispatch + ratify (steps 12-14). Added explicit `feedback_paper_shrink_variants` reasoning in both sections. Finding 2.5 (PM intent — substrate-capability bundled vs separate): §12 Q1 line 288 said "Director-recommend: (b) bundled" while §13 line 340 listed substrate-capability as a non-goal of PB-3 and §15 step 11 had "WAIT for substrate-capability landing" — three sections, two different execution paths. Resolution: annotated Q1 as "PENDING operator/PM ratification" with explicit default-execution clause: until operator ratifies, the doc treats substrate-capability as path (a) separate lane (matching §13 + §15 + §9 row). If/when ratified to (b), §13 drops the non-goal and §15 step 11 collapses into the COMBINED Step 3b/4 brief. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 BLOCKING (sha 5619afa) — parse_tables.dag as single enumerated authority Codex caught me copying the prose summary at parse_tables.dag:23-29 (which enumerates only SG-2c-numbered families) instead of grepping the live `^type [A-Z]` declarations. Result: SoftKeywordIdentRow (line 334) was missing from §3.2 / §5.1 / §6 / §12 because it lacks an SG-2c-N number in the prose summary. Per `feedback_parallel_representation_debt`: structural fix is to stop hand-enumerating in the doc — cite parse_tables.dag itself as the single enumerated authority and use `type`-declaration line-anchors for the worked example, not a hand-maintained count. Edits: - §3.2 §"Live substrate authority": replaced the SG-2c-numbered bullet list with `type`-declaration line-anchor enumeration including SoftKeywordIdentRow at parse_tables.dag:334 + the supporting enum BinaryOpLevel at line 133. Added codex-finding callout explaining the miss + the discipline shift. - §3 preamble line:33, §3.2 line:45 callout, §3.2 line:57 framing, §3.2 §"Substrate authority" line:71, §5.1 line:171-180, §12 Q2 line:298, §12 Q6 line:334: all hardcoded "6 table-families" counts dropped; doc now points readers to §3.2 enumeration / `parse_tables.dag` directly. - §5.1 sub-enumeration list (the parallel 6-item list at lines 173-178) deleted; replaced with redirect to §3.2 + restated 3a-vs-3b/4 scope split. Code-level check before commit: `grep -nE '^type [A-Z]' src/v3/compiler/parse_tables.dag` returns 7 types: BinaryOpLevel (133), BinaryOpRow (167), TopLevelItemKwRow (289), SoftKeywordIdentRow (334), BracketRow (385), PrimaryPrefixRow (449), PrimaryAtomRow (486). Doc enumeration matches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING (sha f08b952) — bind TokenizeDiagnostic to live CharClass authority Codex Finding 1 (sha f08b952, 216s thinking): the §4.2 TokenizeDiagnostic draft and the §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef` — names that exist only as the *generated Rust enum spelling*, not as a declared .dag substrate type. Verified via grep: grep -rn '^type CharClass\|^type ScannerC' dsl/ src/v3/ returns ONE authority: `dsl/std/unicode.dag:62` type CharClass = Whitespace | Digit | IdentStart | IdentContinue consumed at `src/v3/compiler/tokenize.dag:103` data ascii_scan_order: List<CharClass> = [Whitespace, Digit, IdentStart, IdentContinue] There is no `ScannerCharClass` declaration anywhere — that name was copied from generated Rust without grep-verification, the same failure mode as `feedback_grep_substrate_before_naming_ratification` (carrier-name collision discipline). Resolution: - §4.2 TokenizeDiagnostic carrier: `expected_class: ScannerClassRef` → `expected_class: CharClass`, dropped the `type ScannerClassRef = ScannerCharClass` alias entirely; added a codex-finding callout citing the substrate authority + naming the failure mode. - §5.1 heading "Byte → ScannerCharClass dispatch" → "Byte → CharClass dispatch"; bullets unchanged; added line-anchor cites for the substrate authority + explicit "NOT ScannerCharClass" disclaimer. - §5.2 heading "ScannerCharClass → token-recognition state machine" → "CharClass → token-recognition state machine". Finding 2 (TokenizedSource not reconciled with parse input contract): no new fix required — already resolved by commit 6adb992 (TokenizedSource extension dropped entirely; tokenize uses Result<List<Token>, TokenizeDiagnostic>; List<Token> is the single canonical boundary carrier consumed by parse). Codex was reviewing sha f08b952, which predated the TokenizedSource drop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — clarify §7.3 chain is Ok-branch propagation Cursor INLINE at sha f08b952 worried that §7.3's cross-stage chain "tokenize → List<Token> → parse → ..." was inconsistent with §4.3's TokenizedSource carrier (diagnostics not flowing forward). At HEAD the TokenizedSource extension is dropped (commit 6adb992); tokenize uses Result<List<Token>, TokenizeDiagnostic>, so List<Token> IS the canonical Ok-branch payload that flows forward and Err branches terminate the pipeline fail-fast. To make this explicit at §7.3 (instead of leaving readers to infer it from §4.3), annotated the chain with: - "Ok-branch propagation; Err branches are stage-terminal fail-fast per §4.3 Result-sum discriminator" framing prefix. - Per-stage Result/typed-state annotations: tokenize/parse show Result<Ok, Err>; lower/infer show typed-state structural-output; emit shows Result<EmittedArtifact, EmissionDiagnostic>. - Explicit "on any stage's Err branch the pipeline aborts at that stage (no partial-output propagation across boundaries)" trailer. This makes the chain self-consistent vis-a-vis §4.3 without requiring the reader to walk back-and-forth, and prevents future readers from re-introducing a TokenizedSource-shaped extension to "make diagnostics flow forward" — they already do, just via the Err branch terminating the pipeline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f2) — character-level scaffold dissolution trigger openai-pro REQUEST_CHANGES on sha d15e1f2: §1 line:26 character-level under-consumption scaffold named the problem but lacked a checkable dissolution trigger. SG-1a scaffold above had the right shape — "once those bodies lower structurally under compile_to_dag, delete the raw-text extractor + derive directly from lowered Dag in same PR." Character-level scaffold just said "PB-2 Step 4 carries this scope" — a lane assignment, not a trigger. Resolution: rewrote §1 item 2 with the same SG-1a-shape trigger structure: - Substrate-consumption condition (a): scanner classes / string escape / local punctuation retype to `dsl/std/unicode.dag` `CharClass` / `char_in_class` (concrete field retypes named: `StringEscapeSpec.suffix: Char`, `LocalPunctSpec.pattern: List<Char>`, `string_literal_delimiter: Char`). - Codegen-driver condition (b): `tokenize_generated.rs` no longer emits hidden `byte.is_ascii_*` predicates because the driver reads class facts structurally from lowered `tokenize.dag`. - Same-PR dissolution: delete the parallel character-predicate scaffold in the same PR that flips substrate consumption — no Rust-and-`.dag` coexistence per `feedback_paper_shrink_variants`. - Cross-ref to §9 Step 4 gating prereqs: ROADMAP.md:467 + ROADMAP.md:416 Class 5 Gap 3 + std.unicode bootstrap/load-set decision (already cited in §9 from earlier commit 6adb992). Per openai-pro's framing: "small fix — mirror the SG-1a scaffold wording by naming the exact substrate-consumption condition and same-PR deletion receipt for the hidden Rust character predicates." Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: gunbc Director * docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep Cursor review id 12405 (APPROVE_WITH_COMMENTS) caught the same `feedback_discipline_change_audit_all_contract_mentions` failure mode recurring: §12 Q6 was resolved REJECTED in commit 6adb992, and §14 "Surfaces awaiting" + §12 Q6 heading + §9 Step 2 row were updated, but two §-internal contract restatements were missed: - §14 acceptance criterion 11: "Operator/PM ratification on §12 Q1-Q6" - §15 step 1: "Operator / PM-delegate ratifies §12 Q1-Q6" Both contradicted §12 Q6 + §14 "Surfaces awaiting" (which already said "Q1-Q5 only"). A worker reading §14/§15 could schedule sign-offs on Q6 after it was already resolved-rejected elsewhere. Resolution: both sites now say "Q1–Q5" with the explicit Q6-rejected crossref + "see §14/§15 for same scoping" pointer at the §14 criterion so the three sections agree internally. Cursor verdict was APPROVE_WITH_COMMENTS (substantive APPROVE — "fix the checklist/sequence so every section agrees Q6 is closed"); the exploratory volatile-line-anchor note is harmless and out-of-scope for this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same edits as PR #3138 commit e9739ea's tokenize-doc portion ported to this PR's branch. Finding 2 — TokenizeDiagnostic coproduct receipt: Added 🟡 SCAFFOLD classification + dissolution trigger (tokenize-stage only: Step 2 enumerates against tokenize_generated.rs:96 Diagnostic::* sites) + anti-bridge note per Q6.5. Finding 3 — Q7 reconciliation: §4.2 "Lane dependency", §15 step 3, and §14 "Surfaces awaiting" now all annotate Q7 as DONE 2026-05-15T00:21:19Z (PR #3077 merge timestamp); TokenizeDiagnostic per-stage variant authoring is the remaining lane work. (Finding 1 — infer-doc cross-stage trigger leak — does not apply to this branch; it lives on PR #3138's branch which carries the infer L2.5 doc.) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…iting Q7 contradiction Cursor inline at sha 887c696 caught the symmetric finding to the codex 5-finding BLOCKING #3: parse-doc §15 step 4 already annotated Q7 as DONE (commit f85fa1f) but parse-doc §16 "Surfaces awaiting" still listed Q7 as pending. Same `feedback_discipline_change_audit_all_contract_mentions` sweep failure — the tokenize doc had three sites carrying the pending framing (commit e9739ea fixed those) but the parse doc's §16 site was missed in the original Q7-DONE sweep. Resolution: §16 bullet now strikes through + "DONE 2026-05-15T00:21:19Z (PR #3077 merged carrying Q7 ratification; see §15 step 4)" — same shape as the tokenize doc's §14 "Surfaces awaiting" Q7-DONE annotation landed in e9739ea. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r inline Q7 sweep (#3140) * docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14 ratification (Decision 1.A scoping = Option A). PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority already lives in `.dag`: - src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143 lines) - src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE 154 lines) - src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362 lines) This is the END STATE that all other pipeline-stage migrations target. PB-2 L2.5 is correspondingly lighter — mostly verification + residual hand-Rust retirement, NOT new substrate authoring. Distinct §9 4-step framing: - Step 3 = VERIFY substrate completeness (audit per feedback_paper_shrink_variants) - Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding (coordinates with PB-Bootstrap-Process lane for codegen-driver retirement) Captures audit dimensions explicitly: - scanner-class definitions = declarative byte-pattern membership - recognition tables = closed-axis enums - state machine = structural transitions - no V2 `pub mod tokenize` absorption check §12 Q1: codegen-driver retirement scope — Director-recommend PB-Bootstrap-Process handles all codegen-driver retirement cross-cuttingly (not per-stage paper-shrink risk). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md Per cursor PR #3085 finding: §12.6 explicitly tables only 4 pipeline-stage migrations (emit→lower→infer→parse); tokenize is per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085 commit 89fbd7a applied here. INVARIANTS P1 — documentation must not overstate authority cites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty Same class as codex INLINE BLOCKING #3126 finding 1 (live state honesty for diagnostic coupling) applied preemptively to PB-2 tokenize L2.5. PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing which would overstate the live carrier shape (bare List<Token> has no diagnostic field; tokenize_generated.rs:96 today returns Result<Vec<Token>, Diagnostic>). Fix: §4.3 reframed with PROPOSED substrate extension explicit — new `TokenizedSource { tokens, diagnostics }` wrapper carrier as the typed-state output. Step 2 brief includes wrapper authoring in pipeline-slot PR scope. Same discipline as PR #3126 commit bdff8c5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md) Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire" (line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2. Propagated fix applies same cite-error correction as PR #3066 §1.8 discipline: cite the actual doc, not an adjacent doc with similar name. INVARIANTS P2 single-authority-citation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6 Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two substantive contradictions I introduced when adding TokenizedSource in commit 2b9756b: 1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource` but §9 Step 2 row still said `-> List<Token>`. Same `feedback_discipline_change_audit_all_contract_mentions` issue that's recurred 4x this session. 2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor. Fix: 1. §9 Step 2 row updated: signature `-> TokenizedSource` with wrapper carrier shape `{ tokens, diagnostics }` per §4.3 2. §4.3 anchor updated: "§12 Q6" (resolved) 3. Added §12 Q6: TokenizedSource carrier shape ratification — (a) wrapper record vs (b) per-Token diagnostic coupling; Director-recommend (a) for PB-3 SurfaceModule parallelism 4. §14 + §15 + §16 Q-list refs updated to Q1-Q6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary Codex REQUEST_CHANGES (sha b881de2) with 2 substantive findings: 1. §4.1 Token shape claim "optional lexeme: String" — wrong per live substrate at src/v3/std/tokenize.dag:65-67. Live Token has 2 fields only (kind + span); lexeme-content lives ON the TokenKind variants (Ident(String) / IntLit(String) / etc.). Fix: corrected §4.1 to reflect live carrier shape; payloads on TokenKind variants noted explicitly. 2. §12 Q4 substrate-completeness audit scoped only to tokenize_generated.rs — missed the regen_tokenize codegen- driver boundary. If regen_tokenize carries scanner-logic decisions (rather than mechanical template-rendering of substrate facts), the substrate isn't complete — the driver IS hand-Rust scanner logic in disguise. Fix: Q4 audit extended with (d) regen_tokenize codegen- driver logic audit + (e) ROADMAP.md deferral row option per feedback_paper_shrink_variants P5 receipt discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive overstatements: 1. §2 line 46 claimed "tokenize failures produce typed TokenizeDiagnostic variants" — but live tokenize_generated.rs:96 returns generic `Result<Vec<Token>, Diagnostic>` with `Diagnostic::TokenizerError { message, span, correction }`. Typed TokenizeDiagnostic is a PROPOSED extension, not live state. Fix: §2 reframed with live state explicit + TokenizeDiagnostic marked PROPOSED per PR #3077 §12 Q7 ratification path. 2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly verification" — but live tokenize.dag:16-30+ has TWO explicit tracked scaffold zones: - SG-1a: regen_tokenize parses raw source text for dag_keyword_set / dag_operators (ValueBody::Unparsed) - Character-level under-consumption: StringEscapeSpec / LocalPunctSpec.pattern / string_literal_delimiter as opaque Strings; hidden Rust character predicates (byte.is_ascii_digit etc.) at tokenize_generated.rs:15-22 leaking through codegen Residual hand-Rust is NOT just the codegen artifact — it includes (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold, (c) character-predicate scaffold leaking through codegen. Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER ALONG but not complete"; Step 4 carries scaffold-retirement scope, not just codegen-artifact retirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): post-merge fix-forward — §16 + §9 Step 2 internal contradictions Two post-merge doc-internal contradictions caught by reviewers after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z. **PR #3077 PB-4 lower §16 fix**: §16 "Memory disciplines applied" bullet said "diagnostics coupled INTO PreInferDag via biconditional" — but §4.3 (per openai-pro DiagnosticAnchor fix commit b812db9) constrains biconditional to PortAnchor-only. Other anchor kinds (DeclarationAnchor / RecordFieldAnchor / SurfaceFormAnchor) couple without port-state. Fix: §16 bullet honors §4.3 anchor-typed framing. **PR #3126 PB-3 parse §9 Step 2 fix**: §9 Step 2 row described diagnostics as "coupled INTO SurfaceModule" as if live — §4.3 correctly marks it PROPOSED. Same feedback_discipline_change_audit_all_contract_mentions pattern that's recurred this session. Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3"; Step 2 PR scope includes authoring the diagnostics field extension, NOT a live coupling. Per feedback_discipline_change_audit_all_contract_mentions: when a substantive fix changes a discipline framing, audit ALL sections (framing + contract + handoff). Post-merge audit surfaced these residual contradictions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): post-merge fix-forward — PR #3126 codex BLOCKING (GrammarSpec parallel-authority + fail-closed weakening) Codex REQUEST_CHANGES on already-merged PR #3126 (/api/reviews/12175): 2 substantive findings on the post-merge doc. **Finding 1 (P2 violation — GrammarSpec parallel authority)**: §3.2 says GrammarSpec is compile-time-only, NOT runtime- interpreted (per Decision 3.B (b) operator override). But the proposed stage contract still took `grammar: GrammarSpec` as runtime input. Creates two authorities (compiled parser tables + runtime GrammarSpec value). Fix: §4.3 signature reframed to `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` — NO runtime GrammarSpec input. Compile-time generated parser tables consumed via internal dispatch. Step 2 + Step 4 rows updated. **Finding 2 (P3 + Practices 1/2 — fail-closed weakening)**: Live parser at parse_generated.rs:138 returns `Result<SurfaceModule, Diagnostic>` (fail-closed; aborts on first error). Earlier draft proposed `SurfaceModule` with embedded diagnostics — would let partial-parse states be constructible + let downstream observe "success" output after parse failure. Violation of fail-closed discipline. Fix: signature preserves Result-sum (matches live + emit's pattern). Distinguished cross-stage: - Result-sum (parse + emit): fail-fast output domain - Typed-state-with-coupled-diagnostics (lower + infer): structural output domain where partial-failure IS valid intermediate Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 post-merge APPROVE_WITH_COMMENTS — §4.1 + §16 fail-closed honesty Cursor caught 2 more post-merge contradictions on PR #3126: 1. §4.1 line 81 "construction-time invariant" talks about "ParseDiagnostic in the diagnostic stream" tied to SurfaceModule path — but §5.2 + live parse_generated.rs:138 use Result<SurfaceModule, Diagnostic>. §4.1 reads as claim about today's plumbing. Fix: §4.1 reframed — live boundary explicit (Result-sum); construction-time invariant scoped to Ok-arm SurfaceModule + Err-arm ParseDiagnostic, no partial-parse with embedded diagnostics. 2. §16 line 397 cites C-8 as "ParseDiagnostic coupled INTO SurfaceModule" without qualifier — but §4.3 (post codex REQUEST_CHANGES fix) constrains to Result-sum. Fix: §16 bullet honors §4.3 Result-sum framing; cross-stage discriminator named. Same recurring feedback_discipline_change_audit_all_contract_mentions pattern — substantive fix to §4.3 + §9 Step 2 left §4.1 + §16 inconsistent. Post-merge audit catches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING — TypeConnective extension stop-signal Cursor INLINE BLOCKING caught §3.2 line 66 "rules extend automatically" weakens substrate-extension stop-signal. Thesis discipline: a 7th TypeConnective variant requires explicit C1 audit + named infer-rule receipt. Fix: §3.2 reframed. New TypeConnective variants do NOT extend automatically; require explicit C1 substrate-extension audit + named infer-rule receipt for the new variant's structural inference behavior. Per-variant structural facts means new variants need new per-variant facts, NOT silent inheritance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING — AlgebraAxis + InferDiagnostic Practice 4 classification Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed substrate coproducts (AlgebraAxis + InferDiagnostic) lack 🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline Practice 4 (Coproduct dissolution). Fix: added 🟡 SCAFFOLD classification + named dissolution trigger for both: AlgebraAxis 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full algebra-axiom set against infer.rs check sites + verifies coverage parity with live verification.dag:146 AlgebraicLawKind 3-variant subset → promote to 🟢 TERMINAL. InferDiagnostic 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full variant set against parse_generated.rs / lower.rs / infer.rs diagnostic emission sites → promote to 🟢 TERMINAL. - Anti-bridge per Q6.5: does NOT collapse into CompilerDiagnosticKind without substrate-extension ratification per PR #3077 §12 Q7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING — §5.1 SurfaceItem allocation correction Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said "every SurfaceItem variant maps 1:1 to a Declaration placeholder" but live lower.rs:2950-2958 explicitly skips Let/Module/Import in collect_symbols. Verified via Read of lower.rs:2956-2958: SurfaceItem::Let { .. } => continue, SurfaceItem::Module { .. } => continue, SurfaceItem::Import { .. } => continue, Fix: §5.1 reframed — DeclarationAllocating variants (Fn / FnExternalBody / Data / TypeAtom / TypeRecord) map to placeholders; NonDeclarationAllocating variants (Let / Module / Import) skip allocation per live lower.rs behavior. Let-bodies lower to Bind expressions in Pass 2; Module/Import are parsed-facts preserved but un-declared. Earlier "every SurfaceItem variant" framing overstated; would have steered Step 2/3 worker into wrong allocation contract. Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING — ElaborationSpec scope broadened Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only as Surface→Behavior recipe mapping, but lower constructs Declarations / TypeConnectives / BranchPatterns / Bindings as well. Non-Behavior lowering decisions outside declared authority violates THESIS substrate ownership + INVARIANTS P2. Fix: §3.2 ElaborationSpec scope broadened to ALL lowering decisions: 1. SurfaceItem → Declaration recipes (Fn / Data / Type variants + Let/Module/Import skip-allocation per §5.1) 2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose / Disj construction) 3. SurfaceExpr → Behavior recipes (Value / Transform / Branch / Loop / Bind construction) 4. SurfacePattern → BranchPattern recipes (ResolvedVariant / UnresolvedVariant / record-pattern construction) 5. Binding-site rules (Bind params + result_port construction) ElaborationSpec is single-authority across ALL axes; no axis lives in implementation-tier hand-Rust. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — §7.1 ordering vs independence clarification Cursor APPROVE_WITH_COMMENTS /api/reviews/12265 line 197: §7.1 mixed two claims: - "parse migrates AFTER tokenize substrate-side stable" (ordering) - "PB-3 parse migration is independent of PB-2 tokenize migration status" (independence) Read as contradictory by reviewers. Need one coherent story. Fix: §7.1 reframed with two distinct axes explicit: 1. Substrate-stability ordering (SELF_HOSTING.md §2 bottom-up): tokenize Token carrier shape must be stable BEFORE parse migrates. Already true at HEAD (tokenize.dag:65-67 declares live carrier). ✓ 2. Migration-timing independence (parallel-dispatch axis): PB-3 parse migration ships in parallel with PB-2 residual-retirement work (SG-1a + character-level scaffold + codegen-driver retirement per PB-2 L2.5 §1). What parse needs is the stable Token CARRIER; PB-2's migration is about retiring residual hand-Rust, not changing the carrier. Both claims coherent on the axis split; not contradictory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — ParseDiagnostic SourceSpan structural requirement Cursor INLINE BLOCKING /api/reviews/12277 line:65: ParseDiagnostic variants like UnexpectedToken lacked SourceSpan field; List<ParseDiagnostic> cannot satisfy fail-closed source attribution structurally without span on every variant. INVARIANTS P2/P3 violation. Fix: every ParseDiagnostic variant now carries SourceSpan structurally: - UnexpectedToken: added span: SourceSpan - UnterminatedConstruct: opener_span: SourceSpan (already present) - InvalidLiteral: added span: SourceSpan - DuplicateRecordFieldLabel: added span: SourceSpan (current site) + prior_span: SourceSpan (prior site; both required) Per INVARIANTS P2/P3 fail-closed source attribution discipline: every diagnostic emission carries structural source-span provenance; not optional. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Token authority cite phantom-reference fix Cursor INLINE BLOCKING /api/reviews/12279 line:29: §3.1 cited `src/v3/compiler/src/tokenize.rs` as "current hand-Rust" for Token carrier — but `tokenize.rs` (without _generated suffix) doesn't exist. Live state has tokenize.dag (live substrate) + tokenize_generated.rs (codegen artifact). Per design-pure-bootstrap.md PB-2 lane: tokenize retire has substantially landed. The reference was an earlier-draft phantom from when Token-was-hand-Rust framing was the assumption. Fix: §3.1 reframed — Token type lives in LIVE src/v3/std/tokenize.dag:65-67 shared taxonomy; tokenizer implementation also live at src/v3/compiler/tokenize.dag (154 lines); codegen artifact at tokenize_generated.rs. tokenize.rs phantom reference removed explicitly. PB-2 substantially landed per design-pure-bootstrap.md; residual scaffold-retirement scope per PB-2 L2.5 PR #3127. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Step 2 pipeline-slot target fix (compiler.dag → pipeline.dag) Cursor INLINE BLOCKING /api/reviews/12281 line:138: §9 Step 2 referenced generic "compiler.dag" but dsl/gunbc/compiler.dag:24 explicitly directs internal pipeline (Tokenize → Parse → ...) to src/v3/compiler/pipeline.dag, NOT generic compiler.dag. Worker briefs authored against this doc would target the wrong file for pipeline-slot declaration. P2 single-authority violation. Fix: §9 Step 2 row in ALL 4 L2.5 docs (PB-2 / PB-3 / PB-4 / PB-5) updated: - "declared in compiler.dag" → "declared in src/v3/compiler/pipeline.dag (per dsl/gunbc/compiler.dag:24 — internal pipeline lives in pipeline.dag, NOT generic compiler.dag)" - substrate column: "compiler.dag refinement" → "pipeline.dag refinement" - §13 "Step 2 (pipeline-slot in compiler.dag)" → "pipeline-slot in src/v3/compiler/pipeline.dag" Same phantom-citation class as the tokenize.rs phantom (commit 8ae37b4): I cited generic file path without verifying which specific file is authoritative per project structure. Should have grep'd dsl/gunbc/compiler.dag header notes before authoring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Step 3b/4 phasing P5 receipt unambiguity Cursor INLINE BLOCKING /api/reviews/12283 line:181: Q5 said Step 3b "full parser body .dag migration + parser body deletion in same PR", but §15 sequence schedules Step 4 parity/deletion AFTER Step 3b merges. P5 dissolution receipt ambiguous. If Step 3b lands .dag parser body BEFORE Step 4 deletes Rust parse() body, Rust + .dag parser bodies coexist temporarily — paper-shrink-relocation risk per feedback_paper_shrink_variants. Fix: 1. §9 Step 3b row reframed as "Step 3b/4 COMBINED" — atomic single PR (full .dag parser body + parity TestClaim + parse_generated.rs:138 deletion + census shrink). Cannot land .dag parser body before Rust deletion. 2. §12 Q5 phasing clarified: - Phase 3a (separate PR): grammar table extension; P5 receipt = ROADMAP deferral row naming Step 3b/4 as future-receipt - Phase 3b/4 COMBINED (single PR): atomic substrate substitution 3. §9 + §15 update notes: sequence collapses steps 12-17 into single dispatch+merge for combined phase Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 high-level BLOCKING findings 1 + 2 Codex high-level BLOCKING (sha 140eb6b) had 4 findings: - Findings 3 + 4 already addressed in PR #3138 commits 0159773 + a1607a8 - Findings 1 + 2 addressed in this commit **Finding 1 (Diagnostic kind/record conflated)**: §4.2 ParseDiagnostic was modeled as variants-directly with span + kind-fields mixed. Live Diagnostic at diagnostics.dag:150 uses record-wraps-kind pattern (`{ kind, span, message, correction }`). Need consistent shape. Fix: refactored to record-wraps-kind: - `type ParseDiagnostic { kind: ParseDiagnosticKind, span: SourceSpan }` - `type ParseDiagnosticKind = UnexpectedToken | UnterminatedConstruct | InvalidLiteral | DuplicateRecordFieldLabel | ...` Span lives on ParseDiagnostic record (single source of truth); variant-specific spans (opener_span / prior_span) remain on kind variants where meaningful. **Finding 2 (PB-2 §6 obsolete sibling-lane assumption)**: §6 line 198 said "PB-2 Tokenize | src/v3/std/tokenize.dag (NEW per PB-2 L2.5)" — but tokenize.dag is ALREADY LIVE per design-pure-bootstrap.md §"PB-2 — tokenize retire" (substantially landed). Fix: §6 prereq table row updated to reflect LIVE state. PB-2's residual scope is scaffold-retirement (SG-1a + character-level + codegen-driver per PB-2 L2.5 §1), not carrier authoring. PB-3 consumes the live Token carrier; carrier shape stable across PB-2 residual-retirement timing. Findings 3 + 4 already addressed: - Finding 3 (pipeline.dag target): commit 0159773 - Finding 4 (Step 3b/4 atomic vs sequential): commit a1607a8 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — phantom "module-level metadata" removed Cursor APPROVE_WITH_COMMENTS line:79: §4.1 said "SurfaceModule (verified live) carries List<SurfaceItem> + module-level metadata" — but live parse_surface.dag:29 has ONLY `{ items: List<SurfaceItem> }`. No metadata fields. Phantom addition violated INVARIANTS P1 live-state honesty. Fix: §4.1 reframed to match live carrier exactly. Same phantom-addition class as tokenize.rs phantom (commit 8ae37b4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3085 high-level BLOCKING findings — AtomPayload 5-variant + diagnostic-table PROPOSED Codex high-level BLOCKING (sha bf4d315) — 2 substantive findings: **Finding 1 (AtomPayload stale)**: §2 + §5 cited infer.rs:10 top-comment "Atom(Identifier { name, resolved })" — but live substrate.dag:87 has 5-variant AtomPayload sum: Literal | UnresolvedIdentifier | ResolvedByStructure | ResolvedByName | TypeParam. infer.rs top-comment is STALE vs live substrate. My doc inherited the drift. Fix: §2 enumeration corrected to all 5 AtomPayload variants per live substrate.dag:87. **Finding 2 (diagnostic-table PROPOSED, not live)**: §2 + §4.1 + §4.3 said "diagnostics.contains(port_id) biconditional" as if live — but Dag at substrate.dag:525 has ONLY { declarations, nodes, ports, clusters }. NO diagnostics field. Diagnostic-table is PROPOSED substrate extension. Fix: §2 fail-closed note flagged PROPOSED — Step 2 PR scope includes `diagnostics: Map<PortId, Diagnostic>` field extension to Dag, OR PB-Substrate prereq adds it before PB-5 dispatch. Same recurring feedback_grep_carrier_field_before_coupling_claim discipline (PR #3126 SurfaceModule analogous case); needed to grep type Dag fields BEFORE claiming the diagnostics field exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING line:94 — §4.1 + §4.3 PROPOSED diagnostic-table marking Cursor INLINE BLOCKING line:94: §4.1 + §4.3 said "diagnostics coupled INTO InferredDag" without flagging the diagnostic-table as a substrate extension. Live Dag at substrate.dag:525 has { declarations, nodes, ports, clusters } — NO diagnostics field. Earlier commit c0d96af added PROPOSED marking only in §2; §4.1 + §4.3 needed same treatment. Fix: §4.1 + §4.3 reframed with explicit PROPOSED substrate- extension marking + reference to §2 for extension scope. Construction-time invariant + structural coupling are both contingent on the substrate-extension landing (Step 2 PR scope or PB-Substrate prereq). Same recurring feedback_grep_carrier_field_before_coupling_claim discipline applied to §4.1 + §4.3 consistently with §2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3077 high-level BLOCKING — Practice 4 classifications for PB-4 coproducts Codex high-level BLOCKING (sha b812db9): "Diagnostic substrate shape was repaired around anchoring but not re-audited as new substrate type declarations" — meaning DiagnosticAnchor + LowerDiagnostic + SurfaceFormRef + IdentifierRef need 🟢/🟡/🔴 classifications per modeling-discipline Practice 4 (Coproduct dissolution). Same pattern as PB-5 fix in commit 040681f (AlgebraAxis + InferDiagnostic) applied here. Fix: added classifications + dissolution triggers: - SurfaceFormRef 🟢 TERMINAL: closed-axis sum over live Surface* carriers; no further dissolution. - IdentifierRef 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates full identifier-kind set against lower.rs identifier-resolution sites; promote to 🟢 TERMINAL when SurfaceVarRef + TypePathRef + ModulePathRef cover actual axes. - LowerDiagnostic 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates variant set against lower.rs Diagnostic emission sites + Q6.5 anti-bridge preserved + PR #3077 §12 Q7 ratification path. - DiagnosticAnchor 🟢 TERMINAL: closed-axis covering all lowering-stage anchor kinds; no further dissolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING line:161 — DiagnosticSource Practice 4 classification Cursor inline finding adds DiagnosticSource to Practice 4 classification scope. Earlier commit aba79a1 classified SurfaceFormRef + IdentifierRef + LowerDiagnostic + DiagnosticAnchor but missed DiagnosticSource. Fix: DiagnosticSource 🟢 TERMINAL at pipeline-stage discrimination scope. Closed-axis sum (Parse | Lower | Infer | Emit); adding new pipeline stage requires explicit substrate- extension audit per Practice 4 + stop-signal discipline (same shape as PB-5 §3.2 TypeConnective stop-signal). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING line:151 — §11 SurfaceItem::Let + SurfaceLiteral span correction Cursor INLINE BLOCKING line:151: §11 claimed "every Surface variant carries SourceSpan" but live parse_surface.dag has: - SurfaceItem::Let { name, type_ann, expr } — no direct span - SurfaceLiteral = Int(String) | Bool(Bool) | String(String) — plain-tuple variants with no direct span Source-span provenance for these cases is via enclosing carrier: SurfaceLiteral wraps within `Literal { value, span }` at parse_surface.dag:150. Let-item inherits container span. INVARIANTS P2/P3 source provenance is structurally guaranteed via direct-OR-enclosing carrier, but my "every variant" overstatement obscured this. Fix: §11 corrected to "most Surface variants carry SourceSpan directly" + explicit Let + SurfaceLiteral exceptions noted + Step 2 PR scope audits whether exceptions are structural-honest (enclosing-carrier-provides-span) OR require substrate extension. Same recurring overstatement class as earlier "every SurfaceItem maps 1:1 to Declaration" (commit 61e2b67) — need to grep live substrate variant fields BEFORE claiming uniform shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: gunbc Director * docs(r3): cursor PR #3126 INLINE BLOCKING line:32 — GrammarSpec is concept, not carrier Earlier draft (now-merged PR #3126) framed `GrammarSpec` as a second declared `.dag` input type alongside `List<Token>`. Verified via grep that no `type GrammarSpec` exists anywhere under src/v3/ or dsl/ — the repo carries only `parse_tables.dag`'s 6 SG-2c table-families. Per cursor 2026-05-14T23:30:04Z inline finding, this violates INVARIANTS P2 (the Step-2 signature names a carrier the substrate doesn't declare). Reframed §3 (and downstream mentions in §3.2, §3 preamble line:33, §4.2 codex-correction recap line:165, §5.1 line:181, §12 Q6 line:344) so that: - Parse has ONE input at the API boundary: `List<Token>`. - "GrammarSpec" is a concept-level grouping for the 6 compile-time table-families in `parse_tables.dag`, not a substrate carrier and not a runtime parameter. - Step-2 signature stays `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` per cfe842b (already applied in #3126); these edits remove the lingering "two input types" framing that contradicted that signature. Per Decision 3.B (b) compile-time parser tables: substrate authority is parse_tables.dag (6 table-families) consumed via direct table lookups inside the parser body — no runtime grammar value, no `GrammarSpec` carrier needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING — §4.3 + §16 internal contradictions resolved Codex review id 12391 on sha cd6e8d1 flagged two live statements of the already-rejected typed-state-with-coupled-diagnostics model still sitting inside the parse L2.5, contradicting the corrected Result-sum framing in §4.2 and §6 Step 2: 1. §4.3 still proposed a `SurfaceModule { items, diagnostics }` extension modeled on PB-4/PB-5 patterns. Reframed: §4.3 now states explicitly that parse-stage uses Result-sum (no diagnostics field on SurfaceModule), restates the cross-stage discriminator (Result-sum for fail-fast output domains: parse + emit; typed-state for structural output domains: lower + infer), and cites `parse_generated.rs:138` as the live shape. 2. §16 "Memory disciplines applied" bullet read "feedback_state_space_vs_behavioral_invariants (typed-state SurfaceModule at output)". Rewritten to "parse output is `Result<SurfaceModule, ParseDiagnostic>` — the type rules out partial-parse states by construction; SurfaceModule itself carries no diagnostic field per §4.3". Per `feedback_discipline_change_audit_all_contract_mentions`: when a contract changes (here: SurfaceModule extension dropped in favor of Result-sum), all §-internal restatements must be swept in the same diff or they leak through as authoritative parallel claims. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3127 BLOCKING — drop TokenizedSource extension + cite concrete P5 receipts Codex review id 12370 on sha d15e1f2 raised two load-bearing planning-shape findings on the tokenize L2.5. Addressed in this fix-forward branch (PR #3138) since PR #3127 is still open but accumulating cycles. Finding 1 — parallel boundary carriers (INVARIANTS P2 / Modeling Practices 3+5): §4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }` as the output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification I just removed from the parse L2.5 in PR #3138 §4.3: tokenize sits in the fail-fast output domain alongside PB-3 parse + PB-6 emit (a partial token list with a corrupt token in the middle is not a valid downstream input for parse), so the failure couples via `Result`, not into the structural carrier. Resolution: - §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the live `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension. - §9 Step 2 row signature updated to match; explicit "single canonical boundary carrier: List<Token> on the Ok branch" framing. - §12 Q6 resolved REJECTED in-doc (no operator ratification needed; disposition follows from the cross-stage discriminator that's also load-bearing in PR #3138 parse L2.5). - §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16: Result-sum, no diagnostics field on `List<Token>`. - §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list. Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5): deferral previously named "PB-Bootstrap-Process lane scope" without a concrete ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named receipts: - `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane: author bootstrap.dag + generated trampoline; sized M). - `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification gates). - ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax authorities — phase-2 char-class retype owns the codegen-driver path). - ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating substrate-capability for the phase-2 retype). - ROADMAP.md:53 (T-PB-A — non-test census → 0 floor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 BLOCKING line:119 — §6/§7.2/§15 Q7 sequencing resolved by PR #3077 merge Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at merge time of PR #3126) flagged a real internal contradiction: - §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is unblocked" - §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2 worker brief authoring" A worker reading the doc could land Step 2 (pipeline boundary) before the diagnostic carrier's P2/P3 failure shape was fixed. Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z, carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic extension path. The gate IS now satisfied at HEAD, so the resolution is fact-update (annotate Q7 as DONE with the merge timestamp) rather than retracting either §6 or §7.2. Edits: - §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged" and added the explicit "Step 2 is now genuinely unblocked, not just procedurally next" framing so workers reading the sequence don't bypass the gate. - §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief authoring" (future tense, the contradiction surface) to "Gate satisfied 2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring is unblocked at HEAD per §15 step 4." Cites the cursor finding as the resolution path. §6 unblocking statements stay as-is — they were correct at HEAD; the contradiction lived in §7.2's pre-merge framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 BLOCKING (sha 16d21f4) — Q7 cited at every Step 2 unblocking claim Codex BLOCKING finding 2 (sha 16d21f4, 216s thinking): the Q7 dependency was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at §6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without also reading the Q7 prerequisite. Codex framing: "make Q7 a hard precondition wherever Step 2 is called unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate receipts." Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z) and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated all three §6 sites: - Line 191 (Implication for PB-3 migration): cites gate + merge timestamp + explicit "must NOT be brief-authored before that merge timestamp." - Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7 + merge timestamp + P3 failure-shape consequence if violated. - Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4 cross-refs + merge timestamp. Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified already resolved at HEAD via commit c97dc15 — every GrammarSpec mention now explicitly marks it as a concept-not-carrier; Step 2 signature is `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` with no GrammarSpec parameter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3126 BLOCKING (sha 16d21f4) — Step 3b/4 atomicity + Q1 ratification-pending status openai-pro REQUEST_CHANGES on PR #3126 sha 16d21f4 flagged three findings. Findings 1 + 2 (signature vs realization mismatch under LAYER MODEL + P2/P3 boundary discipline) were already resolved at HEAD by earlier fix-forward commits — Step 2 signature is now `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` matching live `parse_generated.rs:138` with no GrammarSpec parameter and no diagnostics-coupled SurfaceModule extension (§4.3 Result-sum disposition). Finding 6 (TRACKED vs UNTRACKED DEBT — Step 3b/4 same-PR vs two-PR): §9 had both a "Step 3b/4 COMBINED" row (line 250) and a leftover separate "Step 4: Parity test" row (line 251) — internally contradictory. §15 also still sequenced Steps 3b + 4 as four separate authoring/dispatch/ratify beats (steps 12-17), contradicting §12 Q5's "same PR" decision and the explicit "Update to §15" note at §12 line 325. Resolution: collapsed §9 to one COMBINED row absorbing the parity-TestClaim mechanics + P5 dissolution receipt from the deleted Step 4 row; collapsed §15 steps 12-17 into single COMBINED authoring + dispatch + ratify (steps 12-14). Added explicit `feedback_paper_shrink_variants` reasoning in both sections. Finding 2.5 (PM intent — substrate-capability bundled vs separate): §12 Q1 line 288 said "Director-recommend: (b) bundled" while §13 line 340 listed substrate-capability as a non-goal of PB-3 and §15 step 11 had "WAIT for substrate-capability landing" — three sections, two different execution paths. Resolution: annotated Q1 as "PENDING operator/PM ratification" with explicit default-execution clause: until operator ratifies, the doc treats substrate-capability as path (a) separate lane (matching §13 + §15 + §9 row). If/when ratified to (b), §13 drops the non-goal and §15 step 11 collapses into the COMBINED Step 3b/4 brief. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 BLOCKING (sha 5619afa) — parse_tables.dag as single enumerated authority Codex caught me copying the prose summary at parse_tables.dag:23-29 (which enumerates only SG-2c-numbered families) instead of grepping the live `^type [A-Z]` declarations. Result: SoftKeywordIdentRow (line 334) was missing from §3.2 / §5.1 / §6 / §12 because it lacks an SG-2c-N number in the prose summary. Per `feedback_parallel_representation_debt`: structural fix is to stop hand-enumerating in the doc — cite parse_tables.dag itself as the single enumerated authority and use `type`-declaration line-anchors for the worked example, not a hand-maintained count. Edits: - §3.2 §"Live substrate authority": replaced the SG-2c-numbered bullet list with `type`-declaration line-anchor enumeration including SoftKeywordIdentRow at parse_tables.dag:334 + the supporting enum BinaryOpLevel at line 133. Added codex-finding callout explaining the miss + the discipline shift. - §3 preamble line:33, §3.2 line:45 callout, §3.2 line:57 framing, §3.2 §"Substrate authority" line:71, §5.1 line:171-180, §12 Q2 line:298, §12 Q6 line:334: all hardcoded "6 table-families" counts dropped; doc now points readers to §3.2 enumeration / `parse_tables.dag` directly. - §5.1 sub-enumeration list (the parallel 6-item list at lines 173-178) deleted; replaced with redirect to §3.2 + restated 3a-vs-3b/4 scope split. Code-level check before commit: `grep -nE '^type [A-Z]' src/v3/compiler/parse_tables.dag` returns 7 types: BinaryOpLevel (133), BinaryOpRow (167), TopLevelItemKwRow (289), SoftKeywordIdentRow (334), BracketRow (385), PrimaryPrefixRow (449), PrimaryAtomRow (486). Doc enumeration matches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING (sha f08b952) — bind TokenizeDiagnostic to live CharClass authority Codex Finding 1 (sha f08b952, 216s thinking): the §4.2 TokenizeDiagnostic draft and the §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef` — names that exist only as the *generated Rust enum spelling*, not as a declared .dag substrate type. Verified via grep: grep -rn '^type CharClass\|^type ScannerC' dsl/ src/v3/ returns ONE authority: `dsl/std/unicode.dag:62` type CharClass = Whitespace | Digit | IdentStart | IdentContinue consumed at `src/v3/compiler/tokenize.dag:103` data ascii_scan_order: List<CharClass> = [Whitespace, Digit, IdentStart, IdentContinue] There is no `ScannerCharClass` declaration anywhere — that name was copied from generated Rust without grep-verification, the same failure mode as `feedback_grep_substrate_before_naming_ratification` (carrier-name collision discipline). Resolution: - §4.2 TokenizeDiagnostic carrier: `expected_class: ScannerClassRef` → `expected_class: CharClass`, dropped the `type ScannerClassRef = ScannerCharClass` alias entirely; added a codex-finding callout citing the substrate authority + naming the failure mode. - §5.1 heading "Byte → ScannerCharClass dispatch" → "Byte → CharClass dispatch"; bullets unchanged; added line-anchor cites for the substrate authority + explicit "NOT ScannerCharClass" disclaimer. - §5.2 heading "ScannerCharClass → token-recognition state machine" → "CharClass → token-recognition state machine". Finding 2 (TokenizedSource not reconciled with parse input contract): no new fix required — already resolved by commit 6adb992 (TokenizedSource extension dropped entirely; tokenize uses Result<List<Token>, TokenizeDiagnostic>; List<Token> is the single canonical boundary carrier consumed by parse). Codex was reviewing sha f08b952, which predated the TokenizedSource drop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — clarify §7.3 chain is Ok-branch propagation Cursor INLINE at sha f08b952 worried that §7.3's cross-stage chain "tokenize → List<Token> → parse → ..." was inconsistent with §4.3's TokenizedSource carrier (diagnostics not flowing forward). At HEAD the TokenizedSource extension is dropped (commit 6adb992); tokenize uses Result<List<Token>, TokenizeDiagnostic>, so List<Token> IS the canonical Ok-branch payload that flows forward and Err branches terminate the pipeline fail-fast. To make this explicit at §7.3 (instead of leaving readers to infer it from §4.3), annotated the chain with: - "Ok-branch propagation; Err branches are stage-terminal fail-fast per §4.3 Result-sum discriminator" framing prefix. - Per-stage Result/typed-state annotations: tokenize/parse show Result<Ok, Err>; lower/infer show typed-state structural-output; emit shows Result<EmittedArtifact, EmissionDiagnostic>. - Explicit "on any stage's Err branch the pipeline aborts at that stage (no partial-output propagation across boundaries)" trailer. This makes the chain self-consistent vis-a-vis §4.3 without requiring the reader to walk back-and-forth, and prevents future readers from re-introducing a TokenizedSource-shaped extension to "make diagnostics flow forward" — they already do, just via the Err branch terminating the pipeline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f2) — character-level scaffold dissolution trigger openai-pro REQUEST_CHANGES on sha d15e1f2: §1 line:26 character-level under-consumption scaffold named the problem but lacked a checkable dissolution trigger. SG-1a scaffold above had the right shape — "once those bodies lower structurally under compile_to_dag, delete the raw-text extractor + derive directly from lowered Dag in same PR." Character-level scaffold just said "PB-2 Step 4 carries this scope" — a lane assignment, not a trigger. Resolution: rewrote §1 item 2 with the same SG-1a-shape trigger structure: - Substrate-consumption condition (a): scanner classes / string escape / local punctuation retype to `dsl/std/unicode.dag` `CharClass` / `char_in_class` (concrete field retypes named: `StringEscapeSpec.suffix: Char`, `LocalPunctSpec.pattern: List<Char>`, `string_literal_delimiter: Char`). - Codegen-driver condition (b): `tokenize_generated.rs` no longer emits hidden `byte.is_ascii_*` predicates because the driver reads class facts structurally from lowered `tokenize.dag`. - Same-PR dissolution: delete the parallel character-predicate scaffold in the same PR that flips substrate consumption — no Rust-and-`.dag` coexistence per `feedback_paper_shrink_variants`. - Cross-ref to §9 Step 4 gating prereqs: ROADMAP.md:467 + ROADMAP.md:416 Class 5 Gap 3 + std.unicode bootstrap/load-set decision (already cited in §9 from earlier commit 6adb992). Per openai-pro's framing: "small fix — mirror the SG-1a scaffold wording by naming the exact substrate-consumption condition and same-PR deletion receipt for the hidden Rust character predicates." Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: gunbc Director * docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep Cursor review id 12405 (APPROVE_WITH_COMMENTS) caught the same `feedback_discipline_change_audit_all_contract_mentions` failure mode recurring: §12 Q6 was resolved REJECTED in commit 6adb992, and §14 "Surfaces awaiting" + §12 Q6 heading + §9 Step 2 row were updated, but two §-internal contract restatements were missed: - §14 acceptance criterion 11: "Operator/PM ratification on §12 Q1-Q6" - §15 step 1: "Operator / PM-delegate ratifies §12 Q1-Q6" Both contradicted §12 Q6 + §14 "Surfaces awaiting" (which already said "Q1-Q5 only"). A worker reading §14/§15 could schedule sign-offs on Q6 after it was already resolved-rejected elsewhere. Resolution: both sites now say "Q1–Q5" with the explicit Q6-rejected crossref + "see §14/§15 for same scoping" pointer at the §14 criterion so the three sections agree internally. Cursor verdict was APPROVE_WITH_COMMENTS (substantive APPROVE — "fix the checklist/sequence so every section agrees Q6 is closed"); the exploratory volatile-line-anchor note is harmless and out-of-scope for this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING (sha 887c696) — 3 findings swept across 3 L2.5 docs Codex review id (sha 887c696, 333s thinking) flagged three findings, all `feedback_discipline_change_audit_all_contract_mentions` recurrences where partial sweeps left §-internal contradictions. Finding 1 — infer doc cross-stage trigger leak: §4.2 InferDiagnostic dissolution trigger said "when Step 2 worker brief enumerates the full variant set against `parse_generated.rs` Diagnostic::ParseError, lower.rs Diagnostic construction sites, and infer.rs Dag::mark_unresolved emission sites." That cross-stage trigger surface is wrong for the infer-specific scaffold. Narrowed to infer-only: "against `src/v3/compiler/src/infer.rs` Diagnostic construction sites + `Dag::mark_unresolved` emission sites (infer-stage only)." Parse and lower have their own per-stage carriers + own Q7 mapping; this doc no longer reaches into their dissolution-trigger surface. Finding 2 — parse + tokenize coproduct receipts: `ParseDiagnosticKind` (parse §4.2) and `TokenizeDiagnostic` (tokenize §4.2) sums were declared without the 🟡 SCAFFOLD / 🟢 TERMINAL classification + dissolution trigger that the infer doc carries (per modeling-discipline Practice 4 + `feedback_coproduct_dissolution`). Added matching scaffold receipts to both: 🟡 SCAFFOLD at PROPOSED stage with stage-local dissolution trigger (Step 2 brief enumerates against parse_generated.rs / tokenize_generated.rs Diagnostic::* construction sites — stage-only, not cross-stage); promote to 🟢 TERMINAL when full variant set lands. Both also carry the anti-bridge note per Q6.5. Finding 3 — tokenize Q7 reconciliation: The parse doc has the "Q7 DONE 2026-05-15T00:21:19Z" annotation at §15 step 4 (commit f85fa1f) but the tokenize doc still framed Q7 as a pending lane dependency at §4.2 line:113 ("Lane dependency"), §15 step 3, and §14 "Surfaces awaiting". Annotated all three: - §4.2 "Lane dependency": Q7 DONE timestamp + "TokenizeDiagnostic per-stage variant authoring is the remaining lane work." - §15 step 3: full DONE annotation matching parse doc §15 step 4 shape + cross-ref to the parse doc. - §14 "Surfaces awaiting": strikethrough + DONE annotation. PR #3127 also carries the tokenize doc; same edits will port there in a companion commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3138 INLINE BLOCKING line:372 — §16 Surfaces awaiting Q7 contradiction Cursor inline at sha 887c696 caught the symmetric finding to the codex 5-finding BLOCKING #3: parse-doc §15 step 4 already annotated Q7 as DONE (commit f85fa1f) but parse-doc §16 "Surfaces awaiting" still listed Q7 as pending. Same `feedback_discipline_change_audit_all_contract_mentions` sweep failure — the tokenize doc had three sites carrying the pending framing (commit e9739ea fixed those) but the parse doc's §16 site was missed in the original Q7-DONE sweep. Resolution: §16 bullet now strikes through + "DONE 2026-05-15T00:21:19Z (PR #3077 merged carrying Q7 ratification; see §15 step 4)" — same shape as the tokenize doc's §14 "Surfaces awaiting" Q7-DONE annotation landed in e9739ea. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…+ cursor inlines (#3141) * docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14 ratification (Decision 1.A scoping = Option A). PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority already lives in `.dag`: - src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143 lines) - src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE 154 lines) - src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362 lines) This is the END STATE that all other pipeline-stage migrations target. PB-2 L2.5 is correspondingly lighter — mostly verification + residual hand-Rust retirement, NOT new substrate authoring. Distinct §9 4-step framing: - Step 3 = VERIFY substrate completeness (audit per feedback_paper_shrink_variants) - Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding (coordinates with PB-Bootstrap-Process lane for codegen-driver retirement) Captures audit dimensions explicitly: - scanner-class definitions = declarative byte-pattern membership - recognition tables = closed-axis enums - state machine = structural transitions - no V2 `pub mod tokenize` absorption check §12 Q1: codegen-driver retirement scope — Director-recommend PB-Bootstrap-Process handles all codegen-driver retirement cross-cuttingly (not per-stage paper-shrink risk). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md Per cursor PR #3085 finding: §12.6 explicitly tables only 4 pipeline-stage migrations (emit→lower→infer→parse); tokenize is per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085 commit 89fbd7a2a applied here. INVARIANTS P1 — documentation must not overstate authority cites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty Same class as codex INLINE BLOCKING #3126 finding 1 (live state honesty for diagnostic coupling) applied preemptively to PB-2 tokenize L2.5. PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing which would overstate the live carrier shape (bare List<Token> has no diagnostic field; tokenize_generated.rs:96 today returns Result<Vec<Token>, Diagnostic>). Fix: §4.3 reframed with PROPOSED substrate extension explicit — new `TokenizedSource { tokens, diagnostics }` wrapper carrier as the typed-state output. Step 2 brief includes wrapper authoring in pipeline-slot PR scope. Same discipline as PR #3126 commit bdff8c500. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md) Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire" (line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2. Propagated fix applies same cite-error correction as PR #3066 §1.8 discipline: cite the actual doc, not an adjacent doc with similar name. INVARIANTS P2 single-authority-citation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6 Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two substantive contradictions I introduced when adding TokenizedSource in commit 2b9756bb5: 1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource` but §9 Step 2 row still said `-> List<Token>`. Same `feedback_discipline_change_audit_all_contract_mentions` issue that's recurred 4x this session. 2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor. Fix: 1. §9 Step 2 row updated: signature `-> TokenizedSource` with wrapper carrier shape `{ tokens, diagnostics }` per §4.3 2. §4.3 anchor updated: "§12 Q6" (resolved) 3. Added §12 Q6: TokenizedSource carrier shape ratification — (a) wrapper record vs (b) per-Token diagnostic coupling; Director-recommend (a) for PB-3 SurfaceModule parallelism 4. §14 + §15 + §16 Q-list refs updated to Q1-Q6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary Codex REQUEST_CHANGES (sha b881de23) with 2 substantive findings: 1. §4.1 Token shape claim "optional lexeme: String" — wrong per live substrate at src/v3/std/tokenize.dag:65-67. Live Token has 2 fields only (kind + span); lexeme-content lives ON the TokenKind variants (Ident(String) / IntLit(String) / etc.). Fix: corrected §4.1 to reflect live carrier shape; payloads on TokenKind variants noted explicitly. 2. §12 Q4 substrate-completeness audit scoped only to tokenize_generated.rs — missed the regen_tokenize codegen- driver boundary. If regen_tokenize carries scanner-logic decisions (rather than mechanical template-rendering of substrate facts), the substrate isn't complete — the driver IS hand-Rust scanner logic in disguise. Fix: Q4 audit extended with (d) regen_tokenize codegen- driver logic audit + (e) ROADMAP.md deferral row option per feedback_paper_shrink_variants P5 receipt discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure Codex REQUEST_CHANGES (sha b881de23, full body) caught 2 substantive overstatements: 1. §2 line 46 claimed "tokenize failures produce typed TokenizeDiagnostic variants" — but live tokenize_generated.rs:96 returns generic `Result<Vec<Token>, Diagnostic>` with `Diagnostic::TokenizerError { message, span, correction }`. Typed TokenizeDiagnostic is a PROPOSED extension, not live state. Fix: §2 reframed with live state explicit + TokenizeDiagnostic marked PROPOSED per PR #3077 §12 Q7 ratification path. 2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly verification" — but live tokenize.dag:16-30+ has TWO explicit tracked scaffold zones: - SG-1a: regen_tokenize parses raw source text for dag_keyword_set / dag_operators (ValueBody::Unparsed) - Character-level under-consumption: StringEscapeSpec / LocalPunctSpec.pattern / string_literal_delimiter as opaque Strings; hidden Rust character predicates (byte.is_ascii_digit etc.) at tokenize_generated.rs:15-22 leaking through codegen Residual hand-Rust is NOT just the codegen artifact — it includes (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold, (c) character-predicate scaffold leaking through codegen. Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER ALONG but not complete"; Step 4 carries scaffold-retirement scope, not just codegen-artifact retirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): post-merge fix-forward — §16 + §9 Step 2 internal contradictions Two post-merge doc-internal contradictions caught by reviewers after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z. **PR #3077 PB-4 lower §16 fix**: §16 "Memory disciplines applied" bullet said "diagnostics coupled INTO PreInferDag via biconditional" — but §4.3 (per openai-pro DiagnosticAnchor fix commit b812db91b) constrains biconditional to PortAnchor-only. Other anchor kinds (DeclarationAnchor / RecordFieldAnchor / SurfaceFormAnchor) couple without port-state. Fix: §16 bullet honors §4.3 anchor-typed framing. **PR #3126 PB-3 parse §9 Step 2 fix**: §9 Step 2 row described diagnostics as "coupled INTO SurfaceModule" as if live — §4.3 correctly marks it PROPOSED. Same feedback_discipline_change_audit_all_contract_mentions pattern that's recurred this session. Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3"; Step 2 PR scope includes authoring the diagnostics field extension, NOT a live coupling. Per feedback_discipline_change_audit_all_contract_mentions: when a substantive fix changes a discipline framing, audit ALL sections (framing + contract + handoff). Post-merge audit surfaced these residual contradictions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): post-merge fix-forward — PR #3126 codex BLOCKING (GrammarSpec parallel-authority + fail-closed weakening) Codex REQUEST_CHANGES on already-merged PR #3126 (/api/reviews/12175): 2 substantive findings on the post-merge doc. **Finding 1 (P2 violation — GrammarSpec parallel authority)**: §3.2 says GrammarSpec is compile-time-only, NOT runtime- interpreted (per Decision 3.B (b) operator override). But the proposed stage contract still took `grammar: GrammarSpec` as runtime input. Creates two authorities (compiled parser tables + runtime GrammarSpec value). Fix: §4.3 signature reframed to `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` — NO runtime GrammarSpec input. Compile-time generated parser tables consumed via internal dispatch. Step 2 + Step 4 rows updated. **Finding 2 (P3 + Practices 1/2 — fail-closed weakening)**: Live parser at parse_generated.rs:138 returns `Result<SurfaceModule, Diagnostic>` (fail-closed; aborts on first error). Earlier draft proposed `SurfaceModule` with embedded diagnostics — would let partial-parse states be constructible + let downstream observe "success" output after parse failure. Violation of fail-closed discipline. Fix: signature preserves Result-sum (matches live + emit's pattern). Distinguished cross-stage: - Result-sum (parse + emit): fail-fast output domain - Typed-state-with-coupled-diagnostics (lower + infer): structural output domain where partial-failure IS valid intermediate Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 post-merge APPROVE_WITH_COMMENTS — §4.1 + §16 fail-closed honesty Cursor caught 2 more post-merge contradictions on PR #3126: 1. §4.1 line 81 "construction-time invariant" talks about "ParseDiagnostic in the diagnostic stream" tied to SurfaceModule path — but §5.2 + live parse_generated.rs:138 use Result<SurfaceModule, Diagnostic>. §4.1 reads as claim about today's plumbing. Fix: §4.1 reframed — live boundary explicit (Result-sum); construction-time invariant scoped to Ok-arm SurfaceModule + Err-arm ParseDiagnostic, no partial-parse with embedded diagnostics. 2. §16 line 397 cites C-8 as "ParseDiagnostic coupled INTO SurfaceModule" without qualifier — but §4.3 (post codex REQUEST_CHANGES fix) constrains to Result-sum. Fix: §16 bullet honors §4.3 Result-sum framing; cross-stage discriminator named. Same recurring feedback_discipline_change_audit_all_contract_mentions pattern — substantive fix to §4.3 + §9 Step 2 left §4.1 + §16 inconsistent. Post-merge audit catches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING — TypeConnective extension stop-signal Cursor INLINE BLOCKING caught §3.2 line 66 "rules extend automatically" weakens substrate-extension stop-signal. Thesis discipline: a 7th TypeConnective variant requires explicit C1 audit + named infer-rule receipt. Fix: §3.2 reframed. New TypeConnective variants do NOT extend automatically; require explicit C1 substrate-extension audit + named infer-rule receipt for the new variant's structural inference behavior. Per-variant structural facts means new variants need new per-variant facts, NOT silent inheritance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING — AlgebraAxis + InferDiagnostic Practice 4 classification Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed substrate coproducts (AlgebraAxis + InferDiagnostic) lack 🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline Practice 4 (Coproduct dissolution). Fix: added 🟡 SCAFFOLD classification + named dissolution trigger for both: AlgebraAxis 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full algebra-axiom set against infer.rs check sites + verifies coverage parity with live verification.dag:146 AlgebraicLawKind 3-variant subset → promote to 🟢 TERMINAL. InferDiagnostic 🟡 SCAFFOLD: - Trigger: Step 2 brief enumerates full variant set against parse_generated.rs / lower.rs / infer.rs diagnostic emission sites → promote to 🟢 TERMINAL. - Anti-bridge per Q6.5: does NOT collapse into CompilerDiagnosticKind without substrate-extension ratification per PR #3077 §12 Q7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING — §5.1 SurfaceItem allocation correction Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said "every SurfaceItem variant maps 1:1 to a Declaration placeholder" but live lower.rs:2950-2958 explicitly skips Let/Module/Import in collect_symbols. Verified via Read of lower.rs:2956-2958: SurfaceItem::Let { .. } => continue, SurfaceItem::Module { .. } => continue, SurfaceItem::Import { .. } => continue, Fix: §5.1 reframed — DeclarationAllocating variants (Fn / FnExternalBody / Data / TypeAtom / TypeRecord) map to placeholders; NonDeclarationAllocating variants (Let / Module / Import) skip allocation per live lower.rs behavior. Let-bodies lower to Bind expressions in Pass 2; Module/Import are parsed-facts preserved but un-declared. Earlier "every SurfaceItem variant" framing overstated; would have steered Step 2/3 worker into wrong allocation contract. Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING — ElaborationSpec scope broadened Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only as Surface→Behavior recipe mapping, but lower constructs Declarations / TypeConnectives / BranchPatterns / Bindings as well. Non-Behavior lowering decisions outside declared authority violates THESIS substrate ownership + INVARIANTS P2. Fix: §3.2 ElaborationSpec scope broadened to ALL lowering decisions: 1. SurfaceItem → Declaration recipes (Fn / Data / Type variants + Let/Module/Import skip-allocation per §5.1) 2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose / Disj construction) 3. SurfaceExpr → Behavior recipes (Value / Transform / Branch / Loop / Bind construction) 4. SurfacePattern → BranchPattern recipes (ResolvedVariant / UnresolvedVariant / record-pattern construction) 5. Binding-site rules (Bind params + result_port construction) ElaborationSpec is single-authority across ALL axes; no axis lives in implementation-tier hand-Rust. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — §7.1 ordering vs independence clarification Cursor APPROVE_WITH_COMMENTS /api/reviews/12265 line 197: §7.1 mixed two claims: - "parse migrates AFTER tokenize substrate-side stable" (ordering) - "PB-3 parse migration is independent of PB-2 tokenize migration status" (independence) Read as contradictory by reviewers. Need one coherent story. Fix: §7.1 reframed with two distinct axes explicit: 1. Substrate-stability ordering (SELF_HOSTING.md §2 bottom-up): tokenize Token carrier shape must be stable BEFORE parse migrates. Already true at HEAD (tokenize.dag:65-67 declares live carrier). ✓ 2. Migration-timing independence (parallel-dispatch axis): PB-3 parse migration ships in parallel with PB-2 residual-retirement work (SG-1a + character-level scaffold + codegen-driver retirement per PB-2 L2.5 §1). What parse needs is the stable Token CARRIER; PB-2's migration is about retiring residual hand-Rust, not changing the carrier. Both claims coherent on the axis split; not contradictory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — ParseDiagnostic SourceSpan structural requirement Cursor INLINE BLOCKING /api/reviews/12277 line:65: ParseDiagnostic variants like UnexpectedToken lacked SourceSpan field; List<ParseDiagnostic> cannot satisfy fail-closed source attribution structurally without span on every variant. INVARIANTS P2/P3 violation. Fix: every ParseDiagnostic variant now carries SourceSpan structurally: - UnexpectedToken: added span: SourceSpan - UnterminatedConstruct: opener_span: SourceSpan (already present) - InvalidLiteral: added span: SourceSpan - DuplicateRecordFieldLabel: added span: SourceSpan (current site) + prior_span: SourceSpan (prior site; both required) Per INVARIANTS P2/P3 fail-closed source attribution discipline: every diagnostic emission carries structural source-span provenance; not optional. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Token authority cite phantom-reference fix Cursor INLINE BLOCKING /api/reviews/12279 line:29: §3.1 cited `src/v3/compiler/src/tokenize.rs` as "current hand-Rust" for Token carrier — but `tokenize.rs` (without _generated suffix) doesn't exist. Live state has tokenize.dag (live substrate) + tokenize_generated.rs (codegen artifact). Per design-pure-bootstrap.md PB-2 lane: tokenize retire has substantially landed. The reference was an earlier-draft phantom from when Token-was-hand-Rust framing was the assumption. Fix: §3.1 reframed — Token type lives in LIVE src/v3/std/tokenize.dag:65-67 shared taxonomy; tokenizer implementation also live at src/v3/compiler/tokenize.dag (154 lines); codegen artifact at tokenize_generated.rs. tokenize.rs phantom reference removed explicitly. PB-2 substantially landed per design-pure-bootstrap.md; residual scaffold-retirement scope per PB-2 L2.5 PR #3127. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Step 2 pipeline-slot target fix (compiler.dag → pipeline.dag) Cursor INLINE BLOCKING /api/reviews/12281 line:138: §9 Step 2 referenced generic "compiler.dag" but dsl/gunbc/compiler.dag:24 explicitly directs internal pipeline (Tokenize → Parse → ...) to src/v3/compiler/pipeline.dag, NOT generic compiler.dag. Worker briefs authored against this doc would target the wrong file for pipeline-slot declaration. P2 single-authority violation. Fix: §9 Step 2 row in ALL 4 L2.5 docs (PB-2 / PB-3 / PB-4 / PB-5) updated: - "declared in compiler.dag" → "declared in src/v3/compiler/pipeline.dag (per dsl/gunbc/compiler.dag:24 — internal pipeline lives in pipeline.dag, NOT generic compiler.dag)" - substrate column: "compiler.dag refinement" → "pipeline.dag refinement" - §13 "Step 2 (pipeline-slot in compiler.dag)" → "pipeline-slot in src/v3/compiler/pipeline.dag" Same phantom-citation class as the tokenize.rs phantom (commit 8ae37b4a5): I cited generic file path without verifying which specific file is authoritative per project structure. Should have grep'd dsl/gunbc/compiler.dag header notes before authoring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING — Step 3b/4 phasing P5 receipt unambiguity Cursor INLINE BLOCKING /api/reviews/12283 line:181: Q5 said Step 3b "full parser body .dag migration + parser body deletion in same PR", but §15 sequence schedules Step 4 parity/deletion AFTER Step 3b merges. P5 dissolution receipt ambiguous. If Step 3b lands .dag parser body BEFORE Step 4 deletes Rust parse() body, Rust + .dag parser bodies coexist temporarily — paper-shrink-relocation risk per feedback_paper_shrink_variants. Fix: 1. §9 Step 3b row reframed as "Step 3b/4 COMBINED" — atomic single PR (full .dag parser body + parity TestClaim + parse_generated.rs:138 deletion + census shrink). Cannot land .dag parser body before Rust deletion. 2. §12 Q5 phasing clarified: - Phase 3a (separate PR): grammar table extension; P5 receipt = ROADMAP deferral row naming Step 3b/4 as future-receipt - Phase 3b/4 COMBINED (single PR): atomic substrate substitution 3. §9 + §15 update notes: sequence collapses steps 12-17 into single dispatch+merge for combined phase Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 high-level BLOCKING findings 1 + 2 Codex high-level BLOCKING (sha 140eb6bb) had 4 findings: - Findings 3 + 4 already addressed in PR #3138 commits 015977347 + a1607a88d - Findings 1 + 2 addressed in this commit **Finding 1 (Diagnostic kind/record conflated)**: §4.2 ParseDiagnostic was modeled as variants-directly with span + kind-fields mixed. Live Diagnostic at diagnostics.dag:150 uses record-wraps-kind pattern (`{ kind, span, message, correction }`). Need consistent shape. Fix: refactored to record-wraps-kind: - `type ParseDiagnostic { kind: ParseDiagnosticKind, span: SourceSpan }` - `type ParseDiagnosticKind = UnexpectedToken | UnterminatedConstruct | InvalidLiteral | DuplicateRecordFieldLabel | ...` Span lives on ParseDiagnostic record (single source of truth); variant-specific spans (opener_span / prior_span) remain on kind variants where meaningful. **Finding 2 (PB-2 §6 obsolete sibling-lane assumption)**: §6 line 198 said "PB-2 Tokenize | src/v3/std/tokenize.dag (NEW per PB-2 L2.5)" — but tokenize.dag is ALREADY LIVE per design-pure-bootstrap.md §"PB-2 — tokenize retire" (substantially landed). Fix: §6 prereq table row updated to reflect LIVE state. PB-2's residual scope is scaffold-retirement (SG-1a + character-level + codegen-driver per PB-2 L2.5 §1), not carrier authoring. PB-3 consumes the live Token carrier; carrier shape stable across PB-2 residual-retirement timing. Findings 3 + 4 already addressed: - Finding 3 (pipeline.dag target): commit 015977347 - Finding 4 (Step 3b/4 atomic vs sequential): commit a1607a88d Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — phantom "module-level metadata" removed Cursor APPROVE_WITH_COMMENTS line:79: §4.1 said "SurfaceModule (verified live) carries List<SurfaceItem> + module-level metadata" — but live parse_surface.dag:29 has ONLY `{ items: List<SurfaceItem> }`. No metadata fields. Phantom addition violated INVARIANTS P1 live-state honesty. Fix: §4.1 reframed to match live carrier exactly. Same phantom-addition class as tokenize.rs phantom (commit 8ae37b4a5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3085 high-level BLOCKING findings — AtomPayload 5-variant + diagnostic-table PROPOSED Codex high-level BLOCKING (sha bf4d3152) — 2 substantive findings: **Finding 1 (AtomPayload stale)**: §2 + §5 cited infer.rs:10 top-comment "Atom(Identifier { name, resolved })" — but live substrate.dag:87 has 5-variant AtomPayload sum: Literal | UnresolvedIdentifier | ResolvedByStructure | ResolvedByName | TypeParam. infer.rs top-comment is STALE vs live substrate. My doc inherited the drift. Fix: §2 enumeration corrected to all 5 AtomPayload variants per live substrate.dag:87. **Finding 2 (diagnostic-table PROPOSED, not live)**: §2 + §4.1 + §4.3 said "diagnostics.contains(port_id) biconditional" as if live — but Dag at substrate.dag:525 has ONLY { declarations, nodes, ports, clusters }. NO diagnostics field. Diagnostic-table is PROPOSED substrate extension. Fix: §2 fail-closed note flagged PROPOSED — Step 2 PR scope includes `diagnostics: Map<PortId, Diagnostic>` field extension to Dag, OR PB-Substrate prereq adds it before PB-5 dispatch. Same recurring feedback_grep_carrier_field_before_coupling_claim discipline (PR #3126 SurfaceModule analogous case); needed to grep type Dag fields BEFORE claiming the diagnostics field exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3085 INLINE BLOCKING line:94 — §4.1 + §4.3 PROPOSED diagnostic-table marking Cursor INLINE BLOCKING line:94: §4.1 + §4.3 said "diagnostics coupled INTO InferredDag" without flagging the diagnostic-table as a substrate extension. Live Dag at substrate.dag:525 has { declarations, nodes, ports, clusters } — NO diagnostics field. Earlier commit c0d96af25 added PROPOSED marking only in §2; §4.1 + §4.3 needed same treatment. Fix: §4.1 + §4.3 reframed with explicit PROPOSED substrate- extension marking + reference to §2 for extension scope. Construction-time invariant + structural coupling are both contingent on the substrate-extension landing (Step 2 PR scope or PB-Substrate prereq). Same recurring feedback_grep_carrier_field_before_coupling_claim discipline applied to §4.1 + §4.3 consistently with §2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3077 high-level BLOCKING — Practice 4 classifications for PB-4 coproducts Codex high-level BLOCKING (sha b812db91): "Diagnostic substrate shape was repaired around anchoring but not re-audited as new substrate type declarations" — meaning DiagnosticAnchor + LowerDiagnostic + SurfaceFormRef + IdentifierRef need 🟢/🟡/🔴 classifications per modeling-discipline Practice 4 (Coproduct dissolution). Same pattern as PB-5 fix in commit 040681f21 (AlgebraAxis + InferDiagnostic) applied here. Fix: added classifications + dissolution triggers: - SurfaceFormRef 🟢 TERMINAL: closed-axis sum over live Surface* carriers; no further dissolution. - IdentifierRef 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates full identifier-kind set against lower.rs identifier-resolution sites; promote to 🟢 TERMINAL when SurfaceVarRef + TypePathRef + ModulePathRef cover actual axes. - LowerDiagnostic 🟡 SCAFFOLD: dissolution trigger = Step 2 brief enumerates variant set against lower.rs Diagnostic emission sites + Q6.5 anti-bridge preserved + PR #3077 §12 Q7 ratification path. - DiagnosticAnchor 🟢 TERMINAL: closed-axis covering all lowering-stage anchor kinds; no further dissolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3077 INLINE BLOCKING line:161 — DiagnosticSource Practice 4 classification Cursor inline finding adds DiagnosticSource to Practice 4 classification scope. Earlier commit aba79a142 classified SurfaceFormRef + IdentifierRef + LowerDiagnostic + DiagnosticAnchor but missed DiagnosticSource. Fix: DiagnosticSource 🟢 TERMINAL at pipeline-stage discrimination scope. Closed-axis sum (Parse | Lower | Infer | Emit); adding new pipeline stage requires explicit substrate- extension audit per Practice 4 + stop-signal discipline (same shape as PB-5 §3.2 TypeConnective stop-signal). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 INLINE BLOCKING line:151 — §11 SurfaceItem::Let + SurfaceLiteral span correction Cursor INLINE BLOCKING line:151: §11 claimed "every Surface variant carries SourceSpan" but live parse_surface.dag has: - SurfaceItem::Let { name, type_ann, expr } — no direct span - SurfaceLiteral = Int(String) | Bool(Bool) | String(String) — plain-tuple variants with no direct span Source-span provenance for these cases is via enclosing carrier: SurfaceLiteral wraps within `Literal { value, span }` at parse_surface.dag:150. Let-item inherits container span. INVARIANTS P2/P3 source provenance is structurally guaranteed via direct-OR-enclosing carrier, but my "every variant" overstatement obscured this. Fix: §11 corrected to "most Surface variants carry SourceSpan directly" + explicit Let + SurfaceLiteral exceptions noted + Step 2 PR scope audits whether exceptions are structural-honest (enclosing-carrier-provides-span) OR require substrate extension. Same recurring overstatement class as earlier "every SurfaceItem maps 1:1 to Declaration" (commit 61e2b67cd) — need to grep live substrate variant fields BEFORE claiming uniform shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: gunbc Director * docs(r3): cursor PR #3126 INLINE BLOCKING line:32 — GrammarSpec is concept, not carrier Earlier draft (now-merged PR #3126) framed `GrammarSpec` as a second declared `.dag` input type alongside `List<Token>`. Verified via grep that no `type GrammarSpec` exists anywhere under src/v3/ or dsl/ — the repo carries only `parse_tables.dag`'s 6 SG-2c table-families. Per cursor 2026-05-14T23:30:04Z inline finding, this violates INVARIANTS P2 (the Step-2 signature names a carrier the substrate doesn't declare). Reframed §3 (and downstream mentions in §3.2, §3 preamble line:33, §4.2 codex-correction recap line:165, §5.1 line:181, §12 Q6 line:344) so that: - Parse has ONE input at the API boundary: `List<Token>`. - "GrammarSpec" is a concept-level grouping for the 6 compile-time table-families in `parse_tables.dag`, not a substrate carrier and not a runtime parameter. - Step-2 signature stays `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` per cfe842b2d (already applied in #3126); these edits remove the lingering "two input types" framing that contradicted that signature. Per Decision 3.B (b) compile-time parser tables: substrate authority is parse_tables.dag (6 table-families) consumed via direct table lookups inside the parser body — no runtime grammar value, no `GrammarSpec` carrier needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING — §4.3 + §16 internal contradictions resolved Codex review id 12391 on sha cd6e8d15 flagged two live statements of the already-rejected typed-state-with-coupled-diagnostics model still sitting inside the parse L2.5, contradicting the corrected Result-sum framing in §4.2 and §6 Step 2: 1. §4.3 still proposed a `SurfaceModule { items, diagnostics }` extension modeled on PB-4/PB-5 patterns. Reframed: §4.3 now states explicitly that parse-stage uses Result-sum (no diagnostics field on SurfaceModule), restates the cross-stage discriminator (Result-sum for fail-fast output domains: parse + emit; typed-state for structural output domains: lower + infer), and cites `parse_generated.rs:138` as the live shape. 2. §16 "Memory disciplines applied" bullet read "feedback_state_space_vs_behavioral_invariants (typed-state SurfaceModule at output)". Rewritten to "parse output is `Result<SurfaceModule, ParseDiagnostic>` — the type rules out partial-parse states by construction; SurfaceModule itself carries no diagnostic field per §4.3". Per `feedback_discipline_change_audit_all_contract_mentions`: when a contract changes (here: SurfaceModule extension dropped in favor of Result-sum), all §-internal restatements must be swept in the same diff or they leak through as authoritative parallel claims. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3127 BLOCKING — drop TokenizedSource extension + cite concrete P5 receipts Codex review id 12370 on sha d15e1f29 raised two load-bearing planning-shape findings on the tokenize L2.5. Addressed in this fix-forward branch (PR #3138) since PR #3127 is still open but accumulating cycles. Finding 1 — parallel boundary carriers (INVARIANTS P2 / Modeling Practices 3+5): §4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }` as the output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification I just removed from the parse L2.5 in PR #3138 §4.3: tokenize sits in the fail-fast output domain alongside PB-3 parse + PB-6 emit (a partial token list with a corrupt token in the middle is not a valid downstream input for parse), so the failure couples via `Result`, not into the structural carrier. Resolution: - §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the live `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension. - §9 Step 2 row signature updated to match; explicit "single canonical boundary carrier: List<Token> on the Ok branch" framing. - §12 Q6 resolved REJECTED in-doc (no operator ratification needed; disposition follows from the cross-stage discriminator that's also load-bearing in PR #3138 parse L2.5). - §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16: Result-sum, no diagnostics field on `List<Token>`. - §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list. Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5): deferral previously named "PB-Bootstrap-Process lane scope" without a concrete ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named receipts: - `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane: author bootstrap.dag + generated trampoline; sized M). - `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification gates). - ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax authorities — phase-2 char-class retype owns the codegen-driver path). - ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating substrate-capability for the phase-2 retype). - ROADMAP.md:53 (T-PB-A — non-test census → 0 floor). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3126 BLOCKING line:119 — §6/§7.2/§15 Q7 sequencing resolved by PR #3077 merge Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at merge time of PR #3126) flagged a real internal contradiction: - §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is unblocked" - §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2 worker brief authoring" A worker reading the doc could land Step 2 (pipeline boundary) before the diagnostic carrier's P2/P3 failure shape was fixed. Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z, carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic extension path. The gate IS now satisfied at HEAD, so the resolution is fact-update (annotate Q7 as DONE with the merge timestamp) rather than retracting either §6 or §7.2. Edits: - §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged" and added the explicit "Step 2 is now genuinely unblocked, not just procedurally next" framing so workers reading the sequence don't bypass the gate. - §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief authoring" (future tense, the contradiction surface) to "Gate satisfied 2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring is unblocked at HEAD per §15 step 4." Cites the cursor finding as the resolution path. §6 unblocking statements stay as-is — they were correct at HEAD; the contradiction lived in §7.2's pre-merge framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 BLOCKING (sha 16d21f4a) — Q7 cited at every Step 2 unblocking claim Codex BLOCKING finding 2 (sha 16d21f4a, 216s thinking): the Q7 dependency was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at §6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without also reading the Q7 prerequisite. Codex framing: "make Q7 a hard precondition wherever Step 2 is called unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate receipts." Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z) and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated all three §6 sites: - Line 191 (Implication for PB-3 migration): cites gate + merge timestamp + explicit "must NOT be brief-authored before that merge timestamp." - Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7 + merge timestamp + P3 failure-shape consequence if violated. - Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4 cross-refs + merge timestamp. Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified already resolved at HEAD via commit c97dc15ae — every GrammarSpec mention now explicitly marks it as a concept-not-carrier; Step 2 signature is `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` with no GrammarSpec parameter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3126 BLOCKING (sha 16d21f4a) — Step 3b/4 atomicity + Q1 ratification-pending status openai-pro REQUEST_CHANGES on PR #3126 sha 16d21f4a flagged three findings. Findings 1 + 2 (signature vs realization mismatch under LAYER MODEL + P2/P3 boundary discipline) were already resolved at HEAD by earlier fix-forward commits — Step 2 signature is now `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>` matching live `parse_generated.rs:138` with no GrammarSpec parameter and no diagnostics-coupled SurfaceModule extension (§4.3 Result-sum disposition). Finding 6 (TRACKED vs UNTRACKED DEBT — Step 3b/4 same-PR vs two-PR): §9 had both a "Step 3b/4 COMBINED" row (line 250) and a leftover separate "Step 4: Parity test" row (line 251) — internally contradictory. §15 also still sequenced Steps 3b + 4 as four separate authoring/dispatch/ratify beats (steps 12-17), contradicting §12 Q5's "same PR" decision and the explicit "Update to §15" note at §12 line 325. Resolution: collapsed §9 to one COMBINED row absorbing the parity-TestClaim mechanics + P5 dissolution receipt from the deleted Step 4 row; collapsed §15 steps 12-17 into single COMBINED authoring + dispatch + ratify (steps 12-14). Added explicit `feedback_paper_shrink_variants` reasoning in both sections. Finding 2.5 (PM intent — substrate-capability bundled vs separate): §12 Q1 line 288 said "Director-recommend: (b) bundled" while §13 line 340 listed substrate-capability as a non-goal of PB-3 and §15 step 11 had "WAIT for substrate-capability landing" — three sections, two different execution paths. Resolution: annotated Q1 as "PENDING operator/PM ratification" with explicit default-execution clause: until operator ratifies, the doc treats substrate-capability as path (a) separate lane (matching §13 + §15 + §9 row). If/when ratified to (b), §13 drops the non-goal and §15 step 11 collapses into the COMBINED Step 3b/4 brief. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3126 BLOCKING (sha 5619afac) — parse_tables.dag as single enumerated authority Codex caught me copying the prose summary at parse_tables.dag:23-29 (which enumerates only SG-2c-numbered families) instead of grepping the live `^type [A-Z]` declarations. Result: SoftKeywordIdentRow (line 334) was missing from §3.2 / §5.1 / §6 / §12 because it lacks an SG-2c-N number in the prose summary. Per `feedback_parallel_representation_debt`: structural fix is to stop hand-enumerating in the doc — cite parse_tables.dag itself as the single enumerated authority and use `type`-declaration line-anchors for the worked example, not a hand-maintained count. Edits: - §3.2 §"Live substrate authority": replaced the SG-2c-numbered bullet list with `type`-declaration line-anchor enumeration including SoftKeywordIdentRow at parse_tables.dag:334 + the supporting enum BinaryOpLevel at line 133. Added codex-finding callout explaining the miss + the discipline shift. - §3 preamble line:33, §3.2 line:45 callout, §3.2 line:57 framing, §3.2 §"Substrate authority" line:71, §5.1 line:171-180, §12 Q2 line:298, §12 Q6 line:334: all hardcoded "6 table-families" counts dropped; doc now points readers to §3.2 enumeration / `parse_tables.dag` directly. - §5.1 sub-enumeration list (the parallel 6-item list at lines 173-178) deleted; replaced with redirect to §3.2 + restated 3a-vs-3b/4 scope split. Code-level check before commit: `grep -nE '^type [A-Z]' src/v3/compiler/parse_tables.dag` returns 7 types: BinaryOpLevel (133), BinaryOpRow (167), TopLevelItemKwRow (289), SoftKeywordIdentRow (334), BracketRow (385), PrimaryPrefixRow (449), PrimaryAtomRow (486). Doc enumeration matches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING (sha f08b9525) — bind TokenizeDiagnostic to live CharClass authority Codex Finding 1 (sha f08b9525, 216s thinking): the §4.2 TokenizeDiagnostic draft and the §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef` — names that exist only as the *generated Rust enum spelling*, not as a declared .dag substrate type. Verified via grep: grep -rn '^type CharClass\|^type ScannerC' dsl/ src/v3/ returns ONE authority: `dsl/std/unicode.dag:62` type CharClass = Whitespace | Digit | IdentStart | IdentContinue consumed at `src/v3/compiler/tokenize.dag:103` data ascii_scan_order: List<CharClass> = [Whitespace, Digit, IdentStart, IdentContinue] There is no `ScannerCharClass` declaration anywhere — that name was copied from generated Rust without grep-verification, the same failure mode as `feedback_grep_substrate_before_naming_ratification` (carrier-name collision discipline). Resolution: - §4.2 TokenizeDiagnostic carrier: `expected_class: ScannerClassRef` → `expected_class: CharClass`, dropped the `type ScannerClassRef = ScannerCharClass` alias entirely; added a codex-finding callout citing the substrate authority + naming the failure mode. - §5.1 heading "Byte → ScannerCharClass dispatch" → "Byte → CharClass dispatch"; bullets unchanged; added line-anchor cites for the substrate authority + explicit "NOT ScannerCharClass" disclaimer. - §5.2 heading "ScannerCharClass → token-recognition state machine" → "CharClass → token-recognition state machine". Finding 2 (TokenizedSource not reconciled with parse input contract): no new fix required — already resolved by commit 6adb99227 (TokenizedSource extension dropped entirely; tokenize uses Result<List<Token>, TokenizeDiagnostic>; List<Token> is the single canonical boundary carrier consumed by parse). Codex was reviewing sha f08b9525, which predated the TokenizedSource drop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — clarify §7.3 chain is Ok-branch propagation Cursor INLINE at sha f08b9525 worried that §7.3's cross-stage chain "tokenize → List<Token> → parse → ..." was inconsistent with §4.3's TokenizedSource carrier (diagnostics not flowing forward). At HEAD the TokenizedSource extension is dropped (commit 6adb99227); tokenize uses Result<List<Token>, TokenizeDiagnostic>, so List<Token> IS the canonical Ok-branch payload that flows forward and Err branches terminate the pipeline fail-fast. To make this explicit at §7.3 (instead of leaving readers to infer it from §4.3), annotated the chain with: - "Ok-branch propagation; Err branches are stage-terminal fail-fast per §4.3 Result-sum discriminator" framing prefix. - Per-stage Result/typed-state annotations: tokenize/parse show Result<Ok, Err>; lower/infer show typed-state structural-output; emit shows Result<EmittedArtifact, EmissionDiagnostic>. - Explicit "on any stage's Err branch the pipeline aborts at that stage (no partial-output propagation across boundaries)" trailer. This makes the chain self-consistent vis-a-vis §4.3 without requiring the reader to walk back-and-forth, and prevents future readers from re-introducing a TokenizedSource-shaped extension to "make diagnostics flow forward" — they already do, just via the Err branch terminating the pipeline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f29) — character-level scaffold dissolution trigger openai-pro REQUEST_CHANGES on sha d15e1f29: §1 line:26 character-level under-consumption scaffold named the problem but lacked a checkable dissolution trigger. SG-1a scaffold above had the right shape — "once those bodies lower structurally under compile_to_dag, delete the raw-text extractor + derive directly from lowered Dag in same PR." Character-level scaffold just said "PB-2 Step 4 carries this scope" — a lane assignment, not a trigger. Resolution: rewrote §1 item 2 with the same SG-1a-shape trigger structure: - Substrate-consumption condition (a): scanner classes / string escape / local punctuation retype to `dsl/std/unicode.dag` `CharClass` / `char_in_class` (concrete field retypes named: `StringEscapeSpec.suffix: Char`, `LocalPunctSpec.pattern: List<Char>`, `string_literal_delimiter: Char`). - Codegen-driver condition (b): `tokenize_generated.rs` no longer emits hidden `byte.is_ascii_*` predicates because the driver reads class facts structurally from lowered `tokenize.dag`. - Same-PR dissolution: delete the parallel character-predicate scaffold in the same PR that flips substrate consumption — no Rust-and-`.dag` coexistence per `feedback_paper_shrink_variants`. - Cross-ref to §9 Step 4 gating prereqs: ROADMAP.md:467 + ROADMAP.md:416 Class 5 Gap 3 + std.unicode bootstrap/load-set decision (already cited in §9 from earlier commit 6adb99227). Per openai-pro's framing: "small fix — mirror the SG-1a scaffold wording by naming the exact substrate-consumption condition and same-PR deletion receipt for the hidden Rust character predicates." Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: gunbc Director * docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep Cursor review id 12405 (APPROVE_WITH_COMMENTS) caught the same `feedback_discipline_change_audit_all_contract_mentions` failure mode recurring: §12 Q6 was resolved REJECTED in commit 6adb99227, and §14 "Surfaces awaiting" + §12 Q6 heading + §9 Step 2 row were updated, but two §-internal contract restatements were missed: - §14 acceptance criterion 11: "Operator/PM ratification on §12 Q1-Q6" - §15 step 1: "Operator / PM-delegate ratifies §12 Q1-Q6" Both contradicted §12 Q6 + §14 "Surfaces awaiting" (which already said "Q1-Q5 only"). A worker reading §14/§15 could schedule sign-offs on Q6 after it was already resolved-rejected elsewhere. Resolution: both sites now say "Q1–Q5" with the explicit Q6-rejected crossref + "see §14/§15 for same scoping" pointer at the §14 criterion so the three sections agree internally. Cursor verdict was APPROVE_WITH_COMMENTS (substantive APPROVE — "fix the checklist/sequence so every section agrees Q6 is closed"); the exploratory volatile-line-anchor note is harmless and out-of-scope for this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3138 BLOCKING (sha 887c69671) — 3 findings swept across 3 L2.5 docs Codex review id (sha 887c69671, 333s thinking) flagged three findings, all `feedback_discipline_change_audit_all_contract_mentions` recurrences where partial sweeps left §-internal contradictions. Finding 1 — infer doc cross-stage trigger leak: §4.2 InferDiagnostic dissolution trigger said "when Step 2 worker brief enumerates the full variant set against `parse_generated.rs` Diagnostic::ParseError, lower.rs Diagnostic construction sites, and infer.rs Dag::mark_unresolved emission sites." That cross-stage trigger surface is wrong for the infer-specific scaffold. Narrowed to infer-only: "against `src/v3/compiler/src/infer.rs` Diagnostic construction sites + `Dag::mark_unresolved` emission sites (infer-stage only)." Parse and lower have their own per-stage carriers + own Q7 mapping; this doc no longer reaches into their dissolution-trigger surface. Finding 2 — parse + tokenize coproduct receipts: `ParseDiagnosticKind` (parse §4.2) and `TokenizeDiagnostic` (tokenize §4.2) sums were declared without the 🟡 SCAFFOLD / 🟢 TERMINAL classification + dissolution trigger that the infer doc carries (per modeling-discipline Practice 4 + `feedback_coproduct_dissolution`). Added matching scaffold receipts to both: 🟡 SCAFFOLD at PROPOSED stage with stage-local dissolution trigger (Step 2 brief enumerates against parse_generated.rs / tokenize_generated.rs Diagnostic::* construction sites — stage-only, not cross-stage); promote to 🟢 TERMINAL when full variant set lands. Both also carry the anti-bridge note per Q6.5. Finding 3 — tokenize Q7 reconciliation: The parse doc has the "Q7 DONE 2026-05-15T00:21:19Z" annotation at §15 step 4 (commit f85fa1f6b) but the tokenize doc still framed Q7 as a pending lane dependency at §4.2 line:113 ("Lane dependency"), §15 step 3, and §14 "Surfaces awaiting". Annotated all three: - §4.2 "Lane dependency": Q7 DONE timestamp + "TokenizeDiagnostic per-stage variant authoring is the remaining lane work." - §15 step 3: full DONE annotation matching parse doc §15 step 4 shape + cross-ref to the parse doc. - §14 "Surfaces awaiting": strikethrough + DONE annotation. PR #3127 also carries the tokenize doc; same edits will port there in a companion commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3138 INLINE BLOCKING line:372 — §16 Surfaces awaiting Q7 contradiction Cursor inline at sha 887c69671 caught the symmetric finding to the codex 5-finding BLOCKING #3: parse-doc §15 step 4 already annotated Q7 as DONE (commit f85fa1f6b) but parse-doc §16 "Surfaces awaiting" still listed Q7 as pending. Same `feedback_discipline_change_audit_all_contract_mentions` sweep failure — the tokenize doc had three sites carrying the pending framing (commit e9739ea4f fixed those) but the parse doc's §16 site was missed in the original Q7-DONE sweep. Resolution: §16 bullet now strikes through + "DONE 2026-05-15T00:21:19Z (PR #3077 merged carrying Q7 ratification; see §15 step 4)" — same shape as the tokenize doc's §14 "Surfaces awaiting" Q7-DONE annotation landed in e9739ea4f. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): codex PR #3127 BLOCKING (sha 8e682eef) — §3.1 source identity + §4.2 live-vs-proposed clarity PR #3127 was merged at 02:04:22Z but codex's later review on sha 8e682eef caught two findings that still live in main. Both addressed in this PR (PR #3140) since the tokenize doc lives on main and this is the open post-merge cleanup branch. Finding 1 — §3.1 source-identity drop: Earlier draft framed tokenize input as bare `String → List<Token>`. That contradicts live `tokenize_generated.rs:96`: pub fn tokenize(source: &str, file: &str) -> Result<Vec<Token>, Diagnostic> The `file` parameter is load-bearing because `SourceSpan` requires a file/source-id field for byte ranges to be attributable; without it the Token + Diagnostic span fields would have to fabricate source-id at the pipeline boundary (P3 fail-closed violation). §3.1 now ratifies the live two-input shape: - `source: String` — UTF-8 source text (primitive). - `file: SourceFileId` — source-identity carrier; Step 2 brief ratifies the appropriate `.dag` shape (NonEmptyStr newtype or richer sum if multiple source-class kinds). Finding 2 — §4.2 live-vs-proposed blur: Prior framing said "TokenizeDiagnostic (substrate extension per Decision 2.B)" without making clear that this is a PROPOSED per-stage carrier, not the live one. The live carrier at `diagnostics.dag:150` is generic `Diagnostic { kind: AnyDiagnosticKind, ... }` with kind sum at `:139-142` discriminating CompilerKind vs LensInstanceKind; tokenize emits today via `Diagnostic::TokenizerError`-shaped sites carrying `kind: CompilerKind(...)`. §4.2 heading now reads "PROPOSED — NOT yet live" + a codex-finding callout explicitly distinguishing the live carrier from the proposed per-stage refinement + Q7 status DONE. Both fixes preserve the e9739ea4f 🟡 SCAFFOLD coproduct receipt that was already addressing codex sha 887c69671 Finding 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3127 INLINE BLOCKING line:121 — §4.3 + §9 Step 2 signature sweep Cursor inline at sha 8e682eef line:121 (the §4.3 Step 2 signature site) caught the same source-identity drop my §3.1 fix already addressed at the input-type framing — but two companion sites still had the single-input signature: - §4.3 line:151 Step 2 signature recap - §9 Step 2 row (4-step migration table) Both now read: fn tokenize(source: String, file: SourceFileId) -> Result<List<Token>, TokenizeDiagnostic> matching the §3.1 source-identity discipline + live `tokenize_generated.rs:96` `pub fn tokenize(source: &str, file: &str)` shape. Same `feedback_discipline_change_audit_all_contract_mentions` recurrence — my Finding 1 fix at §3.1 (commit 18af49fad) didn't sweep the §4.3 + §9 contract-signature restatements. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3127 INLINE BLOCKING line:166 — §6 row TokenizeDiagnostic LIVE/PROPOSED clarity Cursor inline caught ambiguity in the §6 prereq-table row for "TokenizeDiagnostic substrate extension." Old wording in column 4 read "Carrier LIVE; per-stage variant authoring NEW" which could be parsed as "TokenizeDiagnostic carrier itself is LIVE" — but no `type TokenizeDiagnostic` exists in `dsl/std/` or `src/v3/std/`. Only the generic `type Diagnostic` at `diagnostics.dag:150` is live. Cursor's secondary claim that "line 150 is EmissionDiagnostic receipt prose" is INCORRECT — verified via grep + read: `diagnostics.dag:150` is the `type Diagnostic { kind: AnyDiagnosticKind, ... }` declaration header. `type EmissionDiagnostic` lives separately at `diagnostics.dag:201`. The §6 row's citation of `:150` for the underlying Diagnostic carrier is correct. But the ambiguity-in-wording finding stands. Reframed the row: - Column 1: explicitly "PROPOSED — no `type TokenizeDiagnostic` exists yet" - Column 2: clarifies the LIVE underlying carrier is `type Diagnostic` with `kind: AnyDiagnosticKind` sum at `:139-142`; cites Q7 ratification done timestamp. - Column 4: explicit "Underlying Diagnostic carrier LIVE at HEAD; per-stage TokenizeDiagnostic variant authoring is NEW work, NOT live substrate" with cursor-finding callout. Consistent with §4.2's "PROPOSED — NOT yet live" framing from commit 18af49fad. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3141 INLINE BLOCKING line:68 — §2 structural-signature sweep Cursor inline caught §2 still framing tokenize structural signature as `String → List<Token>` — single bare-string input, no source-identity, no Result-sum failure shape — while §3.1 + §4.3 + §9 Step 2 row all ratify the live two-input + fail-fast Result-sum shape. Same `feedback_discipline_change_audit_all_contract_mentions` recurrence that's been compounding across this fix-forward sequence: each finding fix needs a doc-wide signature-restatement sweep, not just the §-local sentence. Resolution: §2 structural-shape sentence now reads `(String, SourceFileId) → Result<List<Token>, TokenizeDiagnostic>` matching §3.1 (source-identity), §4.3 (Result-sum cross-stage discriminator), §9 Step 2 row, and live `tokenize_generated.rs:96` `pub fn tokenize(source: &str, file: &str) -> Result<Vec<Token>, Diagnostic>`. Cross-refs added to §3.1 + §4.3 to make the discipline visible at the high-level framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(r3): cursor PR #3141 INLINE BLOCKING line:73 — replace invented SourceFileId with live FilePath Cursor caught me inventing `SourceFileId` as the Step 2 boundary type without a live `.dag` declaration. Verified via grep: grep -rn '^type SourceFileId' dsl/ src/v3/ returns empty. Same `feedback_grep_substrate_before_naming_ratification` family error as the earlier `ScannerCharClass` miss — naming a substrate carrier without grep-verification. Live carrier already exists at `dsl/std/types.dag:276`: type FilePath = String where non_empty referenced by `type SourceSpan { file: FilePath, ... }` at `dsl/std/types.dag:293`. So source identity flows through every Token + Diagnostic span field via the live `FilePath` carrier — no new carrier authoring needed at Step 2. Edits: - §2 structural-signature: `(String, SourceFileId)` → `(String, FilePath)` - §3.1 source-identity bullet: replaces fictional SourceFileId with the live `FilePath` declaration cite (dsl/std/types.dag:276), points out that `SourceSpan.file` already references this same carrier, and adds a cursor-finding callout naming the failure mode. - §4.3 + §9 Step 2 signature restatements: `file: SourceFileId` → `file: FilePath`. Single substrate authority (INVARIANTS P1/P2) restored: FilePath is the one carrier for source identity across SourceSpan + tokenize input + Token construction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…afts) (#3139) * docs(r3): rust retirement catalogue + emit.rs modeling doc (format-validation drafts) Per operator 2026-05-15 directive — replace SG-0 file-path ratchet (which rewards file-path manipulation / paper-shrink) with a substrate-authority planning artifact. Focus on actual `.dag` substrate growth, not ratchet file-list shrinkage. Two docs: (1) `docs/r3-rust-retirement-catalogue.md` (159 lines) - Framing: explicit anti-paper-shrink stance citing `feedback_template_relocation_paper_shrink_discriminator` (cycles 4/5/6 reverts at PR #3059) - Format spec for per-entry catalogue: Role / Public surface / Inputs / Calls into / Called by / Existing `.dag` substrate / Retirement target / Replacement plan (R1=substrate, R2=consumer-reads-substrate-not-template, R3=parity invariant — semantic NOT textual) / Anti-paper-shrink check / Phase 1-5 / Substantive retirement risks - 5-phase retirement plan ordered cheapest-first: Phase 1: hand-Rust monotonicity invariant (foreclose growth) Phase 2: test harness layer (122 → 1-3 via .dag TestClaim) Phase 3: lens-as-Rust (7-10 → 0 via data lens_X: Lens<C> + fold_lens) Phase 4: substrate-mirror generation (5-8 → 0 via regen reads substrate.dag) Phase 5: pipeline-stage retirement (12-15 → meta-circular bootstrap) - One worked example entry: src/v3/compiler/src/emit.rs (3,992 lines) with 4 substantive retirement risks flagged - 5 open format questions for operator before scaling to remaining ~176 entries (2) `docs/r3-retirement-modeling-emit-rs.md` (310 lines) - Per-file modeling doc; first instance of a series (one per Rust file) - §1 What emit.rs does (4 internal layers identified) - §2 Reference pattern (tokenize.dag) — the proven `.dag`-drives-retirement example - §3 6-layer identification ordered by tractability (Layer 1 dispatcher = most tractable; Layer 6 = whole-file retirement) - §4 Layer 1 (dispatcher) FULLY MODELED: * 4 new substrate carriers in src/v3/std/emit_model.dag: EmitTarget, EmitMode, EmittedSource, EmitTargetDispatchRow * 1 data value: emit_target_dispatch_table * 3 pure functions: emit_with_mode, emit, emit_module * Codegen driver outline: new regen_emit_dispatcher.rs following regen_tokenize.rs pattern * Parity verification: SEMANTIC (m1_3/m1_4 integration tests pass unchanged) NOT TEXTUAL (no source-clone) - §5 Sketches for Layers 2-N - §6 4 open questions about .dag substrate-language features needed - §7 Substantive retirement risks (paper-shrink discriminators) - §8 What Layer 1 demonstrates (proof-of-pattern for emit translation) Neither doc proposes changing the ratchet now — that's separate operator direction. These are planning artifacts for the substantive retirement work, not enforcement bridges. Tokenize/parse pipeline stages are already fully substrate-driven (the proof-of-concept). Lower/infer/emit have L2.5 design docs (PR #3066, #3077, #3085, #3126 just merged) but no executable `.dag` substrate yet — the modeling doc series identifies the smallest tractable layer per file to begin substantive migration. Co-authored-by: Brian (operator briansrls) — directive 2026-05-15 * docs(r3-catalogue): restructure per claude APPROVE-exploratory PR #3139 — move 5-phase plan above format spec (single authority for Phase enum) claude APPROVE on commit 458b08d (PR #3139, 2026-05-15T02:14:43Z) flagged a non-blocking exploratory note: "the catalogue's Phase enum is defined inside the per-entry format spec block, but the 5-phase plan section at the bottom is the canonical authority — if this doc lives long, consider moving the phase definitions above the format spec so the format references rather than redefines them." Applied — the doc now has the 5-phase plan section FIRST, with full definitions, and the format spec section references Phase numbers without duplicating definitions. Eliminates the dual-authority problem the exploratory note identified. Section order (post-fix): - §"5-phase plan (canonical authority for Phase enum referenced below)" - §"Format spec (per entry — references Phase numbers from §"5-phase plan" above)" - §"Catalogue" (worked example: emit.rs) - §"(Remaining ~176 entries — to be filled per format-ratified spec)" - §"Open questions for operator before format is ratified" The format spec's Phase field now reads: "Phase: one of Phase 1–5 per §"5-phase plan" above. (Definitions are NOT duplicated here — the §"5-phase plan" section is the single authority.)" No content changes beyond structure; doc is 154 lines (down 5 from de-duplication of the Phase definitions). * docs(r3): add Path B tokenize/parse brief set (9 briefs, no workarounds) Per operator directive 2026-05-15 — "could we try to do path B for tokenize/ parse (NO workarounds) now — i'd like to spawn workers under you directly". Planning doc enumerating the 9 briefs needed for true 100% .dag retirement of tokenize + parse including codegen drivers. Workers spawn directly under deep-wolf-155 (PM) per operator; no Director/Mgr layer for this lane. Dispatch graph: - Phase 0 (parallel, no deps): Briefs 1-3 substrate-language gaps - Brief 1: generic methods on FreeMonoid<T> (non-endomorphic map + per-method type params; named gap at dsl/std/algebra.dag:387-393) - Brief 2: format(template, args) + Int/Char/Bool → String primitives - Brief 3: char-class structural completion (finish in-progress scaffold at tokenize.dag:23-58) - Phase 1 (parallel, no deps on Phase 0): Briefs 4-6 host effects + bridge - Brief 4: FileReadEffect + FileWriteEffect (bundle) - Brief 5: ProcessSpawnEffect (for rustfmt) - Brief 6: compile_to_dag FFI bridge — operator decision point (FFI vs self-hosted) - Phase 2 (depends on Phases 0+1): Briefs 7-9 driver authoring - Brief 7: tokenize_codegen.dag (retires regen_tokenize.rs 1,186 lines) - Brief 8: parse_tables_codegen.dag (retires regen_parse_tables_emit.rs 1,284 lines) - Brief 9: parse_codegen.dag (retires regen_parse_emit.rs 124 lines) Cumulative: 6-12 months optimistic, 12-18 realistic. Substrate-language work in Briefs 1-6 unblocks Phase 2/3/5 broader retirement paths beyond tokenize/parse alone. 5 open questions for operator at end of doc: 1. Brief 6 FFI vs self-hosted architectural choice 2. Spawn cadence (parallel vs sequential) 3. Test harness scope (in or out of this brief set) 4. Substrate-language work attribution to Phase 2/3/5 5. Worker parallelism cap (3-4 in flight realistic) Anti-paper-shrink discriminator applies to all 9 briefs: substrate-growth PR-by-PR is the receipt, not file-path shrinkage. * docs(briefs): add Path B Phase 0 worker briefs (1-3) — individual files for dispatched workers Workers witty-moth-725 (Brief 1), sunny-tern-495 (Brief 2), bright-swift-668 (Brief 3) auto-spawned under deep-wolf-155 per operator directive. The work- item titles were truncated and didn't carry full brief content; this commit provides the canonical single-file brief per worker. - docs/briefs/r3-path-b-brief-1-freemonoid-generic-methods.md Worker: witty-moth-725 Gap: dsl/std/algebra.dag:387-393 (FreeMonoid<T>.map endomorphic only) Estimated effort: 2-6 months substrate-language work - docs/briefs/r3-path-b-brief-2-string-templating-conversions.md Worker: sunny-tern-495 Gap: no format(template, args) + verify Int/Char/Bool → String primitives Estimated effort: 1-3 months - docs/briefs/r3-path-b-brief-3-char-class-structural.md Worker: bright-swift-668 Gap: tokenize.dag:23-58 named scaffold (char_in_class NYI for structural execution) Estimated effort: 1-2 months Each brief: - Investigation-first (Phase A) — surface findings to deep-wolf-155 before authoring - Concrete deliverables + acceptance criteria (substrate-fact-at-HEAD) - Anti-paper-shrink discriminator (substrate growth, not file-path manipulation) - Coordination protocol: direct dashboard-message to deep-wolf-155, no Director/Mgr layer - PR title prefix r3-path-b-brief-N for traceability * docs(r3): address codex + briansrls BLOCKING PR #3139 — align catalogue with 0-floor target + dissolve EmitTarget closed enum into LanguageSpec open registry Two valid BLOCKING findings: (1) codex REQUEST_CHANGES (catalogue.md:31, :52, :55) — "irreducible 10-15 file seed" + "Irreducible bootstrap seed (cannot retire)" framings CONTRADICTED `docs/design-pure-bootstrap-zero.md` (LIVE 2026-04-25 cascade promotion) which establishes the in-tree floor as ZERO. Authoritative text: - line 41: "Goal: zero hand-authored files in v3's source tree." - line 95: "the in-tree floor target is 0 regardless of which N=0 resolution lands" - line 191: "If first-time bootstrap (N=0) resolution requires hand-Rust in v3's source tree — STOP. The resolution is supposed to live outside v3's source tree (install script, gunbc-runtime crate, or rustc macro)." (2) briansrls INLINE BLOCKING (modeling-emit-rs.md:125) — proposed `type EmitTarget = Go | Rust | Python` closed sum REINTRODUCED a target roster that the live `src/v3/std/emit_model.dag` header (lines 8-16) explicitly dissolves via LanguageSpec references: "Adding a new shared target is a pure spec-file change — drop a `<target>.dag` with a LanguageSpec data item and reference it from each realization. No compiler enum roster to edit." Fixes: Catalogue (docs/r3-rust-retirement-catalogue.md): - §"5-phase plan" end-state: replaced "irreducible 10-15 file seed" with 0-floor target. Files that look irreducible (bootstrap drivers etc.) retire by MOVING OUT-OF-TREE per design-pure-bootstrap-zero.md N=0 resolution paths (install script / gunbc-runtime crate / rustc macro), NOT by accepting a permanent in-tree residual. - §"Format spec" per-entry "Retirement target" options: replaced "Irreducible bootstrap seed (cannot retire; document why)" with "Moved out-of-tree". Added explicit (N.B.) citing codex BLOCKING + design-pure-bootstrap-zero.md line 191: planning artifact does NOT have authority to introduce permanent in-tree carve-outs against the live 0-floor design. Modeling doc (docs/r3-retirement-modeling-emit-rs.md): - §4.1 substrate carriers: retracted `type EmitTarget = Go | Rust | Python` closed sum. Replaced `EmittedSource.target: EmitTarget` with `EmittedSource.language: DeclarationRef` matching the `TypeRealization.language: DeclarationRef` pattern at emit_model.dag:18. Removed `EmitTargetDispatchRow` separate roster carrier — LanguageSpec registry IS the roster. - §4.2/§4.3: dispatch reads LanguageSpec declarations from src/v3/spec/*.dag directly via declaration-namespace walk; functions now take `language: DeclarationRef` parameter. - §4.4 codegen driver: GENERATED Rust uses open-registry pattern too — no hardcoded `match EmitTarget { Go => ..., Rust => ..., Python => ... }` in emitted code; dispatches via DeclarationId lookup against the live LanguageSpec registry. - §6 open question #2: variant-arm exhaustiveness check replaced with declaration-namespace-walk-by-type-tag (open-registry concern). - §7 substantive retirement risks: paper-shrink discriminator updated (no closed enum reintroduction in generated Rust). Cross-target convenience wrappers collapse to ONE `emit_text(dag, language)` parameterized function. EmitMode = Program | Module stays as a closed sum (intentionally bounded; structurally distinct from target-roster concern). * docs(r3): address briansrls BLOCKING PR #3139 at catalogue.md:21 — expand Phase 1 monotonicity invariant to full hand-Rust surface (include src/v3/compiler/tests/**) briansrls inline BLOCKING at 2026-05-15T02:48:45Z flagged that Phase 1 scoped only src/v3/compiler/src/, leaving Rust tests outside the net-shrink gate even though INVARIANTS.md P5 + T-PB-B explicitly include Rust tests in the hand-Rust surface. Verified at INVARIANTS.md:323 (Dispatch-Discipline Mechanisms (b)): "Hand-Rust includes Rust tests (src/v3/compiler/tests/**) — these are the T-PB-B test subset of the SG-0 census; the gate applies the same way it applies to T-PB-A non-test files." Fix: Phase 1 monotonicity invariant now scopes the FULL hand-Rust surface (src + tests). Eliminates the loophole where gate-closure PRs adding Rust tests would skirt the invariant — which is exactly the growth pattern observed in the SG-0 trajectory data (TEST array went 122 → 130 → 131 across recent gate-closure PRs). * docs(r3): M2 / class-5 deferral debt survey (operator-requested 2026-05-15) Per operator directive: "Can we please find all instances of this happening in this project - i want to attack one of these problems specifically so we can gather some confidence." Survey enumerates the M2-deferred / class-5-blocked work in the project: Quantitative scope: - 119 references to "class-5" across docs/ + src/v3/ + dsl/ - 61 citations naming class-5 as a blocker / dissolution trigger - 161 ArrowBody::Unparsed std fn bodies (58% of 276 total) - 1 dedicated design doc (docs/design-m2-feature-parity.md, status "Design ready for implementer review") sitting unimplemented Enumeration: 1. M2 Feature Parity (DB-9 through DB-13, design doc ready): - DB-9: Mutual recursion lowering (L) - DB-10: data value semantics (S) — RECOMMENDED ATTACK POINT - DB-11: where refinement predicates (M) - DB-12: surface generics (S) - DB-13: Disj dotted-path (S) 2. Class-5 grammar gaps (substrate-language sub-program): - #1: Brace-bodied fn on .dag files (161 Unparsed std fns) - #2: Record literals inside data bodies - #3: Lens-fold prereq - #4: Variant-constructor expressions - #5: Dimension<C> data declarations (blocked on #2) - #6: Name rosters 3. Hand-Rust trampolines that exist BECAUSE class-5 isn't closed 4. Downstream symptoms (R3 retirement stalls, lens trampolines, etc.) Recommendation: DB-10 (data value semantics) as confidence-builder: - Smallest (size S per doc) - Substrate carrier already exists (Declaration.value_body at dag.rs:122) - Gap is downstream consumers, not substrate-shape change - Closes class-5 sub-gap #2 + unblocks dimension framework + cost-lens trampoline retirement - Estimated 1-2 weeks if design is accurate - Demonstrates "we can close M2 deferrals" pattern Alternative: class-5 brace-body parse for .dag files (bigger lever, more invasive; coordinates with Brief 3 worker bright-swift-668). * docs(r3-catalogue): clean up stale 'irreducible bootstrap seed' reference in Open Questions §5 (briansrls BLOCKING PR #3139 follow-through at catalogue.md:163) briansrls BLOCKING at catalogue.md:31 about the "irreducible 10-15 file seed" framing was already addressed in commit 6bafd12 (relay arrived after fix per dashboard typical relay-after-fix pattern). However, a stale reference to "irreducible bootstrap seed" remained at line 163 in the Open Questions section — reframed as "move out-of-tree per design-pure-bootstrap-zero.md N=0 resolution paths" with explicit no-permanent-residual disclaimer. The retraction at lines 31-38 + §"Format spec" (N.B.) at line 64 remains the canonical retraction text per the prior commit. * docs(briefs): add Path B Brief 4 — DB-10 data value semantics (M2/class-5 confidence-builder attack point) Per operator directive 2026-05-15 — "lets attack DB-10 for confidence, give it to one of the existing path B brief members". Brief 4 dispatches DB-10 (data value semantics, M2 feature parity item 3a.2) to witty-moth-725 — they closed Brief 1 cleanly (PR #3142 promoted to ready) and are available for new substrate-language work. Authoritative design at docs/design-m2-feature-parity.md §DB-10 (lines 20-71); doc carries "Design ready for implementer review" status since authoring. This is the FIRST attack against the M2 / class-5 deferral pit per the survey at docs/r3-m2-class-5-deferral-survey.md. Scope: - Phase A: verify design-doc cited locations (dag.rs:122, lower.rs:1404, test_3a2_data_field_access_resolves_statically test ratchet) against HEAD; surface drift findings to deep-wolf-155 - Phase B: land 3 consumers per design — Dag::data_value_at accessor + SurfaceExpr::Var fallback for scalar inlining + lower_field_path_expr walks ValueBody::Structural for static field access - Phase C: test fixture demonstrating data answer = 42 + answer + 1 emits 42 + 1 inline across all 3 target languages Architectural commitment honored (per design + PR #496 2026-04-17): inlining at LOWERING, not emission. Load-bearing per locked test ratchet. Emission-time inlining REJECTED. Coordination: parallel to PR #3142 merge (Brief 1 closure); separate branch; report findings directly to deep-wolf-155 (no Director/Mgr layer). Coordinate with sunny-tern-495 (Brief 2) + bright-swift-668 (Brief 3) only if substrate work overlaps. Anti-paper-shrink discriminator: locked test asserts no FieldProject Transform exists in the lowered DAG for data-resolved field accesses; that ratchet catches trampoline-style workarounds. Estimated effort: 1-2 weeks if design doc is accurate. * docs(r3): retract stale 'M2 not landed' framing — DB-10/12/13 verified LANDED at HEAD 2026-05-15 Per gentle-bat-24 Brief 4 Phase A finding (DB-10 substrate already implemented at HEAD with `Dag::data_value_at` at dag.rs:4310 + lower.rs:8489+/8642+/9125+ + passing test at m2_feature_parity_test.rs:771) + subsequent verification of DB-12/DB-13 status amendments in PR #496 against HEAD test names: DB-10: LANDED DB-12: LANDED (parse_generated.rs:927; m2_feature_parity_test.rs:90-156) DB-13: LANDED (lower.rs:3375; m2_feature_parity_test.rs:163-208) DB-9 + DB-11: HEAD landed-state NOT YET AUDITED; may also be silently landed Sites updated: - docs/r3-m2-class-5-deferral-survey.md: M2 feature parity table reframed with cited HEAD evidence per DB; explicit retraction of "no DB item has landed yet" claim; active deferral pits shrink to DB-9 + DB-11 (pending audit) plus class-5 sub-gaps which remain genuinely deferred per Brief 3 findings - docs/design-m2-feature-parity.md: top-level Status line updated from "Design ready for implementer review" to "3 of 4 LANDED" with per-DB cited HEAD evidence; explicit advisory that workers should audit HEAD state before authoring implementation against this doc Residual M2 work for the 3 LANDED items: emission-test-coverage gap for DB-12 + DB-13 (design §Acceptance promises 3-target render verification; current tests check compile + lower only). Small follow-up scope; not pit-shaped. The "M2 deferral pit" framing was substantially wrong as initially described — much of M2 has been silently landing. The class-5 sub-gaps remain genuinely deferred per Brief 3's bright-swift-668 investigation (brace-body fn parse on .dag files). Per `feedback_corrections_must_grep_verify_source` — this is the canonical lesson: design docs drift; verify against HEAD before authoring against them. * docs(r3): address codex BLOCKING PR #3139 (review #12458) — retract String-typed EmitDispatchError + retract Brief 6 FFI bridge as deliverable path Two findings, both valid: (1) modeling-emit-rs.md:203 — proposed `type EmitDispatchError { language: DeclarationRef, detail: String }` as 🟡 SCAFFOLD. RETRACTED. INVARIANTS P3 + docs/modeling-discipline.md Practice 1 forbid String-typed diagnostic channels at the substrate-API level. SCAFFOLD-with-String at the API level is still a String-API at HEAD; the scaffold marker doesn't excuse the typed-carrier requirement. Fix: defer the EmitDispatchError shape entirely until per-language typed error carriers land (Brief 7+). Dispatcher signature stays Result<EmittedSource, ???> with ??? as forward-reference. Workers attempting Brief 7+ surface back if the error-carrier shape becomes load-bearing before per-language errors exist — substantive substrate-language question, not papered over with String channel. (2) brief-set.md:206 — Brief 6 presented an "FFI bridge" option (a) as a deliverable path. The brief text itself admitted "does not retire the Rust compile_to_dag function itself" — that's a bridge preserving hand-Rust compiler authority, NOT retirement. Operator's NO WORKAROUNDS stance + INVARIANTS P5 forbid FFI as deliverable path. The brief currently muddled this; codex correctly flagged that the wording would send a worker to execute the wrong work. Fix: Brief 6 reframed as SCOPE MARKER ONLY (Phase 5 program, NOT dispatchable within this brief set). Recommendation surfaced to operator: declare Phase 5 / meta-circular bootstrap as separate program from Path B; tokenize/parse codegen-driver retirements (Briefs 7-9) are downstream of Phase 5 and not landable until self-hosted compile_to_dag lands. Honest framing: forcing Briefs 7-9 to land before Phase 5 via FFI bridges produces paper-shrink, not retirement. Sites updated: - modeling-emit-rs.md §4.3 EmitDispatchError block: explicit RETRACTION text; signature now Result<EmittedSource, ???> with forward-reference framing - brief-set.md §"Brief 6 — Meta-circular: compile_to_dag Foreign-Function Bridge" retitled to "self-hosted compile_to_dag (Phase 5 scope expansion)" + scope reframed as SCOPE MARKER ONLY - brief-set.md dispatch graph: Brief 6 marked NOT DISPATCHABLE - brief-set.md §Brief 7 prerequisites: Briefs 1-5 + Phase 5 separately - brief-set.md §Brief 7 scope: cites separately-scoped Phase 5 program - brief-set.md §"Open questions for operator before dispatch" #1: RESOLVED per this codex BLOCKING; no FFI workaround acceptable * WIP: Path B Brief 4 — M2 DB-10 data value semantics (data foo: T = v usable a * docs(r3): finish typed emit error retraction
Summary
Context
Per
SELF_HOSTING.md§2.2 gating rule 4: PB-4 lower-stage L3.dagsubstrate work cannot start until this L2.5 is reviewed. PB-6 emit L2.5 landed at PR #3066; PB-4 lower is next in migration order (persubstrate-reflection-design.md§12.6 bottom-up: emit → lower → infer → parse → tokenize).Authoring discipline applied
This doc applies all learnings from the PR #3066 PB-6 emit L2.5 BLOCKING-review cycle:
PreInferDagvariant per Decision 3.A operator-ratified sum-variant shapefeedback_typed_state_carriers_arent_metadata_markersdisciplinesrc/v3/std/diagnostics.dag:150)fn lower(surface: SurfaceModule, elaboration: ElaborationSpec) -> LowerResultSections
§12 Q1-Q6 open questions
Test plan
Dag = PreInferDag | InferredDagcarrier extension)🤖 Generated with Claude Code