Skip to content

fix(v3): B2 lower_fn_body Arrow re-derive to fail-closed diagnostic - #817

Merged
briansrls merged 7 commits into
mainfrom
session/smart-newt-747
Apr 26, 2026
Merged

briansrls merged 7 commits into
mainfrom
session/smart-newt-747

Conversation

@briansrls

@briansrls briansrls commented Apr 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements docs/briefs/b2-lower-fn-body-arrow-rederive-worker.md.

  • Replaces the defensive non-Arrow function-body lowering fallback in src/v3/compiler/src/lower.rs with a fail-closed Diagnostic::ResolveError.
  • Stops re-deriving function parameter/output declarations at body-lowering time when the seeded declaration invariant is violated.
  • Adds a structural regression test for a function declaration that reaches lower_fn_item_expr_body with a non-Arrow connective and asserts the diagnostic is emitted.

Seed-Phase Audit

Audit outcome: no seed-phase gap found. This PR is structural-assertion-only.

Verified paths:

  • lower_bodies_phase calls seed_function_signatures_phase(dag, &module.items, symbols, is_first) before the type/data/refinement pre-passes and before the final body-lowering loop.
  • seed_function_signatures_phase iterates the same module.items plus the same is_first filter as body lowering.
  • seed_function_signatures_phase seeds both function-shaped top-level items: SurfaceItem::Fn with ArrowBody::Pending and SurfaceItem::FnExternalBody with ArrowBody::Unparsed(body_span).
  • lower_fn_item_expr_body is only called from the SurfaceItem::Fn arm in lower_item; duplicate Fn items skipped by is_first are also skipped by seeding/body lowering.
  • SurfaceItem::FnExternalBody is seeded but intentionally no-op at body-lowering time, per the existing DB-11 single-construction-authority comment.

Conclusion: every reachable SurfaceItem::Fn body-lowering path should already have an Arrow connective. A non-Arrow connective at this site indicates seed phase was skipped or the declaration was clobbered, so the new diagnostic converts the previous dead hedge into a fail-closed contract.

Diagnostic Taxonomy Note

The diagnostic currently reuses Diagnostic::ResolveError. That is intentional for this PR because CompilerDiagnosticKind in src/v3/std/diagnostics.dag is a closed enum (TokenizerError | ParseError | TypeMismatch | UnitMismatch | ArityMismatch | ResolveError) and has no dedicated lowering-invariant variant. ResolveError is the closest existing shape; adding a new kind should be handled by a future diagnostic-taxonomy lane with the required coproduct/substrate updates.

Verification

  • git diff --check passes.
  • Local cargo/rustc/rustfmt are unavailable on this worker PATH, so I could not run cargo fmt --all --check, cargo test --workspace --exclude v2-compiler-tests, cargo clippy --all-targets -- -D warnings, or DB-8 fixed-point locally. PR CI should cover the Rust verification once the PR is ready for review.

@briansrls

Copy link
Copy Markdown
Contributor Author

Director check-in — direction is right, three open items before flipping ready:

Deliverable A (defensive fallback → diagnostic): ✅ landed. The replacement at `lower.rs:3585-3611` correctly emits a diagnostic on the non-`Arrow` arm and early-returns. Good shape.

