mix t0. ringb
(Raxol v2.6.1)
View Source
Drives real macOS GUI terminals (iTerm2, Terminal.app, WezTerm, kitty)
through AppleScript/CLI device control, judges the T0 keystone claims
(C1/C2/C3/C4/N06/N07) programmatically against each capture, writes the
results into scripts/harness/t0/t0-verdict.json via
append_result.sh, and prints the D-PA resolver's output.
This retires the manual "Ring B" half of
docs/proposals/t0-runbook.md for every terminal with a
scriptable capture API. Ghostty has neither a get-text CLI nor a
get text/contents/history AppleScript command (confirmed via
sdef) — it is recorded as a documented skip (screenshot residual),
never guessed at.
mix t0.ringbOpens and closes several real GUI windows over the course of the run
(one per driver × claim) — this is expected. Every window this task
opens is torn down through T0.RingB.Guard.safe_teardown/3, which
kills the probe's own process before closing (avoiding the "terminate
running processes?" confirmation dialog a live foreground job would
otherwise trigger) and falls back to a bounded, non-blocking recovery
path if a close still hangs. Every driver call this task makes
(spawn, run-command, capture, resize, close) is itself bounded by
T0.RingB.Guard.with_timeout/2 (RB review FIX-NOW #1) — the
enforced guarantee is that THIS RUN stays bounded, not that every OS
process it ever touches is guaranteed reaped: force-killing a guarded
task cannot reap an already-orphaned osascript subprocess (see
T0.RingB.Osa's moduledoc), and this task does not claim otherwise.
Two things a human running this WATCHED (never unattended) needs to know honestly, not just implicitly:
- The very first run on a machine that has never granted this harness Automation permission (Terminal/iTerm2/System Events) will pop a one-time macOS TCC authorization prompt outside this task's control — it must be clicked by a human before the run can proceed; every run after that grant is unattended.
- The last-resort modal dismissal inside
T0.RingB.Guard(reached only after kill-marker + close + astill_open?/1verification have ALL already failed) is APP-scoped, not sheet-scoped — it activates the whole application and sends a bare keystroke, which per the observed dialog is bound to "Terminate". A sheet-scoped version (targeting the exact confirmation dialog rather than whatever the app has frontmost) is DEFERRED to the next watched live matrix run, where it can be validated against a real modal before replacing this fallback; seeT0.RingB.Guard. dismiss_modal_best_effort/1's moduledoc for the full rationale.
Requires a real macOS GUI session (Aqua) — not runnable headless/CI;
see the test/harness/ringb_*.exs suite (@moduletag :ring_b,
excluded from every default mix test invocation) for the same
coverage as ExUnit assertions.