Commit Graph

141 Commits

Author SHA1 Message Date
Brummel cca6e3959d audit + close: design-ledger-formal-links CLEAN milestone close (no drift, bench 0/0/0, no tidy)
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).
2026-05-19 23:37:59 +02:00
Brummel 8ad91e7f24 iter design-ledger-formal-links.1 (DONE 5/5): clause-5 hard gate + 7 prose-ref conversions + 2 disposition-(b) homeless removals + honesty-rule positive-half (whole milestone in one iter)
Positive-half completion of the DESIGN.md -> design/ split: design/
body cross-references are now formal, file-relative Markdown links
into the durable tier (design/ or source), and a new in-tree hard
gate (design_index_pin.rs clause-5,
design_body_links_are_durable_and_resolve) walks every
design/contracts/*.md + design/models/*.md, strips fenced code
(strip_fences toggles on ```/~~~ lines so a ](  inside a fence is not
treated as a link), extracts every ](path), and asserts the target
resolves file-relative to a real file under design/-or-crates/-or-
runtime/; never docs/, never an in-file #anchor.

RED-first via identity-stubbed strip_fences (four embedded synthetic
vectors -- first one FAILS); replacing the stub with the real
toggle-on-fence impl turns the test GREEN. clause-5 composes with
clause-3 into the complete invariant the milestone establishes:
every contract cross-reference is EITHER a resolving durable
file-link OR clause-3-forbidden decision-record prose.

Conversions (recon-and-corpus-verified closed set):
  Task 2 (7 prose refs, 8 link tokens):
    float-semantics.md:69    Prelude classes -> [..](typeclasses.md)
    float-semantics.md:100   bare-path -> [Str ABI](str-abi.md)
    embedding-abi.md:45      "Frozen value layout" -> [..](frozen-value-layout.md)  (drop stale "below")
    memory-model.md:44       Data model -> [..](data-model.md)
    memory-model.md:105-106  Method dispatch -> [..](typeclasses.md)  (drop stale "below"; the target heading lives in typeclasses.md:227, not in this file)
    scope-boundaries.md:48   Str ABI -> [..](str-abi.md)
    scope-boundaries.md:88   mixed split: ailang-core::desugar -> source link + Pipeline -> ../models/pipeline.md (drop stale "above")
  Task 3 (2 disposition-(b) homeless removals):
    pipeline.md:60-61            (see docs/PROSE_ROUNDTRIP.md) pointer removed, CLI prose preserved
    authoring-surface.md:178-181 cross-tier pointer clause removed, ail merge-prose sentence preserved
  Task 4: honesty-rule.md positive-half paragraph inserted between L14 and the existing L15-blank-L16; both docs_honesty_pin.rs-pinned phrases byte-identical at L14/L19 (now shifted to L19 -> L25 by the +6 lines).

Out of scope, preserved (asserted independently): every intra-file
"above/below"; embedding-abi.md:51 "frozen value layout below
specifies" (no quoted title, no (see) form); data-model.md
38/66/79/206/226 (in-fence ```jsonc schema annotations -- the inline
analog of the nominal-mention carve-out). INDEX.md and the
decision-records journal byte-unchanged; clauses 1-4 of
design_index_pin.rs source byte-unchanged (the only `-` lines in
the diff are the two-line //! header rewrite Task 1 Step 5 itself
delivers).

Boss-verified independently (not on agent report alone):
  cargo test --workspace               647 passed / 0 failed
                                       (+1 vs pre-milestone 646:
                                        the new clause-5)
  cargo test --test design_index_pin   5 / 5 passed
  cargo test --test docs_honesty_pin   5 / 5 passed (additive
                                       paragraph is pin-safe)
  grep ](.../docs/.../) under design/  zero
  grep ](#)        under design/  zero
  ](-link count under design/          8 (closed convert-set)
  git diff --quiet design/INDEX.md     ok
  git diff --quiet decision-records    ok
  embedding-abi.md:48 pinned phrase    byte-identical

One Concerns item: Task-5 Step-7's plan-predicted "`-` line count = 1"
was actually 2 because Task 1 Step 5 rewrote the //! header 5 -> 8
lines (removing the original L4 + L5, not just L5). Planner self-
review-item-8 miss on my part -- a verification-arithmetic error in
the plan, NOT an implementation defect. The substantive assertion
(clauses 1-4 source byte-unchanged) is fully satisfied; the
implementer correctly flagged it and proceeded. The plan stands as
written; the assertion's `1` should have been `2`. Lesson noted for
future header-rewrite tasks.

Spec: docs/specs/2026-05-19-design-ledger-formal-links.md
(grounding-check PASS x3 across two corpus-grounded amendments --
clause-6 + cross-ref definition; clause-5 fence-skip + closed
convert-set enumeration).

Next: mandatory milestone-close audit (no fieldtest -- zero
authoring-surface change, reasoned exclusion).
2026-05-19 23:31:30 +02:00
Brummel f683f1aec8 iter design-md-rolesplit.tidy (DONE 7/7): resolve milestone-close audit drift
Gate-first TDD: widened design_index_pin.rs clause-3 to a hand-rolled
FAITHFUL Sweep-1 superset (case-sensitive digit-anchored line anchors
+ Sweep-1's ^[^/]* path-excluded date + the audit-named
decision-record phrases, case-insensitive); no regex dep; the blanket
iter-detector rejected as unworkable. Sentence-level strip of
faithfully-migrated history/decision-record prose out of 5 contract
files (the audit's 3 spot-checked + roundtrip-invariant.md +
data-model.md the exhaustive scan found) into the decision-record
journal, each replaced by its present-tense contract equivalent;
float-semantics.md stale 'see Str ABI below' -> str-abi.md;
architect_sweeps honesty sweeps re-scoped to design/contracts only
(models/ is the narrative tier) + ailang-architect.md lockstep.
Invariant: clause-3 GREEN => Sweep-1 clean in contracts/.

The prior dispatch correctly BLOCKED on a real plan defect (iso_date
lacked Sweep-1's path-exclusion, over-firing on legit
docs/specs/2026-.. citations); per the two+-defects-in-one-iteration
discipline the audit Resolution mechanism+scope were corrected
upstream in lockstep (f2cdd67) before re-dispatch, not patched a
third time.

Boss-verified independently: cargo test --workspace 646/0,
design_index_pin 4/4 (clause-3 RED->GREEN), architect_sweeps.sh exit
0 'All five sweeps clean' (acceptance criterion 9 met), acceptance
grep CLEAN, 3 docs_honesty_pin pinned runs each exactly 1 contiguous
match. Zero spec/quality re-loops. FINAL design-md-rolesplit
iteration — milestone functionally complete, audited, drift-resolved,
hard gate enforces the honesty spirit.
2026-05-19 13:44:37 +02:00
Brummel f2cdd67e69 plan+audit: design-md-rolesplit.tidy re-derived on planning-time evidence (mechanism + scope corrected)
The tidy's gate-first Task 1 RED-verification + Boss independent
verification surfaced two defects in the audit Resolution as first
written — caught exactly where the planner->Boss loop is designed to,
before any contract byte moved. Per the 'two+ defects in one
iteration => fix the upstream artifact, do not patch a third time'
discipline, the audit Resolution is corrected in lockstep with the
plan re-derivation:

- Mechanism (Resolution-4): the 'case-insensitive iter-code regex'
  clause-3 design is REJECTED as unworkable — a blanket
  iter/milestone detector conflates the memory-model rule-names
  'Iter A'/'Iter B' and ordinary words 'pre-existing'/'pre-set'/
  'pre-Boehm' with provenance, over-firing on legit present-tense
  contract prose (4 no-strip files). Replaced by a FAITHFUL Sweep-1
  superset: case-sensitive digit-anchored Sweep-1 line anchors
  (confirmed ZERO across all contracts) + Sweep-1's ^[^/]*
  path-excluded date (so docs/specs/2026-.. citations are not
  flagged — repairs the iso_date over-fire the implement
  orchestrator correctly BLOCKED on) + the audit-named
  decision-record phrases (case-insensitive). No regex dep. The
  load-bearing invariant (clause-3 GREEN => Sweep-1 clean) is
  preserved; it never required the blanket detector.
- Scope (Resolution-1): the architect's [medium] was a 3-file
  spot-check; the exhaustive scan found roundtrip-invariant.md:73
  ('at iter form-a.1') and data-model.md:149,161 ('loop-recur iter
  1:') also carry lowercase provenance. True strip set = 5 files;
  plan Task 5b adds the 2 (spirit-cleanup, not gate-blocking).

Plan self-review 8/8 re-run; clause-3 = hand-rolled faithful Sweep-1
superset, no regex dep, no blanket iter detector.
2026-05-19 13:36:14 +02:00
Brummel 2ba5e16806 audit design-md-rolesplit (milestone close): DRIFT (one tidy iter) + bench causally-exonerated (baseline pristine)
Architect: relocation byte-faithful; one [medium] spirit-finding —
faithfully-migrated decision-record/history prose in
design/contracts/{typeclasses,str-abi,scope-boundaries}.md dodges the
6 literal clause-3 markers but is the relitigation content the
split's spirit sends to journals; [low] float-semantics.md
stale-direction 'see Str ABI below'. Both routed items: tidy not
ratify (the str-abi.md:23 advisory Sweep-1 exit-1 correctly
diagnoses real pre-existing history residue, byte-identical
DESIGN.md@deeffb1 — faithfully migrated, not split-introduced).

Bencher: causally-exonerated, DECISIVE on byte-evidence — emitted IR
AND final -O2 binaries byte-identical 176821c vs dd5b183 for all 6
check.py firings; all ~11 changed files audited
comment/docstring/diagnostic-string-only; tracked-P2 families;
compile_check/cross_lang pristine. NO-ratify, baseline pristine
(M2/M3/M5 disposition).

Resolution: one tidy iter (move history prose to the decision-record
journal; fix stale 'below'; re-scope architect_sweeps honesty sweeps
to design/contracts only — models/ is the narrative tier; widen
design_index_pin.rs clause-3 to subsume Sweep-1's history-anchor
regex over contracts/ so the hard gate enforces the spirit). No
fieldtest (zero authoring-surface change). Milestone closes after
the tidy lands Boss-verified.
2026-05-19 13:14:15 +02:00
Brummel 176821c2e7 iter design-md-rolesplit.1 (DONE 9/9): DESIGN.md -> design/ ledger role-split
The 3020-line docs/DESIGN.md is replaced by the design/ ledger:
design/INDEX.md (sole addressable spine, typed Contracts+Models tables,
polymorphic links — prose file OR authoritative source //!), 14
design/contracts/*.md test-linked invariants + 3 source-link-only
contracts (mangling/env-construction/qualified-xref, no prose file —
code is SoT), 5 design/models/*.md whitepapers, and
docs/journals/2026-05-19-design-decision-records.md (the
relitigation-guard archive — every why/rejected/does-not-do/rollback/
empirical ### moved out at ###-granularity). Clean cut: git rm
docs/DESIGN.md, no stub.

RED-first crates/ailang-core/tests/design_index_pin.rs — the 4-clause
anti-regrowth spine (DESIGN.md-gone / every-INDEX-link-resolves /
every-contract-names-a-resolvable-ratifier /
contracts-carry-no-decision-record-prose) — demonstrably RED before,
GREEN after. Build-atomic by task ordering: design_schema_drift.rs's
include_str! (the only compile-time consumer) retargeted to
design/contracts/data-model.md BEFORE the deletion; its
## Data model/## Pipeline slicer dropped (a simplification the split
enables). 2 NoInstance diagnostics + 2 lockstep E2Es retargeted to
design/contracts/{float-semantics,typeclasses}.md. ~12 agent reading
lists + 5 SKILL bodies + CLAUDE.md + skills/README.md + ~25
code/C/.ail/spec comment xrefs retargeted; OQ7 dangling 'Iter 13b'
cite deleted (no forward target — a pointer would be fiction).
honesty-rule.md rewritten so the rule names the new home
(rationale->journals), resolving the recon-found internal
contradiction; the two docs_honesty_pin.rs:70,72 pinned phrases kept
verbatim+contiguous.

Boss-verified independently: cargo test --workspace 646 passed /
0 failed; design_index_pin 4/4; acceptance grep CLEAN of live
DESIGN.md refs (residuals = only the spec-mandated clause-4
deletion-enforcer). 2 DONE_WITH_CONCERNS routed to the mandatory
milestone-close audit: (a) str-abi.md:23 '(iter str-concat,
2026-05-13)' provenance stamp trips advisory architect_sweeps Sweep-1
— Boss-confirmed byte-identical to DESIGN.md@deeffb1:2062-2065, a
faithfully-migrated PRE-EXISTING anchor (regexes verbatim, only path
retargeted), NOT split-introduced — RATIFY-or-tidy at audit; (b) a
now stale-direction intra-prose 'see Str ABI below' cross-ref in
float-semantics.md — audit-adjudication candidate. Plan defect noted:
Task 9 Step 4's verbatim acceptance grep used a ^./ anchor not
matching the system's grep -rIn output; substance re-verified CLEAN.

Spec grounding-check PASS x2. Journals INDEX + decision-records
pointer appended (Boss-only).
2026-05-19 13:04:22 +02:00
Brummel 70f2a318e0 iter embedding-abi-m5.tidy (DONE 3/3): milestone-close doc-honesty drift — pin-safe, doc/comment-only
Resolves the M5 milestone-close audit DRIFT (audit journal
28ab56a). Single cohesive commit, M2.tidy a80d495 / M3.tidy
63d7d60 precedent (pins are the coverage, no RED, no
audit/fieldtest gate).

- docs/DESIGN.md edit-1 §"Free (host side)": dropped the retired-M4
  forward-reference ("an additive M4 concern, not a contradiction
  of this freeze"; M4 retired 2026-05-18) -> present-tense current
  fact (a boxed-field record is not an M3 embedding type,
  export-gate-rejected; the freeze covers exactly the all-scalar
  single-ctor record).
- docs/DESIGN.md edit-2 §"Embedding ABI": reconciled the now-
  inaccurate "(no shared mutable runtime state - ... data-race-free,
  sanitiser-verified)" blanket with the real post-7bfa11e state:
  the per-allocation hot path (per-ctx counters + per-object
  refcount header) is non-atomic by design and never shared
  (Ctx:!Send, single-thread-per-ctx); the one shared datum is the
  atomic-relaxed global RC-stats fallback counter; "data-race-free,
  sanitiser-verified" retained (still true).
- runtime/rc.c:88 comment-only: stale "two unconditional ++
  operations" -> accurate "one counter bump per alloc/free ...
  relaxed atomic add on the global null-ctx fallback, a plain ++
  on the per-ctx path" (consistent with the adjacent already-
  correct :93-106 atomic block + :45-55 Threading header).

Boss-verified independently: all pins green (design_schema_drift
8/0, docs_honesty_pin 5/0, effect_doc_honesty_pin 4/0,
embed_record_layout_pin 1/0) = mechanical proof no pinned/hashed
byte moved; the adjacent separately-pinned bare-scalar sentence is
byte-identical (shifted 2299->2305 by net-added lines; substring
pin, passes); rc.c strictly comment-only (filter empty);
cargo build --workspace Finished; git scope = only docs/DESIGN.md
+ runtime/rc.c + journal/stats. Clears the M5-audit doc-honesty
debt; no new debt.

FINAL M5 iteration. The M1-M5 Embedding ABI arc is functionally
complete, audited, ratified, and doc-honest. Includes the per-iter
journal, stats, and INDEX line.
2026-05-19 03:07:40 +02:00
Brummel 28ab56af7e audit embedding-abi-m5: milestone close — RATIFY gc_rss trio (evidenced) + DRIFT (one doc-honesty tidy); P2 bench noise causally exonerated, baseline pristine for it
Architect: Invariant 1 PASS (zero data-server in any compiler
crate/runtime; ail-embed its own workspace root); M3 frozen-layout
SSOT unmoved (the lone rc.c change 7bfa11e touched only the global
stats counters); rc.c header-comment honesty accurate. Drift =
[medium] DESIGN.md:2358-2360 stale "additive M4 concern" (PRE-
EXISTING — M4 retired; correctly scoped out of every M5 iter) +
[medium] DESIGN.md §"Embedding ABI" silent-drift (it asserts "no
shared mutable runtime state … data-race-free" but the now-atomic
global RC-stats fallback IS shared mutable state under concurrency;
M5 is AILang's first concurrent consumer) + [low] rc.c:88 "two
unconditional ++" imprecise → one doc-honesty tidy iteration
(embedding-abi-m5.tidy), same honesty axis, not split.

Bencher refuted my pre-audit "gc_rss allocator-orthogonal →
environmental" hypothesis WITH EVIDENCE: the 3x *.gc_rss_kb +32%
are genuine, deterministic, M5-attributable — 7bfa11e's atomic
split a branch in ailang_rc_alloc (reached by GC programs via
str.c int->str at print), spilling %r14/%rbx; a stale interior
list pointer in the new spill slot is conservatively retained by
Boehm, pinning a ~32 MB dead spine (collection #12 freed PRE 32 MB
vs HEAD 32 B); bisects exactly on the commit, IR byte-identical,
ail sha256-identical; RC/bump RSS dead-stable. bump_s + max_us are
pre-existing tracked-P2 noise (bump RC-orthogonal; max_us 1-sample
tail-jitter, PRE often worse, +65->+104% swing between runs) — NOT
M5.

RATIFY the gc_rss trio. Language reason (not effort): Decision 9 —
Boehm is explicitly transitional; AILang's committed model is RC +
uniqueness. The measurable cost of the correct, necessary,
user-approved swarm-safety fix is exclusively a Boehm
conservative-stack-scan false-retention artifact on the
transitional allocator (codegen-layout-fragile; no memory actually
leaked; RC/bump RSS dead-stable). Chasing it with an out-of-scope
codegen change invests in the path being migrated away from; the
committed RC path is unaffected. Selective baseline re-anchor:
bench/baseline.json lines 14/44/64 ONLY -> 137448/137768/137636
(bencher-confirmed steady-state); every other metric byte-pristine
(a wholesale --update-baseline would absorb the P2 noise and break
the established-envelope discipline). Re-run confirms the 3 now ok
at +-0.3%.

bump_s x2 + max_us x2: NO-ratify, causally exonerated, baseline
left pristine — identical disposition to the M2/M3/prelude-decouple
milestone closes.

Friction-harvest recorded (P2 flat-array-decision input):
host-per-tick-FFI ~= ~206 ns/tick at real EURUSD volume.

Ratify discipline: updated baseline JSON + this paired JOURNAL
ratify entry committed together (bench/baseline.json + the audit
journal + INDEX line). M5 closes after the doc-honesty tidy lands
and is Boss-verified.
2026-05-19 02:56:43 +02:00
Brummel 0900f3f413 iter embedding-abi-m5.3 (DONE 3/3): time-shard boundary-invisibility proof + friction harvest
Final functional M5 iteration (spec ae905de, plan 67027ab; on
green m5.1 204c171 + m5.2 b724cd1 whose leak-proof resolved via
dbd76e5). Proves the chunk/window-boundary-invisibility claim the
M4 retirement rests on:

- adapter::fold_window — purely additive windowed sibling of
  fold_symbol (same MidPriceStream+Kernel path; stream_tick_windowed).
  fold_symbol/MidPriceStream/Kernel byte-untouched.
- chrono as a DEV-dep only — the time-shard test derives
  (y,m)->Unix-ms bounds (data-server's own precedent) and passes
  raw ms to the bin; the bin is date-math-free; Invariant 1
  unaffected.
- new single-responsibility [[bin]] timeshard_runner — one thread
  per disjoint window, each owning its Kernel (Ctx:!Send =>
  compile-time per-thread-ctx).
- tests/timeshard.rs — spec §3 strength-ordered: (a) per-shard
  (acc,n) BIT-EXACT vs single-thread host fold of that exact window
  in stream order (THE boundary-invisibility proof); (b) Σ partials
  bit-exact by construction; (c) whole-window within REL_TOL=1e-6
  only (cross-shard f64 reassociation is host arithmetic, never a
  kernel property — bit-exact there would be the bug; tolerance
  derived from the recursive-summation error bound). Plus the
  now-deterministic leak-Σ + a journal-only friction timing capture
  (no bench gate, no timing assertion).

Concrete pin: EURUSD 2017-03/04/05 (recon-verified present,
contiguous, no gaps; data-server has no month-listing API). RED was
a genuine deterministic compile failure (declared-but-absent bin
source; Cargo missing-source error vs the plan's predicted env!
error — same cause, no false-green; benign plan-text imprecision in
Concerns).

Boss-verified independently: timeshard determinism 5/5 (no jitter);
full ail-embed suite 0 failed AND 0 ignored across all binaries
(m5.2 symbol_fan_swarm_leak_free stays un-ignored & green — the
saga's resolution intact); isolated embed_rc_global_stats_race
still green; AILang workspace data-server count 0; compiler-surface
diff empty (zero diff to crates/ailang-*, crates/ail/, runtime/,
examples/*.ail, root Cargo.toml, DESIGN.md).

Friction-harvest deliverable (P2 flat-array-decision input):
host-per-tick-FFI ~= 658 ms / 3,192,562 ticks ~= ~206 ns/tick at
real EURUSD volume.

M5 functional work complete; milestone closes next via the
mandatory audit (which also handles the pre-existing
DESIGN.md:2358-2360 "additive M4 concern" drift, out of m5.3 scope).
Includes the per-iter journal, stats, and the INDEX.md line.
2026-05-19 02:40:16 +02:00
Brummel dbd76e5503 fix(ail-embed): GREEN — build.rs tracks runtime/ as rerun-if-changed; M5 swarm leak-proof armed & deterministic
bugfix-swarm-rc-alloc-undercount, GREEN stage. RED is the separate
audit-trail commit 483117d.

Root cause of the m5.2-resume-attempt residual: ail-embed/build.rs
declared cargo:rerun-if-changed only for the kernel .ail + build.rs
itself — NOT the runtime/ C sources ail build --emit=staticlib
compiles into libailang_rt.a. Cargo never re-ran build.rs after the
atomic-counter fix 7bfa11e, so ail-embed kept linking a stale
pre-7bfa11e non-atomic libailang_rt.a; the swarm's concurrent
TLS-NULL host allocs raced the stale non-atomic g_rc_alloc_count++
(frees-stable/allocs-jitter). NOT a second runtime bug and NOT
test-methodology unsoundness — runtime/rc.c at HEAD is correct; the
isolated crates/ail RED was green only because it rebuilds the
staticlib fresh per run.

Fix (ail-embed/build.rs, +7 lines): directory-level
cargo:rerun-if-changed=<repo>/runtime (Cargo recurses mtimes under
the dir). Preferred over a per-file list — the implementer inspected
crates/ail build_staticlib (libailang_rt.a = ar(rc.o, str.o), both
under runtime/) and chose the directory mechanism so any future
runtime source cannot silently re-introduce the same staleness.
Existing kernel/build.rs/AIL_BIN rerun-if-changed lines kept.

Cohesive consequence (in-scope): symbol_fan_swarm_leak_free
un-#[ignore]d — the test BODY is byte-for-byte unchanged (it was
quarantined, never weakened); the module-doc + fn-doc breadcrumbs
rewritten to the resolved build-dep-staleness rationale. It is now
the integration-level acceptance of both 7bfa11e and this fix. Boss
also removed a pre-existing unused `DataFormat` import in swarm.rs
inline (trivial; the file is committed this iter regardless;
warning-clean after).

Boss-verified independently: RED rt_archive_freshness -> GREEN;
swarm determinism 5/5 (symbol_fan_swarm_leak_free +
symbol_fan_swarm_bit_exact GREEN every run, 0 ignored, jitter gone,
Sallocs==Sfrees==12000003); isolated embed_rc_global_stats_race
still GREEN (untouched, runtime untouched); Invariant 1 data-server
count 0; scope = ail-embed/build.rs + ail-embed/tests/swarm.rs +
journal + stats only.

The M5 swarm leak-proof bounce-back is fully resolved end-to-end.
M5 stays open [~]; m5.3 (time-shard + friction-harvest + close-out)
remains. Includes the per-iter journal, stats, and INDEX.md line.
2026-05-19 02:21:47 +02:00
Brummel 6500ca0493 ail-embed: re-quarantine symbol_fan_swarm_leak_free — atomic-global fix necessary but insufficient (doc-honesty + finding record)
Attempted to un-#[ignore] the M5 swarm leak-proof as the
integration-level acceptance of bugfix-rc-global-stats-race
(7bfa11e). Boss verification falsified the sufficiency premise:
across 4-6 swarm runs the leak Σ is STILL non-deterministic —
Σfrees stable-exact (12000003) every run, Σallocs short by a
jittering ~1600-2260 in ~1/3 of runs (e.g. left:11998383
right:12000003, 4 stat lines).

The atomic-global runtime fix (7bfa11e) is real, committed, and
NECESSARY — the isolated 8x2M pure-global RED
embed_rc_global_stats_race is deterministically green. It is NOT
sufficient for the swarm: a second, distinct alloc-side undercount
remains that the isolated RED did not model (Σfrees never loses =>
not a per-ctx race; not pure global contention => RED green).

The un-#[ignore] was reverted (never committed). The ONLY shipped
diff is the three now-stale #[ignore]-rationale breadcrumbs in
ail-embed/tests/swarm.rs corrected from "un-ignore when the runtime
makes the counters atomic" to the accurate necessary-but-insufficient
state — a future agent seeing 7bfa11e must NOT un-ignore on that
basis (doc-honesty rule). The test body and the #[ignore] attribute
itself are unchanged: still quarantined, NOT weakened.
symbol_fan_swarm_bit_exact stays live and GREEN — the swarm IS
actually correct and leak-free; only the accounting is wrong.

Residual handed to a fresh debug RED-first cycle. Two framings
recorded for it (genuine residual runtime defect vs Σ-over-
heterogeneous-lines test-methodology unsoundness; the latter, if so,
is a post-root-cause design decision). main stays green; M5 open
[~]; m5.3 remains downstream of a sound leak-proof.

Includes the resume-attempt journal + INDEX line.
2026-05-19 02:06:43 +02:00
Brummel 7bfa11e838 fix(rc): GREEN — atomic global g_rc_* stats fallback counters (swarm-safe)
bugfix-rc-global-stats-race, GREEN stage. RED is the separate
audit-trail commit 427b687.

g_rc_alloc_count / g_rc_free_count (runtime/rc.c:90-91) were plain
static uint64_t; the __ail_tls_ctx == NULL fallback at rc.c:161
(alloc) and rc.c:212 (dec-to-zero) did a non-atomic ++. A
multi-threaded host using the global fallback path (no
ailang_ctx_new) raced the read-modify-write and lost increments, so
the AILANG_RC_STATS atexit Σ under-counted non-deterministically.
Not a memory bug — Ctx:!Send keeps every box on one thread; only
the global statistics Σ was wrong (the M5 iter-2 symbol-fan
leak-proof finding, b724cd1; user-approved Option A bounce-back
resolution).

Fix (runtime/rc.c only, 37+/14-): the two globals are now
_Atomic uint64_t; atomic_fetch_add_explicit(.., memory_order_relaxed)
at the two null-ctx fallback ++ sites; atomic_load_explicit(..,
relaxed) snapshot in ailang_rc_stats_atexit (its sole reader).
Relaxed is correct and sufficient — pure statistics, no
happens-before obligation, atexit reader runs after all worker
threads joined. Per-ctx counters and the per-object refcount header
stay non-atomic BY DESIGN (single-thread-per-ctx; boxes never cross
threads) — out of scope, untouched. Frozen value layout / ABI
offsets / host-free rule untouched. The genuinely-still-
single-threaded drop-worklist doc note was correctly left unchanged
(false correction refused); the two stale atomicity doc blocks
corrected for honesty.

Boss-verified independently: RED -> GREEN deterministically 3/3
(jitter gone, allocs==frees==16_000_000); full cargo test -p ail
green (every binary 0 failed — per-ctx tsan harnesses + embed
e2e unaffected; rc.c links into every ail binary, strong regression
gate); scope = runtime/rc.c + journal + stats only; RED files
unchanged. Unblocks resuming the M5 leak-proof.

Includes the per-iter journal, stats, and the INDEX.md line.
2026-05-19 01:57:06 +02:00
Brummel b724cd17a1 iter embedding-abi-m5.2 (PARTIAL 2/3): data-server adapter + symbol-fan swarm; leak-proof surfaced a non-atomic global g_rc_* stats race
M5 iteration 2 (spec ae905de, plan 9cc9d9c). Tasks 1+2 clean and
committable; Task 3 BLOCKED on a real finding → M5 bounce-back.

Shipped:
- data-server promoted [dev-dependencies] -> [dependencies]
  (Invariant-1 sanctioned: ail-embed is the sole meeting point; the
  AILang workspace graph still has data-server count 0; zero
  compiler-surface diff — not even root Cargo.toml this iter).
- additive `adapter` module (ail-embed/src/adapter.rs): tick_to_px,
  MidPriceStream (lazy Iterator<f64> over SymbolChunkIter),
  fold_symbol; RED-first (E0432 -> GREEN). m5.1 core untouched
  except `pub mod adapter;`.
- swarm_runner [[bin]]: one thread per symbol, each owning its
  Kernel. The clean compile IS the compile-time per-thread-ctx
  proof (Ctx: !Send => a shared-ctx swarm is E0277).
- tests/swarm.rs: real-data symbol-fan E2E. `symbol_fan_swarm_bit_exact`
  is GREEN and live — per-symbol kernel (acc,n) bit-exact vs an
  independent same-order host reference (EURUSD/GER40/XAUUSD, ~4s).

The Task 3 finding (Boss independently confirmed by reading
runtime/rc.c): the global Σallocs==Σfrees leak measurement is an
INSTRUMENTATION race, not a memory bug. No box crosses a thread
(Ctx: !Send), the real refcount/free is correct (bit-exact GREEN
every run); only the global g_rc_* stat counters (rc.c:90-91,
161,212) are non-atomic BY rc.c's own documented single-threaded
design, losing ++s when 3 worker threads hit the null-__ail_tls_ctx
host-side path. M5 is AILang's first concurrent consumer; rc.c's
header (rc.c:44-49) explicitly defers exactly this atomic-vs-non-
atomic decision to "when it acquires concurrency primitives".

The leak assertion was Boss-split into `symbol_fan_swarm_leak_free`
(#[ignore], body preserved VERBATIM — quarantined not weakened;
un-ignore = the runtime fix's acceptance criterion) so main stays
green and the finding is pinned as a regression marker. The earlier
plan/journal claim that embed_swarm_tsan.rs covers this path was
wrong and is corrected on the record (that test uses the scalar
kernel — zero box allocs — so it never exercised the host-side
global-counter path).

Escalated as an M5 bounce-back: resolution touches M3-frozen
runtime/ and re-frames M5's "zero runtime change" commitment;
multiple substantive options, not unilaterally Boss's to pick in
frozen-runtime territory. Boss recommendation on the record =
Option A (make only the global-fallback g_rc_* counters atomic, as
a standalone RED-first runtime micro-iteration; M5 framing amended).
Time-shard + friction-harvest remain m5.3.

Includes the per-iter journal (with Boss disposition), stats, and
the INDEX.md line.
2026-05-19 01:37:50 +02:00
Brummel 204c171e60 iter embedding-abi-m5.1 (DONE 3/3): lean ail-embed core + build.rs + hermetic smoke
M5 iteration 1 (spec ae905de, plan 22f02aa). Stands up the
workspace-excluded `ail-embed` crate:

- zero-dependency embedding core (`ail-embed/src/lib.rs`): extern "C"
  to the M3-frozen ABI + frozen-layout State/Tick box helpers + a
  Kernel price fold; the Rust port of the audited
  crates/ail/tests/embed/tick_roundtrip.c. Raw pointers never escape
  the type.
- build.rs (no in-repo precedent): AIL_BIN env override else nested
  `cargo build -p ail` against the parent workspace (separate target
  dir → no cargo-lock deadlock), `ail build --emit=staticlib`, link
  directives.
- hermetic data-server smoke (ail-embed/tests/smoke.rs): synthetic
  Pepperstone-format ZIP fixture via data-server's own public
  RawTickRecord type → real DataServer → Kernel, bit-exact vs a
  same-order host reference fold; runs with no /mnt.
- `ail-embed` is its own cargo workspace root (empty [workspace]
  table); data-server is a dev-dependency only. Root Cargo.toml gains
  only a 4-line non-membership comment.

Invariant 1 Boss-verified independently: full+no-deps cargo metadata
on the AILang workspace shows data-server count 0; git status path
filter empty (zero diff to crates/ailang-*, crates/ail/, runtime/,
examples/*.ail); src/lib.rs zero code-level data_server; AILang
cargo build --workspace still clean. ail-embed suite 2/2 green
(kernel_run_sums_prices unit RED-first + hermetic_smoke integration),
verified by me, not just the agent report.

Two toolchain-forced corrections to the plan's verbatim
ail-embed/Cargo.toml (added empty [workspace] table; sibling dev-dep
path ../libs -> ../../libs, manifest-relative) — confined to the
plan-created manifest, no acceptance gate altered, 0 review re-loops.
Journal Concerns records the planner-recon implication for the next
workspace-excluded-nested-crate plan. Adapter API + thread-swarm
deferred to M5 iter 2+ per spec/plan.

Includes the per-iter journal, stats, and the INDEX.md line.
2026-05-19 01:12:19 +02:00
Brummel 208d7095bc fix(check): GREEN — over-strict-mode recognises ctor-rebuild-from-primitive-fields as a consume
Drives the RED test from a11cb7c to GREEN. Bug-fix iter
bugfix-over-strict-mode-ctor-rebuild-consume (debug -> implement
mini). Check-only lint-precision fix; zero codegen / runtime / ABI /
schema / DESIGN.md change.

The [over-strict-mode] lint's consume-detection
(any_sub_binder_consumed_for / pattern_has_consumed_heap_binder,
crates/ailang-check/src/linearity.rs) only recognised a consume of an
(own (con T)) param when a heap-typed pattern-binder was moved out of
`match p`. When p was destructured into purely primitive fields fed
into a Term::Ctor rebuilding p's own ctor, that genuine
dismantle+rebuild consume was invisible, so the lint spuriously
advised "(borrow ...) would suffice". An LLM author "fixing" that by
flipping an export own->borrow would silently invert the ABI
ownership contract — why a low-severity advisory FP got a real
RED-first fix.

Fix: a second recognition path in any_sub_binder_consumed_for — a
`match p` arm destructuring binders out of p's ctor that references
any of them (primitive or not) inside a Term::Ctor's args in the arm
body genuinely consumes p. Two pure helpers: ctor_uses_any_binder
(finds a fresh-allocation Term::Ctor reachable in the arm body) +
term_mentions_any_binder (deep free-var scan, so binder flow through
an intervening expr like (+ acc px) is recognised, not only a bare
Var arg). Conservative toward NOT suppressing: a ctor ignoring p's
payload still warns (negative-control verified). Over-strict-only —
by-name-shadowing imprecision is extra-silence, never under-strict
(Known debt in the journal + the fn doc). The two stale doc comments
that mis-attributed this FP to a nested `match` corrected for
doc-honesty (debugger concern #2 — same code region, in-scope).

Boss-verified independently: RED test now GREEN; full
cargo test -p ailang-check 108/0 lib + every binary 0-failed with NO
existing test modified; ail check examples/embed_backtest_step_tick.ail
no longer warns over-strict on st/tick (exit 0);
embed_backtest_step_tick_borrow.ail + M3 embed_backtest_step_record.ail
still clean; embed_tick_e2e + bench posture untouched.

+166/-20 in crates/ailang-check/src/linearity.rs only. Journal +
stats + INDEX line in this commit.
2026-05-18 23:50:13 +02:00
Brummel 38150ae923 roadmap: retire Embedding ABI — M4 (never speced) — speculative infra by feature-acceptance clause 2
M4 (sequence crossing via the List ADT) was struck during its own
/boss brainstorm, in the Step-2/3 Q&A, before any spec — the
"problem mis-framed -> don't ratify a known-unneeded shape into the
roadmap" brainstorm path. No spec, no grounding-check, no planner
handoff.

Why: held against DESIGN.md feature-acceptance criterion clause 2,
M4 removes no redundancy. The shipped M3 export gate is_c_abi_type
(crates/ailang-check/src/lib.rs:1934-1953) is a per-parameter loop
accepting a C scalar OR a single-ctor all-scalar record
independently per param; the forwarder's llvm_scalar maps every
non-scalar Type::Con to ptr (M3-frozen). So (State, Tick) -> State
with both as single-ctor all-scalar records is already
gate-accepted and forwarder-supported today. The minimal
data-server binding is M3 (shipped) + a host-side per-tick loop;
cons-list crossing would add a 2N+1-box-per-chunk host builder and
the deferred flat-array perf debt, with no named consumer (M5's
adapter unrolls each chunk host-side; whole-chunk in-kernel
visibility is semantically void — State threads across calls
regardless of chunk boundaries).

Outcome: M4 retired in docs/roadmap.md (struck entry kept one
cycle for context, never [x] — never shipped); M5 reconciled
(depends on M4 -> M3 + the Tick-coverage todo; adapter unrolls
host-side; friction feeds the host-per-tick-FFI vs. batch-crossing
P2 perf decision); residual recorded as a new [todo] Tick-coverage
on M3 — an E2E + fixture pinning the two-record-param per-tick
(State, Tick) -> State shape (test backfill, no brainstorm).

Rationale + the honest mid-Q&A correction (I had wrongly asserted
M5 needs M4) in
docs/journals/2026-05-18-brainstorm-embedding-abi-m4-retired.md;
INDEX.md mirrors it.
2026-05-18 23:22:39 +02:00
Brummel 63d7d60dd1 iter embedding-abi-m3.tidy (DONE 3/3): close M3 audit [medium]+[low] doc-honesty drift, pin-safe
[medium] DESIGN.md §"Embedding ABI": surgically replaced ONLY the
contradicted M1-era parenthetical (asserted the export boundary is
scalar-only — false post-M3, a single-ctor record is an accepted
export type) with the present-tense truth pointing at the frozen-layout
SSOT + the own/borrow mode contract. The parenthetical shared physical
line :2300 with the docs_honesty_pin:135 pinned bare-scalar sentence;
the edit kept every pinned word (planner Step-5 item-6 pin-safety, the
M2.tidy precedent — docs_honesty_pin stayed 5/5 green, RED-restore path
never triggered). [low] codegen forwarder-body comment honesty fix
(comment-only; the IR byte-pins assert generated code not comments —
byte-identical before/after).

Boss-verified: both stale fragments grep-absent; 4 standing pins green
at the recon baseline; workspace 639/77 byte-unchanged; diff exactly
2 files. No behaviour change; the pins are the coverage (M2.tidy
precedent, no audit/fieldtest gate). bench already carry-on/NO-ratify
at the M3 audit (causally exonerated). One non-gating planner-quality
grep defect recorded in the journal Concerns (orchestrator handled it
correctly, no code bent).
2026-05-18 21:50:15 +02:00
Brummel b8a60b1ec7 audit embedding-abi-m3: milestone close — DRIFT (1 [medium]+[low] doc-honesty -> one tidy); bench check.py exit 1 decisively causally exonerated (byte-identical generated IR HEAD vs pre-M3 9a609ae), NO ratify; architect Invariant 1 + M1/M2 byte-invariant + frozen-SSOT consistency all clean 2026-05-18 21:37:26 +02:00
Brummel 4ea8bc5faf iter embedding-abi-m3.1 (DONE 6-7): freeze the value layout — DESIGN.md frozen-layout SSOT + lockstep pointers + enforceable byte-pin
Tasks 6-7 of the Boss-repaired split dispatch (Tasks 1-5 committed d5c565d).
Task 6: DESIGN.md §"Embedding ABI" gains the `### Frozen value layout
(M3 — one-way commitment)` SSOT subsection; both "provisional until M3"
sentences rewritten to one-way-freeze wording (docs_honesty_pin-safe — the
pinned "written **bare**" sentence stayed byte-verbatim, :2297->:2299
content-asserted); // FROZEN ABI lockstep pointers at runtime/rc.c +
match_lower.rs lower_ctor + drop.rs; 3 plan-named stale rustdocs fixed +
the Boss-caught stale // gate-comment block (check/lib.rs:1917-1922,
M1/scalar-only -> M1/M2/M3/C-ABI-permitted-incl-record); byte-pin
enforceability demonstrated (RED on a local offset perturbation, GREEN on
git-checkout restore — the only legitimate git op, working-tree only).
Task 7: milestone-close verification gate.

Boss-verified independently (agent report = intent, not outcome): workspace
639 passed / 0 failed; embed_record_e2e 2/2 (own+borrow, global
leak-freedom model); byte-pin 1/1; gate 10/10; forwarder 3/3;
docs_honesty_pin 5/5 pin-safe; design_schema_drift + embed_export_hash_stable
+ embed_e2e + M2 swarm regression-green-unmodified.

INDEX.md line added (deferred from the PARTIAL — one line per iter, final
title). Milestone-close audit next (architect Invariant 1 + bench trio,
spec Testing items 8/9 — audit-owned, not the implement run's job).
2026-05-18 21:29:50 +02:00
Brummel d5c565d48d iter embedding-abi-m3.1 (PARTIAL 5/7 + Boss spec-defect repair): single-ctor scalar record crosses the C ABI, ownership follows declared mode
Tasks 1-5 GREEN. T1 baseline pins (re-point annotation + @ailang_rc_alloc
heap-box byte-pin: size=8+n*8, tag@0, fields@8/16). T2 export gate widened
(is_c_scalar -> two-level is_c_abi_type: single-ctor all-Int/Float record;
multi-ctor/Str/List/nested still RED; gate suite 10/10; M1 adt-ret must-fail
re-pointed to multi-ctor+Str Reading). T3 codegen forwarder widened
(llvm_scalar record Type::Con -> ptr; M2 forwarder body byte-unchanged;
3/3 staticlib pins). T4/T5 E2E record round-trip own+borrow, global
leak-freedom.

Boss spec-consistency repair (M2.1-precedent class): orchestrator
correctly BLOCKED Task 5 on a genuine spec defect -- the single-ctx-readback
allocs==frees proof model is unsatisfiable for borrow (and only
coincidentally passes for own) because M2's TLS-ctx is bound only during
the synchronous forwarder call, so host-side decs land on g_rc_*, not ctx.
Boss-verified globally leak-free + value-correct both modes. Spec + plan +
harness amended to the stronger global model (sum all ailang_rc_stats:
lines; the M2-TLS cross-attribution documented as correct behaviour). No
fresh grounding-check (removes an over-strong measurement assumption).

Tasks 6 (DESIGN.md frozen-layout SSOT + lockstep pointers + freeze wording
+ enforceability demo) and 7 (workspace-green gate) re-dispatched on the
amended plan. Bench/architect milestone-close is audit-owned.

iter embedding-abi-m3.1 (PARTIAL); INDEX.md line deferred to the DONE commit
2026-05-18 21:16:41 +02:00
Brummel a80d495ab3 iter embedding-abi-m2.tidy: '## Embedding ABI (M1)' -> '## Embedding ABI' lockstep rename (M2 audit doc-honesty fix)
Resolves the M2 milestone-close audit's only actionable drift item
(architect [medium] DESIGN.md:2266 stale (M1) header vs its now-M2
present-tense body + coupled [low] :2354 xref). Current-state-mirror:
the section describes the current embedding ABI (M1+M2), so the
milestone tag is internal history, not current state.

5 live-coupling sites renamed in lockstep, 3 files:
- docs/DESIGN.md:2266 header '## Embedding ABI (M1)' -> '## Embedding ABI'
- docs/DESIGN.md:2354 schema-block xref 'see §"Embedding ABI"'
- docs_honesty_pin.rs:134 test comment + :136 assert-message
- crates/ailang-core/specs/form_a.md:89 live forward-xref (Boss-added
  5th site: plan-recon-undercount countermeasure surfaced a live
  dangling-xref the architect's 3-site scope missed; folded in on
  the merits — a half-rename contradicts the tidy's own thesis)

docs_honesty_pin.rs:135 asserted substring (the rename-immune
DESIGN.md body sentence) byte-verbatim untouched. Committed
append-only history NOT falsified (Boss-verified diff = 3 content
files + journal + stats only). Pins green before AND after
(docs_honesty_pin 5/0, design_schema_drift 8/0). Zero
language/checker/codegen/schema change.
2026-05-18 17:52:10 +02:00
Brummel ad88dec3d8 audit embedding-abi-m2: milestone close — DRIFT (1 [medium]+[low] doc-honesty -> tidy); bench exit 1 causally exonerated, NO ratify
Architect drift_found: the only actionable item is the stale
'## Embedding ABI (M1)' DESIGN.md header (:2266) vs its now-M2 body
+ coupled :2354 xref — a current-state-mirror honesty desync the
iter journal flagged truthfully (Task-7-scope-deferred to preserve
the docs_honesty_pin:135 verbatim sentence). Everything substantive
holds (Invariant 1, internal-convention byte-invariance, Decision-10
note present-tense-correct, lockstep, no unrequested extras).

Bench check.py exit 1 (bump_s + 2x rc-latency max_us). M2 changed
the benched runtime path so byte-identical exoneration did not apply
-> ailang-bencher localised: H0 refuted, all 3 firings are the two
tracked roadmap-P2 noise families (bump_s causally impossible from
M2's diff; rc.c hunk branchless+free; max_us median/p99 flat +
non-reproducible). NO baseline ratified; not M2 artefacts.

Resolution: doc-honesty drift -> tidy iter embedding-abi-m2.tidy;
bench -> carry-on. Roadmap [~]->[x] after the tidy lands clean.
2026-05-18 17:42:48 +02:00
Brummel fbeeadeba5 iter embedding-abi-m2.1 (DONE 5-9): swarm-safe ctx ABI complete + sanitiser-verified
Completes Embedding ABI — M2.1 (Tasks 1-4 committed c9a84b3 as the
known-good subset; this commit lands Tasks 5-9 from the re-dispatch
against the Boss-corrected plan).

- T5: swarm.c per-thread-ctx scalar-swarm capability demo (no
  SHARED_CTX) + rc_accounting_shared_ctx_is_flagged_by_tsan added to
  the item-1 harness driver (de-globalisation negative-control teeth,
  where a shared ctx genuinely races on ctx->alloc_count).
- T6: M1 host.c migrated to the ctx ABI; embed_e2e green (s==25
  through the ctx-threaded forwarder).
- T7: DESIGN.md current-state update (provisional-until-M3 narrowed
  to the value/record layout; Decision-10 per-thread-ctx note);
  docs_honesty-pinned sentence + (con Int) snippet preserved verbatim.
- T8: regression gate — workspace green; null-ctx fallback
  byte-behaviour preserved.
- T9: bench-trio — compile_check/cross_lang clean; check.py
  tracked-P2 noise only, causally exonerated (zero codegen/runtime
  diff vs HEAD), NO baseline ratified.

Boss-verified directly (not on report trust): docs_honesty_pin 5/0,
design_schema_drift 8/0, embed_export_hash_stable 1/0,
embed_export_gate 6/0, embed_e2e 1/0, embed_staticlib_alloc_guard
2/0, print_no_leak_pin 1/0 + e2e rc_stats 4/0; the tsan coherent-stop
proven by hand — per-ctx clean (exit 0, 0 warnings), shared-ctx a
real ThreadSanitizer data race at rc.c:157/:208 (exit 66).

Known debt (journal + roadmap): DESIGN.md '## Embedding ABI (M1)'
header still says (M1) while the body mirrors M2 — out of Task 7's
scope-limited regions by design; post-audit doc-honesty tidy.

Milestone-close audit next.
2026-05-18 17:31:50 +02:00
Brummel c9a84b33b3 iter embedding-abi-m2.1 (PARTIAL 4/9 + Boss spec-defect repair): ctx ABI + de-globalisation
Tasks 1-4 land fully review-green and are the cohesive shippable
subset (the per-thread embedding ABI, fully wired + proven):
- T1: FIXED-FIRST alloc-guard baseline pin (RED captured -> GREEN at T4).
- T2: runtime/rc.c gains ailang_ctx_t {alloc_count,free_count} +
  ailang_ctx_new/_free + __thread __ail_tls_ctx; the two increment
  sites become 'if (_ctx) _ctx->... else g_rc_...'. g_rc_* statics +
  ailang_rc_stats_atexit + the constructor RETAINED VERBATIM as the
  null-ctx (single-threaded executable) fallback. rc_accounting_tsan.c
  + driver: per-ctx 8x200000 tsan-clean (de-globalisation positive proof).
- T3: codegen Target::StaticLib forwarder gains a leading 'ptr %ctx'
  + one '@__ail_tls_ctx = external thread_local global ptr' decl +
  TLS save/store/restore around the BYTE-UNCHANGED internal call;
  _adapter/_clos + internal arg vector untouched (M1 decision held);
  doc-comment provisionality narrowed to the value/record layout.
- T4: build_staticlib rejects --alloc != rc (RC-only swarm artefact).

Boss adjudication of the orchestrator's Task-5 BLOCKED (spec-defect,
correctly surfaced not hacked): swarm.c's -DSHARED_CTX negative
control is structurally impossible — examples/embed_backtest_step.ail
is a non-allocating scalar kernel that never writes a ctx field, and
__ail_tls_ctx is __thread, so a shared-ctx scalar swarm has no
shared-memory write to race on (the spec's OWN item-1 honesty point).
The de-globalisation teeth belong to the item-1 rc_accounting harness
(shared ctx genuinely races on ctx->alloc_count; orchestrator
independently confirmed tsan exit 66). Spec amended in lockstep
(Goal coherent-stop, must-fail-axis item 2, Testing item 3,
Acceptance) so item 3's negative control is item-1's by the
de-globalisation-proof / capability-demo split; plan Task 5
restructured (swarm.c per-ctx capability demo only; negative-control
standing test relocated into the item-1 harness driver) + Task 3's
plan-transcription error (@ail_backtest_step ->
@ail_embed_backtest_step_step) corrected. This is a Boss
consistency-repair of an internally-contradictory clause whose intent
is already correctly realised in the same spec — not a redesign; no
brainstorm bounce. Task-5 working files discarded (corrected plan
reproduces them; a structurally-RED test must not enter main).
INDEX.md + final journal land at iter completion (re-dispatch [5,9]).
2026-05-18 17:16:40 +02:00
Brummel bcfe554686 iter emit-ir-staticlib: ail emit-ir --emit=staticlib (M1 fieldtest spec_gap#2)
Restores the Decision-5 IR-readability affordance for main-free
kernels: ail emit-ir gains --emit=staticlib, symmetric with
ail build, reusing the M1-audited Target::StaticLib path via a new
one-line lower_workspace_staticlib convenience. Zero-export guard
byte-identical to build_staticlib's. DESIGN.md widened (not
narrowed) + a pre-existing M1 synopsis omission corrected. 3 new
E2E tests; no fixture minted, no doc pin (E2E is the coverage).
Plan 03493c9.
2026-05-18 16:08:33 +02:00
Brummel 7d7f04e1a4 iter form-a-scalar-param-mode-carveout: scalar-param mode carve-out (docs-honesty tidy)
Resolves the M1-fieldtest [friction] + [spec_gap]#1 shared root:
form_a.md stated an unconditional 'every (fn ...) param needs an
(own/borrow) mode' rule in 4 places, contradicting shipped checker
behaviour (scalars take and require bare (con Int); a mode on a
scalar trips body-pointing use-after-consume/consume-while-borrowed).
All 4 sites rewritten symmetric to the existing return-type carve-out;
DESIGN.md gains the bare-scalar export-param rule + a corpus-grounded
Form-A snippet; RED-first anti-regrowth pin via FORM_A_SPEC + norm().
Zero language/checker/codegen change. Plan 4c266a6.
2026-05-18 15:51:34 +02:00
Brummel 4bc7eb2e0a roadmap: close Embedding ABI — M1 ([~]->[x]); route 3 fieldtest findings
M1 fully ratified and CLOSED: spec (grounding-check PASS) + plan
(Boss-Repaired for the module==stem fixture defect) + iter (818177d
partial+Repair / e406d07 DONE 7/7) + audit 425c4eb CLEAN + fieldtest
6a4e866 thesis-substantiated (0 bugs; clause-1 + clause-3 empirically
confirmed first-try).

3 non-blocking fieldtest findings routed to P1, ahead of M2:
- [todo] form_a.md scalar-parameter mode carve-out — docs-honesty
  tidy (friction + spec_gap#1, shared root: form_a.md's unconditional
  'every param needs own/borrow' misdirects the scalar export
  headline; scalars require bare (con Int)). Pre-existing form_a.md
  defect M1 surfaced. Settled behaviour -> tidy, no brainstorm.
- [feature] ail emit-ir --emit=staticlib — restore the Decision-5
  kernel-IR-readability affordance (add it; not narrow DESIGN.md).

INDEX line added. Next milestone (Embedding ABI — M2) has no spec ->
/boss new-milestone bounce-back.
2026-05-18 15:28:48 +02:00
Brummel 425c4eb3c5 audit embedding-abi-m1: milestone close — CLEAN, carry-on, no ratify
Architect clean (Invariant 1 holds semantically; DESIGN.md honesty
satisfied; lockstep intact; Design-decision 6 module==stem confirmed
correct, not drift). Sole [low] (rustfmt-divergent export: None,
indentation) orchestrator-adjudicated carry-on on evidence: cargo fmt
--all --check shows 1137 fmt-divergent locations tree-wide predating
M1 — rustfmt is not a project convention, the churn premise is moot.

Bench: compile_check 0/24 + cross_lang 0/25 exit 0; check.py exit 1
(7 firings: *.bump_s trio + explicit/implicit_at_rc p99_9/max_us).
Bencher causal exoneration decisive: 21/21 bench binaries cmp-byte-
identical 064599e..e406d07 (Target::Executable default = zero emitted-
code change for the bench corpus); latency tails reproduce on the
byte-identical oracle itself (-n 5 single-sample jitter); fresh re-run
collapsed 6/7 to ok. Both families map to the two pre-existing
roadmap-P2 tracked noise items. NO baseline ratify (Iron Law forbids
ratifying noise against a zero-default-path-byte iter).

M1 audit CLEAN. fieldtest (surface-touching) is the next pipeline
step before milestone close.
2026-05-18 15:16:33 +02:00
Brummel e406d07d81 iter embedding-abi-m1.1 (DONE 7/7): Embedding-ABI M1 — scalar AILang fn callable from C/Rust
Tasks 4-7 on the Boss-Repaired plan, completing the M1 iteration:

- Task 4: check-side export-signature gate — CheckError variants
  ExportNonScalarSignature / ExportHasEffects (codes
  export-non-scalar-signature / export-has-effects), code() arms,
  check_fn gate (params->ret->effects, first-violation-wins,
  unconditional on f.export.is_some()). The clause-3 discriminator
  in code: effectful/non-scalar exports fail to typecheck. 6/6.
- Task 5: codegen Target::StaticLib — Target enum, threaded param,
  @main/MissingEntryMain gated behind Target::Executable, one
  external @<sym> forwarder per export to @ail_<module>_<fn>
  (fn_scalar_sig/llvm_scalar). In-source missing_entry_main_is_error
  byte-unchanged. Lowering pin 2/2.
- Task 6: CLI ail build --emit=staticlib — clap field, Cmd::Build
  branch, build_staticlib (verbatim build_to prefix + has_export
  guard + two-archive clang -c/ar rcs tail) + run_cmd. CLI pin 2/2.
- Task 7: C-host E2E coherent-stop proof (cc links
  libembed_backtest_step.a + libailang_rt.a, backtest_step(0,3)=9 /
  (9,4)=25, s==25, exit 0) + DESIGN.md §"Embedding ABI (M1)"
  (scalar C ABI, provisional until M3). E2E pin 1/1.

Independent Boss verification: E2E 1/1, gate 6/6, full workspace
0 failures, roundtrip_cli + design_schema_drift + spec_drift green,
Invariant 1 holds (no new dep in core/codegen/runtime). 3 behaviour-
neutral plan pseudo-vs-reality concerns in the journal. Default-exe
codegen/runtime path byte-unchanged (check.py firing = tracked-P2
known-noise, audit-adjudicated). INDEX line added.

Completes the M1 iteration (impl). Milestone-close audit + fieldtest
(surface-touching) are the next pipeline steps.
2026-05-18 14:50:27 +02:00
Brummel 818177d835 iter embedding-abi-m1.1 (PARTIAL 3/7): schema + surface + baseline prerequisites; plan Repair
Tasks 1-3 of docs/plans/embedding-abi-m1.1.md, a verified known-good
subset (cargo build --workspace exit 0; full workspace green; the
roundtrip_cli all-examples gate green):

- Task 1: CLI build-path MissingEntryMain baseline pin
  (examples/embed_noentry_baseline.ail + embed_missing_main_baseline.rs;
  triple-assertion, layered on the green codegen-unit pin lib.rs:3314).
- Task 2: additive FnDef.export: Option<String> (serde default +
  skip_serializing_if, modelled on FnDef.doc); compile-driven thread
  of export: None across ~85 FnDef/AstFnDef literals / 18 files incl.
  all in-source #[cfg(test)] mod tests + drift/hash/spec-drift
  literals + the codegen lib.rs:3320 in-source pin; hash-stability
  golden pin; DESIGN.md fn-JSON "export" line. DONE_WITH_CONCERNS
  (plan symbol content_hash_fn -> def_hash per hash_pin.rs, plan-
  pseudo-vs-reality class, plan corrected).
- Task 3: Form-A (export "<sym>") modifier — parse_export +
  parse_fn thread + write_fn_def emission + form_a.md grammar;
  byte-identical round-trip.

Task 4 BLOCKED (Boss plan-defect: fixtures declared module != file
stem; AILang's loader hard-enforces module==stem at workspace.rs:438,
so ail check panicked on load before the gate). Boss resolution
(Option 2, overriding the orchestrator's Option 1, rationale in the
journal + plan Design-decision 6): keep descriptive embed_* filenames,
rename fixture MODULES to their stems — the C symbol backtest_step
stays via (export ...), demonstrating spec Decision 2's mangling-
decoupling rather than violating it; archive becomes
libembed_backtest_step.a, internal symbol @ail_embed_backtest_step_step,
host.c unchanged. Plan fixed (Design-decision 6 + Task-4 module==stem
+ Task-5/6/7 dependent strings + the no-*. Float-head + content_hash_fn
concerns folded). Headline fixture corrected; blocked-Task-4 WIP
discarded (recreated by the [4,7] re-dispatch from the fixed plan).

PARTIAL commit (not the iter's final commit): the implement Repair
path mandates committing the known-good subset so the [4,7]
re-dispatch starts from a clean tree that includes Tasks 1-3 (Tasks
4-7 structurally depend on the schema field + surface). INDEX line
added when the full iter lands post-re-dispatch.
2026-05-18 14:32:39 +02:00
Brummel 3fb184417d audit docs-honesty-lint: milestone close — CLEAN, carry-on, no ratify
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.
2026-05-18 12:40:57 +02:00
Brummel e50b400d4b journal: INDEX line for iter docs-honesty-lint.1 2026-05-18 12:30:37 +02:00
Brummel 7580d434f0 iter docs-honesty-lint.1: canonical docs present-tense-honest + wrap-robust pin + Sweep 5
Strips Wunschdenken (forward intent stated as fact) and non-citation
post-mortem / doc-archaeology from docs/DESIGN.md (14 corrections incl.
1 Step-14 procedural-catch-all site the spec's illustrative regex would
have missed) + docs/PROSE_ROUNDTRIP.md; genuine forward intent (LLM
tool-use / MCP / LSP) relocated to roadmap P3. Codifies the
tense+modality discriminator as a present-tense DESIGN.md meta-
subsection. Guards two ways: wrap-robust enumerated absent/present pin
(crates/ailang-core/tests/docs_honesty_pin.rs, norm() whitespace-
collapse helper — structurally discharges the recurring grep/contains
line-wrap failure family) + wrap-robust advisory Sweep 5 in
architect_sweeps.sh (contiguous-fragment regex) with full sweep-count
lockstep + new ailang-architect.md "DESIGN.md honesty drift" bullet.
KEEPs preserved (Diverge-reserved, regions-rejected, self-labelled
tiebreaker). No language/checker/codegen/runtime change — sole crates/
change is the additive pin; ail check/run/build byte-unchanged.
Workspace 609/0 (delta +4 pin), sentinel trio green, build clean.
2026-05-18 12:30:03 +02:00
Brummel 5bb721178f fieldtest: remove-mut-var-assign — 4 examples, all working; milestone CLOSED
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.
2026-05-18 11:28:34 +02:00
Brummel 4837871ddf iter remove-mut-var-assign.tidy: form_a.md grammar deletion + audit close
Milestone-close audit for remove-mut-var-assign (48e7774..07f0802).

Architect drift: one [high] — crates/ailang-core/specs/form_a.md
still documented the full mut/var/assign construct (EBNF 286-288,
prose 308-328, dangling `like mut` at 332). The spec named it for
deletion; the iter missed it. Root cause = the recon-undercount
class (4th recurrence) plus a Boss error: a plan-time grep checked
only docs/form_a.md (dir-scoped), got "No such file", and that
unverified non-existence claim propagated into the recon brief —
the real file is crates/ailang-core/specs/form_a.md. A stale doc
never compile-fails so the implement compile-sweep could not catch
it. Fixed inline as a Boss .tidy (CLAUDE.md context-already-loaded
carve-out; full review discipline kept — tree-wide verified zero
construct residue except the roadmap entry naming the milestone
itself; grammar now reads coherently reuse-as -> loop -> recur).

Bench causally exonerated: HEAD vs 48e7774 bench binaries
cmp-byte-identical (the -2520-line removal alters zero bytes of the
firing fixtures' machine code). check.py exit 1's 3 firings are the
tracked P2 bump_s environmental staleness + single-sample -n5
max_us jitter (explicit_at_rc.max_us +108% -> -2.30% ok on
identical-code rerun). PRISTINE met on the merits; NO baseline
ratify (Iron Law + spec foreclosure).

Roadmap: P0 refreshed (audit clean, fieldtest remains); the
ailang-plan-recon P2 escalated in place to a structural
recon-contract defect (2 named gaps + concrete fix); a new distinct
P2 filed for the check.py *.max_us -n5 3-for-3 false-positive.
2026-05-18 11:19:48 +02:00
Brummel 07f080256c iter remove-mut-var-assign.1: atomic removal of mut/var/assign
mut/var/assign removed from AILang entirely and atomically. Deleted:
Term::Mut/Term::Assign/struct MutVar; the three Form-A keywords +
parse_mut/parse_assign + grammar EBNF; the 4 mut CheckError variants;
the mut_scope_stack synth threading (param dropped from synth + every
internal/external/test caller); the two lower_term arms; and every
exhaustive no-_ Term::Mut/Term::Assign match arm across 17 source
files — cut in lockstep with DESIGN.md, fixtures, the drift trio,
carve-out and roadmap so the schema is honest at every commit. No
catch-all wildcard introduced (verified). loop/recur + let/if are
the surviving forms.

The shared codegen alloca machinery survives (loop reuses it):
mut_var_allocas renamed binder_allocas (representation-only, loop
codegen byte-identical) and the shared Term::Lam escape guard
simplified to !loop_stack.is_empty() with the loop half
(LoopBinderCapturedByLambda) byte-equivalent. Feature-acceptance
applied inverted: the removed feature fails clause 2 (redundant)
and clause 3 (IS the iterated-mutable-state bug class).

Behaviour preservation is executable: mut_counter/mut_sum_floats
still print 55 after the faithful let/if rewrite. The removal is
made executable by the new mut_removed_pin.rs (4 must-fail pins).
Independent verification: cargo test --workspace 605/0, zero
residual mut symbols in any crate source, loop/recur non-regression
all green (55 / 500000500000 / infinite-compiles / the
lambda_capturing_loop_binder pin), roundtrip_cli PASS.

One DONE_WITH_CONCERNS: a 4th recurrence of the recon-undercount
class (in-source mod tests + a drift-pin fn + 5 orphaned mut
.ail.json carve-outs + a non-enumerated E0599); all resolved within
implementer remit, no behaviour change. Milestone-close audit then
fieldtest remain.

spec docs/specs/2026-05-18-remove-mut-var-assign.md (grounding PASS)
plan docs/plans/remove-mut-var-assign.1.md
2026-05-18 11:06:17 +02:00
Brummel 48e7774d01 audit: prose-loop-binders milestone CLOSE — clean / carry-on
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).
2026-05-18 01:10:20 +02:00
Brummel c9355d7d58 iter prose-loop-binders.1: Form-B loop binders as parenthesised init-list
The Term::Loop arm of write_term rendered binders as bare
`name = init;` statements inside the `loop { … }` body block, which
reads as C/Rust re-init-every-iteration semantics — a projection
lying about a body the prose surface exists to let the reader trust.
Rewrite to a parenthesised init-list on the keyword line,
`loop(acc = 0, i = 1) { … }`, positionally isomorphic to the
unchanged Term::Recur arm. Projection-only: loop/recur AST, Form-A,
JSON-AST, typecheck, codegen, and the Form-A↔JSON round-trip
invariant untouched. RED-first via two new committed
examples/*.prose.txt byte-equality snapshots + two snapshot_loop_*
tests; full ailang-prose suite 10/0; both ail-prose CLI byte-matches
green. Single-iteration milestone, brainstorm→plan→implement.

Spec: docs/specs/2026-05-18-prose-loop-binders.md
Plan: docs/plans/prose-loop-binders.1.md
2026-05-18 01:04:19 +02:00
Brummel 2ed355c6fa fieldtest: loop-recur — 10 examples, 6 findings (milestone CLOSE, clean on all axes)
Post-audit downstream-LLM-author field test of the shipped
loop/recur surface (DESIGN.md + public examples only). 3 real
iterative programs (Newton isqrt, Collatz, Euclidean gcd) + 5
plausible-mistake negatives + 2 no-termination probes, all run
through the public ail CLI. 0 bugs. 4 working findings on the
milestone's own axes: rejection diagnostics point-exact AND
self-fixing; recur tail-position threads through match/let/outer-if
(spec only showed if); loop composes as a value sub-expression +
byte-stable round-trip; no-termination boundary exact. This
empirically substantiates the "LLM author can now write iterative
programs" claim.

Two orthogonal non-blocking findings, neither in loop/recur scope,
both routed to P2 todos (refused the scope creep into a loop/recur
tidy): niladic (app f) spec_gap independently re-confirms the
existing mut-local-F3 roadmap item (the design-fork decision
deliberately NOT auto-ratified under /boss — parked,
priority-strengthened); module-level (doc) diagnostic-hint friction
(one-line tidy). Boss-verified independently (gcd->27;
recur-outside-loop fires exact).

The standalone loop/recur milestone is fully ratified and CLOSED:
3 iterations + tidy shipped, audit clean (drift resolved, bench
pristine carry-on), fieldtest clean on every axis. Roadmap P0
marked closed.
2026-05-18 00:31:19 +02:00
Brummel 2ee97943bd iter loop-recur.tidy GREEN: reject lambda-captures-loop-binder at check + milestone-close audit resolution
GREEN side of the RED audit-trail commit 39380d3. The loop/recur
milestone-close audit found a [high] correctness defect — a lambda
capturing a loop binder passed `ail check` then panicked
unreachable!() at codegen (crates/ailang-codegen/src/lambda.rs:102)
on type-correct input. Fixed symmetrically to mut.4-tidy: new
CheckError::LoopBinderCapturedByLambda (code
loop-binder-captured-by-lambda, bracket-free F2 Display), the
Term::Lam escape guard gained a parallel loop_stack pass. Minimal
mechanism: loop_stack element Vec<Type> -> Vec<(String,Type)> so
the already-threaded per-loop frame carries binder names; recur
still reads .1 by position (Boss-call-2 positional invariant
preserved verbatim — the name is a second field for the escape
guard only, a consumer iter-2 did not anticipate). Codegen
byte-unchanged (typecheck-only fix). carve_out 17->18 + ct1-F2 +
DESIGN.md note lockstep.

Folded in (Boss-side, audit resolution): the two [medium]
doc-honesty edits the audit surfaced (mut_var_allocas rustdoc now
states its mut-var+loop-binder dual use; Term::Loop doc-comment
now describes the real shipped state, not iter-1's stale
"per-binder phi" forward-look) + a [low] P2 roadmap todo
(plan-recon undercount countermeasure, pairs with planner Step-5
items 7+8). Bench gate: all 3 scripts exit 0, 25 metrics 0
regressed — pristine, carry-on (no baseline/ratify).

cargo test --workspace 619 -> 622 / 0 red (Boss-reran
independently, hash_pin 11/0). The loop/recur milestone is
audit-clean; fieldtest is the only remaining step before close.
2026-05-18 00:21:06 +02:00
Brummel edd2558d35 iter loop-recur.3: codegen — real LLVM-IR lowering + run-to-value E2E (milestone terminal)
Third and terminal iteration of the standalone loop/recur
milestone (plan eae73bf). Replaces the iter-1 lower_term
CodegenError::Internal stub for Term::Loop/Term::Recur with real
LLVM-IR lowering: loop binders as entry-block allocas (mut.3
pending_entry_allocas, reusing mut_var_allocas so the existing
Term::Var load path is byte-unchanged), a fresh loop-header block,
recur stores + back-edge br, a loop_frames stack saved/restored at
the lambda boundary. clang -O2 mem2reg promotes the allocas to
phi. Four Boss design calls implemented verbatim and journalled
(alloca-not-hand-phi; mut_var_allocas reuse; emergent loop-exit
via the if/match join; single block_terminated field + parallel
SET site). Diff confirmed surgical: codegen/lib.rs 3 hunks (field
+ init + stub->2-arms), lambda.rs 2 hunks (save+restore); zero
edits to any existing block_terminated SET/READ site, tail-app
lowering, or verify_tail_positions (Boss call 4, the spec-pinned
invariant). Three new .ail fixtures: sum_to->55,
deep-n 1e6->500000500000 (clause-2 correctness made executable),
infinite-loop build-only. Codegen-only: no schema/typecheck
change; hash pins + drift trio stay green untouched.

One DONE_WITH_CONCERNS (T3): the plan's `cargo test ... tail`
filter resolved to no tests; ran via real names + the full 619/0
which subsumes it (feedback_plan_pseudo_vs_reality class, no
behaviour change). Boss systemic fix folded in: planner SKILL.md
Step-5 gains item 8 (verification-command filter strings must
resolve) — the second planner-meta-gap this milestone surfaced.

cargo test --workspace 616 -> 619 / 0 red (Boss-reran
independently); the 3 loop/recur e2e explicitly green. All three
components shipped: the loop/recur milestone is structurally
complete. Milestone-close audit + fieldtest is the next step.
2026-05-17 23:57:46 +02:00
Brummel 1566ce0b29 iter loop-recur.2: typecheck semantics — binder typing, recur checks, verify_loop_body
Second of three iterations of the standalone loop/recur milestone
(plan 5ac57fe). Replaces the iter-1 synth CheckError::Internal stub
for Term::Loop/Term::Recur with real binder typing + positional
recur arity/type checking via a new loop_stack: &mut Vec<Vec<Type>>
frame threaded as mut.2's mut_scope_stack, a new private
verify_loop_body tail-position pass (sibling of the byte-frozen
verify_tail_positions — 0 deletions there), and the four Recur*
diagnostics firing point-exactly on four negative fixtures. The
iter-1 loop_sum_to.ail fixture now also typechecks clean; an
infinite loop typechecks (no termination claim). NO codegen (the
iter-1 lower_term stub stays — iter 3); NO Diverge/guardedness
(spec boundary).

Three Boss design calls implemented verbatim and journalled:
RecurTypeMismatch is an Assign-style structural pre-check (not a
unify-propagate); loop_stack is positional Vec<Type> (binder names
via ordinary locals); diagnostic-code precedence is by pass
ordering (no explicit logic).

Two DONE_WITH_CONCERNS, both journalled: a plan-ordering defect
(Task 2's compile gate forced the check_fn threading the plan
deferred to Task 4 — resolved byte-identically, only resequenced)
and the recurring mut.2-class recon-undercount of cross-module
synth callers (resolved via the plan's compile-sweep oracle).

Boss systemic fix folded in: planner SKILL.md Step-5 gains item 7
(compile-gate vs. deferred-caller ordering) so the plan-ordering
defect class is scrubbed at plan time. cargo test --workspace
608 -> 616 / 0 red (Boss-reran independently).
2026-05-17 23:33:43 +02:00
Brummel a179ec30a0 iter loop-recur.1: additive Term::Loop / Term::Recur / LoopBinder foundation
First of three iterations of the standalone loop/recur milestone
(spec 97c1ed1). loop/recur become real parseable / printable /
round-trippable / hash-stable strictly-additive AST nodes across
every no-wildcard exhaustive Term match in all six crates, plus
parse/print, prose arms, DESIGN.md + form_a.md schema blocks,
drift/coverage/hash anchors, and the spec's worked sum_to program
as a green round-trip fixture. NO typecheck semantics and NO real
codegen this iter by design: synth and lower_term are stubbed
CheckError::Internal / CodegenError::Internal exactly as mut.1
(real typecheck = iter 2, real loop-header/phi/back-edge = iter 3).

Two binding Boss design calls recorded in the plan header and the
journal: (1) verify_tail_positions "byte-unchanged" = its tail-app
verification role is unchanged, not its source — it is an
exhaustive no-wildcard match so two descent-only arms are
mandatory; acceptance evidence is the tail-app non-regression test.
(2) codegen is in iter-1 scope as stubs/pass-throughs because the
workspace must compile for cargo test --workspace.

Three plan-pseudo-vs-reality substitutions (serde Type::Con
literal, bare Int -> (con Int), unqualified LoopBinder) and one
recon-undercount integration-test site, all intent-preserving and
journalled. Boss forward-fix folded in: the committed specs
themselves wrote bare Int in the loop-binder snippets (parses as
Type::Var) — corrected the three headline snippets to (con Int) for
doc-honesty (no design/schema change).

cargo test --workspace 600 -> 608 / 0 red (Boss-reran
independently); iter13a + new loop_recur hash pins green.
2026-05-17 23:00:15 +02:00
Brummel a29700cc9e iter effect-doc-honesty: make the effect-system documentation true
Standalone documentation-honesty tidy (no language/checker/codegen
change; `ail check`/`run` byte-unchanged by construction). Corrects
three false effect-system claims the effect-subsystem recon surfaced,
plus two satellite mentions, guarded by a new doc-presence pin:

- DESIGN.md Decision 3: removed the "row-polymorphic (`![IO | r]`)"
  claim (no EffectRow / row variable exists in any crate — effect
  sets are a flat, unordered, closed set unified by set-equality);
  reconciled "`IO` and `Diverge` are wired up" to IO-only +
  `Diverge` reserved/unimplemented (zero code in any crate),
  modelled on Decision 4's reserved-refinements precedent.
- DESIGN.md "What is not (yet) supported": "IO and Diverge ops"
  bullet -> IO-only + Diverge-reserved.
- ast.rs Term::Do doc-comment: "resolved against the effect-handler
  table at link time" -> the real mechanism (typecheck lookup in
  Env::effect_ops + literal lower_effect_op codegen match; no
  handler table, no link-time resolution).
- form_a.md:226 + rule 3, and main.rs merge-prose CONTRACT example:
  Diverge mentions reconciled in lockstep.
- new crates/ailang-core/tests/effect_doc_honesty_pin.rs: 4 tests,
  fiction-absent + corrected-anchor-present, single-line wrap-robust
  substrings.

cargo test --workspace 600 -> 604 (4 new pin tests, 0 regressions);
design_schema_drift / spec_drift / schema_coverage stay green,
empirically confirming none scans the effect-prose region.
2026-05-16 13:25:49 +02:00
Brummel 78426643df audit: iteration-discipline-revert milestone close — clean
Architect: revert byte-pristine vs 1ff7e81 (18 src + 5 test files
byte-identical; zero residual it.1/it.2 production surface; DESIGN.md
+ roadmap + spec hygiene correct). One [medium] drift — a dangling
loop/recur cross-reference into the reverted milestone inside the
LIVE Stateful-islands roadmap scope bullet — fixed inline: reworded
to keep the real, still-true scope guard (no while/for; this
milestone introduces none; repetition stays recursion as the
language has it; a mut block is a sealed expression, never a loop)
and drop the reverted-milestone reference.

Bench: compile_check.py / cross_lang.py exit 0; check.py exit 1 on a
single metric (bench_list_sum.bump_s +12.71%). Bencher localisation:
the HEAD and 1ff7e81 bump binaries are cmp-identical, an interleaved
3x60-run measurement shows head-oracle delta ~0 (±1.5% stdev) with
both ~+11% over the 2026-05-09 baseline — environmental/hardware
drift, NOT a revert regression (third independent proof codegen ==
1ff7e81, alongside the architect byte-diff and the Task-11
behavioural-equivalence sweep). Resolution: carry-on; baseline NOT
ratified (Iron Law — nothing intentionally moved the metric;
byte-identical codegen must not move the baseline; the spec's
PRISTINE mandate is satisfied: pristine = no regression introduced,
proven). The pre-existing *.bump_s baseline-vs-hardware staleness is
filed forward as a separate P2 [todo] (bench-harness recalibration,
no language change), not mis-attributed to the revert.

Fieldtest skipped (Boss judgement; non-mandatory): a revert restores
the already-field-tested pre-9973546 surface; the Task-11
164-fixture byte-equivalence is the stronger correctness proof.

Milestone iteration-discipline-revert closed clean.
2026-05-16 01:42:58 +02:00
Brummel 37ac704bf3 iter revert: back out the Iteration-discipline milestone (it.1 + it.2)
One forward iteration; main never rewound. 1ff7e81 (the pre-9973546
commit) is the per-region byte oracle — every reverted source/test
file is byte-identical to it; crates/ailang-check/src/lib.rs fully so.

Root cause being corrected: the Iteration-discipline milestone was an
over-escalation of fieldtest finding F1 (a [friction] item whose own
minimal recommendation was a DESIGN.md note). Its totality dichotomy
made the maximally-LLM-natural build(d:Int)=Node(1,build(d-1),
build(d-1)) inexpressible (it.3 BLOCKED); the only in-thesis escape
(A1/it.2b) conceded the language's first documented-unenforced
totality precondition — a purity-pillar dilution the user rejected in
favour of a full revert + rebuild.

Removed: Term::Loop/Term::Recur/LoopBinder; the verify_structural_
recursion guardedness pass + term_contains_loop + Diverge-injection +
the transitively-it.2 module_fns plumbing; the five Recur*/
NonStructuralRecursion CheckError variants (+ code() + the 3 dedicated
ctx() arms); the it.1 codegen loop-header/phi/back-edge + parallel
block_terminated setter; all Loop/Recur walker arms; 16 it.1/it.2
fixtures; 2 pin files; bench/it3-oracle/. Restored: 2 RC fixtures to
1ff7e81 content.