Open items per brief acceptance:

  1. Deliverable B — seed-phase audit (brief §Slice + §Acceptance). The brief required: "Seed-phase audit recorded in PR description: every Fn-item path verified to seed before body-lowering, OR root-cause fix landed." The PR body is empty (default dashboard text). Please record the audit outcome:

    • Did you confirm `seed_function_signatures_phase` (`lower.rs:429`) is total over every `Fn` item that reaches `lower_fn_body_into_existing_decl`? If yes, this PR is structural-assertion-only (the diagnostic converts dead hedge → fail-closed contract).
    • If a gap was found, the brief required the fix at the seed phase, not at the body-lowering site. Did you find one?
  2. Regression test (brief §Slice step 4 / §Acceptance). Brief asked for a test that constructs a function declaration with a non-`Arrow` connective at this site and asserts the diagnostic is emitted. I don't see one in the diff yet. If your audit (item 1) shows the path is unreachable in well-formed programs, the test still has value as a structural assertion against future regressions — the brief explicitly framed it as "structural assertion that converts the unreachable hedge into a fail-closed contract."

  3. `Diagnostic::ResolveError` reuse — acceptable interim, but flag it. `CompilerDiagnosticKind` (`src/v3/std/diagnostics.dag:13-18`) is a closed enum: `TokenizerError | ParseError | TypeMismatch | UnitMismatch | ArityMismatch | ResolveError`. None is a perfect fit for "lowering invariant violation"; `ResolveError` is the closest. This is a mild `feedback_naming_is_aliasing` smell but adding a new variant would require coproduct dissolution receipt — out of scope here. Just note it in the PR body so a future diagnostic-taxonomy lane picks it up.

On scope: the brief's STOP-AND-ESCALATE list flagged "audit reveals a legitimate runtime path that produces non-`Arrow` connectives" as a stop condition — your audit (item 1) is what answers that. Don't skip it.

Flip to ready once the body documents items 1 + 2 + 3.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: e151b511 · Trigger: schedule
  • Thinking: 166s wall

Non-blocking — Strengths

  • src/v3/compiler/src/lower.rs The fallback removal is consistent with FAIL-CLOSED and single authority: a non-Arrow seeded function declaration now emits a diagnostic instead of re-deriving signature facts.

✅ No blocking concerns; this is a clean fail-closed tightening of the lowering invariant.

@briansrls briansrls changed the title B2 fix(v3): B2 lower_fn_body Arrow re-derive to fail-closed diagnostic Apr 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the Director check-in items:

  • PR body now records the seed-phase audit outcome: no seed gap found; this is structural-assertion-only.
  • Added regression coverage in src/v3/compiler/src/lower.rs: fn_body_lowering_reports_non_arrow_seed_invariant_violation constructs a non-Arrow function declaration at body-lowering time and asserts the fail-closed diagnostic.
  • PR body now notes the intentional interim reuse of Diagnostic::ResolveError because the diagnostic kind enum is currently closed and has no lowering-invariant variant.

Verification note: git diff --check passes locally. This worker has no cargo/rustc/rustfmt on PATH, so Rust test/fmt/clippy/DB-8 verification needs CI or a Rust-equipped worker.

I attempted to mark the PR ready through the GitHub connector, but the connector mutation failed on an internal GraphQL field selection (htmlUrl on PullRequest). The PR remains draft until that is flipped by dashboard/CLI.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: a53cb4d8 · Trigger: schedule
  • Thinking: 146s wall

✅ No blocking concerns; the code change is focused and does not introduce new substrate shapes, duplicate authority, or untracked debt.

@briansrls
briansrls marked this pull request as ready for review April 25, 2026 22:04
@briansrls

Copy link
Copy Markdown
Contributor Author

Flipping ready. Apologies for the delay — worker addressed all three Director feedback items in the PR body (seed-phase audit ✅, regression test ✅, ResolveError taxonomy note ✅) but I was checking the diff rather than the rendered description. The PR is complete-and-well-documented; the worker explicitly asked for CI to cover Rust verification post-ready-flip. Sending now.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

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

