Skip to content

docs(briefs): 4 receipt-closure dispatch briefs + ROADMAP debt rows - #614

Merged
briansrls merged 9 commits into
mainfrom
session/zesty-bear-812
Apr 21, 2026
Merged

briansrls merged 9 commits into
mainfrom
session/zesty-bear-812

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Summary

Four dispatch briefs for the next wave (receipt-closure, not step-function) per the SG manager's recommended next-wave queue, plus ROADMAP debt-row updates capturing items surfaced during the 2026-04-20 → 2026-04-21 merge wave that didn't land in lanes.

Briefs

Brief Size Scope
SG-4b-1-fix S Delete DeclarationLookup + find_declaration parallel authority from #609; consumers use Dag::declaration(id). Cleans up the C-8/fail-open issue.
SG-3g-b M Wire #612's staged lower_helpers.expr_span into lower.rs's 16 hand-authored match sites. Turns #612 from staging → real receipt.
SG-2c-2 M-L Next bounded parser-data extraction from parse_parser_body.txt (item-keyword OR punct-operator table). Same pattern as SG-2c-1.
1e-2b M-XL (decision-first) Retry Lane 1e-2 after #610 misclassification. Path A: Class 5 Gap 1 (Bool → BooleanAlgebra grounding) + delete hardcoded Logical branches. Path B: different verified cluster after Phase 0 check.

ROADMAP debt rows added

