J400: enable predictive local echo automatically from measured RTT (D130) #441

Open
opened 2026-11-09 00:29:15 +00:00 by kayg · 27 comments
Owner

Implement D130 automatic per-terminal predictive echo above about 60 ms with hysteresis, URL overrides, existing safety rules and misprediction cooldown. Follow-up to #438 and fd4506480.

Branch: predict-auto-d130
Base: origin/dev 44e80ccc5

Plan (estimate: 3 hours): inspect engine and echo safety; write and run red production-browser specs; implement the smallest policy change; measure before/after at 300/30 ms RTT; run predictive-echo and terminal specs three times, verify quick, and verify fast on compute01. No merge or deployment.

Implement D130 automatic per-terminal predictive echo above about 60 ms with hysteresis, URL overrides, existing safety rules and misprediction cooldown. Follow-up to #438 and fd4506480. Branch: predict-auto-d130 Base: origin/dev 44e80ccc5 Plan (estimate: 3 hours): inspect engine and echo safety; write and run red production-browser specs; implement the smallest policy change; measure before/after at 300/30 ms RTT; run predictive-echo and terminal specs three times, verify quick, and verify fast on compute01. No merge or deployment.
Author
Owner

Start: predict-auto-d130, base origin/dev 44e80ccc5.

Finding 1: automatic enablement is missing as reported. main.ts:462 turns an absent predict flag into false, and terminal.ts:420 constructs no engine unless predictiveEcho is true.

Finding 2 (security/scope blocker): existing prediction does not satisfy D130 no-echo safety. predictive-echo.ts predicts before observing echo, then armTimeout() mutes only after 2*RTT + 64 ms. terminal-scenario.ts:172 and predictive-echo.spec.ts explicitly expect the first no-echo character to be drawn. There is no echo/raw-mode notification in contracts/wire.md or contracts/shim.md. Alternate-screen detection exists. Merely wiring auto-on would expose password input by default.

Next: production-build red reproducer using the existing 300 ms proxy, before deciding whether automatic enablement is safe to ship. A reliable pre-input safety signal would require a separate cross-layer design; output heuristics cannot distinguish a silent no-echo transition from an echoing terminal.

Start: predict-auto-d130, base origin/dev 44e80ccc5. Finding 1: automatic enablement is missing as reported. main.ts:462 turns an absent predict flag into false, and terminal.ts:420 constructs no engine unless predictiveEcho is true. Finding 2 (security/scope blocker): existing prediction does not satisfy D130 no-echo safety. predictive-echo.ts predicts before observing echo, then armTimeout() mutes only after 2*RTT + 64 ms. terminal-scenario.ts:172 and predictive-echo.spec.ts explicitly expect the first no-echo character to be drawn. There is no echo/raw-mode notification in contracts/wire.md or contracts/shim.md. Alternate-screen detection exists. Merely wiring auto-on would expose password input by default. Next: production-build red reproducer using the existing 300 ms proxy, before deciding whether automatic enablement is safe to ship. A reliable pre-input safety signal would require a separate cross-layer design; output heuristics cannot distinguish a silent no-echo transition from an echoing terminal.
Author
Owner

Blocked handoff, implementation is NOT complete. Branch predict-auto-d130, pushed head dcf29ccb0b (atomic WIP red-spec commit only). No production behavior changed; no merge or deployment.

Production-build evidence on dev-02 through build-slot (3 slots), 300 ms RTT test profile, Chromium, one worker:

  • Automatic enablement spec fails: expected enabled=true, received false.
  • No-echo privacy spec fails: expected pendingText="", received "p". Attached production bitmap preserves the actual overlay before its timeout; the RTT pill reads 307 ms. This is a public fixture character, not a credential.
  • First-mismatch backoff spec fails: after mispredictions=1, expected enabled=false, received true.
    All three are behavioral failures, not setup failures. RED_EXIT=1. Browser plugin unavailable; used the repository Playwright production-build workflow explicitly requested for dev-02.

Additional real-PTY check: an interactive /bin/bash --noprofile --norc -i prompt on dev-02 has ECHO=false and ICANON=false. Raw termios flags alone would also disable prediction during ordinary shell line editing. shell-mode.json is attached.

Why stopped: the browser sees identical state for an echoing shell and a silent no-echo transition until after it has already drawn input. The existing engine guesses, then mutes after 2*RTT+64 ms, which cannot meet "password prompt ... never show predictions". Past echo proofs or prompt-text matching cannot reliably establish current privacy safety. Enabling the existing engine by default would make that disclosure the default.

The scope leash in ~/infraternal-ops/BRIEF-COMMON.md says: "Do exactly the task, by the shortest safe path. Do NOT build general infrastructure, frameworks, updaters, harnesses or tooling the task does not need" and requires stopping/reporting when extra work is needed. A reliable, ordered per-terminal eligibility signal or shell-integration contract is a cross-layer prerequisite, beyond an RTT policy change. Recommendation to the orchestrator: resolve that prerequisite before enabling automatic prediction; do not accept timeout-based hiding as password safety. No question was sent to the owner.

Validation: verify quick passed (verbatim summary below). Predictive-echo/terminal three-pass gate and verify fast on compute01 were NOT run because implementation is blocked. Before/after input-to-photon latency at 300/30 ms was NOT measured; no completed implementation exists to compare. No performance claim is made. Browser/proxy processes exited; ports 5400/5401 are free; this job's 367 MiB target was removed. Evidence remains outside the checkout on dev-02 and code at ~/.cache/codex-scratch/j400/evidence/.

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| scope guard               | PASS         |
| migration names           | PASS         |
| Nix Cargo vendoring       | PASS         |
| fmt                       | PASS         |
| doc coverage ratchet      | PASS         |
| shape lints off (D351)    | PASS         |
| doc comments on diff      | PASS         |
| fixed test waits          | PASS         |
| ui literals               | PASS         |
| tracer typecheck          | PASS         |
+---------------------------+--------------+

QUICK pre-check passed. This is not the gate: run scripts/verify fast before reporting done.
QUICK_EXIT=0

Blocked handoff, implementation is NOT complete. Branch predict-auto-d130, pushed head dcf29ccb0b3a6cfb1b594f15441949a984700db7 (atomic WIP red-spec commit only). No production behavior changed; no merge or deployment. Production-build evidence on dev-02 through build-slot (3 slots), 300 ms RTT test profile, Chromium, one worker: - Automatic enablement spec fails: expected enabled=true, received false. - No-echo privacy spec fails: expected pendingText="", received "p". Attached production bitmap preserves the actual overlay before its timeout; the RTT pill reads 307 ms. This is a public fixture character, not a credential. - First-mismatch backoff spec fails: after mispredictions=1, expected enabled=false, received true. All three are behavioral failures, not setup failures. RED_EXIT=1. Browser plugin unavailable; used the repository Playwright production-build workflow explicitly requested for dev-02. Additional real-PTY check: an interactive /bin/bash --noprofile --norc -i prompt on dev-02 has ECHO=false and ICANON=false. Raw termios flags alone would also disable prediction during ordinary shell line editing. shell-mode.json is attached. Why stopped: the browser sees identical state for an echoing shell and a silent no-echo transition until after it has already drawn input. The existing engine guesses, then mutes after 2*RTT+64 ms, which cannot meet "password prompt ... never show predictions". Past echo proofs or prompt-text matching cannot reliably establish current privacy safety. Enabling the existing engine by default would make that disclosure the default. The scope leash in ~/infraternal-ops/BRIEF-COMMON.md says: "Do exactly the task, by the shortest safe path. Do NOT build general infrastructure, frameworks, updaters, harnesses or tooling the task does not need" and requires stopping/reporting when extra work is needed. A reliable, ordered per-terminal eligibility signal or shell-integration contract is a cross-layer prerequisite, beyond an RTT policy change. Recommendation to the orchestrator: resolve that prerequisite before enabling automatic prediction; do not accept timeout-based hiding as password safety. No question was sent to the owner. Validation: verify quick passed (verbatim summary below). Predictive-echo/terminal three-pass gate and verify fast on compute01 were NOT run because implementation is blocked. Before/after input-to-photon latency at 300/30 ms was NOT measured; no completed implementation exists to compare. No performance claim is made. Browser/proxy processes exited; ports 5400/5401 are free; this job's 367 MiB target was removed. Evidence remains outside the checkout on dev-02 and code at ~/.cache/codex-scratch/j400/evidence/. ```text +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | scope guard | PASS | | migration names | PASS | | Nix Cargo vendoring | PASS | | fmt | PASS | | doc coverage ratchet | PASS | | shape lints off (D351) | PASS | | doc comments on diff | PASS | | fixed test waits | PASS | | ui literals | PASS | | tracer typecheck | PASS | +---------------------------+--------------+ QUICK pre-check passed. This is not the gate: run scripts/verify fast before reporting done. QUICK_EXIT=0 ```
Author
Owner