Verdict: APPROVE — Converts a silent re-derive fallback into a fail-closed diagnostic at lower.rs:3595-3613, which is exactly the modeling-discipline move (single construction authority for the seeded Arrow; don't paper over invariant violations by reconstructing parallel state). Test at lower.rs:6715-6764 exercises the path by skipping the seed phase and asserts the diagnostic shape. No findings.

Exploratory observation (non-blocking): dag.declaration(fn_decl_id).connective.clone() clones the whole connective unconditionally; a match &...connective { Arrow { inputs, output, .. } => (inputs.clone(), *output), observed => { let observed = observed.clone(); ... } } would avoid the clone on the hot path. Pure micro-optimization — ignore unless it shows up in a profile.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: a53cb4d8 · Trigger: schedule
  • Thinking: 144s wall

Verdict: APPROVE

The diff removes a fabricated re-derive fallback and replaces it with a typed diagnostic path, which aligns with Fail-Closed and Single Authority. The added regression test is focused on that behavior.

Verified with cargo test -p v3-compiler fn_body_lowering_reports_non_arrow_seed_invariant_violation.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: a53cb4d8 · Trigger: manual
  • Conversation: View conversation

1. Story of the diff

This PR removes the defensive re-derivation path in lower_fn_item_expr_body for the case where a function declaration is not backed by the Arrow connective seeded earlier in lowering. The old path rebuilt parameter and return declaration IDs from the surface syntax, which let body lowering continue with a second derived authority; the new path reads the seeded Arrow directly when present at src/v3/compiler/src/lower.rs:3595-3596, and otherwise emits a Diagnostic::ResolveError naming the violated lowering invariant and the observed connective at src/v3/compiler/src/lower.rs:3601-3612, then returns without lowering the body at src/v3/compiler/src/lower.rs:3613. The added regression test intentionally skips seed_function_signatures_phase, invokes lower_fn_item_expr_body, and verifies that the non-Arrow state is reported as a diagnostic rather than repaired locally at src/v3/compiler/src/lower.rs:6716-6763.

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Compliant — this touches a substrate consumer, not substrate shape: TypeConnective::Arrow remains the single seeded authority at src/v3/compiler/src/lower.rs:3595-3596, and the non-Arrow case is rejected rather than modeled by a second implementation-only derivation at src/v3/compiler/src/lower.rs:3601-3613.

  1. INVARIANTS.md + modeling-discipline.md.

Compliant — P3 / fail-closed is handled directly: the changed branch reports Diagnostic::ResolveError at src/v3/compiler/src/lower.rs:3603-3611 and returns at src/v3/compiler/src/lower.rs:3613, instead of fabricating plausible parameter and return declarations. This also preserves single authority / facts-flow-forward by consuming the seeded Arrow rather than reconstructing it downstream. chatgpt-review-57932e9f-7002-41…

chatgpt-review-af662107-55e7-49…

  1. CODING.md.

Compliant — the change stays in the existing free-function lowering flow, uses explicit inputs already in scope, and routes failure through the existing diagnostic carrier rather than adding hidden state, methods, or a side-channel; the relevant path is report_declaration_error(...) at src/v3/compiler/src/lower.rs:3601-3612. chatgpt-review-1971ed92-2bbd-47…

  1. TESTING.md.

Compliant — the PR adds a focused regression test for the exact behavior change: fn_body_lowering_reports_non_arrow_seed_invariant_violation at src/v3/compiler/src/lower.rs:6716 constructs a minimal function item, deliberately calls body lowering without signature seeding at src/v3/compiler/src/lower.rs:6740-6750, and asserts the diagnostic contract at src/v3/compiler/src/lower.rs:6752-6763. chatgpt-review-a9443636-e5cd-44…

  1. LOCKED DESIGN DECISIONS.

N/A — the diff does not alter thesis/design documents, substrate schema, target realization rules, or any explicitly locked design surface.

  1. TRACKED vs UNTRACKED DEBT.

N/A — the diff introduces no new TODOs, scaffolds, compatibility bridges, or temporary representations; it deletes a local fallback and replaces it with fail-closed behavior.

3. Verdict

APPROVE. The PR is narrowly aligned with the stated fix: it removes a downstream re-derivation fallback, preserves the seeded Arrow as the single authority, and adds a regression test for the fail-closed diagnostic path.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

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

Verdict: APPROVE — Diff converts a silent re-derive fallback into a fail-closed Diagnostic::ResolveError (lower.rs:3614–3634), which is exactly what the fail-closed invariant calls for: when seed_function_signatures_phase violates its postcondition, surface it instead of papering over it. The return outer_scope early exit matches the other error paths in the same function (3719–3721). The new unit test (lower.rs:6783+) is hermetic — it deliberately skips the seed phase to construct the violating state, then asserts the diagnostic shape. Clean, narrowly scoped, no concerns.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: 3a635986 · Trigger: schedule
  • Thinking: 145s wall

Verdict: APPROVE

Diff is small and aligned with P3 fail-closed and P2 single-authority: the fallback Arrow re-derivation is removed, non-Arrow seeded declarations now emit a typed ResolveError, and body lowering exits before fabricating substitute facts. Regression test covers the invariant path.

Verified with cargo test -p v3-compiler fn_body_lowering_reports_non_arrow_seed_invariant_violation.

@briansrls

Copy link
Copy Markdown
Contributor Author

PM review — APPROVE_WITH_COMMENTS

Implementation is sound: defensive fallback at lower.rs:3585-3611 removed; replaced with report_declaration_error() emitting Diagnostic::ResolveError per C-8; regression test added (:6783-6832) that triggers the non-Arrow case and asserts diagnostic emission. The fail-closed direction is correct.

One ask before merging — the brief's Acceptance bullet 2 explicitly requires: "Seed-phase audit recorded in PR description: every Fn-item path verified to seed before body-lowering, OR root-cause fix landed." The audit is implicit in the deletion (you removed the fallback, which presumes you verified it was unreachable from well-formed input), but reviewers can't verify the root-cause claim without the narrative.

Add one paragraph to the PR description stating which case applies:

  • (a) Audit found no gap — every Fn-item path verified to seed before body-lowering; the deleted fallback was dead code masking nothing real, and the new diagnostic is a structural assertion against future regression. Cite the audited paths (which Fn-item enumeration sites you traced).
  • (b) Audit found a gap — name the path that was missing seeding, point at the seed-phase fix you landed, and explain why the diagnostic still belongs at the body-lowering site as a structural assertion.

Otherwise this is a clean approve. The audit narrative is the discipline feedback_construction_over_ratchets calls for at brief-acceptance time.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 3a635986 · Trigger: schedule
  • Thinking: 172s wall

Non-blocking — Strengths

  • src/v3/compiler/src/lower.rs The non-Arrow function-declaration path now fails closed through a Dag diagnostic instead of fabricating a second signature, matching fail-closed and single-authority discipline.

✅ No blocking concerns; this is a focused implementation-only lowering fix with no new substrate shape, silent fact drop, or untracked scaffold.

Copy link
Copy Markdown
Contributor Author

Verified against the current PR description. This ask is already addressed in the ## Seed-Phase Audit section.

Current body records case (a) Audit found no gap and cites the audited paths:

  • lower_bodies_phase calls seed_function_signatures_phase(...) before body lowering.
  • seed_function_signatures_phase iterates the same module.items and is_first filter as body lowering.
  • It seeds SurfaceItem::Fn as ArrowBody::Pending and SurfaceItem::FnExternalBody as ArrowBody::Unparsed(body_span).
  • lower_fn_item_expr_body is only called from the SurfaceItem::Fn arm in lower_item.
  • SurfaceItem::FnExternalBody remains seeded but body-lowering no-op by design.

No code or PR-body change needed for this relayed comment.

@briansrls

Copy link
Copy Markdown
Contributor Author

Already in the PR body — see "## Seed-Phase Audit" section (case (a): no gap found, structural-assertion-only). The audit traces the relevant paths:

  • lower_bodies_phase calls seed_function_signatures_phase before body-lowering
  • The phase iterates the same module.items + is_first filter as body lowering
  • Seeds both SurfaceItem::Fn (ArrowBody::Pending) and SurfaceItem::FnExternalBody (ArrowBody::Unparsed)
  • lower_fn_item_expr_body only called from the SurfaceItem::Fn arm in lower_item
  • Duplicate Fn items skipped by is_first are also skipped by seeding/body lowering

Conclusion in body: "every reachable SurfaceItem::Fn body-lowering path should already have an Arrow connective" — converts dead hedge → fail-closed contract. Diagnostic-taxonomy note also recorded (ResolveError reuse intentional pending future taxonomy lane). Closing as fixed.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: a93c299a · Trigger: schedule
  • Thinking: 199s wall

Verdict: APPROVE

This looks clean. The diff removes the Arrow re-derive fallback and replaces it with a fail-closed diagnostic, preserving the seeded signature as the single authority. The added regression test covers that path and passes with cargo test -p v3-compiler fn_body_lowering_reports_non_arrow_seed_invariant_violation.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 932d41aa · Trigger: schedule
  • Thinking: 14s wall

Verdict: APPROVE — replaces a silent defensive re-derive with a fail-closed diagnostic, exactly the direction INVARIANTS pushes. The new test is hermetic, sets up the violation by skipping seed_function_signatures_phase, and pins the diagnostic shape. Diff is small, narrowly scoped, no concerns.

Minor exploratory note (not a finding): the Diagnostic::ResolveError variant is being used as a generic invariant-violation channel here. If/when an InternalInvariantViolation (or similar) variant exists, this is a natural place to switch to it — but reusing ResolveError is reasonable as a tracked bridge.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: 932d41aa · Trigger: schedule
  • Thinking: 149s wall

Verdict: APPROVE

This looks clean. The diff removes a fabricated Arrow re-derive fallback and replaces it with a fail-closed diagnostic at the invariant breach, which aligns with P3 and the single-authority lowering comment already in place.

Verified with cargo test -p v3-compiler fn_body_lowering_reports_non_arrow_seed_invariant_violation.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: a93c299a · Trigger: manual
  • Conversation: View conversation

1. Story of the diff

This PR removes a defensive fallback in lower_fn_item_expr_body that used to re-derive function parameter and return declarations when the function declaration was not seeded as a TypeConnective::Arrow. That fallback kept lowering moving by reconstructing plausible inputs/outputs from surface syntax, which meant the original invariant break could be masked. The new path treats the seeded Arrow as the single authority: it consumes the existing Arrow when present, and otherwise reports a Diagnostic::ResolveError naming the violated lowering invariant and returns early from body lowering (src/v3/compiler/src/lower.rs:3828-3846). The added regression test directly exercises the invalid call shape by collecting symbols without seeding function signatures, then verifies that body lowering emits a diagnostic instead of re-deriving the missing Arrow (src/v3/compiler/src/lower.rs:6995-7044).

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Compliant — this is implementation-only lowering code, not a substrate type change. The key decision is to read the seeded TypeConnective::Arrow as the authority (src/v3/compiler/src/lower.rs:3828-3829) and stop when the declaration is not an Arrow (src/v3/compiler/src/lower.rs:3830-3846), rather than introducing a second substrate-level representation.

  1. INVARIANTS.md + modeling-discipline.md.

Compliant — fail-closed / single-authority is handled correctly: the old re-derivation path is removed, and the non-Arrow state now emits a diagnostic and returns (src/v3/compiler/src/lower.rs:3834-3846) instead of fabricating plausible parameter and return declarations from the surface AST.

  1. CODING.md.

Compliant — the change keeps the logic inside the existing lowering free-function flow, uses explicit inputs already available to lower_fn_item_expr_body, avoids panic/unwrap behavior, and makes the abnormal path visible through the existing diagnostic mechanism (src/v3/compiler/src/lower.rs:3834-3846).

  1. TESTING.md.

Finding (NON-BLOCKING) — src/v3/compiler/src/lower.rs:7037-7039 identifies the new diagnostic by probing free-form text:

if name.contains("function declaration \bad_seed") && name.contains("seed_function_signatures_phase did not produce an Arrow connective") && name.contains("observed connective")

This pins the test to diagnostic wording rather than a structured diagnostic carrier. The production side creates the same pressure by encoding the lowering-invariant failure inside Diagnostic::ResolveError { name: format!(...) } at src/v3/compiler/src/lower.rs:3836-3840. The regression is valuable and at the right unit level, but if this failure mode is meant to be mechanically distinguished long-term, a dedicated diagnostic variant or structured field would better match the typed-carrier testing discipline.

  1. LOCKED DESIGN DECISIONS.

N/A — the diff does not reference or alter a locked thesis/design decision; it changes only a defensive branch in Rust lowering and its regression test.

  1. TRACKED vs UNTRACKED DEBT.

N/A — the diff does not add TODOs, scaffolds, temporary bridges, or new staged representations. It removes a fallback bridge by deleting the Arrow re-derivation path.

3. Verdict

APPROVE_WITH_COMMENTS

The substantive behavior moves in the right direction: seeded function Arrow declarations remain the single authority, and violation of that invariant now fails closed with a diagnostic. The only comment is test/diagnostic shape: the new regression currently has to rely on diagnostic string contents, which is acceptable as a non-blocking comment here but should not become the steady-state carrier for this distinct lowering-invariant failure.

Copy link
Copy Markdown
Contributor Author

Verified the non-blocking diagnostic-shape comment against the current PR body and code. No code change needed in this PR: the concern is already tracked in the Diagnostic Taxonomy Note.

Current state:

  • Production uses Diagnostic::ResolveError because CompilerDiagnosticKind is currently a closed enum with no lowering-invariant/internal-invariant variant.
  • The PR body explicitly records that this is an intentional interim reuse and that adding a dedicated diagnostic kind belongs in a future diagnostic-taxonomy lane with the required coproduct/substrate updates.
  • The regression necessarily checks the current diagnostic payload shape until that typed carrier exists.

So I’m treating the review note as valid but already addressed/documented, with no further change for B2.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 932d41aa · Trigger: schedule
  • Thinking: 147s wall

✅ No blocking concerns; the diff replaces the only changed fallback with a diagnostic-only fail-closed path and adds focused coverage for the non-Arrow seeded-function invariant.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: 932d41aa · Trigger: manual
  • Conversation: View conversation

Loop summary

N = 13 review events across roughly 7 time clusters, from 2026-04-25 20:25:50Z to 2026-04-26 00:29:50Z — about 4 hours 4 minutes elapsed. K = 8 codex reviews. L = 2 browser/openai-pro reviews. There are also 3 Claude/API reviews. M commits is not recoverable from the attached review dump because no commit SHAs are included; from the current attached diff, the visible patch state is a single-file lower.rs change plus one regression test. chatgpt-review-b9813acc-5526-46…

chatgpt-review-b9813acc-5526-46…

chatgpt-review-b9813acc-5526-46…

Forward progress evidence

This loop made real forward progress on the original debt. The PR deletes a downstream Arrow re-derive fallback in lower_fn_item_expr_body and replaces it with a fail-closed diagnostic path: reviewers consistently describe the old behavior as reconstructing plausible parameter/return declaration facts from surface syntax, and the new behavior as consuming the seeded TypeConnective::Arrow as the single authority or stopping with a diagnostic. That is exactly P2/P3 movement: one authority, no fabricated plausible output. chatgpt-review-b9813acc-5526-46…

chatgpt-review-b9813acc-5526-46…

It also adds a real consumer: fn_body_lowering_reports_non_arrow_seed_invariant_violation. The test deliberately skips seed_function_signatures_phase, calls body lowering, and asserts that the non-Arrow state is reported instead of repaired locally. That is enough consumer coverage for this specific implementation-only lowering invariant; this PR does not need a new emit target or interpreter path because it is not introducing a new substrate surface. chatgpt-review-b9813acc-5526-46…

The loop also dissolved a scaffold-like fallback rather than adding one. Multiple reviews explicitly say the change introduces no new substrate shape, duplicate authority, or untracked scaffold, and deletes the local fallback bridge. chatgpt-review-b9813acc-5526-46…

No new invariant needed to be added to INVARIANTS.md for the original issue: the rule already exists. P3 says every path either succeeds or fails with a typed diagnostic, with no fabricated plausible output; P2 says facts live in exactly one authoritative place. chatgpt-review-b8f05eb3-6951-45…

chatgpt-review-b8f05eb3-6951-45…

Debt accumulation evidence

There is one small debt item: the new test identifies the diagnostic by probing free-form text with contains(...), and the production path encodes the invariant failure inside Diagnostic::ResolveError { name: format!(...) } rather than a dedicated structured diagnostic variant or field. The late openai-pro review correctly calls this non-blocking: the regression is valuable, but the carrier is not the ideal steady state for mechanically distinguishing this lowering-invariant failure. chatgpt-review-b9813acc-5526-46…

That debt maps to existing discipline, not a new category. INVARIANTS.md already warns against string-sentinel probing and names DB-1 as “typed diagnostic carriers, not ad hoc warning text.” chatgpt-review-b8f05eb3-6951-45…

The attached testing guidance also says tests should not pin diagnostic message text; they should match structured diagnostic shape where available. chatgpt-review-80c39707-5659-43…

The other repeated observation — the unconditional connective.clone() — is a micro-optimization note, not loop debt. It does not change authority, substrate shape, or consumer behavior. chatgpt-review-b9813acc-5526-46…

Cheating signal

Mostly clean. The implementer is not hiding the main compromise: the main fix is structural for the original problem. It removes the fabricated fallback and makes the seed-phase Arrow the authority.

There is, however, a small “good enough for now” signal around diagnostics: using ResolveError plus formatted text is cheaper than introducing a dedicated LoweringInvariantViolation/InternalInvariantViolation carrier. Reviewers noticed it, but the code itself does not mark it as // SCAFFOLD or attach a dissolution trigger. That is acceptable only because the blast radius is tiny and the follow-up cost is about the same later as now.

The most recent reviews are not discovering new implementation problems; they are mostly repeating “approve, no blocking concerns,” with one non-blocking diagnostic-shape comment. Continuing this review loop is now producing diminishing returns. chatgpt-review-b9813acc-5526-46…

chatgpt-review-b9813acc-5526-46…

Path to convergence

Do not keep iterating on this PR just to perfect the diagnostic carrier.

The smallest action that would justify KEEP_ITERATING would be: add a structured diagnostic variant or structured field for lowering invariant violations, then update the test to match that carrier instead of probing message text. That would fully pay the residual DB-1/C-5 debt.

But that is not necessary for this PR to converge. The acceptable debt to carry is narrow: Diagnostic::ResolveError is temporarily serving as the invariant-violation carrier, and the regression test probes diagnostic text because no better structured carrier exists yet. Track it in a follow-up artifact, preferably one review-finding/debt row named something like:

lowering-invariant diagnostics should use a structured carrier, not ResolveError.name text

The follow-up should dissolve by either adding Diagnostic::InternalInvariantViolation { phase, invariant, observed, span } or adding equivalent structured fields to the existing diagnostic model, then replacing this test’s contains(...) checks with a typed match.

Meta-verdict

⚖️ SHIP_WITH_DEBT — diminishing returns, accept tracked debt, merge and address in follow-up PRs

@briansrls
briansrls merged commit 60be4f0 into main Apr 26, 2026
4 checks passed
briansrls added a commit that referenced this pull request Apr 29, 2026
…er brief

Clarify program-scope row, standing deliverable #7, and Working state:
GitHub merge metadata for #820/#817/#821; distinguish brief reconciliation
date from Tier 0 landings; keep B5 Tier-2 closure on 2026-04-27 per synthesis.

Made-with: Cursor
briansrls added a commit that referenced this pull request Apr 29, 2026
…1208)

* WIP: loyal-ram-816

* docs(r2): reconcile B-wave Tier 0+2 status in Release Manager brief

Mark Tier 0 PRs #820/#817/#821 and Tier 2 B5/B6/B7 as landed at HEAD with synthesis and code pointers. Close the B5 worker brief with a CLOSED banner, checked acceptance boxes, and a closure receipt stanza. Refresh autonomous dispatch wording for closed B-wave scope.

Made-with: Cursor

* docs(r2): pin Tier 0 merge dates to 2026-04-26 (UTC) in Release Manager brief

Clarify program-scope row, standing deliverable #7, and Working state:
GitHub merge metadata for #820/#817/#821; distinguish brief reconciliation
date from Tier 0 landings; keep B5 Tier-2 closure on 2026-04-27 per synthesis.

Made-with: Cursor
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