Skip to content

feat(v3): add SymbolicCost semiring inhabitance - #1555

Merged
briansrls merged 5 commits into
mainfrom
feat/symbolic-cost-semiring-inhabitance
May 3, 2026
Merged

briansrls merged 5 commits into
mainfrom
feat/symbolic-cost-semiring-inhabitance

Conversation

@briansrls

@briansrls briansrls commented May 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • add the supported substrate inhabitance edge SymbolicCost inhabits Semiring<SymbolicCost> per INVARIANTS §P1 and the existing SymbolicCost law-witness debt routing
  • keep this substrate-only: no Verification law row retirement and no downstream law witness authored in this slice
  • fix the semiring product-zero prerequisite by separating additive-zero dropping from multiplicative-zero annihilation in the SymbolicCost normalization path
  • add focused ratchets for the inhabitance edge and product-zero behavior, with regenerated bootstrap snapshots

Notes

  • I did not add a structural data symbolic_cost_semiring: Semiring<SymbolicCost> = { ... } value. Current lowering rejects function-valued structural data fields such as add: sequential; the supported honest carrier for this S-sized unblocker is the declaration-level inhabits edge.

Checks

  • cargo test -p v3-compiler symbolic_cost --test integration -- --nocapture
  • cargo fmt --all --check
  • cargo run -p v3-compiler --features bootstrap-regen-fresh --bin regen_bootstrap -- --verify

@briansrls briansrls changed the title silent-deer-861 feat(v3): add SymbolicCost semiring inhabitance May 3, 2026
@briansrls
briansrls marked this pull request as ready for review May 3, 2026 01:43

@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: 57610d62 · Trigger: schedule
  • Thinking: 295s wall

BLOCKING (1)

Root Cause

  • src/v3/std/algebra.dag The PR adds the inhabitance edge after fixing zero annihilation but does not yet expose the Semiring one/law witness surface → either defer the inhabitance edge or add the structural identity/equivalence witness that makes mul(one, x) == x true for SymbolicCost.

Non-blocking — Strengths

  • src/v3/std/algebra.dag The additive-zero versus multiplicative-zero split is the right direction and fixes the previous zero-as-product-identity bug.

⚠️ One substrate-level algebra inhabitance claim lands before the modeled laws make it true.

Comment thread src/v3/std/algebra.dag
// evidence. The `Semiring<SymbolicCost>` inhabitance edge is the
// substrate prerequisite for downstream Verification law witnesses
// (INVARIANTS §P1); it does not retire those law rows in this slice.
type SymbolicCost inhabits Semiring<SymbolicCost>

This comment was marked as resolved.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: 57610d62 · Trigger: schedule
  • Comparison: origin/main @ 3c77a60c ... review/pr-1555-57610d62 @ 57610d62
  • Thinking: 52s wall

Findings

None. The substantive edits are in src/v3/std/algebra.dag (declare SymbolicCost inhabits Semiring<SymbolicCost>, import Semiring, split additive vs multiplicative zero in normalize), src/v3/compiler/src/dag_cost_generated.rs (same semantics in the generated mirror), and src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs (bootstrap inhabitance check + iterate(linear, constant(0)) → constant(0)). Nothing there contradicts fail-closed modeling, single-authority substrate facts, or the coding/testing guides for new work. The large bootstrap_generated*.rs churn is mechanical regen from the std algebra change, not a separate design.

Verdict

APPROVE — The diff correctly attaches SymbolicCost to Semiring<SymbolicCost> (P1 / algebra-inhabitance), fixes semiring honesty by treating ConstantCost(0) as an annihilator under product while keeping additive zero removal for sums, keeps the Rust cost mirror in sync, and adds targeted bootstrap and composition tests. No concerns.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review pass on #1555: the hand-authored substrate shape matches the dispatch. SymbolicCost inhabits Semiring<SymbolicCost> lands as an inhabitance edge, the normalization split treats additive zero and multiplicative zero differently, and the focused ratchets cover both the bootstrap inhabitance fact and product-zero annihilation. The generated dag_cost_generated.rs mirror is aligned with the .dag authority, and the bootstrap snapshots appear regenerated.

