feat(predictive-echo): Codeman integration + Layer 4 vm tests

terminal-ui.js: _localEchoPolicy ('buffer'|'predict'|'off') computed at the
end of _updateLocalEchoState with _localEchoEnabled keeping its exact 1.12.2
values; _predictHookOnData called as a plain statement between the buffer
block and Normal Mode (visual-only, try/catch, never returns, never touches
_pendingInput); classifyPredictInput + isCodexComposerRow (baseY-based,
measured /^> /-signature gate) on CodemanTerminalInput; construction beside
the LocalEchoOverlay from the separate bundle with graceful absence;
insertTerminalText/clearTerminalInput/setFontSize/applyTerminalSkin clear or
refresh predictions. app.js: fields + tab-switch and SSE-reconnect clears.
voice-input '\r' branch and keyboard-accessory sendKey clear predictions
(both bypass onData). sendEnterKey needs no change: codex falls through to
the immediate-flush branch.

Layer 4 vm tests: classify truth table (20 cases), composer-row gate incl.
the baseY pin, policy matrix with the 1.12.2 invariants untouched, wire
neutrality + throwing-predictor pins. Stale mobile keyboard codex-buffering
tests repointed at claude; new codex twin asserts write-through streaming,
prediction spans and TTL self-heal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-08-09 04:33:09 +02:00
parent 6c55ce3f8d
commit 5bde897752
6 changed files with 390 additions and 4 deletions
+10
View File
@@ -699,6 +699,10 @@ class CodemanApp {
// (not at buffer.cursorY, which reflects Ink's internal cursor position)
this._localEchoOverlay = null; // created after terminal.open()
this._localEchoEnabled = false; // true when setting on + session active
// Predictive write-through echo (codex) — created after terminal.open()
// from the separate vendor/xterm-predictive-echo.js bundle (may stay null)
this._predictiveEcho = null;
this._localEchoPolicy = 'off'; // 'buffer' | 'predict' | 'off' (per active session)
this._restoringFlushedState = false; // true during selectSession buffer load — protects flushed Maps
// Accessibility: Focus trap for modals
@@ -3021,6 +3025,9 @@ class CodemanApp {
// terminal buffer reloads and prompt is visible again. _render() re-scans
// for the ❯ prompt on every call, so rerender() after buffer load repositions it.
this._localEchoOverlay?.rerender();
// Deliberate asymmetry: buffer-mode pending text SURVIVES reconnect (not
// yet sent); predictions do not (their keystrokes were already delivered).
this._predictiveEcho?.clearPredictions();
// Clear pending hooks
this.pendingHooks.clear();
// Clear parent name cache (prevents stale session name entries accumulating)
@@ -4127,6 +4134,9 @@ class CodemanApp {
}
}
this._localEchoOverlay?.clear();
// Predictions are ephemeral + already sent: nothing to save/restore
// across a tab switch (unlike the buffer overlay's setFlushed machinery)
this._predictiveEcho?.clearPredictions();
// Prevent _detectBufferText() from picking up Claude's Ink UI text
// (status bar, model info, etc.) as "user input" on fresh sessions.
// Only sessions with prior flushed text (from tab-switch-away) need detection.