dbd76e5503
bugfix-swarm-rc-alloc-undercount, GREEN stage. RED is the separate audit-trail commit483117d. 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 fix7bfa11e, 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 both7bfa11eand 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.
98 lines
4.3 KiB
Markdown
98 lines
4.3 KiB
Markdown
# iter bugfix-swarm-rc-alloc-undercount — build.rs missed runtime/ as a rerun-if-changed input
|
||
|
||
**Date:** 2026-05-19
|
||
**Started from:** 483117d39be6a38333cb5fae8c4b5b96e108d1c2
|
||
**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
|