No code blocker found in the changed hunks. Before final ready/merge, please make sure the PR wrapper is cleaned up from the dashboard placeholder title/body and includes the explicit validation + the note that no structural symbolic_cost_semiring data value was authored because function-valued structural data fields are currently rejected. Keep the scope as you described: substrate inhabitance + normalization fix only, no Verification law-row retirement in this PR.

My local focused test attempt did not complete because the fresh temp target failed before test execution with a toolchain/sccache process error while compiling num-traits; I did not get a PR-code failure. I’m relying on your reported local checks plus the static diff review here.

— sent from jolly-ram-908 (inbox #1130); reply at #1130

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: bb55f04a · Trigger: schedule
  • Comparison: origin/main @ 3c77a60c ... review/pr-1555-bb55f04a @ bb55f04a
  • Thinking: 56s wall

Findings: none worth blocking on.

Brief notes:

  • src/v3/std/algebra.dag:168 — adds inhabits Semiring<SymbolicCost> and the normalize rewrite now correctly honors semiring laws: additive 0 drops only under Sum, multiplicative 0 annihilates Products, multiplicative 1 is dropped, and empty product reduces to ConstantCost(1) (was 0). This is the right fix; the previous drop_zero shared between Sum and Product was a substrate-level law violation.
  • src/v3/compiler/src/dag_cost_generated.rs:104-167 — Rust mirror matches the DAG semantics. Empty-product → ConstantCost{_0:1} is consistent with the source.
  • tests/integration/lane2_stage_2d_symbolic_cost_test.rs:286 — the loop_body_countdown regression assertion was relaxed from "ProductCost carries non-zero body" to "result is bare LinearCost". The original assertion was a guard against PR ζ #537's "body silently dropped" regression; under the new semiring laws, Linear * 1 legitimately normalizes to Linear, so the symptom the old test pinned (bare LinearCost) is now also the correct output. This is a real loss of regression coverage for "body fact lost" — a future bug where the body gets dropped before normalization would no longer be caught here. Worth a follow-up test that uses a body with non-identity cost (e.g. an O(n) body so the product survives normalization). Non-blocking, but the comment claiming "the loop must remain linear" as a regression guard is weaker than the original guard.
  • New product_with_constant_zero_collapses_to_zero and product_with_constant_one_normalizes_to_other_factor tests directly exercise the semiring laws — good behavioral coverage.
  • Inhabitance test at :192 checks the Instantiation { template, arguments } shape end-to-end through bootstrap. Good.

The thesis text in the type comment ("does not retire those law rows in this slice") correctly flags this as a tracked, bounded scaffold for downstream Verification work — meets the tracked-debt bar.

Verdict: APPROVE_WITH_COMMENTS — substrate change is correct and well-modeled; only soft concern is that the countdown loop test lost its "body fact survives" teeth and is worth restoring with a non-identity body.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: 6efe0e6a · Trigger: manual
  • Comparison: main @ 3c77a60c ... feat/symbolic-cost-semiring-inhabitance @ f8053e26
  • Conversation: View conversation

1. Story of the diff

This PR promotes SymbolicCost from a standalone asymptotic-cost coproduct into a declared Semiring<SymbolicCost> inhabitant by importing Semiring and adding the inhabitance edge on the type itself at src/v3/std/algebra.dag:76 and src/v3/std/algebra.dag:171. To make that claim behaviorally honest, it changes normalization so additive zero is only dropped from sums, multiplicative zero annihilates products, multiplicative one is removed from products, and an empty product reduces to ConstantCost(1) at src/v3/std/algebra.dag:411-413 and src/v3/std/algebra.dag:520. The hand/generated Rust cost mirror is updated consistently in src/v3/compiler/src/dag_cost_generated.rs:105-110 and src/v3/compiler/src/dag_cost_generated.rs:166, and the tests add both a bootstrap inhabitance assertion plus product zero/one law coverage at src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs:192-220 and src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs:414-448.

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Finding (BLOCKING) — substrate generated fixture is not carrying the source substrate fact forward. The source substrate now says product normalization is reduce_product(drop_multiplicative_one(collapse_on_multiplicative_zero(nsl_to_list(terms)))) at src/v3/std/algebra.dag:412-413, but the bootstrapped DAG product path goes from collapse_on_multiplicative_zero directly to reduce_product: src/v3/compiler/src/bootstrap_generated.rs:1405 targets DeclarationId(781), which is declared as collapse_on_multiplicative_zero at src/v3/compiler/src/bootstrap_generated.rs:20258, and src/v3/compiler/src/bootstrap_generated.rs:1412 then targets DeclarationId(786), declared as reduce_product at src/v3/compiler/src/bootstrap_generated.rs:20347-20348. The same skip is present in src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs:1405 and src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs:1412. Because these generated fixtures are the bootstrapped substrate view, this makes the .dag authority and the bootstrapped Dag::new() authority disagree for ProductCost([ConstantCost(1), x]).

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

Finding (BLOCKING) — violates facts-flow-forward / single-authority metadata. The .dag source introduces the drop_multiplicative_one helper at src/v3/std/algebra.dag:449-456 and its predicate at src/v3/std/algebra.dag:470-479, while the Rust cost mirror consumes that helper at src/v3/compiler/src/dag_cost_generated.rs:108-110; the bootstrapped substrate fixture does not. This creates two independently observable semantics for the same declared SymbolicCost normalization: generated Rust obeys the semiring identity law, but the bootstrapped substrate graph skips the identity-removal stage.

  1. CODING.md.

Compliant. The non-bootstrap Rust change keeps the implementation in small pure free helpers rather than adding object state or methods: drop_additive_zero_terms, collapse_on_multiplicative_zero, and drop_multiplicative_one are all standalone transformations in src/v3/compiler/src/dag_cost_generated.rs:128-151.

  1. TESTING.md.

Finding (BLOCKING, as a substrate regression test gap). The new product-law tests exercise iterate(...) through the Rust cost helper at src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs:414-448, but they do not assert that the bootstrapped substrate graph for normalize(ProductCost(_)) includes the same drop_multiplicative_one stage. The existing bootstrap test only checks the inhabitance edge at src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs:193-220, so this stale generated-fixture mismatch can pass even though the substrate consumer view is wrong.

  1. LOCKED DESIGN DECISIONS.

N/A — no locked thesis/design decision is altered. The only design-scope note explicitly bounds the new edge as a prerequisite and says it does not retire downstream law rows at src/v3/std/algebra.dag:168-170.

  1. TRACKED vs UNTRACKED DEBT.

N/A — no new TODO, scaffold, temporary bridge, or deprecation shape is introduced in the diff. The “does not retire those law rows” note is scope-setting for this slice, not a new temporary representation.

3. Verdict

REQUEST_CHANGES

The source .dag and generated Rust semiring normalization are coherent, but the bootstrapped substrate fixtures are stale and omit the new multiplicative-one normalization step. Because this is substrate-visible and creates parallel semantics for SymbolicCost, I would fix/regenerate the bootstrapped fixtures and add a substrate-level regression before merging.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: f8053e26 · Trigger: schedule
  • Comparison: origin/main @ d2e72d26 ... review/pr-1555-f8053e26 @ f8053e26
  • Thinking: 96s wall

Verdict

APPROVE — The diff lines up with the rubric: SymbolicCost is wired as an inhabitant of Semiring<SymbolicCost> via the DAG-ancestor pattern (INVARIANTS P1 substrate-fact procedure), normalization is updated so product behaves like a semiring (0 annihilates, 1 is identity, empty product is 1), and the Python template plus dag_cost_generated.rs stay aligned with the .dag authority. I do not see a concrete breach of INVARIANTS, docs/modeling-discipline.md, CODING.md, or TESTING.md that is tied to a specific changed line.

Findings: None.

Exploratory (optional): The countdown integration test no longer asserts a ProductCost shape; it only checks a normalized LinearCost, while the new budgeted_test! blocks exercise annihilator and unit laws on composed costs. That is consistent with TESTING’s “pin behavior, not layout” stance, but if you still want a pipeline-level guard that the loop body’s cost is included before normalization (not only the normalized shape), that would be a separate, additive test—not required by the docs for this diff.

@briansrls
briansrls force-pushed the feat/symbolic-cost-semiring-inhabitance branch from f8053e2 to b9e22b5 Compare May 3, 2026 02:29
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: 1816d111 · Trigger: schedule
  • Comparison: origin/main @ d2e72d26 ... review/pr-1555-1816d111 @ 1816d111
  • Thinking: 37s wall

Findings

  • NON-BLOCKING (TESTING.md — regression / behavior pinning): In recursive_fn_body_contributes_to_loop_cost, the guard was narrowed from requiring a normalized ProductCost that still exposed both a linear term and a non-zero body term to only matches!(cost, SymbolicCost::LinearCost { .. }) at 351:354:src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs. That matches semiring normalization (Linear * 1 → Linear) but may no longer catch a fault where the body contribution is missing from the iterate composition yet the reported cost stays linear from the loop source alone — the scenario the surrounding PR ζ #537 commentary is worried about. If that omission mode is still plausible, consider an extra assertion that still witnesses body wiring (without fighting multiplicative identity), or a dedicated minimal-Dag test at the iterate/normalization boundary.

Verdict

APPROVE_WITH_COMMENTS — Substrate change is coherent: SymbolicCost inhabits Semiring<SymbolicCost> in algebra.dag, normalization distinguishes additive vs multiplicative zeros/ones, and reduce_product on an empty list correctly uses ConstantCost(1) (multiplicative identity). Generated mirrors stay aligned with the single .dag authority. No invariant/doc violations beyond the narrow regression-test tradeoff above.

Exploratory observations (optional)

  • symbolic_cost_product_identity_stage_is_bootstrap_substrate_fact (bootstrap Transform chain search) encodes the normalize pipeline shape into the fixture graph; semantically right for “substrate-visible staging,” but it will churn if normalize is refactored while preserving laws. Acceptable if treated as an intentional structural ratchet.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: 1816d111 · Trigger: manual
  • Comparison: main @ d2e72d26 ... feat/symbolic-cost-semiring-inhabitance @ 1816d111
  • Conversation: View conversation

1. Story of the diff

This PR makes SymbolicCost a declared inhabitant of the existing Semiring<SymbolicCost> structure rather than leaving cost algebra as an implicit convention: src/v3/std/algebra.dag:171 changes the type declaration to type SymbolicCost inhabits Semiring<SymbolicCost>. To make that declaration honest, normalization now separates additive and multiplicative identities: sums drop ConstantCost(0), products collapse on ConstantCost(0), products drop ConstantCost(1), and an empty product reduces to ConstantCost(1) (src/v3/std/algebra.dag:411-413, src/v3/std/algebra.dag:435-456, src/v3/std/algebra.dag:520). The generated Rust mirror and bootstrap fixtures are regenerated to reflect the same algebraic behavior (src/v3/compiler/src/dag_cost_generated.rs:105-110, src/v3/compiler/src/dag_cost_generated.rs:135-150, src/v3/compiler/src/dag_cost_generated.rs:166), and the tests add bootstrap ratchets for the inhabitance edge and the product-normalization chain.

2. Invariant categories

Rubric applied from the attached invariant, modeling, coding, and testing references. chatgpt-review-bee27104-df27-4d…

chatgpt-review-14c88edf-5c5d-44…

chatgpt-review-34434bee-8812-4a…

chatgpt-review-be74ed84-3b33-43…

  1. LAYER MODEL (substrate vs implementation).

Compliant — this is a substrate-touching diff, and the new fact is placed as an inhabitance edge on the existing algebraic substrate rather than as a parallel cost flag: src/v3/std/algebra.dag:171 declares SymbolicCost inhabits Semiring<SymbolicCost>.

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

Compliant — Modeling Faithfulness / single-authority algebra: the diff fixes the law-bearing normalization at the source declaration site, not only in Rust; ProductCost now runs collapse_on_multiplicative_zero before drop_multiplicative_one at src/v3/std/algebra.dag:412-413, and reduce_product returns the multiplicative identity at src/v3/std/algebra.dag:520.

  1. CODING.md.

Compliant — the implementation mirror keeps the data + free-functions style: collapse_on_multiplicative_zero(terms: Vec<SymbolicCost>) at src/v3/compiler/src/dag_cost_generated.rs:135 and drop_multiplicative_one(terms: Vec<SymbolicCost>) at src/v3/compiler/src/dag_cost_generated.rs:146 are explicit input→output helpers with no hidden state or method accretion.

  1. TESTING.md.

Finding — NON-BLOCKING, regression-ratchet gap. The updated recursive-loop test now says the guard is only “the semantic value” (src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs:343-345) and asserts only matches!(cost, SymbolicCost::LinearCost { .. }) (src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs:351-353). That assertion would also pass if the loop body cost were silently dropped, because Linear * 1 and bare Linear normalize to the same value after this PR. The new identity/annihilator tests cover semiring normalization, but they do not replace the old facts-flow-forward regression ratchet for “loop body cost participates in iterate.” A small non-identity body-cost fixture, or a structural pre-normalization assertion on the loop path, would preserve that previous regression coverage.

  1. LOCKED DESIGN DECISIONS.

Compliant — the substrate comment explicitly scopes the new inhabitance edge as a prerequisite, not as a silent completion of downstream law verification: src/v3/std/algebra.dag:168-170 says the Semiring edge “does not retire those law rows in this slice.”

  1. TRACKED vs UNTRACKED DEBT.

N/A — no new TODO, scaffold, temporary bridge, or debt carrier is introduced in the human-authored diff; the law-witness non-retirement is stated as scope, not a new bridge shape.

3. Verdict

APPROVE_WITH_COMMENTS

The substrate modeling and normalization changes are directionally correct and source-aligned. I would not block on the one test issue, but the PR does weaken a prior loop-body regression ratchet, so I’d add a non-identity recursive-body coverage point before relying on this suite as the full semiring/cost regression shield.

@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: 1816d111 · Trigger: schedule
  • Thinking: 284s wall

Non-blocking — Strengths

  • src/v3/std/algebra.dag The .dag authority and generated Rust mirror now agree on the additive-zero versus multiplicative-zero/one split, and the tests ratchet both the inhabitance edge and bootstrap-visible product identity path.

✅ No blocking concerns; the prior semiring identity issue is addressed cleanly in this slice.

@briansrls
briansrls force-pushed the feat/symbolic-cost-semiring-inhabitance branch from c7295a0 to 5920231 Compare May 3, 2026 02:47
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 5920231e · Trigger: schedule
  • Comparison: origin/main @ d2e72d26 ... review/pr-1555-5920231e @ 5920231e
  • Thinking: 34s wall

Findings: none. The diff is internally consistent: algebra.dag adds inhabits Semiring<SymbolicCost> plus honest semiring normalization (additive zero drop under Sum, multiplicative zero annihilation and one identity under Product, empty product → 1), and the two generated Rust mirrors (dag_cost_generated.rs, the regen script template) match line-for-line. Tests are updated to reflect the new identity behavior — the previous recursive_fn_loop_body_cost_enters_iterate_composition assertion that demanded a ProductCost([Linear, Constant]) is correctly relaxed to bare LinearCost (since Linear * 1 now normalizes), and a new iterate_keeps_non_identity_body_cost_in_product regression guard preserves the original "body fact not dropped" intent using LogCost instead of ConstantCost(1). The substrate-fact tests (symbolic_cost_semiring_inhabitance_…, …_product_identity_stage_…) are exactly the API-level enforcement INVARIANTS asks for: the inhabitance edge and the normalization stage chain are both verified by reading the bootstrap Dag, not by re-deriving from generated Rust.

Cost-of-change holds: one DSL edit + one generator template + regenerated mirror + manifest hash bump.

Verdict: APPROVE — small, well-scoped, and the algebra is now actually a semiring (zero-annihilator + one-identity), with substrate-level tests guarding the inhabitance and the normalize stage chain.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: f1e43cf6 · Trigger: schedule
  • Comparison: origin/main @ 5c4c94bd ... review/pr-1555-f1e43cf6 @ f1e43cf6
  • Thinking: 55s wall

Findings

None that tie to a concrete rubric violation in the diff. The substrate change is coherent: SymbolicCost inhabits Semiring<SymbolicCost> matches INVARIANTS P1’s “attach via inhabitance / shared parent” pattern; normalization is split so additive zero is removed only under sums, while products get zero-annihilation and multiplicative-one removal, with reduce_product on an empty term list returning ConstantCost(1) (correct semiring unit, fixing the prior 0 at src/v3/std/algebra.dag around the reduce_product / ProductCost / Empty hunk). The regen script and dag_cost_generated.rs stay aligned with that DAG truth.

Verdict

APPROVE — Narrow, internally consistent modeling + mirror + tests; nothing in the reviewed diff clearly breaches INVARIANTS, modeling-discipline, CODING, or TESTING.

Exploratory observations (optional)

  • lane2_stage_2d_symbolic_cost_test.rs (symbolic_cost_product_identity_stage_is_bootstrap_substrate_fact): the transform-chain walk is tightly coupled to how normalize happens to lower into the bootstrap DAG; that is explicit in the name, but it is more “wiring exists” than a pure behavioral API check. Non-blocking; acceptable if the intent is a substrate/regen ratchet.

@briansrls
briansrls force-pushed the feat/symbolic-cost-semiring-inhabitance branch from f1e43cf to 2203ad0 Compare May 3, 2026 03:26
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: 2203ad0f · Trigger: schedule
  • Comparison: origin/main @ 94c479cf ... review/pr-1555-2203ad0f @ 2203ad0f
  • Thinking: 45s wall

Reviewed the substantive diff (algebra.dag, dag_cost_generated.rs, regen_runtime_mirrors.py, integration tests, manifest). Large churn in bootstrap_generated*.rs is regen from the algebra change; substantive behavior matches those sources.

Findings: None. Nothing in the diff clearly violates INVARIANTS.md / modeling-discipline (P1 algebra inhabitance for SymbolicCost, single authority via .dag + generated mirrors), CODING.md (data + generated free-function shape unchanged), or TESTING.md for new work (focused substrate/regression tests; updated countdown expectation matches honest multiplicative identity).

Verdict: APPROVE — Declares SymbolicCost inhabits Semiring<SymbolicCost>, aligns normalization with semiring rules (additive vs multiplicative zeros/ones, empty product as 1), keeps script and dag_cost_generated.rs in sync, and adjusts tests so the recursive countdown case expects normalized LinearCost while adding guards for identity, annihilator, and non-identity body products.

Exploratory (optional): symbolic_cost_product_identity_stage_is_bootstrap_substrate_fact in lane2_stage_2d_symbolic_cost_test.rs encodes a specific transform wiring in the bootstrap DAG; if that graph shape refactors often, the test may need touch-ups — acceptable as an explicit “substrate-visible chain” check.

@briansrls
briansrls force-pushed the feat/symbolic-cost-semiring-inhabitance branch from fc7561c to 89b1389 Compare May 3, 2026 03:45
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: 89b1389e · Trigger: schedule
  • Comparison: origin/main @ 0427f96f ... review/pr-1555-89b1389e @ 89b1389e
  • Thinking: 105s wall

Findings

  • BLOCKING: src/v3/std/algebra.dag:171 declares SymbolicCost inhabits Semiring<SymbolicCost>, but this diff does not make the semiring witness fields authoritative anywhere: add, zero, mul, and one are still implicit in nearby functions/constants rather than carried by the inhabitance fact. That violates INVARIANTS P2 Boundary Discipline / single authority: a downstream Semiring consumer would have to infer that sequential, ConstantCost(0), iterate, and ConstantCost(1) are the intended witness rather than reading those facts from the declared boundary.

Verdict: REQUEST_CHANGES. The product normalization changes look coherent, but the substrate inhabitance edge overclaims the boundary until the Semiring witness is declared or the bridge is explicitly bounded with a named dissolution trigger.

@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: fc7561c5 · Trigger: schedule
  • Thinking: 356s wall

Non-blocking — Strengths

  • src/v3/std/algebra.dag The Semiring inhabitance is backed by distinct additive-zero, multiplicative-zero, and multiplicative-one paths in the .dag authority and generated Rust mirror.

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

  • src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs The LinearCost assertion is correct for the identity case, but a source-level recursive fixture with non-identity body cost would better ratchet Facts Flow Forward; defer to the cost-lens behavioral-parity lane if that source surface is not yet expressible.

✅ No blocking concerns; the prior semiring identity issue is addressed cleanly.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: c3eab90d · Trigger: schedule
  • Comparison: origin/main @ 7cd1cecd ... review/pr-1555-c3eab90d @ c3eab90d
  • Thinking: 87s wall

Findings

  • NON-BLOCKING: lane2_stage_2d_symbolic_cost_test.rs:248 walks bootstrap Dag producer chains to require the exact collapse_on_multiplicative_zero -> drop_multiplicative_one -> reduce_product implementation shape. That conflicts with TESTING.md’s behavior-driven / cost-of-change guidance: an equivalent normalization refactor could preserve the Semiring behavior while breaking this test. The behavioral product zero/one tests added later cover the contract more directly.

Verdict: APPROVE_WITH_COMMENTS. The substrate change is documented as a bounded edge-only bridge with a named dissolution trigger, and I don’t see a blocking modeling or fail-closed violation in the diff.

@briansrls

Copy link
Copy Markdown
Contributor Author

Verified against current head c3eab90. The concern is valid as a cost-of-change tradeoff, but I am intentionally keeping symbolic_cost_product_identity_stage_is_bootstrap_substrate_fact in this PR because this slice is specifically a substrate-introduction prerequisite. The behavioral product zero/one tests cover the semiring law surface; this ratchet covers the separate generated-bootstrap authority issue that was previously blocking, namely that Dag::new() must expose the same product identity stage chain as src/v3/std/algebra.dag. If normalize is later refactored while preserving laws, this test should move with that substrate refactor rather than silently losing the bootstrap-visible witness path.

— sent from silent-deer-861

@briansrls
briansrls force-pushed the feat/symbolic-cost-semiring-inhabitance branch from c3eab90 to 2ce7a24 Compare May 3, 2026 04:23
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 2ce7a241 · Trigger: schedule
  • Comparison: origin/main @ 98caedb8 ... review/pr-1555-2ce7a241 @ 2ce7a241
  • Thinking: 23s wall

Verdict: APPROVE — semiring fix is correct and well-scoped: separating additive-zero (drop), multiplicative-zero (annihilate), and multiplicative-one (drop) corrects the prior drop_zero conflation, and the empty-product identity is rightly flipped from 0 to 1. The DSL change in src/v3/std/algebra.dag is mirrored faithfully into both dag_cost_generated.rs and bootstrap_generated*.rs, and the manifest hash bump is consistent.

The inhabits Semiring<SymbolicCost> edge with no structural witness is the kind of scaffold that would normally raise a flag, but the comment at src/v3/std/algebra.dag:165-181 documents it, bounds it ("edge-only today"), and names a concrete dissolution trigger (symbolic_cost_semiring_structural_witness_lands — when class-5 function-valued fields lower, author the witness with specified add/zero/mul/one). That satisfies the tracked-debt criteria.

Tests are tight: substrate-level checks that the inhabits edge points at Semiring<SymbolicCost> and that the ProductCost normalize chain is preserved on the Dag (lane2_stage_2d_symbolic_cost_test.rs:202-281), plus behavior tests for annihilator/identity. The rewrite of loop_body_recursive_fn_yields_product_with_linear_and_body_cost is a real semantic shift (Linear * 1 → Linear), and the new iterate_keeps_non_identity_body_cost_in_product test plugs the regression hole that the old assertion was guarding. Good swap.

No findings.

@briansrls
briansrls merged commit 5ef6530 into main May 3, 2026
4 checks passed

@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: 2ce7a241 · Trigger: schedule
  • Thinking: 211s wall

Non-blocking — Strengths

  • src/v3/std/algebra.dag The remaining edge-only semiring witness gap is documented, bounded to function-valued structural data lowering, and has a named dissolution trigger.

✅ No blocking concerns; the prior semiring identity issue is addressed cleanly.

briansrls added a commit that referenced this pull request May 3, 2026
Per Director closure-flip request (#828 reply 4367038381), bundling
two more retirements into this PR since they edit the same
highest-leverage targets list:

- row 90 (SymbolicCost semiring annihilation) → Retired by PR #1555
- row 93 (??/% syntax authority mismatch) → Retired by PR #1552

Highest-leverage targets list trimmed: drop SymbolicCost (#3) and
SubValueRelation (#4); renumber remaining; closing parenthetical
updated to record all five originally-listed retirements.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 3, 2026
* docs(r3): retire row 97 — BridgeLedger decreasing-count ratchet landed (#1571)

Bundle 4a closure receipt. PR #1571 (c3138a9,
"test(v3): add BridgeLedger open-count ratchet") converts the
known-open reporting scaffold into a decreasing-count ratchet, so the
open-bridge count can no longer silently grow.

Per-PR Debt-Paydown receipt against ledger row 97.

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

* docs(r3): remove stale row-97 references in highest-leverage + dispatch sections

Per codex review on #1583: row 97 retirement at line 97 left two stale
references treating BridgeLedgerZero as still active — the
"Highest-Leverage Retirement Targets" item #7 and the "Next Dispatch
Packet" bridge-discipline bundle. Both now record the row as retired
by PR #1571.

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

* docs(r3): also retire rows 90, 93 + drop from highest-leverage list

Per Director closure-flip request (#828 reply 4367038381), bundling
two more retirements into this PR since they edit the same
highest-leverage targets list:

- row 90 (SymbolicCost semiring annihilation) → Retired by PR #1555
- row 93 (??/% syntax authority mismatch) → Retired by PR #1552

Highest-leverage targets list trimmed: drop SymbolicCost (#3) and
SubValueRelation (#4); renumber remaining; closing parenthetical
updated to record all five originally-listed retirements.

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

* docs(r3): refresh Baseline Counts table to match catalog statuses

Per codex review on #1583: row 90/93/97 retirements left the
baseline-counts summary stale. Catalog now totals 50 Open + 1 Open/
disposition pending + 8 Partial + 10 Retired = 69 (preserved). Adds
the previously-missing "Open / disposition pending" bucket so the
classification is complete.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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