No-backward-compat sweep, part 2. The module had been reduced to a
units-only re-export ('retired, do not add values'); per policy it is
now gone and every consumer reads the real home:
- 32 internal modules, the package __init__, and core/__init__ import
core.units (physics modules keep their own physics/constants)
- 43 book chapters' LEGO cells migrated (star imports, named imports,
and the appendix attribute style 'constants.VIDEO_*' -> units.*);
lego_focal_verify confirms identical pass/flag state to pre-sweep
(8 pre-existing structural flags, A/B-verified unchanged)
- tutorial/tools/test imports migrated (incl. binder test_units.py);
book tests' legacy-symbol scanner treats a missing constants.py as
'nothing defined'
- test_constants_allowlist.py rewritten as a deletion pin: the module
(and any shim for it) must never return; core.units must keep the
measurement surface (ureg, Q_, GB, BYTES_FP16, PRECISION_MAP, ...)
- test_mlsysim_registry_parity.py deleted: it compared registry values
against legacy constants 'before deletion' — that migration is
complete (registry gate list updated)
- Docs prose (DATA_MODEL, architecture, contributing) states the
deletion instead of describing a retired shim
749 passed; binder registry gate green; star import intact.
Visual QA of all 207 margin figures surfaced figures that contradicted
their own captions/labels. Fixes:
- 6 ladder inversions where bar length taught the opposite of the data
(P99 vs mean, Image vs Text bandwidth, FHE vs AES latency, HBM vs
register energy, training vs inference memory, radio vs arithmetic).
Regenerated via margin_devices with consistent-unit / mlsysim SSOT
values.
- 5 trend/threshold figures whose shape did not match the relationship
(cloud-edge crossover, FPS collapse, burst-vs-sustained levels) plus
two caption reframes (retraining knee, training power).
- 7 segmented-bar figures whose labels were truncated to 4 chars and two
whose highlight contradicted the caption (egress, optimizer state);
regenerated readable with full labels.
- 10 passive/meta captions rewritten as declarative takeaways.
Root cause hardened in generate_margin_figures.py: _parse_number now
unit-aware (ms vs s, MB/s vs GB/s, pJ vs nJ) instead of mis-reading the
first letter of a unit as a k/M/B/T multiplier; ironbar label cap raised
from 5 chars so words are no longer chopped.