waxwing

Bootstrap evidence and current checkpoint

Language direction recorded (2026-10-08)

User review revisions: FN001 is scheduled after P001 before C001/R001/ FX001; C001/R001 require joint design review of ordinary record instances. Documented row-specialization key/code growth and dictionary/accessor passing as an option needing an ADR, not a chosen fallback. Lowered IR’s default to test is after specialization, above layouts. D001 records text, numeric and collection foundations; M001 remains required for shared modules. Rust pragmatics are explicit; FX001 compares ZIO-like computations and Koka-like effect rows/handlers. All five review points addressed in the direction document and backlog/handoff. Current P001 worktree untouched.

Fresh npm run verify on main exited 0: 162 tests, zero failures/skips, zero build warnings/errors, gates, strict rebuild proof and eight isolated regression proofs. Raw log: .build/language-direction-review-verify.log. Documentation only; these milestones remain unimplemented.

User requested a local commit of the current language/backend/effect discussion using the planning guidance. Read brainstorming/writing-plans; recorded docs/plans/2026-10-08-language-direction.md as direction and hypotheses, not an implementation spec. Goals, early-release deferrals, row/service scenarios, effect-design questions, inspectable IR and future targets are separated from assistant recommendations and open decisions. Backlog follow-ups FX001 (effect design), L001 (lowered IR direction) and J001 (JavaScript evaluation direction); P001’s approved scope/order intact. README, bootstrap index, next-session, findings and provenance linked. Self-review checked scope, status, references and distinction between proposed acceptance scenarios and implemented behavior. Documentation only.

Fresh npm run verify on main exited 0: 162 tests, zero failures/skips, zero build warnings/errors, formatting/style/layer gates, strict rebuild proof and eight isolated regression proofs passed. Raw evidence: .build/language-direction-verify.log. Existing .vscode/settings.json edit excluded from this change. No feature implemented and no push authorized.

2026-10-07. The language is renamed from Sprig to Bumpus (A003 Task 3a). Dated evidence below keeps literal historical identifiers (old module names such as Sprig.Check, sprigCmpN-style Go helpers, old command lines, .sprig paths and log names) verbatim because they name artifacts that existed; the prose language name changes.

2026-10-07. The completed documentation/style audit is merged into main through 1f760af. Fresh review found no blockers; merged verification passed. Baseline 9624bec is preserved in history. Audit branch/worktree removed after retaining their evidence. Task 1 commit: 4410609. No publishing or push. The audit plan is docs/plans/2026-10-07-bootstrap-audit.md.

Historical pre-audit checkpoint

The following evidence was recorded before skill installation/execution; new worktree evidence follows below. Earlier raw logs are in the original checkout, not assumed to exist in the isolated worktree.

Verified evidence

node scripts/verify.mjs (same implementation as npm run verify) completed with zero source warnings/errors, strict/pedantic workspace builds, 19 passing Node tests, no skipped tests, and a successful isolated regression proof. Recent raw output is in ignored .build/verify.log; this summary survives it.

A clean-output npm run verify passed, followed by a final successful run after the formatter-version, cache-portability, unsafe-import, and malformed negative-literal fixes. Final log: .build/verification-final.log (exit 0). The MileAhead patch passed git apply --check against the read-only reference. Online installation and cross-platform execution remain unverified.

Artifacts already on disk

