Build the DoE region reader + automated R/LaTeX report pipeline
Closes the "still open" reader-tool note from §XXXV.10: scripts/ extract_doe_region.py spools DOE-PERSIST-TRIAL's on-disk binary ring off disk/artemis.img into a CSV -- direct file read by default, or via a real loop device (--loop, losetup) per the literal request. Independent Python reimplementation of doe_region.c's own ring-walk, verified against a live 3-record write/read round trip. analyse_multiuser_doe.R (house style, ggplot2/svglite) and multiuser_doe_report.tex (same preamble convention as bare_metal_doe_report.tex) auto-discover whatever data exists and degrade gracefully to a placeholder when a campaign has 0 trials so far -- the whole point being this can be rebuilt at any point during a multi-day campaign, including mid-run. build_multiuser_doe_report.sh chains extraction -> R -> svg_to_pdf.py -> pdflatex into one command. Found and fixed a real bug while verifying: the R script's SCRIPT_DIR detection silently wrote charts/tables/report output to the repo root instead of the analysis directory when invoked from a different cwd -- switched to the robust commandArgs() "--file=" idiom. Verified live both branches (0 trials and a real 3-record write), reverted synthetic test data and incidental svg_to_pdf.py churn on ~85 unrelated committed figures before committing. FABRIC-3.md §XXXV.11 has the full account. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BWpNjdwPtFLuVLaAq44L9K
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
aaf349946f
commit
c535252907
+75
@@ -5642,3 +5642,78 @@ scope per §XXXV.3 was the writer only, verified here by a one-off Python script
|
||||
bytes directly, not a maintained tool. Launching the first live multi-hour campaign is still a
|
||||
separate, later, explicit decision -- this entry closes the persistence-writer gap, nothing more.
|
||||
|
||||
### XXXV.11 -- The reader tool from §XXXV.10's own "still open" note: built, plus a full
|
||||
R/LaTeX report pipeline, all live-verified (2026-09-17)
|
||||
|
||||
Requested directly: "mount the virtual drive on a loop device... spool the csv's into a file
|
||||
for the proper deeply detailed R/LaTeX report with svg charts... build that workflow script for
|
||||
automated production of the PDF artifact while execution of the experiment is underway." Closes
|
||||
the one item §XXXV.10 itself flagged as still missing.
|
||||
|
||||
**Built:**
|
||||
- `scripts/extract_doe_region.py` -- standalone reader, independent reimplementation of
|
||||
`doe_region.c`'s own ring-walk logic in Python (same devblock_from_top fence math, same
|
||||
head/tail/record_count ring-order walk) reading `disk/artemis.img` directly. Two modes:
|
||||
`--img PATH` (default, no privilege needed -- opens the image as a plain file) and `--loop`
|
||||
(attaches via `losetup --read-only`, needs sudo, detaches on exit -- the literal loop-device
|
||||
step requested; noted in the script's own docstring that the ring is raw binary at a fixed
|
||||
offset, not a filesystem, so there is nothing to `mount` in the POSIX sense once attached, it
|
||||
reads exactly like a regular file). Read-only in both modes; a torn read mid-write from a
|
||||
live campaign is rejected the same way `doe_region_ctrl_read()` itself rejects a bad
|
||||
magic/version -- "not yet initialized," not a crash.
|
||||
- `experiments/bare_metal/analysis/analyse_multiuser_doe.R` -- new analysis script, house style
|
||||
(`ggplot2`/`svglite`, same `theme_light_report()` shape as `analyse_multirep.R`), but
|
||||
deliberately NOT that script's fixed-manifest pattern: auto-discovers whatever CSV or CSV
|
||||
directory it's given and **degrades gracefully to a placeholder table/chart when 0 trials
|
||||
exist yet**, rather than erroring -- the explicit "while execution of the experiment is
|
||||
underway" requirement. Also writes an auto-generated LaTeX fragment
|
||||
(`report/sections/multiuser_summary_autogen.tex`) with the actual current trial count, fail
|
||||
rate, and per-cell breakdown, computed fresh every run -- the report's own numbers stay
|
||||
truthful across re-runs instead of going stale.
|
||||
- `experiments/bare_metal/analysis/report/multiuser_doe_report.tex` -- new self-contained
|
||||
report (same preamble/colour-palette convention as `bare_metal_doe_report.tex`), every
|
||||
data-dependent figure wrapped in `\IfFileExists` so the report builds correctly whether 0
|
||||
trials or many have been extracted.
|
||||
- `scripts/build_multiuser_doe_report.sh` -- orchestrates all of the above: extract -> R
|
||||
analysis -> `svg_to_pdf.py` (existing, reused unmodified) -> `pdflatex` (twice, for
|
||||
cross-references) -> `multiuser_doe_report.pdf`. `--csv PATH` skips disk extraction entirely
|
||||
(smoke-testing against an arbitrary CSV); `--loop` passes through to the extractor.
|
||||
|
||||
**Real bug found and fixed while verifying, not left in:** the R script's original
|
||||
`SCRIPT_DIR` detection (`sys.frames()[[1]]$ofile`, the same pattern `analyse_multirep.R` already
|
||||
uses) silently fell back to `getwd()` when invoked from the orchestration script's own working
|
||||
directory -- wrote `charts/`, `tables/`, and `report/sections/` at the repo root instead of
|
||||
under `experiments/bare_metal/analysis/`, confirmed live (all three stray directories actually
|
||||
appeared there on the first orchestrated run). Fixed with the robust `commandArgs()`
|
||||
`"--file="` idiom, re-verified correct placement, stray directories removed. Not touched in
|
||||
`analyse_multirep.R` itself -- out of scope, not verified broken there, flag only.
|
||||
|
||||
**Verified live, full pipeline, both branches:**
|
||||
1. **No-data branch:** ran the full orchestration script against the current (post-§XXXV.10
|
||||
test-write-reverted) `disk/artemis.img` -- 0 trials, placeholder chart/table/summary
|
||||
generated, real 2-page PDF produced, correctly states "No trial data has been persisted to
|
||||
the DoE region yet."
|
||||
2. **Populated branch:** booted amd64, wrote 3 synthetic trial records via `DOE-PERSIST-TRIAL`
|
||||
at the console (one deliberately with `fail=1`), clean `BYE`. `extract_doe_region.py`
|
||||
round-tripped all 3 records correctly, in ring order, byte-exact. Full orchestration run
|
||||
(`--csv` override, to isolate the R/LaTeX stage from the disk-extraction stage) produced a
|
||||
real 4-page PDF with correct auto-generated summary text ("3 completed trial(s)... Overall
|
||||
fail rate... 33.3%...") and real embedded SVG-derived charts.
|
||||
3. Reverted the synthetic test write from `disk/artemis.img` afterward (same convention as
|
||||
§XXXV.10) and regenerated the final on-disk report/CSV against the real, empty state before
|
||||
committing -- what's in the repo now honestly reflects "no campaign has run yet," not
|
||||
leftover demo numbers.
|
||||
4. Reverted an unrelated side effect caught before committing: `svg_to_pdf.py` (existing,
|
||||
unmodified) re-converts every SVG in the shared `charts/` directory on each run, which
|
||||
touched ~85 pre-existing, unrelated committed figure PDFs with meaningless
|
||||
binary/metadata-only diffs (almost certainly `rsvg-convert` version drift, not content
|
||||
changes) -- reverted before staging, confirmed only the new `multiuser_*` files remain
|
||||
changed.
|
||||
|
||||
**Not done, explicitly out of scope for this pass:** the actual multi-day campaign launch is
|
||||
still a separate, deliberate decision -- this closes only the "how do we get a report out of
|
||||
it" side. `--loop` mode was implemented per the literal request but not live-tested (the
|
||||
default `--img` direct-file mode was what got exercised above; both modes share the same
|
||||
`read_ring()` code path once handed a device/file path, so this is a thin, low-risk gap, not
|
||||
an unverified core mechanism).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user