Repository navigation
docs(design): Prereq-X audit — HO field-call for fold_lens<C> - #1264
Conversation
# Conflicts: # src/v3/compiler/src/bootstrap_generated.rs # src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs
- Add method_template_contract_test.rs to EXPECTED_HAND_AUTHORED_TEST with Director-approved receipt (T-Ground-LanguageSpec dispatch explicitly accepted "focused Rust tests over the reflected substrate"). - Refresh parse_corpus_manifest.txt entry for src/v3/std/emit_model.dag to reflect MethodTemplateContract + PlaceholderConvention additions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # src/v3/compiler/src/bootstrap_generated.rs # src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs
Re-regenerate v3 bootstrap so MethodTemplateContract + PlaceholderConvention land on top of main after merging origin/main (carrier shape unchanged). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First substrate slice for the lens framework (docs/design-lens-framework.md, docs/briefs/r2-substrate-manager.md). Director-locked option (c) on parent inbox #1130. Substrate changes: - New src/v3/std/lens.dag declares Lens<C> with the locked 6-field shape: name, read: fn(Dag, Behavior) -> Witness<C>, sequential: Monoid<C>, branch: fn(C, C) -> C, iterate: fn(C, LoopBound) -> C, validate: fn(Dag, C) -> OptionalDiagnostic. Reuses Witness<C> / OptionalDiagnostic / DimensionReport<C> from dimensions.dag and Monoid<C> from dsl/std/algebra.dag — no parallel reps introduced. - diagnostics.dag: Q6.5 two-layer authority. Adds DiagnosticKindDecl, LensInstanceKindWitness (decl-only, no payload field — see gap receipt below), and AnyDiagnosticKind = CompilerKind | LensInstanceKind. Widens Diagnostic.kind from CompilerDiagnosticKind to AnyDiagnosticKind. CompilerDiagnosticKind closed sum unchanged (anti-bridge invariant). Substrate gap receipt (Director-approved option (c)): - LensInstanceKindWitness intentionally lacks a payload value field. Today's .dag grammar cannot express `payload: <inhabits kind_decl.payload>` (refinement-type-on-sibling- field). The flat alternative ratifies the illegal-state Q6.5 rejected (Lens / name / payload-shape three independent coords). Layer-2 kind identity + namespace authority land now; structured payload value waits for dependent-field typing. Acceptance: - src/v3/compiler/tests/integration/lens_substrate_carrier_test.rs: Lens<C> 6-field shape, Diagnostic.kind widening, closed-sum invariance, AnyDiagnosticKind two-constructor shape, Layer-2 payload absence as fail-loud trigger when grammar gap closes. - SG-0 ratchet receipt added with Director acceptance citation. - parse_corpus_manifest.txt refreshed via refresh_handwritten_parse_snapshot_manifest -- --ignored. Out of scope (deferred to subsequent lanes): - Migration of cost.dag / complexity.dag / idempotency.dag / parallelism.dag PROXY lenses to consume Lens<C> (R3-T-CostLens- Composition + R2-Evaluator PR-A..E). - fold_lens<C> generic fold machinery (I2 in design doc). - User-authored lens TestClaim wiring (I7 in design doc). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Strengthen LensInstanceKindWitness SCAFFOLD comment to call out that bare `DeclarationRef` for `kind_decl` is part of the SAME dissolution trigger as the deferred payload typing — substrate-level refinement-typing-on-DeclarationRef closes both the payload-typing gap and the kind-decl resolution gap in one move. Cites the analogous PatternRealization and MethodTemplateContract.dag_method patterns. Addresses non-blocking codex BLOCKING relay at sha fa5bba2 (Layer-2 diagnostic-kind witness leaving its core authority unconstrained) — shape unchanged per Director-locked option (c) on parent inbox #1130; just makes the bounded-scaffold receipt fully explicit on this row. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # src/v3/compiler/src/bootstrap_generated.rs # src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs
Re-regenerate v3 bootstrap so Lens<C> + Q6.5 widening land on top of latest main after the merge conflict resolution. Refresh parse manifest. Carrier shape unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # src/v3/compiler/src/bootstrap_generated.rs # src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs
Re-regenerate v3 bootstrap so Lens<C> + Q6.5 widening land on top of main after #1188 fixed the v2-extdeps regression. Refresh parse manifest. Carrier shape unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed in 8dbdfed. Reviewer was right: Replaced the named-field variants with tuple-struct payloads: pub enum TransformDispatch {
Callable (CallableDispatch),
FieldProject (FieldProjectDispatch),
Operator (OperatorCall),
Indirect (IndirectDispatch),
}
pub struct CallableDispatch {
pub(crate) callee: DeclarationId,
pub(crate) args: Vec<PortId>,
}
// + analogous FieldProjectDispatch / IndirectDispatchOutside the dag module, — sent from tidy-wolf-507 |
|
Review metadata
Findings
Verdict: REQUEST_CHANGES. The audit is otherwise well-scoped, but this visibility mismatch undermines the central structural guarantee the design is locking. |
…b(crate))
Reviewer caught: pub(crate) fields permit any in-crate module to
construct CallableDispatch { ... } literally, bypassing the Dag
builder that binds args to target. Switched to module-private (no
visibility modifier) so only code inside the dag module can construct
the payloads. Aligns ArrowPortRef precedent (already module-private).
|
Addressed in 76a65b2. Reviewer was right — — sent from tidy-wolf-507 |
|
Review metadata
1. Story of the diffThis PR adds one audit document, 2. Invariant categories
Finding — BLOCKING, Modeling Faithfulness / coproduct dissolution. The diff is a docs-only PR, but the doc proposes substrate shape for It also conflicts with the invariant example that operator symbols come from algebra field declarations, not a target/private enum table. chatgpt-review-1bfa188d-313b-4e… At minimum,
Finding — BLOCKING, P1 Modeling Faithfulness / Practice 4 Coproduct dissolution. The document does include a dissolution ledger for The diff’s rationale is only that no
Compliant. Although no Rust code changes land, the proposed API shape follows the coding preference for structured carriers and typed handles:
Compliant. No tests are required in this audit-only PR because it explicitly does not implement behavior (
Compliant. The doc explicitly records the Director-locked explicit block syntax decision for X3 (
Finding — BLOCKING, tracked debt / dissolution trigger. The Either reclassify 3. VerdictREQUEST_CHANGES. The audit is otherwise careful and valuable, especially around |
… example
Modeling-discipline Practice 4's canonical example is ArithOp →
Apply { function: FunctionRef } pointing at std::int::add. OperatorCall
is structurally that case; absence of a current DeclarationId for + / -
/ unary ! is not the same as 'no richer source exists.' Tracking gate:
std/{int,bool,float}/ declaring operator-algebra witness functions and
parser desugaring operator tokens to Call(FunctionRef).
|
Addressed in 6bf392f. Reviewer is right —
The "absence of a current — sent from tidy-wolf-507 |
|
Review metadata
Findings: None. The diff only adds Verdict: APPROVE — Narrow, Director-scoped audit with explicit non-scope, cross-links, and test-matrix hooks for follow-on work; no rubric violations spotted in the diff. Exploratory (optional): The large Rust sketch uses tuple variants like |
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
5c53727b· Trigger:schedule - Thinking:
313s wall
BLOCKING (2)
Root Cause
docs/design-prereq-x-ho-field-call.mdThe proposed substrate lacks a clean separation between field projection and field invocation → preserve projection as a one-carrier dispatch fact, then invoke Arrow-valued projections via anIndirect/Callshape whose dependency iterator includes callee and arguments.
Non-blocking — Strengths
docs/design-prereq-x-ho-field-call.mdClassified as design/docs; the audit now cleanly separates Lens field assignment from consumer-side invocation and names concrete acceptance cases for X1/X2/X3.
Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)
docs/design-prereq-x-ho-field-call.mdThe emitter-contract snippet should use tuple payload matches/accessors instead of struct-variant destructuring so it matches the private-payload API; defer to the Prereq-X1 implementation lane if not fixed here.
| /* private */ field_label: String, | ||
| /* private */ field_child: Option<DeclarationId>, | ||
| /* private */ carrier: PortId, | ||
| /* private */ args: Vec<PortId>, |
There was a problem hiding this comment.
BLOCKING: FieldProjectDispatch adds args: Vec<PortId> to a substrate form that current code uses for one-carrier Conj projection, collapsing plain field access and field invocation into one state family (illegal states unrepresentable / modeling faithfulness).
| impl TransformDispatch { | ||
| /// Single-authority dependency walk for Facts Flow Forward. | ||
| /// For `Indirect`, yields the callee port first, then args. | ||
| /// For other variants, yields args only (callee identity is |
There was a problem hiding this comment.
BLOCKING: input_ports() excludes non-Indirect runtime inputs, but FieldProjectDispatch carries carrier: PortId, so reflected consumers would miss the carrier dependency (Facts Flow Forward / Every Dependency Is A Substrate Fact).
|
Stale — dissolution ledger has been in the doc since
— sent from tidy-wolf-507 |
|
Review metadata
Findings:
Verdict: APPROVE_WITH_COMMENTS. The audit is otherwise narrowly scoped, docs-only, and it names the substrate target, typed construction path, fail-closed tests, and dissolution gates clearly. |
…ocation)
Reviewer caught: collapsing plain field access and field invocation
into one variant with optional args admits a malformed state where
projection has args or invocation has none. Different state families
should be different variants.
- FieldProject preserves current TransformTarget::FieldProject shape
(no args; pure value access) — 🟢 keep.
- FieldCall is the new X1 variant — projection-then-call; always has
args. 🟡 future-collapses with Callable/Indirect into Call{CalleeRef}.
Builders split: push_field_project_transform vs push_field_call_transform.
|
Addressed in e03703e. Reviewer is right — Split into two variants:
Builder surface split accordingly: — sent from tidy-wolf-507 |
Reviewer caught: FieldProject.carrier and Operator(Unary/Binary) operand ports are runtime deps; input_ports() must yield every runtime PortId across all variants for Facts Flow Forward to hold. Documented per-variant enumeration explicitly.
|
Addressed in 02f04e7. Reviewer is right — Documented the full per-variant enumeration:
— sent from tidy-wolf-507 |
|
Stale — review ran against Blocking #1 (projection vs invocation): done in Blocking #2 (input_ports must include callee + carrier + args): done in
Non-blocking (emitter snippet uses tuple form): done in — sent from tidy-wolf-507 |
…ect variant transitional'
Reviewer flagged: 'Indirect is permanent' (line 482) muddled with
'Callable/FieldCall/Indirect 🟡 future-dissolve' (line 424). Split into
two claims: the capability is permanent (some variant must carry HO
dispatch), but the specific variant spelling 'Indirect(IndirectDispatch)'
retires when the 🟡 collapse to Call{CalleeRef::Port} lands.
|
Review metadata
Findings: None. The only change vs Verdict: APPROVE — Single scoped design doc; no rubric violations observed in the diff. |
|
Review metadata
1. Story of the diffThis PR adds a single design audit, 2. Invariant categories
Finding — BLOCKING, substrate design / single authority. The audit introduces
Finding — same blocking issue under Boundary Discipline / No Parallel Representations. The diff correctly identifies the anti-pattern at
Compliant. The proposed Rust shape uses typed carriers and explicit
Compliant. This is explicitly an audit-only PR with no parser/lowerer changes, and it says so at
Compliant. The diff treats X3’s parser ambiguity as locked to explicit block syntax, not heuristic lookahead:
Compliant. The audit does not leave an unbounded scaffold: it classifies the proposed coproduct variants in a dissolution ledger at 3. VerdictREQUEST_CHANGES The audit is mostly careful and well-scoped, but the proposed substrate shape currently gives two incompatible representations for runtime field invocation: direct |
|
Review metadata
1. Story of the diffThis PR adds one new audit/design document, From that evidence, the audit splits the follow-up into X1 call-on-field/access generalization, X2 call-on-Arrow-typed local values, and X3 explicit block expressions. The load-bearing design move is the proposed substrate-side replacement of 2. Invariant categories
Finding — BLOCKING, substrate design ambiguity / single-authority. The audit clearly touches substrate shape: it proposes collapsing
Finding — Boundary Discipline / single-authority metadata. Same issue as above, stated at the invariant level: two consumers reading one resolved fact is fine, but two substrate representations for the same call shape are not.
Compliant, modulo the finding above. The proposed Rust shape follows the local style: data carriers plus
Compliant. This is an audit-only PR and explicitly states no parser/lowerer/emitter edits or test additions are part of the deliverable (
Compliant. The X3 syntax decision is explicitly framed as locked only at the discipline level — explicit block marker, not heuristic
Compliant, once the FieldCall/Indirect ambiguity is clarified. The coproduct ledger gives each proposed 3. VerdictREQUEST_CHANGES The audit is valuable and mostly disciplined, but it currently leaves the central substrate representation for runtime field calls ambiguous between |
* test(v3): Prereq-X call-on-field-access blocker ratchet Verifies the parser-grammar gap (call-on-field-access expression and brace-block let inside = body) still blocks fold_lens<C> consumer wiring (Prereq-3b dispatch). Pins the diagnostic shape of each gap so the ratchet flips to red when the implementation lane (X1/X3 from #1264 audit) lands and the lane owner retires the fixtures. No hand-Rust scaffolding for fold_lens<C>; the gap is structural in the grammar and must be closed at the parser/lowerer, not bridged in Rust. * chore: apply cargo fmt * test(v3): use real surface syntax in Prereq-X ratchet fixtures Previous fixture used 'type Wrapper = Conj { f: Arrow(Int) -> Int }'; that risked pinning a parse error from the type-decl side rather than the w.f(x) call-on-field-access gap. Switched both fixtures to 'type Wrapper { f: fn(Int) -> Int }' (matches Lens<C> field syntax in src/v3/std/lens.dag) and added a control test asserting the type declaration alone parses cleanly so X1/X3 isolate the call-site gap. * chore: apply cargo fmt * test(v3): register prereq_x ratchet path in EXPECTED_HAND_AUTHORED_TEST SG-0 census ratchet failed at 8ea73f1 / 424ea69 because the new prereq_x_call_on_field_access_ratchet_test.rs was a hand-authored .rs not declared in the EXPECTED_HAND_AUTHORED_TEST list. Added it in sorted ASCII-ascending position with a receipt comment naming the dissolution trigger (lane owner retires at the same time as the X1/X3 parser/lowerer change). * test(v3): switch .err().expect(...) to .expect_err(...) to satisfy clippy
Summary
Audit/planning PR — no code, no parser edits, no fold_lens implementation. Director-approved option (b) on parent inbox #1130 (2026-04-30) after the
fold_lens<C>HO field-call smoke confirmed v3 surface grammar does not support call-on-field-access.The deliverable is
docs/design-prereq-x-ho-field-call.md. It records exact parse failures, splits the prerequisite into three implementation slices, and maps each tofold_lens<C>and lens-instance consumer dispatch shapes.Smoke evidence
Four shapes tested via
cached_compile_to_dagagainst currentorigin/mainpost-Prereq-1 / Prereq-2 / Prereq-3a. All four fail:w.f(x)— parse error:expected let/fn/type/module/import/data, got LParen. Field-call grammar absent.(w.f)(x)— parse error:expected primary expression, got LParen. Parenthesized callee not in primary position.let g = wrap_double.f; g(x)— semantic errors: data field projection requires "compile-time value";gdoesn't resolve.fn r(...) -> T = { let g = ...; g(x) }— parse error:expected field label, got KwLet. Brace-after-=is record literal, not block expression.Three implementation slices
<ident>(<args>)to<expr>(<args>)for Arrow-typed<expr>. Primary case:lens.read(d, b).=bodies): block-vs-record-literal disambiguation. Two strategies presented (lookahead at first non-WS token vs explicitdo { ... }keyword). Director call.Mapping to fold_lens
Every Lens instance dispatch path is a call-on-field-access:
lens.read(d, b)— X1lens.sequential.op(a, b)— X1 with two-level field projectionlens.branch(a, b)/lens.iterate(body, bound)/lens.validate(d, c)— X1fold_lens<C>cannot be authored without X1. The lens-fold-prerequisites audit atdocs/design-lens-fold-prerequisites.md(PR #1207) conflated field assignment (Prereq-1, landed) with field invocation (Prereq-X, missing); the audit doc lays out the correction.Out of scope
fold_lens<C>authoring (blocked on Prereq-X).Test plan
docs/design-prereq-x-ho-field-call.mdwith exact parse-failure messages and acceptance test matrix per slice.🤖 Generated with Claude Code