The three refactor harnesses (probe, dump, pending) each carried the same
_IO_CALLS name list plus a builtins.open spy. Measured at bb4a85e in a clean
clone: Path(__file__).read_text(), os.open(__file__, O_RDONLY), io.open(__file__)
and with Path(__file__).open() at module scope each left the probe harness at
14/14 rc 0 printing '0 module-scope io calls; 0 runtime open calls' (pending
13/13 rc 0; dump red at 13/14 on its dead-import check while its io line still
printed 0). The name-list walk resolves Path(p).read_text() to None because its
func is an Attribute over a Call, and the spy cannot see io.open/pathlib.
Now: wizard-work/forge/import_io_detector.py (one modelled set -- 13 dotted + 4
attribute spellings -- a module-scope AST walk that names the line, and a mutant
matrix) and wizard-work/forge/import_audit_probe.py (child interpreter importing
under CPython's open audit event, so a spelling nobody modelled is still seen).
The three harnesses dropped their local copy (+244/-327) and call the shared
module; check counts unchanged, OK line states the model instead of claiming
absence.
Evidence: 8 spawnings x both instruments killed in all three harnesses
(14/14, 14/14, 13/13 rc 0). Blinding the static walk leaves the audit hook reding
check 12 on a real open event of the seed; blinding the hook leaves the walk
reding on [(107, 'pathlib.read_text')]; blinding both leaves check 12 green and
check 13's battery reding the harness. _F = open / _F(DEFAULT_PATH) -- a spelling
no list names -- is caught by the hook alone.
Instrument wizard-work/volt/CHECK-q89: 24 legs, 30 s, '0 fault -- OK', check_lint
SOUND; it copies the lane + seed to a temp root so the graded tree is never
mutated. Fourth copy (verify_dump_seed_refactor.py) untouched at 16/16 and used
as an independent oracle: agrees 12/12. Q90's beam guard untouched.
verify.py --fast: 10 legs, 9 pass, 0 fault, 1 skipped, gate OK.