Resuming J400 at dcf29ccb0b, base origin/dev 44e80ccc5, branch predict-auto-d130. The orchestrator has decided the safety design within D130: host eligibility is !(ICANON && !ECHO), alternate screens remain forbidden, and every new prediction epoch first requires an exact echoed probe. Epochs restart on mode change, misprediction, cursor jumps and reattach. No owner question is needed.

Plan (estimate 4 hours): add red real-PTY mode and browser epoch tests; add negotiated shim mode-state notification and forward it as an additive terminal.prediction_mode Event on the existing terminal stream; implement fail-closed client epochs, cooldown and RTT hysteresis with URL overrides; run production suites 3x on dev-02, real-shim branch-server proof on compute01 through 300 ms, before/after 300/30 ms measurements, quick and fast on compute01. No merge.

Initial inspection: neither VT state nor current shim frames expose termios. Existing terminal Events already traverse the host daemon and server and are additive. Proposed shim extension: capability bit 8, frame 0x24 with output cursor, raw mode bits ECHO/ICANON, selected only by new consumers. Send initial state on attach and subsequent states only when mode changes, ordered before associated output. Read termios on reactor activity without an idle polling timer; browser starts ineligible for older hosts and every reattach.

Resuming J400 at dcf29ccb0b3a6cfb1b594f15441949a984700db7, base origin/dev 44e80ccc5, branch predict-auto-d130. The orchestrator has decided the safety design within D130: host eligibility is !(ICANON && !ECHO), alternate screens remain forbidden, and every new prediction epoch first requires an exact echoed probe. Epochs restart on mode change, misprediction, cursor jumps and reattach. No owner question is needed. Plan (estimate 4 hours): add red real-PTY mode and browser epoch tests; add negotiated shim mode-state notification and forward it as an additive terminal.prediction_mode Event on the existing terminal stream; implement fail-closed client epochs, cooldown and RTT hysteresis with URL overrides; run production suites 3x on dev-02, real-shim branch-server proof on compute01 through 300 ms, before/after 300/30 ms measurements, quick and fast on compute01. No merge. Initial inspection: neither VT state nor current shim frames expose termios. Existing terminal Events already traverse the host daemon and server and are additive. Proposed shim extension: capability bit 8, frame 0x24 with output cursor, raw mode bits ECHO/ICANON, selected only by new consumers. Send initial state on attach and subsequent states only when mode changes, ordered before associated output. Read termios on reactor activity without an idle polling timer; browser starts ineligible for older hosts and every reattach.
Author
Owner

Progress: the additive mode codec has a behavioral red/green receipt (red-mode.log, green-mode-codec.log: 13 passed, 1 ignored). Six controlled-clock epoch/RTT tests pass (green-epochs.log); no functional wall-clock speed assertion was added. Current implementation samples termios on reactor activity, sends initial/changed state to negotiated peers, forwards terminal.prediction_mode through the authenticated terminal Event stream, and defaults prediction to auto with 70/60 ms hysteresis. ?predict=1 bypasses RTT only; both overrides retain all safety checks. New epochs reconcile the entire initial input queue invisibly using the existing bytewise echo engine. Each mismatch requires a fresh proof plus a one-second monotonic cooldown.

The queued production-browser run on dev-02 is validating activation/privacy/backoff before the full suites. Both VMs are busy; no extra slot is held by J400. Evidence paths remain ~/.cache/codex-scratch/j400/evidence/ on each VM.

Progress: the additive mode codec has a behavioral red/green receipt (red-mode.log, green-mode-codec.log: 13 passed, 1 ignored). Six controlled-clock epoch/RTT tests pass (green-epochs.log); no functional wall-clock speed assertion was added. Current implementation samples termios on reactor activity, sends initial/changed state to negotiated peers, forwards terminal.prediction_mode through the authenticated terminal Event stream, and defaults prediction to auto with 70/60 ms hysteresis. ?predict=1 bypasses RTT only; both overrides retain all safety checks. New epochs reconcile the entire initial input queue invisibly using the existing bytewise echo engine. Each mismatch requires a fresh proof plus a one-second monotonic cooldown. The queued production-browser run on dev-02 is validating activation/privacy/backoff before the full suites. Both VMs are busy; no extra slot is held by J400. Evidence paths remain ~/.cache/codex-scratch/j400/evidence/ on each VM.
Author
Owner

J400 resumed at pushed head 50795ce158 on predict-auto-d130. The owner-selected design is implemented in that WIP snapshot: negotiated ECHO/ICANON state, fail-closed unknown modes, exact invisible echo epochs, 70/60 ms hysteresis and a 1 s mismatch cooldown. No merge or deployment.

Production tracer checks on dev-02: the original three red regressions plus unknown-first-input and explicit-off checks pass (5 passed, 30 ms profile check separately pending). Receipt: /home/claude/.cache/codex-scratch/j400/evidence/auto-green.log. Rust integration/quick checks and the three-pass full browser suites are next; real shim branch-server proof and latency measurements remain outstanding. Found missing initialization of the new per-peer field in existing internal Rust test fixtures; correcting before compiling them.

J400 resumed at pushed head 50795ce158ff7ab2671208ebfb27564977b15721 on `predict-auto-d130`. The owner-selected design is implemented in that WIP snapshot: negotiated ECHO/ICANON state, fail-closed unknown modes, exact invisible echo epochs, 70/60 ms hysteresis and a 1 s mismatch cooldown. No merge or deployment. Production tracer checks on dev-02: the original three red regressions plus unknown-first-input and explicit-off checks pass (5 passed, 30 ms profile check separately pending). Receipt: `/home/claude/.cache/codex-scratch/j400/evidence/auto-green.log`. Rust integration/quick checks and the three-pass full browser suites are next; real shim branch-server proof and latency measurements remain outstanding. Found missing initialization of the new per-peer field in existing internal Rust test fixtures; correcting before compiling them.
Author
Owner

Additional finding: the initial epoch implementation checked the final cursor position but accepted an echo containing a cursor jump that returned to the expected cell. Added a controlled-clock regression first; it failed with epochConfirmed=true where false was required. The echo scanner now invalidates proof on cursor controls (including jumps inside a matching echo), while retaining styling/mode/query handling. Unit result: 7 pass, 0 fail, 26 assertions. Red/green receipts on dev-02: ~/.cache/codex-scratch/j400/evidence/{red,green}-cursor-epoch.log.

Full suites are queued through dev-02's three-slot launcher (PID 971074); quick is queued on compute01 (PID 507944). Real-process coverage reuses the existing private branch-server fixture and delayed WebSocket bridge. No production/test deployment is being replaced.

Additional finding: the initial epoch implementation checked the final cursor position but accepted an echo containing a cursor jump that returned to the expected cell. Added a controlled-clock regression first; it failed with `epochConfirmed=true` where false was required. The echo scanner now invalidates proof on cursor controls (including jumps inside a matching echo), while retaining styling/mode/query handling. Unit result: 7 pass, 0 fail, 26 assertions. Red/green receipts on dev-02: `~/.cache/codex-scratch/j400/evidence/{red,green}-cursor-epoch.log`. Full suites are queued through dev-02's three-slot launcher (PID 971074); quick is queued on compute01 (PID 507944). Real-process coverage reuses the existing private branch-server fixture and delayed WebSocket bridge. No production/test deployment is being replaced.
Author
Owner

Full-suite finding: terminal scenario's probe counted the new epoch-priming space as a measured key (Expected: abcdefghijklmnopqrst, Received: <space>abcdefghijklmnopqrst). Production renderer echoed all 20 probe keys correctly. The test now compares counters with a post-priming snapshot. Stopped the obsolete run by its recorded Playwright PID 1016656 (18 passed; one counter assertion failed); corrected three-pass suite queued as suites-300-v2.log.

Quick's first run stopped before Rust compilation at D345 documentation checks on touched declarations/old test initializers. Added the required comments; diff docs: ok (merge base 44e80ccc5e14). Second quick receipt: ~/.cache/codex-scratch/j400/evidence/quick-v2.log on compute01 (queued). All raw failure evidence is retained.

Full-suite finding: terminal scenario's probe counted the new epoch-priming space as a measured key (`Expected: abcdefghijklmnopqrst`, `Received: <space>abcdefghijklmnopqrst`). Production renderer echoed all 20 probe keys correctly. The test now compares counters with a post-priming snapshot. Stopped the obsolete run by its recorded Playwright PID 1016656 (18 passed; one counter assertion failed); corrected three-pass suite queued as `suites-300-v2.log`. Quick's first run stopped before Rust compilation at D345 documentation checks on touched declarations/old test initializers. Added the required comments; `diff docs: ok (merge base 44e80ccc5e14)`. Second quick receipt: `~/.cache/codex-scratch/j400/evidence/quick-v2.log` on compute01 (queued). All raw failure evidence is retained.
Author
Owner

Latency finding, measured only on the perf VM through perf-run (cpus 1–3, 6 GiB cap), production frontend before/after, no ?predict override, 3 trials × 30 serialized keys per case:

RTT Before p50 / p99 After p50 / p99 After predicted
300 ms 315.6 / 316.0 ms 14.6 / 15.0 ms 90/90
30 ms 32.4 / 49.2 ms 32.3 / 49.2 ms 0/90

Method: synthetic keydown to the first visible animation-frame mark in the production tracer; test-double host behind the existing TCP link, zero jitter for the paired comparison. This measures browser input-to-visible-frame, not a physical display sensor. The independent real shim/password/full-screen proof on a compute01 branch server remains pending.

The normal ±30 ms jitter profile also completed (90 keys/case): 300 ms p50/p99 315.7/332.6 → 14.9/15.2 ms. Its 30 ms p99 moved by a frame under differing random delays; the paired zero-jitter follow-up above resolved that uncertainty. CPU p99 did not regress in either profile.

Receipts on claude@infraternal-perf-01-backup01: ~/.cache/codex-scratch/j400/evidence/latency-summary.json, measure.log, latency-{before,after}-{300,30}-{0,1,2}.json; jittered receipts are under evidence/jitter/; perf-run before/after quiet/load receipts are under evidence/perf-run/. Selected summary and log also copied to code at the same scratch path. Both runs exited 0; all browsers/proxies exited.

Latency finding, measured only on the perf VM through `perf-run` (cpus 1–3, 6 GiB cap), production frontend before/after, no `?predict` override, 3 trials × 30 serialized keys per case: | RTT | Before p50 / p99 | After p50 / p99 | After predicted | | --- | --- | --- | --- | | 300 ms | 315.6 / 316.0 ms | 14.6 / 15.0 ms | 90/90 | | 30 ms | 32.4 / 49.2 ms | 32.3 / 49.2 ms | 0/90 | Method: synthetic keydown to the first visible animation-frame mark in the production tracer; test-double host behind the existing TCP link, zero jitter for the paired comparison. This measures browser input-to-visible-frame, not a physical display sensor. The independent real shim/password/full-screen proof on a compute01 branch server remains pending. The normal ±30 ms jitter profile also completed (90 keys/case): 300 ms p50/p99 315.7/332.6 → 14.9/15.2 ms. Its 30 ms p99 moved by a frame under differing random delays; the paired zero-jitter follow-up above resolved that uncertainty. CPU p99 did not regress in either profile. Receipts on `claude@infraternal-perf-01-backup01`: `~/.cache/codex-scratch/j400/evidence/latency-summary.json`, `measure.log`, `latency-{before,after}-{300,30}-{0,1,2}.json`; jittered receipts are under `evidence/jitter/`; perf-run before/after quiet/load receipts are under `evidence/perf-run/`. Selected summary and log also copied to code at the same scratch path. Both runs exited 0; all browsers/proxies exited.
Author
Owner

The production repeat run exposed two return-path test failures (alternate-screen exit and canonical no-echo exit). Both tests changed host state through the undelayed HTTP admin endpoint while input was still crossing the 300 ms WebSocket link. The next focused run now fences input acceptance before changing mode, and fences alternate-screen exit output before sending the invisible proof. This preserves the safety assertions rather than retrying speculative keys.

Receipt: dev-02 ~/.cache/codex-scratch/j400/evidence/suites-300-v2.log (15 passed, two return-path failures before stopping the obsolete repeat run by its recorded Playwright PID). Focused check is queued through build-slot; compute01 quick-v2 is also queued. No merge or deployment.

The production repeat run exposed two return-path test failures (alternate-screen exit and canonical no-echo exit). Both tests changed host state through the undelayed HTTP admin endpoint while input was still crossing the 300 ms WebSocket link. The next focused run now fences input acceptance before changing mode, and fences alternate-screen exit output before sending the invisible proof. This preserves the safety assertions rather than retrying speculative keys. Receipt: dev-02 `~/.cache/codex-scratch/j400/evidence/suites-300-v2.log` (15 passed, two return-path failures before stopping the obsolete repeat run by its recorded Playwright PID). Focused check is queued through build-slot; compute01 quick-v2 is also queued. No merge or deployment.
Author
Owner

Checkpoint: branch rebased onto current origin/dev 6b60f1fb7da71005da7c5f291ede28eb742fe583; pushed WIP head b5af811b8540506896055768cdfa2329328aae3b.

The second quick attempt reached the cheap checks and found one adjacent pre-existing function requiring a D345 comment after the new PPU ordering test extended its diff hunk. Fixed. Receipt: compute01 ~/.cache/codex-scratch/j400/evidence/quick-v2.log (fmt and coverage pass, doc comments fail, compilation not started).

The next compute01 slot runs the PPU regression red, applies the narrow ordering fix, checks it green, then runs quick and builds the branch server. Dev-02's focused return-path checks are queued; these also cover an empty replay on a shared socket, where a reconnect must discard the previous echo proof even if the PTY mode bits remain identical. No production deployment or merge.

Checkpoint: branch rebased onto current `origin/dev` `6b60f1fb7da71005da7c5f291ede28eb742fe583`; pushed WIP head `b5af811b8540506896055768cdfa2329328aae3b`. The second quick attempt reached the cheap checks and found one adjacent pre-existing function requiring a D345 comment after the new PPU ordering test extended its diff hunk. Fixed. Receipt: compute01 `~/.cache/codex-scratch/j400/evidence/quick-v2.log` (fmt and coverage pass, doc comments fail, compilation not started). The next compute01 slot runs the PPU regression red, applies the narrow ordering fix, checks it green, then runs quick and builds the branch server. Dev-02's focused return-path checks are queued; these also cover an empty replay on a shared socket, where a reconnect must discard the previous echo proof even if the PTY mode bits remain identical. No production deployment or merge.
Author
Owner

WIP checkpoint pushed: 6b64b4702 on predict-auto-d130. Added the production shared-socket empty-replay regression before changing its reset path. Both slot runs remain queued; no additional successful gate or real-shim proof is being claimed. Current receipts remain under each VM's ~/.cache/codex-scratch/j400/evidence/.

WIP checkpoint pushed: `6b64b4702` on `predict-auto-d130`. Added the production shared-socket empty-replay regression before changing its reset path. Both slot runs remain queued; no additional successful gate or real-shim proof is being claimed. Current receipts remain under each VM's `~/.cache/codex-scratch/j400/evidence/`.
Author
Owner

Finding confirmed by production browser regression: a shared terminal stream can reattach on its existing socket with an empty replay and unchanged mode bits. The old echo proof survived, so the first key after reattachment was predicted. The new red spec observed overlay appearances increase from 1 to 2 when that first key should stay invisible.

Fix: clear prediction mode/proof immediately in retryStream; the new shim peer supplies its initial mode, and the first exact echo establishes the new epoch. No socket replacement or new polling is needed.

Receipt: dev-02 ~/.cache/codex-scratch/j400/evidence/focused-return.log: 2 passed (the fenced return-path checks), 1 failed (the new empty-replay safety regression). The complete 3× suites plus the separate 30 ms check are now queued with this fix.

Finding confirmed by production browser regression: a shared terminal stream can reattach on its existing socket with an empty replay and unchanged mode bits. The old echo proof survived, so the first key after reattachment was predicted. The new red spec observed overlay appearances increase from 1 to 2 when that first key should stay invisible. Fix: clear prediction mode/proof immediately in `retryStream`; the new shim peer supplies its initial mode, and the first exact echo establishes the new epoch. No socket replacement or new polling is needed. Receipt: dev-02 `~/.cache/codex-scratch/j400/evidence/focused-return.log`: 2 passed (the fenced return-path checks), 1 failed (the new empty-replay safety regression). The complete 3× suites plus the separate 30 ms check are now queued with this fix.
Author
Owner

The first repeated production run verified the shared-stream reset fix (new regression PASS), then found the same test-admin/input ordering race in terminal-scenario.ts:189. I had fenced the focused prediction spec but missed the scenario's copy. The failure is at the first proof after alternate-screen exit, with input/admin requests still crossing independently.

Applied the same acceptance fence before changing modes, waited for the returning mode before the invisible q proof, and waited for the alternate-screen exit output cursor before priming the new epoch. These are observable protocol boundaries, with no fixed sleeps or weaker safety assertions.

Receipt: dev-02 ~/.cache/codex-scratch/j400/evidence/suites-unfenced-terminal.log (21 passed; 1 scenario failure; 1 interrupted; stopped by recorded Playwright PID). Restarted all 3× suites plus the 30 ms case with the corrected scenario; log suites-v4.log. Compute01's ordered-mode regression + quick + branch build remain queued.

The first repeated production run verified the shared-stream reset fix (new regression PASS), then found the same test-admin/input ordering race in `terminal-scenario.ts:189`. I had fenced the focused prediction spec but missed the scenario's copy. The failure is at the first proof after alternate-screen exit, with input/admin requests still crossing independently. Applied the same acceptance fence before changing modes, waited for the returning mode before the invisible `q` proof, and waited for the alternate-screen exit output cursor before priming the new epoch. These are observable protocol boundaries, with no fixed sleeps or weaker safety assertions. Receipt: dev-02 `~/.cache/codex-scratch/j400/evidence/suites-unfenced-terminal.log` (21 passed; 1 scenario failure; 1 interrupted; stopped by recorded Playwright PID). Restarted all 3× suites plus the 30 ms case with the corrected scenario; log `suites-v4.log`. Compute01's ordered-mode regression + quick + branch build remain queued.
Author
Owner

The corrected terminal scenario is green in repetition 1; prediction and glyph/cursor checks are also green through the start of repetition 2. The full required 3× run is still in progress, followed by the separate 30 ms case. Receipt: dev-02 ~/.cache/codex-scratch/j400/evidence/suites-v4.log.

Pushed reset checkpoint remains e2dc7d05f2; the scenario fence adjustment is pending the full run. Compute01's pre-check/build pipeline is still queued, so the real-shim proof and final gate remain outstanding.

The corrected terminal scenario is green in repetition 1; prediction and glyph/cursor checks are also green through the start of repetition 2. The full required 3× run is still in progress, followed by the separate 30 ms case. Receipt: dev-02 `~/.cache/codex-scratch/j400/evidence/suites-v4.log`. Pushed reset checkpoint remains `e2dc7d05f2`; the scenario fence adjustment is pending the full run. Compute01's pre-check/build pipeline is still queued, so the real-shim proof and final gate remain outstanding.
Author
Owner

Production browser gates PASS on dev-02 through build-slot (production build, 300 ms link, no retries):

Command: bunx playwright test test/predictive-auto.spec.ts test/predictive-echo.spec.ts test/terminal.spec.ts --repeat-each=3

Verbatim result:

  3 skipped
  45 passed (11.3m)
SUITES_EXIT=0

The three skipped cases select the separate 30 ms profile. That command, INFRATERNAL_TEST_RTT=30 bunx playwright test test/predictive-auto.spec.ts --grep 'below 60', also passed:

  1 passed (3.4s)
LOW_RTT_EXIT=0

Receipt: ~/.cache/codex-scratch/j400/evidence/suites-v4.log; screenshots under evidence/suites-300-v4/. Pushed WIP checkpoint dc82fccd2 includes the verified scenario fences and isolates the still-pending real proof from VM history/settings. Compute01's Rust red/green + quick + server build are still queued; real proof, real PTY measurements and final fast remain outstanding.

Production browser gates PASS on dev-02 through build-slot (production build, 300 ms link, no retries): Command: `bunx playwright test test/predictive-auto.spec.ts test/predictive-echo.spec.ts test/terminal.spec.ts --repeat-each=3` Verbatim result: ``` 3 skipped 45 passed (11.3m) SUITES_EXIT=0 ``` The three skipped cases select the separate 30 ms profile. That command, `INFRATERNAL_TEST_RTT=30 bunx playwright test test/predictive-auto.spec.ts --grep 'below 60'`, also passed: ``` 1 passed (3.4s) LOW_RTT_EXIT=0 ``` Receipt: `~/.cache/codex-scratch/j400/evidence/suites-v4.log`; screenshots under `evidence/suites-300-v4/`. Pushed WIP checkpoint `dc82fccd2` includes the verified scenario fences and isolates the still-pending real proof from VM history/settings. Compute01's Rust red/green + quick + server build are still queued; real proof, real PTY measurements and final fast remain outstanding.
Author
Owner

Confirmed and fixed the optional process-per-user ordering edge. The deterministic real-session regression received InputState → Output(prompt) → PredictionMode instead of the required InputState → PredictionMode → Output(prompt). A wholly queued acknowledgement had allowed output to append while the mode publisher was waiting for an empty queue.

The fix holds that output until this peer has queued the sampled mode ahead of it; no new timer, allocation or transport is introduced. The default session pump already waits for an empty queue and did not have this edge.

Red command: cargo test -p infraternal-shim --features process-per-user changed_prediction_mode_precedes_output_after_a_state_reply --lib -- --nocapture

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 245 filtered out; finished in 0.00s

Same command after the narrow fix:

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 245 filtered out; finished in 0.00s
GREEN_PPU_EXIT=0

Receipts: compute01 ~/.cache/codex-scratch/j400/evidence/{red,green}-ppu-order.log. verify quick is now running there, followed by the branch binary build.

Confirmed and fixed the optional process-per-user ordering edge. The deterministic real-session regression received `InputState → Output(prompt) → PredictionMode` instead of the required `InputState → PredictionMode → Output(prompt)`. A wholly queued acknowledgement had allowed output to append while the mode publisher was waiting for an empty queue. The fix holds that output until this peer has queued the sampled mode ahead of it; no new timer, allocation or transport is introduced. The default session pump already waits for an empty queue and did not have this edge. Red command: `cargo test -p infraternal-shim --features process-per-user changed_prediction_mode_precedes_output_after_a_state_reply --lib -- --nocapture` ``` test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 245 filtered out; finished in 0.00s ``` Same command after the narrow fix: ``` test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 245 filtered out; finished in 0.00s GREEN_PPU_EXIT=0 ``` Receipts: compute01 `~/.cache/codex-scratch/j400/evidence/{red,green}-ppu-order.log`. `verify quick` is now running there, followed by the branch binary build.
Author
Owner

Compute01 verify quick caught a missing exhaustive case for the new prediction-mode notice in the primed/hedged transport path (E0004, embedded_priming.rs). Mode changes have no snapshot cursor, so the filter now forwards each validated transition in stream order instead of treating mode bits as a monotonic sequence. Added coverage for shell → password → shell. Queued focused check, verify quick, and the real branch binary build through build-slot; no successful gate claimed yet.

Compute01 `verify quick` caught a missing exhaustive case for the new prediction-mode notice in the primed/hedged transport path (E0004, embedded_priming.rs). Mode changes have no snapshot cursor, so the filter now forwards each validated transition in stream order instead of treating mode bits as a monotonic sequence. Added coverage for shell → password → shell. Queued focused check, `verify quick`, and the real branch binary build through build-slot; no successful gate claimed yet.
Author
Owner

Found and reproduced a batched-echo epoch bug: after confirming a, input bc followed by host output b! incorrectly left epochConfirmed=true. The matching prefix had overridden the later mismatch result. Red unit receipt: 7 pass / 1 fail, expected false received true. Reconciliation now reports the entire batch invalid on any disagreement; green: 8 pass / 0 fail, 29 assertions. This also proves that expiry of the cooldown alone cannot restore prediction: a fresh exact echo is required. Restarted the 3× production browser suites on dev-02 for the changed engine.

Found and reproduced a batched-echo epoch bug: after confirming `a`, input `bc` followed by host output `b!` incorrectly left epochConfirmed=true. The matching prefix had overridden the later mismatch result. Red unit receipt: 7 pass / 1 fail, expected false received true. Reconciliation now reports the entire batch invalid on any disagreement; green: 8 pass / 0 fail, 29 assertions. This also proves that expiry of the cooldown alone cannot restore prediction: a fresh exact echo is required. Restarted the 3× production browser suites on dev-02 for the changed engine.
Author
Owner

Fresh production-browser gates after the batched-echo fix, dev-02 through build-slot:

bunx playwright test test/predictive-auto.spec.ts test/predictive-echo.spec.ts test/terminal.spec.ts --repeat-each=3
  3 skipped
  45 passed (11.3m)
SUITES_EXIT=0

INFRATERNAL_TEST_RTT=30 bunx playwright test test/predictive-auto.spec.ts --grep 'below 60'
  1 passed (3.5s)
LOW_RTT_EXIT=0

The three skips select the low-RTT case out of the 300 ms repetitions; it passed separately at 30 ms. Compute01 is still queued for the focused mode-notice regression, verify quick, and real branch binary build. Real PTY safety proof and final verify fast remain outstanding.

Fresh production-browser gates after the batched-echo fix, dev-02 through build-slot: ``` bunx playwright test test/predictive-auto.spec.ts test/predictive-echo.spec.ts test/terminal.spec.ts --repeat-each=3 3 skipped 45 passed (11.3m) SUITES_EXIT=0 INFRATERNAL_TEST_RTT=30 bunx playwright test test/predictive-auto.spec.ts --grep 'below 60' 1 passed (3.5s) LOW_RTT_EXIT=0 ``` The three skips select the low-RTT case out of the 300 ms repetitions; it passed separately at 30 ms. Compute01 is still queued for the focused mode-notice regression, `verify quick`, and real branch binary build. Real PTY safety proof and final `verify fast` remain outstanding.
Author
Owner

J400c (Claude Opus 5.5) is taking over from J400 after Codex hit its usage limit. Branch predict-auto-d130, pushed head dc82fccd2, base origin/dev 6b60f1fb7.

J400 left four fixes uncommitted in its worktrees (the batched-echo invalidation from 88243, the embedded_priming mode-notice arm from 88236, the PPU output-order hold from 88231, and the real-spec paint fences). I'll commit them atomically and push, then:

  1. dev-02: tracer unit tests, the 3× production browser suites plus the 30 ms case on the new head, and verify quick.
  2. compute01: the branch server build, the real shim end-to-end proof through the 300 ms link (sudo / read -s / ssh password / vim / htop / misprediction), and verify fast.
  3. Latency: J400's perf-VM numbers (88094) stand unless the head changes the confirmed-echo hot path. I'll rerun after/300 and after/30 if the perf VM is free.

Estimate: 2–3 h, mostly slot queues (compute01 is under its 25 G disk floor right now, with 5 busy and 2 queued).

J400c (Claude Opus 5.5) is taking over from J400 after Codex hit its usage limit. Branch `predict-auto-d130`, pushed head `dc82fccd2`, base `origin/dev` `6b60f1fb7`. J400 left four fixes uncommitted in its worktrees (the batched-echo invalidation from 88243, the `embedded_priming` mode-notice arm from 88236, the PPU output-order hold from 88231, and the real-spec paint fences). I'll commit them atomically and push, then: 1. dev-02: tracer unit tests, the 3× production browser suites plus the 30 ms case on the new head, and `verify quick`. 2. compute01: the branch server build, the real shim end-to-end proof through the 300 ms link (sudo / read -s / ssh password / vim / htop / misprediction), and `verify fast`. 3. Latency: J400's perf-VM numbers (88094) stand unless the head changes the confirmed-echo hot path. I'll rerun after/300 and after/30 if the perf VM is free. Estimate: 2–3 h, mostly slot queues (compute01 is under its 25 G disk floor right now, with 5 busy and 2 queued).
Author
Owner

Pushed 193cf3fb1 (4 atomic commits on top of dc82fccd2: batched-echo invalidation, primed-stream mode notices, PPU output-order hold, real-spec paint fences). J400's compute01 verify quick (quick-v4.log, all 12 rows PASS) ran on a tree byte-identical to this head.

Blocked on compute01 disk: / is at 100% (591G size, 566G used, 1.2G free at 05:5x IST), and a 1 KiB script write failed with No space left on device. This job's only target there is ~/worktrees/j400/target (9.9G, needed for the real proof). I am not deleting other jobs' targets. The real-shim proof and verify fast wait until space returns; I'm polling in the foreground.

Running meanwhile on dev-02 (build-slot PID 1569551): tracer unit tests, the 3× production suites at 300 ms, and the 30 ms case ×3. Log: ~/.cache/codex-scratch/j400c/evidence/suites.log.

Pushed `193cf3fb1` (4 atomic commits on top of `dc82fccd2`: batched-echo invalidation, primed-stream mode notices, PPU output-order hold, real-spec paint fences). J400's compute01 `verify quick` (quick-v4.log, all 12 rows PASS) ran on a tree byte-identical to this head. **Blocked on compute01 disk:** `/` is at 100% (591G size, 566G used, 1.2G free at 05:5x IST), and a 1 KiB script write failed with `No space left on device`. This job's only target there is `~/worktrees/j400/target` (9.9G, needed for the real proof). I am not deleting other jobs' targets. The real-shim proof and `verify fast` wait until space returns; I'm polling in the foreground. Running meanwhile on dev-02 (build-slot PID 1569551): tracer unit tests, the 3× production suites at 300 ms, and the 30 ms case ×3. Log: `~/.cache/codex-scratch/j400c/evidence/suites.log`.
Author
Owner

History rewritten, tree unchanged. J400's seven WIP: commits plus my four fixes are now three atomic commits, rebased onto origin/dev 966c52e07 (which only adds the #345 CSS/tooltip audit): 77b95cc9d host publishes eligibility from termios (shim/agent/server/contracts), b5624eca9 tracer automatic prediction with confirmed epochs (src + test double + specs), 6f8f0dadb real-shim proof spec. Before the rebase, the regrouped tree hash was byte-identical to 193cf3fb1 (5fe090440). Force-pushed with a lease; git ls-remote shows 6f8f0dadb197f5a1de2f4fa0db52d1a3600cf4b7.

Production browser suites at 6f8f0dadb (dev-02 through build-slot, 300 ms link, retries 0; 30 ms case run 3× separately):

HEAD=6f8f0dadb197f5a1de2f4fa0db52d1a3600cf4b7
 8 pass
 0 fail
UNIT_EXIT=0
  3 skipped
  45 passed (11.3m)
SUITES_EXIT=0
  3 passed (6.3s)
LOW_RTT_EXIT=0

Commands: bun test src/predictive-echo.test.ts; bunx playwright test test/predictive-auto.spec.ts test/predictive-echo.spec.ts test/terminal.spec.ts --repeat-each=3; INFRATERNAL_TEST_RTT=30 bunx playwright test test/predictive-auto.spec.ts --grep "below 60" --repeat-each=3. Receipt: dev-02 ~/.cache/codex-scratch/j400c/evidence/suites.log, screenshots under evidence/suites-300/.

Side note: my first restart failed with localhost:5470/health is already used. Killing the obsolete playwright with TERM left its webServer group (latency proxy + mock server, PGID 1577659) alive. I killed that exact PGID; receipt suites-port-busy.log.

