fix(cli-registry): merge-time fixes for the run-menu consolidation (#458)

- 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)
This commit is contained in:
Codeman maintainer
2026-09-21 04:37:45 +02:00
parent d3f2ec0220
commit 0f955327b2
8 changed files with 280 additions and 23 deletions
+22 -12
View File
@@ -68,23 +68,33 @@ describe('OpenCode session initial resize', () => {
({ context, page } = await freshPage());
await navigateAndWait(page);
const hasPreAssignment = await page.evaluate(() => {
const { selectIdx, assignIdx } = await page.evaluate(() => {
const app = (window as unknown as { app: { _runCliMode: { toString: () => string } } }).app;
const source = app._runCliMode.toString();
// Check: the source should NOT have activeSessionId = ... before selectSession
// Find positions of both patterns
const assignIdx = source.indexOf('this.activeSessionId = data.sessionId');
const selectIdx = source.indexOf('this.selectSession(data.sessionId)');
// If assign doesn't exist at all, that's the correct fix
if (assignIdx === -1) return false;
// If assign comes before select, that's the bug
return assignIdx < selectIdx;
// The launcher hands the FIRST created session to selectSession
// (`_launchQuickStartInstances()` returns `firstSessionId`). An earlier
// version of this check looked for `this.selectSession(data.sessionId)`,
// a string that exists nowhere in session-ui.js, so both lookups came
// back -1 and the assertion could never fail. Hence the anti-vacuity
// check below: the select call itself must be found.
const selectIdx = source.indexOf('this.selectSession(firstSessionId)');
// ANY assignment to activeSessionId (whatever the right-hand side is
// called), not `==`/`===` comparisons and not the comment that mentions
// pre-setting it without a `this.` prefix.
const assign = /this\.activeSessionId\s*=(?!=)/.exec(source);
return { selectIdx, assignIdx: assign ? assign.index : -1 };
});
expect(hasPreAssignment).toBe(false);
// Anti-vacuity: if the select call is renamed again, fail here rather
// than pass on two -1s.
expect(selectIdx).toBeGreaterThan(-1);
// Correct: no assignment at all. Bug: an assignment that lands BEFORE
// selectSession runs, which makes selectSession early-return.
expect(
assignIdx === -1 || assignIdx > selectIdx,
`activeSessionId is assigned at ${assignIdx}, before selectSession at ${selectIdx}`
).toBe(true);
});
it('sends resize to server after creating a session via quick-start', async () => {