mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-13 18:29:32 +01:00
Measured on 1.47.0 with the same "spawn a shell worker, echo, read, delete" task: DeepSeek Harness and OpenCode already pass end to end; Codex 0.162 failed three ways, fixed here. - Start Codex 0.162+ with --no-daemon (new noDaemonFlag gate, fail-closed). The shared app-server daemon stopped every launch on an "incompatible feature settings" dialog when another version's daemon was running, and ran commands with another session's CODEMAN_* environment. - Evaluate registry version gates against the gated CLI's own version (resolveSessionCliVersion) instead of claude's for every entry. - Add the opt-in synced setting App Settings > Codex > Allow network access (codexNetworkAccess, default off): --config sandbox_workspace_write.network_access=true, filled as a launch default and clamped off for non-granted owners like the bypass switch. - Skill: carry on with the curl path when `codeman` is not on PATH, re-run a sandbox-blocked call once through the CLI's approval path, name the new setting. Wiki and registry docs updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
/**
|
|
* @fileoverview A launch gate is measured against its OWN CLI's version.
|
|
*
|
|
* `capabilities.gates` used to be resolved with `getClaudeCliVersion()` for every entry,
|
|
* because claude was the only CLI with a gate. Codex's `noDaemonFlag` (0.162.0) would then
|
|
* have passed on any claude 2.x and handed an older codex `--no-daemon`, which makes codex
|
|
* exit on launch. The bridge now asks `resolveSessionCliVersion(entry.id)`; this pins that
|
|
* with both resolvers mocked to DIFFERENT versions.
|
|
*/
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
const versions: Record<string, string | null> = {};
|
|
|
|
vi.mock('../src/utils/cli-resolver.js', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('../src/utils/cli-resolver.js')>();
|
|
return { ...actual, resolveSessionCliVersion: vi.fn((mode: string) => versions[mode] ?? null) };
|
|
});
|
|
vi.mock('../src/utils/claude-cli-resolver.js', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('../src/utils/claude-cli-resolver.js')>();
|
|
return { ...actual, getClaudeCliVersion: vi.fn(() => '2.1.316') };
|
|
});
|
|
|
|
const { getCli } = await import('../src/config/cli-registry/registry.js');
|
|
const { buildSpawnCommandFromRegistry, launchGatePasses } = await import('../src/session-cli-registry-bridge.js');
|
|
|
|
const SID = '00000000-0000-4000-8000-000000000000';
|
|
|
|
function codexCommand(): string | undefined {
|
|
return buildSpawnCommandFromRegistry(getCli('codex')!, { mode: 'codex', sessionId: SID });
|
|
}
|
|
|
|
describe('launch gates read the gated CLI version', () => {
|
|
beforeEach(() => {
|
|
for (const key of Object.keys(versions)) delete versions[key];
|
|
});
|
|
|
|
it("does not pass codex's gate on claude's version", () => {
|
|
versions.claude = '2.1.316';
|
|
versions.codex = '0.161.0';
|
|
expect(codexCommand()).toBe('codex');
|
|
expect(launchGatePasses('codex', 'noDaemonFlag')).toBe(false);
|
|
});
|
|
|
|
it("passes codex's gate on codex's own version", () => {
|
|
versions.codex = '0.162.0';
|
|
expect(codexCommand()).toBe('codex --no-daemon');
|
|
expect(launchGatePasses('codex', 'noDaemonFlag')).toBe(true);
|
|
});
|
|
|
|
it('fails closed when the codex version is unknown', () => {
|
|
versions.claude = '2.1.316';
|
|
expect(codexCommand()).toBe('codex');
|
|
});
|
|
|
|
it("still measures claude's gates on claude's version", () => {
|
|
versions.claude = '2.1.316';
|
|
versions.codex = '0.1.0';
|
|
expect(launchGatePasses('claude', 'nameFlag')).toBe(true);
|
|
});
|
|
});
|