PureScript compiler: src/{Domain,Features,Format,Program}/*/.purs and src/Domain/IR/Internal.purs. Boundary: src/Runtime/Node.purs and Node.js. Style tooling: tools/style/src/Style/Check.purs (separate package). Tests: test/*.test.mjs and the regression witness/script. Example, three negative files, and bootstrap/answer.go (example snapshot). Documentation: README, AGENTS/CLAUDE, plan, findings, architecture, language, provenance, ADRs, engineering guidance, bootstrap roadmap, and local backlog.

Current remaining actions

Local integration is complete; proceed to a separate bounded ADT design/plan. Closed ADTs/exhaustive matching require a separate later design and plan. F001 (fresh compiler-tool setup), F002 (unapplied external patch), E001/E002 and E003 remain explicit.

Superpowers installation and backport

Historical installation steering: install skills, migrate, then plan the run. 15 skills installed project-locally via bunx at the revision in skills-lock.json; list command confirmed Codex/project scope. The unfinished audit is migrated to docs/plans/2026-10-07-bootstrap-audit.md with a durable historical ledger. At migration, no audit task or feature had run and Git had no HEAD. User subsequently approved inline execution/checkpoint/worktree. W001 is resolved; prior compiler evidence above is preserved.

Fresh migration validation: npm run verify on 2026-10-07 exited 0. Strict/pedantic build reported zero source/library warnings and errors; formatting and architecture/CST gates passed; 19 tests passed, zero failures and skips; isolated restored branch-check defect failed as required while the fixed compiler passed. Output was read from this session’s command output, not saved to a new raw log. This validates the preserved compiler after the installation/migration; it does not complete the pending documentation/style audit or represent a clean-output rebuild in this session.

Audit execution: Task 1

User approved checkpoint, isolated worktree, inline execution and final fresh review. Checkpoint 9624bec is on main; audit/bootstrap-docs runs in .worktrees/bootstrap-audit. Clean-output baseline compiled 269 modules with zero source/library warnings/errors, then passed 19 tests and the isolated regression proof. Raw evidence: worktree .build/audit-baseline.log.

Review focus Source and evidence Result/limit
Setup claims README; scripts/build.mjs/cache.mjs; baseline log Cached dependency build verified from clean compiler output. Fresh PATH-tool install/cross-platform setup remains F001.
IR boundary Check/IR.Internal/Go; structure.mjs; layer test Only checking/lowering imports internal IR in source. Checker validates encountered local/call indices; forged entry/table structure is trusted and documented.
Automated vs manual style Style.Check; structure.mjs; style/structure tests Essential CST/import/format/line gates pass. Manual fallback/callback/branch issues corrected; ten-arm (now twelve; see BACKLOG E003) tag mapping target exception recorded as E003. Full lint automation stays E001.
Snapshot/seed bootstrap/answer.go; compiler snapshot assertion; docs/bootstrap.md Example bytes match canonical emission; Stage 1 compiler seed remains proposed. Stage 0 source and locks preserved in baseline.
Handoff/external edit patch; planning-skills; backlog; migration ledger Skills installed and real BASE created. MileAhead patch remains unapplied (F002); current execution status is synchronized in Task 2.

Style-only refactors preserve the existing public source-language contract. The passing pre-change suite is the baseline; post-change verification and existing isolated mutation establish continued behavior. No synthetic RED history is asserted for documentation or helper extraction. ADRs 001/002 are unchanged: no semantic/representation decision changed in this audit.

Task 1 post-change npm run verify exited 0: strict/pedantic build with zero warnings/errors, all gates, 19/19 tests and isolated branch mutation proof passed. Raw evidence: .build/audit-task-1-green.log. The earlier accidental IR alias edit failed the same build; its copied defect also failed compile in isolation. docs/findings.md retains the complete failed-attempt account.

Audit execution: Task 2

Handoff files now identify the real baseline, audit branch, completed tasks and final fresh review. Historical no-HEAD/no-commit statements are labeled as historical. Review is complete; final completion verification is recorded below. No ADT source or plan was added.

Task 2 pre-review npm run verify exited 0 on 2026-10-07: zero strict-build warnings/errors, 19/19 tests with no skips, style/layer gates and regression proof passed. Raw log: .build/audit-task-2-pre-review.log in the audit worktree.

Fresh review and closure

Fresh reviewer inspected 9624bec..56cbde1 read-only: no Critical/Important findings. Two pre-existing test-title inaccuracies are deferred as E004; no assertions were changed. Full review and exhaustive scope rulings are saved in docs/plans/bootstrap-audit-review.md and bootstrap-audit-ledger.md. The server restart interrupted delivery; the same reviewer resumed, avoiding a second review or repeated implementation.

Two separate actual CLI emit invocations produced byte-identical output, also equal to bootstrap/answer.go (cmp checks succeeded). The preserved MileAhead patch again passed git apply –check without being applied. Stage 0, locks, tests, example bytes and pure boundaries remain preserved. ADR 001/002 remain unchanged. At audit closure no language feature, merge, push or publication had occurred.

Raw failure evidence retained outside executor scratch: .build/audit-task-1-failed-alias.log, .build/alias-regression/failure.log, and .build/audit-task-1-fixed.log (the failed reproduction-helper attempt). Successful raw evidence: .build/audit-baseline.log, audit-task-1-green.log, audit-task-1-completion.log, and audit-task-2-pre-review.log in .build.

Final closure npm run verify exited 0 on 2026-10-07: strict/pedantic build zero warnings/errors; 19/19 tests, zero skips; format/CST/layer gates and isolated branch mutation proof passed. Raw final log: .build/audit-final.log. Tasks 1/2 and original bootstrap tasks 7/8 are complete; no blocking review finding remains. E004 minor titles are intentionally deferred. Integration into main was still pending at that checkpoint; it is now complete as recorded below.

The installed task-done helper also verified Task 2 after commit f27b499: 19/19 tests, zero skips, strict build/gates/regression proof passed; commit range 4410609..f27b499 is recorded in the durable ledger. Raw completion log: .build/audit-task-2-completion.log. Executor scratch was copied in full to .build/audit-executor-evidence before cleanup; durable ledger/review remain committed in docs/plans. Only local branch integration is pending.

Authorized local integration

User explicitly approved merge. Main fast-forwarded 9624bec..1f760af; npm run verify on the merged checkout exited 0 on 2026-10-07: zero strict warnings/errors, 19/19 tests, zero skips, formatting/CST/import gates and isolated regression proof passed. Raw log: .build/merge-verification.log.

Audit raw logs, emitted files, isolated rename-defect copy and executor artifacts were preserved under .build/merged-audit-evidence before removing the merged audit worktree and branch. Historical worktree .build paths above now resolve under that archive. Original checkout logs were not overwritten. Durable ledger/review remain in docs/plans and all audit commits stay in main. The pre-existing .vscode/settings.json spell-check additions are preserved uncommitted. No push or publication occurred.

A001 design (in progress)

2026-10-07: brainstorming for closed ADTs and exhaustive matching. User chose recursive types, nested patterns with Maranget usefulness, type/match brace syntax, tagged value-struct representation and sequential first-match lowering. User review added CtorId identity, nil-guarded projections, inhabitedness, canonical witnesses and two-pass type resolution. Approved spec: docs/plans/2026-10-07-closed-adts-design.md. Documentation only; no compiler source changed, so no verification run is claimed for this step.

2026-10-07: spec approved and committed (1d71f2f). writing-plans produced docs/plans/2026-10-07-closed-adts-plan.md: five tasks (syntax; types and construction; patterns and match; coverage; docs and review). Plan-time spec amendments: E_DUPLICATE at the first duplicate (Stage 0 rule), depth-named match parameters, and the Float row moving from E_SYNTAX to E_UNBOUND. Documentation only; no compiler source changed.

2026-10-07: closed-ADT Task 1 (syntax) done. Added |{} and => tokens, reserved type/match/_, TypeRef, Parse.Declaration and Program dispatch; Resolve maps NamedRef to E_UNBOUND transitionally. New test/adt-syntax.test.mjs (7 tests) failed against pre-change source, then passed. npm run verify exit 0 (26 tests, regression proof, answer.go unchanged).

2026-10-07: closed-ADT Task 2 (types and construction) done. Ty moved to Resolved with TData; two-pass type table, shared global table, Construct through Check and Go (Go.Data). test/adt-types.test.mjs (6 tests) failed before the change (unbound-type errors), then passed. npm run verify exit 0 (32 tests, regression proof, answer.go unchanged).

2026-10-07: closed-ADT Task 3 (patterns and match, no coverage) done. Parse.Literal and Parse.Pattern, Resolve.Pattern with pre-order LocalIds, Check.Match, Go.Match (depth-named IIFE, nil-guarded projections); examples/shapes.sprig with snapshot bootstrap/shapes.go. test/adt-match (12) and test/adt-properties (1) failed before the change (match was E_SYNTAX), then passed. Regression proof is a table: branch and new nil-guard both fail on their mutants. npm run verify exit 0. Fix round 1: pattern-constructor arity moved from Check.Match into Resolve.Pattern (E_ARITY in pattern pre-order, before body and later-function errors); two new rejection rows failed before (E_UNBOUND) and pass after. npm run verify exit 0.

2026-10-07: closed-ADT Task 4 (coverage) done. Check.Usefulness (inhabitation fixed point, U(P,q), algorithm I) and Check.Coverage (E_REDUNDANT, E_NON_EXHAUSTIVE with canonical witness) run after checking; test/adt-coverage (6) and test/coverage (300-case oracle) failed before (non-exhaustive programs compiled), then passed; regression row exhaustive fails on its mutant. No existing test program changed. npm run verify exit 0 (52 tests, three regression proofs).

2026-10-07: closed-ADT Task 5 (five layers) done. Modules moved to Domain/Features/Format/Runtime/Program with git mv; Token, isUpper -> Format.Lex, codeName -> Format.Diagnostic; scripts/structure.mjs per-module table replaced by layer rules, four new structure cases failed before the gate. bootstrap/answer.go and shapes.go cmp identical, no stale Sprig./Shell. names. npm run verify exit 0 (52 tests, three regression proofs).

2026-10-07: closed-ADT Task 6 (structured diagnostics) done. Domain.Problem holds Problem/TypeName/Witness data; Features build no text; Format.Diagnostic code/message/wire render it, Program.Main uses wire. test/diagnostics characterization (39 families) passed at HEAD and unchanged after; its message/wire assertions failed before (no Domain.Problem); the R5 invalid-TypeId case compiled at HEAD returned Right (vacuously complete) and is now E_INTERNAL. Coverage table lookups split into Features.Check.Signature. bootstrap/answer.go and shapes.go cmp identical. npm run verify exit 0 (55 tests, three regression proofs; exhaustive mutant now const (const (Right Nothing))).

2026-10-07: closed-ADT Task 7 (capability ports) done. Domain.Host ports over abstract m; Format.Arguments (argv, usage text) and Format.Wire (plain/source/tool wire shapes); Program.Command over any Host; Runtime.Node is port implementations plus argv/stdout/stderr/exit and JSON only. test/program.test (9 fake-host cases) failed before (no Program.Command), then passed; two new structure rows (Program.Command importing Effect/Runtime) failed before the gate. Old/new CLI stdout, stderr and status byte-identical on 15 probes (usage, E_IO read/write, E_TYPE, E_TOOL with PATH=’’ and bad -o, emit/build/run); no temp dir leaked. bootstrap/answer.go and shapes.go cmp identical. Clean rm -rf output && npm run verify exit 0 (64 tests, three regression proofs).

2026-10-07: closed-ADT Task 8 (documentation and closure) done, review step excluded by controller ruling R6. Wrote ADRs 003 and 004; rewrote docs/language.md and docs/architecture.md; updated engineering, provenance (Maranget JFP 2007; MileAhead layers, conceptual only), README, BACKLOG (A001 Done; A002-A005, F005 added; E003 and F004 current), plan index and next-session. Clean rm -rf output && npm run verify (.build/a001-final.log): exit 0, 64 tests, 0 skips, regression proofs branch, nil-guard and exhaustive all passed. Two CLI emits of examples/shapes.sprig byte-equal each other and bootstrap/shapes.go; examples/answer.sprig emit equals bootstrap/answer.go (cmp). $TMPDIR still holds the same four stale sprig-regression-* directories after the run (F005). Final whole-branch review is run by the controller.

2026-10-07: A001 final whole-branch review findings fixed (record docs/plans/closed-adts-review.md). Function/constructor clashes report at the earliest declaration by source offset (new adt-types case failed before the fix at offset 26, passed after; .build/a001-review-minor3-red.log, -green.log). specialize and checkCtor return E_INTERNAL on field-count mismatch; the new diagnostics test fails with either change reverted in an isolated copy (.build/a001-review-isolated-red.log). Coverage oracle now requires witnesses to cover only unmatched values and checks brute-forced inhabitedness over 120 generated type systems (an inhabitedness mutant fails it: .build/a001-review-inhabited-mutation.log); 8 generated flat 3-5-arm matches run in Go (an arm-reordering mutant fails them: .build/a001-review-flat-mutation.log). verify.mjs runs every test/*.test.mjs (an unlisted failing dummy made verify exit 1: .build/a001-review-unlisted-probe.log). Clean rm -rf output && npm run verify (.build/a001-review-fix.log): exit 0, 0 warnings, 13 test files, 68 tests, 0 skips, regression proofs branch, nil-guard and exhaustive passed. CLI emits of examples/answer.sprig and examples/shapes.sprig equal bootstrap/answer.go and bootstrap/shapes.go (cmp). $TMPDIR still holds four stale sprig-regression-* directories (F005).

Next milestone, item 1: F004 (2026-10-07)

Reproduced in an isolated copy: with a shadowed name added to Domain.Host, the first node scripts/build.mjs failed with ShadowedName and the second exited

  1. scripts/build.mjs now removes the output directory of every module declared under src and tools/style/src before building (dependencies stay cached); the same copy then failed both builds. New scripts/strict-rebuild.mjs, run by verify, automates that proof; with HEAD’s build.mjs restored in an isolated copy it fails with “second build accepted a strict warning” (.build/f004-red.log). AGENTS.md no longer requires a clean output directory. Clean rm -rf output && npm run verify (.build/f004-verify.log) and the following incremental npm run verify (.build/f004-verify-incremental.log) both exit 0: 0 warnings, 68 tests, 0 skips, strict rebuild proof and regression proofs branch, nil-guard and exhaustive passed. The main item of the milestone is not yet chosen.

Next milestone, main item: A003 (design, 2026-10-07)

User chose A003 with print, equality and ordering. Design direction approved with five clarifications (E_ENTRY keeps missing-main and parameters; round trip recompiles with original declarations and checks structural equality via the interpreter; ordering mutations must fail an oracle or explicit-order assertion, with separately built equal values; nil-field panic rule scoped to visited fields; Bool helper only when needed). Written spec: docs/plans/2026-10-07-adt-printing-design.md, approved by the user. Plan: docs/plans/2026-10-07-adt-printing-plan.md (4 tasks), awaiting review. Documentation only; no compiler source changed.

A003 execution

A003 merged (2026-10-07)

User approved the merge. main fast-forwarded 74e5c2a..4b5ce2e. Clean rm -rf output && npm run verify on main exited 0: zero warnings, 98 tests, zero failures/skips, strict rebuild proof and six regression proofs (branch, nil-guard, exhaustive, ctor-order, first-field, show-fields). Raw log: .build/a003-merge-verify.log. Worktree .build logs and the SDD ledger were archived under .build/merged-a003-evidence before the a003 worktree and branch were removed. No push. Next: G001 (design first).

G001 design (2026-10-07)

User chose an applicative-only parser (no Monad instance) and a depth limit with a structured diagnostic for deep nesting (over a larger Node stack or heap-based phases). Written spec: docs/plans/2026-10-07-applicative-parser-design.md, approved as written with clarifications (section 7). Documentation only; no compiler source changed. Plan: docs/plans/2026-10-07-applicative-parser-plan.md (5 tasks), awaiting user review.

G001 execution

G001 merged (2026-10-07)

User approved the merge and kept the externally rewritten history. main fast-forwarded to 44a735b. Clean rm -rf output && npm run verify on main exited 0: zero warnings, 151 tests, zero failures/skips, strict rebuild proof and seven regression proofs (branch, nil-guard, exhaustive, ctor-order, first-field, show-fields, state-thread). Raw log: .build/g001-merge-verify.log. Scoped re-review of the final fixes found all findings addressed (116,000+ differential coverage cases identical to the pre-fix build); remaining wording nits fixed here (engineering test count) or parked (coverage-scale comment, Inhabited complexity formula). The re-review’s out-of-scope allowlist gap is BACKLOG F007. Worktree evidence and the SDD ledger are archived under .build/merged-g001-evidence; the g001 worktree and branch are removed.

E005 execution

E005 merged (2026-10-08)

User approved. main fast-forwarded to 09f3071 (E005 c928d93 plus review fix round 09f3071). Clean rm -rf output && npm run verify on main exited 0: zero warnings, 156 tests, zero failures/skips, eight regression proofs. Raw log: .build/e005-merge-verify.log. Review: 430-program base/head differential identical (values and call traces) and malformed-value panics identical; fix round re-review addressed all three findings. Parked: one 82-column JS test line (rule binds PureScript only), the stale Format.Go.Capture header comment (fixed with T001), wall-clock budgets with ~5x headroom. Evidence archived under .build/merged-e005-evidence; worktree and branch removed. Next: T001, then P001 (user order 2026-10-07).

T001 execution (2026-10-08)

Branch t001 (.worktrees/t001) from 62f8192. Brief: .superpowers/sdd/t001/brief.md (approved with eight binding amendments).

T001 review fix round 1 (2026-10-08; review: ready to merge, six cheap items). (1) large-source: the 5,000-arm case has its own batch (label arms), declared inside its test after the timed compile, so that timed compile is cold again. (2) The guard self-test gains package main followed by package other, and a second multi-line func main() {; the two guard clauses that no self-test bound (the package \w+ count and the func main count), each replaced by true, now fail that test. (3) runGoBatch takes an array of [name, spec] pairs and refuses a duplicate name (compared as strings, as run looks names up) at declaration; every caller passes pairs. New self-test failed first with Missing expected exception (.build/t001-fix1-dup-red.log). (4) The directory self-test removes its neighbour marker in finally. (5) docs/engineering.md: batch directories persist (rm -rf .build/go-batches reclaims them), concurrent test runs in one checkout race on them, and the 300 s build timeout does not group-kill (noted rather than changed: spawnSync cannot kill a group). (6) Only the shape guard’s refusal becomes “generated Go was refused”; filesystem errors propagate as themselves. Mutants in an isolated copy (.build/t001-fix1-mutants.log): all eight (the five earlier, both guard clauses, no duplicate check) fail exactly their self-test; healthy 6/6. rm -rf output && npm run verify exit 0: 162 tests, zero failures/skips, eight regression proofs, test phase 19.9 s, 61.8 s wall (.build/t001-fix1-verify.log).

T001 merged (2026-10-08)

User approved. main fast-forwarded to 4230eb9 (T001 7cbf2dd, c4e5cd0 and review fix round 4230eb9). Clean rm -rf output && npm run verify on main exited 0: zero warnings, 162 tests, zero failures/skips, test phase 19.4 s, eight regression proofs. Raw log: .build/t001-merge-verify.log. Evidence and brief archived under .build/merged-t001-evidence; worktree and branch removed. main pushed to origin at the user’s request. Next: P001.

P001 execution

Plan: docs/plans/2026-10-08-polymorphism-plan.md (spec docs/plans/2026-10-08-polymorphism-design.md). Branch p001 in .worktrees/p001; baseline npm run verify exit 0, 162 tests, eight regression proofs (.build/p001-baseline-verify.log).

Task 1: parameterized type, checked IR, Specialize seam (2026-10-08)

Behavior-preserving refactor; no language change. Pipeline is now Parse → Resolve → Check → Specialize → Go (Program.Compile parse >=> resolve >=> check >=> specialize, then emit).

Task 2: type parameters and applied types, syntax and resolution (2026-10-08)

Language change: type List(a) = Nil | Cons(a, List(a));, lowercase type variables, parenthesized application. Status: done.

Task 3: the unifier (2026-10-08)

No language change; nothing calls the unifier until Task 4. Status: done.

Task 4: polymorphic checking (2026-10-08)

Language change: rank-1 polymorphic functions and constructors type-check. Status: done.

Task 5: the instantiation rule (2026-10-08)

Language change: polymorphic recursion and nested datatypes that would make specialization infinite are rejected (design §4.1). Status: done.

Task 6: coverage over applied types (2026-10-08)

Language change: matches over applied types (List(a), Maybe(Void), List(List(Int))) and over type variables are checked for exhaustiveness and redundancy (design §5); the E_INTERNAL Coverage of a type variable gap is gone. Status: done.

Task 7: specialization (2026-10-08)

Language change: polymorphic programs now compile and run end to end through the CLI (npm run bumpus -- run examples/lists.bumpus prints Pair(Cons(Pair(3, true), Cons(Pair(2, false), Nil)), Just(6))). Status: done.

Task 8: specialization properties (2026-10-08)

Language change: none (tests only). Status: done.

Task 9: regression proofs and documentation (2026-10-08)

Language change: none (regression rows and documentation). Status: done.

P001 summary

Rank-1 polymorphism is implemented on branch p001 (Tasks 1-9, commits 959a7d1 onward). Parameterized types and generic functions type-check with rigid signature variables, fresh metas per use and occurs-checked unification; comparisons need ground operand types; unsolved metas are holes that Specialize fills with Int; the instantiation rule makes the set of specializations finite; coverage works over applied types; inferred types are bounded at 1,000 levels (E_NESTING, never a crash); a pure Specialize phase produces the variable-free monomorphic IR with hash-consed keys and a 10,000-key limit. Monomorphic programs emit byte-identical Go. Tests grew from 162 to 302 and regression proofs from eight to twelve. ADR 007 records the decisions (rulings R1-R20 in the plan’s ledger). Open follow-ups: BACKLOG E006-E011. Pending: final whole-branch review and the user’s approval to merge; FN001’s currying direction is to be discussed with the user before its design.

P001 final review fixes (2026-10-08)

The final whole-branch review (verdict: with fixes) found one Important issue and several minors; all were fixed in one commit on p001.

Verification: rm -rf output && npm run verify exits 0 in 90 s wall (97 s on an earlier run) with 318 tests (302 + 2 timing + 1 E_INTERNAL + 13 compile twins), zero warnings and twelve regression proofs (.build/p001-final-fix-verify.log). The eight files (node --test test/unify.test.mjs test/poly-*.test.mjs test/diagnostics.test.mjs, 153 tests) passed three sequential runs (.build/p001-final-fix-run{1,2,3}.log).

P001 merged (2026-10-08)

User approved the merge (no push). main fast-forwarded from 79c2327 to dcb40fb (P001 Tasks 1-9, the final-review fix wave, and the merged main direction commits). Clean rm -rf output && npm run verify on main exited 0: zero warnings, 318 tests, zero failures/skips, twelve regression proofs. Raw log: .build/p001-merge-verify.log. Per-task logs, briefs, reports, review packages and the ledger (rulings R1-R20) archived under .build/merged-p001-evidence; worktree and branch removed. Next: FN001, starting with the currying discussion recorded in BACKLOG.

FN001 direction settled (2026-10-08)

Discussed with the user before any design decision, as BACKLOG required. Settled: curried semantics with Algol-like multi-argument syntax as proposed (partial application, over-application, under-application becomes a function-typed value with a missing N argument(s) hint replacing today’s under-application E_ARITY); lambdas fn(x) => body reusing fn and =>, parameter annotations optional and inferred locally; |> included in FN001 (left-associative, below comparison), >>/<< wait for a Prelude; no local binding form in FN001 (separate item), so closures capture parameters and pattern variables by value. Design draft written the same day: docs/plans/2026-10-08-functions-design.md (syntax, names, typing, declared arity, evaluation, instantiation rule, canonical uncurried Go representation with adapters, tests and regression probes, deliberate diagnostic changes, four open questions). Not reviewed or approved; no plan, no code. Next: the user’s review of the draft.

FN001 design revised after the user’s review (2026-10-08)

The user’s review of the first draft: revise before approving. The canonical uncurried representation (A -> B -> C as func(A, B) C with adapters) lost declared-arity timing: with fn stuck(n: Int): Int -> Int = stuck(n); and use(f) = drop1(f(1)), use(stuck) must diverge but the adapter made f(1) a partial application returning 0; lambda eta-expansion delayed bodies the same way, and the draft’s “delays nothing observable” claim was wrong. Revision: nested Go function values func(A) func(B) C, staged wrappers for named functions and constructors used as values, direct saturated calls unchanged; declared arity is a stage boundary; pipe evaluates its left operand first (kept as a Pipe IR node); constructors are curried values; _ discards lambda arguments; the under-application hint is narrow with provenance rules; timing tests use instrumented bounded panics, never stack exhaustion; arrow spines are depth-flat, traversed iteratively, named Go function types keep text linear, scale tests at 5,000 parameters. Section 12 of the design maps each finding. Not yet approved; no plan, no code.

FN001 design approved; plan drafted (2026-10-08)

The user approved the revised design and asked for the plan. While writing it, the section 8 go build question was measured on hand-written Go (scratchpad, Go 1.26.4): nested-closure staged wrappers took 1.3 s at 50 parameters, 2.6 s at 100, 13.9 s at 200, 221 s at 300, and did not finish within 10 minutes at 1,000; an environment struct copied per stage took 1.1 s at 300 and 1,000 and 12.8 s at 5,000. A parameter bound is not viable (large-source already checks a 20,000-parameter declaration). Recorded as design Amendment A1 (section 13, proposed): no nested Go closures; staged wrappers and every lambda lifted to top-level stage chains over linked environments; meaning and types unchanged. Plan: docs/plans/2026-10-08-functions-plan.md (nine tasks; Task 1 re-measures the linked environment before any lowering code). Awaiting the user’s confirmation of A1 and review of the plan. No code. Verify for this docs change: first run failed one timing test (match ladder 1,830 ms over its 1.5 s bound under external load, 471 ms alone; .build/fn001-plan-verify.log), recorded as BACKLOG T003 before re-running; second run exit 0, 318 tests, twelve regression proofs, the ladder at 752 ms (.build/fn001-plan-verify-2.log).

FN001 plan approved with changes (2026-10-08)

The user approved A1’s architecture (top-level stages, immutable environments) and the nine-task structure with three changes, applied to the plan: Task 1 has no quadratic fallback (if the linked environment fails its linearity thresholds, stop and reconsider with the user) and benchmarks runtime with repeated applications, every argument consumed, explicit build/run timeouts; equality, ordering and type interning are in the scale work (hand-written spine-iterative Eq/Ord for both Tys in Tasks 2 and 5, arrows hash-consed in Specialize.Keys, Go function type names numbered from interned suffixes in Task 6, a 5,000-parameter function type as a generic argument in Tasks 5 and 8); the core timing probes move into Task 6’s first step, Task 7 keeps the interpreter and generated comparisons. Accepted diagnostic adjustments now in the design (§2, §4, §9): over-application past a non-function and f() keep E_ARITY Wrong number of arguments; x() and N() keep E_NOT_CALLABLE. Task 1 (measurement only) authorized in .worktrees/fn001.

FN001 Task 1: linked-environment measurement (2026-10-08)

Branch fn001 (.worktrees/fn001). Added scripts/stage-shapes.mjs (Go generator: linked, copied, nested; attribution baselines direct, bare, idle, chain; remedy candidates shared, packed) and scripts/stage-probe.mjs (explicit build/run timeouts, repeated applications with every argument consumed, checksums recomputed in JavaScript, growth-exponent verdict). Every run’s checksum matched. The first verdict line (“linear”) was wrong: its ratio bound admitted a 16× build for 4× n; replaced by the exponent bound before any decision. Result (design §13 “A1 measurement”): the linked environment fails the build bound (k = 1.92 with the statement driver, 1.74 without applying it); run time is linear. Attribution: the last stage’s n-local unpack and n-argument call; a packed calling convention fixes the staged value (k = 1.23 including a k = 1.52 floor of types and f). Applying a value to n arguments in one Go function is k ≈ 2 in every shape. Stopped per the user’s ruling: no representation adopted; decision returned to the user. No compiler change.

FN001 Task 1, round 2 (2026-10-08)

User authorized a second measurement round only. Added scripts/stage-baselines.mjs (types, signature, body, call), scripts/stage-mixed.mjs (mixed Int/Bool/pointer parameters, each read twice out of order; today’s n-ary convention, packed per-type arrays, packed struct), scripts/stage-blocks.mjs (block-split application, arguments evaluated in place), scripts/stage-order.mjs (order, body-entry and shared-partial checks with expected output computed from the semantics); probe reports total build times and an exponent per program. All checksums matched; four order cases matched; a hoisting mutant of the helpers failed the order check (scratchpad, not committed). Results in design §13 “round 2”: Go’s growth is confirmed in large bodies (today’s convention, mixed body: 1.51 s / 33.6 s at 5,000 / 20,000); packed arrays plus blocks of 64: 2.45 s / 19.2 s; homogeneous packed, blocks of 64: 2.08 s / 13.1 s; runtime linear. Nothing adopted; proposed Go bounds returned to the user. No compiler change.

FN001 Task 1 complete (2026-10-08)

The user approved the scale rule (Bumpus phases linear and stack-safe; Go builds at most 10 s per program at 5,000 parameters in verify and 100 s at 20,000 in the milestone probe) and one final round, adoption conditional on the shared-body bound and type-diversity allocation. Added scripts/stage-shared.mjs. Round 3 (.build/fn001-task1/run5-*.log): shared body with direct call, packed entry and a shared partial, total build 3.4 s / 5.1 s at 5,000 (3 / 1,000 types) and 52.1 s / 80.0 s at 20,000; 49.3 / 52.0 bytes per stage; checksums matched. Both conditions hold; convention adopted and written as design §13 rules 1-8; plan Task 6 interfaces and tests updated; conclusions narrowed (“tested large bodies”, not “no representation”). The 20,000 / 1,000-type build uses 80% of its bound. Next: Task 2.

FN001 Task 2: the arrow type (2026-10-08)

Branch fn001. Behavior-preserving: no syntax produces an arrow yet.

FN001 Task 3: syntax and resolution (2026-10-08)

Branch fn001. No existing row changes; bare names and calls of locals keep their P001 resolution until Task 4.

FN001 Task 4: checking (2026-10-08)

Branch fn001. Reach: Parse → Resolve → Check (test/phases.mjs, test/fn-checked.mjs); one CLI row asserts that checked function programs reach Specialize as Internal "unlowered function".

FN001 Task 5: instantiation rule and specialization (2026-10-08)

Branch fn001. Reach: Parse → Resolve → Check → Specialize (specialize, specializeWith and specializationKeys called directly); the CLI stops every function program at the temporary guard after Specialize.

FN001 decisions (2026-10-08)

The user approved (a) fixing BACKLOG T003 (match-ladder timing margin: 1,480, 1,393 and 1,441 ms against 1,500 inside the last three verifies) on fn001 after the Task 5 review and before Task 6, by reducing the workload, not raising the bound; (b) durability additions: Task 8 Step 1b commits the Task 4 review’s linear-cost table as bounded tests (test/fn-linear.test.mjs), Task 8 Step 4 uses a committed scripts/fn-milestone.mjs for the 20,000 tier, and Task 9 Step 1b promotes four scratchpad mutants to regression rows (block-order, value-edge, functional-fixpoint, arrow-key; 22 proofs); (c) the design §9 documentation of over-application diagnostic changes (Task 4 review).

T003: match-ladder compile cost (2026-10-08)

Goal (approved by the user before FN001 Task 6): make the 127-deep, 50-arm ladder in test/match-lift.test.mjs substantially cheaper so its 1.5 s bound has headroom inside verify’s parallel run; the bound, the workload and the test’s place in verify are unchanged. Acceptance was a 2× drop in the isolated median, or, if that needs a design change, the profile and the options.

Profile (c120d48, built in an isolated copy). The measurement is committed as scripts/ladder-profile.mjs (node scripts/ladder-profile.mjs --rounds 7 --baseline DIR: cold compiles in fresh processes alternating with a built baseline tree, steady per-phase medians, load average); the CPU and allocation profiles below used node --cpu-prof and V8 allocation sampling on the same source. Steady state per phase (median of 15, in-process): parse 137 ms (lex 55), resolve 22, check 134 (infer 61, coverage 36, firstTooDeep 9, holes 8, instantiation rule 9, retype 7, comparable 5), specialize 24, Go emission 46. One cold compile (fresh process, the test file’s small program first, as in the test) was ~500 ms: about 1.4× the steady sum, from JIT warm-up and GC. The compile allocates about 2.8 GB for the 150 KB source (--trace-gc: 149 scavenges, ~110 ms of GC). Hot spots: Format.Lex (per-character tailRecM steps over a copied character array, Array.elem, a fresh slice per two-character-token probe); isName/decimalToken copying each token into a character array; Format.Go.Capture’s union (concat, sort, then Array.nubBy, which sorts again) at 26% of emission; coverage’s per-arm redundancy query re-simplifying every earlier arm and uncons-copying every row a specialization drops (quadratic in arms by design, so the constant matters); tooDeep/walk entering their loops for Int, Bool and rigid types; retype/holes rebuilding a body that has no bound meta or hole. Everything else is a flat spread of combinator, Either and record overhead (no single function above 4% after these fixes).

Changes (each keeps its semantics; no public formula is new):

After (steady, median of 15, load average 9-11, alternating with the baseline): parse 124 → 92, resolve 19 → 19, check 125 → 78 (infer 53 → 35, coverage 31 → 26), specialize 21 → 21, emission 43 → 27; sum 332 → 237. Allocation (V8 total_allocated_bytes, per phase summed) 3.3 → 2.4 GB. Isolated cold compile, nine alternating rounds at load average 5.7 (18:29): baseline 543 504 507 517 502 495 514 512 495, median 507 ms; T003 379 368 363 385 379 376 370 362 366, median 370 ms: 1.37×, short of the 2× target. Cold phases: parse 176 → 125, check 193 → 131, emission 61 → 42.

Verify (three consecutive npm run verify, every run reported): all exit 0, 486 tests, zero failures, twelve regression proofs, snapshots byte-identical. Ladder: 942 ms (load 8.9 after), 968 ms (14.7), 852 ms (12.0); logs .build/t003-verify{1,2,3}.log. Before T003 the same test took 1,345-1,732 ms inside verify. Two direct node --test runs during the work, while other projects’ builds pushed the load average to 16-30, failed it at 1,659 ms and 2,573 ms (.build/t003-tests1.log, .build/t003-tests2.log); the second also failed coverage-scale’s 5,000-field pattern (5.1 s) and fn-specialize’s 5,000-parameter keys (2.7 s). Both pass alone (0.80 s and 3.2 s wall under load 27; baseline 0.70 s and 2.7 s in the same minute) and neither path’s timing changed in kind; these are T003’s external-load symptom in other timing tests.

Why not 2×: what remains is spread over the combinator parser (each argument passes about a dozen Either-threaded combinator layers), monadic threading in Infer, Resolve and Specialize, coverage’s quadratic redundancy query, and GC. Options that would reach 2×, each a design change: (1) a direct token-level parser for expressions in place of the layered combinators (parse is now 35% of the cold compile); (2) redundancy for literal-only columns without one usefulness query per earlier arm; (3) fusing the checker’s remaining whole-body passes (firstTooDeep, comparable, coverage roots, instantiation’s two call folds) into one; (4) an allocation-light State/Parsed representation. BACKLOG T003 stays Open with these.

Re-run with the committed script (18:37, load average 7.03 before, 6.40 after; 7 alternating rounds against the c120d48 copy): cold baseline 513 539 504 494 520 500 501, median 504 ms; current 396 373 392 382 373 368 368, median 373 ms. Steady medians baseline → current: lex 61 → 31, parse 136 → 96, resolve 21 → 21, check 136 → 86, specialize 22 → 21, emit 46 → 26 ms. npm run verify with the script committed: exit 0, 486 tests, twelve regression proofs, ladder 748 ms (load average 6.05 before, 19.82 after; .build/t003-script-verify.log).

Review follow-up (2026-10-08): the independent review approved 7c6c0f5 (50,453 differential cases, 0 differences). Minors fixed: Usefulness’s comment (once per arm, against all earlier arms); Lex spaceEnd reads each character once (spaceStep); Check’s settle uses a new Unify.isEmpty (test isEmpty holds exactly until a meta is bound) instead of Subst(..); Coverage’s import order. The reviewer’s harness is now scripts/differential.mjs (+ differential-corpus.mjs, differential-hook.mjs; docs/engineering.md). Against the c120d48 copy, seed 7, count 1000, harvest regenerated (3,419 parses → 2,355 distinct sources; load average 11.6 at 18:49): harvested 2,355, fuzz 1,029 plus 1,085 isName probes, matches 1,000, mutations 1,000, 0 differences (.build/t003-differential.log). Against a copy whose lexer no longer treats tab as whitespace: 148 of 329 fuzz sources differ at lex, exit 1 (.build/t003-differential-broken.log). npm run verify: exit 0, 487 tests, twelve regression proofs, ladder 811 ms (load average 6.95 before, 12.03 after; .build/t003-review-verify.log).

T003 decision (2026-10-08)

The user chose to accept the 1.37× isolated gain (7c6c0f5; script scripts/ladder-profile.mjs, 6d0906c) and continue to FN001 Task 6. T003 stays Open with its five recorded design options; ladder in verify now 748-968 ms against 1,500. Task 6 starts after the T003 review.

FN001 Task 6: Go lowering (2026-10-08)

Branch fn001. Reach: the whole CLI; programs with function types, lambdas, function values, partial and over-application and pipes now compile, build and run. Design §13 rules 1-8 as adopted.

Differential harvest failure, unidentified (2026-10-08)

During the Task 6 review fixes, scripts/differential.mjs --regenerate ran the full test suite under its harvest hook and that run exited 1; the tool discarded the run’s output, so the failing test is unknown (likeliest a load-sensitive timing test, BACKLOG T003, unconfirmed). The tool now writes the run’s output to <harvest>.jsonl.log and prints the failing test names. One rerun afterwards (load 3.3 before, 9.1 after) exited 0: 2,374 harvested sources, 0 differences against itself.

FN001 Task 8: scale (2026-10-09)

User decisions (2026-10-09): (A) the 5,000-parameter go build test failed once at 10,584 ms against 10 s under verify’s own parallel load (4.0-4.4 s alone); bound and workload stay, and go build-timing scale tests now run in a separate serial phase: scripts/verify.mjs runs test/*.serial.test.mjs after the parallel node --test run with --test-concurrency=1, still discovered by pattern (docs/engineering.md). (B) At 20,000 parameters the mixed body’s 2n-term bumpusAdd tree in one Go expression kills the Go compiler (7.4 GB) even for direct calls only, pre-existing lowering, not FN001 staging (BACKLOG G003, new). The milestone therefore tests FN001’s machinery at full width with bodies that read six parameters (first and last three, mixed kinds).

FN001 Task 7: reference interpreter (2026-10-09)

FN001 Task 9: regression proofs and documentation (2026-10-09)

FN001 whole-branch review (2026-10-09)

Fresh reviewer, whole diff 2a61a2b..e2a6735: ready to merge, no Critical or Important findings. Verify in an isolated copy: exit 0, 541 + 12 tests, 22 proofs. Six adversarial cross-task programs matched the interpreter including entry order; 2,300 extra generator seeds matched; ~46,000 sources against a main build: 0 Go differences among sources main accepts, none newly rejected, every non-syntax diagnostic change a design §9 row. Minors fixed: language.md hint condition (M1), generator label (M3), ADR 008 note on syntax diagnostics of invalid sources (M6), BACKLOG T005 for the unidentified harvest failure (M5; renumbered at the merge because main had added its own T004); deferred to BACKLOG FN006: interpreter zero-argument calls (M2), splitting the value-edge row (M4), fn-linear bounds in the parallel phase (M7). Awaiting the user’s merge decision.

FX001 sequencing discussion recorded (2026-10-08)

At the user’s request, language-direction records proposed do notation as an expression elaborated into bind and lambdas, with an illustrative block and its expansion. Result binding, discarded results, final computation and the distinction between constructing and running deferred effects are explained. Service/error inference is a goal; bind/pure selection, binding rules and monadic versus algebraic effects stay open. This is direction only, with no compiler change or implementation authorization. Next-session and the FX001 backlog row point to the proposal. Verification: npm run verify exited 0 with 318 tests, no failures or skips, and all twelve regression proofs; evidence: .build/fx001-do-docs-verify.log. The proposed notation is not implemented or behaviorally verified by this suite.

Effect-row notation and constraint scope recorded (2026-10-08)

The user asked to preserve the algebraic-effect/open-row discussion and defer explicit effect-row constraint syntax to a future feature. The language-direction document now records direct-style handler evaluation, candidate Log + ...effects notation, inferred higher-order effect relationships and proposed implicit universal row quantification. It distinguishes record rows and R001’s lacks constraints from effect rows. Outer syntax, quantifier scope and handler semantics remain design work; no compiler change or implementation authorization. BACKLOG and the next-session handoff record the future constraint-syntax scope. Verification: npm run verify exited 0 with 318 tests, no failures or skips, and twelve regression proofs; evidence: .build/fx001-row-direction-verify.log. This verifies the existing compiler, not the proposed effects or notation.

MileAhead error-row pattern captured (2026-10-08)

The user’s error-widening question revealed that earlier direction only mentioned extensible errors generically. Read-only inspection of MileAhead (../trailmapper, as recorded in provenance) confirmed open error-family rows, caller composition without conversion wrappers, context-only wrapping, and closure at handling/test boundaries. Language-direction now records this brief and independent Bumpus syntax candidates hiding Variant and injection plumbing. FX001/R001 must resolve error-sum support against the current general-variant deferral; no feature scope or code changed. Provenance, BACKLOG and the next-session handoff track the design work. Clarified after the user’s follow-up: errors is an ordinary implicitly universally quantified row-variable name, not reserved or existential; only the spread punctuation is special syntax in the proposal. Verification: npm run verify exited 0 with 318 tests, no failures or skips, and twelve regression proofs; evidence: .build/fx001-error-rows-verify.log. Proposed error sums remain unimplemented.

Standard-library helper direction recorded (2026-10-08)

The user requested planning for common PureScript/Haskell FP helpers with approachable Rust-informed names. Added STD001 and a dedicated direction document covering optional/result eliminators, defaults, transformations, functions, sequences, text, maps/sets and generic collection operations. Candidate names distinguish getOrElse from full branch elimination and make eager/lazy evaluation explicit. Delivery follows FN001 and stages other APIs by their prerequisites; no compiler or helper implementation. Acceptance requires an upstream coverage matrix, readable examples, behavioral/law tests and explicit deferrals. Handoff and language-direction link the brief; exact public names still need reviewed API designs. Verification: npm run verify exited 0 with 318 tests, no failures or skips, and twelve regression proofs; evidence: .build/std001-direction-verify.log. Helpers are planned, not implemented.

STD001 generic rigor clarified (2026-10-08)

The user clarified that approachable naming must preserve theoretical rigor and HKT-based shared operations. STD001 now pins generic bimap over any lawful Bifunctor, shared Functor/Applicative/Monad contracts, required constructor kinds and partial type application, and coherent instance evidence under the current rank-1/specialization constraints. Concrete helpers are incremental delivery, not completion of the generic library. Acceptance includes generic clients, user-defined product/sum instances, algebraic law properties and cross-operation coherence; pure callback laws remain distinct from FX001 effectful sequencing. BACKLOG and handoff track the clarification. No language or library implementation changed. Verification: npm run verify exited 0 with 318 tests, no failures or skips, and twelve regression proofs; evidence: .build/std001-generic-rigor-verify.log. Generic APIs and laws above are future acceptance requirements, not implemented or proven by this run.

Cross-language audit planned (2026-10-08)

The user asked for a structured audit of leading language specifications and library/runtime designs. Existing STD001 only audited helper coverage; there was no broader systematic plan. Added LA001 covering all twelve named references, a versioned primary-source/section ledger, comparative briefs, decision and interaction matrices, practical application scenarios, independent review and durable scope decisions. Primary landing pages were checked to assemble the roster; detailed reading/audit is not complete. Relevant findings feed upcoming designs without expanding FN001 or revoking existing advanced-feature deferrals. BACKLOG and handoff track the plan. Verification: npm run verify exited 1 with 316 of 318 tests passing, no skips, and two large-source timing failures (6.572 s and 5.633 s against 5 s bounds). Regression proofs were not reached. Evidence is .build/la001-plan-verify.log; BACKLOG T004 records the cases, unconfirmed cause and diagnostic next action. No checks or assertions were changed, and no rerun concealed the failures. The audit itself remains planned.

Developer tooling direction recorded (2026-10-08)

The user requested highlighting/IDE support, first-class doctests, property-based testing, possible literate capabilities, and LLM skills/discoverability. Added distinct IDE001, DOC001, PBT001, LIT001 and AI001 entries with docs/plans/2026-10-08-tooling-direction.md. The brief records outcomes, proposed acceptance and dependencies without selecting syntax, tool protocols or implementations; literate capabilities remain exploratory. LA001 now includes these concerns in its comparison axes and application scenarios. Updated language direction and next-session handoff. No language/compiler code changed and FN001’s delivery is unchanged. Verification: npm run verify exited 0 with 318 tests passing, no failures or skips, and all twelve isolated regression proofs passing; evidence: .build/tooling-direction-verify.log. This checks the existing compiler, not the proposed tooling. T004’s earlier timing failures remain recorded and unresolved; this successful run does not establish their cause.

Libraries, platform services and packages direction (2026-10-08)

The user requested distinguishing Bumpus libraries compiled to the host target, FFI bindings and dependency-inverted services implemented through host-language libraries, then added package management. Recorded PKG001 in the tooling brief and backlog; updated LA001, language direction and handoff. Planning includes source packages/host-callable export assessment, service contract/provider substitution, combined host/Bumpus dependency resolution, manifests/locks, identity, compatibility and target/runtime availability. Effect Platform’s primary introduction was checked as a conceptual precedent; its mechanisms are not adopted. No compiler code, package manager, binary ABI or provider mechanism is implemented/selected, and FN001 scope is unchanged. Verification: npm run verify exited 0 with 318 tests passing, no failures or skips, and twelve isolated regression proofs passing; evidence: .build/pkg001-direction-verify.log. This validates existing behavior, not the proposed package/interop features. T003/T004 remain open.

FN001 merged (2026-10-09)

User approved merge and push. main had gained eight docs-only planning commits (2190c8f..340953a: FX001 do notation, error rows, STD001, LA001, tooling, PKG001); they were merged into fn001 (9527233). Conflicts: the T003 row (fn001’s extends main’s; kept fn001’s) and two different T004 items (main’s large-source timing item kept as T004; fn001’s unidentified harvest failure renumbered T005); progress kept both sides. Clean rm -rf output && npm run verify on the merged tree: exit 0, 541 + 12 tests, twenty-two proofs (.build/fn001-merge-verify.log). main fast-forwarded to fn001 and pushed to origin; worktree and branch removed.

FX001 Task 1: runtime shape measurement (2026-10-09)

Branch fx001. No compiler change. Added scripts/effect-probe.mjs (driver: explicit build 300 s / run 120 s timeouts, five repetitions, checksums verified, load averages before and after each batch), scripts/effect-runtime.mjs (Go prelude: bumpusCtx list, non-zero-sized bumpusMarker, bumpusAbort, lifted bumpusHandle returning (result, abort), bumpusCleanup, defect report and main wrapper), scripts/effect-semantics.mjs (Step 2 programs and independently written expected output) and scripts/effect-programs.mjs (Step 3 loops and the generated lifted-helper program). Semantic checks: all 7 modes pass (clause reaches the outer handler; aborts cross unrelated and same-key inner handles to their target; clause failures after the helper returns reach the outer handle; nested blocks unwind LIFO; cleanup that handles a failure internally lets the abort continue; two cleanup failures print the three confirmed report lines in order, exit 1; normal-exit cleanup failures; crash not caught by handle with cleanup run; guard line; 1,000 markers distinct). A first run of abort failed on my own expected output (two nested blocks give d2 d1 d2 d1, I had written one pair); corrected the expectation, not the program. Two mutants (handle catching every abort; clause run in its own context) each fail their check (scratchpad, not committed). A second full run reused Go’s build cache (identical seed per repetition; 0.2-0.4 s builds) and was discarded; the seed now varies per run. Measurements (.build/fx001-task1/run3.log): median go build 0.83 s / 1.53 s / 2.91 s at 1,000 / 2,000 / 4,000 helpers (bound 10 s). Decision: ADOPT the shapes. Details in findings “FX001 Task 1”.

FX001 Task 2: Unit, blocks and let (2026-10-09)

Branch fx001. No existing test assertion changes; the five bootstrap snapshots are byte-identical (verify’s snapshot tests).

FX001 Task 3: effect rows and scoped-label unification (2026-10-09)

Branch fx001. Behavior-preserving: no syntax writes a row yet; every existing TFun carries the closed empty row and every TData empty row arguments. No existing assertion changes; the five bootstrap snapshots are byte-identical (verify’s snapshot tests).

R003 Waxwing rename (2026-10-09, verification in progress)

User approved the Bumpus -> Waxwing / .wxw migration and subagent help. Work uses the existing isolated FX001 tree at 3481468 (Tasks 1-3), with main and its pre-existing editor setting untouched. Separate agents handled current documentation and test identity edits; a fresh read-only reviewer found only a stale Provisional name sentence, which was corrected.

CLI is scripts/waxwing.mjs, npm script waxwing; packages are waxwing, waxwing-style and waxwing-bootstrap. Renamed nine example/negative sources; updated Go names/panics, temporary prefixes, harvest instrumentation, current documentation, active FX001 documents, backlog and handoff. Historical plans/progress/findings, prior naming evidence and branding provenance remain. ADR 009 records the decision. No semantics, verbs, aliases, extension-based rejection or final artwork were added.

Evidence so far:

No whole-suite success, merge, commit or push is claimed by this entry.

R003 paused-tree validation and supplied branding (2026-10-09)

The user confirmed the other worker paused. Its eight changed source files remain byte-identical to .build/waxwing-paused-files.json; no worker edit was reverted or folded into the rename’s semantic claims.

R003 final rename evidence (2026-10-09)

The original 3481468 compiler was rebuilt in .build/waxwing-baseline-compiled for a differential comparison. Its first scratch build failed because the copy omitted tools/style/src (.build/waxwing-original-build.log); supplying that unchanged directory fixed the setup, and the next build passed with zero warnings/errors (.build/waxwing-original-build-fixed.log).

A scratch copy of scripts/differential.mjs normalizes only Bumpus/Waxwing and bumpus/waxwing in emitted-Go hashes; all seven phase comparisons and diagnostic comparisons remain. The full harvested corpus comparison was interrupted (status 130) after several minutes without a report; T006 owns the investigation. The bounded comparison used sources up to 20,000 characters (2,433 captured sources, 53 stress sources outside this optional comparison only). It exited 0: 2,433 harvested, 1,029 fuzz, 1,000 match and 1,000 mutation sources, plus 1,085 isName probes; zero differences. Log .build/waxwing-differential.log; scope .build/waxwing-differential-scope.json. The bounded run had already completed when an interrupt was requested. A redundant memoized-hash scratch experiment was then stopped (status 130) and is not validation evidence; the final scratch checker was restored to the successful version. No maintained differential check was weakened.

Final smoke: live npm waxwing run examples/answer.wxw prints 42; all eight paused worker files still match their saved hashes; current branding assets match the user-supplied originals (.build/waxwing-final-smoke.log). The user confirmed the visible logo files are right. Read the supplied Claude continuation prompt and the local SDD ledger; they corroborate the paused Task 3 review-fix state. No further effects implementation was started by this rename task.

Rename implementation is complete on fx001. Full verification is not green: the isolated rename tree has the recorded pipe timing failure, and the live combined tree also contains the unfinished deferred-row test mismatch plus timing failures. Serial continuation (13) and all twenty-two regression proofs pass; earlier failures remain recorded. The rename and eight preserved FX001 worker files remain uncommitted; main is unchanged. For the continuation, commit the rename separately from Task 3 review fixes; finish those fixes/tests and re-review before Task 4. No merge or push.

FX001 Task 3 review-fix continuation (2026-10-09)

The user resumed FX001 after the rename’s separate commit 40cf312. Preserved and completed the eight paused source files: deferred Fail keys postpone the whole original row equation with type/row/fresh/event rollback; settleRows retries after other constraints and preserves undecidable pairs; groundErased is used only for Seeds/Resolve monomorphism while strict ground remains strict. RowOccurs distinguishes a row’s occurs failure. The left-over-right path also needed a deferred-key guard: new tests first failed 9/10 with RowExtra, then passed after that guard. Exact closed/open reflexivity, one-Fail settling, closed deferred right, never-skip-first, rollback, retry, arrow continuation and erased grounding cases are covered.

The independent transactional oracle now models rollback, postponement and settling. Generators include deferred Fail arguments, same-family Error(Int)/Error(Bool), arrow label arguments and nonempty starting type/row substitutions. Original 1,500-pair solved laws (including symmetric acceptance and scoped equality) remain; 2,000 further pairs in both directions distinguish pending acceptance from solved equality and compare settling after ordinary constraints. Focused run: 44/44 pass, no skips (.build/fx001-task3-fix-focused.log). Seven isolated source mutants all compiled successfully then failed intended assertions; full logs/results in .build/fx001-task3-fix-mutants, summarized in the local Task 3 report.

Verification history retained:

The row fix is verified through direct semantic tests/oracles; no syntax can create nonempty effect rows yet. Task 5 must settle after body constraints and diagnose remaining unknown families. Deferred equations currently carry no spans/provenance; Task 9 must preserve/recover origins when integrating traced retries. UnifyRow is 249 lines. Both are explicit handoff concerns, not claims of completed later tasks. Active effects ADR references now use 010 (009 is naming). Ready for independent review before Task 4; no merge or push. Local report/ledger: .superpowers/sdd/2026-10-09-effects-plan/{task-3-report,progress}.md.

FX001 Task 4 — effect signatures, operations and Console (2026-10-09)

Implemented sorted signature variables with one rigid ambient row, explicit rows, declared operations, stage consumption, Console print and Unit entry output. Rows erase from specialization arguments. Field and operation arrows default to pure, with declared effect names available; lambda annotation omissions share the lambda’s own fresh ambient row. Program.Compile explicitly rejects user effects before specialization; handlers and user effect execution remain later tasks. Wire diagnostics carry related: [] with existing messages and spans preserved.

Clean-output npm run verify exited 0 (.build/fx001-task4-verify.log): zero build warnings/errors, formatting/structure/strict-rebuild gates, 672 parallel tests, 22 serial tests, no failures or skips, and all 22 existing actual-source regression proofs. Four additional isolated actual source mutants built and failed their named regressions: lambda annotation omission, 20,000-arrow row collection, row argument erasure and effect names in field types (.build/fx001-task4-sensitivity/{results.json,*-test.log}). Earlier failed runs remain documented in the local Task 4 report; no unchanged rerun hid a failure. Concrete malformed-input validation gaps are BACKLOG FX004, with reproductions and the Task 5 next action. No merge or push. Implementation/evidence: .superpowers/sdd/2026-10-09-effects-plan/task-4-report.md.

FX001 Task 5 — handlers and typed failures in Check (2026-10-09)

Implemented handler values, with, handle, and fail through Parse, Resolve, and Check. Handler clauses are checked against declared operations; with consumes the handler capability while preserving the outside row; handle settles concrete Fail(E) keys and forwards unhandled error families. Deferred retries preserve the original semantic failure category and fail span. Nested failures are traversed through their payloads.

Row-parameterized ADTs support interleaved, multiple type/row parameters, bare effect labels, and pure; source sorts are retained while VarIds stay canonical (type slots first). The parser remains Applicative-only; Handler type syntax is isolated in Format.Parse.HandlerType. A declared ADT named Handler wins for Handler(Foo), while Handler(Clock) resolves as a handler type when no such ADT exists. Duplicate effects, operations, effect/type parameters and function/handler binders use the existing duplicate diagnostics. Both written row forms reject repeated or nonfinal tails.

Program.Compile rejects checked Handler/HandlerValue, With, Handle and Fail nodes, plus Handler types in signatures, expressions and every constructor field, before Specialize. The iterative type walk stays stack-safe at a 20,000-arrow signature. This is Check-only support: specialization/lowering, runtime behavior, and Go emission remain later FX001 tasks.

Root audit findings 1–13 are fixed and recorded with reproductions in .superpowers/sdd/2026-10-09-effects-plan/task-5-root-audit.md. The previous FX004 validation gaps are closed. Focused handler tests pass 81/81; the large-source suite passes 15/15, with 20,000-type duplicate rejection at 475 ms against its unchanged five-second bound. Eleven new isolated source mutations prove the nested Fail, duplicate validation, deferred diagnostic, metadata guard and duplicate-scan timing regressions.

Clean-output npm run verify exited 0 in .build/fx-handler-task5-verify5.log: zero build warnings/errors, pinned formatting, strict rebuild and structural gates, 722 parallel tests and 22 serial tests with no failures or skips, and all 33 actual-source regression proofs. Earlier real failures remain preserved: verify2 exposed duplicate and resolver-metadata compatibility issues; verify4 exposed eager when-argument evaluation in duplicate scanning (6.92 s against the unchanged five-second limit). Those defects were fixed and their regression proofs added before verify5. Full interfaces, evidence and the remaining Task 9 origin-provenance handoff are in .superpowers/sdd/2026-10-09-effects-plan/task-5-report.md. No runtime or specialization behavior is claimed for this task.

FX001 Task 6 — effect specialization with erased rows (2026-10-09)

Resumed in a Claude Code cloud session on branch claude/vibrant-cerf-3km61i (fast-forwarded to fx001 at 9a6befd; no .worktrees, ruling recorded in the SDD ledger). The local SDD ledger of Tasks 1-5 was never committed; it was recreated from git and this file. Task 6 was implemented inline by the controller before the superpowers skills were linked into .claude/skills (32ee2d2); it then received an independent task review.

Implemented: effect keys (EffectRef, ground type arguments) in the one specialization worklist, created on first reference; user effect keys fill their operations’ types beside their source (Resolved.OperationInfo gains syntax), so they reach type keys and the effect keys of handler types; Handler(L …) lowers to L’s key in bodies and constructor fields; rows are erased everywhere. The IR gains THandler EffectKey, an effects table and nodes OperationRef, Perform, HandlerValue, Install, Handle and Abort (fail; handle clauses and aborts carry the payload’s declared family). Check.Nested judges one reference graph over type and effect declarations (constructor fields, operation parameters and results, Handler(L …) edges); Grow, the mutual pair and the data/effect cycle are E_SPECIALIZATION at the nested reference, their bare-parameter versions compile. A function whose type variable appears only in its own row’s labels is polymorphic (it crashed specialization before). Features.Check.Unlowered is replaced by Features.Specialize.Unlowered over the emitted IR: effect layouts or effect nodes stop at E_INTERNAL “unlowered effect”; unused effect declarations reach Go unchanged. Only keys with type arguments count toward the 10,000 limit. Tests reach Specialize directly (test/fx-specialize.test.mjs, 18 tests); executable probes wait for Task 7.

A Task 5 parser defect surfaced: with R inside Handler(L with R) was silently dropped (and rows after non-arrow types elsewhere). Fixed by a Sonnet implementer in 5da7865 and 3aa1217 (round 2 pending at this entry), reviewed by Opus; meaningless rows are now E_SYNTAX “Unexpected effect row”.

Evidence: RED 15/18 (.build/fx001-task6-red.log; three characterization tests passed before). Clean npm run verify at 85c5867 (.build/fx001-task6-verify.log): zero build warnings, gates pass, 752/752 parallel tests; serial phase 13/22 — the 9 failures are fixed timing bounds that fail identically on the pre-Task-6 baseline 9a6befd on this container (BACKLOG T007); regression proofs, run explicitly: 33/33 (.build/fx001- task6-regression{,2,3}.log; four duplicate-declaration rows now expect an accepted program because the old guard no longer masks them). Test-helper defect fixed: test/poly-keys.mjs built a 5,000-deep JSON message eagerly (stack overflow here). Task review (Opus): spec ✅, quality Approved, no Critical/Important; Minor items deferred in the ledger.

FX001 spec revision: defer must not fail (2026-10-09)

Before Task 8, the user was asked how a cleanup failure during an abort should behave (abort-to-defect conversion as specified, drop, replace, or suppressed causes). The user chose the static rule, after Swift’s defer: a deferred expression that performs an unhandled Fail is E_EFFECT defer must not fail, but it performs <L>; cleanup that can fail handles its failure inside the deferred expression. Only defects can fail cleanup, so a pending typed abort reaches its handle unless a cleanup on the way raises a defect (the abort then heads the report) or diverges (corrected per CF001 §11). Spec §2 (defer rule), §3 (“Cleanup failures”, with rejected alternatives), §5 (report example, probes 6 and 11), plan Global Constraints and Tasks 8, 10 and 12, findings and the handoff were updated. Docs only; no code changed.

FX001 Task 7 — Go lowering of handlers, operations and failures (2026-10-09)

Subagent-driven: Sonnet implementer (e9a613f, fix round 4b80bd1), Opus task review and scoped re-review. Effect programs now build and run. ctx mode is chosen over the emitted IR (any effect layout or effect node); in it every function, stage, lambda, constructor, lifted helper and function type takes ctx *waxwingCtx first; otherwise Go output is unchanged (bootstrap snapshots byte-identical, Console-only programs without ctx). Runtime (Task 1’s adopted shapes, emitted only when used): immutable context list, non-zero-sized markers, targeted aborts recovered only by their own lifted handle helper. Keys: user effect EffectId+1, Fail families by declared head (negative keys); missing handler is panic("no handler for L"). Handler structs per layout (empty for Console/Fail layouts), perform functions call clauses with the frame’s outer context (intercept-and- forward), clauses lifted like lambdas. Features.Specialize.Unlowered is deleted; every ‘unlowered effect’ assertion was replaced by an executable assertion (test/fx-run.test.mjs, 24 programs with exact stdout). Two checker defects found and fixed: constructor patterns dropped row arguments (Check.Match/Tables), and consumption did not resolve a bound row tail (Check.Consume); Check-level tests in test/fx-check-fixes.test.mjs, each failing with its fix reverted. Review found one Critical: the clauses of one handle were installed in reverse (runtime panic for Error(Int) vs Error(Bool) clauses); fixed with probes. Regression rows: block-order needle updated; handler-metadata replaced by effect-free-ctx.

Evidence: rm -rf output && npm run verify (.build/fx001-task7-verify.log): build, gates, 786/786 parallel tests; serial 12/22, the 10 failures are the BACKLOG T007 environment bounds (same set on pre-change baselines); regression proofs 33/33 (.build/fx001-task7-regression.log). The fx-block.serial 20,000-let test sits at its 1,500 ms bound on this container: 49717bc 1,533-1,574 ms vs Task 7 1,386-1,505 ms, alternating.

FX001 Task 8 — defer, crash, cleanup and the defect report (2026-10-09)

Subagent-driven: Sonnet implementer (041cb31; fix round d5bfa8d, resumed after a container restart), Opus task review and scoped re-review. defer e (block item) and crash(value: a): b (built-in, printable argument, no effect, uncatchable) run through every phase. Cleanup runs LIFO, exactly once per exiting activation, in the registration context; the defect report follows spec §5 (exit status 1, first line the original cause, later lines cleanup failed: ; <not printable> decided statically). Runtime pieces (Format.Go.Cleanup, Format.Go.Report) are emitted only when used; defer and crash do not force ctx; blocks without defer emit no Go defer. Conventions recorded: with no pending cause the first cleanup crash is the unprefixed first line; Go runtime panics print as panic: <text>.

The user’s rule that defer must not fail is enforced soundly after review: the first implementation checked only labels, so five programs (callback parameters with ambient or named rows, unsettled closures, lambdas decided later) let a typed failure escape cleanup and become a fatal report. Ruling (controller, pending user confirmation of strict over a lacks-Fail constraint): the deferred expression has its own row; after the function’s constraints settle, a remaining Fail label or a tail resolved to a rigid row variable is E_EFFECT (defer must not fail, but it performs <L> / ... but it may perform any effect of <r>). Accepted limitations (spec §2, BACKLOG FX007): the bracket idiom needs with pure callbacks; a local lambda also called outside the defer in a non-main function is rejected in it. Report.payloadName now walks arrow spines by a loop (a 5,000-arrow payload crashed the compiler).

Evidence: fx-cleanup 32/32 (RED 24/26 before, then 7 new failing tests for the fix round; seven isolated mutants caught). npm run verify (.build/fx001-task8-verify.log): build, gates, 818/818 parallel tests; serial 12/22, the 10 failures are BACKLOG T007 timing bounds; regression proofs 33/33 (.build/fx001-task8-regression.log). Re-review probes: legitimate defers (defer log(1), defer print(x), monomorphic helpers) accepted; the check is linear (1k-8k defers).

FX001 Task 9 — effect diagnostic provenance (2026-10-10)

Subagent-driven: Sonnet implementer (2fc7a02; fix rounds 04ab898, cee8542, b80cc17), Opus task review and two Opus re-reviews, Sonnet re-review of the last one-line fix. (A first dispatch was lost to a container restart; the second was briefly stopped by a controller misreading of a user message and resumed with its work intact.) Effect errors now carry origin, boundary and path notes (spec §6): occurrence links live in the substitution and are recorded on every unification path (nested arrow rows, settleRows retries, consumption); deferred-row origins are kept apart from the function row; note texts follow ruling R4 and the wire carries related: [{ span, message }]. Resolved gains rowSpan on functions and parameters so boundary notes point at the written with (or the parameter name when the concerned row is nested or not the only pure row). Path hops, note count and characters are abbreviated (visibleLabels 4, pathHops 2, maxNotes 4, maxCharacters 2000 for notes); labels over 120 characters print Effect(…) in headlines. Pre-FX001 diagnostics are unchanged (related: [] by construction; wire JSON identical); 20,000-parameter signatures check in about 1.5 s.

Known limits recorded: maxCharacters bounds notes only — a headline with a very long type or effect name can exceed 2,000 characters (BACKLOG E011); the late-Fail-key defer note follows let-bound locals only and otherwise gives no note (never a wrong one; ~20 probes); origin notes may point outside the deferred expression.

Evidence: fx-diagnostics, fx-diagnostic-origins, fx-signature 46/46; the fix-round tests were each seen failing (the round-2 tests by the controller against 04ab898 in an isolated worktree). Final verify (.build/fx001-task9-fix3-verify.log): build, gates, parallel 847/848 — the one failure is large-source “three-thousand-constructor match” timing (BACKLOG T004; passes alone); serial phase failures are the T007 set; regression proofs 33/33 (.build/fx001-task9-fix3-regression.log).

FX001 Task 10 — reference interpreter and differential corpus (2026-10-10)

Subagent-driven: Sonnet implementer (50f84ae; fix round 9365db3), Opus task review, Sonnet scoped re-review. Test-side only: no compiler source changed (git diff 89de11c -- src scripts is empty). New files: test/fx-oracle.mjs (independent lexer, parser, values, frames, cleanup and interpreter; no compiler import), test/fx-gen-.mjs and fx-programs.mjs (generator), fx-census.mjs, fx-shrink.mjs, fx-diff-support.mjs, fx-oracle.test.mjs (parallel) and fx-differential.serial.test.mjs (serial, ruling F11). Executable probes moved unchanged into importable modules and imported back: fx-cleanup-programs, fx-console-programs, fx-task7-programs (Task 7’s eight inline run probes from fx-specialize and fx-handler-check). docs/engineering.md documents the corpus and the knobs WAXWING_FX_SEED and WAXWING_FX_PROGRAMS.

The interpreter models the shipped semantics: handler frames keyed by effect identity, Fail by the payload’s declared head, the first clause innermost, clauses in their with’s outer context, defer LIFO in its registration context, the pending abort heading a cleanup-crash report, cleanup failed: lines in execution order. It is validated against every executable probe of Tasks 2, 4, 7 and 8 (fx-oracle.test.mjs 86/86); the fx-cleanup injected cases and fx-block orders probes (Go transformed after emission) are excluded by name. Ruled deviations: the oracle parser re-implements the grammar rather than extending poly-parse.mjs (a closed closure that may not be edited); only the first three differences per run are shrunk (every difference’s seed and source are written first); the sensitivity check compares the interpreter with its inner-clause-context flag (50 programs, at least one difference), Go-vs-interpreter equality being the serial run’s job.

Default run: 500 programs, seed 20261010 (program i uses seed 20261010+i), five go-batches of 100, 0 differences, 0 rejections, 0 interpreter errors, 12.9 s (.build/fx001-task10-fix-default.log). Census (minimum): nested same-key 225 (50), intercept-and-forward 68 (50), aborts crossing an unrelated handle 109 (50), stage order with over-application 90 (50), escaped callbacks 109 (50); cleanup normal 267, abort 363, defect 119, crash on normal exit 65, crash while abort pending 38, several crashes 38, own failure during abort 193, registration context 74, unreached defer 143 (25 each). 25 rejection variants give E_EFFECT with the Task 8 texts at the defer span. Extra run: seed 7, 2,000 programs, 0 differences (.build/fx001-task10-large.log). Mutation witnesses (isolated copies): inner clause context, first clause outermost, FIFO cleanup, abort not heading the report, eager argument evaluation each fail the hand traces; disabling item removal or literal replacement fails the shrinker tests.

Finding: the interpreter exposed a hole in the strict defer rule — a deferred operation whose handler clause fails ends cleanup in a typed abort (BACKLOG FX008). The generator emits only fail-free random clauses until it is fixed.

Verify (.build/fx001-task10-fix-verify.log): build, gates, parallel 933/934 — the one failure is large-source “three-thousand-constructor match” (T004; passes alone). Serial phase run directly (.build/fx001-task10-fix-serial.log): the new differential tests pass; failures are timing bounds only — the T007 set, fn-scale 1,000-long arrow (also failed in Task 9’s serial log), the match ladder (T003, also failed in Task 9’s), and fn-scale “chain of 1,000 partial applications” (phases 253 ms; new in this log, and failing alone three times at 310-341 ms with compiler, scripts and that test unchanged since 89de11c — the container’s bound, recorded under T007). Regression proofs 33/33 (.build/fx001-task10-fix-regression.log).

FX008 design note: tracking handlers that may fail (2026-10-10)

Branch fx008 (from claude/vibrant-cerf-3km61i at fdd375a), on the user’s machine. Baseline rm -rf output && npm run verify (.build/fx008-baseline-verify.log): exit 0; build, gates, 934/934 parallel tests, 29/29 serial tests (the T003/T004/T007 timing bounds all passed here), 33/33 regression proofs. The user ran verify on main in the same checkout about the same time, and this session had just switched the checkout to fx008; overlap was not established, and this run passed.

Design only, no code: docs/plans/2026-10-10-abort-tracking-design.md. Recommended approach A: a nofail mark on each non-Fail label occurrence; with h gives the body’s label h’s mark; handler clauses get own rows (the R0 technique), and clause labels relate to the handler by ⊑, not unification; defer demands N on every label it performs; signatures write nofail L to rely on a handler not failing; a per-declaration two-point propagation, linear, with no scheme constraints; marks erased before specialization, so Go is unchanged. Alternatives B (totality per effect) and C (inferred marks) are recorded. Newly rejected: one pinned acceptance (fx-cleanup-programs a defer performing a non-Fail effect, migrated with with nofail Log), plus the pinned oracle hole. Independent Opus review dispatched; user decisions D1-D5 pending.

Review (Opus, review-fx008-design-result.md): Accept with fixes. Critical: C1, the solve was seeded only from defer demands, so a handler mark made N by a callee’s nofail signature was never checked (the cross-function hole stayed open); C2, separate clause rows need late consumption that keeps Fail, to a fixpoint, or the base effect system becomes unsound (the reviewer’s late-Fail program is Unhandled Fail(E) in main today). Important: equality merges through monomorphic locals (I1), no mark polymorphism for forwarding helpers (I2), an understated migration (I3), and a soundness argument to restate (I4). The reviewer ran the hole and the I1/I2 programs on the current compiler (accepted; I1/I2 run correctly). Revision 1 of the note applies every finding: a fixed settle order, seeding from every N mark, limitations L4/L5 with decisions D6/D7, the D0 interpretation decision, and minors M1-M10.

Re-review (rereview-fx008-design-result.md): C1, C2, I3, I4 and M1-M10 addressed; new Critical N1: the late-consumption fixpoint does not terminate when a restricted row shares its tail with its target (the reviewer’s programs: a never-called lambda with a Console-only cleanup, accepted today; a no-defer clause form, rejected today, which would hang). Revision 2 adds a shared-suffix rule, the full settle order (N2) and N3-N5. Round 3 judged the rule sound but the termination measure unsound as written (it used provenance links, which may cycle and must not influence typing); revision 3 uses a copy map local to that step. Revision 3 is not re-reviewed. Stopped for the user’s decisions D0-D7.

Verify at afedaec (docs only; .build/fx008-design-verify.log): rm -rf output && npm run verify exit 0; 934/934 parallel, 29/29 serial, 33/33 proofs.

Module and instance-selection direction (2026-10-10)

At the user’s request, documented module-system comparisons and fp-ts-style selection/construction of instances without mandatory newtypes in docs/plans/2026-10-10-modules-and-instance-selection-direction.md. Linked from language direction and C001/M001 backlog entries. Separates user preferences, recommendations and open decisions; covers abstraction/type identity, coherence, collection consistency and evidence for algebraic laws. No implementation or syntax approved. Active FX008 documents left untouched. Documentation inspection only; verification not run, preserving the user’s instruction not to run checks for this discussion.

Outside advice, shared by the user 2026-10-10 and treated as advice only (note §12; D0-D7 open), asked for a focused termination review. Revision 4 rewrote §3.5 steps 1-3. The fresh Opus review (review-fx008-termination-result.md) found:

Revision 5 adopts the corrected procedure:

The procedure is the reviewer’s and has had no second check.

Probes are copied to .build/fx008-probes/. The controller reproduced two defects in today’s checker:

Both are new BACKLOG rows.

Verify at 9b47e4b (docs only; .build/fx008-rev5-verify.log): exit 0; 934/934 parallel, 29/29 serial, 33/33 proofs.

User decisions 2026-10-10 (interview; note §11): D0-D5 as recommended; D6 mark variables (nofail(k) L) and D7 directional checking are included in FX008. Revision 6 of the note adds them. Including D7 needed two structural changes, which remove the merge and forwarding limitations (L4 mostly, L5):

Mark solving becomes a path check over a two-point lattice with rigid mark variables. One Opus review of the whole note is in progress. FX009 is being fixed test-first in parallel, on branch fx009 in a worktree.

FX009 review (Opus, review-fx009-result.md): Needs fixes.

FX008 revision 6 review (Opus, review-fx008-rev6-result.md): no Critical findings and no unsound acceptance found. The path check is correct, and the revision 5 loop holds with installation entries.

Revision 7 is unreviewed.

FX008 revision 7 check (Opus, review-fx008-rev7-result.md): soundness established. The two-row split restores meta2 and hole2c, but not all of today’s inference: late1 and late2, without defer, would be rejected. User decision: a one-way hook keeps R in step with the clause rows (revision 8). The other findings are applied as text:

A narrow review of the hook is in progress.

FX009 re-review (Opus, rereview-fx009-result.md):

User decision: every written Fail payload without a family key is E_TYPE at the label, in signatures and in handle clauses. Round 2 is in progress.

FX008 revision 9 applies the hook review (review-fx008-rev8-hook-result.md; no Critical findings, soundness unaffected):

F1 and F2 are unreviewed. A probe gate, which re-runs every review probe (kept in .build/fx008-probes/), is now the first plan task.

FX009’s round 2 was approved by the re-review, and the branch’s docs are committed (3518678 on fx009). Verify at 3518678: exit 0, 958/958 parallel, 29/29 serial, 36 proofs. It awaits the user’s merge decision. New BACKLOG FX012: firstUnkeyed runs before deferred rows settle.

FX009: unresolved Fail payloads rejected (2026-10-10)

Branch fx009, from fx008 at 531e438. Sonnet implementer (c445bac; review rounds 33a3a62 and f6cb6d0), Opus review and two re-reviews (docs/sdd/2026-10-09-effects-plan/review-fx009-result.md and rereview-fx009-result.md).

Defect: leftover deferred-key pairs were dropped silently, so a Fail(a) parameter row let a failure escape at run time (no handler for Fail).

User decisions:

The reviews found no program that reaches that guard (about 50 probes compared against a build without it), so it is a 3-line rejection. Mutants of the written-label checks are caught by the guard at the wrong span.

Evidence:

Spec §2 “Label keys” updated. Pre-existing and recorded separately: a handle whose failure key is decided only after deferred rows are settled is rejected early (firstUnkeyed runs in the first settle).

FX009 merged into fx008 (26fefe3, user decision 2026-10-10). Verify on the merged tree (.build/fx009-merge-verify.log): exit 0, 958/958 parallel, 29/29 serial, 36 proofs. The user asked for one focused review of FX008 revision 9’s F1/F2 procedure (termination, inference compatibility, scheduling). On no substantive issue, the user approves the written spec and the implementation plan follows, starting with the probe gate.

First-party Schema direction (2026-10-10)

Recorded the user’s requested Schema foundation as SCH001 in docs/plans/2026-10-10-schema-direction.md and the backlog, with links from language/tooling direction and a targeted LA001 comparison. Consulted Effect v4 Schema documentation and the supplied rae-hill/schemata-ts README/interface docs. Covers parse-into-domain boundaries, codecs, selectable interpreters, generators/shrinkers and independent properties. Library/compiler mechanism and v1 subset remain open. No implementation, tests, commit or verification run; preserves the user’s request not to run checks during design discussion.

SCH001 follow-up (2026-10-10): expanded schema-direction with capability overlap versus Effect, the direct io-ts Schema/Schemable precedent, tagless-final research and ZIO Schema’s different representation. No major required capability exclusive to schemata established; interpreter encoding versus AST remains open. Documentation inspection only; no checks run.

Focused F1/F2 review (review-fx008-rev9-f1f2-result.md): a substantive issue. Termination, inference compatibility and scheduling each failed as written (cyc1, ov1, set1, all accepted today). It found no unsound acceptance. Revision 10 applies the corrections:

FX008 revision 10 re-check (review-fx008-rev10-result.md): no substantive issue.

The wording fixes are applied. By the user’s condition (2026-10-10), the written spec is approved. The implementation plan is next, starting with the probe gate. Probes are kept in .build/fx008-probes/ (rev6-rev10).

FX006 constraints and FX008 hypothesis recorded (2026-10-10)

Docs only, from a review of the draft Waxwing article outline. BACKLOG gains FX006 (general resume) ahead of FX001 Task 12, carrying the plan’s scope plus the user’s constraints: multiplicity decided on language terms, one-shot by default and declared per operation so multi-shot stays an additive, row-visible extension, reserved spelling, at-most-once assumptions stated in defer/FX003/CF001, and a double-resume regression. FX008 records an unverified hole in defer must not fail through a failing handler clause. (Merged 2026-10-10 into branch fx008, which already tracked and verified this hole as FX008: the duplicate row was folded into that record. See “FX008 merge with the article-outline branch” below.) language-direction.md records the user’s direction that the language (frontend, syntax, type system) outranks the Go target. No code changed; no build or verify ran (a parallel worktree was active).

FX008 merge with the article-outline branch (2026-10-10)

Branch claude/optimistic-dijkstra-6i21jy (81990d6, 2b42574; docs only, from main 234d115) is merged into fx008 with a merge commit. Its FX006 row and the language-direction section “Language before target” are kept unchanged. The FX008 work does not contradict FX006’s constraints: design §4.6 makes any ctl clause’s handler may-fail until general resume. Its Task 12 change to the effects plan is kept.

Its FX008 row duplicated this branch’s FX008, recorded there as an unverified hypothesis. It is folded into this branch’s row and removed. The folded-in facts:

Established on the current compiler (probes in .build/fx008-probes/facts/):

docs/writing/article-outline.md Part 3 §5 now states:

§4 (the Task 8 case study) was checked against review-task8-result.md: the five programs and the 25/25 tests match. It is unchanged.

Verify at the outline merge (3e24e21; .build/fx008-merge-outline-verify.log): rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify exit 0; 958/958 parallel, 29/29 serial (timing bounds included), 36 regression proofs.

History tidied before publication (2026-10-10, user-authorized):

The tree differs from the verified 207474b only in docs.

FX008 implementation plan (docs/plans/2026-10-10-abort-tracking-plan.md, revision 3, 1,228 lines, 12 tasks plus setup). Drafted by an Opus planner and reviewed twice by an independent Opus reviewer (review-fx008-plan-result.md): round 1 “ready with fixes” (8 Important), round 2 “ready with fixes” (one Important, the ec1 expected text). All fixes are applied. The reviewer ran 102 probes, and the plan’s recorded outcomes match. The plan awaits the user’s approval and sign-off on the P3, P5, P6, P7, P10 and P11 decisions. Nothing is implemented.

User approval 2026-10-10: the FX008 plan (at 0d7cc27) is approved, with sign-off on P3, P5, P6, P7, P10 and P11 and P13 accepted. The user added:

Setup and Task 1 are authorized.

FX008 Task 1: probe gate (2026-10-10)

Worktree /Users/ethan/Desktop/waxwing-fx008-impl, branch fx008-impl, from 8fe4218. Sonnet implementer (58c3d61; fix round 71d6263), Opus task review and scoped re-review (review-fx008-task1-result.md): Spec ✅, Quality Approved.

test/fx008-probes/ holds 104 programs: 102 review probes, deduplicated, plus the witnesses ec1 and tp1. The table pins each probe’s outcome today:

It also records each probe’s FX008 outcome. 17 entries flip, each with a task, a reason and an exact outcome or a pattern with report-before-pin. 14 slow probes run in child processes with a 20 s timeout. A tamper hash covers the table, and invariant tests check flips; a flipped accepted entry must pin its Go hash.

Rulings:

The reviewer re-ran all 104 probes independently (0 mismatches), checked the timeout path (fails at 20,006 ms, no orphan process) and nine mutation kinds, each caught. Verify at 71d6263 (.build/task1-fix-verify.log in the worktree): exit 0, 1065/1065 parallel, 29/29 serial, 36 regression proofs. Stopped before Task 2, as authorized.

FX008 Task 2: mark representation (2026-10-10)

Sonnet implementer (66e4f5d; fix rounds c6af69f and 5ed5b0e). Opus task review and re-review (review-fx008-task2-result.md): Spec ✅, Quality Approved after the fixes. The second fix round (a test bound and plan text) was checked by the controller.

What it adds:

Behaviour is preserved: the gate is green, and the Go text and bootstrap snapshots are unchanged.

Review C1 (Critical): two handler rows doubled at every nested handler type. Depth 22 ran out of memory, where base accepts to 124. Ruling: clauses ∷ Maybe Row, where Nothing means the same as R. Passes visit C only when it is Just. Plan P2, P4 and the interfaces of Tasks 2, 4, 7 and 8 are updated. Timings now match base to depth 124, with identical Go.

Guards:

The strip test now covers bodies, operations and constructor fields, with four mutants caught. Plan updates for later tasks: Task 3’s localMarks gives a Just C only to handler types that are not nested in a handler row, with a guard. Task 7 gets a 30-literal guard and a note on unequal derived Eq.

Verify at 5ed5b0e (.build/task2-fix2-verify.log in the worktree): exit 0, 1070/1070 parallel, 31/31 serial, 36 proofs. New BACKLOG G004 (pre-existing): a depth-125 handler type ends in a RangeError instead of E_NESTING.

FX008 Task 3: nofail syntax, resolution and printing (2026-10-10)

Sonnet implementer (f16c6b5; fix rounds 1f9f257 and e0580a4). Opus task review and re-review (review-fx008-task3-result.md): Spec ✅, Quality Approved. The second fix round was checked by the controller.

What it adds:

The reviewer compared whole-compile outcomes between base and candidate on 3,371 harvested sources plus 23,029 mutated ones: 0 differences for programs without nofail. 45 adversarial grammar programs confirm nofail stays an ordinary name elsewhere.

Rulings:

New BACKLOG E012 (pre-existing): closed and ambient rows print alike. Verify at e0580a4 (.build/task3-fix2-verify.log in the worktree): exit 0, 1105/1105 parallel, 33/33 serial, 36 proofs; gate 107/107.

User decision 2026-10-10 (FX008 Task 4): mismatch texts are symmetric. When either side of an E_TYPE mismatch shows a handler clause row or an arrow row, both sides show theirs. An empty handler row prints with pure, and ambient tails stay omitted. This amends the approved P3 callback text to Expected Unit -> Unit with nofail Log, found Unit -> Unit with Log.

FX008 Task 4: directional consumption, copies, mark equality (2026-10-10)

Sonnet implementer (3b0dd3e; fix rounds aa8db84, a43f56c, 84b684e). Opus task review and re-review (review-fx008-task4-result.md): Spec ✅, Quality Approved. Rounds 2 and 3 were checked by the controller.

What it adds:

Review fixes:

Evidence:

User decisions 2026-10-10 (FX008 Task 5 probe gate):

FX008 Task 5: the settling loop over deferred rows (2026-10-10)

Sonnet implementer (d9a0576; fix round dd45b58; comment b5fab7c). Opus task review and re-review (review-fx008-task5-result.md): Spec ✅, Quality Approved.

The corrected §3.5 loop (Features.Check.Settle, Feed, FeedOrder, Cycle):

Probe gate, with the user’s decisions: dup, n1 and r5 flip as planned, and design-review/r4 (wrongly predicted unchanged) is a fourth flip. All four texts are pinned exactly. The differential against 84b684e shows only those programs differ. A 60,000-graph brute-force check confirms cycle detection.

The review found the settle order quadratic: an eager maybe fallback took 8,000 defers to 6.4 s against base’s 0.8 s. It is fixed with maybe'. Now linear, at about 1.3x base. Guards:

Recorded:

Verify at dd45b58 (.build/task5-fix-verify.log in the worktree): exit 0, 1142/1142 parallel, 34/34 serial, 38 proofs; gate 107/107.

2026-10-10, at the user’s request:

FX008 Task 6: tail watches and the restricted registry (2026-10-11)

Sonnet implementer (01cbe77 refactor, 418cd38; fix round c8503f9). Opus review (review-fx008-task6-result.md): Spec ✅, Quality Needs fixes; the fix round was checked by the controller.

What it adds, with no behaviour change:

Review fixes: I1, the revert test could not fail (a mutant keeping the progressed watch passed); it now watches both tails and fails on that mutant. M1 compose keeps the later watch. M2/M3 comment the invariants Task 7 relies on. The reviewer killed the other three mutants (one per test).

Evidence:

FX008 Task 7: clause own rows, sync, correction S, tail pass (2026-10-11)

Sonnet implementer (wip 8dd22be; 9358d79; fix rounds 95eac9e, 66f1eca). Opus design pre-review (review-fx008-task7-design-result.md, A1-A7, two Critical design defects fixed before code), gate diagnosis (review-fx008-task7-gate-diagnosis.md), code review and re-review (review-fx008-task7-result.md); round 2 checked by the controller.

User decisions 2026-10-11:

Controller ruling: F1′ also runs at the start of each settling round (a plan gap, not a workaround), skipping the rigid branch (the tail pass binds ϱ after the loop), reporting at the handler literal.

Evidence:

Open: no probe distinguishes F1′’s join-group from a new group (cost only); Task 8 must build env.current labels from R and pair C by key.

INF001 requirements recorded (2026-10-11)

User requested a project milestone for automatic requirement inference, then explicitly required error composition during service assembly and business logic. Recorded A1-A10, design alternatives, current named-function inference gap, generic error-family questions, FX008 compatibility and completion evidence in the milestone. Status: requirements defined; language design and implementation plan remain. No compiler changes; active FX008 delivery is unchanged.

Documentation checks: A1-A10 present, tracking links resolve, and git diff --check passed. Fresh npm run verify exited 1: 958/958 parallel tests and 28/29 serial tests passed; partialFirst at 20,000 parameters took 973.142 ms against its 930 ms bound (T007). Build, strict rebuild proof and structural gates passed. Regression proofs were not reached. No retry or assertion change. Evidence: .build/inf001-definition-verify.log. This run verifies no INF001 behavior.

FX008 Task 8: installations with frame marks (2026-10-11)

Sonnet implementer (b30b8b8; fix round ff0c6d1). Opus review (review-fx008-task8-result.md): Spec ✅ given the deviation, Quality Needs fixes; the fix round was checked by the controller.

What it adds, with no probe change: each with registers an installation with a frame mark (NoFail for Console, else a fresh mark meta); settling pairs the handler’s clause row C with the installing row by key and position (Lend.assume), taking arguments from R, and records the frame ⊑ C edges; the tail pass gains an installation rule (a guard, unreachable while R ≡ current).

Deviation, accepted by the controller: install does not consume C, as the plan said; consumption renamed row tails (442-449 check-phase IR differences, nothing later). The reviewer swapped the plan’s consumption back in and found identical mark-edge sets over 3,151 sources (570 with installations), with the fallback never taken. The plan now describes assume.

Review fixes: I1, 1,000 installations went from 3.97 s (base) to 11.6 s; now 5.2-6.3 s (eager where bindings recomputed pairing every round); serial guard 9.5 s. I2, edge endpoints and direction asserted (a reversed-edge mutant fails 2 of 6), plus a nested duplicate-key case.

Evidence: gate 110/110, no change; differential 0 differences against 66f1eca and b30b8b8; verify at ff0c6d1 (.build/task8-fix-verify.log in the worktree): exit 0, 1182/1182 parallel, 37/37 serial, 49 proof lines.

FX008 Task 9: the mark check makes defer sound (2026-10-11/12)

Sonnet implementer (1649218; fix rounds 360f13e, 889ca99). Opus review and re-review (review-fx008-task9-result.md); round 2 checked by the controller.

What it adds: after settling, markConstraints records frame, own-abort and defer-demand edges; violation searches paths from Plain and the declaration’s mark variables to a fail-free atom (P7), and reportViolation chooses the headline by the last edge (P6), with the approved P10 texts. The pinned FX008 program is rejected with defer must not fail, but it performs Log, whose handler may fail. Exactly the 8 listed probes flipped (lexical, hole, c1, cross, pending, l4b, merge2, q1). The fx-cleanup program and the generator were migrated (§6).

Review findings and user decisions:

Evidence:

FX008 Task 10: notes for mark rejections (2026-10-12)

Sonnet implementer (d85a791; fix round 52b9df8). Opus review (review-fx008-task10-result.md): Approved, 4 Minor; the fix round was checked by the controller.

Mark rejections now carry the approved P10 notes, from the demand back to the source: <L> is handled here, `this handler’s clauses perform

, whose handler may fail`, `this handler's clauses may perform any effect of `, `its clause for fails with ` / `may perform any effect of `, `the signature of allows a failing handler; write with nofail `, and `nofail() is fail-free only when the caller's handler is`. Every plan assertion matched on the first run, including merge2. A 1,000-hop path keeps its first three notes and its source within maxCharacters. Implementation decision: a path starting at Plain through a DeferDemand edge also gives the signature note (P1). Evidence: 12 assertions seen failing first; differential against 889ca99: 23 differences, all notes only (code, message, span unchanged); verify at 52b9df8 (.build/task10-fix-verify.log in the worktree): exit 0, 1226/1226 parallel, 41/41 serial. ### FX008 Task 11: failing random clauses and the soundness differential (2026-10-12) Sonnet implementer (2ef711b; fix round 0a571d4). Opus review (review-fx008-task11-result.md): changes required; the fix round was checked by the controller. Test-side only; no compiler change. The generator now produces failing handler clauses in the default corpus (178 per 500 programs; 116 without the dedicated fragment), lifting FX001 Task 10's fail-free restriction. The one-way soundness differential (test/fx008-soundness.serial.test.mjs, 300 programs whose cleanup ignores which handlers may fail) requires every escape the reference interpreter witnesses to be rejected with an FX008 headline, and every accepted program to agree with the interpreter and Go. The review found the first version's evidence covered one shape (73 of 77 escapes lexical) and that random failing clauses never ran. After the fix, escapes by shape at the default seed, all rejected: lexical 24, forwarding 24, callee under a caller's handler (plain 9, nofail 9), handler value passed 12, returned 10, ambient callback 14, random clause 18. Sensitivity: Task 8's compiler (ff0c6d1, no mark check) accepts 110 of the 120. Ten seeds: no accepted escape, no Go/interpreter disagreement. Evidence: serial run 15.5 s; verify at 0a571d4 (.build/task11-fix-verify.log in the worktree): exit 0, 1226/1226 parallel, 47/47 serial. Gap for the whole-branch review: the generator has no `nofail(k)` mark-variable shape. ### FX008 Task 12: spec, CF001 and FX001 plan amendments (2026-10-12) Sonnet implementer (9a62014), docs only; checked by the controller (the P10 headlines and notes appear in the spec; CF001 changed only §5 R0, §8A.6 and §8A.8). The effects spec now carries the FX008 rule, the `nofail` and `nofail(k)` syntax, the approved texts, and the rulings made during implementation (C carries no label arguments; F1′ in settling; installation by `assume`; a result handler type's own C; opening only at function signatures). Limitations are BACKLOG FX013-FX016. Verify at 9a62014: exit 0, 1226/1226, 47/47; 64 regression proofs, 28 of them FX008. FX008 Tasks 1-12 are complete. Before merging: T008 (user decision) and the whole-branch review. ### T008: linear settling for shared tails (2026-10-12) Sonnet implementer (33f9854; fix round e54d869), Opus review (review-t008-result.md): approved with fixes, checked by the controller. Profiling showed the quadratic cost was not the feed graph: each settling consumption added a label-free alias hop to one shared row, and every walk crossed the whole chain. Features.Check.Aliases keeps classes of such hops and jumps to their end. 1,000 installations in one declaration: 7.9 s → 0.5 s; 2,000: 35 s → 1.0 s; other scale cases unchanged. Differential against 9a62014: 0 differences in every phase. Guards: a 2,000/1,000 ratio test, two regression rows, and a property test comparing jumps with a naive walk (~500k checks). Verify at e54d869 (.build/t008-fix-verify.log in the worktree): exit 0. INF001 main-integration review (2026-10-11): independent requirements and adversarial reviews approved the brief, with no blocking findings. Minor M1 addressed by individually named B1-B8 observations and a handler-site failure witness; scoped adversarial follow-up approved. Reports, process audit and dispositions: `docs/sdd/2026-10-11-inference-milestone/`. Fresh isolated full verify exited 1: 957/958 parallel tests; unchanged 10,000-type inhabitation chain 7.196051 s against 5 s (T004), no retry. Unreached serial phase run separately: 29/29 passed. Compiler inputs are identical to main baseline d35edf2. The prior T007 failure remains recorded. This records a reviewed requirements brief, not an approved language design. User clarified that shipping documentation does not require compiler tests. Stopped the isolated regression run; partial proof output is not a full result. Documentation release checks and both reviews are complete; no compiler tests are a gate for this brief. All observed failures remain recorded. No other agent's checkout or processes were changed. INF001 requirements and reviews integrated into local main at da1b4d0 with an atomic expected-reference guard. Shared checkout HEAD, index and working status unchanged; other agent's implementation worktree untouched. No remote push. Integration receipt: INF001 review ledger. ### FX001 Task 11: acceptance scenario and scale (2026-10-12) Sonnet implementer (3b51d21). Scenario examples/services.wxw: Database, Clock and Log, five service functions with only their own labels, cleanup by `defer` with `nofail Log` along the chain, real and stateless fake handlers built inline in `main` and selected there. Snapshot bootstrap/services.go (byte-compared; other snapshots unchanged). Real and fake outputs asserted. The scenario has no `Fail` (docs/findings.md, "FX001 Task 11: callback rows"). Keys (F6): scenario 9 = 0 type + 6 function + 3 effect (Log, Database, Clock); the baseline has the same 6 function keys; the extras are exactly the three effect keys. Dropped Clock handler: E_EFFECT `Unhandled Clock in main` at `report(1, 2)`; notes `audited(first)` "through report", `stamp(id)` "through audited", `now()` "Clock is performed here", `main` "main may perform only Console"; as spec section 6, within 2,000 characters. Timings (serial; whole-process wall time after a warm-up run; five runs, load averages 1.54-1.59; bound 3x median): | Workload | Median ms (min-max) | Bound | |---|---|---| | 10^6 shallow installs | 131 (128-134) | 393 | | 10^6 operations, context 100 deep | 141 (137-144) | 423 | | one fail across 1,000 handle frames | 46 (45-47) | 138 | | 100,000 caught failures | 38 (35-39) | 114 | | go build of the scenario | 135 (134-142) | 405 | Installation and lookup are about 10^6-deep non-tail recursion in the emitted Go; the review measured about 40 ms without operations against about 135 ms with them, so recursion does not dominate. The unwinding and caught-failure figures are close to the roughly 30 ms process start and resolve little. The go build bound assumes the warm `.build/go-cache` that verify provides. Under verify (load 4.9) the build took 292 ms. FX005 observation against Task 1's hand-written Go (loops, not process time): installs 18.3 ms, lookup at depth 100 79.8 ms, 1,000-frame abort 34.9 ms, 100,000 caught aborts 19.9 ms. Waxwing's installs cost about 5x and lookup about 1.4x (net of start), the others are within noise of start. Shapes differ, so these are upper bounds, not a like-for-like comparison. 1,000-label row (CLI): `emit` compiles; rejecting a call of it prints 498 characters (`Unhandled E1 in main`); a side-condition rejection of rows of 999 and 1,000 labels prints 451 (limit 2,000). `rm -rf output && npm run verify` (.build/task11-verify.log in the worktree): the first run failed one parallel test, specialize.test.mjs (it assumes examples are identity-specialized; services.wxw declares effects), fixed by excluding it; the rerun exit 0, 1252/1252, serial and regression proofs passed. ### FX001 Task 12: regression proofs and documentation (2026-10-12) Part A (Sonnet implementer, ab456fa `test: FX001 regression proofs`, reviewed): fifteen new regression rows, each restoring one defect in an isolated copy, with probes that pass on the healthy compiler and fail on the mutant with a named message. Checker and diagnostics rows (scripts/regression-fx.mjs, probes in test/regression-fx.mjs): `fx-side-condition` (the probe compiles in a child process under its own 20 s timeout and reports the timeout as the defect, so the runner's 180 s timeout never fires), `fx-defer-fail`, `fx-defer-rigid`, `fx-defer-unified`, `fx-closed-opened`, `fx-layout-edges`, `fx-provenance`, `fx-abbreviation`. Emitted-Go rows (scripts/regression-fx-go.mjs, probes in test/regression-fx-go.mjs): `fx-clause-context`, `fx-abort-target`, `fx-clause-order` (Task 7 Critical), `fx-cleanup-context`, `fx-cleanup-cause`, `fx-cleanup-defect`, `fx-ctx-reachable`. `ctx` for effect-free programs is the existing row `effect-free-ctx` (Task 7), not duplicated. test/regression.mjs is untouched; test/regression-probes.mjs and scripts/regression.mjs gained an import and a spread. The mutant re-targeting notes (no single-line restoration for `fx-cleanup-context`; `fx-ctx-reachable` is an entry-body-only stand-in) are in docs/findings.md. Verify after part A (`rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify`, .build/task12a-verify.log in the worktree): exit 0, 81 regression proofs in all, each new one printing `fixed compiler passes; restored defect fails.` No bound raised, no rerun. Part B (documentation only, no code): ADR 010 (docs/adr/010-effects.md: row erasure revising direction decision 1; runtime keys; first clause innermost; `ctx` mode over the emitted IR; the 10,000-key count of keys with type arguments only, ruling F5; the strict `defer` rule, its accepted costs (FX007) and FX008's mark refinement with the limitations L1 with P5, L4, L6 and the handler-through-a-generic-function case; report conventions; the empty `Handler(Console)`/`Handler(Fail(E))` structs, ruling F3; Task 11's key-count and timing evidence); the language Effects section (docs/language.md, with the documented limits and E_EFFECT/E_HANDLER added to the code list); docs/architecture.md (the FX001 modules); docs/ engineering.md (the fifteen rows and the Task 11 timing convention, a review convention: median of five, bound 3x); docs/findings.md; BACKLOG (FX001 Done pending whole-branch review; FX008 corrected to merged; new FX002, FX003, FX005; FX006, FX007, CF001, D001, R001, STD001, PKG001, I001 and FN006 updated; FN006 (1) only half closed); and docs/next-session.md. FX001 Tasks 1-12 are complete on branch fx001-finish, pending the whole-branch review, then the user's merge decision. Final whole-branch review (2026-10-12) and fix wave (docs and test regexes only, no compiler change): the review found the callback-row limit untracked (FX017: probes reproduced, workaround in docs/language.md Limits), eight documentation corrections in ADR 010, language.md, findings and BACKLOG, and seven row `message` regexes that matched only a prefix; they now match the observed detection and each of the seven rows prints `fixed compiler passes; restored defect fails.` T003 and FX001 gained notes (timing retune, timeout in `timedRun`, typed-failure scenario), recorded only. Verify: `rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify` exit 0 (.build/final-fix-verify.log), 81 regression proofs, no bound raised, no rerun. ### FX017: callback-row diagnostic (2026-10-12) Branch fx017 (from 3ff0538, the approved text). A function value applied inside a function whose signature row has a label the value's row lacks (`fn a(q: Int -> Int with L, x: Int): Int with L + M = q(x)`) was reported as `a performs M, which its signature does not allow`, contradicting the signature. It is now E_EFFECT at the call with the approved text: `q must allow every effect of a (L + M), but its row is L` (`but its row has no labels` for an unannotated arrow, `this function value` for a callee that is not a named parameter), the hint `write q's row as `with L + M`; a callback's row must equal its caller's (FX017)` after `; `, and notes `q's row is written here` and `a's row is written here`. Classification (Features.Check.Callback): the unifier pairs the callee's labels first, so `RowMissing` is the callee performing what the caller lacks (unchanged: probes p5, p6) and `RowExtra`, now carrying the row it was left over against, is a caller label the callee lacks. The new text needs that, an `Application` origin that crossed no boundary (installation and `defer` set `via`), and a current row that is the signature's alone (one site): inside a `with` or `handle` a callee's label can pair with an installed duplicate, and the old text stays. Accepted and rejected programs are unchanged (differential: only the new-text programs differ). Recorded limits: a `let`-bound or lambda-bound callee is `this function value` (the resolved syntax keeps no local's name); an unannotated arrow's note points at the parameter's name (no type span is kept) and reads `q's row is not written`; a call inside a `with` or `handle`, and a callback passed as an argument, kept their old text until FX018; the hint writes the caller's row as written, so a named tail stays (p3: `with M + L + ...e`) and the ambient tail is omitted, while the headline prints labels only. When a caller label's payload holds an arrow, handler or row-applied type, the printer drops its rows, so the hint takes the anonymous text instead of a row that would fail differently when written. Only a parameter whose type is one arrow (its result is no arrow) is named; later stages and two-stage types are anonymous (their `with` belongs to the last arrow, so the hint would loop), and a leftover from a row nested in a label payload keeps the old text. Tests: test/fx017-callback-row.test.mjs (16); regression row `fx-callback-row`. Subsumption of the callback's row stays with FX007. Verify: `rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify` exit 0 (.build/fx017-verify.log): 1264/1264 parallel, 53/53 serial, 82 regression proofs. Differential against a build of 3ff0538 (.build/fx017-differential.log, exit 1 by design): 8 differences in 3,841 harvested sources, all the new FX017 probes; 0 in 1,029 fuzz, 1,085 `isName`, 1,000 matches and 1,000 mutations sources. No bound raised, no rerun hiding a failure (the first verify attempts failed on an 80-column comment and a regression needle that the new `RowExtra` layout broke; both fixed, then one clean run). ### FX018: callback-row diagnostics in with/handle and argument passing (2026-10-13) Branch fx018 (from 0a23784, wording chosen in BACKLOG FX018). Diagnostic only: the accepted and rejected programs and the Go output are unchanged. (a) A callback-row mismatch directly in a function's body but under `with` or `handle` (`Features.Check.Callback`; FX017 had excluded it): `q must allow every effect at this call (M + L + M), but its row is L; write q's row as `with M + L + M`; a callback's row must equal the row where it is called (FX018)`. The row at the call is the installed labels, innermost first, then the signature's; the notes are the callee's, `M is handled here` at each installing `with`/`handle`, and the caller's. The two corpus programs where a callee label pairs with an installed duplicate (`around`) get this text and it is true there: the hint (`with Log + Log + ...e`) compiles. The FX008 probe table pins these two (rev6/around3 and rev6/around6): their expected text, around3's notes and the table hash changed with this task, for the reviewer's diff of test/fx008-probe-table-rev6.mjs. Inside a lambda body there is no signature site and the old text stays. (b) A function passed where the parameter's row has a label the function's row lacks (`Features.Check.ArgumentRow`, from `Argument.refused`): `q must allow every effect of take's parameter f (L + M), but its row is L; ... (FX018)` with the callee's note and `f's row is written here`. Only the top-level arrow row of the argument against the parameter's counts: the two rows are unified on their own and must fail for a label the argument lacks. The other direction (b3), a nested row, and applications of function values keep the old text. A constructor field has no parameter name (`of the parameter it is passed to`). FX017's rules carry over (named only for single-stage parameters; payload rows holding a row give the anonymous hint; named tails kept). One new rule: the `write …` hint of (b) is printed only if a simulation of the rewritten argument, unifying it with the parameter and consuming the callee's row, succeeds. A sweep of 616 generated programs found cases where the parameter's row is not enough (a caller wider than the callee, since the callee's ambient tail is shared with the argument's; a constructor's closed row); those keep the headline with the anonymous hint. The hint's tail is the row at the call's named tail, which the callee's own row ends in. After that change no printed hint failed on the sweep, and each tested hint is shown to compile when applied. Tests: test/fx018-callback-row.test.mjs, test/fx018-argument-row.test.mjs; regression rows `fx-callback-install` and `fx-callback-argument` (and `fx-callback-row`, whose needle moved). Verify: `rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify` exit 0 (.build/fx018-verify.log): 1291/1291 parallel, 53/53 serial, 84 regression proofs. Differential against a build of 0a23784 (.build/fx018-differential.log, exit 1 by design): 312 differences in 4,492 harvested sources and 5 in 1,000 mutations sources, every one a previously rejected program whose message is now an FX018 (or FX017) text, none an acceptance or Go change; 0 in fuzz, `isName` and matches. The first verify attempts failed on the style gate (a `case` on `Either`) and on the two FX008 probes above. FX018 review fix (2026-10-13): an (a) or FX017 `write …` hint is printed only for a callback read once in the function (`Features.Check.LocalUses`); with a call outside and one inside a `with`, no one row serves both. The effect error's subject for a function value is a named constant (`thisFunction`), not a copy of the text. Verify exit 0 (.build/fx018-fix-verify.log): 1298/1298 parallel, 53/53 serial, 84 proofs; differential (against 0a23784): 421 harvested and 2 mutations differences, every one rejected by both compilers with an FX017/FX018 text. ## Services example injects implementations (2026-10-13) Principle (user): never choose an implementation with a control-flow artifact; construct each as a value and inject it at the composition root. examples/services.wxw now has `liveDatabase`, `systemClock` and `consoleLogger` constructors and a `main` that installs them with `with`; no `live` flag, no `if`. The tests build `fakeDatabase`, `fixedClock` and `silentLogger` and their own `main` (test/fx-services-programs.mjs); the effect-free baseline takes lambdas from named constructors. Outputs are unchanged (live and fake). The dropped-handler diagnostic is unchanged in text: `Unhandled Clock in main` with the through, origin and boundary notes (drop `with systemClock()`). Key breakdown: before 9 keys (0 type, 6 function, 3 effect; baseline 6), after 12 (0 type, 9 function, 3 effect; baseline 9). bootstrap/services.go regenerated; the other snapshots are byte-identical. Mark sharing moved to test/fx-services-marks.test.mjs (an `if` between two Log handlers reached by a `nofail Log` cleanup: accepted when both are fail-free, `Expected nofail Log, found Log` when one may fail). An entry function taking the handlers as parameters could not be written: BACKLOG FX019 (the logger needs the named tail `Handler(nofail Log with Console + ...e)`). No compiler change. Verify (services-di, 2026-10-13): `rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify` exit 0 (.build/services-di-verify.log): 1301/1301 parallel, 53/53 serial, 84 regression proofs. A first run at load average about 25 failed two serial timing tests (`a 5,000-parameter function type through generics builds in 10 s`, `20,000 let items compile in linear time`) and the rerun at lower load passed; the failure is recorded in the BACKLOG T007 row. ## Text v1 (D001, first tranche) done on branch `text` (2026-10-13) Plan docs/plans/2026-10-13-text-plan.md, Tasks 1-9, on branch `text` rebased onto main 0b1f850; spec docs/plans/2026-10-13-text-design.md, ADR 011 (docs/adr/011-text.md). Not merged; the whole-branch review is next. Delivered: - `Text`, a reserved ground type lowered to a Go `string`, with ordinary, raw (`#"…"#`) and `"""` block literals, `${}` interpolation (left to right, nesting), `++`, comparison by code point, canonical quoting of Text nested in data, and the built-in `show`. - Source read as UTF-8 with a fatal decoder; the first invalid byte is a diagnostic (`ReadFailure`). Non-ASCII outside a literal stays E_LEX, with a whole-code-point span. - Splits made for room before adding: Domain.Type.Core, Domain.Syntax.Core, Format.Parse.Steps, Format.Lex.{Origin,Escape,Chars}. - Reference model: independent decoder, quoter and code-point comparison; the effects oracle and FX generator gained Text. Differential 0 disagreements on every seed tried. Task 9 (regression proofs, scale, example, docs): - Seven isolated-copy rows (scripts/regression-text.mjs, probes in test/regression-text.mjs), each printing "fixed compiler passes; restored defect fails": `text-order`, `text-nested-raw`, `text-indent-count`, `text-dollar`, `text-hash-mismatch`, `text-surrogate`, `text-utf16-order`. Go compares strings bytewise, which on valid UTF-8 is code-point order, and no Go helper compares Text, so the "native UTF-16 comparison" mutant replaces the field comparison in Format.Go.Compare with a UTF-16 unit comparison. The runner's replace now takes a function, because a `$'` in a replacement is a replace pattern (the `text-dollar` mutant has one). - Scale (test/text-scale.serial.test.mjs, serial phase): a 1 MB literal, 10,000 interpolation parts and a literal of 100,000 escapes compile and run with the right output; emission is deterministic (two emits equal). Bound = 3x the median of five runs on this host (macOS, Node 26.6.0, Go 1.26.4), compile in-process and `go build` alone. Method (fix round 1, docs/engineering.md): one warm-up `go build` of a trivial program, then each measured build is the minimum of three; the first version timed a single build, which at about 130 ms (Go's fixed startup and link cost) is as large as the 1 MB and 100,000-escape bounds. Five serial runs under the new method, 1-, 5- and 15-minute load averages before each run: 2.88 3.16 3.86; 2.82 3.14 3.84; 2.78 3.12 3.83; 2.65 3.08 3.81; 2.76 3.10 3.81. Single-build medians of the first method (ms): 1 MB 141 compile and 146 build, 10,000 parts 521 and 709, 100,000 escapes 142 and 130. Under the new method: | Case | Phase | Median ms | Min | Max | Bound ms | |---|---|---|---|---|---| | 1 MB literal | compile | 142 | 139 | 151 | 423 | | 1 MB literal | go build (min of 3) | 151 | 146 | 153 | 438 | | 10,000 parts | compile | 531 | 515 | 536 | 1563 | | 10,000 parts | go build (min of 3) | 719 | 717 | 724 | 2127 | | 100,000 escapes | compile | 148 | 138 | 153 | 426 | | 100,000 escapes | go build (min of 3) | 133 | 131 | 137 | 390 | The medians moved by 1 to 4 percent (noise), so no bound changed: none is raised, none lowered. - examples/text.wxw (a `Directory` effect injected by `with directory()`, a pipe with one stage per line, a block, a raw literal, an `Entry(Text, Int)` printed nested, `show`) with bootstrap/text.go compared byte for byte in test/text-literal.test.mjs; the six existing snapshots are byte-identical (checked with `emit`). test/specialize.test.mjs now lists text.wxw with the examples that intern an arrow. - Docs: ADR 011, the Text section of docs/language.md (including `"""` maximal munch, the non-BMP location convention and holes sharing the nesting budget), docs/architecture.md and docs/engineering.md (Text rows), the spec's §1 maximal-munch sentence and §6 lone-CR span note, README (Text under "works today", "strings" removed from "Not yet supported", roadmap), BACKLOG (D001, STD001, header, T007), and the stale `chainLeft1` / Grammar `apply` references (now `chainLeftAny` and Format.Parse.Steps' `applyAt`; docs/architecture.md, docs/engineering.md, docs/adr/006-nesting-limit.md, test/regression.mjs, BACKLOG O001). Evidence: - `rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify` exit 0 (.build/text-t9-verify.log): 1535/1535 parallel, 57/57 serial, 91 regression proofs, 7 of them the new Text rows. A first attempt (.build/text-t9-verify-first.log) failed one test, `specialize is the identity on monomorphic programs`, because examples/text.wxw interns an arrow; fixed by listing it, then the full run above passed. - Differential against f36744d (`scripts/differential.mjs --corpus all --regenerate`, .build/text-t9-diff.log): harvested 6775 sources, fuzz 1029, isName 1085, matches 1000, mutations 1000: 0 differences (no compiler change since f36744d). The harvest run's test pass exited 1 on timing tests under the hook; recorded in BACKLOG T007 with figures only. - `.build/regression` and the baseline copy were deleted. Text v1 Task 9 fix round 1 (2026-10-13): scale test now warms up and takes the minimum of three builds (medians above; no bound changed); hash-mismatch probe message corrected; example's `welcome` and `rawPath` renamed and bootstrap/text.go regenerated; README shows the whole example verbatim; EBNF, spec notes and dates fixed; a Text-only program joined `specialize is the identity`. Verify exit 0 (.build/text-t9-fix-verify.log): 1535/1535, 57/57, 91 proofs. Inside verify the `go build` minimums were 300, 883 and 292 ms (bounds 438, 2127, 390), about twice the standalone figures: the bounds hold but the margin is thin on the 100,000-escape case. No timing failure, so no T007 entry. ## FX020 effect operation namespaces done on branch `fx020` (2026-10-14) Plan docs/plans/2026-10-13-effect-namespaces-plan.md, Tasks 1-8 on branch `fx020` from main 26611c3 (worktree .worktrees/fx020); spec docs/plans/2026-10-13-effect-namespaces-design.md, ADR 012 (docs/adr/012-effect-namespaces.md). Not merged; the hint wordings were approved 2026-10-14 and the merge into main is next. Ledger and task reports: .superpowers/sdd/2026-10-13-effect-namespaces-plan/ (progress.md, task-*-report.md; rulings R1-R18). Delivered: - Every operation is `Effect.op`, resolved by declaration and never by the row; `.` is a token, and only an uppercase name before it qualifies. - A function's own row may alias effects and import operations (`with Database as D + Log { log, info as note }`); lexical order binders, parameters, imports, globals with no fallback; the three approved collision and placement errors, with notes. - `fail` is no longer a keyword: `Fail.fail(e)` and an imported `fail(e)` are one `Resolved.Fail` node (an imported family rides on it, R12); a Fail reference is an eta lambda. Console and Fail are built-in declarations with no EffectIds (runtime keys unchanged). - Unbound bare operation names keep their error with a hint; the multi-candidate wording (R18) was approved 2026-10-14. `Console.print` and `show` remain compiler-provided until C001. - Final review (R19): a qualifier's `.` touches both names (`Log . log(1)` and `Log\n.log(1)` give the stray-`.` `Expected ';'` at the `.`; test/fx020-qualified.test.mjs), at no parser stack cost (depth probe, limit lifted, isolated copies at 9c488ca and after: constructor-argument 259, call-argument 296, parens 396, parens-in-call-in-constructor 326, all unchanged); aliases and imports are folded one label at a time, so the first error in source order wins (test/fx020-imports-review.test.mjs). - The corpus (examples, 101 fixtures, tests; about 920 automatic edits (sum of the Task 6 report's chunk figures) plus manual ones) was migrated by a one-off tool, then the tool, the paired run and bare-name support were removed (R4, Task 7). Tasks (commits on fx020): - Task 1: behaviour-preserving splits (bb083c5, fb89cd5): Format.Diagnostic.Code, test/fx-oracle-expr.mjs, test/regression-diag.mjs. - Task 2: qualified operations (c503adb, fix 19784ed): lexer `.`, Format.Parse.Name, Features.Resolve.{Name,Qualified}. G002 margin measured: constructor-argument 259. - Task 2b (controller-added, R7): the Fail reference as an eta lambda (5d66dcc). - Task 3: aliases and imports (96e8450, fix 6c88869): Resolve.Imports, Format.Parse.Chain, R10, R11, R12; FX021 added. - Task 4: Console and Fail as built-in declarations, E_DUPLICATE (3c5547f). - Task 5a: the rewrite tool, manifest, edit map and paired differential (739194c, c9601dd, c4e3920); Task 5b: reference interpreter and generator for qualified names, imports and aliases (c781627, fd83293). The 5a/5b split is R13. - Task 6: corpus migration in chunks (4878aaa .. ee455f6), 10 commits plus a review fix round. - Task 7: bare resolution and tooling removed, unbound hint (383699f, e21b19a). - Task 8: review cleanups (3ab36d2, `refactor: FX020 review cleanups`) and the documentation commit. Evidence (logs under .build/ in the worktree, names fx020-task-*): - Verify: exit 0 at every task's end. Final counts: Task 5b fix 1647/1647 parallel (fx020-task5b-fix1-verify.log), Task 7 1626 parallel, 57/57 serial, 94 regression proof lines (fx020-task7-verify.log); Task 8, on the committed clean tree, exit 0 (.build/fx020-task8-verify.log): 1626/1626 parallel, 57/57 serial, 94 regression proof lines, width 0 over 80 in 490 files. - Regression rows (scripts/regression-fx020.mjs, probes test/regression-fx020.mjs), each fixed passes and restored defect fails: `fx020-first-declaration` (bare unbound call fell back to the first effect declaring the name), `fx020-function-wins` (`fn log` beside `Log.log` must each reach their own), `fx020-row-dependent` (resolution must not depend on the written row). The Task 8 cleanup made the function-wins probe print the rejection. - Compiler differential per task against its base (`scripts/differential.mjs --corpus all --regenerate`): Task 1 0; Task 2 1,071 (966 fail-as-Call parse trees, 41 enclosing spans, 59 lone `.`, 1 `fail()` E_SYNTAX to E_ARITY; accepted, R8); Task 3 2,761 raw, 46 normalised, all parse-phase and new-syntax sources; Task 4 5 (sources declaring `effect Console` or `effect Fail`); Task 5a, 5b 0; Task 7 11 (exactly the 11 new bare-name rejection programs). Fuzz, isName and matches 0 throughout. - Paired runs (original program against migrated twin, same Go required, scripts/fx020-paired.mjs, since removed): final Task 6 tree 6,930 pairs, 0 unexpected, 1 ledger entry (R15, `Expected now()` to `Expected Clock.now()`); the seven bootstrap/*.go snapshots byte-identical (`git diff 26611c3..HEAD -- bootstrap` empty). Two nested-handler sources overflow the stack on a cold first compile in either tree (G006), so paired runs used `node --stack-size=3000` (R16). - Go-vs-interpreter differential (test/fx-differential.serial.test.mjs, `WAXWING_FX_SEED=$((20261010 + 500*k))`, k = 0..10): 11 seeds x 500 = 5,500 programs, 0 disagreements at Task 5b, again after its fix round (imported and aliased spellings 213-249 and 85-117 per seed) and at Task 7 (.build/fx020-task7-seeds.log, 8/8 tests per seed). - Timing failures under the differential and harvest runs are in BACKLOG T007 (figures only, bounds unchanged); verify itself passed. Rulings summary (ledger has the full text): R1 user `effect Console` is the existing `Duplicate effect Console`; R2 no note for a built-in; R3-R4 bare tests converted in Task 7, one-off tools removed; R5/R18 the multi-candidate hint is pinned and goes to the user (approved 2026-10-14); R6 unknown `X.y` uses existing texts; R7 Fail reference in its own task; R8 differential categories accepted; R9 the G002 margin is measured; R10/R12 a family rides on the Fail node; R11 a duplicated label's import binds the reachable one (FX021); R13 Task 5 split; R14 Task 6 as one chunked dispatch; R15 one message changes; R16 stack-size for paired runs; R17 qualify and wrap commits are verified as a pair. Open: FX021, G002, G006, T007. FX022 (2026-10-14, user-approved wording): the unbound-name hint writes a parameterised effect's parameters in the import form (`Fail(E) { fail }`, `Box(t) { put }`, `Pair(a, b) { … }`); `use` stays bare and effects without parameters are unchanged. The multi-candidate hint wording was approved too. Report: .superpowers/sdd/2026-10-13-effect-namespaces-plan/fx022-report.md. ## R001 Task 10: regression rows, scale, services proxy (2026-10-14) On branch `records` (plan .superpowers/sdd/2026-10-14-records-plan, spec docs/plans/2026-10-14-records-design.md §8). - Five regression rows (scripts/regression-r001.mjs, probes in test/regression-r001.mjs), each "fixed compiler passes; restored defect fails" in an isolated copy: `r001-sorted-layout` (Layouts' key in written order: an open row's spliced tail makes a second struct for one type), `r001-lacks` (RecordTail's lacks check removed), `r001-shared-remainder` (two open tails each given their own fresh remainder), `r001-field-order` (every field used in place in the Go struct literal, so Go evaluates them in sorted order) and `r001-shape-types` (layouts keyed by labels alone, so `{ x: Int }` and `{ x: Text }` share a struct). The E017 row `r001-print-ground` now proves that `go build` itself failed: the probe reads Go's `# command-line-arguments` header and first error, rather than calling every failed `go run` a build failure. - Fail keys: a test where the later-sorted label set (`{ zed }`) is declared, raised and handled first pins `{ alpha }` to MinInt32 + 1. With first-use numbering restored in an isolated copy, the existing "count up … in sorted order" test passed and this one failed. - Scale (test/r001-scale.serial.test.mjs, serial phase): 200 distinct shapes `{ k: Int, fI: Int }` through a chain of 20 generic functions, each updating `k`: 4,001 keys (one per shape and link, plus `main`, asserted exactly), 19,617 Go lines, output checked. Keys and lines grow linearly: 50x20 1,001 keys and 4,917 lines; 100x20 2,001 and 9,817; 200x20 4,001 and 19,617; 100x40 4,001 and 17,817. Text v1 method: compile in-process; `go build` after one warm-up build, the minimum of three. Five serial runs on this host (macOS, Node 26.6.0, Go 1.26.4), load average (1, 5, 15 minutes) before each: 2.74 2.48 3.31; 3.56 2.65 3.36; 3.35 2.62 3.35; 3.25 2.61 3.34; 3.23 2.62 3.34 (.build/r001-t10-scale-five.log). | Measure | Runs | Median | Bound (3x) | |---|---|---|---| | compile ms | 243, 243, 242, 242, 251 | 243 | 729 | | go build ms (min of 3) | 728, 718, 714, 693, 697 | 714 | 2142 | | Go lines | 19617 (all five) | 19617 | 58851 | Each tail's layout is interned too, so the chain emits 400 structs for 200 shapes, half of them (`{ fI: Int }`) declared and never used. - Services proxy, a proxy and not a validation of the unimplemented services feature (same test file, no time bound; keys exact, output checked): environments are records of `(Int) -> Int with Console` service functions, each holding a window of `width` consecutive services of `services`, so neighbours overlap; generic `useI(env: { sI: …, ...r }, n)` calls the service through its label alone, and each environment calls each of its services through that code. Keys are one per (environment label set, service), one per service function, and `main`; environments with one label set share keys. Single in-process compiles: | Services | Environments | Width | Keys | Go lines | Structs | Compile ms | |---|---|---|---|---|---|---| | 20 | 20 | 8 | 181 | 2519 | 160 | 152 | | 20 | 100 | 8 | 181 | 2759 | 160 | 351 | | 40 | 40 | 10 | 441 | 6939 | 400 | 221 | | 40 | 200 | 10 | 441 | 7419 | 400 | 967 | | 80 | 80 | 10 | 881 | 13859 | 800 | 397 | The test runs 20 services, 100 environments, width 8. The first row's compile includes JIT warm-up; repeated environments add only `main`'s lines, but its compile time grows with `main`'s 100 or 200 `let` bindings of 8 or 10 nested calls. ## R001 records (first tranche) done on branch `records` (2026-10-14) Plan docs/plans/2026-10-14-records-plan.md, Tasks 1-11, on branch `records` from main de96a15 (worktree .worktrees/records); spec docs/plans/2026-10-14-records-design.md (approved 2026-10-14), ADR 013 (docs/adr/013-records.md), language docs/language.md ("Records"). Not merged and nothing pushed: the user's merge decision (fast-forward only) is next. Ledger and task reports: .superpowers/sdd/2026-10-14-records-plan/ (progress.md with every ruling, task-*-report.md). Delivered: - Record types `{ l: T, … }` and `{ l: T, ...r }`, sorted and unique labels, and row sorts: a row variable is a record row or an effect row, solved over the declarations in both directions. - Literals, `e.l` and `e { l = v }` as postfix operations; inference with rigid tails, implicit lacks sets and shared remainders; type-preserving update; the approved diagnostics of spec §6. - Comparison and printing in sorted label order; records as `Fail` payloads keyed by label set; one Go struct per shape and one function copy per concrete row, with evaluation order kept by temporaries. - E017 (printable check at the ground type) fixed first. Tasks (commits on `records`): - Task 1: behaviour-preserving splits (356397c): Subst/UnifyFailure, Unify/Compose/UnifyParts, Resolve.Types/TypeRef/TypeArguments, Specialize.Keys/State, Type.Core/Compare. Differential 0 differences. - Task 2: E017 (d36fcc4): Specialize.Printable `checkSites`, Ground. - Task 3: record types and row sorts (0a09142; fixes bd766c4, a93b899, c14d4b1, 61d55d4 after four review rounds): RecordType parser, Type.Record, Resolve.Sorts, RowSettle, SortCheck, SortConflict, Occurrences. - Task 4: record-row unification (a16ce1b; fix b800a18): UnifyRecord, RecordTail, Lacks, Seed, Implied; effect operations seed lacks, and an effect's parameter cannot be a record tail. - Task 5: literals, access, update (fd6f17c): Parse.Lookahead, Postfix, Record; Resolve.Record; Check.Record. - Task 6: comparison and printability (ef5ca3b). - Task 7: specialization keys and Go lowering (0d7d0e0): Specialize.Layouts, Record; Format.Go.Record, RecordHelpers, RecordNames, RecordUse; examples/records.wxw and bootstrap/records.go. - Task 8: unsolved record-sorted arguments are the empty rest (5fbb1ac); records as `Fail` payloads (baf796f): `HeadRecord`, FlatRecord `failHead`, Format.Go.Families. - Task 9: records in the reference interpreter and generator (dfec27a). - Task 10: regression rows, scale, services proxy (7fd1d14; section above). - Task 11: the five Task-10 rows' messages pin their mutant's symptom (9e8cf17), and this documentation. Evidence (logs under .build/ in the worktree): - Verify, `rm -rf output && GOTOOLCHAIN=go1.26.4 npm run verify`, exit 0 at every task's end on its committed tree: Task 2 1651 parallel and 57 serial; Task 4 fix 1717/57; Task 5 1749/57; Task 7 1786/57, 103 proofs; Task 8 1807/57, 103 proofs; Task 9 1819/57; Task 10 1820/59, 108 proofs (14 of them R001 rows). No timing failure in any verify. - Compiler differential against each task's base (`scripts/differential.mjs --corpus all --regenerate`): Task 1 0; Task 2 11 (this task's own programs, E_TOOL at `go build` to E_TYPE; no existing source); Task 3 final 44, all sources the base rejected with `Expected a type` at a `{` in a type (41 new sources, 3 mutations); Task 4 fix 26 (new sources and one mutant); Task 5 64, all parse-phase sources the base rejected (57 new, 2 fx020 sources and 2 mutants whose lowercase `.` is now an access, 3 mutants of new sources); Task 6 0; Task 7 27 (sources the base rejected with E_INTERNAL "Record types are not lowered yet"); Task 8 15 (new sources). Tasks 9-11 changed no compiler source. Fuzz, isName and matches 0 throughout; no valid existing program's Go changed. - The seven bootstrap/*.go snapshots are byte-identical throughout; bootstrap/records.go is new. - Parser depth (scripts/depth-probe.mjs, limit lifted, isolated copies): constructor-argument 259, call-argument 296, parens 396, parens-in-call-in-constructor 326 before and after Tasks 1, 3, 4 and 5 (one 325 reading at a base was noise). G002 unchanged. - Go-vs-interpreter differential, `WAXWING_FX_SEED=$((20261010+500*k))`, k = 0..10: 0 disagreements on every seed (Task 9); seven record census rows met (337 to 368 programs per seed, minimum 250). - Timing failures seen only in the differential's instrumented harvest runs are in BACKLOG T007 (figures only, bounds unchanged). Rulings summary (the ledger has the full text): R1-R4 sequencing of printer, rule-6 tests, interim E_INTERNAL and end-to-end printable tests; the duplicate-field text is the existing template `Duplicate field