@kbediako/codex-orchestrator 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -83
- package/dist/bin/codex-orchestrator.js +2 -0
- package/dist/orchestrator/src/cli/adapters/CommandBuilder.js +50 -0
- package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +117 -5
- package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +2 -2
- package/dist/orchestrator/src/cli/coStatusCliShell.js +28 -6
- package/dist/orchestrator/src/cli/codexCliShell.js +48 -1
- package/dist/orchestrator/src/cli/codexDefaultsSetup.js +217 -26
- package/dist/orchestrator/src/cli/control/controlHostSupervision.js +28 -6
- package/dist/orchestrator/src/cli/control/controlRuntime.js +17 -6
- package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +6 -1
- package/dist/orchestrator/src/cli/control/selectedRunProjection.js +49 -2
- package/dist/orchestrator/src/cli/doctor.js +142 -48
- package/dist/orchestrator/src/cli/init.js +94 -1
- package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +64 -1
- package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +1165 -69
- package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
- package/dist/orchestrator/src/cli/services/commandRunner.js +31 -0
- package/dist/orchestrator/src/cli/utils/cloudPreflight.js +202 -6
- package/dist/orchestrator/src/cli/utils/codexFeatures.js +60 -0
- package/dist/orchestrator/src/manager.js +74 -4
- package/dist/scripts/lib/docs-catalog.js +35 -1
- package/docs/README.md +333 -0
- package/docs/book/README.md +19 -0
- package/docs/book/codex-cli-0124-adoption.md +68 -0
- package/docs/book/local-hook-impact.md +73 -0
- package/docs/book/operations.md +60 -0
- package/docs/book/public-posture.md +34 -0
- package/docs/book/setup.md +91 -0
- package/docs/book/skills.md +11 -0
- package/docs/guides/codex-version-policy.md +104 -0
- package/docs/public/downstream-setup.md +25 -18
- package/package.json +4 -1
- package/plugins/codex-orchestrator/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-orchestrator/launcher.mjs +6 -4
- package/schemas/manifest.json +17 -0
- package/skills/README.md +26 -0
- package/skills/collab-subagents-first/SKILL.md +1 -1
- package/skills/delegation-usage/DELEGATION_GUIDE.md +12 -7
- package/skills/delegation-usage/SKILL.md +13 -8
- package/templates/codex/AGENTS.md +12 -10
|
@@ -4,18 +4,25 @@ import { createRequire } from 'node:module';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { resolveCodexHome } from './utils/codexPaths.js';
|
|
7
|
+
import { resolveCodexCliBin } from './utils/codexCli.js';
|
|
8
|
+
import { codexFeatureProbeDisablesMultiAgentV2, codexFeatureProbeRejectsAgentMaxThreads, readCodexFeatureProbe } from './utils/codexFeatures.js';
|
|
7
9
|
import { findPackageRoot } from './utils/packageInfo.js';
|
|
8
10
|
import { writeAtomicFile } from '../utils/atomicWrite.js';
|
|
9
11
|
const require = createRequire(import.meta.url);
|
|
10
12
|
let tomlLibrary;
|
|
11
13
|
export const BASELINE_MODEL = 'gpt-5.4';
|
|
12
14
|
export const BASELINE_REVIEW_MODEL = BASELINE_MODEL;
|
|
15
|
+
export const CURRENT_CHATGPT_MODEL = 'gpt-5.5';
|
|
13
16
|
export const BASELINE_REASONING = 'xhigh';
|
|
14
17
|
export const BASELINE_REASONING_MINIMUM = 'high';
|
|
15
18
|
export const BASELINE_AGENTS = {
|
|
16
19
|
max_threads: 12,
|
|
17
20
|
max_depth: 4
|
|
18
21
|
};
|
|
22
|
+
export const LOCAL_MODEL_OPT_INS = [CURRENT_CHATGPT_MODEL];
|
|
23
|
+
const LOCAL_MODEL_OPT_IN_SET = new Set(LOCAL_MODEL_OPT_INS);
|
|
24
|
+
const CODEX_ORCHESTRATOR_CONFIG_KEY = 'codex_orchestrator';
|
|
25
|
+
const LOCAL_MODEL_OPT_IN_CONFIG_KEY = 'local_model_opt_in';
|
|
19
26
|
const ROLE_DEFINITIONS = [
|
|
20
27
|
{
|
|
21
28
|
key: 'explorer_fast',
|
|
@@ -29,26 +36,45 @@ const ROLE_DEFINITIONS = [
|
|
|
29
36
|
description: 'Complex implementation role.',
|
|
30
37
|
fileName: 'worker-complex.toml',
|
|
31
38
|
configFile: './agents/worker-complex.toml',
|
|
32
|
-
templatePath: join('templates', 'codex', '.codex', 'agents', 'worker-complex.toml')
|
|
39
|
+
templatePath: join('templates', 'codex', '.codex', 'agents', 'worker-complex.toml'),
|
|
40
|
+
managedMigrationBaselines: [{ model: 'gpt-5.5', modelReasoningEffort: 'xhigh' }]
|
|
33
41
|
},
|
|
34
42
|
{
|
|
35
43
|
key: 'awaiter',
|
|
36
44
|
description: 'Awaiter override (keeps awaiter behavior with latest codex/high reasoning).',
|
|
37
45
|
fileName: 'awaiter-high.toml',
|
|
38
46
|
configFile: './agents/awaiter-high.toml',
|
|
39
|
-
templatePath: join('templates', 'codex', '.codex', 'agents', 'awaiter-high.toml')
|
|
47
|
+
templatePath: join('templates', 'codex', '.codex', 'agents', 'awaiter-high.toml'),
|
|
48
|
+
managedMigrationBaselines: [{ model: 'gpt-5.5', modelReasoningEffort: 'xhigh' }],
|
|
49
|
+
managedMigrationContentVariants: [
|
|
50
|
+
{
|
|
51
|
+
model: 'gpt-5.5',
|
|
52
|
+
modelReasoningEffort: 'high',
|
|
53
|
+
overrideComment: '# with CO portable override to use gpt-5.4 at high reasoning.'
|
|
54
|
+
}
|
|
55
|
+
]
|
|
40
56
|
}
|
|
41
57
|
];
|
|
42
58
|
export async function runCodexDefaultsSetup(options = {}) {
|
|
43
59
|
const env = options.env ?? process.env;
|
|
44
60
|
const force = Boolean(options.force);
|
|
45
61
|
const apply = Boolean(options.apply);
|
|
46
|
-
const
|
|
62
|
+
const configState = await loadConfigState(buildConfigPath(env));
|
|
63
|
+
const topLevelLocalModelOptIn = resolveRequestedLocalModelOptIn(configState.parsed, options.authScope);
|
|
64
|
+
const roleAndReviewLocalModelOptIn = resolveRoleAndReviewLocalModelOptIn(configState.parsed, topLevelLocalModelOptIn, options.authScope);
|
|
65
|
+
const authScope = topLevelLocalModelOptIn ? 'chatgpt' : 'portable';
|
|
66
|
+
const plan = buildPlan(env, force, authScope);
|
|
47
67
|
const roleDefinitions = await loadRoleDefinitions();
|
|
48
|
-
const
|
|
49
|
-
const nextConfig = mergeBaselineDefaults(configState.parsed, roleDefinitions
|
|
68
|
+
const featureProbe = readCodexFeatureProbe(resolveCodexCliBin(env), env);
|
|
69
|
+
const nextConfig = mergeBaselineDefaults(configState.parsed, roleDefinitions, {
|
|
70
|
+
topLevelLocalModelOptIn,
|
|
71
|
+
reviewModelOptIn: roleAndReviewLocalModelOptIn,
|
|
72
|
+
requestedAuthScope: options.authScope,
|
|
73
|
+
featureProbe
|
|
74
|
+
});
|
|
75
|
+
const activeRoleDefinitions = buildActiveRoleDefinitions(roleDefinitions, roleAndReviewLocalModelOptIn);
|
|
50
76
|
const configChanged = canonicalizeConfigValue(configState.parsed) !== canonicalizeConfigValue(nextConfig);
|
|
51
|
-
const roleChanges = await planRoleChanges(plan.agentsDir, force,
|
|
77
|
+
const roleChanges = await planRoleChanges(plan.agentsDir, force, activeRoleDefinitions);
|
|
52
78
|
if (!apply) {
|
|
53
79
|
const changes = buildPlannedChanges({
|
|
54
80
|
configPath: plan.configPath,
|
|
@@ -72,7 +98,7 @@ export async function runCodexDefaultsSetup(options = {}) {
|
|
|
72
98
|
path: plan.configPath,
|
|
73
99
|
status: configState.exists ? 'updated' : 'created',
|
|
74
100
|
detail: configState.exists
|
|
75
|
-
? 'Updated CO baseline defaults
|
|
101
|
+
? 'Updated CO-compatible baseline defaults and preserved unrelated keys.'
|
|
76
102
|
: 'Created config.toml with CO baseline defaults.'
|
|
77
103
|
});
|
|
78
104
|
}
|
|
@@ -87,9 +113,7 @@ export async function runCodexDefaultsSetup(options = {}) {
|
|
|
87
113
|
}
|
|
88
114
|
await mkdir(plan.agentsDir, { recursive: true });
|
|
89
115
|
for (const roleChange of roleChanges) {
|
|
90
|
-
|
|
91
|
-
|| (force && roleChange.existingContent !== roleChange.definition.content);
|
|
92
|
-
if (shouldWrite) {
|
|
116
|
+
if (roleChange.writeReason) {
|
|
93
117
|
await writeAtomicFile(roleChange.path, roleChange.definition.content, {
|
|
94
118
|
ensureDir: true,
|
|
95
119
|
encoding: 'utf8'
|
|
@@ -99,9 +123,7 @@ export async function runCodexDefaultsSetup(options = {}) {
|
|
|
99
123
|
name: roleChange.definition.key,
|
|
100
124
|
path: roleChange.path,
|
|
101
125
|
status: roleChange.existingContent === null ? 'created' : 'updated',
|
|
102
|
-
detail: roleChange
|
|
103
|
-
? `Created ${roleChange.definition.fileName}.`
|
|
104
|
-
: `Overwrote ${roleChange.definition.fileName} because --force was set.`
|
|
126
|
+
detail: formatAppliedRoleWriteDetail(roleChange)
|
|
105
127
|
});
|
|
106
128
|
continue;
|
|
107
129
|
}
|
|
@@ -126,6 +148,7 @@ export function formatCodexDefaultsSetupSummary(result) {
|
|
|
126
148
|
lines.push(`- Config: ${result.plan.configPath}`);
|
|
127
149
|
lines.push(`- Agents dir: ${result.plan.agentsDir}`);
|
|
128
150
|
lines.push(`- Force overwrite: ${result.plan.force ? 'yes' : 'no'}`);
|
|
151
|
+
lines.push(`- Auth scope: ${result.plan.authScope}`);
|
|
129
152
|
lines.push('- Changes:');
|
|
130
153
|
for (const change of result.changes) {
|
|
131
154
|
lines.push(` - ${change.target}:${change.name} -> ${change.status} (${change.path})`);
|
|
@@ -136,13 +159,18 @@ export function formatCodexDefaultsSetupSummary(result) {
|
|
|
136
159
|
}
|
|
137
160
|
return lines;
|
|
138
161
|
}
|
|
139
|
-
function
|
|
162
|
+
function buildConfigPath(env) {
|
|
163
|
+
return join(resolveCodexHome(env), 'config.toml');
|
|
164
|
+
}
|
|
165
|
+
function buildPlan(env, force, authScope) {
|
|
166
|
+
const configPath = buildConfigPath(env);
|
|
140
167
|
const codexHome = resolveCodexHome(env);
|
|
141
168
|
return {
|
|
142
169
|
codexHome,
|
|
143
|
-
configPath
|
|
170
|
+
configPath,
|
|
144
171
|
agentsDir: join(codexHome, 'agents'),
|
|
145
|
-
force
|
|
172
|
+
force,
|
|
173
|
+
authScope
|
|
146
174
|
};
|
|
147
175
|
}
|
|
148
176
|
async function loadConfigState(configPath) {
|
|
@@ -202,13 +230,19 @@ function canonicalizeConfigValue(value) {
|
|
|
202
230
|
}
|
|
203
231
|
return undefined;
|
|
204
232
|
}
|
|
205
|
-
function mergeBaselineDefaults(existing, roleDefinitions) {
|
|
233
|
+
function mergeBaselineDefaults(existing, roleDefinitions, options) {
|
|
206
234
|
const next = structuredClone(existing);
|
|
207
|
-
next.model = BASELINE_MODEL;
|
|
208
|
-
next.review_model = BASELINE_REVIEW_MODEL;
|
|
235
|
+
next.model = resolveModelDefault(options.topLevelLocalModelOptIn, BASELINE_MODEL);
|
|
236
|
+
next.review_model = resolveModelDefault(options.reviewModelOptIn, BASELINE_REVIEW_MODEL);
|
|
209
237
|
next.model_reasoning_effort = BASELINE_REASONING;
|
|
238
|
+
removeLegacyLocalModelOptInMarker(next);
|
|
210
239
|
const agents = isRecord(next.agents) ? structuredClone(next.agents) : {};
|
|
211
|
-
|
|
240
|
+
if (isMultiAgentV2Enabled(next, options.featureProbe)) {
|
|
241
|
+
delete agents.max_threads;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
agents.max_threads = BASELINE_AGENTS.max_threads;
|
|
245
|
+
}
|
|
212
246
|
for (const role of roleDefinitions) {
|
|
213
247
|
const existingRole = isRecord(agents[role.key])
|
|
214
248
|
? structuredClone(agents[role.key])
|
|
@@ -220,6 +254,71 @@ function mergeBaselineDefaults(existing, roleDefinitions) {
|
|
|
220
254
|
next.agents = agents;
|
|
221
255
|
return next;
|
|
222
256
|
}
|
|
257
|
+
export function isLocalModelOptIn(value) {
|
|
258
|
+
return typeof value === 'string' && LOCAL_MODEL_OPT_IN_SET.has(value);
|
|
259
|
+
}
|
|
260
|
+
export function resolveLocalModelOptIn(existing) {
|
|
261
|
+
const localConfig = isRecord(existing[CODEX_ORCHESTRATOR_CONFIG_KEY])
|
|
262
|
+
? existing[CODEX_ORCHESTRATOR_CONFIG_KEY]
|
|
263
|
+
: null;
|
|
264
|
+
const configuredModel = localConfig?.[LOCAL_MODEL_OPT_IN_CONFIG_KEY];
|
|
265
|
+
return isLocalModelOptIn(configuredModel) ? configuredModel : null;
|
|
266
|
+
}
|
|
267
|
+
function resolveRequestedLocalModelOptIn(existing, requestedAuthScope) {
|
|
268
|
+
if (requestedAuthScope === 'portable') {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
if (requestedAuthScope === 'chatgpt') {
|
|
272
|
+
return CURRENT_CHATGPT_MODEL;
|
|
273
|
+
}
|
|
274
|
+
const model = readOptionalString(existing.model);
|
|
275
|
+
const reviewModel = readOptionalString(existing.review_model);
|
|
276
|
+
if (isLocalModelOptIn(model)) {
|
|
277
|
+
return model;
|
|
278
|
+
}
|
|
279
|
+
if (isLocalModelOptIn(reviewModel)) {
|
|
280
|
+
return reviewModel;
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
function resolveRoleAndReviewLocalModelOptIn(existing, topLevelLocalModelOptIn, requestedAuthScope) {
|
|
285
|
+
if (requestedAuthScope === 'portable') {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
if (topLevelLocalModelOptIn) {
|
|
289
|
+
return topLevelLocalModelOptIn;
|
|
290
|
+
}
|
|
291
|
+
const reviewModel = readOptionalString(existing.review_model);
|
|
292
|
+
const existingLocalModelOptIn = resolveLocalModelOptIn(existing);
|
|
293
|
+
return existingLocalModelOptIn === topLevelLocalModelOptIn
|
|
294
|
+
&& reviewModel === topLevelLocalModelOptIn
|
|
295
|
+
&& isLocalModelOptIn(reviewModel)
|
|
296
|
+
? reviewModel
|
|
297
|
+
: null;
|
|
298
|
+
}
|
|
299
|
+
function readOptionalString(value) {
|
|
300
|
+
return typeof value === 'string' ? value : undefined;
|
|
301
|
+
}
|
|
302
|
+
function removeLegacyLocalModelOptInMarker(next) {
|
|
303
|
+
const existingConfig = isRecord(next[CODEX_ORCHESTRATOR_CONFIG_KEY])
|
|
304
|
+
? structuredClone(next[CODEX_ORCHESTRATOR_CONFIG_KEY])
|
|
305
|
+
: {};
|
|
306
|
+
if (LOCAL_MODEL_OPT_IN_CONFIG_KEY in existingConfig) {
|
|
307
|
+
delete existingConfig[LOCAL_MODEL_OPT_IN_CONFIG_KEY];
|
|
308
|
+
if (Object.keys(existingConfig).length > 0) {
|
|
309
|
+
next[CODEX_ORCHESTRATOR_CONFIG_KEY] = existingConfig;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
delete next[CODEX_ORCHESTRATOR_CONFIG_KEY];
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
export function formatModelDefaultExpectation(baseline) {
|
|
317
|
+
return `${CURRENT_CHATGPT_MODEL} when ChatGPT-auth access is verified (fallback: ${baseline})`;
|
|
318
|
+
}
|
|
319
|
+
function resolveModelDefault(localModelOptIn, baseline) {
|
|
320
|
+
return localModelOptIn ?? baseline;
|
|
321
|
+
}
|
|
223
322
|
async function planRoleChanges(agentsDir, force, roleDefinitions) {
|
|
224
323
|
const changes = [];
|
|
225
324
|
for (const definition of roleDefinitions) {
|
|
@@ -230,7 +329,8 @@ async function planRoleChanges(agentsDir, force, roleDefinitions) {
|
|
|
230
329
|
path,
|
|
231
330
|
existingContent: null,
|
|
232
331
|
currentStatus: 'pending',
|
|
233
|
-
detail: `Will create ${definition.fileName}
|
|
332
|
+
detail: `Will create ${definition.fileName}.`,
|
|
333
|
+
writeReason: 'create'
|
|
234
334
|
});
|
|
235
335
|
continue;
|
|
236
336
|
}
|
|
@@ -241,7 +341,8 @@ async function planRoleChanges(agentsDir, force, roleDefinitions) {
|
|
|
241
341
|
path,
|
|
242
342
|
existingContent: current,
|
|
243
343
|
currentStatus: 'unchanged',
|
|
244
|
-
detail: `${definition.fileName} already matches CO baseline defaults
|
|
344
|
+
detail: `${definition.fileName} already matches CO baseline defaults.`,
|
|
345
|
+
writeReason: null
|
|
245
346
|
});
|
|
246
347
|
continue;
|
|
247
348
|
}
|
|
@@ -251,7 +352,19 @@ async function planRoleChanges(agentsDir, force, roleDefinitions) {
|
|
|
251
352
|
path,
|
|
252
353
|
existingContent: current,
|
|
253
354
|
currentStatus: 'pending',
|
|
254
|
-
detail: `Will overwrite ${definition.fileName} because --force is set
|
|
355
|
+
detail: `Will overwrite ${definition.fileName} because --force is set.`,
|
|
356
|
+
writeReason: 'force'
|
|
357
|
+
});
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (definition.managedMigrationContents.includes(current)) {
|
|
361
|
+
changes.push({
|
|
362
|
+
definition,
|
|
363
|
+
path,
|
|
364
|
+
existingContent: current,
|
|
365
|
+
currentStatus: 'pending',
|
|
366
|
+
detail: `Will update ${definition.fileName} from a prior CO-managed model baseline.`,
|
|
367
|
+
writeReason: 'managed_migration'
|
|
255
368
|
});
|
|
256
369
|
continue;
|
|
257
370
|
}
|
|
@@ -260,7 +373,8 @@ async function planRoleChanges(agentsDir, force, roleDefinitions) {
|
|
|
260
373
|
path,
|
|
261
374
|
existingContent: current,
|
|
262
375
|
currentStatus: 'preserved',
|
|
263
|
-
detail: `${definition.fileName} already exists; preserving without --force
|
|
376
|
+
detail: `${definition.fileName} already exists; preserving without --force.`,
|
|
377
|
+
writeReason: null
|
|
264
378
|
});
|
|
265
379
|
}
|
|
266
380
|
return changes;
|
|
@@ -278,10 +392,69 @@ async function loadRoleDefinitions() {
|
|
|
278
392
|
const reason = error?.message ?? String(error);
|
|
279
393
|
throw new Error(`Unable to read role template ${templateFile}: ${reason}`);
|
|
280
394
|
}
|
|
281
|
-
loaded.push({
|
|
395
|
+
loaded.push({
|
|
396
|
+
...definition,
|
|
397
|
+
content,
|
|
398
|
+
managedMigrationContents: buildManagedMigrationContents(content, definition)
|
|
399
|
+
});
|
|
282
400
|
}
|
|
283
401
|
return loaded;
|
|
284
402
|
}
|
|
403
|
+
function buildActiveRoleDefinitions(roleDefinitions, localModelOptIn) {
|
|
404
|
+
if (!localModelOptIn) {
|
|
405
|
+
return [...roleDefinitions];
|
|
406
|
+
}
|
|
407
|
+
return roleDefinitions.map((definition) => {
|
|
408
|
+
const matchingOptInBaseline = definition.managedMigrationBaselines?.find((baseline) => baseline.model === localModelOptIn);
|
|
409
|
+
if (!matchingOptInBaseline) {
|
|
410
|
+
return definition;
|
|
411
|
+
}
|
|
412
|
+
const optInContent = applyRoleBaselineOverrides(definition.content, definition.fileName, matchingOptInBaseline);
|
|
413
|
+
return {
|
|
414
|
+
...definition,
|
|
415
|
+
content: optInContent,
|
|
416
|
+
managedMigrationContents: uniqueRoleContents([
|
|
417
|
+
definition.content,
|
|
418
|
+
...definition.managedMigrationContents
|
|
419
|
+
]).filter((migrationContent) => migrationContent !== optInContent)
|
|
420
|
+
};
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
function buildManagedMigrationContents(content, definition) {
|
|
424
|
+
const migrationContents = [
|
|
425
|
+
...(definition.managedMigrationBaselines ?? []),
|
|
426
|
+
...(definition.managedMigrationContentVariants ?? [])
|
|
427
|
+
].map((baseline) => applyRoleBaselineOverrides(content, definition.fileName, baseline));
|
|
428
|
+
return uniqueRoleContents(migrationContents).filter((migrationContent) => migrationContent !== content);
|
|
429
|
+
}
|
|
430
|
+
function uniqueRoleContents(contents) {
|
|
431
|
+
return [...new Set(contents)];
|
|
432
|
+
}
|
|
433
|
+
function formatAppliedRoleWriteDetail(roleChange) {
|
|
434
|
+
switch (roleChange.writeReason) {
|
|
435
|
+
case 'create':
|
|
436
|
+
return `Created ${roleChange.definition.fileName}.`;
|
|
437
|
+
case 'force':
|
|
438
|
+
return `Overwrote ${roleChange.definition.fileName} because --force was set.`;
|
|
439
|
+
case 'managed_migration':
|
|
440
|
+
return `Updated ${roleChange.definition.fileName} from a prior CO-managed model baseline.`;
|
|
441
|
+
case null:
|
|
442
|
+
return roleChange.detail;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function applyRoleBaselineOverrides(content, fileName, baseline) {
|
|
446
|
+
let next = replaceRoleTomlString(content, 'model', baseline.model, fileName);
|
|
447
|
+
next = replaceRoleTomlString(next, 'model_reasoning_effort', baseline.modelReasoningEffort, fileName);
|
|
448
|
+
return next.replace(/^# with CO override to use .+ at .+ reasoning\.$/m, baseline.overrideComment
|
|
449
|
+
?? `# with CO override to use ${baseline.model} at ${baseline.modelReasoningEffort} reasoning.`);
|
|
450
|
+
}
|
|
451
|
+
function replaceRoleTomlString(content, key, value, fileName) {
|
|
452
|
+
const pattern = new RegExp(`^(${key}\\s*=\\s*)"[^"]*"$`, 'm');
|
|
453
|
+
if (!pattern.test(content)) {
|
|
454
|
+
throw new Error(`Role template ${fileName} is missing a ${key} assignment.`);
|
|
455
|
+
}
|
|
456
|
+
return content.replace(pattern, (_match, prefix) => `${prefix}"${value}"`);
|
|
457
|
+
}
|
|
285
458
|
function buildPlannedChanges(params) {
|
|
286
459
|
const changes = [];
|
|
287
460
|
const configStatus = params.configChanged || !params.configExists ? 'pending' : 'unchanged';
|
|
@@ -292,7 +465,7 @@ function buildPlannedChanges(params) {
|
|
|
292
465
|
status: configStatus,
|
|
293
466
|
detail: configStatus === 'pending'
|
|
294
467
|
? params.configExists
|
|
295
|
-
? 'Will update CO baseline defaults
|
|
468
|
+
? 'Will update CO-compatible baseline defaults while preserving unrelated keys.'
|
|
296
469
|
: 'Will create config.toml with CO baseline defaults.'
|
|
297
470
|
: 'CO baseline defaults already present.'
|
|
298
471
|
});
|
|
@@ -310,3 +483,21 @@ function buildPlannedChanges(params) {
|
|
|
310
483
|
function isRecord(value) {
|
|
311
484
|
return typeof value === 'object' && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
312
485
|
}
|
|
486
|
+
function isMultiAgentV2Enabled(config, featureProbe) {
|
|
487
|
+
if (featureProbe.flags?.multi_agent_v2 === true) {
|
|
488
|
+
return true;
|
|
489
|
+
}
|
|
490
|
+
if (codexFeatureProbeDisablesMultiAgentV2(featureProbe)) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
if (codexFeatureProbeRejectsAgentMaxThreads(featureProbe)) {
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
if (!isRecord(config.features)) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
return readBooleanValue(config.features.multi_agent_v2) === true;
|
|
500
|
+
}
|
|
501
|
+
function readBooleanValue(value) {
|
|
502
|
+
return typeof value === 'boolean' ? value : null;
|
|
503
|
+
}
|
|
@@ -315,14 +315,12 @@ export function evaluateControlHostSupervisionProbeTimeoutDiagnostic(diagnostic,
|
|
|
315
315
|
if (!diagnostic || diagnostic.running_workers.length === 0) {
|
|
316
316
|
return null;
|
|
317
317
|
}
|
|
318
|
-
if (!isProviderRefreshLifecycleRestartRequiredDiagnostic(diagnostic.polling)) {
|
|
319
|
-
return null;
|
|
320
|
-
}
|
|
321
318
|
if (!isCurrentControlHostSupervisionPollingDiagnostic(diagnostic.polling, options.minPollingUpdatedAt)) {
|
|
322
319
|
return null;
|
|
323
320
|
}
|
|
324
|
-
const
|
|
325
|
-
|
|
321
|
+
const restartRequired = isProviderRefreshLifecycleRestartRequiredDiagnostic(diagnostic.polling);
|
|
322
|
+
const activeRefresh = isActiveProviderRefreshProbeTimeoutDiagnostic(diagnostic.polling);
|
|
323
|
+
if (!restartRequired && !activeRefresh) {
|
|
326
324
|
return null;
|
|
327
325
|
}
|
|
328
326
|
if (hasAvailableProviderWorkerCapacity(diagnostic)) {
|
|
@@ -371,6 +369,18 @@ function isProviderRefreshLifecycleRestartRequiredDiagnostic(polling) {
|
|
|
371
369
|
return (polling.reason === 'provider_refresh_lifecycle_stuck' ||
|
|
372
370
|
polling.last_error === 'provider_refresh_lifecycle_stuck');
|
|
373
371
|
}
|
|
372
|
+
function isActiveProviderRefreshProbeTimeoutDiagnostic(polling) {
|
|
373
|
+
if (!polling || polling.checking !== true) {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
if (polling.restart_required === true || polling.stuck === true) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
if (polling.reason !== null) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
return polling.refresh_phase?.startsWith('refresh:') === true;
|
|
383
|
+
}
|
|
374
384
|
function isCurrentControlHostSupervisionPollingDiagnostic(polling, minPollingUpdatedAt) {
|
|
375
385
|
const minimumUpdatedAt = parseIsoTimestampToMs(minPollingUpdatedAt);
|
|
376
386
|
if (minimumUpdatedAt === null) {
|
|
@@ -467,10 +477,22 @@ function buildControlHostSupervisionRestartSignature(diagnostic) {
|
|
|
467
477
|
// Quarantine repeated restart churn on the stable active-worker series, not on transient
|
|
468
478
|
// refresh checkpoints that can legitimately drift within one stuck refresh cycle.
|
|
469
479
|
return JSON.stringify({
|
|
470
|
-
reason: diagnostic.polling
|
|
480
|
+
reason: buildControlHostSupervisionRestartReasonKey(diagnostic.polling),
|
|
471
481
|
worker_series: workerSeries
|
|
472
482
|
});
|
|
473
483
|
}
|
|
484
|
+
function buildControlHostSupervisionRestartReasonKey(polling) {
|
|
485
|
+
if (polling.reason) {
|
|
486
|
+
return polling.reason;
|
|
487
|
+
}
|
|
488
|
+
if (isActiveProviderRefreshProbeTimeoutDiagnostic(polling)) {
|
|
489
|
+
return 'active_provider_refresh_probe_timeout';
|
|
490
|
+
}
|
|
491
|
+
if (isProviderRefreshLifecycleRestartRequiredDiagnostic(polling)) {
|
|
492
|
+
return 'provider_refresh_lifecycle_stuck';
|
|
493
|
+
}
|
|
494
|
+
return polling.last_error ?? null;
|
|
495
|
+
}
|
|
474
496
|
function buildControlHostSupervisionWorkerSeriesKey(worker) {
|
|
475
497
|
if (worker.issue_identifier.length === 0) {
|
|
476
498
|
return null;
|
|
@@ -883,6 +883,8 @@ function buildCompatibilityTelemetrySnapshot(sources, polling) {
|
|
|
883
883
|
let hasOutputTokens = false;
|
|
884
884
|
let totalTokens = 0;
|
|
885
885
|
let hasTotalTokens = false;
|
|
886
|
+
let reasoningOutputTokens = 0;
|
|
887
|
+
let hasReasoningOutputTokens = false;
|
|
886
888
|
let secondsRunning = 0;
|
|
887
889
|
let latestAuthoritativeRateLimits = polling?.linear_budget
|
|
888
890
|
? { ...polling.linear_budget }
|
|
@@ -908,6 +910,11 @@ function buildCompatibilityTelemetrySnapshot(sources, polling) {
|
|
|
908
910
|
totalTokens += Math.max(0, tokenUsage.total_tokens);
|
|
909
911
|
hasTotalTokens = true;
|
|
910
912
|
}
|
|
913
|
+
if (typeof tokenUsage?.reasoning_output_tokens === 'number' &&
|
|
914
|
+
Number.isFinite(tokenUsage.reasoning_output_tokens)) {
|
|
915
|
+
reasoningOutputTokens += Math.max(0, tokenUsage.reasoning_output_tokens);
|
|
916
|
+
hasReasoningOutputTokens = true;
|
|
917
|
+
}
|
|
911
918
|
secondsRunning += computeCompatibilityRuntimeSeconds(source, now);
|
|
912
919
|
const linearBudget = proof?.linear_budget ? { ...proof.linear_budget } : null;
|
|
913
920
|
if (linearBudget) {
|
|
@@ -926,13 +933,17 @@ function buildCompatibilityTelemetrySnapshot(sources, polling) {
|
|
|
926
933
|
}
|
|
927
934
|
}
|
|
928
935
|
}
|
|
936
|
+
const codexTotals = {
|
|
937
|
+
input_tokens: hasInputTokens ? inputTokens : null,
|
|
938
|
+
output_tokens: hasOutputTokens ? outputTokens : null,
|
|
939
|
+
total_tokens: hasTotalTokens ? totalTokens : null,
|
|
940
|
+
seconds_running: Number(secondsRunning.toFixed(3))
|
|
941
|
+
};
|
|
942
|
+
if (hasReasoningOutputTokens) {
|
|
943
|
+
codexTotals.reasoning_output_tokens = reasoningOutputTokens;
|
|
944
|
+
}
|
|
929
945
|
return {
|
|
930
|
-
codexTotals
|
|
931
|
-
input_tokens: hasInputTokens ? inputTokens : null,
|
|
932
|
-
output_tokens: hasOutputTokens ? outputTokens : null,
|
|
933
|
-
total_tokens: hasTotalTokens ? totalTokens : null,
|
|
934
|
-
seconds_running: Number(secondsRunning.toFixed(3))
|
|
935
|
-
},
|
|
946
|
+
codexTotals,
|
|
936
947
|
rateLimits: combineCompatibilityRateLimits({
|
|
937
948
|
codex: latestCodexRateLimits,
|
|
938
949
|
linearBudget: latestAuthoritativeRateLimits
|
|
@@ -738,7 +738,12 @@ function renderTokensLine(dataset, terminalColumns) {
|
|
|
738
738
|
{ text: ' | ', color: ANSI_GRAY },
|
|
739
739
|
{ text: `out ${formatOptionalCount(dataset.totals.output_tokens)}`, color: ANSI_YELLOW },
|
|
740
740
|
{ text: ' | ', color: ANSI_GRAY },
|
|
741
|
-
{ text: `total ${formatOptionalCount(dataset.totals.total_tokens)}`, color: ANSI_YELLOW }
|
|
741
|
+
{ text: `total ${formatOptionalCount(dataset.totals.total_tokens)}`, color: ANSI_YELLOW },
|
|
742
|
+
{ text: ' | ', color: ANSI_GRAY },
|
|
743
|
+
{
|
|
744
|
+
text: `reasoning ${formatOptionalCount(dataset.totals.reasoning_output_tokens)}`,
|
|
745
|
+
color: ANSI_YELLOW
|
|
746
|
+
}
|
|
742
747
|
], terminalColumns);
|
|
743
748
|
}
|
|
744
749
|
function renderRateLimitsLine(dataset, referenceTime, terminalColumns) {
|
|
@@ -1370,11 +1370,58 @@ function hasProviderLinearWorkerProjectionRetiredChildLaneResidue(proof) {
|
|
|
1370
1370
|
}
|
|
1371
1371
|
function hasProviderLinearWorkerProjectionTelemetryGap(proof) {
|
|
1372
1372
|
const tokens = proof.tokens ?? null;
|
|
1373
|
-
const hasTokens = tokens?.input_tokens != null ||
|
|
1373
|
+
const hasTokens = tokens?.input_tokens != null ||
|
|
1374
|
+
tokens?.output_tokens != null ||
|
|
1375
|
+
tokens?.total_tokens != null ||
|
|
1376
|
+
tokens?.reasoning_output_tokens != null;
|
|
1374
1377
|
return (!proof.latest_turn_id ||
|
|
1375
1378
|
!proof.latest_session_id ||
|
|
1376
1379
|
!hasTokens ||
|
|
1377
|
-
proof.rate_limits == null
|
|
1380
|
+
proof.rate_limits == null ||
|
|
1381
|
+
hasProviderLinearWorkerProjectionSessionLogHydrationGap(proof) ||
|
|
1382
|
+
hasProviderLinearWorkerProjectionAppServerSupervisionGap(proof));
|
|
1383
|
+
}
|
|
1384
|
+
function hasProviderLinearWorkerProjectionAppServerSupervisionGap(proof) {
|
|
1385
|
+
const selectedRuntimeMode = proof.runtime?.selected_mode ?? proof.auth_provenance?.runtime_mode ?? null;
|
|
1386
|
+
const requestedRuntimeMode = proof.runtime?.requested_mode ?? null;
|
|
1387
|
+
const fallback = proof.runtime?.fallback ?? null;
|
|
1388
|
+
if (selectedRuntimeMode !== 'appserver' &&
|
|
1389
|
+
requestedRuntimeMode !== 'appserver' &&
|
|
1390
|
+
fallback?.from_mode !== 'appserver' &&
|
|
1391
|
+
fallback?.to_mode !== 'appserver') {
|
|
1392
|
+
return false;
|
|
1393
|
+
}
|
|
1394
|
+
const supervision = proof.appserver_supervision ?? null;
|
|
1395
|
+
if (!supervision) {
|
|
1396
|
+
return true;
|
|
1397
|
+
}
|
|
1398
|
+
const expectedSessionLogTruthRetained = selectedRuntimeMode === 'appserver';
|
|
1399
|
+
return (supervision.selected_runtime?.selected_mode !== selectedRuntimeMode ||
|
|
1400
|
+
supervision.selected_runtime?.requested_mode !== requestedRuntimeMode ||
|
|
1401
|
+
supervision.thread_id !== proof.thread_id ||
|
|
1402
|
+
supervision.latest_turn_id !== proof.latest_turn_id ||
|
|
1403
|
+
supervision.latest_session_id !== proof.latest_session_id ||
|
|
1404
|
+
supervision.session_log_thread_id !== (proof.session_log_thread_id ?? null) ||
|
|
1405
|
+
supervision.session_log_turn_id !== (proof.session_log_turn_id ?? null) ||
|
|
1406
|
+
supervision.session_log_session_id !== (proof.session_log_session_id ?? null) ||
|
|
1407
|
+
supervision.turn_persistence_status == null ||
|
|
1408
|
+
supervision.pagination_status == null ||
|
|
1409
|
+
supervision.resume_status == null ||
|
|
1410
|
+
supervision.fork_status == null ||
|
|
1411
|
+
supervision.jsonl_truth_retained !== true ||
|
|
1412
|
+
supervision.session_log_truth_retained !== expectedSessionLogTruthRetained);
|
|
1413
|
+
}
|
|
1414
|
+
function hasProviderLinearWorkerProjectionSessionLogHydrationGap(proof) {
|
|
1415
|
+
const runtimeMode = proof.runtime?.selected_mode ?? proof.auth_provenance?.runtime_mode ?? null;
|
|
1416
|
+
if (runtimeMode !== 'appserver') {
|
|
1417
|
+
return false;
|
|
1418
|
+
}
|
|
1419
|
+
if (!proof.thread_id || !proof.latest_turn_id || !proof.latest_session_id) {
|
|
1420
|
+
return false;
|
|
1421
|
+
}
|
|
1422
|
+
return (proof.session_log_thread_id !== proof.thread_id ||
|
|
1423
|
+
proof.session_log_turn_id !== proof.latest_turn_id ||
|
|
1424
|
+
proof.session_log_session_id !== proof.latest_session_id);
|
|
1378
1425
|
}
|
|
1379
1426
|
function canSkipProviderLinearWorkerProjectionSessionLogHydration(proof, telemetryGap) {
|
|
1380
1427
|
if (proof.owner_phase !== 'turn_completed') {
|