feat(browser): add explicit runtime policy controls

This commit is contained in:
Tam Nhu Tran committed 2026-04-20 21:01:19 -04:00
1 parent d6c45fef04
commit 7d02f55f9f
25 files changed
+795 -50

No files matched your search

@@ -205,11 +205,13 @@ process.exit(0);
config.browser = {
claude: {
enabled: false,
policy: 'auto',
user_data_dir: '',
devtools_port: 9222,
},
codex: {
enabled: false,
policy: 'auto',
},
};
});
@@ -235,6 +237,114 @@ process.exit(0);
}
});
it('keeps Codex browser MCP overrides off by default when policy is manual', () => {
if (process.platform === 'win32') return;
const originalCcsHome = process.env.CCS_HOME;
process.env.CCS_HOME = tmpHome;
try {
mutateUnifiedConfig((config) => {
config.browser = {
claude: {
enabled: false,
policy: 'auto',
user_data_dir: '',
devtools_port: 9222,
},
codex: {
enabled: true,
policy: 'manual',
},
};
});
const result = runCcs(['default', '--target', 'codex', 'fix failing tests'], {
...process.env,
CI: '1',
NO_COLOR: '1',
CCS_HOME: tmpHome,
CCS_CODEX_PATH: fakeCodexPath,
CCS_TEST_CODEX_ARGS_OUT: codexArgsLogPath,
});
expect(result.status).toBe(0);
const calls = readLoggedCodexCalls(codexArgsLogPath);
expect(calls).toEqual([['fix failing tests']]);
} finally {
if (originalCcsHome !== undefined) {
process.env.CCS_HOME = originalCcsHome;
} else {
delete process.env.CCS_HOME;
}
}
});
it('forces Codex browser MCP overrides on for one launch when --browser is passed', () => {
if (process.platform === 'win32') return;
const originalCcsHome = process.env.CCS_HOME;
process.env.CCS_HOME = tmpHome;
try {
mutateUnifiedConfig((config) => {
config.browser = {
claude: {
enabled: false,
policy: 'auto',
user_data_dir: '',
devtools_port: 9222,
},
codex: {
enabled: true,
policy: 'manual',
},
};
});
const result = runCcs(['default', '--target', 'codex', '--browser', 'fix failing tests'], {
...process.env,
CI: '1',
NO_COLOR: '1',
CCS_HOME: tmpHome,
CCS_CODEX_PATH: fakeCodexPath,
CCS_TEST_CODEX_ARGS_OUT: codexArgsLogPath,
});
expect(result.status).toBe(0);
const calls = readLoggedCodexCalls(codexArgsLogPath);
expect(calls[1]).toEqual(
expect.arrayContaining([
'mcp_servers.ccs_browser.enabled=true',
'fix failing tests',
])
);
} finally {
if (originalCcsHome !== undefined) {
process.env.CCS_HOME = originalCcsHome;
} else {
delete process.env.CCS_HOME;
}
}
});
it('suppresses Codex browser MCP overrides for one launch when --no-browser is passed', () => {
if (process.platform === 'win32') return;
const result = runCcs(['default', '--target', 'codex', '--no-browser', 'fix failing tests'], {
...process.env,
CI: '1',
NO_COLOR: '1',
CCS_HOME: tmpHome,
CCS_CODEX_PATH: fakeCodexPath,
CCS_TEST_CODEX_ARGS_OUT: codexArgsLogPath,
});
expect(result.status).toBe(0);
const calls = readLoggedCodexCalls(codexArgsLogPath);
expect(calls).toEqual([['fix failing tests']]);
});
it('keeps browser MCP runtime overrides when CCS_THINKING is ignored for native Codex default mode', () => {
if (process.platform === 'win32') return;
@@ -270,11 +270,13 @@ server.listen(0, '127.0.0.1', () => {
config.browser = {
claude: {
enabled: true,
policy: 'auto',
user_data_dir: '',
devtools_port: 43123,
},
codex: {
enabled: true,
policy: 'auto',
},
};
});
@@ -321,11 +323,13 @@ server.listen(0, '127.0.0.1', () => {
config.browser = {
claude: {
enabled: true,
policy: 'auto',
user_data_dir: '',
devtools_port: unreachablePort,
},
codex: {
enabled: true,
policy: 'auto',
},
};
});
@@ -396,11 +400,13 @@ server.listen(0, '127.0.0.1', () => {
config.browser = {
claude: {
enabled: true,
policy: 'auto',
user_data_dir: browserProfileDir,
devtools_port: Number.parseInt(port, 10),
},
codex: {
enabled: true,
policy: 'auto',
},
};
});
@@ -221,11 +221,13 @@ server.listen(0, '127.0.0.1', () => {
config.browser = {
claude: {
enabled: true,
policy: 'auto',
user_data_dir: '',
devtools_port: 43123,
},
codex: {
enabled: true,
policy: 'auto',
},
};
});
@@ -273,11 +275,13 @@ server.listen(0, '127.0.0.1', () => {
config.browser = {
claude: {
enabled: true,
policy: 'auto',
user_data_dir: '',
devtools_port: unreachablePort,
},
codex: {
enabled: true,
policy: 'auto',
},
};
});
@@ -354,11 +358,13 @@ server.listen(0, '127.0.0.1', () => {
config.browser = {
claude: {
enabled: true,
policy: 'auto',
user_data_dir: browserProfileDir,
devtools_port: Number.parseInt(port, 10),
},
codex: {
enabled: true,
policy: 'auto',
},
};
});
+9 -3
View File
@@ -158,16 +158,22 @@ describe('resolveTargetType', () => {
it('should detect internal entry target for dedicated package bin entrypoints', () => {
process.env.CCS_INTERNAL_ENTRY_TARGET = 'droid';
process.argv = ['node', 'ccs'];
process.argv = ['node', '/usr/local/lib/ccs/dist/bin/droid-runtime.js'];
expect(resolveTargetType([])).toBe('droid');
});
it('should detect internal entry target for codex runtime bins', () => {
process.env.CCS_INTERNAL_ENTRY_TARGET = 'codex';
process.argv = ['node', 'ccs'];
process.argv = ['node', '/usr/local/lib/ccs/dist/bin/codex-runtime.js'];
expect(resolveTargetType([])).toBe('codex');
});
it('should ignore leaked internal entry target env on the main ccs entrypoint', () => {
process.env.CCS_INTERNAL_ENTRY_TARGET = 'codex';
process.argv = ['node', 'ccs.js'];
expect(resolveTargetType([])).toBe('claude');
});
it('should normalize argv[0] and custom aliases case-insensitively', () => {
process.env.CCS_DROID_ALIASES = 'DroidCaps';
process.argv = ['node', 'DROIDCAPS'];
@@ -242,7 +248,7 @@ describe('resolveTargetType', () => {
it('should prioritize internal entry target over profile config', () => {
process.env.CCS_INTERNAL_ENTRY_TARGET = 'droid';
process.argv = ['node', 'ccs'];
process.argv = ['node', '/usr/local/lib/ccs/dist/bin/droid-runtime.js'];
expect(resolveTargetType([], { target: 'claude' })).toBe('droid');
});