Post-merge debt (2026-04-21 receipt-closure wave):

  • Class 5 Gap 1 — Bool grounding gap
  • SurfaceLiteral → LiteralBits rename (emit_rust_module gap)
  • render_variant_constructor tuple variant gap (emit_rust_module)
  • SG-4b-1 DeclarationLookup parallel authority (live on main post-SG-4b-1 #609)

Wave framing

This is a receipt-closure wave, not step-function. No full-file retirement, no walker collapse, no new XXL umbrella lanes without verified clusters. Closes design debts surfaced by prior wave; validates patterns end-to-end on small slices.

Meta-observation: pattern holding well since lessons of #608/#610 — small bounded receipts work; big-bang XXL lanes without verified clusters produce flawed outputs fast.

Test plan

  • Docs-only PR; no compiler behavior changes
  • CI: fmt should pass (markdown only)
  • Briefs render correctly

🤖 Generated with Claude Code

Briefs for the next wave per SG manager recommendation:

- docs/briefs/sg-4b-1-fix-declaration-lookup-cleanup.md (S) —
  delete DeclarationLookup + find_declaration parallel authority
  from #609's merged tranche; consumers use Dag::declaration(id).
- docs/briefs/sg-3g-b-lower-helpers-wire-in.md (M) — wire 16
  expr_span call sites in lower.rs to consume the generated
  lower_helpers helper from #612's staging.
- docs/briefs/sg-2c-2-next-parser-table.md (M-L) — next bounded
  parser-data extraction from parse_parser_body.txt following
  SG-2c-1 pattern; item-keyword or punct/operator table.
- docs/briefs/1e-2b-class-5-gap-1-or-different-cluster.md (M-XL,
  decision-first) — retry Lane 1e-2 after #610 miss. Path A:
  Bool → BooleanAlgebra grounding (Class 5 Gap 1) then logical
  ops via existing OperatorRealization. Path B: different
  verified cluster after Phase 0 verification.

ROADMAP debt rows added to "Post-merge debt (2026-04-21
receipt-closure wave)":
- Class 5 Gap 1 (Bool grounding) — owner 1e-2b Path A
- emit_rust_module SurfaceLiteral→LiteralBits rename gap (from #612)
- emit_rust_module render_variant_constructor tuple variant gap
  (from #612)
- SG-4b-1 DeclarationLookup parallel authority (from #609 override)

Receipt-closure wave posture: no full-file retirement, no walker
collapse, no new XXL umbrella lanes without verified clusters.
Closes design debts surfaced by prior wave; validates patterns
end-to-end on small slices before next step-function dispatch.

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

Copy link
Copy Markdown
Contributor Author

Latest read: this package is mostly in good shape, and the overall queue is aligned with the post-merge state. I have one material correction to make before I’d treat the brief set as fully clean.

Blocking direction: SG-3g-b brief is mis-stating the real blocker

In the SG-3g-b brief, the Read first / Non-goals section says the two blockers named in #612 are:

  • SurfaceLiteral -> LiteralBits rename gap
  • render_variant_constructor external tuple variant handling

and then says those are not blocking wire-in.

That is not the current state of #612.

Per the merged #612 body, the real blocker for wire-in is:

  • parse / parse_surface convergence
  • the staged helper types against parse_surface::SurfaceExpr
  • lower.rs still operates on parse::SurfaceExpr
  • the available bridge is a deep-clone From path, which the PR explicitly rejects as a regression

The two emit gaps above were blockers for the earlier candidate slices that were abandoned. They are important debt rows, but they are not the gating reason SG-3g-b is parked.

Requested fix to the brief

Please revise SG-3g-b so it reads something like:

  • primary prerequisite / first read: the parse vs parse_surface split called out in #612
  • explicit STOP: if wire-in requires per-call deep cloning across that boundary, stop and escalate
  • keep the LiteralBits rename gap and external tuple-variant constructor gap as adjacent debt, but not as the main wire-in blocker

Right now the brief risks dispatching a worker toward the wrong prerequisite.

Everything else

Outside that, the packet reads well:

  • SG-4b-1-fix is the right cleanup lane for the post-merge lookup-authority debt in #609
  • SG-2c-2 is a good continuation of the #611 table-extraction pattern
  • 1e-2b is correctly decision-first after the #610 misclassification
  • the ROADMAP debt rows are useful and grounded in the actual merge wave

So from my side: one real fix on SG-3g-b, rest looks sound.

Codex inline review on #608 caught a 5th audit error: Cluster E's
proposed OptionalTypeRendering.wrapper_template is already covered by
TypeApplicationSyntax.optional in emit_model.dag (consumed by
go/python/rust emit — e.g., go_type_applications.optional: "*{element}").

1e-2b's Phase 0 verification section now explicitly names Cluster E
alongside A, B, C, F, H as known-to-skip. Path B workers will
correctly bypass it; Path A is unaffected.

The #608 audit document itself remains un-fixed on main — this is a
forward-looking brief update rather than a retroactive correction.
The 1e-2b "treat #608's classification as hypothesis, verify before
implementing" posture covers the remaining uncontested clusters.

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

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 32446d5f · Trigger: schedule
  • Thinking: 19s wall

Verdict: APPROVE — diff is docs-only (4 new dispatch briefs under docs/briefs/ + 4 tracked-debt rows in ROADMAP.md:164-169). No substrate, no code, no tests changed. The new ROADMAP entries satisfy scaffold-boundaries discipline: each names a specific dissolution trigger and an owner/lane (1e-2b, SG-3g follow-up, SG-3g follow-up, SG-4b-1-fix). The briefs themselves cite live files, flag Phase 0 verification as non-negotiable, and include STOP-AND-ESCALATE clauses that prevent silent scope widening. Nothing in this diff touches modeling, fail-closed paths, or enum classification, so those principles don't apply here.

Exploratory observations (optional):

  • ROADMAP.md:167 ("SurfaceLiteral → LiteralBits rename") and ROADMAP.md:168 (render_variant_constructor external tuple variants) are listed as "unassigned" debt. That's honest, but per no-short-term-solutions / scaffold-boundaries, an unassigned owner is weaker than a named lane — worth pulling into the next dispatch wave rather than letting them drift. Not a finding against this diff, just flagging that the two rows are the least-anchored of the four.
  • The Path A / Path B decision-first framing in docs/briefs/1e-2b-class-5-gap-1-or-different-cluster.md is a nice pattern for ambiguous lanes; consider reusing it whenever a brief's classification is itself uncertain.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32446d5fd7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ROADMAP.md Outdated
- **Class 5 Gap 1 — `Bool` inhabits `BooleanAlgebra<Bool>` grounding not wired**: surfaced during #610's closing. Current `OperatorKind::Logical(_)` dispatch in the three emitters is hardcoded (`if let OperatorKind::Logical(_)` branches bypass the algebra-field resolution that arithmetic operators use). The substrate already models `BooleanAlgebra<T>` with `meet/join/complement` per `dsl/std/algebra.dag:230-236`, and comments there state *"Bool inhabits BooleanAlgebra"* — but the `inhabits` edge isn't structurally landed. Dissolution: wire `Bool inhabits BooleanAlgebra<Bool>` + extend `resolve_operator_arrow` for `OperatorKind::Logical(_)` + delete the hardcoded emitter branches. Owner: 1e-2b lane (Path A).
- **`emit_rust_module` gap: SurfaceLiteral → LiteralBits rename**: substrate declares `LitInt/LitBool/LitString` in `LiteralBits`; Rust enum is `Int/Bool/String`; no rename facility in `emit_rust_module` causes connective-producing slices (per #612's staging choice notes) to fail on this. Dissolution: add per-variant name mapping in spec or rename-facility in emit. Owner: unassigned; blocks deeper SG-3g slices.
- **`emit_rust_module` gap: `render_variant_constructor` fails on external tuple variants**: `src/v3/compiler/src/emit/rust_target.rs:4296` unconditionally emits `Variant { _0: value }` which is wrong for external tuple variants. Dissolution: spec-driven variant-constructor template per source kind. Owner: unassigned; blocks deeper SG-3g slices.
- **SG-4b-1 `DeclarationLookup` parallel authority**: PR #609 merged with a fail-open `find_declaration` / `DeclarationLookup` path that duplicates `Dag::declaration(id)` and converts Track-9 constructor-validation failures into normal inference outcomes (C-8 violation). Dissolution: replace consumers with `Dag::declaration(id)`, delete the parallel path. Owner: SG-4b-1-fix lane.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Remove nonexistent SG-4b-1 debt from roadmap

This new debt row says a live find_declaration/DeclarationLookup path still exists, but in this revision those symbols are already absent from both src/v3/lenses/infer_helpers.dag and src/v3/compiler/src/infer_helpers_generated.rs (the helper file only contains TemplateArgumentLookup and related functions). Keeping this as an active lane makes the associated cleanup brief unexecutable and its acceptance criteria impossible to verify, which can misdirect follow-up work.

Useful? React with 👍 / 👎.

briansrls and others added 3 commits April 21, 2026 02:34
Codex inline review on #608 flagged internal contradiction:
PR-4.2's claim "new target = one spec file, zero walker changes"
contradicted Category 3's named per-target walker hooks (Go
modules, Python indent, Go Loop feature gap).

Both statements can't hold: if the walker has per-target hooks
for those three concerns, a new target with different module
semantics / whitespace rules would require a new hook (walker
change).

Calibrated: PR-4.2's claim now reads "new target = one spec file
+ reuse of existing per-target hook categories." Targets fitting
the residual hook surface need zero walker changes; targets with
new language-intrinsic concerns add one narrow hook (same small
surface as the three existing residuals).

Two edits:
- Phase 4 table: PR-4.2 description reworded
- Estimated Impact section: "Thesis claim validated (calibrated)"
  explains the walker-change surface IS the per-target-hook
  surface, not zero — but that surface is narrow and matches
  the three named residuals.

Doc-only correction to the merged #608 audit; the calibrated
falsifier is what Phase 4 actually tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Earlier fix (cbd7b70) marked all of Cluster E as "already covered"
— too broad. Codex's nuanced re-read caught that Cluster E bundled
two unrelated concerns:

1. `wrapper_template` (type-wrapper syntax Option<T> / *T /
   Optional[T]) — really is covered by TypeApplicationSyntax.optional.
2. `none_literal` / `some_constructor` / `deref_syntax` / `none_check`
   (expression-level None/Some rendering + check strategy) — NOT
   covered by TypeApplicationSyntax (that's type-level).

LiteralSyntax covers true/false/string_delimiter but not None/Some.
The expression-level optional behavior may be handled via
PatternBindingRule + VariantPayloadFieldAccessRule (structural
variant dispatch) OR may be hardcoded — Phase 0 verification
required before implementing.

1e-2b's Cluster E skip entry now reflects the split: wrapper_template
→ skip (Category 1), expression-level fields → verify before
implementing. If verification shows they're structurally handled,
also Category 1. If verification shows they're hardcoded branches,
the narrow Category 2 scope is just those expression-level facts —
not the wrapper_template.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reviewer (briansrls) caught: SG-3g-b brief mis-stated the
blockers for wire-in. Per #612's actual body:

**Primary wire-in blocker**: parse vs parse_surface convergence.
Generated helper types against parse_surface::SurfaceExpr;
lower.rs uses parse::SurfaceExpr. The available From bridge
deep-clones across 16 call sites, which regresses the lowerer —
#612 explicitly rejects this.

**Secondary blocker**: render_variant_constructor external
tuple-variant handling (blocks connective-producing lens slices
generally, not specific to expr_span).

**NOT a wire-in blocker**: SurfaceLiteral → LiteralBits rename.
That was a reason for abandoning *alternative* candidate slices
during #612, not a blocker for the expr_span slice that was
actually selected.

Changes to the brief:

1. "Read first" now names the type-convergence blocker as primary,
   keeps the tuple-variant concern as secondary, and explicitly
   says LiteralBits rename is NOT a wire-in blocker (just named
   debt from candidate-slice abandonment).

2. New "Phase 0 verify" step before touching call sites —
   confirm the deep-clone situation matches #612's body.

3. New "Core wire-in (resolve type-convergence)" section with
   three options A/B/C for the worker to evaluate (unify types,
   lower.rs adopts new type, helper generates against old type).
   Worker picks + justifies in PR body.

4. STOP-AND-ESCALATE updated: primary STOP is now "wire-in
   requires per-call deep cloning across the boundary" — that's
   the critical no-compromise gate. Deep-clone wire-in is worse
   than the current staging state.

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

Copy link
Copy Markdown
Contributor Author

Reviewer correct — my SG-3g-b brief mis-stated the real wire-in blocker. Fixed at HEAD.

Re-read of #612's body confirms:

Primary wire-in blocker: parse vs parse_surface convergence — generated helper types against parse_surface::SurfaceExpr; lower.rs uses parse::SurfaceExpr; existing From bridge deep-clones across 16 call sites, which #612 explicitly rejects as a regression.

Secondary blocker: render_variant_constructor external tuple-variant handling (blocks connective-producing slices generally).

NOT a wire-in blocker: SurfaceLiteral → LiteralBits rename — that was a reason for abandoning alternative candidate slices during #612, not for this slice's wire-in.

Changes to SG-3g-b brief

  1. "Read first" reordered: type-convergence named as the primary blocker; tuple-variant gap secondary; LiteralBits rename explicitly marked as named-debt-not-wire-in-blocker.

  2. New "Phase 0 verify" step before touching call sites — worker confirms the deep-clone state matches SG-3g: lower_helpers lens staging (wire-in parked) #612's framing.

  3. New "Core wire-in (resolve type-convergence)" section with three option paths (A: unify types; B: lower.rs adopts new type; C: helper generates against old type). Worker picks + justifies in PR body.

  4. STOP-AND-ESCALATE primary gate updated: "wire-in requires per-call deep cloning across the boundary" — that's the critical no-compromise gate. Deep-clone wire-in is strictly worse than the current staging state.

Other three briefs (SG-4b-1-fix, SG-2c-2, 1e-2b) unchanged per your "rest looks sound" signal. Ready for re-read on SG-3g-b when convenient.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / gpt-5.4
  • Commit: 32446d5f · Trigger: schedule
  • Thinking: 440s wall

BLOCKING (2)

Root Cause

  • docs/briefs/sg-4b-1-fix-declaration-lookup-cleanup.md Historical #609 review context was copied into the brief without re-verifying the current infer-helper authority → re-check the referenced files on the target branch before adding debt rows or dispatch docs.
  • docs/briefs/sg-3g-b-lower-helpers-wire-in.md The brief rechecked earlier emit-gap blockers but not the current helper authority header that names the actual gate → either retarget SG-3g-b to the convergence work or explain how that type mismatch is closed first.

Non-blocking — Strengths

  • docs/briefs/1e-2b-class-5-gap-1-or-different-cluster.md The Path A / Path B split plus mandatory Phase 0 verification is well-calibrated against the thesis and does a good job preventing another carrier-style workaround.

Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)

  • docs/briefs/sg-2c-2-next-parser-table.md The ratchet reference should point at src/v3/compiler/tests/integration/sg2c1_parse_tables_authority_test.rs, which is the existing parse-tables authority check, not sg2_parse_authority_test.rs.

ROADMAP — Verified

  • Class 5 Gap 1 — Bool grounding gap: The new Bool/BooleanAlgebra debt row matches live code: infer still documents the missing structural Bool link and the emitters still special-case logical operators.

ROADMAP — Incomplete

  • SG-4b-1 DeclarationLookup parallel authority: This new debt row is stale because the referenced infer-helper parallel authority is not present in the current branch state.

⚠️ Two of the new dispatch briefs describe stale or still-blocked work, so the docs should be brought back in sync with live branch state before they become the next-wave queue.


## Work

1. **Delete `DeclarationLookup` enum and `find_declaration` fn** from `infer_helpers.dag`.

This comment was marked as resolved.

## Work

1. **Identify all 16 `expr_span` call sites** in `lower.rs` (grep for the pattern, verify count matches #612's body claim).
2. **Replace each call site** with a call to the generated `lower_helpers::expr_span(...)` fn. Import the generated module as needed in `lib.rs` / `lower.rs`.

This comment was marked as resolved.

…anup

Codex reviewer correctly flagged: find_declaration /
DeclarationLookup are NOT in infer_helpers.dag /
infer_helpers_generated.rs on main. Those files were cleaned up
independently after #609; they now contain only
TemplateArgumentLookup.

The pattern DOES persist on main — in
`src/v3/lenses/variant_payload.dag`:

  type DeclarationLookup
    = LookupMissing
    | LookupFound(Declaration)

  fn find_declaration(decls: List<Declaration>, target: ...) -> DeclarationLookup = ...

Same concerns (parallel O(n) walk vs Dag::declaration; fail-open
vs fail-closed C-8) — just different file. Variant names are
slightly different (LookupMissing / LookupFound vs
MissingDeclaration / FoundDeclaration) reflecting the separate
author path.

Updates:
- ROADMAP debt row now cites variant_payload.dag
- SG-4b-1-fix brief retargeted: Read first, Context, Work,
  Acceptance all point at src/v3/lenses/variant_payload.dag
- Acceptance now includes a sanity grep confirming zero hits
  post-cleanup
- The "originally surfaced via #609; that file cleaned up
  independently; pattern persists in variant_payload.dag"
  framing makes the migration context honest

The underlying work is unchanged in shape: delete the parallel
authority, consume the canonical Dag::declaration accessor,
treat missing-id as a substrate-integrity violation not a normal
lens outcome.

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

Copy link
Copy Markdown
Contributor Author

Reviewer correct — but with a nuance: find_declaration / DeclarationLookup don't exist in infer_helpers anymore, but the pattern DOES persist on main in src/v3/lenses/variant_payload.dag. The infer_helpers side was cleaned up independently after #609.

Verified on origin/main:

$ git grep "DeclarationLookup" origin/main -- 'src/v3/lenses/'
origin/main:src/v3/lenses/variant_payload.dag:type DeclarationLookup
origin/main:src/v3/lenses/variant_payload.dag:fn find_declaration(decls: List<Declaration>, target: DeclarationId) -> DeclarationLookup =
...

The pattern variants are slightly renamed (LookupMissing | LookupFound(Declaration) vs the MissingDeclaration | FoundDeclaration from #609's original diff) but same shape — parallel O(n) walk + fail-open contract.

Fix pushed

  1. ROADMAP debt row now cites src/v3/lenses/variant_payload.dag as the live location, acknowledges the infer_helpers cleanup happened independently.

  2. SG-4b-1-fix brief retargeted across Read first / Context / Work / Acceptance — all now point at variant_payload.dag. Added sanity grep to the acceptance: git grep "DeclarationLookup\|find_declaration" src/v3/lenses/ returns zero hits post-cleanup.

The debt is real and the brief is now executable against the actual file. Thanks for the catch — saves the worker from reading the wrong file.

Codex reviewer flagged (at line 44, but the issue was broader):
previous retargeting at 19eeb5c2 missed stale references in the
STOP-AND-ESCALATE section (line 58 mentioned "regen_infer_helpers
ratchet"; line 59 named infer_helpers.dag / infer_helpers_generated.rs
as scope gates) and the Size section (line 70 said
"deleted from infer_helpers.dag, corresponding deletion in
infer_helpers_generated.rs").

Those were leftover from the original infer-focused draft and
would have misdirected the worker.

Changes:
- STOP item 2: "regen_infer_helpers" → "variant_payload regen
  ratchet (or equivalent lens freshness check)"
- STOP item 3: "infer_helpers.dag / infer_helpers_generated.rs"
  scope-gate → "variant_payload.dag / variant_payload_generated.rs"
- Non-goals: explicit "not touching infer_helpers.dag" line
  (confirm via sanity grep; do not modify)
- Size estimate: retargeted to variant_payload with 30-80 LOC
  (more accurate for a lens file vs the earlier infer estimate)
- Dispatch note: "inference tests" → "variant-payload + adjacent
  tests"

Remaining `infer_helpers` references are honest — they document the
migration context (pattern was originally in infer_helpers, cleaned
up independently, persists in variant_payload).

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

Copy link
Copy Markdown
Contributor Author

Verified — reviewer pointed at line 44 but the issue was broader. My previous fix at 19eeb5c2 retargeted the primary sections (Context, Read first, Work, Acceptance) to variant_payload.dag but missed leftover infer_helpers references in:

  • STOP-AND-ESCALATE (lines 58-59): still said "breaks the regen_infer_helpers ratchet" and "touching outside infer_helpers.dag / infer_helpers_generated.rs"
  • Size section (line 70): estimated "~50-100 LOC deleted from infer_helpers.dag, corresponding deletion in infer_helpers_generated.rs"

Both would have misdirected a worker to the wrong file mid-execution. Scrubbed at HEAD:

  • STOP items now correctly cite variant_payload.dag / variant_payload_generated.rs as the scope gate
  • Size estimate retargeted (30-80 LOC, more accurate for lens file scope)
  • Non-goals explicit: "not touching infer_helpers.dag; confirm via sanity grep but do not modify"
  • Dispatch note: "inference tests" → "variant-payload + adjacent tests"

The remaining infer_helpers references in the Context/Read-first sections are intentional — they document the migration history (pattern originally in infer_helpers, cleaned up independently, persists in variant_payload). Worker will understand the file lineage.

Thanks for the catch; the line-44 point made me re-scan and find the other stale references.

@briansrls

Copy link
Copy Markdown
Contributor Author

Already addressed at 7b8534c (pushed before this review relay arrived). Current HEAD has the fix in place.

Verified at current HEAD of #614:

  • Line 17 (Read first): "The primary wire-in blocker: parse / parse_surface convergence (SG-3f follow-up). Per SG-3g: lower_helpers lens staging (wire-in parked) #612: generated helper types against parse_surface::SurfaceExpr; lower.rs uses parse::SurfaceExpr. The available From bridge deep-clones across 16 call sites — that wires in but regresses the lowerer."

  • Line 23 (Work): "Phase 0 — verify the type-convergence blocker is what the PR body named" with explicit grep instructions.

  • Line 32 (Work): "Core wire-in (resolve the type-convergence problem)" with three option paths (A: unify types; B: lower.rs adopts new type; C: helper generates against old type).

  • Line 63 (STOP-AND-ESCALATE): "If wire-in requires per-call deep cloning across the parse::SurfaceExpr ↔ parse_surface::SurfaceExpr boundary — STOP. That regresses the lowerer, not improves it." Named as the critical no-compromise gate.

The finding matches the fix I pushed at 7b8534c. The reviewer was pinned at an older sha; relay timing mismatch.

No new action needed — the brief already states exactly what the reviewer is asking for. Sanity-check line numbers against current HEAD before concluding stale.

Codex reviewer (non-blocking): SG-2c-2 brief pointed at the wrong
ratchet test. Both files exist on main:

- src/v3/compiler/tests/integration/sg2_parse_authority_test.rs
  (older parser-staging authority, from #589)
- src/v3/compiler/tests/integration/sg2c1_parse_tables_authority_test.rs
  (the SG-2c-1 parse-tables ratchet — the actual template SG-2c-2
  should replicate)

Fixed two references:
- "Read first" line now cites sg2c1_parse_tables_authority_test.rs
  with an explicit "not sg2_parse_authority_test.rs" clarification
- "Extend the ratchet test" step points at the correct file

Ergonomic fix — prevents worker from editing the wrong file or
copy-pasting the wrong pattern during SG-2c-2 execution.

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

Copy link
Copy Markdown
Contributor Author

Reviewing the consolidated codex review (sha 32446d5f, pre-fix). Both blockers already addressed in earlier commits; one non-blocking improvement fixed now.

Item 1 — SG-4b-1-fix stale infer context

Already addressed at 19eeb5c + 9b0bca7. The brief is now retargeted to src/v3/lenses/variant_payload.dag where the DeclarationLookup / find_declaration pattern actually persists on main. Stale scope gates in STOP-AND-ESCALATE and Size sections scrubbed. Verified infer_helpers.dag no longer carries the pattern; brief acknowledges that migration explicitly.

Item 2 — SG-3g-b convergence gate

Already addressed at 7b8534c. Brief now explicitly names parse / parse_surface convergence as the primary wire-in blocker (lines 17, 23, 32, 63), with Phase 0 verify step, three option paths for resolving, and the deep-clone STOP-AND-ESCALATE as no-compromise gate.

Non-blocking improvement — SG-2c-2 ratchet file reference

Fixed now at HEAD. Verified both files exist on main:

Brief's two references (Read first + Work step 5) now point at sg2c1_parse_tables_authority_test.rs with an explicit clarifying note.

ROADMAP — Incomplete (reviewer stale)

Reviewer flagged "SG-4b-1 DeclarationLookup parallel authority" debt row as stale. This was already corrected at 19eeb5c — row now cites src/v3/lenses/variant_payload.dag as the live location, not infer_helpers. Reviewer's sha predates that fix.

ROADMAP — Verified

Reviewer confirms Class 5 Gap 1 row matches live code. ✓

Non-blocking strength

1e-2b Path A / Path B decision-first split noted as well-calibrated. Thanks — intent to reuse the pattern for future ambiguous lanes.

Summary

All live items addressed; no new action beyond this commit. Ready for re-review.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 9b0bca71 · Trigger: schedule
  • Thinking: 24s wall

Verdict: APPROVE — docs-only PR. Four brief files + four ROADMAP debt rows + a calibration tweak to emit-target-spec-gaps.md. No source/substrate code is touched, so the modeling-discipline lens has nothing to bite.

The four ROADMAP debt entries (lines 164-167) each carry the three properties the scaffold-boundary rule asks for: a named symptom, a bounded scope, and an explicit dissolution trigger with an owner lane. That's the right shape for tracked debt.

The briefs themselves are planning artifacts — they call out their own STOP-AND-ESCALATE conditions, name Phase 0 verification before implementation, and explicitly flag "wrong outcome is another misclassified carrier like #610" (1e-2b brief). The emit-target-spec-gaps.md edit at line 293 is a useful honesty-correction: walks back the strong "zero walker changes ever" claim to "walker-change surface is the narrow per-target-hook surface" — that's a doc moving toward live state, not away from it.

One small observation (non-blocking): The 1e-2b brief cites src/v3/compiler/src/emit/rust_target.rs:3312 and emit/python_target.rs:783, while the ROADMAP debt entry cites src/v3/compiler/src/emit/rust_target.rs:4296 for a different gap. Line numbers in briefs go stale fast; if you want them durable, anchor by symbol name (e.g., "render_variant_constructor", which the ROADMAP entry already does) rather than line. Not worth a re-spin.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / gpt-5.4
  • Commit: 9b0bca71 · Trigger: schedule
  • Thinking: 468s wall

BLOCKING (1)

Root Cause

  • src/v3/std/substrate.dag reflected substrate exposes keyed port/node accessors but no keyed declaration accessor → add typed declaration lookup authority first, or explicitly rescope SG-4b-1 as substrate-extension work instead of a variant_payload-only cleanup

Non-blocking — Strengths

  • docs/briefs/sg-2c-2-next-parser-table.md The brief now points SG-2c-2 at the live sg2c1_parse_tables_authority_test.rs ratchet, which is the authority test that actually guards parse_tables.dag / parse_tables_generated.rs.
  • docs/briefs/1e-2b-class-5-gap-1-or-different-cluster.md Path A / Path B plus mandatory Phase 0 verification matches the live logical-operator state and avoids reintroducing the rejected parallel LogicalOperatorCarrier.
  • docs/briefs/sg-3g-b-lower-helpers-wire-in.md This now reflects the real wire-in gate: lower_helpers_generated.rs is typed against parse_surface::SurfaceExpr, lower.rs still owns its local expr_span, and the available mirror path is a deep-cloning bridge.

ROADMAP — Verified

  • Class 5 Gap 1 — Bool grounding gap: The new debt row matches live code: resolve_operator_arrow still falls back Logical ops to Bool-monomorphic scaffolding and all three emitters still special-case logical symbols.
  • SG-4b-1 DeclarationLookup parallel authority: The new debt row now points at the live variant_payload.dag / variant_payload_generated.rs authority split rather than the already-cleaned infer_helpers site.

⚠️ One dispatch brief is still scoped around substrate authority that does not exist yet, so I would fix that mismatch before using it as next-wave queue input.

## Work

1. **Delete `DeclarationLookup` enum and `find_declaration` fn** from `src/v3/lenses/variant_payload.dag`.
2. **Replace consumer sites** in the same file (grep for `find_declaration(` within `variant_payload.dag`) with direct consumption of the canonical declaration accessor — whatever `.dag`-side surface resolves to `Dag::declaration(id)` without going through a parallel enum.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

BLOCKING: This brief assumes a live .dag equivalent of Dag::declaration(id), but the reflected substrate still does not expose that accessor, so the promised variant_payload-only cleanup cannot honestly close the single-authority / fail-closed issue as scoped.

@briansrls

Copy link
Copy Markdown
Contributor Author

Verified at current HEAD — this is a stale relay. Fixes landed at 19eeb5c + 9b0bca7 (both pushed well before this 06:57 relay timestamp).

Line 44 at current HEAD (verified just now):

2. **Replace consumer sites** in the same file (grep for `find_declaration(` within `variant_payload.dag`) with direct consumption of the canonical declaration accessor...

Other sections targeting variant_payload.dag (not infer_helpers):

  • Context (line 5) — names the migration: "infer_helpers.dag / infer_helpers_generated.rs no longer carry it... pattern persists on main in src/v3/lenses/variant_payload.dag"
  • Read first (line 31) — primary read: src/v3/lenses/variant_payload.dag
  • Work step 1 (line 39) — "Delete DeclarationLookup enum and find_declaration fn from src/v3/lenses/variant_payload.dag"
  • Work step 4 (line 42) — "Regenerate variant_payload_generated.rs"
  • Acceptance — all checks on variant_payload.dag
  • STOP (line 59) — scope gate cites variant_payload.dag / variant_payload_generated.rs
  • Non-goals (line 63) — explicit "Not touching infer_helpers.dag"
  • Size (line 70) — retargeted 30-80 LOC on variant_payload.dag

Remaining infer_helpers references are intentional (documenting the migration history in Context/Read first) — they orient the worker to the file lineage but never dispatch work there.

The finding would be real if the brief still pointed at infer_helpers. It doesn't. Reviewer sha predates commits 19eeb5c + 9b0bca7. Sanity-check current HEAD against reviewer findings before concluding stale.

@briansrls

Copy link
Copy Markdown
Contributor Author

Verified at current HEAD — stale relay, second time for this same finding. Fix landed at 7b8534c (~30 minutes before this 06:57 relay timestamp).

Line 17 (Read first) at current HEAD:

The primary wire-in blocker: parse / parse_surface convergence (SG-3f follow-up). Per #612: generated helper types against parse_surface::SurfaceExpr; lower.rs uses parse::SurfaceExpr. The available From bridge deep-clones across 16 call sites — that wires in but regresses the lowerer, not improves it. Resolving this is the core SG-3g-b work.

Lines 23-30 (Work / Phase 0) at current HEAD explicitly name verification of the convergence blocker, with grep instructions for impl From<parse_surface::SurfaceExpr> for parse::SurfaceExpr.

The brief does NOT assume lower.rs can call the generated helper directly — it names resolving the type convergence as the core SG-3g-b work and has three option paths (A/B/C) for doing so.

Reviewer sha is pre-fix (same issue as the 06:40:44Z relay, which I responded to at 7b8534c's push time). Genuine stale relay, not dismissal.

Sanity-check line numbers against current HEAD before flagging blockers — relayed sha 32446d5f is ~4 commits behind.

Codex reviewer surfaced real prerequisite gap: `src/v3/std/substrate.dag`
exposes keyed accessors for `port`, `node`, `resolve_producer`,
`lane2_workflow_at` — but NOT for declarations by id. `.dag` lens
consumers literally cannot call `Dag::declaration(id)`; they must
either walk `d.declarations` via fold or use the parallel
`find_declaration` helper.

So the "variant_payload-only cleanup" framing was incorrect — the
parallel authority exists BECAUSE the reflected substrate is
incomplete. Deleting `find_declaration` without a substrate
extension would force consumers to inline the same walk under a
different name.

Rescoped as two-step lane:

**Step 1 — Substrate extension (prerequisite)**:
Add `fn declaration_by_id(d: Dag, id: DeclarationId) -> Declaration?`
to substrate.dag with `host declaration_by_id` realization binding
to Rust's `Dag::declaration`. Preferred return type: `Declaration?`
for symmetry with existing `port` / `node` accessors; C-8
fail-closed enforced at caller.

**Step 2 — variant_payload migration**:
Delete DeclarationLookup + find_declaration; replace consumer
sites with typed `match declaration_by_id(d, id) { Some(decl) =>
... / None => diagnostic }`. None-handling treats as
constructor-layer violation via typed diagnostic, NOT as a
normal lens outcome (which was LookupMissing's sin).

Size: S → S-M. Acceptance split into Step 1 / Step 2 / End-state
sections.

End-state: reflected substrate now has id-keyed lookup parity
with port / node accessors, and the parallel authority is gone.

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

Copy link
Copy Markdown
Contributor Author

Reviewer correct — real finding, not stale. Fixed at HEAD.

Verified the gap:

$ git grep -E "^fn " origin/main -- 'src/v3/std/substrate.dag'
fn port(d: Dag, id: PortId) -> DagPort?
fn node(d: Dag, id: NodeId) -> Behavior?
fn resolve_producer(d: Dag, port_id: PortId) -> Behavior?
fn lane2_workflow_at(d: Dag, id: NodeId) -> WorkflowEffect?

No declaration_by_id or equivalent. So .dag consumers have two options, both parallel-authority:

  1. Walk d.declarations via fold (what structural_resolution.dag does)
  2. Use find_declaration helper (what variant_payload.dag does)

Deleting option 2 without adding a real accessor just pushes consumers to option 1 — same parallel authority, different shape.

Rescope pushed

SG-4b-1-fix is now a two-step lane (size upgraded S → S-M):

Step 1 — Substrate extension (prerequisite):
Add fn declaration_by_id(d: Dag, id: DeclarationId) -> Declaration? to substrate.dag with host declaration_by_id Rust realization. Preferred return type: Declaration? for symmetry with existing port / node accessors. C-8 fail-closed contract enforced at the caller (None-handling emits a typed diagnostic, not absorbed as a normal lens outcome like LookupMissing did).

Step 2 — variant_payload migration:
Delete DeclarationLookup + find_declaration; replace consumer sites with match declaration_by_id(d, id) { Some(decl) => ... / None => diagnostic }.

End-state

  • Reflected substrate has id-keyed declaration lookup parity with port / node accessors
  • Parallel authority gone from variant_payload.dag
  • Single authority: consumers route through the reflected accessor; reflected accessor routes through Dag::declaration

The substrate extension is the actual load-bearing work here; the variant_payload cleanup is the receipt.

Acks on other items from consolidated review

  • SG-2c-2 ratchet file ✓ (reviewer confirmed sg2c1_parse_tables_authority_test.rs is correct)
  • 1e-2b Path A/B ✓
  • SG-3g-b convergence gate ✓
  • ROADMAP Class 5 Gap 1 ✓
  • ROADMAP SG-4b-1 variant_payload citation ✓

Only the SG-4b-1-fix scoping needed this one more pass. Ready for re-review at current HEAD.

@briansrls
briansrls merged commit 2d7a65d into main Apr 21, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant