Commit Graph
4 Commits
Author SHA1 Message Date
Robert Allan JamesandClaude Sonnet 5 c02fed140f Fix ISA-tagging: two real bugs found live, campaign quit for a fresh run
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
FABRIC-3.md §XXXV.13. Quit the running amd64 campaign directly on request
once §XXXV.12's build unblocked live testing -- first live check found
the ISA-tagging mechanism completely non-functional, in two independent
ways, both only caught by checking an actual printed value rather than
"it resolves without error."

Bug 1: per-isa-doe.4th's strategy of redefining MU-EMIT-TRIAL-MARKER
never worked, structurally, from the moment it was written. This FORTH
compiles a colon definition's word calls to a direct, early-bound
reference at compile time -- MU-RUN-TRIAL's call to MU-EMIT-TRIAL-MARKER
bound when multiuser-doe.4th loaded, before per-isa-doe.4th's later
redefinition of the same name ever existed. Every trial the running
campaign persisted had an empty isa tag, not "amd64". Fixed by moving
ISA-tag storage (MU-ISA-TAG-BUF/LEN/!) and the one true
MU-EMIT-TRIAL-MARKER into multiuser-doe.4th itself, reading a shared
variable at run time instead. per-isa-doe.4th shrank from 3 blocks to 2
(Block 5118 freed) -- fixing this recovered namespace, didn't cost any.

Bug 2: found immediately while verifying the fix. MU-ISA-TAG!'s CMOVE
call was copied from the original PER-ISA-TAG! it replaced, which had
its own latent stack-order bug -- passed the ISA string's length as the
copy source address instead of the real address, silently copying
blank/garbage bytes with no error. Never caught before because §XXXV.8's
own verification only checked that the entry words resolved, not that
the tag they set was actually correct. Fixed the stack order; the old
buggy word no longer exists anywhere (removed with Bug 1's fix, not
patched in place).

Verified live, together, one boot: MU-ISA-TAG-BUF readback -> "amd64"
(was blank), full MU-EMIT-TRIAL-MARKER with all 6 fields set manually ->
exact match on every field, VM-ERROR? -> 0, DOE-RESUME-COUNT correctly
isolates by ISA (amd64->1, riscv64->0 in the same ring). Clean BYE, zero
leaked processes, synthetic test write reverted before committing.

Preserved logs/CSVs from the killed campaign and both verification boots
per this repo's own convention -- never delete these.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
2026-09-17 19:28:36 -04:00
Robert Allan JamesandClaude Sonnet 5 51940f49d0 Add per-slot CRC + campaign crash-resume (DOE-RESUME-COUNT)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
FABRIC-3.md §XXXV.12: closes two real gaps found by walking the disk-to-
PDF pipeline end to end. (1) doe_trial_slot_t had no integrity check of
its own -- 64 slots share one devblock via a read-modify-write, so a
crash mid-write to any slot could silently corrupt its siblings with
nothing to catch it. Added an 8-byte CRC (same discipline the control
header already had), computed/verified the same way. (2) The campaign
itself had no crash-resume -- a reboot always restarted the whole
18-trial loop from index 0 even with good persisted data already on
disk. Since the trial matrix is fully deterministic from (seed, n-reps),
resuming needs no persisted "which trials ran" state, just a count:
DOE-RESUME-COUNT (new kernel primitive, same pattern as
DOE-PERSIST-TRIAL) walks the ring counting CRC-valid records for a given
ISA; MU-EXEC-CAMPAIGN's signature changes to accept a start-idx and seeds
MU-RUN-ID/the DO loop from it. Each RUN-*-CAMPAIGN entry word now calls
DOE-RESUME-COUNT before launching. Both block-namespace-checked to fit
existing headroom before committing to the design -- no new blocks
needed.

Real bug caught by the build, not shipped: an implicit compiler-inserted
alignment byte before slot_crc silently broke the hand-computed trailing
pad size (doe_trial_slot_size_check failed to compile). Fixed with an
explicit alignment field, matching log_slot_t's own zero-implicit-
padding discipline.

extract_doe_region.py now verifies both CRCs with the REAL CRC-64/XZ
algorithm from block_subsystem.c's compute_crc64() (ported and verified
bit-for-bit against a native C reference this session), replacing
§XXXV.11's incorrect guessed implementation.

Verified: clean compile on all 3 ISAs (amd64/aarch64/riscv64 -- amd64
verified via isolated build only, not boot, since the real per-ISA
campaign is currently live on the only QEMU instance this project's own
rule allows), both capsules pass mkcapsule --lint, CRC64 bit-exact via
native reference. Live boot-verification explicitly deferred until that
campaign finishes or is interrupted -- not claimed as tested when it
wasn't. Found (not missed) a real compatibility consequence: the running
campaign's data is in the old pre-CRC format, so it reads as "corrupt"
under the new extractor and DOE-RESUME-COUNT will resume it from 0, not
mid-campaign -- no data loss, cheap redundant re-run of ~1-2 trials.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
2026-09-17 19:17:04 -04:00
Robert Allan JamesandClaude Sonnet 5 2da746c01c Build DOE-PERSIST-TRIAL: block-backed DoE campaign persistence, live-verified
FABRIC-3.md §XXXV.3/.4 designed this and it was never built -- two live
campaigns got launched relying entirely on a live serial-log tail before
this was caught. doe_region.c/.h mirrors log_region.c's own growable-ring
pattern (own devblock_from_top fence at 98, past log_region's ceiling at
97) to persist one trial-summary record per completed trial straight to
disk/artemis.img, surviving past QEMU exit with no host required.

Verified end to end: booted amd64, called DOE-PERSIST-TRIAL at the
console, clean BYE, then read the raw disk bytes back with QEMU fully
dead -- confirmed the exact values passed in. Wired into both
multiuser-doe.4th and per-isa-doe.4th's trial markers. Clean build, zero
new warnings, all 3 ISAs; mkcapsule --lint passes both edited capsules.

FABRIC-3.md §XXXV.10 documents the fix and the root-cause correction: two
campaigns were launched on an unbuilt persistence design before this was
caught and fixed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
2026-09-17 16:43:46 -04:00
Robert Allan JamesandClaude Sonnet 5 8b8e8e1405 Build capsules/per-isa-doe.4th: per-ISA campaign driver (N=3, 18 trials/ISA)
Build / build-amd64-iso (push) Canceled after 0s
Build / build-aarch64-iso (push) Canceled after 0s
Build / build-riscv64-img (push) Canceled after 0s
Thin wrapper over multiuser-doe.4th's own MU-EXEC-CAMPAIGN, which already
implements the ratified 6-cell factorial generically -- adds only what
FABRIC-3.md §XXXIV.4's per-ISA pivot needed: one fixed seed per ISA,
N=3 reps/cell=18 trials/ISA (ratified over §XXXV.5's own N=2 safety-margin
recommendation, Captain Bob's explicit choice), an ISA tag threaded into
the trial marker so records from all 3 ISAs' sequential campaigns can be
told apart on the shared disk/artemis.img, and three single-word
no-argument entry points (RUN-AMD64-CAMPAIGN/RUN-AARCH64-CAMPAIGN/
RUN-RISCV64-CAMPAIGN).

Blocks 5117-5119 -- the only 3 remaining in the [2048,5120) user block
namespace; mkcapsule --lint caught the first draft going one block past
the ceiling. Verified live, load-only: both capsules load with zero
UNKNOWN WORD/redefinition/error lines, all 3 entry words resolve,
constants compile correctly. No campaign trial has been run yet --
build+verify only, per explicit scope for this pass.

FABRIC-3.md §XXXV.8/.9 records the decision and verification.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 12:30:43 -04:00