Commit Graph
6 Commits
Author SHA1 Message Date
Robert Allan JamesandClaude Sonnet 5 c8ba8832c4 Fix N-RUNS/START-REP hardcoded constants; N-REPS increase blocked on reservoir cost, not a bug (FABRIC-3.md §XXIII)
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
Two real bugs found and fixed while attempting to raise N-REPS from
3 (both harmless only by coincidence at N-REPS=3, since 3 happened
to equal the hardcoded/literal values):

- N-RUNS was `27 CONSTANT`, not derived -- now `N-ID N-REPS *
  CONSTANT N-RUNS`.
- START-REP's run_id decode used a literal `3 *` where it meant
  `N-REPS *` (confirmed against EXEC-STD79-DOE, the serialized
  baseline, which correctly uses N-REPS for the same decode).

Re-verified at N-REPS=3 (amd64): byte-identical to the already-
verified baseline -- 193s, 0 faults, 99/99 tokens every identity,
K conserved on all 656 rows.

Raising N-REPS to 6 was then tested and found to cause real, silent
data loss at full 8-identity scale (rajames 0/198, 00 66/198, 01/02
99/198, 03-06 fully complete) -- same failure class as §XXI defect 2,
just past the budget again since doubling N-REPS roughly doubles
total MSG-SEND volume (24->48).

Measured the reservoir's replenishment directly rather than assume
from source: 40 sends drained it from 21735 to 1; 300s of pure idle
time (zero further sends) brought it back to 2049 -- real, but only
~6.8 units/s, meaning a full refill would take on the order of 53
minutes against a campaign's few-hundred-second runtime. Raising
N-REPS further needs a cheaper per-send cost or an explicit top-up,
not reliance on ambient decay.

Reverted N-REPS to 3 (fixes kept, they're correctness fixes
independent of the value) rather than commit a silently-lossy result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
2026-09-12 20:03:21 -04:00
Robert Allan JamesandClaude Sonnet 5 19916717b2 Turn-attractor rebuilt on real messaging: two live defects found and fixed before the full campaign (FABRIC-3.md §XXI)
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
Rewrote EXEC-STD79-DOE-CD's dispatch to coordinate via MSG-SEND/
MSG-TICK instead of blocking VM-EXEC, now that Hera can genuinely
message (§XX). RUN-TEST/EXEC-STD79-DOE (the serialized baseline) are
untouched, kept as a byte-for-byte-reproducible historical comparison
point.

A small 2-identity smoke test before any multi-architecture
commitment caught two real defects the design alone didn't predict:

1. Absolute VM-HEAT can't produce fine-grained interleaving -- a
   fresh identity starts at heat=0 against Hera's ~62000+, a gap no
   1..24 divisor closes, so priority locked onto whichever identity
   had executed least, for its entire campaign. Fixed with BASE-HEAT:
   each identity's heat is snapshotted once at campaign start, and
   priority is computed from heat gained *this campaign*, not
   lifetime heat.

2. Single-test-per-message granularity silently drops most of a
   campaign's data: MSG-SEND no-ops on MSG-ALLOC failure, and the
   turn bookkeeping advanced regardless, so rows looked complete
   while missing most of their tests. A live reservoir probe showed
   Hera's own STADIUM-RES@ draining ~725/cycle with no
   replenishment observed -- a 648-send full campaign would exhaust
   it almost immediately. Fixed by dispatching a whole rep (24 tests,
   one concatenated command, measured 442 bytes, well under
   VM-EXEC's 1025-byte cap) per message instead -- 27 sends for a
   full campaign, not 648.

Re-verified after both fixes: 99/99 expected test outputs present,
zero drops, zero faults, genuine rep-level interleaving instead of
either the serialized baseline's fixed order or the first cut's
72-test lock-in.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
2026-09-12 16:53:01 -04:00
Robert Allan JamesandClaude Sonnet 5 66ba21adb4 Log fleet_k_q48/fleet_conserved; K holds exactly, 775/775 ticks (FABRIC-3.md §XVIII)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
doe_log.c's per-heartbeat-tick CSV gains two columns: fleet_k_q48
(vm_physics_fleet_heat_sum() over ALL live VMs -- the genuine fleet-wide
conservation invariant K, not reconstructable from the 3 named-Tripod-
member heat columns already logged, which omit every identity VM's own
heat) and fleet_conserved (vm_physics_conserved() as 0/1). Requested
explicitly after the first heartbeat-telemetry analysis pass
(analysis-20260912/) omitted K entirely.

Kernel rebuilt on all three architectures, full 3x9x3 campaign rerun
(results-20260912-with-k/). K = 1.0000000000 (Q48.16 raw 65536) on every
one of 775 heartbeat-tick observations, sd(K) = 0, 100% fleet_conserved,
across amd64/aarch64/riscv64, nine identities, three replicates -- zero
deviation. Also a free regression check on both recent Stadium fixes
(§XVI/§XVII): neither disturbed the reservoir-transfer accounting K
depends on.

Found and fixed a tooling wrinkle along the way: fleet_conserved, being
the CSV row's very last field with nothing after it to bound a regex
match, can have a resumed trial digit merge into it with zero separator
on the wire -- combine.py now derives it from fleet_k_q48 directly (same
epsilon vm_physics_conserved() uses) instead of trusting the raw field.
fleet_k_q48 itself is unaffected either way.

Full analysis, discussion, and light/dark SVG->PDF figures written up as
a proper LaTeX report (report-20260912/report/std79_doe_report.pdf),
following experiments/bare_metal/analysis/report/bare_metal_doe_report.tex's
established style -- supersedes analysis-20260912/'s markdown-only first
pass as the primary deliverable for this dataset (kept, not discarded).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
2026-09-12 13:25:09 -04:00
Robert Allan JamesandClaude Sonnet 5 403a7639e1 Bracket std79 DoE trial loop with HB-ON/HB-OFF, capture real heartbeat CSVs
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
Every prior std79-doe.fth run's automatically-extracted CSV
(scripts/extract_doe.sh) was silently empty -- g_doe_log_enabled
(doe_log.c) defaults off, and nothing in the campaign ever called HB-ON.
EXEC-STD79-DOE now calls HB-ON right before its trial loop and HB-OFF
right after, so the per-heartbeat-tick physics/timing CSV (18 columns:
tick_number, hot_word_count, avg_word_heat_q48, apic_ticks, per-VM
heat_q48, etc.) finally covers the run's own window on all three
architectures.

Found and fixed two bugs along the way, one in a comment and one in the
ad hoc QEMU orchestration script used to drive these runs (not part of
this repo):

- std79-doe.fth's own explanatory comment accidentally spelled out the
  literal "[HADES][DOE ]" tag string doe_log.c prefixes each row with --
  the FORTH REPL's compile-time echo of that comment then matched
  scripts/extract_doe.sh's own extraction grep, corrupting the first
  extracted CSV row with comment text instead of real telemetry. Fixed by
  never spelling out the literal substring.

- The harness script's completion-detection watched for "STD79-DOE:
  complete" anywhere in the log since before the whole capsule was fed,
  which matches the colon definition's own compile-time echo of that same
  string literal, not just the real end-of-run print. Without HB-ON the
  entire 27-trial run finished in a few seconds -- faster than one poll
  interval -- so the false match and the real one always landed in the
  same window and this never surfaced. HB-ON's added per-tick console I/O
  slowed real execution enough to expose it: the script sent BYE the
  moment compilation finished, truncating every trial after whatever
  point compilation had reached (aarch64 lost 9 of 27 trials this way on
  the first attempt). Fixed by feeding definitions and invocation as two
  genuinely separate connections, with the completion-watch window opened
  only after compilation is confirmed landed.

Verified 27/27 trials correct on every architecture via the campcampaign's
most distinctive result markers (both M*/M/MOD 18-19 digit values and the
2147483648 2/ result, all exactly 27 occurrences, zero faults) rather than
exact substring reconstruction: HB-ON's async per-tick CSV printer and the
trial loop's own console output share the same serial line with no
locking, so CSV rows can splice mid-token into trial output on the wire
(confirmed live -- cosmetic only, the underlying FORTH execution and
values are unaffected). results-20260912-with-heartbeat-csv/ holds both
the raw logs and their paired heartbeat CSVs; the earlier truncated runs'
logs are kept too (never delete logs) as the record of how this was found.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
2026-09-12 10:44:00 -04:00
Robert Allan JamesandClaude Sonnet 5 9eff122090 Fix aarch64 Stadium/COOL O(ncells) scan; rerun std79 DoE clean, 81/81 (FABRIC-3.md §XVI)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
Root cause of the 90+ minute aarch64 VM-birth stall found in §XV: stadium_admit()'s
eviction-fallback scan iterated the entire stadium_ncells array filtered by owner,
not the calling VM's own resident cells as its own doc comment claimed. Combined
with stadium_grant_quota() always splitting from Hera's shrinking free list and
stadium_word_dispatch() calling stadium_admit() per distinct word a VM's capsule
executes, this compounded into a real O(n) blowup — catastrophic specifically on
aarch64 because its -m 4096 (vs 1024 on amd64/riscv64) inflates the kmalloc heap
kmalloc_init() bisects down to, which inflates stadium_ncells 4x (335,544 vs 83,886
cells, measured from boot logs).

Fixed by threading a real per-VM doubly-linked resident-cell list
(StadiumVMQuota.resident_head + stadium_resident_next[]/stadium_resident_prev[])
so the fallback scan is bounded by that VM's own resident count, not the global
cell array size.

Verified with a full rerun of the 3x9x3 std79 DoE campaign from scratch: one
continuous boot per architecture, all 9 identities simultaneously live throughout
(the 3-boot aarch64/riscv64 batching workaround is no longer needed). 81/81 trials
correct, 0 mismatches, DOE-RUN header sequence md5-identical across all three raw
logs. Identity 04's attach on aarch64, which stalled 90+ minutes before, now
completes in ~34s; full boot-to-DoE-complete in ~290s.

Corrects an earlier misreading (carried into §XV, std79-doe.fth's comments, and
the project memory note) that described the symptom as a runaway "335,000+ cycles"
dispatch counter — those were cell array indices, not an event count.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
2026-09-11 16:37:44 -04:00
Robert Allan JamesandClaude Sonnet 5 e2abc56306 3(arch) x 9(identity) x 3(rep) randomized full-factorial std79 DoE: 81/81 correct (FABRIC-3.md §XV)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
Formal successor to §XII's ad hoc exerciser campaign, requested as a
genuine randomized full-factorial design matching this project's own
DoE methodology (capsules/doe.4th's Fisher-Yates shuffle), and written
entirely in FORTH per explicit request -- not host-orchestrated shell
scripting.

experiments/std79-doe/std79-doe.fth: builds a 27-cell (9 identity x 3
replicate) run matrix, Fisher-Yates shuffles it with a fixed seed
(matching doe.4th's own default), then dispatches each of the 24
exerciser test cases directly into the target identity's own live VM
via VM-EXEC -- no console USE redirection, no per-trial host
interaction. The zuse case runs as directly-compiled native code
(RUN-TEST-NATIVE) rather than VM-EXEC targeting "Hera" herself:
VM-EXEC's own vm_state_push/pop only saves rsp/exit_colon/ecw_nesting,
not input_buffer/input_pos, so a self-targeting call while this
capsule's own vm_interpret call is still mid-line would risk exactly
the class of bug the idle-tick reentrancy guards exist for.

amd64: all 27 trials ran with all 9 identities simultaneously live in
one boot -- clean, zero mismatches.

aarch64: hit a real, uninvestigated bug attaching all 9 simultaneously
-- the 6th live VM's birth stalled for 90+ minutes at 100%+ CPU with a
Stadium COOL-dispatch counter already at 335,000+ cycles, versus tens
of thousands at the same checkpoint for earlier identities. Not
root-caused here (flagged in FABRIC-3.md for later); worked around by
splitting into 3 boots of 3 simultaneously-live identities each, every
boot sharing the same seed so the master 27-slot shuffle is identical,
filtered per boot by a new ACTIVE-LO/ACTIVE-HI range
(EXEC-STD79-DOE's signature: seed lo hi -- ). run_id is always the
slot's true position in the master shuffle, so trial order stays
comparable across boots -- standard DoE blocking.

riscv64: same 3-boot pattern, clean.

Grand total: 81/81 trials correct, 0 mismatches, across all three
architectures, all nine identities, all three replicates.

Also flagged (FABRIC-3.md §XIV, not fixed): attaching several WIREBIND
identities near-simultaneously (whether via rapid hotplug or all
present from boot) causes the kernel to silently detect only some of
them -- confirmed at the host/QMP level that every device was genuinely
present. Worked around throughout this campaign by attaching one
identity at a time with confirmed waits; real hardware hotplug could
hit the same gap, so it's a genuine robustness concern, not just a
test-harness inconvenience.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
2026-09-11 13:59:32 -04:00