Next: the real-shim proof on compute01 (queue head, PID 3683548; 3 runs, private non-root sshd on 127.0.0.1:5422 for the ssh prompt), the latency remeasure at the final head on the perf VM (waiting for the perf-run lock), then verify fast on compute01.

**History rewritten, tree unchanged.** J400's seven `WIP:` commits plus my four fixes are now three atomic commits, rebased onto `origin/dev` `966c52e07` (which only adds the #345 CSS/tooltip audit): `77b95cc9d` host publishes eligibility from termios (shim/agent/server/contracts), `b5624eca9` tracer automatic prediction with confirmed epochs (src + test double + specs), `6f8f0dadb` real-shim proof spec. Before the rebase, the regrouped tree hash was byte-identical to `193cf3fb1` (`5fe090440`). Force-pushed with a lease; `git ls-remote` shows `6f8f0dadb197f5a1de2f4fa0db52d1a3600cf4b7`. **Production browser suites at `6f8f0dadb`** (dev-02 through build-slot, 300 ms link, retries 0; 30 ms case run 3× separately): ``` HEAD=6f8f0dadb197f5a1de2f4fa0db52d1a3600cf4b7 8 pass 0 fail UNIT_EXIT=0 3 skipped 45 passed (11.3m) SUITES_EXIT=0 3 passed (6.3s) LOW_RTT_EXIT=0 ``` Commands: `bun test src/predictive-echo.test.ts`; `bunx playwright test test/predictive-auto.spec.ts test/predictive-echo.spec.ts test/terminal.spec.ts --repeat-each=3`; `INFRATERNAL_TEST_RTT=30 bunx playwright test test/predictive-auto.spec.ts --grep "below 60" --repeat-each=3`. Receipt: dev-02 `~/.cache/codex-scratch/j400c/evidence/suites.log`, screenshots under `evidence/suites-300/`. Side note: my first restart failed with `localhost:5470/health is already used`. Killing the obsolete playwright with TERM left its webServer group (latency proxy + mock server, PGID 1577659) alive. I killed that exact PGID; receipt `suites-port-busy.log`. Next: the real-shim proof on compute01 (queue head, PID 3683548; 3 runs, private non-root sshd on 127.0.0.1:5422 for the ssh prompt), the latency remeasure at the final head on the perf VM (waiting for the perf-run lock), then `verify fast` on compute01.
Author
Owner

Real-shim proof on compute01: two fixture bugs found and fixed. The product behaved correctly both times.

Run 1 (6f8f0dadb; receipt compute01 ~/.cache/codex-scratch/j400c/evidence/real-run1-mode-log-missing.log):

D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300
D130_REAL password_prompt=read-s predictions=0 PASS
Expected: {"canonical": true, "echo": false}
Received: undefined

The bridge created its mode log only under the unrelated REAL_EVENT_TIMES=1 switch. Fixed in 6c89655f3 (explicit recordPredictionModes option).

Run 2 (6c89655f3; receipt real-run2-sudo-reprompt.log): the sudo mode check now passes (the shim reported canonical no-echo). The way back then hung:

D130_SUDO:
Sorry, try again.
D130_SUDO:

At sudo's PAM prompt, Ctrl+C counts as a failed try. sudo flushes typeahead and re-prompts, so the printf BACK command was discarded. Fixed in 7e3979382: the spec presses Ctrl+C until D130> is painted again (bounded polls, no fixed sleep). The assertion is unchanged.

Latency remeasured at the final tracer head (perf VM via perf-run, cpus 1–3, 0 steal; production renderer, keydown to first visible frame, 3×30 serialized keys per case, zero-jitter TCP profile, no ?predict override; before = J400's origin/dev frontend dist):

RTT Before p50 / p99 After p50 / p99 After predicted
300 ms 315.7 / 315.9 ms 14.9 / 15.1 ms 90/90
30 ms 32.4 / 49.1 ms 32.4 / 49.1 ms 0/90

CPU p99 (onData→wsSend): 300 ms 0.3 → 0.1 ms, 30 ms 0.2 → 0.2 ms. Receipts: perf VM ~/.cache/codex-scratch/j400c/evidence/{latency-summary.json,measure.log,latency-*.json,perf-run/}; summary also on code at the same path. The real/ commits since then change no tracer runtime code.

The real run at 7e3979382 is queued on compute01 (14 runs queued), then verify fast.

**Real-shim proof on compute01: two fixture bugs found and fixed. The product behaved correctly both times.** Run 1 (`6f8f0dadb`; receipt compute01 `~/.cache/codex-scratch/j400c/evidence/real-run1-mode-log-missing.log`): ``` D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300 D130_REAL password_prompt=read-s predictions=0 PASS Expected: {"canonical": true, "echo": false} Received: undefined ``` The bridge created its mode log only under the unrelated `REAL_EVENT_TIMES=1` switch. Fixed in `6c89655f3` (explicit `recordPredictionModes` option). Run 2 (`6c89655f3`; receipt `real-run2-sudo-reprompt.log`): the sudo mode check now passes (the shim reported canonical no-echo). The way back then hung: ``` D130_SUDO: Sorry, try again. D130_SUDO: ``` At sudo's PAM prompt, Ctrl+C counts as a failed try. sudo flushes typeahead and re-prompts, so the `printf BACK` command was discarded. Fixed in `7e3979382`: the spec presses Ctrl+C until `D130> ` is painted again (bounded polls, no fixed sleep). The assertion is unchanged. **Latency remeasured at the final tracer head** (perf VM via `perf-run`, cpus 1–3, 0 steal; production renderer, keydown to first visible frame, 3×30 serialized keys per case, zero-jitter TCP profile, no `?predict` override; before = J400's origin/dev frontend dist): | RTT | Before p50 / p99 | After p50 / p99 | After predicted | | --- | --- | --- | --- | | 300 ms | 315.7 / 315.9 ms | 14.9 / 15.1 ms | 90/90 | | 30 ms | 32.4 / 49.1 ms | 32.4 / 49.1 ms | 0/90 | CPU p99 (onData→wsSend): 300 ms 0.3 → 0.1 ms, 30 ms 0.2 → 0.2 ms. Receipts: perf VM `~/.cache/codex-scratch/j400c/evidence/{latency-summary.json,measure.log,latency-*.json,perf-run/}`; summary also on code at the same path. The `real/` commits since then change no tracer runtime code. The real run at `7e3979382` is queued on compute01 (14 runs queued), then `verify fast`.
Author
Owner

Real-shim proof PASS 3/3 at dc9e4db87 on compute01: real branch server (target/debug/infraternal), real shim and PTY, production tracer build, Chromium, 150 ms each way (300 ms RTT) bridge, no ?predict override, retries 0. The ssh prompt comes from a private non-root sshd on 127.0.0.1:5422 (UsePAM no, so it cannot authenticate; no valid password is ever typed). sudo prompts for real: claude has no NOPASSWD on compute01.

Run 1 of 3, verbatim (runs 2 and 3 are identical apart from the times):

Running 1 test using 1 worker

D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300
D130_REAL password_prompt=read-s predictions=0 PASS
D130_REAL password_prompt=sudo predictions=0 PASS
D130_REAL password_prompt=ssh predictions=0 PASS
D130_REAL alternate_screen=vim predictions=0 PASS
D130_REAL alternate_screen=htop predictions=0 PASS
D130_REAL forced_misprediction=PASS next_key_prediction=hidden
  ✓  1 real/predictive-auto.spec.ts:65:1 › D130 real shim gates shell predictions, password prompts and alternate-screen programs (21.6s)

  1 passed (22.8s)
REAL_RUN_1_EXIT=0
Running 1 test using 1 worker

D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300
D130_REAL password_prompt=read-s predictions=0 PASS
D130_REAL password_prompt=sudo predictions=0 PASS
D130_REAL password_prompt=ssh predictions=0 PASS
D130_REAL alternate_screen=vim predictions=0 PASS
D130_REAL alternate_screen=htop predictions=0 PASS
D130_REAL forced_misprediction=PASS next_key_prediction=hidden
  ✓  1 real/predictive-auto.spec.ts:65:1 › D130 real shim gates shell predictions, password prompts and alternate-screen programs (22.3s)

  1 passed (23.4s)
REAL_RUN_2_EXIT=0

Running 1 test using 1 worker

D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300
D130_REAL password_prompt=read-s predictions=0 PASS
D130_REAL password_prompt=sudo predictions=0 PASS
D130_REAL password_prompt=ssh predictions=0 PASS
D130_REAL alternate_screen=vim predictions=0 PASS
D130_REAL alternate_screen=htop predictions=0 PASS
D130_REAL forced_misprediction=PASS next_key_prediction=hidden
  ✓  1 real/predictive-auto.spec.ts:65:1 › D130 real shim gates shell predictions, password prompts and alternate-screen programs (21.3s)

  1 passed (22.4s)
REAL_RUN_3_EXIT=0
REAL_EXIT=0
SSHD_STOPPED=2840419

Tail: REAL_RUN_2_EXIT=0, REAL_RUN_3_EXIT=0, REAL_EXIT=0, SSHD_STOPPED=2840419 (sshd stopped by its recorded PID).

What each line proves: shell keys are predicted automatically once the first exact echo arrives. At read -s, sudo and the ssh password prompt, the host reported {echo:false, canonical:true} for sudo and ssh, and "xy" typed at each prompt produced 0 overlay appearances. The counter is a MutationObserver that also catches an overlay hidden again within the same frame. vim and htop on the alternate screen: 0. A raw program that echoes a and then mis-echoes b as !: b was drawn (confirmed epoch), and c stayed hidden (back-off). Screenshots attached. Receipt: compute01 ~/.cache/codex-scratch/j400c/evidence/real.log and real-300/; failed earlier runs are kept as real-run{1,2,3}-*.log.

Branch rebased onto origin/dev 4754b14a7 (dev added D373–D376, host Forget and remote removal; nothing in the terminal, shim or prediction path, and a clean rebase). Head b28cb7492. verify fast is queued on compute01; verify quick is queued on dev-02.

Note for the orchestrator, from D375 (added today): the 120 Hz target for "key to letter on screen, prediction on" is 8.3 ms p99. This branch measures 14.9 / 15.1 ms p50/p99 in the perf-VM harness, where headless Chromium paces animation frames at 60 Hz (16.7 ms). So the number is "next 60 Hz frame", and this harness cannot show a 120 Hz frame. Meeting or measuring D375 needs a 120 Hz frame source (the Mac VM per the frame-performance rule). That is outside #441's scope; I have not changed any rendering.

**Real-shim proof PASS 3/3** at `dc9e4db87` on compute01: real branch server (`target/debug/infraternal`), real shim and PTY, production tracer build, Chromium, 150 ms each way (300 ms RTT) bridge, no `?predict` override, retries 0. The ssh prompt comes from a private non-root sshd on 127.0.0.1:5422 (`UsePAM no`, so it cannot authenticate; no valid password is ever typed). sudo prompts for real: `claude` has no NOPASSWD on compute01. Run 1 of 3, verbatim (runs 2 and 3 are identical apart from the times): ``` Running 1 test using 1 worker D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300 D130_REAL password_prompt=read-s predictions=0 PASS D130_REAL password_prompt=sudo predictions=0 PASS D130_REAL password_prompt=ssh predictions=0 PASS D130_REAL alternate_screen=vim predictions=0 PASS D130_REAL alternate_screen=htop predictions=0 PASS D130_REAL forced_misprediction=PASS next_key_prediction=hidden ✓ 1 real/predictive-auto.spec.ts:65:1 › D130 real shim gates shell predictions, password prompts and alternate-screen programs (21.6s) 1 passed (22.8s) REAL_RUN_1_EXIT=0 Running 1 test using 1 worker D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300 D130_REAL password_prompt=read-s predictions=0 PASS D130_REAL password_prompt=sudo predictions=0 PASS D130_REAL password_prompt=ssh predictions=0 PASS D130_REAL alternate_screen=vim predictions=0 PASS D130_REAL alternate_screen=htop predictions=0 PASS D130_REAL forced_misprediction=PASS next_key_prediction=hidden ✓ 1 real/predictive-auto.spec.ts:65:1 › D130 real shim gates shell predictions, password prompts and alternate-screen programs (22.3s) 1 passed (23.4s) REAL_RUN_2_EXIT=0 Running 1 test using 1 worker D130_REAL automatic_shell_prediction=PASS override=absent rtt_profile_ms=300 D130_REAL password_prompt=read-s predictions=0 PASS D130_REAL password_prompt=sudo predictions=0 PASS D130_REAL password_prompt=ssh predictions=0 PASS D130_REAL alternate_screen=vim predictions=0 PASS D130_REAL alternate_screen=htop predictions=0 PASS D130_REAL forced_misprediction=PASS next_key_prediction=hidden ✓ 1 real/predictive-auto.spec.ts:65:1 › D130 real shim gates shell predictions, password prompts and alternate-screen programs (21.3s) 1 passed (22.4s) REAL_RUN_3_EXIT=0 REAL_EXIT=0 SSHD_STOPPED=2840419 ``` Tail: `REAL_RUN_2_EXIT=0`, `REAL_RUN_3_EXIT=0`, `REAL_EXIT=0`, `SSHD_STOPPED=2840419` (sshd stopped by its recorded PID). What each line proves: shell keys are predicted automatically once the first exact echo arrives. At `read -s`, `sudo` and the ssh password prompt, the host reported `{echo:false, canonical:true}` for sudo and ssh, and "xy" typed at each prompt produced 0 overlay appearances. The counter is a MutationObserver that also catches an overlay hidden again within the same frame. vim and htop on the alternate screen: 0. A raw program that echoes `a` and then mis-echoes `b` as `!`: `b` was drawn (confirmed epoch), and `c` stayed hidden (back-off). Screenshots attached. Receipt: compute01 `~/.cache/codex-scratch/j400c/evidence/real.log` and `real-300/`; failed earlier runs are kept as `real-run{1,2,3}-*.log`. Branch rebased onto `origin/dev` `4754b14a7` (dev added D373–D376, host Forget and remote removal; nothing in the terminal, shim or prediction path, and a clean rebase). Head `b28cb7492`. `verify fast` is queued on compute01; `verify quick` is queued on dev-02. **Note for the orchestrator, from D375 (added today):** the 120 Hz target for "key to letter on screen, prediction on" is 8.3 ms p99. This branch measures 14.9 / 15.1 ms p50/p99 in the perf-VM harness, where headless Chromium paces animation frames at 60 Hz (16.7 ms). So the number is "next 60 Hz frame", and this harness cannot show a 120 Hz frame. Meeting or measuring D375 needs a 120 Hz frame source (the Mac VM per the frame-performance rule). That is outside #441's scope; I have not changed any rendering.
Author
Owner

verify fast at b28cb7492 (compute01): one real finding, in a test fixture. The test row failed in saturated_terminal_queues_preserve_every_byte_and_daemon_liveness. Its Python oracle (scripts/agent_fixture.py) treats every terminal-stream event as a replay marker:

AssertionError: {'type': 'terminal.prediction_mode', 'session_id': '…', 'echo': False, 'canonical': False}

Every other row passed, including static builds. Verbatim table:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| Nix Cargo vendoring       | PASS         |
| fmt                       | PASS         |
| migration names           | PASS         |
| migration tooling tests   | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| Traefik component manifest | PASS         |
| release component publication | PASS         |
| test                      | FAIL (101)   |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| doc coverage ratchet      | PASS         |
| shape lints off (D351)    | PASS         |
| doc comments on diff      | PASS         |
| fixed test waits          | PASS         |
| privileged integration    | PASS         |
| probe release exclusion   | PASS         |
| nightly fuzz reporter     | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+
VERIFY_EXIT=1

Fixed in 3a19e0ed0: the fixture validates the notice strictly (same session, exactly four keys, boolean bits), records it in prediction_modes, and keeps it out of events. That way the oracles that assert no events or count them (verify-vt-credit, verify-agent-snapshot) don't start depending on PTY mode timing.

cargo test stops at the first failing binary, so a --no-fail-fast workspace run at 3a19e0ed0 is queued on compute01 to surface any other test that assumes the old event set. The final verify fast follows. Receipt: compute01 ~/.cache/codex-scratch/j400c/evidence/fast-b28cb7492.log. verify quick at b28cb7492 (dev-02): all 12 rows PASS (evidence/quick.log).

