Files
AILang/docs/journals/2026-05-19-iter-bugfix-swarm-rc-alloc-undercount.md
T
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

4.3 KiB
Raw Blame History

iter bugfix-swarm-rc-alloc-undercount — build.rs missed runtime/ as a rerun-if-changed input

Date: 2026-05-19 Started from: 483117d39b Status: DONE Tasks completed: 1 of 1

Summary

The M5 swarm leak-proof symbol_fan_swarm_leak_free was non-deterministic: Σfrees stable-exact (12000003) every run while Σallocs was short by a jittering amount in ~1/3 of runs. The m5.2-resume-attempt journal framed this as a residual runtime defect distinct from 7bfa11e (the atomic-global-counter fix). The debug cycle root-caused it instead to a build-dependency completeness gap, not a runtime bug: ail-embed/build.rs declared cargo:rerun-if-changed only for the kernel .ail and build.rs itself — NOT the runtime/ C sources that ail build --emit=staticlib compiles into libailang_rt.a. Cargo therefore never re-ran build.rs after 7bfa11e landed, so ail-embed kept linking a stale pre-7bfa11e non-atomic libailang_rt.a whose g_rc_alloc_count++ raced the M5 swarm's concurrent TLS-NULL host allocs (the isolated 8×2M pure-global RED embed_rc_global_stats_race structurally could not model this because it never touches the stale ail-embed archive — it links the workspace runtime fresh). runtime/rc.c at HEAD was already correct; the entire production fix is one line in the build script.

The fix adds a directory-level println!("cargo:rerun-if-changed={}", repo.join("runtime").display()). Confirmed by inspecting crates/ail/src/main.rs::build_staticlib (lines 2519-2534): libailang_rt.a = ar(rc.o, str.o) where the sources are exactly runtime/rc.c + runtime/str.c, both under runtime/. The directory-level mechanism (Cargo recurses mtimes under a tracked directory) is preferred over enumerating individual files precisely because a per-file list would silently re-introduce the same staleness for any future runtime source (e.g. a new runtime/foo.c). Existing rerun-if-changed lines (kernel .ail, build.rs, AIL_BIN) were kept. The build.rs edit triggers its own rerun-if-changed=build.rs, which relinks the archive from the current atomic runtime/rc.c — the RED's self-bootstrapping mechanism.

The cohesive, in-scope consequence: symbol_fan_swarm_leak_free is un-#[ignore]d (the #[ignore] attribute and its reason string removed; the test BODY is byte-for-byte unchanged — it was quarantined, never weakened). The two surviving doc breadcrumbs (module-doc bullet, fn-doc) are rewritten to present-tense-resolved with the accurate build-dependency-staleness rationale and the corrected journal reference. This test is now the integration-level acceptance of both 7bfa11e and the build-dependency fix; the leak Σ balances deterministically (Σallocs == Σfrees == 12000003) across 6 consecutive runs.

Per-task notes

  • iter bugfix-swarm-rc-alloc-undercount.1: added directory-level cargo:rerun-if-changed=<repo>/runtime to ail-embed/build.rs (existing kernel/build.rs/AIL_BIN lines kept); un-#[ignore]d symbol_fan_swarm_leak_free in ail-embed/tests/swarm.rs (body verbatim) and corrected its module-doc + fn-doc breadcrumbs to the resolved build-dep-staleness rationale. RED rt_archive_freshness went 0-lock-insn → GREEN (≥2 lock insns, matches fresh cross-check). Gate-2 determinism: 6/6 runs, both symbol_fan_swarm_leak_free and symbol_fan_swarm_bit_exact GREEN every run, 0 failed / 0 ignored.

Concerns

(none)

Known debt

  • (resolved) ail-embed/tests/swarm.rs carried a pre-existing warning: unused import: data_server::records::DataFormat (present since the m5.2 split at b724cd1; DataFormat is used only by swarm_runner.rs, never the test). The orchestrator correctly did not chase it under the minimal-fix constraint; the Boss removed the dead import inline at commit time (trivial mechanical edit per the CLAUDE.md carve-out — swarm.rs was being committed this iter regardless, and leaving a warning in the now-final, no-longer- quarantined M5 leak-proof file is its own debt). cargo test --manifest-path ail-embed/Cargo.toml is warning-clean for this crate after removal.

Blocked detail

(n/a — DONE)

Files touched

  • ail-embed/build.rs
  • ail-embed/tests/swarm.rs

Stats

bench/orchestrator-stats/2026-05-19-iter-bugfix-swarm-rc-alloc-undercount.json