Surgically kept (not in 1ff7e81, landed with the milestone but
independently sound): feature-acceptance clause 3 in DESIGN.md and
skills/brainstorm/SKILL.md, with its worked example de-claimed from
"shipped" to hypothetical-illustration form; the F3 P2 todo.
bench/orchestrator-stats/2026-05-15-iter-it.{1,2,3}.json kept as
historical record (like journals/plans).

Sole net addition: an honest F1/F4 documented-idiom note in DESIGN.md
(the tail-recursive accumulator fallback; examples/mut_counter.ail),
guarded by a doc-presence test — "a documentation note is not a
reshape", asserts nothing at the typecheck level.

Roadmap: the Iteration-discipline block + blocking-fork section
removed; the genuine total-Int-recursion ambition preserved as a
deferred P2 milestone sequenced behind a future Nat/refinement-types
milestone (not abandoned — correctly sequenced after the type
machinery it needs). 2026-05-15-iteration-discipline.md carries a
superseded header; it.1/it.2/it.3 journals + plans stay as history.

Correctness gate PRISTINE: 164 surviving 1ff7e81-era fixtures
ail check/ail run byte-identical to pre-milestone behaviour (verified
against a 1ff7e81 worktree reference compiler, zero drift);
cargo test --workspace 600/0; zero residual it.1/it.2 production
surface.