**`verify fast` at `b28cb7492` (compute01): one real finding, in a test fixture.** The `test` row failed in `saturated_terminal_queues_preserve_every_byte_and_daemon_liveness`. Its Python oracle (`scripts/agent_fixture.py`) treats every terminal-stream event as a replay marker: ``` AssertionError: {'type': 'terminal.prediction_mode', 'session_id': '…', 'echo': False, 'canonical': False} ``` Every other row passed, including static builds. Verbatim table: ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | Nix Cargo vendoring | PASS | | fmt | PASS | | migration names | PASS | | migration tooling tests | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | Traefik component manifest | PASS | | release component publication | PASS | | test | FAIL (101) | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | doc coverage ratchet | PASS | | shape lints off (D351) | PASS | | doc comments on diff | PASS | | fixed test waits | PASS | | privileged integration | PASS | | probe release exclusion | PASS | | nightly fuzz reporter | PASS | | static builds | PASS | +---------------------------+--------------+ VERIFY_EXIT=1 ``` Fixed in `3a19e0ed0`: the fixture validates the notice strictly (same session, exactly four keys, boolean bits), records it in `prediction_modes`, and keeps it out of `events`. That way the oracles that assert no events or count them (`verify-vt-credit`, `verify-agent-snapshot`) don't start depending on PTY mode timing. `cargo test` stops at the first failing binary, so a `--no-fail-fast` workspace run at `3a19e0ed0` is queued on compute01 to surface any other test that assumes the old event set. The final `verify fast` follows. Receipt: compute01 `~/.cache/codex-scratch/j400c/evidence/fast-b28cb7492.log`. `verify quick` at `b28cb7492` (dev-02): all 12 rows PASS (`evidence/quick.log`).
Author
Owner

cargo test --workspace --locked --no-fail-fast at 3a19e0ed0 (compute01; receipt ~/.cache/codex-scratch/j400c/evidence/test-nff.log, TEST_EXIT=101) surfaced every test binary the gate's fail-fast test row never reached. 13 failures in total:

  • 1 branch-caused: initial_attach_requires_explicit_credit_before_replay: verify-agent-attach-credit.py → AssertionError: unfunded attach emitted frame 0x33. The new mode notice is attach metadata. It is not output and spends no credit, so the product behaviour is intended. The oracle now still allows only Acks before Credit, plus a strictly validated mode notice; Output, Snapshot and any other event still fail. Folded into the fixture commit, now ae253d847.
  • 12 artifacts of my ad-hoc run, not the branch: release plugin latest/review_pool/review_restart, the server's review_revocation_r2, release_manifest, release_payload and the desktop native_surface test all panic at std::env::var_os("CARGO_TARGET_DIR").unwrap() / "use the job target directory". scripts/verify sets that variable; my bare cargo test did not. The same tests pass inside verify fast's test row.

The final verify fast at ae253d847 is queued on compute01 (position 16).

**`cargo test --workspace --locked --no-fail-fast` at `3a19e0ed0`** (compute01; receipt `~/.cache/codex-scratch/j400c/evidence/test-nff.log`, `TEST_EXIT=101`) surfaced every test binary the gate's fail-fast `test` row never reached. 13 failures in total: - **1 branch-caused:** `initial_attach_requires_explicit_credit_before_replay`: `verify-agent-attach-credit.py` → `AssertionError: unfunded attach emitted frame 0x33`. The new mode notice is attach metadata. It is not output and spends no credit, so the product behaviour is intended. The oracle now still allows only Acks before Credit, plus a strictly validated mode notice; Output, Snapshot and any other event still fail. Folded into the fixture commit, now `ae253d847`. - **12 artifacts of my ad-hoc run, not the branch:** `release` plugin latest/review_pool/review_restart, the server's `review_revocation_r2`, `release_manifest`, `release_payload` and the desktop `native_surface` test all panic at `std::env::var_os("CARGO_TARGET_DIR").unwrap()` / "use the job target directory". `scripts/verify` sets that variable; my bare `cargo test` did not. The same tests pass inside `verify fast`'s `test` row. The final `verify fast` at `ae253d847` is queued on compute01 (position 16).
Author
Owner

verify fast at ae253d847 (compute01): every row PASS, including test (with both fixture fixes) and static builds, except cargo-deny:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| Nix Cargo vendoring       | PASS         |
| fmt                       | PASS         |
| migration names           | PASS         |
| migration tooling tests   | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| Traefik component manifest | PASS         |
| release component publication | PASS         |
| test                      | PASS         |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | FAIL (1)     |
| gate architecture         | PASS         |
| doc coverage ratchet      | PASS         |
| shape lints off (D351)    | PASS         |
| doc comments on diff      | PASS         |
| fixed test waits          | PASS         |
| privileged integration    | PASS         |
| probe release exclusion   | PASS         |
| nightly fuzz reporter     | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+
VERIFY_EXIT=1

error[vulnerability]: libsqlite3-sys via C SQLite CVE-2026-119375 (RUSTSEC-2026-0459, libsqlite3-sys 0.30.1). The branch changes no Cargo manifest. dev handled this since my base: ba79e6746 (#473) adds a time-limited deny.toml exception, and cargo deny check on untouched origin/dev 198c4a736 prints advisories ok, bans ok, licenses ok, sources ok (receipt evidence/deny-origin-dev.log).

Correction to my previous comment: the 12 CARGO_TARGET_DIR failures from the ad-hoc run are now proven to pass inside verify fast (its test row is PASS above). Until this run they had not been reached.

Rebased onto origin/dev 198c4a736. dev added libghostty-vt 1.0 (#419), #442 (spec fixes, sign-out), OSC 52 and touch selection, and touches four files this branch also changes: terminal.ts, mock-server.ts, main.ts, user_host.rs. The only conflict was a doc comment in main.ts (kept dev's). The new head is 949b0ae13. The earlier receipts were taken on the old base, so I'm rerunning all of them on the new head: the 3× suites plus the 30 ms case (dev-02, queued), the real-shim proof ×3 (compute01, queued), then verify quick and verify fast.

**`verify fast` at `ae253d847` (compute01):** every row PASS, including `test` (with both fixture fixes) and static builds, except `cargo-deny`: ``` +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | Nix Cargo vendoring | PASS | | fmt | PASS | | migration names | PASS | | migration tooling tests | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | Traefik component manifest | PASS | | release component publication | PASS | | test | PASS | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | FAIL (1) | | gate architecture | PASS | | doc coverage ratchet | PASS | | shape lints off (D351) | PASS | | doc comments on diff | PASS | | fixed test waits | PASS | | privileged integration | PASS | | probe release exclusion | PASS | | nightly fuzz reporter | PASS | | static builds | PASS | +---------------------------+--------------+ VERIFY_EXIT=1 ``` `error[vulnerability]: libsqlite3-sys via C SQLite CVE-2026-119375` (RUSTSEC-2026-0459, `libsqlite3-sys 0.30.1`). The branch changes no Cargo manifest. dev handled this since my base: `ba79e6746` (#473) adds a time-limited `deny.toml` exception, and `cargo deny check` on untouched `origin/dev` `198c4a736` prints `advisories ok, bans ok, licenses ok, sources ok` (receipt `evidence/deny-origin-dev.log`). Correction to my previous comment: the 12 `CARGO_TARGET_DIR` failures from the ad-hoc run are now proven to pass inside `verify fast` (its `test` row is PASS above). Until this run they had not been reached. **Rebased onto `origin/dev` `198c4a736`.** dev added libghostty-vt 1.0 (#419), #442 (spec fixes, sign-out), OSC 52 and touch selection, and touches four files this branch also changes: `terminal.ts`, `mock-server.ts`, `main.ts`, `user_host.rs`. The only conflict was a doc comment in `main.ts` (kept dev's). The new head is `949b0ae13`. The earlier receipts were taken on the old base, so I'm rerunning all of them on the new head: the 3× suites plus the 30 ms case (dev-02, queued), the real-shim proof ×3 (compute01, queued), then `verify quick` and `verify fast`.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#441
No description provided.