Skip to content

docs(design): lens-fold prerequisites audit (planning, no implementation) - #1207

Merged
briansrls merged 56 commits into
mainfrom
session/tidy-wolf-507
Apr 29, 2026
Merged

briansrls merged 56 commits into
mainfrom
session/tidy-wolf-507

Conversation

@briansrls

@briansrls briansrls commented Apr 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Planning/audit PR — no code, no substrate edits, no implementation of fold_lens<C>. Director-approved option (C) on parent inbox #1130 (2026-04-29) after the T-Substrate-Lens-Primitive complexity-lens migration slice STOP+PINGed on the class-5 / fn block-body grammar gap.

The deliverable is docs/design-lens-fold-prerequisites.md. It names the exact substrate/lowering work required before any Lens<C> instance (starting with the dispatched data complexity_lens: Lens<Int> = { ... }) can lower honestly, and before complexity_lens_via_framework_correct becomes a meaningful equivalence test.

Director-locked dispositions (2026-04-29)

Both decision points the audit raised are now resolved on parent inbox #1130:

  1. Workflow-root identification = (α) last topological Bind, behind a named workflow_root_port(d: Dag) -> PortId helper/accessor. β rejected as too narrow. γ remains a future refinement behind the same accessor. Cross-reference: workflow_root_port is shared authority for both fold_lens<C>'s workflow-root identification AND R2-Evaluator's runtime entry-point identification (evaluate(program, entry, args) -> Value shape from Items 4+5 / docs(design): Tier 1 design locks 4+5 (PB-Runtime interpreter-as-data + bin-shim emit pattern) #1176 §3.2). One accessor surface; two consumers.
  2. Class-5 gap Consolidate binaries into gunbc-dag package #4 strategy = infer-time re-resolution for variant constructors. No per-type special cases for Witness<C> / OptionalDiagnostic. Lens-framework variant constructions inherit the generic resolution path.

Doc updated in head d34ca4a19 to land both dispositions in line with the audit content.

Why an audit PR

The migration plan in docs/design-lens-framework.md (~5-8 days for 4 lenses) implicitly assumed the class-5 / fn-block-body lowering surface existed. The cost.dag deferral at src/v3/lenses/cost.dag:260-302 already named the same blocker for Dimension<SymbolicCost> data-binding authoring; the lens framework migration inherits it unchanged. Surfacing the implicit dependency here means subsequent dispatch can scope the prerequisite work explicitly instead of discovering it again per lens.

Three prerequisite slices (Director-locked sequencing)

Prereq-1 — port-carried field values in data record bodies (~3-5 days; standalone). Closes class-5 gap #3 port-carried branch. lower_record_to_structural accepts SurfaceExpr::Var / SurfaceExpr::Path / nested record/list/map literals as field values; recursive structural inhabitance check. Can land first. Unblocks every Lens<C> field assignment AND dissolves the Dimension<SymbolicCost> deferral simultaneously.

Prereq-2 — fn block-body lowering with variant-constructor expressions (~5-7 days). Closes class-5 gap #4 (infer-time re-resolution per Director disposition) plus the fn X { body } block-body restriction. Unblocks Witness<Int>::Inhabits(n) | Violates { ... } construction inside complexity_read.

Prereq-3a — workflow_root_port accessor (~1-2 days; standalone). Declare the accessor in src/v3/std/substrate.dag (or sibling) with the α implementation. Shared authority for fold_lens<C> and R2-Evaluator. Can land in parallel with Prereq-1 / Prereq-2 to unblock R2-Evaluator early.

Prereq-3b — fold_lens<C> machinery (~3-5 days). Authors fold_lens<C>: Lens<C> → Dag → DimensionReport<C>, consuming workflow_root_port from 3a. Depends on Prereq-1 + Prereq-2 + Prereq-3a. Unblocks complexity_lens_via_framework_correct as a meaningful equivalence test.

Total sequencing

~11-17 days at gunbc velocity, partially parallelizable:

  • Day 0: Prereq-1 and Prereq-3a kick off in parallel (independent).
  • Prereq-2 runs in parallel with Prereq-1; depends only on class-5 gap Consolidate binaries into gunbc-dag package #4.
  • Prereq-3b runs after Prereq-1 + Prereq-2 + Prereq-3a all land.

Out of scope

  • Authoring data complexity_lens: Lens<Int> = { ... } (blocked on Prereq-1 + Prereq-2 + Prereq-3b).
  • Authoring per-field free functions or callable fn complexity_lens() -> Lens<Int> as substitutes (Director rejected B and D).
  • Modifying the existing per-port complexity fold (src/v3/lenses/complexity.dag) — preserved as the M2 equivalence oracle.

Test plan

  • Audit doc lands at docs/design-lens-fold-prerequisites.md; cross-references existing class-5 / cost.dag deferral entries.
  • Director dispositions on workflow-root α/β/γ + class-5 gap Consolidate binaries into gunbc-dag package #4 landed in head d34ca4a19.
  • Manager review (approved 2026-04-29T15:05:15Z, no content changes).
  • Subsequent dispatch scopes Prereq-1 / Prereq-2 / Prereq-3a / Prereq-3b as separate substrate lanes.

🤖 Generated with Claude Code

briansrls and others added 30 commits April 28, 2026 23:33
# 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>
Per BLOCKING review on PR #1207 sha d34ca4a: original framing
was stale. Verified at lower.rs:3273-3565: lower_record_to_structural
already handles nested Record/List/Map; lower_structural_field_value
already resolves SurfaceExpr::Var/Path to FieldValue::Reference for
DeclarationRef-typed and meta-tag-matching fields. The actual
residual gap is narrower — Arrow-signature inhabitance for fn-typed
fields like Lens<C>.read: fn(Dag, Behavior) -> Witness<C>.

Prereq-1 sizing drops ~3-5 days → ~1-3 days. Total sequencing
revised from ~11-17 days to ~9-15 days. Other prereqs unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`UserCallable` Bind) reuses the same `WorkflowRoot` partition.