Spec docs/specs/2026-05-16-iteration-discipline-revert.md (b3853bf),
plan docs/plans/2026-05-16-iter-revert.md (abf0013).
2026-05-16 01:28:47 +02:00
Brummel 305ffd1367 iter it.3 BLOCKED: surfaced fundamental milestone-design fork (bounce-back)
it.3 Task 1 (non-destructive oracle + spec-delegated class-(b)
sweep) ran complete; zero production code changed. The mandated
sweep surfaced that 6 corpus fixtures contain
build(d:Int)=if d==0 then Leaf else Node(1,build(d-1),build(d-1)) —
a terminating, maximally-LLM-natural, non-structural non-tail
BRANCHING recursion the milestone's totality dichotomy makes
inexpressible (not ADT-structural; not recur-able — branching is
not a single tail back-edge). The milestone as-specified would
fail its own feature-acceptance criterion. Orchestrator correctly
bounced rather than patch a 4th time (spec_over_plan_patches).
Records the blocked attempt + the reusable bench/it3-oracle/
(40-fixture behavioural oracle, valid for the post-decision
re-dispatch). main forward-only; nothing reverted. Resolution
(it.2b + a user purity-pillar decision) tracked in the roadmap.
2026-05-15 16:06:42 +02:00
Brummel a4be1e58a3 iter it.2: structural-guardedness checker + first real Diverge effect
Iteration-discipline milestone, 2 of 3. Strictly additive (nothing
tail-related removed; that is it.3). New whole-body pass
verify_structural_recursion sibling of verify_tail_positions
(DD-1): smaller-set algorithm with implicit candidate inference +
unconstrained accumulators (DD-2, foldl=structural), self/mutual
via inline ADT-family union-find (DD-3), it.2-only tail==false
grandfather. CheckError::NonStructuralRecursion. term_contains_loop
(stops at Term::Lam, DD-4) injects Diverge so existing
UndeclaredEffect enforces it, no new variant; lam-arrow + LetRec
sub-effect sites wired. DESIGN.md Decision 3 synced. Four it.1
loop fixtures gained !Diverge.

