From 4cf442c6afddae28c05f6f60d23a1a812cf2ae91 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 11:32:16 -0400 Subject: [PATCH 01/13] =?UTF-8?q?docs(briefs):=20Fn=E2=86=92Arrow=20refact?= =?UTF-8?q?or=20pre-prereq=20for=20unenumerated-effects=20chain?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-prereq sub-lane authored post-sunny-otter-128 STOP-AND-ESCALATE on the parser-effects brief. Worker verified that the parser brief's recommended `declared_effects on SurfaceType.Arrow` placement does not load-bear on `SurfaceItem.Fn` because Fn today carries `params: List` + `return_type: SurfaceType` as two separate fields, not as an Arrow-shaped signature. Per parser-brief STOP #2, Director picked (b)(2): structural refactor first. This brief reshapes `SurfaceItem.Fn` to carry an Arrow-shaped signature so the downstream parser-effects sub-lane can land `declared_effects` on Arrow once and have it apply uniformly to top-level functions and higher-order function types. Chain: this PR → parser-effects sub-lane → substrate-effects sub-lane. Mirrors the parser-prereq pattern from #797 (ValueBody::Map) and #799 (parser-effects). Six reqs, slice steps, eight STOP-AND-ESCALATE conditions, structural-carrier rationale requirement for new `ArrowInput` carrier. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...erated-effects-fn-arrow-refactor-worker.md | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md new file mode 100644 index 00000000000..35425468607 --- /dev/null +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -0,0 +1,128 @@ +# T-ImpossibleBugs unenumerated effects — `Fn`→`Arrow` signature refactor `(M, R2 pre-prereq)` + +> **Director ad-hoc dispatch.** Sibling pre-requisite to the +> [`t-impossiblebugs-unenumerated-effects-parser-worker.md`](t-impossiblebugs-unenumerated-effects-parser-worker.md) +> parser sub-lane, which is itself pre-requisite to the +> [`t-impossiblebugs-unenumerated-effects-worker.md`](t-impossiblebugs-unenumerated-effects-worker.md) +> substrate sub-lane. Authored 2026-04-25 post-`sunny-otter-128` +> STOP-AND-ESCALATE on the parser-prereq brief — worker verified that +> the parser brief's recommended `declared_effects on SurfaceType.Arrow` +> placement does not load-bear on `SurfaceItem.Fn`, because `Fn` today +> carries `params: List` + `return_type: SurfaceType` as +> two separate fields, not as an `Arrow`-shaped signature. Per the +> parser brief's STOP #2 (*"if execution surfaces a strong reason to +> put the field on `Fn` instead of `Arrow` (e.g., effect-as-type-component +> breaks), STOP. Director call."*), Director picked **(b)(2): structural +> refactor first**. +> +> This brief reshapes `SurfaceItem.Fn` to carry an `Arrow`-shaped +> signature so that the downstream parser sub-lane can land +> `declared_effects` on `Arrow` once and have it apply uniformly to +> top-level functions and higher-order function types. Reports back to +> Director (`zesty-bear-812`); Surface Manager territory overlap +> (parser surface-syntax authority). +> +> **Precedent**: this split mirrors the parser-prereq pattern from +> PR #797 ([`t-substrate-valuebody-map-parser-worker.md`](t-substrate-valuebody-map-parser-worker.md)) +> and PR #799 ([`t-impossiblebugs-unenumerated-effects-parser-worker.md`](t-impossiblebugs-unenumerated-effects-parser-worker.md)). +> The chain: this brief → parser-effects brief → substrate-effects brief. + +## Read first + +- **[`docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md`](t-impossiblebugs-unenumerated-effects-parser-worker.md)** — sibling parser sub-lane brief; blocks on this PR landing. The parser brief assumes `SurfaceType.Arrow` is the load-bearing function-type-signature carrier; this brief makes that assumption true on `Fn`. +- **[`src/v3/std/parse_surface.dag:60-75`](../../src/v3/std/parse_surface.dag)** — `SurfaceType.Arrow` declaration; today carries `inputs: List` (pure types, no names, no refinements) + `output: SurfaceType` + `span: SourceSpan`. Higher-order types written `(A, B) -> C` flow through this. +- **[`src/v3/std/parse_surface.dag:33-37`](../../src/v3/std/parse_surface.dag)** — `SurfaceParam = { name: String, ty: SurfaceType, refinement: SurfaceExpr? }`. Carries the param-binding info that today lives parallel to `SurfaceType` on `Fn`. +- **[`src/v3/std/parse_surface.dag:179-200`](../../src/v3/std/parse_surface.dag)** — `SurfaceItem.Fn` (and `FnExternalBody`); today: `name`, `type_params`, `params: List`, `return_type: SurfaceType`, `body`, `span`. The `params` + `return_type` split is the vestige this brief dissolves. +- **[`src/v3/compiler/parse_parser_body.txt`](../../src/v3/compiler/parse_parser_body.txt)** — parse-body algorithm authority. The function-item path constructs `Fn { params, return_type, ... }`; this brief routes that construction through an `Arrow` signature. +- **[`src/v3/compiler/src/parse_generated.rs`](../../src/v3/compiler/src/parse_generated.rs)** — auto-generated. Per `feedback_no_generated_code_on_disk`, edits flow through `.dag` + `.txt` authority then regen. **No hand edits to `parse_generated.rs`**. +- **[`src/v3/compiler/src/lower.rs`](../../src/v3/compiler/src/lower.rs)** — primary `Fn` consumer; lowers params + return_type to substrate connectives. Worker re-confirms exhaustive-match site count via `grep -n "SurfaceItem::Fn\b\|match.*SurfaceItem\b" src/v3/compiler/src/lower.rs` at dispatch (snapshot grep: ~20 hits across `src/v3/compiler/src/`; not authority). +- **[`src/v3/std/substrate.dag:154-163`](../../src/v3/std/substrate.dag)** — substrate `Declaration` + `Arrow` connectives. The substrate-side function-arrow shape is a separate concern from this surface-side refactor; this brief does NOT touch substrate `Arrow`. +- **`feedback_construction_over_ratchets`** + **`feedback_parallel_representation_debt`** + **`feedback_coproduct_dissolution`** + **`feedback_missing_checks_review_heuristic`** + **`feedback_no_generated_code_on_disk`** + **`feedback_no_annotations`** + **MODELING.md M9** + **INVARIANTS.md**. + +## Frame + +`SurfaceItem.Fn` today carries `params: List` + `return_type: SurfaceType` as two fields. There is no synthesized `Arrow` on the function declaration — `SurfaceType.Arrow` only appears when a higher-order function type is *written out as a type annotation* (e.g., a parameter typed `(A, B) -> C`). + +This split is a vestige. Function declarations *are* arrows: their structural type signature is `(input₁, …, inputₙ) -> output`. The parallel encoding (separate `params` + `return_type` fields on `Fn`, separate `Arrow.inputs` + `Arrow.output` on `SurfaceType`) is `feedback_parallel_representation_debt` waiting to be dissolved — the same shape encoded twice. + +The downstream parser-effects sub-lane needs to add a `declared_effects` field that is *part of the function type signature* (per `feedback_no_annotations` — first-class language feature, not an annotation). With the current split, that field would either: +- Have to live on `SurfaceItem.Fn` only (effects can't appear in higher-order function types — discipline anchor weakens), OR +- Have to live on both `SurfaceType.Arrow` and `SurfaceItem.Fn` (parallel representation; two carriers for the same concept). + +Both are dead-ends. The constructive fix is to dissolve the split: `SurfaceType.Arrow` carries the structural function-type signature uniformly, and `SurfaceItem.Fn` carries an `Arrow`-shaped signature alongside the bind-site param-name + refinement metadata. + +This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `ArrowInput` carries optional name + refinement alongside the type) and reshapes `SurfaceItem.Fn` to use that `Arrow` shape directly. Effects do NOT land in this PR — that's the next sub-lane in the chain. + +**Top-level functions + higher-order function types** for this PR. Closures / lambdas (which today use `SurfaceExpr::Lambda` with no explicit type signature) — out of scope; `Lambda` continues to carry `params: List` + `body` as today. + +## Six consumer-side requirements + +1. **New `ArrowInput` carrier in `parse_surface.dag`.** Element shape: `ArrowInput { name: String?, ty: SurfaceType, refinement: SurfaceExpr? }`. Both `name` and `refinement` are optional — higher-order types written `(A, B) -> C` produce `ArrowInput { name: None, ty: A, refinement: None }`; named function-declaration params produce `ArrowInput { name: Some("x"), ty: A, refinement: }`. **Coproduct dissolution receipt is N/A** (this is a record, not a coproduct), but worker MUST author a **structural-carrier rationale** in the same file — what concept this carrier names, why optional name + optional refinement is the right shape (not two separate variants), and why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`. The justification should anchor on: `SurfaceParam` is the *data* of a param at a binding site (used by lowerer to bind names); `ArrowInput` is the *type-signature view* (used by type-checker to compose function types). Once the refactor lands, `SurfaceParam` is dissolved into `ArrowInput`. +2. **`SurfaceType.Arrow` refactored.** `inputs: List` → `inputs: List`. `output` + `span` unchanged. Higher-order function-type parsing (`(A, B) -> C`) produces an `Arrow` with `ArrowInput { name: None, ty: A, refinement: None }` entries. **No silent compatibility shim**; existing callers updated per req 6. +3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: SurfaceType` (constrained at construction site to be an `Arrow` variant — enforced by the parser, not by the type system; lowerer + consumers fail-closed if it's any other variant per `feedback_fail_closed_discipline`). The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.Arrow.inputs[i]`'s `ArrowInput { name: Some, refinement: ... }`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. +4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) now routes its parsed params + return-type through `ArrowInput` construction → `SurfaceType::Arrow` → `SurfaceItem::Fn { signature, ... }`. The higher-order type parse path (where `SurfaceType::Arrow` is constructed for type annotations) constructs `ArrowInput { name: None, refinement: None, ty }` entries. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. +5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature` and destructure the `Arrow` shape. The bound-name + refinement information continues to flow through to the substrate side identically — this is a surface-side reshaping; substrate-side `Declaration` + `Arrow` are untouched. **Lowerer fail-closed** if `Fn.signature` is anything other than `SurfaceType::Arrow` (per req 3 + `feedback_fail_closed_discipline`). +6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated to handle the new field shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }` and only uses param/return data, it now destructures `Fn { signature: SurfaceType::Arrow { inputs, output, .. }, ... }` and reads from there. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures over `List` and reads `.ty` per entry. + +## Slice — `Fn`→`Arrow` refactor + +1. Add `ArrowInput` carrier (per req 1) to `parse_surface.dag` with structural-carrier rationale comment. +2. Refactor `SurfaceType.Arrow` (per req 2): `inputs: List` → `inputs: List`. +3. Refactor `SurfaceItem.Fn` + `FnExternalBody` (per req 3): drop `params` + `return_type`, add `signature: SurfaceType`. Retire `SurfaceParam`. +4. Edit `parse_parser_body.txt` (per req 4): update function-item + higher-order-type construction sites to flow through the new shape. +5. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). +6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Fail-closed on non-Arrow `signature`. +7. Exhaustive-match audit + updates (per req 6) across every consumer. +8. Smoke + regression tests: + - Parser accepts `fn foo(x: Int, y: Bool) -> String { ... }` and produces `Fn { signature: SurfaceType::Arrow { inputs: [ArrowInput { name: Some("x"), ty: Int, refinement: None }, ArrowInput { name: Some("y"), ty: Bool, refinement: None }], output: String, .. }, .. }`. + - Parser accepts `fn higher_order(f: (Int, Bool) -> String) -> Int { ... }` and produces an `ArrowInput` for `f` whose `ty` is `SurfaceType::Arrow { inputs: [ArrowInput { name: None, ty: Int, refinement: None }, ArrowInput { name: None, ty: Bool, refinement: None }], output: String, .. }`. + - Existing v3 compiler tests pass unchanged (refactor is structurally equivalent on the surface; no surface-syntax change). + +## Acceptance + +- [ ] All 6 consumer-side requirements satisfied + documented in PR body. +- [ ] `ArrowInput` carrier in `parse_surface.dag` with structural-carrier rationale comment. +- [ ] `SurfaceType.Arrow.inputs: List` (not `List`). +- [ ] `SurfaceItem.Fn` + `FnExternalBody` carry `signature: SurfaceType` (not `params` + `return_type`). +- [ ] `SurfaceParam` retired (zero references post-refactor). +- [ ] `parse_parser_body.txt` construction-site updates landed. +- [ ] `parse_generated.rs` regenerated; no hand edits. +- [ ] All `SurfaceType::Arrow` + `SurfaceItem::Fn`/`FnExternalBody` exhaustive-match sites updated; no new wildcard `_` arms. +- [ ] Lowerer fail-closed on non-Arrow `signature`. +- [ ] Smoke tests for top-level fn + higher-order-type both produce the new shape. +- [ ] `cargo test --workspace --exclude v2-compiler-tests` / `clippy --all-targets -- -D warnings` / `fmt --all --check` clean. +- [ ] DB-8 fixed-point converges bit-identically. +- [ ] SG-0 census deltas: regen-output updates land in REGEN_OUTPUTS partition. + +## STOP-AND-ESCALATE + +Surface to Director. + +- **Higher-order-type surface syntax accepts named params today** — if `(x: A, y: B) -> C` is already a valid surface form (i.e., `SurfaceType::Arrow.inputs` already carries names somewhere the snapshot grep missed), STOP. The refactor is then a *renaming* not a *promotion*; the structural-carrier rationale needs to reflect that. +- **`SurfaceParam` has consumers beyond `Fn` / `FnExternalBody`** — req 3 retires `SurfaceParam`. If grep surfaces consumers in (e.g.) `Lambda`, `Match`, or other carriers, STOP. Either keep `SurfaceParam` as a live carrier (and have `ArrowInput` be a sibling) or scope a coupled retirement. +- **Higher-order types appear in positions that today silently drop refinements** — if existing `Arrow.inputs: List` consumers somewhere assume the type carries no refinement (and the new `ArrowInput.refinement: Some` would surface a previously-impossible state), STOP. Fail-closed at the point of inspection, not silent fall-through. +- **`parse_parser_body.txt` edits cascade beyond function-item / higher-order-type construction** — STOP. Cross-cutting parser changes need Surface Manager coordination. +- **Exhaustive-match audit reveals consumer using wildcard `_`** — STOP. Surface a fix decision (this PR vs follow-up). +- **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: SurfaceType::Arrow` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. +- **DB-11 / refinement-strip interaction surfaces** (`infer.rs:3693-3703`) — if refinements on `ArrowInput` interact with DB-11's refinement strip in a non-obvious way, STOP. +- **DB-8 fixed-point drifts** — STOP immediately. + +## Non-goals + +- **Not adding `declared_effects`.** That's the sibling parser-effects sub-lane; this PR makes `Arrow` the load-bearing site so that the *next* PR can add the field once and have it apply uniformly. +- **Not refactoring `SurfaceExpr::Lambda`.** Lambdas don't have explicit type signatures today; they're out of scope. +- **Not refactoring substrate-side `Declaration` / `Arrow`.** Surface-side only. +- **Not changing surface syntax.** The user-visible function-declaration syntax is unchanged; this is a pure construction-site refactor. +- **Not changing higher-order type syntax.** `(A, B) -> C` continues to parse as today; the only structural change is that `Arrow.inputs` now wraps each entry in `ArrowInput { name: None, refinement: None, ty }`. + +## Reporting + +- Single PR. Title: `feat(v3): T-ImpossibleBugs Fn→Arrow refactor — SurfaceItem.Fn carries Arrow-shaped signature (pre-prereq for unenumerated-effects parser sub-lane)`. +- PR body cites this brief + addresses each of the 6 reqs + documents structural-carrier rationale for `ArrowInput`. +- On merge: signal Director; Director signals sibling parser sub-lane (`t-impossiblebugs-unenumerated-effects-parser-worker.md`) is now dispatchable. The parser sub-lane brief itself does NOT need editing — it already assumes `Arrow` is the load-bearing carrier; this PR makes that assumption true. + +## Cross-manager note + +- **Surface Manager**: heads-up at dispatch. This PR is Surface Manager territory by overlap (parser surface-syntax authority — though no syntax change, parse-body construction sites move); coordinate at landing. +- **Zero-Floor Manager**: heads-up — `parse_surface.dag` shape changes are substrate-discipline-adjacent. Structural-carrier rationale (req 1) is the discipline anchor. +- **Grounding Manager**: no current overlap. From 74db6699284dde9ef0355e83b8f1e44038c01532 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 11:37:20 -0400 Subject: [PATCH 02/13] =?UTF-8?q?docs(briefs):=20tighten=20Fn=E2=86=92Arro?= =?UTF-8?q?w=20refactor=20brief=20=E2=80=94=20illegal=20states=20unreprese?= =?UTF-8?q?ntable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three review threads (Director non-blocking observation + Codex BLOCKING ×2 + Codex P2 inline + Claude API exploratory) converged on the same fix: the brief's draft 1 admitted illegal states via behavioral enforcement where structural enforcement was available. Fixes: 1. `ArrowInput` reshaped from `{ name: String?, ty, refinement: SurfaceExpr? }` (independent optionals — `name: None, refinement: Some` was representable-but-illegal) into a proper coproduct: Anonymous { ty } | Named { name, ty, refinement: SurfaceExpr? } Refinement-without-binder now structurally unrepresentable. Coproduct dissolution receipt now mandatory (was N/A under the record shape). 2. `SurfaceArrow` typed sub-carrier introduced; `SurfaceType.Arrow` wraps it as `Arrow(SurfaceArrow)`. `SurfaceItem.Fn.signature` typed as `SurfaceArrow` (not `SurfaceType`). `Fn { signature: SurfaceType::Bool }` now structurally unrepresentable per `feedback_state_space_vs_behavioral_invariants` — rejecting draft 1's "fail-closed lowerer" behavioral compromise that codex / Director both flagged. 3. Smoke-test examples corrected to `fn(Int, Bool) -> String` form. v3 surface requires `fn(...)` prefix per `parse_atom_type`'s `TokenKind::KwFn` gate — original `(A, B) -> C` examples would parse- error and mislead the worker. Codex P2 inline finding. 4. Slice + acceptance + STOP-AND-ESCALATE updated for the new shapes; added STOP for `SurfaceArrow` cascade beyond expected consumers (escape hatch to type-alias / typed-view shape if blast radius surprises). 5. Acceptance gains a post-refactor exhaustive-match-site count recording line per Claude API exploratory observation. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...erated-effects-fn-arrow-refactor-worker.md | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index 35425468607..7f3cefed43c 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -57,34 +57,43 @@ This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `A ## Six consumer-side requirements -1. **New `ArrowInput` carrier in `parse_surface.dag`.** Element shape: `ArrowInput { name: String?, ty: SurfaceType, refinement: SurfaceExpr? }`. Both `name` and `refinement` are optional — higher-order types written `(A, B) -> C` produce `ArrowInput { name: None, ty: A, refinement: None }`; named function-declaration params produce `ArrowInput { name: Some("x"), ty: A, refinement: }`. **Coproduct dissolution receipt is N/A** (this is a record, not a coproduct), but worker MUST author a **structural-carrier rationale** in the same file — what concept this carrier names, why optional name + optional refinement is the right shape (not two separate variants), and why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`. The justification should anchor on: `SurfaceParam` is the *data* of a param at a binding site (used by lowerer to bind names); `ArrowInput` is the *type-signature view* (used by type-checker to compose function types). Once the refactor lands, `SurfaceParam` is dissolved into `ArrowInput`. -2. **`SurfaceType.Arrow` refactored.** `inputs: List` → `inputs: List`. `output` + `span` unchanged. Higher-order function-type parsing (`(A, B) -> C`) produces an `Arrow` with `ArrowInput { name: None, ty: A, refinement: None }` entries. **No silent compatibility shim**; existing callers updated per req 6. -3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: SurfaceType` (constrained at construction site to be an `Arrow` variant — enforced by the parser, not by the type system; lowerer + consumers fail-closed if it's any other variant per `feedback_fail_closed_discipline`). The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.Arrow.inputs[i]`'s `ArrowInput { name: Some, refinement: ... }`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. +1. **New `ArrowInput` coproduct in `parse_surface.dag`.** Two variants — illegal states unrepresentable per `feedback_state_space_vs_behavioral_invariants` and modeling-discipline practice 2: + + ``` + type ArrowInput + = Anonymous { ty: SurfaceType } + | Named { name: String, ty: SurfaceType, refinement: SurfaceExpr? } + ``` + + Higher-order types written `fn(A, B) -> C` produce `ArrowInput::Anonymous { ty: A }` entries (no name, no refinement — both structurally absent, not "optional but None"). Named function-declaration params produce `ArrowInput::Named { name: "x", ty: A, refinement: ... }`. The previous shape (`name: String?` + `refinement: SurfaceExpr?` as independent optionals) is rejected: `name: None, refinement: Some` is a meaningless state (refinement without a binder) and would be representable-but-illegal. **Coproduct dissolution receipt** mandatory per `feedback_coproduct_dissolution` and the `LoopBound` precedent at `docs/design-mutual-recursion-lowering.md:117-134` — worker authors the receipt in `parse_surface.dag` adjacent to the type. Receipt should also address why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`: `SurfaceParam` is the *data of a param at a binding site* (lowerer-binding view); `ArrowInput::Named` is the *type-signature view*. Once the refactor lands, `SurfaceParam` dissolves into `ArrowInput::Named` (req 3). +2. **`SurfaceType.Arrow` refactored to wrap a typed `SurfaceArrow` sub-carrier.** Introduce a new top-level struct `SurfaceArrow { inputs: List, output: SurfaceType, span: SourceSpan }`, then change `SurfaceType.Arrow(SurfaceArrow)` (single positional payload, not record fields). This makes the `Arrow`-shape a typed entity that consumers can hold directly without destructuring through `SurfaceType` first — load-bearing for req 3. **No silent compatibility shim**; existing callers updated per req 6. +3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored to carry `SurfaceArrow` directly.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: SurfaceArrow` (the typed sub-carrier from req 2 — **not** `SurfaceType`). This makes `Fn { signature: SurfaceType::Bool, ... }` and similar illegal states **structurally unrepresentable** per `feedback_state_space_vs_behavioral_invariants` (rejecting the earlier draft's behavioral-enforcement-via-fail-closed-lowerer compromise that codex / Director both flagged). The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.inputs[i]` as `ArrowInput::Named { name, ty, refinement }`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. 4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) now routes its parsed params + return-type through `ArrowInput` construction → `SurfaceType::Arrow` → `SurfaceItem::Fn { signature, ... }`. The higher-order type parse path (where `SurfaceType::Arrow` is constructed for type annotations) constructs `ArrowInput { name: None, refinement: None, ty }` entries. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. -5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature` and destructure the `Arrow` shape. The bound-name + refinement information continues to flow through to the substrate side identically — this is a surface-side reshaping; substrate-side `Declaration` + `Arrow` are untouched. **Lowerer fail-closed** if `Fn.signature` is anything other than `SurfaceType::Arrow` (per req 3 + `feedback_fail_closed_discipline`). -6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated to handle the new field shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }` and only uses param/return data, it now destructures `Fn { signature: SurfaceType::Arrow { inputs, output, .. }, ... }` and reads from there. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures over `List` and reads `.ty` per entry. +5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature.inputs` + `Fn.signature.output`. Per-input destructuring branches on `ArrowInput::Anonymous` vs `ArrowInput::Named` — the lowerer's bind-name + refinement consumption only fires on `Named`, and `Anonymous` in a function-declaration position is a parser-side invariant violation that the lowerer surfaces as a structured Diagnostic (per `feedback_fail_closed_discipline` + C-8). This is surface-side reshaping; substrate-side `Declaration` + `Arrow` untouched. **No wildcard arms** that swallow the `Anonymous` case silently. +6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated for the new shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }`, it now destructures `Fn { signature: SurfaceArrow { inputs, output, .. }, ... }`. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures `SurfaceType::Arrow(arrow)` and reads `arrow.inputs: List`, branching per-entry on `Anonymous { ty }` vs `Named { name, ty, refinement }`. ## Slice — `Fn`→`Arrow` refactor -1. Add `ArrowInput` carrier (per req 1) to `parse_surface.dag` with structural-carrier rationale comment. -2. Refactor `SurfaceType.Arrow` (per req 2): `inputs: List` → `inputs: List`. -3. Refactor `SurfaceItem.Fn` + `FnExternalBody` (per req 3): drop `params` + `return_type`, add `signature: SurfaceType`. Retire `SurfaceParam`. +1. Add `ArrowInput` coproduct (per req 1) to `parse_surface.dag` with coproduct dissolution receipt. +2. Add `SurfaceArrow` typed sub-carrier (per req 2); refactor `SurfaceType.Arrow` to wrap it as a single positional payload. +3. Refactor `SurfaceItem.Fn` + `FnExternalBody` (per req 3): drop `params` + `return_type`, add `signature: SurfaceArrow` (typed; not `SurfaceType`). Retire `SurfaceParam`. 4. Edit `parse_parser_body.txt` (per req 4): update function-item + higher-order-type construction sites to flow through the new shape. 5. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). -6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Fail-closed on non-Arrow `signature`. +6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Branch per-input on `ArrowInput::Anonymous` vs `Named`; structured Diagnostic for `Anonymous` in function-declaration position. 7. Exhaustive-match audit + updates (per req 6) across every consumer. -8. Smoke + regression tests: - - Parser accepts `fn foo(x: Int, y: Bool) -> String { ... }` and produces `Fn { signature: SurfaceType::Arrow { inputs: [ArrowInput { name: Some("x"), ty: Int, refinement: None }, ArrowInput { name: Some("y"), ty: Bool, refinement: None }], output: String, .. }, .. }`. - - Parser accepts `fn higher_order(f: (Int, Bool) -> String) -> Int { ... }` and produces an `ArrowInput` for `f` whose `ty` is `SurfaceType::Arrow { inputs: [ArrowInput { name: None, ty: Int, refinement: None }, ArrowInput { name: None, ty: Bool, refinement: None }], output: String, .. }`. +8. Smoke + regression tests (note: v3 surface requires `fn(...)` prefix for higher-order types per `parse_atom_type`'s `TokenKind::KwFn` gate — examples below use that form): + - Parser accepts `fn foo(x: Int, y: Bool) -> String { ... }` and produces `Fn { signature: SurfaceArrow { inputs: [ArrowInput::Named { name: "x", ty: Int, refinement: None }, ArrowInput::Named { name: "y", ty: Bool, refinement: None }], output: String, .. }, .. }`. + - Parser accepts `fn higher_order(f: fn(Int, Bool) -> String) -> Int { ... }` and produces an `ArrowInput::Named` for `f` whose `ty` is `SurfaceType::Arrow(SurfaceArrow { inputs: [ArrowInput::Anonymous { ty: Int }, ArrowInput::Anonymous { ty: Bool }], output: String, .. })`. - Existing v3 compiler tests pass unchanged (refactor is structurally equivalent on the surface; no surface-syntax change). ## Acceptance - [ ] All 6 consumer-side requirements satisfied + documented in PR body. -- [ ] `ArrowInput` carrier in `parse_surface.dag` with structural-carrier rationale comment. -- [ ] `SurfaceType.Arrow.inputs: List` (not `List`). -- [ ] `SurfaceItem.Fn` + `FnExternalBody` carry `signature: SurfaceType` (not `params` + `return_type`). +- [ ] `ArrowInput` coproduct (`Anonymous` | `Named`) in `parse_surface.dag` with coproduct dissolution receipt. +- [ ] `SurfaceArrow` typed sub-carrier in `parse_surface.dag`; `SurfaceType.Arrow(SurfaceArrow)` wraps it. +- [ ] `SurfaceItem.Fn` + `FnExternalBody` carry `signature: SurfaceArrow` (typed; not `SurfaceType`; illegal-state-unrepresentable). - [ ] `SurfaceParam` retired (zero references post-refactor). +- [ ] Post-refactor exhaustive-match-site count for `SurfaceType::Arrow` + `SurfaceItem::Fn` / `FnExternalBody` recorded in PR body. - [ ] `parse_parser_body.txt` construction-site updates landed. - [ ] `parse_generated.rs` regenerated; no hand edits. - [ ] All `SurfaceType::Arrow` + `SurfaceItem::Fn`/`FnExternalBody` exhaustive-match sites updated; no new wildcard `_` arms. @@ -103,7 +112,8 @@ Surface to Director. - **Higher-order types appear in positions that today silently drop refinements** — if existing `Arrow.inputs: List` consumers somewhere assume the type carries no refinement (and the new `ArrowInput.refinement: Some` would surface a previously-impossible state), STOP. Fail-closed at the point of inspection, not silent fall-through. - **`parse_parser_body.txt` edits cascade beyond function-item / higher-order-type construction** — STOP. Cross-cutting parser changes need Surface Manager coordination. - **Exhaustive-match audit reveals consumer using wildcard `_`** — STOP. Surface a fix decision (this PR vs follow-up). -- **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: SurfaceType::Arrow` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. +- **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: SurfaceArrow` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. +- **`SurfaceArrow` introduction cascades into substrate authority** — req 2 introduces `SurfaceArrow` as a top-level `parse_surface.dag` carrier wrapped by `SurfaceType.Arrow`. If grep surfaces consumers that expect `SurfaceType::Arrow { inputs, output, span }` as record-style fields (rather than `Arrow(SurfaceArrow)` positional payload) and updating them cascades beyond `lower.rs` + immediate parse consumers, STOP. May indicate a smaller-blast-radius shape (e.g., keeping `Arrow` as record-style and instead defining `SurfaceArrow` as a type alias / typed view rather than a wrapping payload) is preferable. - **DB-11 / refinement-strip interaction surfaces** (`infer.rs:3693-3703`) — if refinements on `ArrowInput` interact with DB-11's refinement strip in a non-obvious way, STOP. - **DB-8 fixed-point drifts** — STOP immediately. From 47d13cc22bb8ae41219ae027baccc16d14e2878e Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 11:46:33 -0400 Subject: [PATCH 03/13] docs(briefs): scrub residual rejected-shape references from req 4 + non-goals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex BLOCKING inline at brief:71 caught req 4 still routing Fn construction through SurfaceType::Arrow (not the typed SurfaceArrow sub-carrier from req 2/3) and spelling anonymous inputs as `ArrowInput { name: None, refinement: None, ty }` — the exact rejected shape from draft 1. Non-goals line 126 had the same stale shape and `(A, B) -> C` higher-order syntax (also corrected per the prior fn(...)-prefix fix). Fixes: - Req 4 routes function-item construction directly through ArrowInput::Named → SurfaceArrow → SurfaceItem::Fn { signature: SurfaceArrow }, never wrapping through SurfaceType::Arrow first. - Higher-order construction uses ArrowInput::Anonymous { ty } per the req 1 coproduct. - Non-goals example shape + syntax updated. Pure scrub of leftover draft-1 phrasing missed by 74db66992; no shape changes. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...siblebugs-unenumerated-effects-fn-arrow-refactor-worker.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index 7f3cefed43c..b6652197623 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -68,7 +68,7 @@ This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `A Higher-order types written `fn(A, B) -> C` produce `ArrowInput::Anonymous { ty: A }` entries (no name, no refinement — both structurally absent, not "optional but None"). Named function-declaration params produce `ArrowInput::Named { name: "x", ty: A, refinement: ... }`. The previous shape (`name: String?` + `refinement: SurfaceExpr?` as independent optionals) is rejected: `name: None, refinement: Some` is a meaningless state (refinement without a binder) and would be representable-but-illegal. **Coproduct dissolution receipt** mandatory per `feedback_coproduct_dissolution` and the `LoopBound` precedent at `docs/design-mutual-recursion-lowering.md:117-134` — worker authors the receipt in `parse_surface.dag` adjacent to the type. Receipt should also address why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`: `SurfaceParam` is the *data of a param at a binding site* (lowerer-binding view); `ArrowInput::Named` is the *type-signature view*. Once the refactor lands, `SurfaceParam` dissolves into `ArrowInput::Named` (req 3). 2. **`SurfaceType.Arrow` refactored to wrap a typed `SurfaceArrow` sub-carrier.** Introduce a new top-level struct `SurfaceArrow { inputs: List, output: SurfaceType, span: SourceSpan }`, then change `SurfaceType.Arrow(SurfaceArrow)` (single positional payload, not record fields). This makes the `Arrow`-shape a typed entity that consumers can hold directly without destructuring through `SurfaceType` first — load-bearing for req 3. **No silent compatibility shim**; existing callers updated per req 6. 3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored to carry `SurfaceArrow` directly.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: SurfaceArrow` (the typed sub-carrier from req 2 — **not** `SurfaceType`). This makes `Fn { signature: SurfaceType::Bool, ... }` and similar illegal states **structurally unrepresentable** per `feedback_state_space_vs_behavioral_invariants` (rejecting the earlier draft's behavioral-enforcement-via-fail-closed-lowerer compromise that codex / Director both flagged). The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.inputs[i]` as `ArrowInput::Named { name, ty, refinement }`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. -4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) now routes its parsed params + return-type through `ArrowInput` construction → `SurfaceType::Arrow` → `SurfaceItem::Fn { signature, ... }`. The higher-order type parse path (where `SurfaceType::Arrow` is constructed for type annotations) constructs `ArrowInput { name: None, refinement: None, ty }` entries. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. +4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) now routes its parsed params + return-type through `ArrowInput::Named` construction → `SurfaceArrow` → `SurfaceItem::Fn { signature: SurfaceArrow, ... }` (signature is the typed sub-carrier per req 3 — **not** wrapped through `SurfaceType::Arrow` first). The higher-order type parse path (where `SurfaceType::Arrow(SurfaceArrow)` is constructed for type annotations) constructs `ArrowInput::Anonymous { ty }` entries — never the rejected `{ name: None, refinement: None, ty }` shape, which is structurally absent under the req 1 coproduct. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. 5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature.inputs` + `Fn.signature.output`. Per-input destructuring branches on `ArrowInput::Anonymous` vs `ArrowInput::Named` — the lowerer's bind-name + refinement consumption only fires on `Named`, and `Anonymous` in a function-declaration position is a parser-side invariant violation that the lowerer surfaces as a structured Diagnostic (per `feedback_fail_closed_discipline` + C-8). This is surface-side reshaping; substrate-side `Declaration` + `Arrow` untouched. **No wildcard arms** that swallow the `Anonymous` case silently. 6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated for the new shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }`, it now destructures `Fn { signature: SurfaceArrow { inputs, output, .. }, ... }`. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures `SurfaceType::Arrow(arrow)` and reads `arrow.inputs: List`, branching per-entry on `Anonymous { ty }` vs `Named { name, ty, refinement }`. @@ -123,7 +123,7 @@ Surface to Director. - **Not refactoring `SurfaceExpr::Lambda`.** Lambdas don't have explicit type signatures today; they're out of scope. - **Not refactoring substrate-side `Declaration` / `Arrow`.** Surface-side only. - **Not changing surface syntax.** The user-visible function-declaration syntax is unchanged; this is a pure construction-site refactor. -- **Not changing higher-order type syntax.** `(A, B) -> C` continues to parse as today; the only structural change is that `Arrow.inputs` now wraps each entry in `ArrowInput { name: None, refinement: None, ty }`. +- **Not changing higher-order type syntax.** `fn(A, B) -> C` continues to parse as today; the only structural change is that `Arrow.inputs` now wraps each entry in `ArrowInput::Anonymous { ty }`. ## Reporting From b821a30ab77c695e3d81673b6c5208fb738595c2 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 11:49:37 -0400 Subject: [PATCH 04/13] WIP: T-I unenumerated effects/parser (dual) --- ...erated-effects-fn-arrow-refactor-worker.md | 60 ++++++++++++------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index b6652197623..91fe3c0d9da 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -57,41 +57,60 @@ This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `A ## Six consumer-side requirements -1. **New `ArrowInput` coproduct in `parse_surface.dag`.** Two variants — illegal states unrepresentable per `feedback_state_space_vs_behavioral_invariants` and modeling-discipline practice 2: +1. **New input-element shapes in `parse_surface.dag`.** Two carriers, distinguishing declaration position (always named) from type position (mixed) — both illegal-state-unrepresentable per `feedback_state_space_vs_behavioral_invariants`: ``` + type NamedArrowInput { + name: String + ty: SurfaceType + refinement: SurfaceExpr? + } + type ArrowInput = Anonymous { ty: SurfaceType } - | Named { name: String, ty: SurfaceType, refinement: SurfaceExpr? } + | Named(NamedArrowInput) + ``` + + `NamedArrowInput` is the load-bearing atom for declaration position (function-decl params always have a name, so the binder is structurally mandatory; refinement remains optional because not every param is refined). `ArrowInput` is the coproduct used in type position only — a higher-order type `fn(A, B) -> C` may carry anonymous entries (no binder) or named entries (e.g., `fn(x: Int) -> ...`). Refinement-without-binder is structurally unrepresentable in either carrier. **Coproduct dissolution receipt** mandatory for `ArrowInput` per `feedback_coproduct_dissolution` and the `LoopBound` precedent at `docs/design-mutual-recursion-lowering.md:117-134` — worker authors the receipt in `parse_surface.dag` adjacent to the type. Receipt should also address why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`: `SurfaceParam` is the *data of a param at a binding site* (lowerer-binding view, today); `NamedArrowInput` is the *type-signature view at declaration position*; `ArrowInput` is the *type-signature view at type-annotation position*. Once the refactor lands, `SurfaceParam` dissolves into `NamedArrowInput` (req 3). +2. **`SurfaceType.Arrow` refactored to wrap a typed `SurfaceArrow` sub-carrier.** Introduce a new top-level struct `SurfaceArrow { inputs: List, output: SurfaceType, span: SourceSpan }` (mixed inputs, type position), then change `SurfaceType.Arrow(SurfaceArrow)` (single positional payload, not record fields). This makes the type-position arrow-shape a typed entity that consumers can hold directly without destructuring through `SurfaceType` first. **No silent compatibility shim**; existing callers updated per req 6. +3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored to carry a typed `FnSignature` sub-carrier with restricted inputs.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: FnSignature` where: + + ``` + type FnSignature { + inputs: List + output: SurfaceType + span: SourceSpan + } ``` - Higher-order types written `fn(A, B) -> C` produce `ArrowInput::Anonymous { ty: A }` entries (no name, no refinement — both structurally absent, not "optional but None"). Named function-declaration params produce `ArrowInput::Named { name: "x", ty: A, refinement: ... }`. The previous shape (`name: String?` + `refinement: SurfaceExpr?` as independent optionals) is rejected: `name: None, refinement: Some` is a meaningless state (refinement without a binder) and would be representable-but-illegal. **Coproduct dissolution receipt** mandatory per `feedback_coproduct_dissolution` and the `LoopBound` precedent at `docs/design-mutual-recursion-lowering.md:117-134` — worker authors the receipt in `parse_surface.dag` adjacent to the type. Receipt should also address why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`: `SurfaceParam` is the *data of a param at a binding site* (lowerer-binding view); `ArrowInput::Named` is the *type-signature view*. Once the refactor lands, `SurfaceParam` dissolves into `ArrowInput::Named` (req 3). -2. **`SurfaceType.Arrow` refactored to wrap a typed `SurfaceArrow` sub-carrier.** Introduce a new top-level struct `SurfaceArrow { inputs: List, output: SurfaceType, span: SourceSpan }`, then change `SurfaceType.Arrow(SurfaceArrow)` (single positional payload, not record fields). This makes the `Arrow`-shape a typed entity that consumers can hold directly without destructuring through `SurfaceType` first — load-bearing for req 3. **No silent compatibility shim**; existing callers updated per req 6. -3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored to carry `SurfaceArrow` directly.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: SurfaceArrow` (the typed sub-carrier from req 2 — **not** `SurfaceType`). This makes `Fn { signature: SurfaceType::Bool, ... }` and similar illegal states **structurally unrepresentable** per `feedback_state_space_vs_behavioral_invariants` (rejecting the earlier draft's behavioral-enforcement-via-fail-closed-lowerer compromise that codex / Director both flagged). The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.inputs[i]` as `ArrowInput::Named { name, ty, refinement }`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. -4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) now routes its parsed params + return-type through `ArrowInput::Named` construction → `SurfaceArrow` → `SurfaceItem::Fn { signature: SurfaceArrow, ... }` (signature is the typed sub-carrier per req 3 — **not** wrapped through `SurfaceType::Arrow` first). The higher-order type parse path (where `SurfaceType::Arrow(SurfaceArrow)` is constructed for type annotations) constructs `ArrowInput::Anonymous { ty }` entries — never the rejected `{ name: None, refinement: None, ty }` shape, which is structurally absent under the req 1 coproduct. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. -5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature.inputs` + `Fn.signature.output`. Per-input destructuring branches on `ArrowInput::Anonymous` vs `ArrowInput::Named` — the lowerer's bind-name + refinement consumption only fires on `Named`, and `Anonymous` in a function-declaration position is a parser-side invariant violation that the lowerer surfaces as a structured Diagnostic (per `feedback_fail_closed_discipline` + C-8). This is surface-side reshaping; substrate-side `Declaration` + `Arrow` untouched. **No wildcard arms** that swallow the `Anonymous` case silently. -6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated for the new shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }`, it now destructures `Fn { signature: SurfaceArrow { inputs, output, .. }, ... }`. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures `SurfaceType::Arrow(arrow)` and reads `arrow.inputs: List`, branching per-entry on `Anonymous { ty }` vs `Named { name, ty, refinement }`. + `inputs: List` (not `List`) makes binderless params **structurally unrepresentable in declaration position** per `feedback_state_space_vs_behavioral_invariants` — rejecting an earlier draft's behavioral fall-back where the lowerer would have surfaced a Diagnostic for `ArrowInput::Anonymous` inside `Fn.signature`. The parser cannot construct `Fn { signature: FnSignature { inputs: [] } }` because no `Anonymous` variant exists in `NamedArrowInput`. The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.inputs[i]: NamedArrowInput`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. + + **Carrier-distinction rationale (mandatory in PR description).** `FnSignature` and `SurfaceArrow` are both arrow-shape sub-carriers but encode different invariants: `FnSignature.inputs: List` (declaration must bind names so the body can reference them); `SurfaceArrow.inputs: List` (type position; binders optional). This is concept distinction, not parallel-representation debt — same justification as `SurfaceParam` vs `NamedArrowInput` carrying overlapping fields but different concepts. The downstream parser-effects sub-lane (#799 brief) lands `declared_effects` on **both** `FnSignature` and `SurfaceArrow` — both are type-signature shapes per `feedback_no_annotations`, so the discipline anchor is satisfied per-carrier; this is co-invariant duplication, not bookkeeping duplication. +4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) routes its parsed params directly through `NamedArrowInput` construction → `FnSignature` → `SurfaceItem::Fn { signature: FnSignature, ... }`. The higher-order type parse path (where `SurfaceType::Arrow(SurfaceArrow)` is constructed for type annotations) constructs `ArrowInput::Anonymous { ty }` or `ArrowInput::Named(NamedArrowInput { ... })` per the syntactic form. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. +5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature.inputs: List` + `Fn.signature.output`. Per-input destructuring is uniform — every entry is a `NamedArrowInput` carrying `name` + `ty` + `refinement?`; **no `ArrowInput::Anonymous` arm to handle in declaration position** (structurally absent per req 3). Type-position consumers (those reading `SurfaceArrow.inputs: List`) branch on `Anonymous` vs `Named`. This is surface-side reshaping; substrate-side `Declaration` + `Arrow` untouched. **No wildcard arms** anywhere. +6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated for the new shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }`, it now destructures `Fn { signature: FnSignature { inputs, output, .. }, ... }` and reads each input as a `NamedArrowInput { name, ty, refinement }`. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures `SurfaceType::Arrow(arrow)` and reads `arrow.inputs: List`, branching per-entry on `Anonymous { ty }` vs `Named(named)`. ## Slice — `Fn`→`Arrow` refactor -1. Add `ArrowInput` coproduct (per req 1) to `parse_surface.dag` with coproduct dissolution receipt. -2. Add `SurfaceArrow` typed sub-carrier (per req 2); refactor `SurfaceType.Arrow` to wrap it as a single positional payload. -3. Refactor `SurfaceItem.Fn` + `FnExternalBody` (per req 3): drop `params` + `return_type`, add `signature: SurfaceArrow` (typed; not `SurfaceType`). Retire `SurfaceParam`. -4. Edit `parse_parser_body.txt` (per req 4): update function-item + higher-order-type construction sites to flow through the new shape. +1. Add `NamedArrowInput` + `ArrowInput` (per req 1) to `parse_surface.dag` with coproduct dissolution receipt for `ArrowInput`. +2. Add `SurfaceArrow` typed sub-carrier (per req 2; type position; `inputs: List`); refactor `SurfaceType.Arrow` to wrap it as a single positional payload. +3. Add `FnSignature` typed sub-carrier (per req 3; declaration position; `inputs: List`); refactor `SurfaceItem.Fn` + `FnExternalBody`: drop `params` + `return_type`, add `signature: FnSignature`. Retire `SurfaceParam`. +4. Edit `parse_parser_body.txt` (per req 4): update function-item construction (→ `NamedArrowInput` → `FnSignature`) + higher-order-type construction (→ `ArrowInput::Anonymous` or `Named` → `SurfaceArrow`). 5. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). -6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Branch per-input on `ArrowInput::Anonymous` vs `Named`; structured Diagnostic for `Anonymous` in function-declaration position. +6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Declaration-position consumers read `NamedArrowInput` directly (no variant branching). Type-position consumers branch on `Anonymous` vs `Named`. 7. Exhaustive-match audit + updates (per req 6) across every consumer. 8. Smoke + regression tests (note: v3 surface requires `fn(...)` prefix for higher-order types per `parse_atom_type`'s `TokenKind::KwFn` gate — examples below use that form): - - Parser accepts `fn foo(x: Int, y: Bool) -> String { ... }` and produces `Fn { signature: SurfaceArrow { inputs: [ArrowInput::Named { name: "x", ty: Int, refinement: None }, ArrowInput::Named { name: "y", ty: Bool, refinement: None }], output: String, .. }, .. }`. - - Parser accepts `fn higher_order(f: fn(Int, Bool) -> String) -> Int { ... }` and produces an `ArrowInput::Named` for `f` whose `ty` is `SurfaceType::Arrow(SurfaceArrow { inputs: [ArrowInput::Anonymous { ty: Int }, ArrowInput::Anonymous { ty: Bool }], output: String, .. })`. + - Parser accepts `fn foo(x: Int, y: Bool) -> String { ... }` and produces `Fn { signature: FnSignature { inputs: [NamedArrowInput { name: "x", ty: Int, refinement: None }, NamedArrowInput { name: "y", ty: Bool, refinement: None }], output: String, .. }, .. }`. + - Parser accepts `fn higher_order(f: fn(Int, Bool) -> String) -> Int { ... }` and produces a `NamedArrowInput` for `f` whose `ty` is `SurfaceType::Arrow(SurfaceArrow { inputs: [ArrowInput::Anonymous { ty: Int }, ArrowInput::Anonymous { ty: Bool }], output: String, .. })`. - Existing v3 compiler tests pass unchanged (refactor is structurally equivalent on the surface; no surface-syntax change). ## Acceptance - [ ] All 6 consumer-side requirements satisfied + documented in PR body. -- [ ] `ArrowInput` coproduct (`Anonymous` | `Named`) in `parse_surface.dag` with coproduct dissolution receipt. -- [ ] `SurfaceArrow` typed sub-carrier in `parse_surface.dag`; `SurfaceType.Arrow(SurfaceArrow)` wraps it. -- [ ] `SurfaceItem.Fn` + `FnExternalBody` carry `signature: SurfaceArrow` (typed; not `SurfaceType`; illegal-state-unrepresentable). +- [ ] `NamedArrowInput` + `ArrowInput` (coproduct: `Anonymous` | `Named(NamedArrowInput)`) in `parse_surface.dag` with coproduct dissolution receipt for `ArrowInput`. +- [ ] `SurfaceArrow` typed sub-carrier (`inputs: List`) in `parse_surface.dag`; `SurfaceType.Arrow(SurfaceArrow)` wraps it. +- [ ] `FnSignature` typed sub-carrier (`inputs: List`) in `parse_surface.dag`; `SurfaceItem.Fn` + `FnExternalBody` carry `signature: FnSignature` (binderless params structurally unrepresentable in declaration position). +- [ ] PR description includes carrier-distinction rationale for `FnSignature` vs `SurfaceArrow` (both arrow-shape; different invariants per req 3). - [ ] `SurfaceParam` retired (zero references post-refactor). - [ ] Post-refactor exhaustive-match-site count for `SurfaceType::Arrow` + `SurfaceItem::Fn` / `FnExternalBody` recorded in PR body. - [ ] `parse_parser_body.txt` construction-site updates landed. @@ -112,8 +131,9 @@ Surface to Director. - **Higher-order types appear in positions that today silently drop refinements** — if existing `Arrow.inputs: List` consumers somewhere assume the type carries no refinement (and the new `ArrowInput.refinement: Some` would surface a previously-impossible state), STOP. Fail-closed at the point of inspection, not silent fall-through. - **`parse_parser_body.txt` edits cascade beyond function-item / higher-order-type construction** — STOP. Cross-cutting parser changes need Surface Manager coordination. - **Exhaustive-match audit reveals consumer using wildcard `_`** — STOP. Surface a fix decision (this PR vs follow-up). -- **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: SurfaceArrow` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. -- **`SurfaceArrow` introduction cascades into substrate authority** — req 2 introduces `SurfaceArrow` as a top-level `parse_surface.dag` carrier wrapped by `SurfaceType.Arrow`. If grep surfaces consumers that expect `SurfaceType::Arrow { inputs, output, span }` as record-style fields (rather than `Arrow(SurfaceArrow)` positional payload) and updating them cascades beyond `lower.rs` + immediate parse consumers, STOP. May indicate a smaller-blast-radius shape (e.g., keeping `Arrow` as record-style and instead defining `SurfaceArrow` as a type alias / typed view rather than a wrapping payload) is preferable. +- **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: FnSignature` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. +- **`SurfaceArrow` / `FnSignature` introduction cascades into substrate authority** — reqs 2 + 3 introduce two top-level `parse_surface.dag` carriers. If grep surfaces consumers that expect `SurfaceType::Arrow { inputs, output, span }` as record-style fields (rather than `Arrow(SurfaceArrow)` positional payload) and updating them cascades beyond `lower.rs` + immediate parse consumers, STOP. May indicate a smaller-blast-radius shape (e.g., keeping `Arrow` as record-style and instead defining the sub-carriers as type aliases / typed views rather than wrapping payloads) is preferable. +- **Type-position higher-order syntax accepts named binders today** (`fn(x: A) -> B`) — req 1 / `ArrowInput::Named(NamedArrowInput)` is the path. If the parser doesn't currently accept that form (i.e., type-position is anonymous-only on the surface today), worker may simplify `ArrowInput` to a single non-coproduct shape (just `Anonymous { ty }`-equivalent) and surface that simplification with rationale. STOP if the simplification would conflict with downstream effect-on-Arrow consumer expectations. - **DB-11 / refinement-strip interaction surfaces** (`infer.rs:3693-3703`) — if refinements on `ArrowInput` interact with DB-11's refinement strip in a non-obvious way, STOP. - **DB-8 fixed-point drifts** — STOP immediately. From 653b2e0064f2469004455ee9ad0d8d13bf954361 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 11:53:17 -0400 Subject: [PATCH 05/13] docs(briefs): rewrite stale "fail-closed on non-Arrow signature" acceptance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude API review at b821a30a flagged this acceptance line as tautological under FnSignature: once signature: FnSignature is the only shape, there's no non-Arrow case for the lowerer to fail-closed on. Reworded to "lowerer destructures FnSignature exhaustively without wildcard arms" — the residual constraint is exhaustiveness, not runtime variant validation, and that's already structurally enforced by req 3. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...ossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index 91fe3c0d9da..5e59bf64d83 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -116,7 +116,7 @@ This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `A - [ ] `parse_parser_body.txt` construction-site updates landed. - [ ] `parse_generated.rs` regenerated; no hand edits. - [ ] All `SurfaceType::Arrow` + `SurfaceItem::Fn`/`FnExternalBody` exhaustive-match sites updated; no new wildcard `_` arms. -- [ ] Lowerer fail-closed on non-Arrow `signature`. +- [ ] Lowerer destructures `FnSignature` exhaustively without wildcard arms (no runtime non-Arrow check needed — typed sub-carrier eliminates the case structurally per req 3). - [ ] Smoke tests for top-level fn + higher-order-type both produce the new shape. - [ ] `cargo test --workspace --exclude v2-compiler-tests` / `clippy --all-targets -- -D warnings` / `fmt --all --check` clean. - [ ] DB-8 fixed-point converges bit-identically. From ea9cb03c910095474c19dcb3a166e23127304929 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:07:36 -0400 Subject: [PATCH 06/13] WIP: T-I unenumerated effects/parser (dual) --- .../t-impossiblebugs-unenumerated-effects-parser-worker.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md index db3762fcf40..21a609f573b 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md @@ -19,8 +19,8 @@ ## Read first - **[`docs/briefs/t-impossiblebugs-unenumerated-effects-worker.md`](t-impossiblebugs-unenumerated-effects-worker.md)** — sibling substrate sub-lane brief (post-this-PR-narrowed). The substrate side blocks on this PR landing. -- **[`src/v3/std/parse_surface.dag:71-75`](../../src/v3/std/parse_surface.dag)** — `SurfaceType.Arrow` declaration; today carries `inputs: List` + `output: SurfaceType` + `span: SourceSpan`. **No `declared_effects` field**. New surface-syntax + carrier extension lands here. -- **[`src/v3/std/parse_surface.dag:185-199`](../../src/v3/std/parse_surface.dag)** — `SurfaceItem.Fn` declaration. Worker decides whether to put the declared-effects field on `Arrow` (cleaner, type-signature-level) or `Fn` (item-level only); surface choice in PR description. Recommend `Arrow` since effect-as-part-of-type-signature is the discipline anchor (per `feedback_no_annotations`). +- **[`docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md`](t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md)** — pre-prereq refactor brief. Lands `SurfaceArrow` (type-position arrow-shape carrier) + `FnSignature` (declaration-position arrow-shape carrier) + `NamedArrowInput` / `ArrowInput` input-element shapes. **This brief depends on that refactor having landed**; pre-flight check + STOP if it hasn't. +- **`SurfaceArrow` + `FnSignature` in `parse_surface.dag` (post-refactor)** — both arrow-shape sub-carriers. Today (pre-refactor) carries no `declared_effects` field on either. New surface-syntax + carrier extension lands on **both** sub-carriers per the refactor brief's carrier-distinction rationale (req 3): both are type-signature shapes per `feedback_no_annotations`, so effects must appear on each as a co-invariant — declaration-position effects (on `FnSignature`) and type-position effects (on `SurfaceArrow`) are real co-invariants, not bookkeeping duplication. - **[`src/v3/compiler/parse_parser_body.txt`](../../src/v3/compiler/parse_parser_body.txt)** — parse-body algorithm authority. The function-type / function-item parsing paths produce the `Arrow` / `Fn` surface shapes; new declared-effects syntax lands here. Worker picks syntax (recommend post-arrow-output suffix: `fn foo() -> T effects [Read, Write]` or similar; surface choice in PR description). - **[`src/v3/compiler/src/parse_generated.rs`](../../src/v3/compiler/src/parse_generated.rs)** — auto-generated from `parse_surface.dag` + `parse_parser_body.txt`. Per `feedback_no_generated_code_on_disk`, edits flow through `.dag` + `.txt` authority then regen. **No hand edits to `parse_generated.rs`**. - **[`src/v3/std/substrate.dag:154-163`](../../src/v3/std/substrate.dag)** — `Declaration` and `Arrow` connectives have **zero** effect slots today; adding `declared_effects: List` to `Arrow` is purely additive on the substrate side. @@ -33,7 +33,7 @@ The substrate `declared_effects` carrier cannot land standalone — the parser m This sub-lane lands the parser side. Output: -1. New `declared_effects: List` (or equivalent — element shape worker's call) on `SurfaceType.Arrow` (or `SurfaceItem.Fn` — worker picks; recommend `Arrow`). +1. New `declared_effects: List` (or equivalent — element shape worker's call) on **both** `SurfaceArrow` (type position) and `FnSignature` (declaration position) — per refactor-brief carrier-distinction rationale (req 3), effects are a co-invariant on both arrow-shape sub-carriers, not a single placement choice. 2. Surface syntax: post-arrow-output suffix expressing the declared effect set (recommended `fn foo() -> T effects [Read, Write]` or worker-equivalent; surface in PR description). 3. Lowering: surface `declared_effects` lowers to `Declaration.connective` (or sibling `Arrow` substrate field) carrying the resolved `List`. 4. Regen `parse_generated.rs` from authority. From fbdd0fbe4f46d60d74b902fbc8d524b3c58fcd8a Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:08:36 -0400 Subject: [PATCH 07/13] docs(briefs): scrub stale parser-effects authority drift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex BLOCKING at sha 653b2e00: refactor brief line 152 claimed parser- effects brief didn't need editing, but parser-effects brief still pointed workers at SurfaceType.Arrow / SurfaceItem.Fn (pre-refactor shapes) and framed Arrow-vs-Fn as a worker placement choice. Refactor brief req 3 mandates declared_effects lands on BOTH FnSignature and SurfaceArrow as a co-invariant. Two-file fix: 1. Parser-effects brief: removed worker-placement-choice language; declared_effects now mandated on both FnSignature + SurfaceArrow. Read-first cites the refactor brief as pre-prereq. Pre-flight check added as slice step 1. Coproduct dissolution receipt requirement removed (no new variants — purely additive field on two existing carriers); replaced with structural-carrier rationale requirement. Title + smoke test + acceptance updated to reference FnSignature. 2. Refactor brief: line 152 reworded to reflect that parser-effects brief WAS updated alongside, not "doesn't need editing." P1 Documentation Describes Live State / P2 Boundary Discipline violation closed. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...erated-effects-fn-arrow-refactor-worker.md | 2 +- ...bugs-unenumerated-effects-parser-worker.md | 21 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index 5e59bf64d83..7dab4cabcaf 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -149,7 +149,7 @@ Surface to Director. - Single PR. Title: `feat(v3): T-ImpossibleBugs Fn→Arrow refactor — SurfaceItem.Fn carries Arrow-shaped signature (pre-prereq for unenumerated-effects parser sub-lane)`. - PR body cites this brief + addresses each of the 6 reqs + documents structural-carrier rationale for `ArrowInput`. -- On merge: signal Director; Director signals sibling parser sub-lane (`t-impossiblebugs-unenumerated-effects-parser-worker.md`) is now dispatchable. The parser sub-lane brief itself does NOT need editing — it already assumes `Arrow` is the load-bearing carrier; this PR makes that assumption true. +- On merge: signal Director; Director signals sibling parser sub-lane (`t-impossiblebugs-unenumerated-effects-parser-worker.md`) is now dispatchable. The parser sub-lane brief was updated alongside this brief (same PR) to point at `FnSignature` + `SurfaceArrow` (post-refactor) and to mandate co-invariant placement of `declared_effects` on both carriers per req 3's carrier-distinction rationale. ## Cross-manager note diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md index 21a609f573b..019ab7c67cb 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md @@ -45,26 +45,27 @@ Today the parser silently accepts no effect declaration; after this PR, the surf ## Six consumer-side requirements -1. **`declared_effects` field on `SurfaceType.Arrow`** (or `SurfaceItem.Fn` — worker picks + surfaces rationale; recommend `Arrow`). Element shape: `List` where each entry resolves to an `OperationEffect` declaration (Read/Upsert/Create/Append/Delete from `effects.dag`). **Coproduct dissolution receipt** for any new variant per `feedback_coproduct_dissolution` and the `LoopBound` precedent at `docs/design-mutual-recursion-lowering.md:117-134`. +1. **`declared_effects` field on both `SurfaceArrow` and `FnSignature`** (post-refactor sub-carriers; not a worker placement choice — co-invariant per refactor-brief req 3). Element shape: `List` where each entry resolves to an `OperationEffect` declaration (Read/Upsert/Create/Append/Delete from `effects.dag`). No new variants (purely additive field on two existing carriers); structural-carrier rationale required in PR body explaining why this isn't `feedback_parallel_representation_debt` (answer: each sub-carrier names a different position — declaration vs. type — both genuinely require their own effect set). 2. **Surface syntax** for the declared-effects clause. Worker picks (recommend post-arrow-output suffix); document choice + reasoning in PR description. The syntax is part of the function type signature, not an annotation (per `feedback_no_annotations`). 3. **`looks_like_effects_clause` lookahead** at the relevant parse site (function type / item parsing); routes into a new `parse_effects_clause` body. Disambiguation must not break existing function syntax. 4. **`parse_effects_clause` body parser** producing `List` (or equivalent) with the parsed effect-type references. 5. **Lowerer extension** producing the post-parser substrate carrier on `Arrow` (or `Fn`-level) declarations. Resolves each surface effect-type to its `OperationEffect` declaration. -6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType.Arrow` / `SurfaceItem.Fn` updated for the new field. **No wildcard `_` swallowing**; per `feedback_missing_checks_review_heuristic`. +6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceArrow` / `FnSignature` updated for the new `declared_effects` field. **No wildcard `_` swallowing**; per `feedback_missing_checks_review_heuristic`. ## Slice — parser extension -1. Add `declared_effects` field to `SurfaceType.Arrow` (per req 1) in `parse_surface.dag`. Author coproduct dissolution receipt for any new variant. -2. Edit `parse_parser_body.txt` (per reqs 2 + 3 + 4): add `looks_like_effects_clause` + `parse_effects_clause`; route from the function-type/item parse entry. -3. Add lowerer extension (per req 5) producing the post-parser substrate carrier; resolve each surface effect to its `OperationEffect` declaration. -4. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). -5. Exhaustive-match audit + updates (per req 6). -6. Smoke test: parser accepts `fn read_user(id: String) -> User effects [Read]` and produces a function declaration with `declared_effects = [ReadEffect]`. **NOTE**: this PR does NOT consume the field via lens (sibling substrate sub-lane does that); after this PR the field is populated but unread. That's expected; the sibling sub-lane closes that path. Test should assert the parser-output shape, not end-to-end lens behavior. +1. **Pre-flight check**: confirm the Fn→Arrow refactor brief has merged and `parse_surface.dag` carries `SurfaceArrow` + `FnSignature` + `NamedArrowInput`/`ArrowInput`. STOP if not — sequencing error. +2. Add `declared_effects` field to **both** `SurfaceArrow` and `FnSignature` (per req 1) in `parse_surface.dag`. Add structural-carrier rationale (no new coproduct variants; field-level addition on two existing carriers). +3. Edit `parse_parser_body.txt` (per reqs 2 + 3 + 4): add `looks_like_effects_clause` + `parse_effects_clause`; route from the function-type/item parse entry. +4. Add lowerer extension (per req 5) producing the post-parser substrate carrier; resolve each surface effect to its `OperationEffect` declaration. +5. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). +6. Exhaustive-match audit + updates (per req 6). +7. Smoke test: parser accepts `fn read_user(id: String) -> User effects [Read]` and produces a function declaration whose `signature: FnSignature` carries `declared_effects = [ReadEffect]`. **NOTE**: this PR does NOT consume the field via lens (sibling substrate sub-lane does that); after this PR the field is populated but unread. That's expected; the sibling sub-lane closes that path. Test should assert the parser-output shape, not end-to-end lens behavior. ## Acceptance - [ ] All 6 consumer-side requirements satisfied + documented in PR body. -- [ ] `declared_effects` field on `SurfaceType.Arrow` (or `SurfaceItem.Fn`); coproduct dissolution receipt landed. +- [ ] `declared_effects` field on **both** `SurfaceArrow` and `FnSignature` (post-refactor sub-carriers); structural-carrier rationale documented in PR body. - [ ] `looks_like_effects_clause` + `parse_effects_clause` in `parse_parser_body.txt`. - [ ] Lowerer resolves surface effects to `OperationEffect` declarations. - [ ] `parse_generated.rs` regenerated; no hand edits. @@ -95,7 +96,7 @@ Surface to Director. ## Reporting -- Single PR. Title: `feat(v3): T-ImpossibleBugs parser-extension — declared_effects on SurfaceType.Arrow (prereq for unenumerated-effects substrate sub-lane)`. +- Single PR. Title: `feat(v3): T-ImpossibleBugs parser-extension — declared_effects on FnSignature + SurfaceArrow (prereq for unenumerated-effects substrate sub-lane)`. - PR body cites this brief + addresses each of the 6 reqs + documents surface-syntax + Arrow-vs-Fn placement choices. - On merge: signal Director; Director signals sibling substrate sub-lane (`t-impossiblebugs-unenumerated-effects-worker.md`) is now dispatchable. From 6a5a9f5c0ab419946bc197de1a417aba5d2f173c Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:24:25 -0400 Subject: [PATCH 08/13] docs(briefs): scrub residual "Arrow once" wording from refactor brief MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex non-blocking at sha fbdd0fbe: refactor brief still framed the downstream parser-effects work as "add declared_effects on Arrow once" in two spots (header blockquote + non-goals line) — conflicting with the parser-effects brief's mandate to land on both FnSignature and SurfaceArrow as a co-invariant. P2 single-authority drift. Updated both spots to reference the two-carrier plan explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...ebugs-unenumerated-effects-fn-arrow-refactor-worker.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index 7dab4cabcaf..7ed001f88c7 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -17,8 +17,10 @@ > > This brief reshapes `SurfaceItem.Fn` to carry an `Arrow`-shaped > signature so that the downstream parser sub-lane can land -> `declared_effects` on `Arrow` once and have it apply uniformly to -> top-level functions and higher-order function types. Reports back to +> `declared_effects` on the two arrow-shape sub-carriers (`FnSignature` +> for declaration position; `SurfaceArrow` for type position) as a +> co-invariant — both genuinely require their own effect set per the +> carrier-distinction rationale (req 3). Reports back to > Director (`zesty-bear-812`); Surface Manager territory overlap > (parser surface-syntax authority). > @@ -139,7 +141,7 @@ Surface to Director. ## Non-goals -- **Not adding `declared_effects`.** That's the sibling parser-effects sub-lane; this PR makes `Arrow` the load-bearing site so that the *next* PR can add the field once and have it apply uniformly. +- **Not adding `declared_effects`.** That's the sibling parser-effects sub-lane; this PR establishes the two arrow-shape sub-carriers (`FnSignature` + `SurfaceArrow`) so the next PR can land `declared_effects` on each as a co-invariant per req 3's carrier-distinction rationale. - **Not refactoring `SurfaceExpr::Lambda`.** Lambdas don't have explicit type signatures today; they're out of scope. - **Not refactoring substrate-side `Declaration` / `Arrow`.** Surface-side only. - **Not changing surface syntax.** The user-visible function-declaration syntax is unchanged; this is a pure construction-site refactor. From 19c567707d01f2b617bff51d1330aad3119ef381 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:27:06 -0400 Subject: [PATCH 09/13] WIP: T-I unenumerated effects/parser (dual) --- ...erated-effects-fn-arrow-refactor-worker.md | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index 7ed001f88c7..c4ccde15b65 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -53,13 +53,13 @@ The downstream parser-effects sub-lane needs to add a `declared_effects` field t Both are dead-ends. The constructive fix is to dissolve the split: `SurfaceType.Arrow` carries the structural function-type signature uniformly, and `SurfaceItem.Fn` carries an `Arrow`-shaped signature alongside the bind-site param-name + refinement metadata. -This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `ArrowInput` carries optional name + refinement alongside the type) and reshapes `SurfaceItem.Fn` to use that `Arrow` shape directly. Effects do NOT land in this PR — that's the next sub-lane in the chain. +This sub-lane introduces two arrow-shape sub-carriers — `SurfaceArrow` (type position, `inputs: List` to match today's parser surface) wrapped by `SurfaceType.Arrow(SurfaceArrow)`, and `FnSignature` (declaration position, `inputs: List` so binderless params are structurally unrepresentable) carried directly by `SurfaceItem.Fn`. Effects do NOT land in this PR — that's the next sub-lane in the chain. **Top-level functions + higher-order function types** for this PR. Closures / lambdas (which today use `SurfaceExpr::Lambda` with no explicit type signature) — out of scope; `Lambda` continues to carry `params: List` + `body` as today. ## Six consumer-side requirements -1. **New input-element shapes in `parse_surface.dag`.** Two carriers, distinguishing declaration position (always named) from type position (mixed) — both illegal-state-unrepresentable per `feedback_state_space_vs_behavioral_invariants`: +1. **New `NamedArrowInput` carrier in `parse_surface.dag`.** Single new carrier — declaration-position-only, since the parser today only accepts anonymous inputs in type position (verified at HEAD: `src/v3/compiler/parse_parser_body.txt:864-877` `parse_atom_type` reads `inputs` via `parse_type_expr_list_until`, which parses pure type expressions with no name-binding): ``` type NamedArrowInput { @@ -67,14 +67,10 @@ This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `A ty: SurfaceType refinement: SurfaceExpr? } - - type ArrowInput - = Anonymous { ty: SurfaceType } - | Named(NamedArrowInput) ``` - `NamedArrowInput` is the load-bearing atom for declaration position (function-decl params always have a name, so the binder is structurally mandatory; refinement remains optional because not every param is refined). `ArrowInput` is the coproduct used in type position only — a higher-order type `fn(A, B) -> C` may carry anonymous entries (no binder) or named entries (e.g., `fn(x: Int) -> ...`). Refinement-without-binder is structurally unrepresentable in either carrier. **Coproduct dissolution receipt** mandatory for `ArrowInput` per `feedback_coproduct_dissolution` and the `LoopBound` precedent at `docs/design-mutual-recursion-lowering.md:117-134` — worker authors the receipt in `parse_surface.dag` adjacent to the type. Receipt should also address why this isn't `feedback_parallel_representation_debt` against `SurfaceParam`: `SurfaceParam` is the *data of a param at a binding site* (lowerer-binding view, today); `NamedArrowInput` is the *type-signature view at declaration position*; `ArrowInput` is the *type-signature view at type-annotation position*. Once the refactor lands, `SurfaceParam` dissolves into `NamedArrowInput` (req 3). -2. **`SurfaceType.Arrow` refactored to wrap a typed `SurfaceArrow` sub-carrier.** Introduce a new top-level struct `SurfaceArrow { inputs: List, output: SurfaceType, span: SourceSpan }` (mixed inputs, type position), then change `SurfaceType.Arrow(SurfaceArrow)` (single positional payload, not record fields). This makes the type-position arrow-shape a typed entity that consumers can hold directly without destructuring through `SurfaceType` first. **No silent compatibility shim**; existing callers updated per req 6. + `NamedArrowInput` is the load-bearing atom for declaration position (function-decl params always have a name, so the binder is structurally mandatory; refinement remains optional because not every param is refined). Refinement-without-binder is structurally unrepresentable. Type-position inputs continue to be raw `SurfaceType` entries (no binder, no refinement — the parser doesn't surface either today, so there's nothing to model). **No `ArrowInput` coproduct** — earlier drafts proposed `ArrowInput = Anonymous { ty } | Named(NamedArrowInput)` for a hypothetical `fn(x: A) -> B` type-position syntax that the parser doesn't accept today; pre-resolving the simplification per Claude-API exploratory observation. If a future PR adds named binders in type position, that PR introduces the coproduct (with its own dissolution receipt at that time), not this one. **Structural-carrier rationale** (mandatory in PR description) addressing why `NamedArrowInput` isn't `feedback_parallel_representation_debt` against `SurfaceParam`: `SurfaceParam` is the *data of a param at a binding site* (lowerer-binding view, today); `NamedArrowInput` is the *type-signature view at declaration position*. Once the refactor lands, `SurfaceParam` dissolves into `NamedArrowInput` (req 3). +2. **`SurfaceType.Arrow` refactored to wrap a typed `SurfaceArrow` sub-carrier.** Introduce a new top-level struct `SurfaceArrow { inputs: List, output: SurfaceType, span: SourceSpan }` (anonymous inputs, type position — matches today's parser surface), then change `SurfaceType.Arrow(SurfaceArrow)` (single positional payload, not record fields). The wrapper variant carries **no separate span** — `SurfaceArrow.span` is the source-of-truth span for the arrow; consumers reading `SurfaceType::Arrow(arrow)` use `arrow.span`. This makes the type-position arrow-shape a typed entity that consumers can hold directly without destructuring through `SurfaceType` first, and avoids the two-spans-per-arrow risk per Claude-API exploratory observation. **No silent compatibility shim**; existing callers updated per req 6. 3. **`SurfaceItem.Fn` + `SurfaceItem.FnExternalBody` refactored to carry a typed `FnSignature` sub-carrier with restricted inputs.** Drop `params: List` + `return_type: SurfaceType` fields; replace with `signature: FnSignature` where: ``` @@ -85,12 +81,12 @@ This sub-lane reshapes `SurfaceType.Arrow` to carry `List` (where `A } ``` - `inputs: List` (not `List`) makes binderless params **structurally unrepresentable in declaration position** per `feedback_state_space_vs_behavioral_invariants` — rejecting an earlier draft's behavioral fall-back where the lowerer would have surfaced a Diagnostic for `ArrowInput::Anonymous` inside `Fn.signature`. The parser cannot construct `Fn { signature: FnSignature { inputs: [] } }` because no `Anonymous` variant exists in `NamedArrowInput`. The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.inputs[i]: NamedArrowInput`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. + `inputs: List` (not `List`) makes binderless params **structurally unrepresentable in declaration position** per `feedback_state_space_vs_behavioral_invariants` — rejecting an earlier draft's behavioral fall-back where the lowerer would have surfaced a Diagnostic for an anonymous-shape inside `Fn.signature`. The parser cannot construct `Fn { signature: FnSignature { inputs: [] } }` because the input element type is `NamedArrowInput` directly. The bound-name + refinement information that today lives on `SurfaceParam` flows through `signature.inputs[i]: NamedArrowInput`. **`SurfaceParam` is fully retired** by this PR — no consumers reference it post-refactor. Worker should grep-survey + cite count in PR description. `FnSignature` carries its own `span: SourceSpan`; the wrapping context (`SurfaceItem.Fn`) consumes it directly without authoring a parallel span. - **Carrier-distinction rationale (mandatory in PR description).** `FnSignature` and `SurfaceArrow` are both arrow-shape sub-carriers but encode different invariants: `FnSignature.inputs: List` (declaration must bind names so the body can reference them); `SurfaceArrow.inputs: List` (type position; binders optional). This is concept distinction, not parallel-representation debt — same justification as `SurfaceParam` vs `NamedArrowInput` carrying overlapping fields but different concepts. The downstream parser-effects sub-lane (#799 brief) lands `declared_effects` on **both** `FnSignature` and `SurfaceArrow` — both are type-signature shapes per `feedback_no_annotations`, so the discipline anchor is satisfied per-carrier; this is co-invariant duplication, not bookkeeping duplication. -4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) routes its parsed params directly through `NamedArrowInput` construction → `FnSignature` → `SurfaceItem::Fn { signature: FnSignature, ... }`. The higher-order type parse path (where `SurfaceType::Arrow(SurfaceArrow)` is constructed for type annotations) constructs `ArrowInput::Anonymous { ty }` or `ArrowInput::Named(NamedArrowInput { ... })` per the syntactic form. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. -5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature.inputs: List` + `Fn.signature.output`. Per-input destructuring is uniform — every entry is a `NamedArrowInput` carrying `name` + `ty` + `refinement?`; **no `ArrowInput::Anonymous` arm to handle in declaration position** (structurally absent per req 3). Type-position consumers (those reading `SurfaceArrow.inputs: List`) branch on `Anonymous` vs `Named`. This is surface-side reshaping; substrate-side `Declaration` + `Arrow` untouched. **No wildcard arms** anywhere. -6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated for the new shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }`, it now destructures `Fn { signature: FnSignature { inputs, output, .. }, ... }` and reads each input as a `NamedArrowInput { name, ty, refinement }`. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures `SurfaceType::Arrow(arrow)` and reads `arrow.inputs: List`, branching per-entry on `Anonymous { ty }` vs `Named(named)`. + **Carrier-distinction rationale (mandatory in PR description).** `FnSignature` and `SurfaceArrow` are both arrow-shape sub-carriers but encode different invariants: `FnSignature.inputs: List` (declaration must bind names so the body can reference them); `SurfaceArrow.inputs: List` (type position; the parser doesn't accept binders in this position today). This is concept distinction, not parallel-representation debt — same justification as `SurfaceParam` vs `NamedArrowInput` carrying overlapping fields but different concepts. The downstream parser-effects sub-lane lands `declared_effects` on **both** `FnSignature` and `SurfaceArrow` — both are type-signature shapes per `feedback_no_annotations`, so the discipline anchor is satisfied per-carrier; this is co-invariant duplication, not bookkeeping duplication. +4. **`parse_parser_body.txt` updates.** The function-item parse path (where `SurfaceItem::Fn` is constructed) routes its parsed params directly through `NamedArrowInput` construction → `FnSignature` → `SurfaceItem::Fn { signature: FnSignature, ... }`. The higher-order type parse path (where `SurfaceType::Arrow(SurfaceArrow)` is constructed for type annotations) constructs `SurfaceArrow { inputs: List, output, span }` directly — no per-input variant branching, since type-position inputs are anonymous-only today. **No new lookahead** — this is a pure construction-site refactor; the surface syntax doesn't change. +5. **Lowerer extension.** Every consumer that today reads `Fn.params` + `Fn.return_type` is updated to read `Fn.signature.inputs: List` + `Fn.signature.output`. Per-input destructuring is uniform — every entry is a `NamedArrowInput` carrying `name` + `ty` + `refinement?`. Type-position consumers (those reading `SurfaceArrow.inputs: List`) read each input as a raw `SurfaceType`. This is surface-side reshaping; substrate-side `Declaration` + `Arrow` untouched. **No wildcard arms** anywhere. +6. **Exhaustive-match audit + updates.** Every `match` site over `SurfaceType::Arrow` (snapshot grep: ~5 hits) and `SurfaceItem::Fn` / `FnExternalBody` (snapshot grep: ~20 hits) updated for the new shapes. **No wildcard `_` swallowing** per `feedback_missing_checks_review_heuristic`. Where a consumer today destructures `Fn { params, return_type, ... }`, it now destructures `Fn { signature: FnSignature { inputs, output, .. }, ... }` and reads each input as a `NamedArrowInput { name, ty, refinement }`. Where a consumer today destructures `SurfaceType::Arrow { inputs, .. }` over `List`, it now destructures `SurfaceType::Arrow(arrow)` and reads `arrow.inputs: List` — same element shape as today, just routed through the typed sub-carrier. ## Slice — `Fn`→`Arrow` refactor From 8cd23151df2cbb6f002a3f2712c83354267c02b8 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:27:58 -0400 Subject: [PATCH 10/13] docs(briefs): pre-resolve type-position simplification + drop wrapper variant span MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude API exploratory at sha fbdd0fbe flagged two pre-dispatch tightenings: 1. The STOP for "ArrowInput simplification if type-position doesn't accept named binders today" was a worker-time deferral. Verified at HEAD (src/v3/compiler/parse_parser_body.txt:864-877 parse_atom_type reads inputs via parse_type_expr_list_until — pure type expressions, no binding): type position is anonymous-only today. Pre-resolved. - ArrowInput coproduct dropped entirely. - SurfaceArrow.inputs simplifies to List (today's shape preserved, just routed through the typed sub-carrier). - Coproduct dissolution receipt requirement removed; replaced with structural-carrier rationale for NamedArrowInput. - STOP rephrased: STOP if dispatch grep surfaces a parse path that does accept fn(x: A) -> B (would invalidate the simplification). 2. Two-spans-per-arrow risk (SurfaceType::Arrow wrapper variant + wrapped SurfaceArrow.span). Resolved: the wrapper variant carries no separate span; SurfaceArrow.span is source-of-truth. Brief is now leaner and pre-resolves the worker-discretion question that Claude API recommended pre-resolving. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...erated-effects-fn-arrow-refactor-worker.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index c4ccde15b65..c8c78d6530f 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -90,23 +90,23 @@ This sub-lane introduces two arrow-shape sub-carriers — `SurfaceArrow` (type p ## Slice — `Fn`→`Arrow` refactor -1. Add `NamedArrowInput` + `ArrowInput` (per req 1) to `parse_surface.dag` with coproduct dissolution receipt for `ArrowInput`. -2. Add `SurfaceArrow` typed sub-carrier (per req 2; type position; `inputs: List`); refactor `SurfaceType.Arrow` to wrap it as a single positional payload. +1. Add `NamedArrowInput` (per req 1) to `parse_surface.dag` with structural-carrier rationale (no coproduct, no dissolution receipt — single carrier). +2. Add `SurfaceArrow` typed sub-carrier (per req 2; type position; `inputs: List`); refactor `SurfaceType.Arrow` to wrap it as a single positional payload (no separate span on the variant). 3. Add `FnSignature` typed sub-carrier (per req 3; declaration position; `inputs: List`); refactor `SurfaceItem.Fn` + `FnExternalBody`: drop `params` + `return_type`, add `signature: FnSignature`. Retire `SurfaceParam`. -4. Edit `parse_parser_body.txt` (per req 4): update function-item construction (→ `NamedArrowInput` → `FnSignature`) + higher-order-type construction (→ `ArrowInput::Anonymous` or `Named` → `SurfaceArrow`). +4. Edit `parse_parser_body.txt` (per req 4): update function-item construction (→ `NamedArrowInput` → `FnSignature`) + higher-order-type construction (→ `SurfaceArrow` with `List` inputs, no per-input variant). 5. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). -6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Declaration-position consumers read `NamedArrowInput` directly (no variant branching). Type-position consumers branch on `Anonymous` vs `Named`. +6. Lowerer extension (per req 5): update every `Fn` / `Arrow` consumer in `src/v3/compiler/src/lower.rs` + sibling consumer files. Declaration-position consumers read `NamedArrowInput` directly. Type-position consumers read `SurfaceType` directly. No variant branching anywhere. 7. Exhaustive-match audit + updates (per req 6) across every consumer. 8. Smoke + regression tests (note: v3 surface requires `fn(...)` prefix for higher-order types per `parse_atom_type`'s `TokenKind::KwFn` gate — examples below use that form): - Parser accepts `fn foo(x: Int, y: Bool) -> String { ... }` and produces `Fn { signature: FnSignature { inputs: [NamedArrowInput { name: "x", ty: Int, refinement: None }, NamedArrowInput { name: "y", ty: Bool, refinement: None }], output: String, .. }, .. }`. - - Parser accepts `fn higher_order(f: fn(Int, Bool) -> String) -> Int { ... }` and produces a `NamedArrowInput` for `f` whose `ty` is `SurfaceType::Arrow(SurfaceArrow { inputs: [ArrowInput::Anonymous { ty: Int }, ArrowInput::Anonymous { ty: Bool }], output: String, .. })`. + - Parser accepts `fn higher_order(f: fn(Int, Bool) -> String) -> Int { ... }` and produces a `NamedArrowInput` for `f` whose `ty` is `SurfaceType::Arrow(SurfaceArrow { inputs: [Int, Bool], output: String, .. })`. - Existing v3 compiler tests pass unchanged (refactor is structurally equivalent on the surface; no surface-syntax change). ## Acceptance - [ ] All 6 consumer-side requirements satisfied + documented in PR body. -- [ ] `NamedArrowInput` + `ArrowInput` (coproduct: `Anonymous` | `Named(NamedArrowInput)`) in `parse_surface.dag` with coproduct dissolution receipt for `ArrowInput`. -- [ ] `SurfaceArrow` typed sub-carrier (`inputs: List`) in `parse_surface.dag`; `SurfaceType.Arrow(SurfaceArrow)` wraps it. +- [ ] `NamedArrowInput` carrier in `parse_surface.dag` with structural-carrier rationale (no coproduct introduced — type-position binders aren't surfaced today). +- [ ] `SurfaceArrow` typed sub-carrier (`inputs: List`) in `parse_surface.dag`; `SurfaceType.Arrow(SurfaceArrow)` wraps it (no separate span on the wrapper variant — `SurfaceArrow.span` is source-of-truth). - [ ] `FnSignature` typed sub-carrier (`inputs: List`) in `parse_surface.dag`; `SurfaceItem.Fn` + `FnExternalBody` carry `signature: FnSignature` (binderless params structurally unrepresentable in declaration position). - [ ] PR description includes carrier-distinction rationale for `FnSignature` vs `SurfaceArrow` (both arrow-shape; different invariants per req 3). - [ ] `SurfaceParam` retired (zero references post-refactor). @@ -125,14 +125,14 @@ This sub-lane introduces two arrow-shape sub-carriers — `SurfaceArrow` (type p Surface to Director. - **Higher-order-type surface syntax accepts named params today** — if `(x: A, y: B) -> C` is already a valid surface form (i.e., `SurfaceType::Arrow.inputs` already carries names somewhere the snapshot grep missed), STOP. The refactor is then a *renaming* not a *promotion*; the structural-carrier rationale needs to reflect that. -- **`SurfaceParam` has consumers beyond `Fn` / `FnExternalBody`** — req 3 retires `SurfaceParam`. If grep surfaces consumers in (e.g.) `Lambda`, `Match`, or other carriers, STOP. Either keep `SurfaceParam` as a live carrier (and have `ArrowInput` be a sibling) or scope a coupled retirement. -- **Higher-order types appear in positions that today silently drop refinements** — if existing `Arrow.inputs: List` consumers somewhere assume the type carries no refinement (and the new `ArrowInput.refinement: Some` would surface a previously-impossible state), STOP. Fail-closed at the point of inspection, not silent fall-through. +- **`SurfaceParam` has consumers beyond `Fn` / `FnExternalBody`** — req 3 retires `SurfaceParam`. If grep surfaces consumers in (e.g.) `Lambda`, `Match`, or other carriers, STOP. Either keep `SurfaceParam` as a live carrier (and have `NamedArrowInput` be a sibling) or scope a coupled retirement. +- **Type-position higher-order surface accepts named binders** — req 1 + req 2 assume type-position inputs are anonymous-only (verified at HEAD `parse_atom_type:864-877`). If grep / re-verification at dispatch surfaces a parse path that does accept `fn(x: A) -> B`, STOP. The simplification (no `ArrowInput` coproduct) is invalidated; brief needs updating to introduce the coproduct + dissolution receipt. - **`parse_parser_body.txt` edits cascade beyond function-item / higher-order-type construction** — STOP. Cross-cutting parser changes need Surface Manager coordination. - **Exhaustive-match audit reveals consumer using wildcard `_`** — STOP. Surface a fix decision (this PR vs follow-up). - **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: FnSignature` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. - **`SurfaceArrow` / `FnSignature` introduction cascades into substrate authority** — reqs 2 + 3 introduce two top-level `parse_surface.dag` carriers. If grep surfaces consumers that expect `SurfaceType::Arrow { inputs, output, span }` as record-style fields (rather than `Arrow(SurfaceArrow)` positional payload) and updating them cascades beyond `lower.rs` + immediate parse consumers, STOP. May indicate a smaller-blast-radius shape (e.g., keeping `Arrow` as record-style and instead defining the sub-carriers as type aliases / typed views rather than wrapping payloads) is preferable. - **Type-position higher-order syntax accepts named binders today** (`fn(x: A) -> B`) — req 1 / `ArrowInput::Named(NamedArrowInput)` is the path. If the parser doesn't currently accept that form (i.e., type-position is anonymous-only on the surface today), worker may simplify `ArrowInput` to a single non-coproduct shape (just `Anonymous { ty }`-equivalent) and surface that simplification with rationale. STOP if the simplification would conflict with downstream effect-on-Arrow consumer expectations. -- **DB-11 / refinement-strip interaction surfaces** (`infer.rs:3693-3703`) — if refinements on `ArrowInput` interact with DB-11's refinement strip in a non-obvious way, STOP. +- **DB-11 / refinement-strip interaction surfaces** (`infer.rs:3693-3703`) — if refinements on `NamedArrowInput` interact with DB-11's refinement strip in a non-obvious way, STOP. - **DB-8 fixed-point drifts** — STOP immediately. ## Non-goals @@ -146,7 +146,7 @@ Surface to Director. ## Reporting - Single PR. Title: `feat(v3): T-ImpossibleBugs Fn→Arrow refactor — SurfaceItem.Fn carries Arrow-shaped signature (pre-prereq for unenumerated-effects parser sub-lane)`. -- PR body cites this brief + addresses each of the 6 reqs + documents structural-carrier rationale for `ArrowInput`. +- PR body cites this brief + addresses each of the 6 reqs + documents structural-carrier rationale for `NamedArrowInput` and the `FnSignature` vs `SurfaceArrow` carrier-distinction rationale. - On merge: signal Director; Director signals sibling parser sub-lane (`t-impossiblebugs-unenumerated-effects-parser-worker.md`) is now dispatchable. The parser sub-lane brief was updated alongside this brief (same PR) to point at `FnSignature` + `SurfaceArrow` (post-refactor) and to mandate co-invariant placement of `declared_effects` on both carriers per req 3's carrier-distinction rationale. ## Cross-manager note From e977932e0ec888c5443d9606a8951db3fd649374 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:36:31 -0400 Subject: [PATCH 11/13] docs(briefs): split parser-effects smoke into parser-stage + lowerer-stage tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAI-pro BLOCKING at sha 6a5a9f5c: parser-effects brief smoke test asserted declared_effects = [ReadEffect] at the parser-output stage, but req 1 declares the parser carrier as List and req 5 assigns OperationEffect resolution to the lowerer. Asserting the resolved variant at the parser-output boundary either makes the parser do semantic resolution too early (boundary violation) or pins a post-lowerer fact at the parse boundary (facts-don't-flow-forward). Fix: split into two smoke tests at the right stage boundaries — parser smoke asserts the SurfaceType::Named "Read" reference; lowerer smoke asserts resolution to ReadEffect. Acceptance bullet updated to match. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../t-impossiblebugs-unenumerated-effects-parser-worker.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md index 019ab7c67cb..b8d9c1911d4 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md @@ -60,7 +60,10 @@ Today the parser silently accepts no effect declaration; after this PR, the surf 4. Add lowerer extension (per req 5) producing the post-parser substrate carrier; resolve each surface effect to its `OperationEffect` declaration. 5. Regen `parse_generated.rs` (per `feedback_no_generated_code_on_disk`). 6. Exhaustive-match audit + updates (per req 6). -7. Smoke test: parser accepts `fn read_user(id: String) -> User effects [Read]` and produces a function declaration whose `signature: FnSignature` carries `declared_effects = [ReadEffect]`. **NOTE**: this PR does NOT consume the field via lens (sibling substrate sub-lane does that); after this PR the field is populated but unread. That's expected; the sibling sub-lane closes that path. Test should assert the parser-output shape, not end-to-end lens behavior. +7. Smoke tests at the right stage boundaries (parser-output vs. lowerer-resolved — facts-flow-forward discipline): + - **Parser smoke**: parser accepts `fn read_user(id: String) -> User effects [Read]` and produces a function declaration whose `signature: FnSignature` carries `declared_effects: List` with one entry — a `SurfaceType::Named { name: "Read", ... }` reference. Assert the parsed surface shape only; do NOT assert resolution to `OperationEffect`. + - **Lowerer smoke**: same source through the lowerer produces the resolved post-parser substrate carrier with `[ReadEffect]` (or whatever variant `derive_op_effect` / req 5's resolution produces). The boundary between the two tests is the parser→lowerer authority split. + - **NOTE**: this PR does NOT consume the field via lens (sibling substrate sub-lane does that); after this PR the field is populated and resolved but unread by any lens. That's expected; the sibling sub-lane closes that path. ## Acceptance @@ -70,7 +73,7 @@ Today the parser silently accepts no effect declaration; after this PR, the surf - [ ] Lowerer resolves surface effects to `OperationEffect` declarations. - [ ] `parse_generated.rs` regenerated; no hand edits. - [ ] All `SurfaceType` / `SurfaceItem` exhaustive-match sites updated. -- [ ] Parser smoke test: function with declared-effects clause parses to populated `declared_effects` field. +- [ ] Parser smoke test asserts surface shape only (`List` references); lowerer smoke test asserts resolution to `OperationEffect`. Stage boundary preserved. - [ ] `cargo test --workspace --exclude v2-compiler-tests` / `clippy --all-targets -- -D warnings` / `fmt --all --check` clean. - [ ] DB-8 fixed-point converges bit-identically. - [ ] SG-0 census deltas: regen-output updates land in REGEN_OUTPUTS partition. From a30f3b1923dc2a41f4c74daa6747d8be179c1c53 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:39:28 -0400 Subject: [PATCH 12/13] =?UTF-8?q?docs(briefs):=20convergence=20sweep=20?= =?UTF-8?q?=E2=80=94=20live=20carrier=20table=20+=20stale-authority=20scru?= =?UTF-8?q?b?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAI-pro meta-review at sha 91504d8c gave a tight three-action path to convergence. Executing. Action 1: Live carrier table added to refactor brief frame section. Single source of truth for which carrier sits at which position (declaration vs. type), what input element shape each takes, what's retired, what's absent in this PR, what's deferred to a future PR. Action 2: Mechanical stale-authority sweep across both briefs: - Refactor brief: line 35 `(A, B) -> C` → `fn(A, B) -> C` (parser requires fn(...) prefix per parse_atom_type KwFn gate). - Refactor brief: line 46 same fix. - Refactor brief: dropped duplicate STOP at line 134 referencing removed ArrowInput::Named(NamedArrowInput) shape — same condition already covered by line 129 STOP in the cleaned-up form. - Refactor brief: line 144 non-goals cleaned up "wraps each entry in ArrowInput::Anonymous { ty }" → describes actual post-PR shape (List at type-position layer). - Parser brief: lines 22 + 57 dropped `ArrowInput` from the pre-flight carrier list (it's not introduced). Action 3 (PR body handoff receipt) follows in the next push. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...umerated-effects-fn-arrow-refactor-worker.md | 17 +++++++++++++---- ...lebugs-unenumerated-effects-parser-worker.md | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md index c8c78d6530f..53050d072b1 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md @@ -32,7 +32,7 @@ ## Read first - **[`docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md`](t-impossiblebugs-unenumerated-effects-parser-worker.md)** — sibling parser sub-lane brief; blocks on this PR landing. The parser brief assumes `SurfaceType.Arrow` is the load-bearing function-type-signature carrier; this brief makes that assumption true on `Fn`. -- **[`src/v3/std/parse_surface.dag:60-75`](../../src/v3/std/parse_surface.dag)** — `SurfaceType.Arrow` declaration; today carries `inputs: List` (pure types, no names, no refinements) + `output: SurfaceType` + `span: SourceSpan`. Higher-order types written `(A, B) -> C` flow through this. +- **[`src/v3/std/parse_surface.dag:60-75`](../../src/v3/std/parse_surface.dag)** — `SurfaceType.Arrow` declaration; today carries `inputs: List` (pure types, no names, no refinements) + `output: SurfaceType` + `span: SourceSpan`. Higher-order types written `fn(A, B) -> C` flow through this (`fn(...)` prefix mandatory per `parse_atom_type` `KwFn` gate). - **[`src/v3/std/parse_surface.dag:33-37`](../../src/v3/std/parse_surface.dag)** — `SurfaceParam = { name: String, ty: SurfaceType, refinement: SurfaceExpr? }`. Carries the param-binding info that today lives parallel to `SurfaceType` on `Fn`. - **[`src/v3/std/parse_surface.dag:179-200`](../../src/v3/std/parse_surface.dag)** — `SurfaceItem.Fn` (and `FnExternalBody`); today: `name`, `type_params`, `params: List`, `return_type: SurfaceType`, `body`, `span`. The `params` + `return_type` split is the vestige this brief dissolves. - **[`src/v3/compiler/parse_parser_body.txt`](../../src/v3/compiler/parse_parser_body.txt)** — parse-body algorithm authority. The function-item path constructs `Fn { params, return_type, ... }`; this brief routes that construction through an `Arrow` signature. @@ -43,7 +43,7 @@ ## Frame -`SurfaceItem.Fn` today carries `params: List` + `return_type: SurfaceType` as two fields. There is no synthesized `Arrow` on the function declaration — `SurfaceType.Arrow` only appears when a higher-order function type is *written out as a type annotation* (e.g., a parameter typed `(A, B) -> C`). +`SurfaceItem.Fn` today carries `params: List` + `return_type: SurfaceType` as two fields. There is no synthesized `Arrow` on the function declaration — `SurfaceType.Arrow` only appears when a higher-order function type is *written out as a type annotation* (e.g., a parameter typed `fn(A, B) -> C`). This split is a vestige. Function declarations *are* arrows: their structural type signature is `(input₁, …, inputₙ) -> output`. The parallel encoding (separate `params` + `return_type` fields on `Fn`, separate `Arrow.inputs` + `Arrow.output` on `SurfaceType`) is `feedback_parallel_representation_debt` waiting to be dissolved — the same shape encoded twice. @@ -55,6 +55,16 @@ Both are dead-ends. The constructive fix is to dissolve the split: `SurfaceType. This sub-lane introduces two arrow-shape sub-carriers — `SurfaceArrow` (type position, `inputs: List` to match today's parser surface) wrapped by `SurfaceType.Arrow(SurfaceArrow)`, and `FnSignature` (declaration position, `inputs: List` so binderless params are structurally unrepresentable) carried directly by `SurfaceItem.Fn`. Effects do NOT land in this PR — that's the next sub-lane in the chain. +### Live carrier table (post-refactor) + +| Position | Carrier | Inputs element | Notes | +|---|---|---|---| +| Declaration (top-level `fn` items) | `FnSignature { inputs, output, span }` | `NamedArrowInput { name, ty, refinement: SurfaceExpr? }` | `name` mandatory (no `Anonymous` shape); refinement-without-binder structurally unrepresentable | +| Type annotation (higher-order `fn(...)`) | `SurfaceArrow { inputs, output, span }`, wrapped by `SurfaceType::Arrow(SurfaceArrow)` (no separate span on the variant) | `SurfaceType` | Anonymous-only; matches today's parser surface | +| Retired by this PR | `SurfaceParam` | — | Dissolved into `NamedArrowInput`; zero references post-refactor | +| **Absent** in this PR | `ArrowInput` | — | Earlier drafts proposed an `Anonymous \| Named` coproduct for type-position binders; type position is anonymous-only today, so the coproduct isn't introduced | +| Future-only | named type-position binders | — | If a future PR adds `fn(x: A) -> B` syntax, that PR introduces the type-position carrier (with its own dissolution receipt at that time) | + **Top-level functions + higher-order function types** for this PR. Closures / lambdas (which today use `SurfaceExpr::Lambda` with no explicit type signature) — out of scope; `Lambda` continues to carry `params: List` + `body` as today. ## Six consumer-side requirements @@ -131,7 +141,6 @@ Surface to Director. - **Exhaustive-match audit reveals consumer using wildcard `_`** — STOP. Surface a fix decision (this PR vs follow-up). - **Substrate-side `Arrow` shape needs a parallel refactor** — if the lowerer can't translate `Fn.signature: FnSignature` into the substrate `Declaration` / `Arrow` shape without also reshaping the substrate side, STOP. That's a separate sub-lane. - **`SurfaceArrow` / `FnSignature` introduction cascades into substrate authority** — reqs 2 + 3 introduce two top-level `parse_surface.dag` carriers. If grep surfaces consumers that expect `SurfaceType::Arrow { inputs, output, span }` as record-style fields (rather than `Arrow(SurfaceArrow)` positional payload) and updating them cascades beyond `lower.rs` + immediate parse consumers, STOP. May indicate a smaller-blast-radius shape (e.g., keeping `Arrow` as record-style and instead defining the sub-carriers as type aliases / typed views rather than wrapping payloads) is preferable. -- **Type-position higher-order syntax accepts named binders today** (`fn(x: A) -> B`) — req 1 / `ArrowInput::Named(NamedArrowInput)` is the path. If the parser doesn't currently accept that form (i.e., type-position is anonymous-only on the surface today), worker may simplify `ArrowInput` to a single non-coproduct shape (just `Anonymous { ty }`-equivalent) and surface that simplification with rationale. STOP if the simplification would conflict with downstream effect-on-Arrow consumer expectations. - **DB-11 / refinement-strip interaction surfaces** (`infer.rs:3693-3703`) — if refinements on `NamedArrowInput` interact with DB-11's refinement strip in a non-obvious way, STOP. - **DB-8 fixed-point drifts** — STOP immediately. @@ -141,7 +150,7 @@ Surface to Director. - **Not refactoring `SurfaceExpr::Lambda`.** Lambdas don't have explicit type signatures today; they're out of scope. - **Not refactoring substrate-side `Declaration` / `Arrow`.** Surface-side only. - **Not changing surface syntax.** The user-visible function-declaration syntax is unchanged; this is a pure construction-site refactor. -- **Not changing higher-order type syntax.** `fn(A, B) -> C` continues to parse as today; the only structural change is that `Arrow.inputs` now wraps each entry in `ArrowInput::Anonymous { ty }`. +- **Not changing higher-order type syntax.** `fn(A, B) -> C` continues to parse as today; type-position `Arrow.inputs` continues to be `List` — the only structural change at the type-position layer is that `SurfaceType::Arrow` now wraps a typed `SurfaceArrow` carrier (positional payload, no separate span on the variant). ## Reporting diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md index b8d9c1911d4..9056c51b91a 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md @@ -19,7 +19,7 @@ ## Read first - **[`docs/briefs/t-impossiblebugs-unenumerated-effects-worker.md`](t-impossiblebugs-unenumerated-effects-worker.md)** — sibling substrate sub-lane brief (post-this-PR-narrowed). The substrate side blocks on this PR landing. -- **[`docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md`](t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md)** — pre-prereq refactor brief. Lands `SurfaceArrow` (type-position arrow-shape carrier) + `FnSignature` (declaration-position arrow-shape carrier) + `NamedArrowInput` / `ArrowInput` input-element shapes. **This brief depends on that refactor having landed**; pre-flight check + STOP if it hasn't. +- **[`docs/briefs/t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md`](t-impossiblebugs-unenumerated-effects-fn-arrow-refactor-worker.md)** — pre-prereq refactor brief. Lands `SurfaceArrow` (type-position arrow-shape carrier) + `FnSignature` (declaration-position arrow-shape carrier) + `NamedArrowInput` (declaration-position input atom). **This brief depends on that refactor having landed**; pre-flight check + STOP if it hasn't. - **`SurfaceArrow` + `FnSignature` in `parse_surface.dag` (post-refactor)** — both arrow-shape sub-carriers. Today (pre-refactor) carries no `declared_effects` field on either. New surface-syntax + carrier extension lands on **both** sub-carriers per the refactor brief's carrier-distinction rationale (req 3): both are type-signature shapes per `feedback_no_annotations`, so effects must appear on each as a co-invariant — declaration-position effects (on `FnSignature`) and type-position effects (on `SurfaceArrow`) are real co-invariants, not bookkeeping duplication. - **[`src/v3/compiler/parse_parser_body.txt`](../../src/v3/compiler/parse_parser_body.txt)** — parse-body algorithm authority. The function-type / function-item parsing paths produce the `Arrow` / `Fn` surface shapes; new declared-effects syntax lands here. Worker picks syntax (recommend post-arrow-output suffix: `fn foo() -> T effects [Read, Write]` or similar; surface choice in PR description). - **[`src/v3/compiler/src/parse_generated.rs`](../../src/v3/compiler/src/parse_generated.rs)** — auto-generated from `parse_surface.dag` + `parse_parser_body.txt`. Per `feedback_no_generated_code_on_disk`, edits flow through `.dag` + `.txt` authority then regen. **No hand edits to `parse_generated.rs`**. @@ -54,7 +54,7 @@ Today the parser silently accepts no effect declaration; after this PR, the surf ## Slice — parser extension -1. **Pre-flight check**: confirm the Fn→Arrow refactor brief has merged and `parse_surface.dag` carries `SurfaceArrow` + `FnSignature` + `NamedArrowInput`/`ArrowInput`. STOP if not — sequencing error. +1. **Pre-flight check**: confirm the Fn→Arrow refactor brief has merged and `parse_surface.dag` carries `SurfaceArrow` + `FnSignature` + `NamedArrowInput`. STOP if not — sequencing error. 2. Add `declared_effects` field to **both** `SurfaceArrow` and `FnSignature` (per req 1) in `parse_surface.dag`. Add structural-carrier rationale (no new coproduct variants; field-level addition on two existing carriers). 3. Edit `parse_parser_body.txt` (per reqs 2 + 3 + 4): add `looks_like_effects_clause` + `parse_effects_clause`; route from the function-type/item parse entry. 4. Add lowerer extension (per req 5) producing the post-parser substrate carrier; resolve each surface effect to its `OperationEffect` declaration. From 0be6e6688adb247c44fda71a34b8d38dde4ccd8a Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 25 Apr 2026 12:50:18 -0400 Subject: [PATCH 13/13] docs(briefs): scrub stale Arrow-vs-Fn placement-choice language from parser-effects reporting OpenAI-pro non-blocking at sha a30f3b19: parser-effects brief reporting line still asked the worker to document Arrow-vs-Fn placement choices, but the same diff already fixed placement as co-invariant on both FnSignature + SurfaceArrow per refactor-brief req 3 ("not a worker placement choice"). Boundary-discipline / single-authority drift on a one-liner. Updated to ask for the carrier-distinction rationale instead. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../t-impossiblebugs-unenumerated-effects-parser-worker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md index 9056c51b91a..1aca0947359 100644 --- a/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md +++ b/docs/briefs/t-impossiblebugs-unenumerated-effects-parser-worker.md @@ -100,7 +100,7 @@ Surface to Director. ## Reporting - Single PR. Title: `feat(v3): T-ImpossibleBugs parser-extension — declared_effects on FnSignature + SurfaceArrow (prereq for unenumerated-effects substrate sub-lane)`. -- PR body cites this brief + addresses each of the 6 reqs + documents surface-syntax + Arrow-vs-Fn placement choices. +- PR body cites this brief + addresses each of the 6 reqs + documents surface-syntax choice + `FnSignature` / `SurfaceArrow` co-invariant carrier rationale (placement is not a worker choice — fixed by req 1 + refactor-brief req 3). - On merge: signal Director; Director signals sibling substrate sub-lane (`t-impossiblebugs-unenumerated-effects-worker.md`) is now dispatchable. ## Cross-manager note