Cleanest close pattern in recent project history. Architect: zero
drift -- every commitment + invariant verified positively (clause-5
implements all 4 predicates incl. fence-skip, 8 link tokens match
the closed convert-set exactly, disposition-(b) applied to the 2
homeless pointers, honesty-rule positive-half pin-safe, commitments
4/7 byte-unchanged, composition invariant clause-3 ∧ clause-5 GREEN
simultaneously, out-of-scope set untouched incl. the 5 in-fence
data-model annotations, no commitment-2 violation in any reading
list, architect_sweeps clean). Bench: check.py exit 0 (63/0/0/63),
compile_check exit 0 (24/0/0/24), cross_lang exit 0 (25/0/0/25);
baseline pristine, no --update-baseline, no paired ratify.
The two spec amendments (clause-6 + cross-ref definition;
clause-5 fence-skip + closed convert-set enumeration) were the
discipline working: planner-recon and plan-corpus-fetch surfaced
gaps the brainstorm-sample missed; the spec was corpus-grounded
*before* any byte moved (grounding-check PASS x3); implementation
then ran clean 5/5 with one non-blocking concern (planner
self-review-item-8 arithmetic miss on the //! header line count --
substantive assertion unaffected; recorded as lesson).
No tidy iteration. No fieldtest -- zero authoring-surface change
(no .ail, no language construct, no compiler/checker/codegen path)
is the spec-stated reasoned exclusion, audit-confirmed.
This commit ratifies the milestone close:
- audit journal: docs/journals/2026-05-19-audit-design-ledger-formal-links.md
- journals/INDEX.md: audit pointer appended
- roadmap.md: [~] -> [x] CLOSED 2026-05-19 with full pipeline record
- WhatsNew.md: user-facing done-state entry (verbatim with notify)
Spec: docs/specs/2026-05-19-design-ledger-formal-links.md
Plan: docs/plans/design-ledger-formal-links.1.md
Iter journal: docs/journals/2026-05-19-iter-design-ledger-formal-links.1.md
Pipeline: brainstorm (PASS x3) -> planner (recon + plan +
self-review 8/8) -> implement (DONE 5/5, Boss-verified independently)
-> audit (CLEAN, no tidy).
M5 done 2026-05-19: real backtest over real Pepperstone tick data
through the real external data-server into the shipped M3-frozen
kernel, across a per-thread-ctx thread swarm; symbol-fan (headline
existence proof) + time-shard (first actual proof of chunk-boundary
invisibility); globally leak-free, deterministic. Zero
language/compiler change; one runtime change (7bfa11e atomic
global RC-stats fallback — user-adjudicated bounce-back, RED-first,
+ a build-dep staleness root-caused & fixed). Audit: Invariant 1
PASS, M3 frozen-layout unmoved, gc_rss trio evidenced-RATIFY
(Boehm conservative-scan artefact, Decision-9 transitional), P2
noise causally exonerated baseline-pristine, doc-honesty tidy
clean. Friction-harvest: host-per-tick-FFI ~= ~206 ns/tick at real
EURUSD volume.
- roadmap M5 [~]->[x] with the done-state summary (stays one cycle
for context, then prune).
- roadmap P2 "Flat array/slice primitive" reframed: the
M4-retirement forward note's deferred reconciliation is now
done — the obsolete "1024-cell cons-chain per chunk / M4 ships
it" framing replaced with the real residual (host-per-tick-FFI
vs. batch crossing) anchored on M5's measured ~206 ns/tick; the
M5-dependency is now satisfied (the justification input exists).
- WhatsNew.md done-state entry (verbatim == the notify text):
user-facing, no internals — the embedding arc is complete.
Done-state notification fired (user away per /boss). The next
roadmap item is a new milestone (the P2 flat-array decision or
another P0) — a deliberate user call, not autonomous.
Architect clean (one [medium] advisory Sweep-5 self-match wart filed
as P3, not a fix iteration). Bench causally exonerated: HEAD vs
5bb7211/de66eb7 — all 5 firing bench binaries cmp-byte-identical, ail
sha256 identical at all 3 commits; the check.py firings are the two
tracked-P2 environmental classes (*.bump_s anchor staleness; *.max_us
-n5 tail-jitter, 4th on a zero-runtime-change milestone), NOT this
milestone — NO baseline ratify (Iron Law forbids ratifying noise).
compile_check 0/24, cross_lang 0/25 EXIT 0. No fieldtest (zero
authoring-surface change). docs-honesty-lint CLOSED: roadmap [~]->[x],
WhatsNew appended, INDEX line added.
Post-audit downstream-LLM-author field test of the post-removal
Form-A surface. 4 fresh real-world programs written from DESIGN.md +
form_a.md + public examples only (no compiler source): running
sum-of-squares accumulator (loop/recur → 385), grade cascade
(let-threaded if → 4/2/0), Horner polynomial straight-line build-up
(let-shadow chain → 73), multi-state bracket scanner threading
(rest,depth,ok) by tail recursion → true/false. 0 bugs, 0 friction,
0 spec_gap, 4 working — every task clean and correct on the first
try with only let/if/loop/recur; all parse|render|parse
byte-identical; zero mut/var/assign tokens produced (a doc-faithful
author did not reach for the removed construct).
The closest-to-friction case (multi-state machine restates the full
state tuple per tail-call) is correctly classified working, not a
spec_gap: that explicit-dataflow cost is the local-reasoning pillar
working as designed; mut's implicit cross-iteration persistence is
exactly the failure class the removal eliminates. mut-keyword
rejection is fail-closed with a diagnostic that enumerates the
surviving forms (no tombstone, no-nostalgia, as spec'd).
Removal thesis empirically CONFIRMED — mut was redundant with
let/if/loop/recur in 100% of the fresh tasks. The
remove-mut-var-assign milestone is fully ratified and CLOSED:
spec+plan+iter, audit clean (architect [high] form_a.md fixed in
.tidy, bench causally exonerated), fieldtest clean. Roadmap P0
flipped [~]→[x]; WhatsNew user-facing entry appended.
Architect drift review clean (zero drift/debt, diff-verified: single
Term::Loop write_term hunk, no non-render site / Term::Recur / doc /
lockstep touched). Bench: compile_check 0/24 + cross_lang 0/25 exit
0; check.py's latency-tail firings proven single-sample jitter by an
identical confirmatory re-run (p99.9 +37%→+10% ok, max +114%→+22%
ok); the sole persistent firing is the pre-tracked P2 *.bump_s
environmental staleness, causally impossible to attribute to a
projection-only ailang-prose change. All items carry-on — no fix, no
baseline ratify. Fieldtest not applicable (no authoring-surface
change). Roadmap P0 flipped to closed; WhatsNew user-facing entry
appended (user present → notification suppressed per policy).
Mirrors the done-state notify text verbatim (user-facing changelog,
no internals). The iteration-discipline-revert milestone is fully
closed (brainstorm → planner → implement → audit, clean); next move
surfaced is the effect-handler-infrastructure milestone.
- docs/WhatsNew.md: append a user-facing entry describing the new
local-mutable-state block — what it does, what it does not yet
cover (heap-Str and user ADTs), the two example fixtures, and
the broader streaming-workloads motivation. No internals.
- docs/roadmap.md: the Stateful-islands milestone flips from [ ] to
[~] (in progress). A Progress paragraph records sub-milestone 1
(mut-local) as closed with its commit references, and enumerates
the remaining sub-milestones (effect-handler infrastructure,
refs + !Mut, MutArray, Stateful + pipe) — each to be brainstormed
separately so each one stays small and audit-friendly.
User-facing entry covering the rpe.1 milestone close + the two
upstream bugs fixed in this session + the cli-diag-human P2 todo.
Five separate iters folded into one done-state note (per the
WhatsNew convention of one entry per done-state notification, not
one entry per iter).
Two libraries can now each declare their own class with the same
method name; type-driven dispatch resolves at the call site, with
explicit module-qualified syntax as the author's disambiguation
tool when the type alone isn't decisive.
Language rule: Term::Do.args[*] are walked in Position::Borrow by
the uniqueness + linearity passes, symmetric to Term::Ctor.args[*]
being walked in Position::Consume. The kind itself carries the
ownership default — no per-op field on EffectOpSig. Three
analyser sites flip in lockstep: uniqueness.rs:289, linearity.rs:506,
and the shared doc-comment at linearity.rs:42.
Heap-Str-specific consequences (closing hs.4's leak):
- int_to_str / float_to_str ret_mode: Implicit → Own at four lockstep
sites (builtins.rs:200,210 + synth.rs:172,179). The codegen
trackability gate (drop.rs:464-475, iter 18g.2) now fires on these
callees, so the let-binder receives a scope-close drop.
- drop_symbol_for_binder's App arm gets a Type::Con{name:"Str"} →
"ailang_rc_dec" carve-out, symmetric to field_drop_call's existing
Str arm. Without it, the new Own-trackable App binder would emit
drop_<m>_Str (undefined).
Tests: the two pre-existing RED tests at e2e.rs (commit 592d87b)
flip to GREEN unchanged with predicted numbers (allocs=1,frees=1,
live=0 and allocs=2,frees=2,live=0). Two new positive tests pin
the rule's coverage: primitive-Int arg through io/print_int produces
zero RC traffic; heap-Str through 2× io/print_str in sequence
typechecks (no use-after-consume) and balances allocs=1,frees=1,
live=0.
DESIGN.md §Decision 10 gets the arg-position-policy table for both
AST node kinds (Ctor=Consume, Do=Borrow) plus a linking paragraph
explaining how Do=Borrow cooperates with ret_mode==Own.
heap-str-abi milestone closes here: WhatsNew entry shipped (Strings
produced at runtime now release cleanly), roadmap P1 entry checked
off, Post-22-Prelude depends-on line removed.
Workspace cargo test + cross_lang.py + compile_check.py all green.
check.py noisy latency cluster + bench_list_sum.bump_s ±12% — same
precedent as the previous two audits, not coupled to this milestone.
Claude Code categorically forbids subagents from spawning other
subagents (code.claude.com/docs/en/sub-agents and the Agent SDK
subagents page). The `or.1` architecture (and `pr.1` that ran on
top of it) presumed a named-exception for `ailang-implement-
orchestrator` to dispatch implementer / spec-reviewer / quality-
reviewer / tester per task. That exception never existed at the
platform level; the `Agent` tool was silently dropped from the
orchestrator-agent's tool set at dispatch time.
Architecture revised, doc-only:
- Per-task phases (implementer → spec-compliance check → quality
check) now run as sequential role-switches in the orchestrator-
agent's own context, not as nested subagents.
- The four role-files (implementer / spec-reviewer / quality-
reviewer / tester) become phase reference files the
orchestrator-agent consults at role-switch boundaries.
- Boss-context offload preserved; fresh-per-phase context given
up (the property that drove or.1's nested-dispatch design is
not buildable in Claude Code).
Files touched:
- skills/implement/agents/ailang-implement-orchestrator.md
(frontmatter, Iron Law, Phase 2/3 rewrite, rationalisations,
red flags)
- skills/implement/SKILL.md (frontmatter, Iron Law, sub-status
vocabulary note, cross-references)
- skills/README.md (Conventions: no more named exception; agent
roster: role-files recast as phase references)
- docs/journals/INDEX.md (or.2 entry appended)
- docs/journals/2026-05-11-iter-or.2.md (new — full rationale)
- docs/roadmap.md (P1 tool-wiring item removed; resolved as
categorically-not-fixable)
- docs/WhatsNew.md (user-facing correction entry appended)
No code changes; no bench impact; CLAUDE.md untouched (no stale
references to fix there).
Reversal of the language decision from 6d94fa5. Texts that get
committed to the repo permanently should follow the same English-
only rule as everything else; the Notify push stays 1:1 with the
WhatsNew entry, so both are English now.
The "only file intentionally not in English" carve-out in CLAUDE.md
is removed.
Done-state notifications now produce two synchronised outputs sharing
one text: an entry appended to docs/WhatsNew.md and the same string
sent via notify.sh. The text is written in German for the user-as-
reader who did not watch the session — no technical internals, no
iteration codes, lead with the change-in-the-project.
WhatsNew.md is the only file in the repo intentionally not in English;
the exception is documented in CLAUDE.md (Roles of docs/...) so a
future reader does not "correct" it back. Bounce-back notifications
stay Notify-only.