Two spec-premise boundary defects surfaced + resolved within the
additive invariant (corpus clean, check not weakened), recorded as
corrected it.3 corpus-migration scope: (1) the "21 tail-app
fixtures" grandfather premise under-counts the corpus —
no-ADT-candidate counter recursions have no structural position to
verify, deferred to it.3; (2) two RC-regression fixtures joined the
spec's transitional tail-app grandfather as the other 20 do (RC==GC
guards verified still green). cargo test --workspace 622/0; 9
acceptance pins non-vacuous. Spec fda9b78, plan bc9f512.
2026-05-15 15:29:43 +02:00
Brummel 96db54d15d iter it.1: loop/recur additive — Term::Loop/Term::Recur/LoopBinder end-to-end
Iteration-discipline milestone, 1 of 3. Adds named loop + recur as
strictly-additive first-class AST nodes: parse/print/prose/serde/
round-trip/schema lockstep, typecheck (binder typing + recur
arity/type unification via loop_stack threaded as mut.2's
mut_scope_stack; recur-tail-position via verify_loop_body), codegen
(loop-header + one phi per binder; recur back-edge br with a NEW
parallel block_terminated setter; lambda-boundary loop_frames
save/restore). Four Recur* CheckError variants. Strictly additive:
zero deletions touch tail-app/tail-do or the seven existing
block_terminated sites — this is what makes the destructive it.3
safe. recur synth = fresh metavar (resolves the plan's flagged
Type::unit() risk). loop_counter->55, loop_in_lambda->49, four
negatives fire, tail-app byte-identical, cargo test --workspace
green. Spec fda9b78, plan 7381a42.
2026-05-15 14:38:55 +02:00
Brummel 1ff7e811af fix: mut-local diagnostics doubled the [code] prefix in human stderr (fieldtest F2)
The four mut-local CheckError variants (MutAssignOutOfScope,
AssignTypeMismatch, UnsupportedMutVarType, MutVarCapturedByLambda)
embedded the bracketed kebab code in their thiserror Display body,
while the non-JSON CLI formatter independently prepends [code] from
CheckError::code() — doubling it. Non-mut variants never embedded
the bracket; this brings the four in line with that convention.

RED-first via the debug skill: ct1_check_cli.rs pins the observable
property (code appears exactly once in the rendered human
diagnostic). GREEN was a trivial four-string mechanical edit.

Tests 598 -> 599.
2026-05-15 10:13:50 +02:00