The accessor lands as part of Prereq-3 (or as a separate
sub-slice of Prereq-3 that can lead, since the accessor doesn't

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.

Valid finding — verified at src/v3/compiler/src/lower.rs:3273-3565. lower_record_to_structural already lowers nested Record/List/Map; lower_structural_field_value at :3369-3411 already resolves SurfaceExpr::Var/Path to FieldValue::Reference(DeclarationId) (lines 3399, 3409) for DeclarationRef-typed and meta_tag-matching fields. SurfaceExpr::Map (parse.rs) and FieldValue::Map (dag.rs:993) both exist. The original Prereq-1 framing claimed those needed authoring — stale.

The actual residual gap is narrower: Arrow-signature inhabitance for fields like Lens<C>.read: fn(Dag, Behavior) -> Witness<C> whose expected_type resolves to an Arrow type, not DeclarationRef and not matched via meta_tag. The current declaration_ref_types_equivalent path covers marker-type equivalence, not Arrow-signature equivalence.

Updated Prereq-1 in head 42bf818a4 to scope this narrower gap (~1-3 days instead of ~3-5); revised total sequencing from ~11-17 days to ~9-15 days. — sent from tidy-wolf-507

Per BLOCKING review on PR #1207 sha 42bf818: Prereq-3a was
allowed to land before 3b but only 3b had named acceptance,
violating the reflected-facts invariant. Add four claims for
Prereq-3a (single-Bind / zero-Bind / multi-Bind variant
returns + R2-Evaluator cross-consumer proof) so the accessor
has its own generated-consumer proof at the substrate-load
boundary, independent of 3b's downstream fold correctness.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
**Sizing estimate:** ~1-3 days. Smaller than the original
framing because most of the lowering pipeline is already in
place; the change is a narrower inhabitance refinement.

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.

Valid finding. Addressed in head a4950f5e3: added four standalone acceptance claims for Prereq-3a — workflow_root_single_bind_returns_single_root, workflow_root_zero_bind_returns_no_root, workflow_root_multi_bind_returns_ambiguous, and workflow_root_consumed_by_runtime_entry_point (R2-Evaluator cross-consumer proof). The accessor now has its own generated-consumer proof at the substrate-load boundary; 3b's complexity_lens_via_framework_correct becomes a pure fold-correctness test that doesn't re-test the accessor partition. — sent from tidy-wolf-507

Per codex non-blocking finding on PR #1207 sha d34ca4a: the
"does not commit to workflow-root interpretation" bullet
contradicted the Director-locked α + accessor disposition added
above. Strike the bullet and reference the locked disposition.

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

Copy link
Copy Markdown
Contributor Author

All four codex BLOCKING-review items addressed at head cca85a632:

  1. Workflow-root accessor return type (inline at :296): refined PortId → WorkflowRoot = SingleRoot(PortId) | NoRoot | AmbiguousRoot { candidates: List<PortId> } — fail-closed for no-root and multi-entry programs. (head 09c221e36)
  2. Stale Prereq-1 scope (inline at :316): verified lower_record_to_structural already handles nested Record/List/Map and Var/Path → FieldValue::Reference; narrowed Prereq-1 to Arrow-signature inhabitance only. Sizing dropped from ~3-5d → ~1-3d. (head 42bf818a4)
  3. 3a acceptance separation (inline at :381): added four standalone Prereq-3a claims (single/zero/multi-Bind variant returns + R2-Evaluator cross-consumer proof) so the accessor has its own generated-consumer proof at the substrate-load boundary. (head a4950f5e3)
  4. Workflow-root contradiction in does-not-do list (non-blocking): struck the "does not commit to interpretation" bullet and referenced the locked Director disposition. Audit-history preservation kept via strikethrough. (head cca85a632)

— sent from tidy-wolf-507

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: cursor / composer-2
  • Commit: cca85a63 · Trigger: schedule
  • Comparison: origin/main @ e41a46d6 ... review/pr-1207-cca85a63 @ cca85a63
  • Thinking: 53s wall

Findings: None. The only change vs origin/main is docs/design-lens-fold-prerequisites.md (+544 lines). It is explicitly an AUDIT/planning artifact (“does not author code”), names prerequisites, acceptance hooks, and Director-locked dispositions in line with P2 boundary / reflected-facts and P5 scaffold + dissolution framing in INVARIANTS.md. Nothing here imposes new substrate or tests that would contradict TESTING.md or CODING.md (no compiler code). Spot-checked the cited lower_record_to_structural / lower_structural_field_value anchors in lower.rs (e.g. around 3273:3273:src/v3/compiler/src/lower.rs and 3369:3410:src/v3/compiler/src/lower.rs); they match the doc’s intent.

Verdict: APPROVE — Narrowly scoped design audit; no rubric violations observed in the diff.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / codex-default
  • Commit: 8f48849d · Trigger: schedule
  • Comparison: origin/main @ df458e7b ... review/pr-1207-8f48849d @ 8f48849d
  • Thinking: 35s wall

Findings:

  • docs/design-lens-fold-prerequisites.md:320 contradicts the fail-closed carrier defined just above. Lines 292-299 say workflow_root_port must not return bare PortId because NoRoot / AmbiguousRoot would be fabricated or lost, but Sub-slice 3a then scopes the substrate declaration as workflow_root_port(d: Dag) -> PortId. That violates INVARIANTS P3 Fail-Closed and P2 Boundary Discipline; the planned substrate surface should stay -> WorkflowRoot.

Verdict: REQUEST_CHANGES. The audit is otherwise narrowly scoped and useful, but this line would dispatch the next implementation PR toward the exact substrate shape the document rejects.

briansrls and others added 2 commits April 29, 2026 16:08
…refinement

Per codex REQUEST_CHANGES on PR #1207 sha 8f48849: line 320 still
said `workflow_root_port(d: Dag) -> PortId` while the rest of the
doc had been updated to `-> WorkflowRoot` (the fail-closed
sum from the earlier inline blocking review). Stale residue from
the iterative refinements; fixed.

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: 96c9901d · Trigger: schedule
  • Comparison: origin/main @ 985966bf ... review/pr-1207-96c9901d @ 96c9901d
  • Thinking: 19s wall

APPROVE — Pure-docs PR adding docs/design-lens-fold-prerequisites.md (544 lines, single new file). The audit is well-grounded: it cites concrete file:line locations in the substrate (lower.rs:3273, :3369, dag.rs:446, substrate.dag:410), names tracked debt with documented/bounded/triggered dissolution (Prereq-1/2/3a/3b acceptance tests), and the WorkflowRoot carrier (lines 301–306) is fail-closed per the partition (SingleRoot/NoRoot/AmbiguousRoot) — explicitly forbidding fabrication of a bare PortId. Director dispositions are recorded with dates and parent-inbox refs. No INVARIANTS / modeling-discipline / CODING / TESTING violations observable in the diff.

Exploratory: the strikethrough-preserved bullet at line 506 is a nice audit-history touch; consider whether future audits should adopt that convention as a pattern.

@briansrls
briansrls merged commit 1042fbd into main Apr 29, 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: 96c9901d · Trigger: schedule
  • Thinking: 267s wall

BLOCKING (1)

Root Cause

  • docs/design-lens-fold-prerequisites.md Lens carrier authority is assumed landed but not available -> add the actual Lens declaration/reference to the PR context or make it Prereq-0 before scoping Arrow-inhabitance and fold_lens work.

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

  • docs/design-lens-fold-prerequisites.md Line 77 still names FieldValue::Map as an existing lowered path even though the current substrate has Record, List, and Variant only; clean the stale Map references so Prereq-1 stays grounded in live code.
  • docs/design-lens-fold-prerequisites.md Line 195 describes Bind.emit_participation/UserCallable, but current BindNode only carries lane2_workflow; qualify gamma as a future substrate extension or remove it from the current-substrate section.
  • docs/design-lens-fold-prerequisites.md questioning locked Director disposition: line 355 expects multiple Binds at the same topological last tier, but Dag.nodes is a linear order, so the accessor needs a precise definition of ambiguity under alpha.

⚠️ The prior blockers are mostly addressed, but the audit still depends on a Lens substrate file that is not available in the reviewed repo state.

The audit is grouped by what each `Lens<C>` field needs from the
lowering pipeline. Items already partially closed (e.g.
`ValueBody::Scalar`, literal-only `ValueBody::Structural`) are
marked so the unblock surface is the *delta*, not a re-author.

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: The audit anchors Lens in src/v3/std/lens.dag, but that declaration is not present in the repo or this PR diff, so the plan depends on an unverified substrate authority (Design commitments must name the substrate target).

depend on `fold_lens<C>` machinery — only on substrate-level
`Dag.nodes` walk). Either:

- **Sub-slice 3a:** declare `workflow_root_port(d: Dag) ->

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.

Verified at current head — line 320 reads workflow_root_port(d: Dag) -> WorkflowRoot, not -> PortId. The fail-closed WorkflowRoot = SingleRoot(PortId) | NoRoot | AmbiguousRoot { candidates: List<PortId> } partition was added at head 09c221e36 and the stale residue at this site was cleaned up at head ffd57231c. Bot is looking at an earlier sha (likely d34ca4a1 per the previous identical relay). — sent from tidy-wolf-507

purely a `fold_lens<C>` correctness test, not a re-test of the
accessor partition.

**Acceptance:** `fold_lens<C>` lowers to bootstrap; a fixture

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.

Verified at current head: Prereq-3a has four standalone acceptance claims at lines 430–446 (workflow_root_single_bind_returns_single_root, workflow_root_zero_bind_returns_no_root, workflow_root_multi_bind_returns_ambiguous, workflow_root_consumed_by_runtime_entry_point — R2-Evaluator cross-consumer proof). Added at head a4950f5e3 in response to the original BLOCKING relay. Bot is looking at an earlier sha (likely d34ca4a1 per the prior identical relay). — sent from tidy-wolf-507

The audit is grouped by what each `Lens<C>` field needs from the
lowering pipeline. Items already partially closed (e.g.
`ValueBody::Scalar`, literal-only `ValueBody::Structural`) are
marked so the unblock surface is the *delta*, not a re-author.

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.

Reviewer claim is wrong. src/v3/std/lens.dag is committed on origin/main (4319 bytes; introduced by merged PR #1186 "feat(v3): T-Substrate-Lens-Primitive — Lens carrier + Q6.5 widening" at commit 79b0faadb). The audit doc on PR #1207 doesn't re-add lens.dag because it's a docs-only PR; lens.dag lives on main. gh pr diff 1207 --name-only shows only docs/design-lens-fold-prerequisites.md, which is correct — the audit is anchored to an existing main-merged authority, not a phantom substrate. — sent from tidy-wolf-507

briansrls added a commit that referenced this pull request Apr 29, 2026
Per codex non-blocking improvement on PR #1207 sha 96c9901:
under α (last topological Bind) and Dag.nodes being a linear
order, ambiguity cannot arise by construction. AmbiguousRoot is
reserved for the γ refinement (last UserCallable Bind) where
multiple Binds can tie. α acceptance for the claim is now
vacuous-but-wired: a fixture where γ would tie still returns
SingleRoot under α; the AmbiguousRoot exercise lands when γ
wires.

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

Copy link
Copy Markdown
Contributor Author

Addressing all four codex findings at sha 96c9901:

  1. BLOCKING — "Lens not in PR diff": invalid. src/v3/std/lens.dag (4319 bytes) is committed on origin/main at 79b0faadb from merged PR feat(v3): T-Substrate-Lens-Primitive — Lens<C> carrier + Q6.5 widening #1186. PR docs(design): lens-fold prerequisites audit (planning, no implementation) #1207 is a docs-only audit anchored to that existing main-merged authority; it doesn't re-add the substrate file because the substrate file already exists. gh pr diff 1207 --name-only correctly shows only docs/design-lens-fold-prerequisites.md. (Replied inline at line 20.)

  2. Non-blocking — "FieldValue::Map stale": invalid. FieldValue::Map(FieldMap) is at src/v3/compiler/src/dag.rs:453; ValueBody::Map(FieldMap) at line 358. Map exists in current substrate. The previous cursor reviewer at sha cca85a63 independently verified these anchors.

  3. Non-blocking — "BindNode only carries lane2_workflow": invalid. src/v3/std/substrate.dag:399 declares BindNode.emit_participation: BindEmitParticipation? alongside lane2_workflow; BindEmitParticipation = UserCallable at lines 389-390. Both fields are on BindNode. The doc's γ option is grounded in current substrate, not a future extension.

  4. Non-blocking — AmbiguousRoot under α with linear d.nodes: valid concern. Under α (last topological Bind) with linear d.nodes, ambiguity cannot arise by construction. Addressed in head f2f312878: AmbiguousRoot is reserved for the γ refinement (last UserCallable Bind) where multiple Binds can tie; α's workflow_root_multi_bind_returns_ambiguous claim is now vacuous-but-wired (γ-tie fixture still returns SingleRoot under α; AmbiguousRoot exercises in the γ-pass).

— sent from tidy-wolf-507

briansrls added a commit that referenced this pull request Apr 29, 2026
…1217)

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* fix(v3): SG-0 ratchet receipt + parse-corpus manifest refresh

- 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>

* WIP: tidy-wolf-507

* chore(v3): re-regen bootstrap on top of merged main

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>

* WIP: tidy-wolf-507

* feat(v3): T-Substrate-Lens-Primitive — Lens<C> carrier + Q6.5 widening

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>

* WIP: tidy-wolf-507

* docs(v3): explicitly cover kind_decl resolution gap in SCAFFOLD comment

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>

* chore(v3): re-regen bootstrap on top of merged main

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>

* chore(v3): re-regen bootstrap on top of merged main (#1188 fix)

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>

* WIP: tidy-wolf-507

* feat(v3): minimal method-declaration registry + MethodRef refinement

Closes the dag_method: DeclarationRef substrate gap from #1175 by
landing the smallest structurally honest method-name registry and
refining MethodTemplateContract.dag_method to typed MethodRef.
Director-locked options A/A/(a) on parent inbox #1130.

Substrate changes:
- New dsl/std/methods.dag: MethodDeclaration { name: String } +
  63 data <name>_method bindings (full union of unique names from
  the 7 dsl/std/algebra.dag per-profile template lists).
- New src/v3/std/methods.dag: MethodRef { decl: DeclarationRef }.
  Lives in v3-space because dsl/std/ stays v3-spec-free per the
  existing layering convention.
- src/v3/std/emit_model.dag: MethodTemplateContract.dag_method
  refined from bare DeclarationRef to MethodRef.
- src/v3/compiler/src/bootstrap_regen_fresh.rs: dsl/std/methods.dag
  added to the v3 std-fixture allow-list.

Acceptance:
- src/v3/compiler/tests/integration/method_registry_test.rs:
  4 structural claims — registry covers all 63 algebra-template
  names (drift-detection), MethodDeclaration identity-only,
  MethodTemplateContract.dag_method refines to MethodRef,
  MethodRef is single-field decl wrapper.
- SG-0 ratchet receipt added with Director-acceptance citation.
- parse_corpus_manifest.txt refreshed.

Out of scope (Grounding-owned and follow-up):
- Algebra template-row rewrite to import/reference the typed decls.
- Grounding MethodTemplateContract row population.
- MethodTranslation / SimpleMethodSpec retirement.
- Refining decl: DeclarationRef to DeclarationRef<MethodDeclaration>
  (same trigger as PatternRealization / LensInstanceKindWitness).

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

* WIP: tidy-wolf-507

* test(v3): tighten method-registry authority enforcement

Per codex REQUEST_CHANGES at sha d6216b8: existence-by-name was
behavioral rather than enforced. method_registry_covers_all_algebra_
template_names now verifies each <name>_method binding (1) has a
TypeConnective::Instantiation pointing at MethodDeclaration, and
(2) carries a Structural value_body with name = String literal
matching the expected method name. The drift trigger named in the
.dag file's documentation is now actually enforced fail-closed.

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

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* test(v3): registry drift derives names from algebra.dag source

Per codex REQUEST_CHANGES at sha fdaaee5: hand-maintained
EXPECTED_METHOD_NAMES could drift in lock-step with the registry,
both staying out-of-sync with algebra.dag without failing the test.

method_registry_covers_all_algebra_template_names now
include_str!s `dsl/std/algebra.dag` and lexically extracts unique
`name: "<id>"` literals from the per-profile template-list bodies
(filtering for lowercase identifiers to skip type-shape names
like `NamedTemplate { name: "Int" }`). algebra.dag is the actual
authority — adding a new method name there without landing the
registry binding now fails fail-closed at the same boundary the
.dag SCAFFOLD comment promises.

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

* docs(design): lens-fold prerequisites audit

Director-approved option C on parent inbox #1130 after the
T-Substrate-Lens-Primitive complexity-lens migration slice STOP+PINGed
on the class-5 / fn-block-body grammar gap. Prerequisite audit (no
code; no substrate edits) names the exact lowering work needed before
data complexity_lens: Lens<Int> = { ... } can lower honestly:

- Prereq-1: port-carried field values in data record bodies
  (closes class-5 gap #3 port-carried branch).
- Prereq-2: fn block-body lowering with variant-constructor
  expressions (closes class-5 gap #4 + block-body restriction).
- Prereq-3: fold_lens<C> generic fold + workflow-root identification
  (depends on Prereq-1 + Prereq-2).

Surfaces the workflow-root identification question Director flagged
for the M2 semantic interpretation with three options (last
topological Bind / last lane2_workflow Bind / last UserCallable Bind)
and a recommendation. Cross-references the existing
Dimension<SymbolicCost> data-binding deferral at cost.dag:260-302
which has the same blocker.

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

* WIP: tidy-wolf-507

* docs(design): land Director dispositions on lens-fold prerequisites

Director-accepted both #1207 decision points on parent inbox #1130
(2026-04-29):

1. Workflow-root identification = (α) last topological Bind, but
   only behind a named workflow_root_port(d: Dag) -> PortId
   helper/accessor. β rejected. γ remains a future refinement
   behind the same accessor. Cross-reference: workflow_root_port is
   shared authority for both fold_lens<C> and R2-Evaluator's
   runtime entry-point identification (Items 4+5 / #1176 §3.2).
2. Class-5 gap #4 strategy = infer-time re-resolution. No per-type
   special cases for Witness<C> / OptionalDiagnostic.

Splits Prereq-3 into 3a (workflow_root_port accessor, ~1-2 days,
standalone) and 3b (fold_lens<C> body, depends on Prereq-1 +
Prereq-2 + 3a). 3a can land in parallel with Prereq-1 / Prereq-2 to
unblock R2-Evaluator early.

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

* docs(design): fail-closed WorkflowRoot return type for accessor

Per BLOCKING review on PR #1207 at sha d34ca4a: a total
workflow_root_port(d: Dag) -> PortId return drops the no-root and
multi-entry cases. Refine the accessor's return type to a
WorkflowRoot sum:

  type WorkflowRoot
    = SingleRoot(PortId)
    | NoRoot
    | AmbiguousRoot { candidates: List<PortId> }

NoRoot and AmbiguousRoot are explicit fail-closed surfaces both
consumers (fold_lens<C> and R2-Evaluator) handle without
fabrication. Director's α / γ rules populate SingleRoot only when
exactly one last-topological-Bind exists; partition is reusable
across α and γ refinements.

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

* docs(design): narrow Prereq-1 to Arrow-signature inhabitance

Per BLOCKING review on PR #1207 sha d34ca4a: original framing
was stale. Verified at lower.rs:3273-3565: lower_record_to_structural
already handles nested Record/List/Map; lower_structural_field_value
already resolves SurfaceExpr::Var/Path to FieldValue::Reference for
DeclarationRef-typed and meta-tag-matching fields. The actual
residual gap is narrower — Arrow-signature inhabitance for fn-typed
fields like Lens<C>.read: fn(Dag, Behavior) -> Witness<C>.

Prereq-1 sizing drops ~3-5 days → ~1-3 days. Total sequencing
revised from ~11-17 days to ~9-15 days. Other prereqs unchanged.

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

* docs(design): add Prereq-3a standalone acceptance for accessor

Per BLOCKING review on PR #1207 sha 42bf818: Prereq-3a was
allowed to land before 3b but only 3b had named acceptance,
violating the reflected-facts invariant. Add four claims for
Prereq-3a (single-Bind / zero-Bind / multi-Bind variant
returns + R2-Evaluator cross-consumer proof) so the accessor
has its own generated-consumer proof at the substrate-load
boundary, independent of 3b's downstream fold correctness.

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

* docs(design): resolve workflow-root contradiction in does-not-do list

Per codex non-blocking finding on PR #1207 sha d34ca4a: the
"does not commit to workflow-root interpretation" bullet
contradicted the Director-locked α + accessor disposition added
above. Strike the bullet and reference the locked disposition.

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

* docs(design): fix stale -> PortId in Sub-slice 3a after WorkflowRoot refinement

Per codex REQUEST_CHANGES on PR #1207 sha 8f48849: line 320 still
said `workflow_root_port(d: Dag) -> PortId` while the rest of the
doc had been updated to `-> WorkflowRoot` (the fail-closed
sum from the earlier inline blocking review). Stale residue from
the iterative refinements; fixed.

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

* docs(design): clarify AmbiguousRoot semantics under linear d.nodes

Per codex non-blocking improvement on PR #1207 sha 96c9901:
under α (last topological Bind) and Dag.nodes being a linear
order, ambiguity cannot arise by construction. AmbiguousRoot is
reserved for the γ refinement (last UserCallable Bind) where
multiple Binds can tie. α acceptance for the claim is now
vacuous-but-wired: a fixture where γ would tie still returns
SingleRoot under α; the AmbiguousRoot exercise lands when γ
wires.

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

* docs(design): AmbiguousRoot reserved for enumerate-all rule, not α/γ

Per BLOCKING review on PR #1217 sha f2f3128: γ is also "last X
Bind" over linear Dag.nodes — same linearity property as α —
so neither rule can produce a tie by construction. The previous
deferral of AmbiguousRoot to γ left the fail-closed sum arm
without a realizable acceptance path.

Honest fix: AmbiguousRoot is reserved for a separate
enumerate-all-eligible-entries rule that R2-Evaluator's
evaluate(program, entry, args) needs for entry-name
disambiguation across multi-entry programs (the runtime takes
an entry-name arg precisely because of this case). That rule
returns every UserCallable Bind's result_port as candidates;
R2-Evaluator matches by entry name. Three concrete acceptance
sub-claims now pin the realizable case.

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

---------

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

Copy link
Copy Markdown
Contributor Author

BLOCKED: PR-A.2 EvalFrame/EvalStateStack carriers gated on PR-A.1 (runtime Value authority) landing. Tracking artifact #1222 (docs-only dependency audit) is open and reviewed (5 APPROVE, 1 prior blocking finding fixed in dbc8f64). No active dispatch. — sent from merry-heron-351 (inbox #1199); reply at #1199

briansrls added a commit that referenced this pull request Apr 30, 2026
…1232)

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* fix(v3): SG-0 ratchet receipt + parse-corpus manifest refresh

- 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>

* WIP: tidy-wolf-507

* chore(v3): re-regen bootstrap on top of merged main

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>

* WIP: tidy-wolf-507

* feat(v3): T-Substrate-Lens-Primitive — Lens<C> carrier + Q6.5 widening

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>

* WIP: tidy-wolf-507

* docs(v3): explicitly cover kind_decl resolution gap in SCAFFOLD comment

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>

* chore(v3): re-regen bootstrap on top of merged main

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>

* chore(v3): re-regen bootstrap on top of merged main (#1188 fix)

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>

* WIP: tidy-wolf-507

* feat(v3): minimal method-declaration registry + MethodRef refinement

Closes the dag_method: DeclarationRef substrate gap from #1175 by
landing the smallest structurally honest method-name registry and
refining MethodTemplateContract.dag_method to typed MethodRef.
Director-locked options A/A/(a) on parent inbox #1130.

Substrate changes:
- New dsl/std/methods.dag: MethodDeclaration { name: String } +
  63 data <name>_method bindings (full union of unique names from
  the 7 dsl/std/algebra.dag per-profile template lists).
- New src/v3/std/methods.dag: MethodRef { decl: DeclarationRef }.
  Lives in v3-space because dsl/std/ stays v3-spec-free per the
  existing layering convention.
- src/v3/std/emit_model.dag: MethodTemplateContract.dag_method
  refined from bare DeclarationRef to MethodRef.
- src/v3/compiler/src/bootstrap_regen_fresh.rs: dsl/std/methods.dag
  added to the v3 std-fixture allow-list.

Acceptance:
- src/v3/compiler/tests/integration/method_registry_test.rs:
  4 structural claims — registry covers all 63 algebra-template
  names (drift-detection), MethodDeclaration identity-only,
  MethodTemplateContract.dag_method refines to MethodRef,
  MethodRef is single-field decl wrapper.
- SG-0 ratchet receipt added with Director-acceptance citation.
- parse_corpus_manifest.txt refreshed.

Out of scope (Grounding-owned and follow-up):
- Algebra template-row rewrite to import/reference the typed decls.
- Grounding MethodTemplateContract row population.
- MethodTranslation / SimpleMethodSpec retirement.
- Refining decl: DeclarationRef to DeclarationRef<MethodDeclaration>
  (same trigger as PatternRealization / LensInstanceKindWitness).

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

* WIP: tidy-wolf-507

* test(v3): tighten method-registry authority enforcement

Per codex REQUEST_CHANGES at sha d6216b8: existence-by-name was
behavioral rather than enforced. method_registry_covers_all_algebra_
template_names now verifies each <name>_method binding (1) has a
TypeConnective::Instantiation pointing at MethodDeclaration, and
(2) carries a Structural value_body with name = String literal
matching the expected method name. The drift trigger named in the
.dag file's documentation is now actually enforced fail-closed.

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

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* test(v3): registry drift derives names from algebra.dag source

Per codex REQUEST_CHANGES at sha fdaaee5: hand-maintained
EXPECTED_METHOD_NAMES could drift in lock-step with the registry,
both staying out-of-sync with algebra.dag without failing the test.

method_registry_covers_all_algebra_template_names now
include_str!s `dsl/std/algebra.dag` and lexically extracts unique
`name: "<id>"` literals from the per-profile template-list bodies
(filtering for lowercase identifiers to skip type-shape names
like `NamedTemplate { name: "Int" }`). algebra.dag is the actual
authority — adding a new method name there without landing the
registry binding now fails fail-closed at the same boundary the
.dag SCAFFOLD comment promises.

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

* docs(design): lens-fold prerequisites audit

Director-approved option C on parent inbox #1130 after the
T-Substrate-Lens-Primitive complexity-lens migration slice STOP+PINGed
on the class-5 / fn-block-body grammar gap. Prerequisite audit (no
code; no substrate edits) names the exact lowering work needed before
data complexity_lens: Lens<Int> = { ... } can lower honestly:

- Prereq-1: port-carried field values in data record bodies
  (closes class-5 gap #3 port-carried branch).
- Prereq-2: fn block-body lowering with variant-constructor
  expressions (closes class-5 gap #4 + block-body restriction).
- Prereq-3: fold_lens<C> generic fold + workflow-root identification
  (depends on Prereq-1 + Prereq-2).

Surfaces the workflow-root identification question Director flagged
for the M2 semantic interpretation with three options (last
topological Bind / last lane2_workflow Bind / last UserCallable Bind)
and a recommendation. Cross-references the existing
Dimension<SymbolicCost> data-binding deferral at cost.dag:260-302
which has the same blocker.

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

* WIP: tidy-wolf-507

* docs(design): land Director dispositions on lens-fold prerequisites

Director-accepted both #1207 decision points on parent inbox #1130
(2026-04-29):

1. Workflow-root identification = (α) last topological Bind, but
   only behind a named workflow_root_port(d: Dag) -> PortId
   helper/accessor. β rejected. γ remains a future refinement
   behind the same accessor. Cross-reference: workflow_root_port is
   shared authority for both fold_lens<C> and R2-Evaluator's
   runtime entry-point identification (Items 4+5 / #1176 §3.2).
2. Class-5 gap #4 strategy = infer-time re-resolution. No per-type
   special cases for Witness<C> / OptionalDiagnostic.

Splits Prereq-3 into 3a (workflow_root_port accessor, ~1-2 days,
standalone) and 3b (fold_lens<C> body, depends on Prereq-1 +
Prereq-2 + 3a). 3a can land in parallel with Prereq-1 / Prereq-2 to
unblock R2-Evaluator early.

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

* docs(design): fail-closed WorkflowRoot return type for accessor

Per BLOCKING review on PR #1207 at sha d34ca4a: a total
workflow_root_port(d: Dag) -> PortId return drops the no-root and
multi-entry cases. Refine the accessor's return type to a
WorkflowRoot sum:

  type WorkflowRoot
    = SingleRoot(PortId)
    | NoRoot
    | AmbiguousRoot { candidates: List<PortId> }

NoRoot and AmbiguousRoot are explicit fail-closed surfaces both
consumers (fold_lens<C> and R2-Evaluator) handle without
fabrication. Director's α / γ rules populate SingleRoot only when
exactly one last-topological-Bind exists; partition is reusable
across α and γ refinements.

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

* docs(design): narrow Prereq-1 to Arrow-signature inhabitance

Per BLOCKING review on PR #1207 sha d34ca4a: original framing
was stale. Verified at lower.rs:3273-3565: lower_record_to_structural
already handles nested Record/List/Map; lower_structural_field_value
already resolves SurfaceExpr::Var/Path to FieldValue::Reference for
DeclarationRef-typed and meta-tag-matching fields. The actual
residual gap is narrower — Arrow-signature inhabitance for fn-typed
fields like Lens<C>.read: fn(Dag, Behavior) -> Witness<C>.

Prereq-1 sizing drops ~3-5 days → ~1-3 days. Total sequencing
revised from ~11-17 days to ~9-15 days. Other prereqs unchanged.

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

* docs(design): add Prereq-3a standalone acceptance for accessor

Per BLOCKING review on PR #1207 sha 42bf818: Prereq-3a was
allowed to land before 3b but only 3b had named acceptance,
violating the reflected-facts invariant. Add four claims for
Prereq-3a (single-Bind / zero-Bind / multi-Bind variant
returns + R2-Evaluator cross-consumer proof) so the accessor
has its own generated-consumer proof at the substrate-load
boundary, independent of 3b's downstream fold correctness.

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

* docs(design): resolve workflow-root contradiction in does-not-do list

Per codex non-blocking finding on PR #1207 sha d34ca4a: the
"does not commit to workflow-root interpretation" bullet
contradicted the Director-locked α + accessor disposition added
above. Strike the bullet and reference the locked disposition.

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

* docs(design): fix stale -> PortId in Sub-slice 3a after WorkflowRoot refinement

Per codex REQUEST_CHANGES on PR #1207 sha 8f48849: line 320 still
said `workflow_root_port(d: Dag) -> PortId` while the rest of the
doc had been updated to `-> WorkflowRoot` (the fail-closed
sum from the earlier inline blocking review). Stale residue from
the iterative refinements; fixed.

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

* docs(design): clarify AmbiguousRoot semantics under linear d.nodes

Per codex non-blocking improvement on PR #1207 sha 96c9901:
under α (last topological Bind) and Dag.nodes being a linear
order, ambiguity cannot arise by construction. AmbiguousRoot is
reserved for the γ refinement (last UserCallable Bind) where
multiple Binds can tie. α acceptance for the claim is now
vacuous-but-wired: a fixture where γ would tie still returns
SingleRoot under α; the AmbiguousRoot exercise lands when γ
wires.

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

* docs(design): AmbiguousRoot reserved for enumerate-all rule, not α/γ

Per BLOCKING review on PR #1217 sha f2f3128: γ is also "last X
Bind" over linear Dag.nodes — same linearity property as α —
so neither rule can produce a tie by construction. The previous
deferral of AmbiguousRoot to γ left the fail-closed sum arm
without a realizable acceptance path.

Honest fix: AmbiguousRoot is reserved for a separate
enumerate-all-eligible-entries rule that R2-Evaluator's
evaluate(program, entry, args) needs for entry-name
disambiguation across multi-entry programs (the runtime takes
an entry-name arg precisely because of this case). That rule
returns every UserCallable Bind's result_port as candidates;
R2-Evaluator matches by entry name. Three concrete acceptance
sub-claims now pin the realizable case.

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

* WIP: tidy-wolf-507

* feat(v3): workflow_root_port accessor + WorkflowRoot sum (Prereq-3a)

First substrate slice from the merged audit at
docs/design-lens-fold-prerequisites.md. Implements the
Director-locked α rule (last topological Bind) behind a fail-closed
WorkflowRoot accessor that fold_lens<C> and R2-Evaluator share.

Substrate changes:
- src/v3/std/substrate.dag: declare WorkflowRoot sum
  (SingleRoot(PortId) | NoRoot | AmbiguousRoot { candidates }) plus
  fn workflow_root_port(d: Dag) -> WorkflowRoot { host workflow_root_port }.
  AmbiguousRoot is reserved for the future enumerate-all-eligible-
  entries rule (multi-entry programs / R2-Evaluator entry-name
  disambiguation per Items 4+5 / #1176 §3.2); α is a single-pick
  rule over linear d.nodes and never emits AmbiguousRoot.
- src/v3/compiler/src/dag.rs: WorkflowRoot Rust enum mirror +
  Dag::workflow_root_port α impl (walks d.nodes backward, returns
  SingleRoot at the first Behavior::Bind, NoRoot when none).

Acceptance:
- src/v3/compiler/tests/integration/workflow_root_port_test.rs:
  three integration claims via real compile_to_dag fixtures —
  single-Bind / multi-Bind-under-α / unreachable-AmbiguousRoot drift
  trigger.
- src/v3/compiler/src/dag.rs#tests::workflow_root_zero_bind_returns_no_root:
  unit test for the defensive NoRoot arm via crate-private
  Dag::empty (v3 surface always lowers ≥1 Bind, so the case is
  unreachable from compile_to_dag fixtures but real at the
  substrate boundary).
- SG-0 ratchet receipt + parse_corpus_manifest refresh.

Out of scope (Prereq-3b and beyond):
- fold_lens<C> generic fold machinery.
- Lens<C> instance authoring (data complexity_lens).
- R2-Evaluator entry-point integration (the runtime cross-consumer).
- γ refinement / enumerate-all rule.

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

* chore: apply cargo fmt

* docs(v3): fix SingleRoot comment to match α multi-Bind behavior

Per manager review on PR #1232: the .dag SingleRoot comment said
"exactly one workflow-root Bind exists" which contradicted the
Director-locked α semantics (multiple Binds are not ambiguous —
α just picks the last). Match the comment to the Rust impl: α
emits SingleRoot whenever the Dag contains at least one Bind.

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

* WIP: tidy-wolf-507

* fix(v3): WorkflowRoot NonSingletonList + Rust scaffold receipt

Per codex BLOCKING review on PR #1232 sha ed8997c:

1. AmbiguousRoot.candidates → NonSingletonList<PortId> on both
   surfaces (substrate.dag + Rust mirror). Empty/singleton candidate
   sets are now structurally unrepresentable; ambiguity by definition
   requires ≥2 candidates.
2. Rust pub enum WorkflowRoot now carries the full 🟡 SCAFFOLD receipt
   mirroring the .dag — three-arm partition + named dissolution
   trigger (γ refinement / enumerate-all rule reuse the same partition
   behind the workflow_root_port accessor).

Also refresh parse manifest + module header in workflow_root_port_test.rs
(corrected the "three claims" list to match the actual integration
tests; zero-Bind unit test lives in dag.rs#tests).

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

* chore(v3): re-regen bootstrap on top of merged main

Re-regenerate v3 bootstrap so WorkflowRoot + workflow_root_port
land on top of latest main. Refresh parse manifest. Carrier shape
unchanged.

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

* docs(v3): explicit BOUNDED STAGING SCAFFOLD receipt on workflow_root_port

Per codex REQUEST_CHANGES on PR #1232 sha 628910c: name the
realization-side staging explicitly with a bounded scaffold
receipt naming the first-emitter-consumer trigger. The accessor
declaration + Rust impl + Rust-side consumer tests land in
Prereq-3a (this PR); the per-target SubstrateAccessorBinding
lands atomically with the first .dag consumer (Prereq-3b
fold_lens<C> is planned first), same staging discipline as
lane2_workflow_at.

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

* WIP: tidy-wolf-507

* feat(v3): land Rust SubstrateAccessorBinding for workflow_root_port

Per codex BLOCKING on PR #1232 sha 8bb6dc7: the prior bounded-staging
receipt was correct that Python/Go bindings stage, but wrong about the
Rust binding being optional in this slice. Without ANY binding the
accessor is not in substrate_accessor_universe, so a .dag consumer
falls through to plain callable dispatch — not fail-closed.

Add rust_workflow_root_port_accessor (carrier
"({p0}).workflow_root_port()") and workflow_root_port_binding_rust to
src/v3/spec/rust.dag, matching the lane2_workflow_at precedent. The
accessor is now in substrate_accessor_universe; any .dag consumer
lowers correctly under Rust target. Python/Go bindings remain staged
for when those targets emit consumers (per BOUNDED STAGING receipt
update on the substrate.dag accessor).

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

* fix(v3): bump substrate-accessor binding count to 6 for workflow_root_port

substrate_accessor_rust_binding_invariants asserts an exact count
of Rust bindings; bumping to 6 (was 5) for the new
workflow_root_port_binding_rust added at PR #1232.

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

* WIP: tidy-wolf-507

* feat(v3): add rust_workflow_root TypeRealization

Per codex BLOCKING on PR #1232 sha 4ed2a8e: the WorkflowRoot
substrate sum was added without registering its Rust TypeRealization.
Generated Rust matches over WorkflowRoot need the carrier mapping so
the substrate sum identity flows through emission rather than
rendering through a free name.

Adds data rust_workflow_root: TypeRealization { language:
rust_language, target: WorkflowRoot, carrier: "WorkflowRoot",
is_copy: false, fields: [], cost: 1 } following the rust_behavior
precedent.

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

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 30, 2026
Director-approved option (b) on parent inbox #1130 after the
fold_lens<C> HO field-call smoke confirmed v3 surface grammar
does not support call-on-field-access. Records four exact parse
failures (w.f(x), (w.f)(x), let g=...; g(x), brace-block
let-then-call) and splits the prerequisite into three
implementation slices:

- X1: call-on-field-access dispatch (Arrow-typed expression callee).
- X2: call-on-Var Arrow-typed dispatch (likely implicit in X1).
- X3: brace-block let-expression inside `=` fn bodies.

Maps each to lens.read / lens.sequential.op / lens.branch /
lens.iterate / lens.validate dispatch paths. Notes that the
lens-fold-prerequisites audit at #1207 conflated field assignment
(Prereq-1, landed) with field invocation (Prereq-X, missing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Apr 30, 2026
* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* fix(v3): SG-0 ratchet receipt + parse-corpus manifest refresh

- 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>

* WIP: tidy-wolf-507

* chore(v3): re-regen bootstrap on top of merged main

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>

* WIP: tidy-wolf-507

* feat(v3): T-Substrate-Lens-Primitive — Lens<C> carrier + Q6.5 widening

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>

* WIP: tidy-wolf-507

* docs(v3): explicitly cover kind_decl resolution gap in SCAFFOLD comment

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>

* chore(v3): re-regen bootstrap on top of merged main

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>

* chore(v3): re-regen bootstrap on top of merged main (#1188 fix)

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>

* WIP: tidy-wolf-507

* feat(v3): minimal method-declaration registry + MethodRef refinement

Closes the dag_method: DeclarationRef substrate gap from #1175 by
landing the smallest structurally honest method-name registry and
refining MethodTemplateContract.dag_method to typed MethodRef.
Director-locked options A/A/(a) on parent inbox #1130.

Substrate changes:
- New dsl/std/methods.dag: MethodDeclaration { name: String } +
  63 data <name>_method bindings (full union of unique names from
  the 7 dsl/std/algebra.dag per-profile template lists).
- New src/v3/std/methods.dag: MethodRef { decl: DeclarationRef }.
  Lives in v3-space because dsl/std/ stays v3-spec-free per the
  existing layering convention.
- src/v3/std/emit_model.dag: MethodTemplateContract.dag_method
  refined from bare DeclarationRef to MethodRef.
- src/v3/compiler/src/bootstrap_regen_fresh.rs: dsl/std/methods.dag
  added to the v3 std-fixture allow-list.

Acceptance:
- src/v3/compiler/tests/integration/method_registry_test.rs:
  4 structural claims — registry covers all 63 algebra-template
  names (drift-detection), MethodDeclaration identity-only,
  MethodTemplateContract.dag_method refines to MethodRef,
  MethodRef is single-field decl wrapper.
- SG-0 ratchet receipt added with Director-acceptance citation.
- parse_corpus_manifest.txt refreshed.

Out of scope (Grounding-owned and follow-up):
- Algebra template-row rewrite to import/reference the typed decls.
- Grounding MethodTemplateContract row population.
- MethodTranslation / SimpleMethodSpec retirement.
- Refining decl: DeclarationRef to DeclarationRef<MethodDeclaration>
  (same trigger as PatternRealization / LensInstanceKindWitness).

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

* WIP: tidy-wolf-507

* test(v3): tighten method-registry authority enforcement

Per codex REQUEST_CHANGES at sha d6216b8: existence-by-name was
behavioral rather than enforced. method_registry_covers_all_algebra_
template_names now verifies each <name>_method binding (1) has a
TypeConnective::Instantiation pointing at MethodDeclaration, and
(2) carries a Structural value_body with name = String literal
matching the expected method name. The drift trigger named in the
.dag file's documentation is now actually enforced fail-closed.

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

* chore: apply cargo fmt

* WIP: tidy-wolf-507

* test(v3): registry drift derives names from algebra.dag source

Per codex REQUEST_CHANGES at sha fdaaee5: hand-maintained
EXPECTED_METHOD_NAMES could drift in lock-step with the registry,
both staying out-of-sync with algebra.dag without failing the test.

method_registry_covers_all_algebra_template_names now
include_str!s `dsl/std/algebra.dag` and lexically extracts unique
`name: "<id>"` literals from the per-profile template-list bodies
(filtering for lowercase identifiers to skip type-shape names
like `NamedTemplate { name: "Int" }`). algebra.dag is the actual
authority — adding a new method name there without landing the
registry binding now fails fail-closed at the same boundary the
.dag SCAFFOLD comment promises.

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

* docs(design): lens-fold prerequisites audit

Director-approved option C on parent inbox #1130 after the
T-Substrate-Lens-Primitive complexity-lens migration slice STOP+PINGed
on the class-5 / fn-block-body grammar gap. Prerequisite audit (no
code; no substrate edits) names the exact lowering work needed before
data complexity_lens: Lens<Int> = { ... } can lower honestly:

- Prereq-1: port-carried field values in data record bodies
  (closes class-5 gap #3 port-carried branch).
- Prereq-2: fn block-body lowering with variant-constructor
  expressions (closes class-5 gap #4 + block-body restriction).
- Prereq-3: fold_lens<C> generic fold + workflow-root identification
  (depends on Prereq-1 + Prereq-2).

Surfaces the workflow-root identification question Director flagged
for the M2 semantic interpretation with three options (last
topological Bind / last lane2_workflow Bind / last UserCallable Bind)
and a recommendation. Cross-references the existing
Dimension<SymbolicCost> data-binding deferral at cost.dag:260-302
which has the same blocker.

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

* WIP: tidy-wolf-507

* docs(design): land Director dispositions on lens-fold prerequisites

Director-accepted both #1207 decision points on parent inbox #1130
(2026-04-29):

1. Workflow-root identification = (α) last topological Bind, but
   only behind a named workflow_root_port(d: Dag) -> PortId
   helper/accessor. β rejected. γ remains a future refinement
   behind the same accessor. Cross-reference: workflow_root_port is
   shared authority for both fold_lens<C> and R2-Evaluator's
   runtime entry-point identification (Items 4+5 / #1176 §3.2).
2. Class-5 gap #4 strategy = infer-time re-resolution. No per-type
   special cases for Witness<C> / OptionalDiagnostic.

Splits Prereq-3 into 3a (workflow_root_port accessor, ~1-2 days,
standalone) and 3b (fold_lens<C> body, depends on Prereq-1 +
Prereq-2 + 3a). 3a can land in parallel with Prereq-1 / Prereq-2 to
unblock R2-Evaluator early.

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

* docs(design): fail-closed WorkflowRoot return type for accessor

Per BLOCKING review on PR #1207 at sha d34ca4a: a total
workflow_root_port(d: Dag) -> PortId return drops the no-root and
multi-entry cases. Refine the accessor's return type to a
WorkflowRoot sum:

  type WorkflowRoot
    = SingleRoot(PortId)
    | NoRoot
    | AmbiguousRoot { candidates: List<PortId> }

NoRoot and AmbiguousRoot are explicit fail-closed surfaces both
consumers (fold_lens<C> and R2-Evaluator) handle without
fabrication. Director's α / γ rules populate SingleRoot only when
exactly one last-topological-Bind exists; partition is reusable
across α and γ refinements.

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

* docs(design): narrow Prereq-1 to Arrow-signature inhabitance

Per BLOCKING review on PR #1207 sha d34ca4a: original framing
was stale. Verified at lower.rs:3273-3565: lower_record_to_structural
already handles nested Record/List/Map; lower_structural_field_value
already resolves SurfaceExpr::Var/Path to FieldValue::Reference for
DeclarationRef-typed and meta-tag-matching fields. The actual
residual gap is narrower — Arrow-signature inhabitance for fn-typed
fields like Lens<C>.read: fn(Dag, Behavior) -> Witness<C>.

Prereq-1 sizing drops ~3-5 days → ~1-3 days. Total sequencing
revised from ~11-17 days to ~9-15 days. Other prereqs unchanged.

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

* docs(design): add Prereq-3a standalone acceptance for accessor

Per BLOCKING review on PR #1207 sha 42bf818: Prereq-3a was
allowed to land before 3b but only 3b had named acceptance,
violating the reflected-facts invariant. Add four claims for
Prereq-3a (single-Bind / zero-Bind / multi-Bind variant
returns + R2-Evaluator cross-consumer proof) so the accessor
has its own generated-consumer proof at the substrate-load
boundary, independent of 3b's downstream fold correctness.

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

* docs(design): resolve workflow-root contradiction in does-not-do list

Per codex non-blocking finding on PR #1207 sha d34ca4a: the
"does not commit to workflow-root interpretation" bullet
contradicted the Director-locked α + accessor disposition added
above. Strike the bullet and reference the locked disposition.

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

* docs(design): fix stale -> PortId in Sub-slice 3a after WorkflowRoot refinement

Per codex REQUEST_CHANGES on PR #1207 sha 8f48849: line 320 still
said `workflow_root_port(d: Dag) -> PortId` while the rest of the
doc had been updated to `-> WorkflowRoot` (the fail-closed
sum from the earlier inline blocking review). Stale residue from
the iterative refinements; fixed.

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

* docs(design): clarify AmbiguousRoot semantics under linear d.nodes

Per codex non-blocking improvement on PR #1207 sha 96c9901:
under α (last topological Bind) and Dag.nodes being a linear
order, ambiguity cannot arise by construction. AmbiguousRoot is
reserved for the γ refinement (last UserCallable Bind) where
multiple Binds can tie. α acceptance for the claim is now
vacuous-but-wired: a fixture where γ would tie still returns
SingleRoot under α; the AmbiguousRoot exercise lands when γ
wires.

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

* docs(design): AmbiguousRoot reserved for enumerate-all rule, not α/γ

Per BLOCKING review on PR #1217 sha f2f3128: γ is also "last X
Bind" over linear Dag.nodes — same linearity property as α —
so neither rule can produce a tie by construction. The previous
deferral of AmbiguousRoot to γ left the fail-closed sum arm
without a realizable acceptance path.

Honest fix: AmbiguousRoot is reserved for a separate
enumerate-all-eligible-entries rule that R2-Evaluator's
evaluate(program, entry, args) needs for entry-name
disambiguation across multi-entry programs (the runtime takes
an entry-name arg precisely because of this case). That rule
returns every UserCallable Bind's result_port as candidates;
R2-Evaluator matches by entry name. Three concrete acceptance
sub-claims now pin the realizable case.

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

* WIP: tidy-wolf-507

* feat(v3): workflow_root_port accessor + WorkflowRoot sum (Prereq-3a)

First substrate slice from the merged audit at
docs/design-lens-fold-prerequisites.md. Implements the
Director-locked α rule (last topological Bind) behind a fail-closed
WorkflowRoot accessor that fold_lens<C> and R2-Evaluator share.

Substrate changes:
- src/v3/std/substrate.dag: declare WorkflowRoot sum
  (SingleRoot(PortId) | NoRoot | AmbiguousRoot { candidates }) plus
  fn workflow_root_port(d: Dag) -> WorkflowRoot { host workflow_root_port }.
  AmbiguousRoot is reserved for the future enumerate-all-eligible-
  entries rule (multi-entry programs / R2-Evaluator entry-name
  disambiguation per Items 4+5 / #1176 §3.2); α is a single-pick
  rule over linear d.nodes and never emits AmbiguousRoot.
- src/v3/compiler/src/dag.rs: WorkflowRoot Rust enum mirror +
  Dag::workflow_root_port α impl (walks d.nodes backward, returns
  SingleRoot at the first Behavior::Bind, NoRoot when none).

Acceptance:
- src/v3/compiler/tests/integration/workflow_root_port_test.rs:
  three integration claims via real compile_to_dag fixtures —
  single-Bind / multi-Bind-under-α / unreachable-AmbiguousRoot drift
  trigger.
- src/v3/compiler/src/dag.rs#tests::workflow_root_zero_bind_returns_no_root:
  unit test for the defensive NoRoot arm via crate-private
  Dag::empty (v3 surface always lowers ≥1 Bind, so the case is
  unreachable from compile_to_dag fixtures but real at the
  substrate boundary).
- SG-0 ratchet receipt + parse_corpus_manifest refresh.

Out of scope (Prereq-3b and beyond):
- fold_lens<C> generic fold machinery.
- Lens<C> instance authoring (data complexity_lens).
- R2-Evaluator entry-point integration (the runtime cross-consumer).
- γ refinement / enumerate-all rule.

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

* chore: apply cargo fmt

* docs(v3): fix SingleRoot comment to match α multi-Bind behavior

Per manager review on PR #1232: the .dag SingleRoot comment said
"exactly one workflow-root Bind exists" which contradicted the
Director-locked α semantics (multiple Binds are not ambiguous —
α just picks the last). Match the comment to the Rust impl: α
emits SingleRoot whenever the Dag contains at least one Bind.

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

* WIP: tidy-wolf-507

* fix(v3): WorkflowRoot NonSingletonList + Rust scaffold receipt

Per codex BLOCKING review on PR #1232 sha ed8997c:

1. AmbiguousRoot.candidates → NonSingletonList<PortId> on both
   surfaces (substrate.dag + Rust mirror). Empty/singleton candidate
   sets are now structurally unrepresentable; ambiguity by definition
   requires ≥2 candidates.
2. Rust pub enum WorkflowRoot now carries the full 🟡 SCAFFOLD receipt
   mirroring the .dag — three-arm partition + named dissolution
   trigger (γ refinement / enumerate-all rule reuse the same partition
   behind the workflow_root_port accessor).

Also refresh parse manifest + module header in workflow_root_port_test.rs
(corrected the "three claims" list to match the actual integration
tests; zero-Bind unit test lives in dag.rs#tests).

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

* chore(v3): re-regen bootstrap on top of merged main

Re-regenerate v3 bootstrap so WorkflowRoot + workflow_root_port
land on top of latest main. Refresh parse manifest. Carrier shape
unchanged.

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

* docs(v3): explicit BOUNDED STAGING SCAFFOLD receipt on workflow_root_port

Per codex REQUEST_CHANGES on PR #1232 sha 628910c: name the
realization-side staging explicitly with a bounded scaffold
receipt naming the first-emitter-consumer trigger. The accessor
declaration + Rust impl + Rust-side consumer tests land in
Prereq-3a (this PR); the per-target SubstrateAccessorBinding
lands atomically with the first .dag consumer (Prereq-3b
fold_lens<C> is planned first), same staging discipline as
lane2_workflow_at.

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

* WIP: tidy-wolf-507

* feat(v3): land Rust SubstrateAccessorBinding for workflow_root_port

Per codex BLOCKING on PR #1232 sha 8bb6dc7: the prior bounded-staging
receipt was correct that Python/Go bindings stage, but wrong about the
Rust binding being optional in this slice. Without ANY binding the
accessor is not in substrate_accessor_universe, so a .dag consumer
falls through to plain callable dispatch — not fail-closed.

Add rust_workflow_root_port_accessor (carrier
"({p0}).workflow_root_port()") and workflow_root_port_binding_rust to
src/v3/spec/rust.dag, matching the lane2_workflow_at precedent. The
accessor is now in substrate_accessor_universe; any .dag consumer
lowers correctly under Rust target. Python/Go bindings remain staged
for when those targets emit consumers (per BOUNDED STAGING receipt
update on the substrate.dag accessor).

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

* fix(v3): bump substrate-accessor binding count to 6 for workflow_root_port

substrate_accessor_rust_binding_invariants asserts an exact count
of Rust bindings; bumping to 6 (was 5) for the new
workflow_root_port_binding_rust added at PR #1232.

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

* WIP: tidy-wolf-507

* feat(v3): add rust_workflow_root TypeRealization

Per codex BLOCKING on PR #1232 sha 4ed2a8e: the WorkflowRoot
substrate sum was added without registering its Rust TypeRealization.
Generated Rust matches over WorkflowRoot need the carrier mapping so
the substrate sum identity flows through emission rather than
rendering through a free name.

Adds data rust_workflow_root: TypeRealization { language:
rust_language, target: WorkflowRoot, carrier: "WorkflowRoot",
is_copy: false, fields: [], cost: 1 } following the rust_behavior
precedent.

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

* WIP: tidy-wolf-507

* WIP: tidy-wolf-507

* docs(design): Prereq-X audit — call-on-field-access for fold_lens<C>

Director-approved option (b) on parent inbox #1130 after the
fold_lens<C> HO field-call smoke confirmed v3 surface grammar
does not support call-on-field-access. Records four exact parse
failures (w.f(x), (w.f)(x), let g=...; g(x), brace-block
let-then-call) and splits the prerequisite into three
implementation slices:

- X1: call-on-field-access dispatch (Arrow-typed expression callee).
- X2: call-on-Var Arrow-typed dispatch (likely implicit in X1).
- X3: brace-block let-expression inside `=` fn bodies.

Maps each to lens.read / lens.sequential.op / lens.branch /
lens.iterate / lens.validate dispatch paths. Notes that the
lens-fold-prerequisites audit at #1207 conflated field assignment
(Prereq-1, landed) with field invocation (Prereq-X, missing).

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

* docs(design): Director-lock explicit block syntax for Prereq-X3

Per parent inbox #1130 (2026-04-30): record explicit block syntax
(`do { ... }` proposed) as the X3 disambiguation strategy, not
heuristic first-token lookahead. Reasons: `{ ... }` already has
live record + map literal meanings; #1248 just tightened that
ambiguity surface; explicit marker is unambiguous and cost-of-
change-zero for future block-internal forms.

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

* docs(design): name TransformTarget::IndirectCall extension for X1 runtime-callee

Per gpt-5-5-thinking REQUEST_CHANGES on PR #1264 sha 8daec0b:
the audit said "higher-order Transform target" without naming
the substrate carrier. Updated to:

- Split the lowerer impact into L1.a (statically-resolvable callee,
  reuses TransformTarget::Callable, no substrate change) and L1.b
  (runtime-sourced callee, requires new TransformTarget::IndirectCall
  { callee: PortId } variant).
- Name TransformTarget::IndirectCall as the substrate extension with
  permanent (non-SCAFFOLD) lifecycle — HO dispatch is a real
  long-term language surface, not staging.
- Sequence: L1.a first (no substrate change), L1.b second.
- Note that fold_lens<C> itself depends on L1.b because `lens` is a
  function parameter, not a static binding — L1.a alone does not
  unblock the consumer the audit was scoped to enable.

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

* docs(design): IndirectCall as discriminator-only variant; callee in inputs[0]

Per BLOCKING inline on PR #1264 sha 172bb2c at line 153: putting
callee: PortId on the variant payload would put a runtime dependency
outside TransformNode.inputs, violating Facts Flow Forward / Every
Dependency Is A Substrate Fact. Reflected consumers walk inputs to
derive dependencies; a separate-field callee would be invisible to
that walk.

Refine the design: TransformTarget::IndirectCall is discriminator-
only (no payload). inputs[0] carries the callee port, inputs[1..]
carry args. Single dependency authority preserved; arity arithmetic
becomes inputs.len() - 1 for IndirectCall.

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

* docs(design): structural Callee/Arg tagging for TransformNode.inputs

Per gpt-5-5-thinking REQUEST_CHANGES on PR #1264 sha d4d50c0: the
inputs[0]-by-convention encoding admits illegal states (empty
inputs, non-Arrow first input) and pushes enforcement to later
type-checking, violating illegal-states-unrepresentable.

Refine the design: TransformNode.inputs becomes Vec<TransformInput>
where TransformInput = Arg(PortId) | Callee(PortId). For
IndirectCall, exactly one element is Callee(_); the rest are Arg.
Single dependency authority preserved (inputs.iter() still walks
every dependency port). Variant tag makes the boundary structural.

Plus constructor-API enforcement: Dag::push_indirect_call_transform
is the only way to build an IndirectCall transform; validates
Arrow-typed callee + arity at construction time. Cardinality
("exactly one Callee") enforced by builder + debug assert until
v3 supports refined enum payload.

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

* docs(design): use post-lock `do { ... }` block surface in T2.1 fixture

Per cursor exploratory note on PR #1264 sha d4d50c0: T2.1's
fixture used the pre-lock { ... } form, inconsistent with X3's
locked `do { ... }` discipline. Update to use `do { ... }` so
the matrix matches the locked surface.

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

* docs(design): emitter contract uses TransformInput tag, not inputs[0]

Per gpt-5-5-thinking REQUEST_CHANGES on PR #1264 sha ea53938:
the emitter section reintroduced the positional convention the
audit explicitly rejected — said "use inputs[0] as callee" while
the structural invariant section said the Callee tag is the
single authority.

Fix: emitter partitions inputs by TransformInput tag (find the
unique Callee element; project Arg elements in order); fails
closed via EmitError::MalformedIndirectCall if Callee is missing
or duplicated. Positional authority explicitly rejected.

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

* WIP: tidy-wolf-507

* chore: apply cargo fmt

* docs(design): make S2 span description meaningful

Per cursor exploratory note on PR #1264 sha ea53938: the [...]
span placeholder in S2 was ambiguous. Replace with a meaningful
description ("at the leading `(` of the parenthesized callee")
so the audit's regression-fixture purpose is self-explanatory
even without exact byte offsets.

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

* docs(design): real S2 span + remove stray integration.rs blank line

Per cursor APPROVE_WITH_COMMENTS on PR #1264 sha de24278:

1. S2 span placeholder replaced with real byte offsets [106, 107]
   (leading `(` of parenthesized callee in the smoke fixture),
   matching the verbatim-evidence bar S1/S3/S4 set.
2. Stray blank line in src/v3/compiler/tests/integration.rs from
   the earlier S2-probe cleanup removed; integration.rs now matches
   origin/main exactly so the acceptance bullet ("no code changes")
   is honest.

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

* docs(design): collapse target+inputs into TransformDispatch sum (X1)

Per gpt-5-5-thinking REQUEST_CHANGES on PR #1264 sha de24278:
the Vec<TransformInput> tagged-element approach left cardinality
of Callee per IndirectCall as a cross-field invariant
enforced by builder + debug assert, not by the type. Failed
illegal-states-unrepresentable.

Resolution: collapse TransformNode.target and TransformNode.inputs
into a single typed sum TransformDispatch with one variant per
dispatch shape, each carrying its own structured fields (Callable
{ callee: DeclarationId, args }, Indirect { callee: PortId, args },
etc.). Cardinality and target/callee compatibility are both
expressed in the type:

- Callable / FieldProject / Operator cannot carry runtime callee
  ports (no callee: PortId field).
- Indirect cannot omit its callee (single field, not Option, not Vec).
- Multi-callee Indirect is impossible (single field, not Vec).
- Callable.callee is DeclarationId (compile-time);
  Indirect.callee is PortId (runtime); type system separates them.

Single-authority dependency walk preserved via
TransformDispatch::input_ports() iterator.
EmitError::MalformedIndirectCall retires — malformed state
unrepresentable.

Migration cost noted: substantial refactor of TransformNode and
all consumers walking target/inputs separately. Implementation
worker scopes the migration; audit only locks the target shape.

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

* docs(design): ArrowPortRef typed handle for IndirectCall.callee

Per BLOCKING inline on PR #1264 sha de24278 line 215:
Indirect.callee: PortId admits non-Arrow callees with API-level
enforcement only behavioral. Refine to ArrowPortRef — Track-9
named-typed-handle wrapping PortId with Arrow-type proof,
constructable only via Dag::resolve_arrow_port which validates
the port's producer signature at construction.

Non-Arrow callees become structurally unrepresentable:
- ArrowPortRef's constructor is private to the dag module.
- Outside callers go through resolve_arrow_port, which returns
  Err(NonArrowPortError) on non-Arrow ports.
- Indirect { callee: ArrowPortRef, ... } can only be built with a
  validated ArrowPortRef.

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

* docs(design): fix "against existing the existing" typo

Per codex exploratory note on PR #1264 sha 69ee59a.

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

* docs(design): clarify X3 'if Director confirms' refers to need not syntax

Per cursor exploratory note on PR #1264 sha 79af7aa: X3's syntax
is already Director-locked to explicit block markers earlier in
the doc; only whether X3 is required for fold_lens<C> remains
open. Tighten the acceptance section to disambiguate.

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

* docs(design): close arity gap — OperatorCall fixed-arity + ArityCheckedArgs Track-9 handle

Operator arity now encoded in OperatorCall sum (Unary/Binary); call-shape
args wrapped in ArityCheckedArgs typed handle validated by
Dag::resolve_call_args against the resolved Arrow signature. Malformed
arity is structurally unrepresentable rather than convention-level.

* docs(design): align L1.b sequencing bullet with ArityCheckedArgs typed handle

* docs(design): bind args proof to dispatch target via atomic construction

ArityCheckedArgs as a free-floating proof admitted reattaching args
validated against signature A to a dispatch built for target B.
Replaced with crate-private variant fields + Dag-level builders
(push_callable/field_project/indirect_transform) that fuse target
resolution and arity/type validation in one step. The proof and
target are co-constructed; no public path can split them.

* docs(design): add TransformDispatch dissolution ledger (🟢/🟡/🔴)

Per modeling-discipline coproduct classification:
- 🟢 Operator: keep (true user-input-boundary; primitives have no DeclarationId)
- 🟡 Callable/FieldProject/Indirect: future-dissolve to Call { callee: CalleeRef, args }; separate today only because emitter rendering and args co-construction bind per-variant
- 🔴 none

Tracking gate for the 🟡 collapse: emitter callee-rendering split.

* docs(design): align builder name to push_indirect_transform

* docs(design): close pub-enum-field gap — wrap dispatch variants in pub(crate)-field structs

Reviewer caught: pub enum with named-field variants exposes those
fields publicly, so 'crate-private fields' was a false claim. Replaced
named-field variants with tuple-struct payloads (CallableDispatch,
FieldProjectDispatch, IndirectDispatch) whose fields are pub(crate).
Outside the dag module, literal construction is blocked by the type
system; only the Dag builder produces them. OperatorCall stays a plain
pub enum since its variants witness no signature.

* docs(design): scope dispatch payload fields to module-private (not pub(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).

* docs(design): reclassify Operator from 🟢 to 🟡 per ArithOp dissolution 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).

* docs(design): harmonize dispatch variant snippets to tuple-payload form

* docs(design): split FieldProject (pure projection) and FieldCall (invocation)

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.

* docs(design): input_ports() enumerates carrier/operand ports too

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.

* docs(design): separate 'HO dispatch capability permanent' from 'Indirect 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.

---------

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