- test/opencode-resize.test.ts: retarget the launcher guard at the real code (this.selectSession(firstSessionId), any this.activeSessionId assignment) with an anti-vacuity check; the old strings existed nowhere, so it could never fail
- session-ui.js: restore as comments the two invariants the merged bodies lost (deepseek leaves statusReporting unset, i.e. ON; no effort field for external CLIs, it is Claude-specific)
- docs/cli-registry.md: move the frontend-guard paragraph below the two backend-guard paragraphs so they keep their antecedent, and note the widened comparison shape
- test/frontend-cli-no-id-branching.test.ts: the comparison shape accepts any left-hand identifier (const m = this._runMode; m === 'codex' was invisible), normalized to `mode`; the two `m !== 'shell'` display filters are allowlisted and the remaining blind spots documented
- test/run-mode-dispatch.test.ts: table-driven pin of run() dispatch (claude to runClaude, each RUN_MODE_LAUNCH id to _runCliMode(id), shell to runShell, unknown to runClaude, lock held and released)
- CLAUDE.md: name the second CI-gated guard next to the backend one
- server.ts: every </head> injection passes a replacer function; a clis.json label containing $' re-injected the rest of the document past escapeScriptJson (two render tests pin it, proven failing on the string form)
- _isAltCliMode(): no reference anywhere in the tree, nothing to fix
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 1ea363ff808a62861559bc141e724b163cc1c56e)
Two required fixes from Ark0N's review of #458:
1. test/frontend-cli-no-id-branching.test.ts's ALLOWED_BRANCHES keyed on
<file>::<line>::<expression>. A single inserted line anywhere above an
entry shifted every subsequent line number, so all 21 entries went stale
simultaneously and the same 21 branches were reported as "new" — on a
file six other open PRs also touch. Dropped the line number from the key
(<file>::<expression>, matching the backend guard's own design), which
collapses 21 line-keyed entries to 11 or-collapse where the same
expression recurs at multiple call sites in the same file.
2. test/run-mode-ui.test.ts's terminal-ownership guard scanned method
bodies via `^ {2}async (run[A-Za-z]*)\(\) \{$`, which matched the 8
one-line run<Mode>() wrappers PR B2 introduced but not _runCliMode(mode),
where the real logic (and the actual risk the guard exists to catch) now
lives. Fixed the regex to `^ {2}async (_?run[A-Za-z]*)\(\w*\) \{$` and
added _runCliMode to the sanity list. Same-class fix in
test/opencode-resize.test.ts, which had the identical blind spot via
runOpenCode.toString().
Both reproduced live before fixing (inserted the same comment line; added
this.terminal.clear() to _runCliMode) to confirm the bug, then confirmed
the fix catches it and the suite stays green otherwise.
Also resolves Open Question 2 by dropping window.__codemanCliCatalog
entirely: nothing consumed it, and a registry DECLARED_FOR_LATER field
costs nothing until read while an unconsumed script tag on every page
render is a different trade. Reverts Phase 1 cleanly — server.ts's
injection, shortBadge back in types.ts's DECLARED_FOR_LATER list and the
pinned guard test, and the three associated render-index-html.test.ts /
server-index-title.test.ts assertions.
Full gate: 405 files / 7717 tests / 0 failures (net unchanged), typecheck/
lint/format clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GuHtuPiHXdykq9T6rKQJ9n
- Add _isStopped guard to OpenCode 3s readiness timeout (session.ts)
- Block respawn for opencode sessions on interactive-respawn and
respawn/enable routes (server.ts)
- Fail fast in direct PTY fallback for OpenCode mode (session.ts)
- Validate configContent as JSON at schema level (schemas.ts)
- Update JSDoc example for createSession options API (tmux-manager.ts)
- Un-hide Context tab for OpenCode sessions (index.html)
- Add OpenCode UI tests (opencode-resize.test.ts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>