@kbediako/codex-orchestrator 0.1.33 → 0.1.34
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 +19 -3
- package/codex.orchestrator.json +448 -0
- package/dist/bin/codex-orchestrator.js +365 -78
- package/dist/orchestrator/src/cli/config/repoConfigPolicy.js +22 -0
- package/dist/orchestrator/src/cli/config/userConfig.js +20 -9
- package/dist/orchestrator/src/cli/delegationSetup.js +111 -14
- package/dist/orchestrator/src/cli/doctor.js +82 -5
- package/dist/orchestrator/src/cli/doctorIssueLog.js +350 -0
- package/dist/orchestrator/src/cli/init.js +23 -0
- package/dist/orchestrator/src/cli/orchestrator.js +19 -3
- package/dist/orchestrator/src/cli/services/pipelineResolver.js +70 -18
- package/dist/orchestrator/src/cli/services/runPreparation.js +2 -0
- package/dist/orchestrator/src/cli/utils/commandPreview.js +10 -0
- package/dist/orchestrator/src/cli/utils/devtools.js +2 -1
- package/dist/orchestrator/src/cloud/CodexCloudTaskExecutor.js +21 -0
- package/docs/README.md +12 -7
- package/package.json +2 -1
|
@@ -15,6 +15,7 @@ import { buildSelfCheckResult } from '../orchestrator/src/cli/selfCheck.js';
|
|
|
15
15
|
import { initCodexTemplates, formatInitSummary } from '../orchestrator/src/cli/init.js';
|
|
16
16
|
import { runDoctor, runDoctorCloudPreflight, formatDoctorSummary, formatDoctorCloudPreflightSummary } from '../orchestrator/src/cli/doctor.js';
|
|
17
17
|
import { formatDoctorUsageSummary, runDoctorUsage } from '../orchestrator/src/cli/doctorUsage.js';
|
|
18
|
+
import { formatDoctorIssueLogSummary, writeDoctorIssueLog } from '../orchestrator/src/cli/doctorIssueLog.js';
|
|
18
19
|
import { formatDevtoolsSetupSummary, runDevtoolsSetup } from '../orchestrator/src/cli/devtoolsSetup.js';
|
|
19
20
|
import { formatCodexCliSetupSummary, runCodexCliSetup } from '../orchestrator/src/cli/codexCliSetup.js';
|
|
20
21
|
import { formatDelegationSetupSummary, runDelegationSetup } from '../orchestrator/src/cli/delegationSetup.js';
|
|
@@ -25,6 +26,9 @@ import { serveMcp } from '../orchestrator/src/cli/mcp.js';
|
|
|
25
26
|
import { formatMcpEnableSummary, runMcpEnable } from '../orchestrator/src/cli/mcpEnable.js';
|
|
26
27
|
import { startDelegationServer } from '../orchestrator/src/cli/delegationServer.js';
|
|
27
28
|
import { splitDelegationConfigOverrides } from '../orchestrator/src/cli/config/delegationConfig.js';
|
|
29
|
+
import { buildCommandPreview } from '../orchestrator/src/cli/utils/commandPreview.js';
|
|
30
|
+
import { REPO_CONFIG_REQUIRED_ENV_KEY } from '../orchestrator/src/cli/config/repoConfigPolicy.js';
|
|
31
|
+
const AUTO_ISSUE_LOG_ENV_KEY = 'CODEX_ORCHESTRATOR_AUTO_ISSUE_LOG';
|
|
28
32
|
async function main() {
|
|
29
33
|
const args = process.argv.slice(2);
|
|
30
34
|
const command = args.shift();
|
|
@@ -117,6 +121,7 @@ function parseArgs(raw) {
|
|
|
117
121
|
const queue = [...raw];
|
|
118
122
|
const booleanFlagKeys = new Set([
|
|
119
123
|
'apply',
|
|
124
|
+
'auto-issue-log',
|
|
120
125
|
'cloud',
|
|
121
126
|
'cloud-preflight',
|
|
122
127
|
'codex-cli',
|
|
@@ -127,8 +132,10 @@ function parseArgs(raw) {
|
|
|
127
132
|
'force',
|
|
128
133
|
'help',
|
|
129
134
|
'interactive',
|
|
135
|
+
'issue-log',
|
|
130
136
|
'multi-agent',
|
|
131
137
|
'no-interactive',
|
|
138
|
+
'repo-config-required',
|
|
132
139
|
'refresh-skills',
|
|
133
140
|
'ui',
|
|
134
141
|
'usage',
|
|
@@ -327,6 +334,41 @@ function readStringFlag(flags, key) {
|
|
|
327
334
|
const trimmed = value.trim();
|
|
328
335
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
329
336
|
}
|
|
337
|
+
function parseBooleanSetting(raw, label) {
|
|
338
|
+
if (typeof raw === 'boolean') {
|
|
339
|
+
return raw;
|
|
340
|
+
}
|
|
341
|
+
const normalized = raw.trim().toLowerCase();
|
|
342
|
+
if (['1', 'true', 'yes', 'on'].includes(normalized)) {
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
if (['0', 'false', 'no', 'off'].includes(normalized)) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
throw new Error(`Invalid ${label} value "${raw}". Expected true|false.`);
|
|
349
|
+
}
|
|
350
|
+
function resolveBooleanOption(flags, key, envKey) {
|
|
351
|
+
const fromFlag = flags[key];
|
|
352
|
+
if (fromFlag !== undefined) {
|
|
353
|
+
return parseBooleanSetting(fromFlag, `--${key}`);
|
|
354
|
+
}
|
|
355
|
+
if (!envKey) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
const fromEnv = process.env[envKey];
|
|
359
|
+
if (typeof fromEnv !== 'string' || fromEnv.trim().length === 0) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
return parseBooleanSetting(fromEnv, envKey);
|
|
363
|
+
}
|
|
364
|
+
function applyRepoConfigRequiredPolicy(flags) {
|
|
365
|
+
const required = resolveBooleanOption(flags, 'repo-config-required', REPO_CONFIG_REQUIRED_ENV_KEY);
|
|
366
|
+
process.env[REPO_CONFIG_REQUIRED_ENV_KEY] = required ? '1' : '0';
|
|
367
|
+
return required;
|
|
368
|
+
}
|
|
369
|
+
function resolveAutoIssueLogEnabled(flags) {
|
|
370
|
+
return resolveBooleanOption(flags, 'auto-issue-log', AUTO_ISSUE_LOG_ENV_KEY);
|
|
371
|
+
}
|
|
330
372
|
function resolveExecutionModeFlag(flags) {
|
|
331
373
|
const cloudShortcut = flags['cloud'] === true;
|
|
332
374
|
const rawMode = readStringFlag(flags, 'execution-mode');
|
|
@@ -474,11 +516,66 @@ async function readRlmState(statePath) {
|
|
|
474
516
|
return null;
|
|
475
517
|
}
|
|
476
518
|
}
|
|
519
|
+
async function maybeCaptureAutoIssueLog(params) {
|
|
520
|
+
if (!params.enabled) {
|
|
521
|
+
return { issueLog: null, issueLogError: null };
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
524
|
+
const issueLog = await writeDoctorIssueLog({
|
|
525
|
+
doctor: runDoctor(),
|
|
526
|
+
issueTitle: params.issueTitle,
|
|
527
|
+
issueNotes: params.issueNotes,
|
|
528
|
+
taskFilter: params.taskFilter
|
|
529
|
+
});
|
|
530
|
+
return { issueLog, issueLogError: null };
|
|
531
|
+
}
|
|
532
|
+
catch (error) {
|
|
533
|
+
const issueLogError = error?.message ?? String(error);
|
|
534
|
+
return { issueLog: null, issueLogError };
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
function withAutoIssueLogContext(error, capture) {
|
|
538
|
+
const baseMessage = error?.message ?? String(error);
|
|
539
|
+
const lines = [baseMessage];
|
|
540
|
+
if (capture.issueLog) {
|
|
541
|
+
lines.push(`Auto issue log: saved to ${capture.issueLog.issue_log_path} (bundle: ${capture.issueLog.bundle_path}).`);
|
|
542
|
+
}
|
|
543
|
+
if (capture.issueLogError) {
|
|
544
|
+
lines.push(`Auto issue log: failed (${capture.issueLogError})`);
|
|
545
|
+
}
|
|
546
|
+
return new Error(lines.join('\n'));
|
|
547
|
+
}
|
|
548
|
+
function resolveTaskFilter(preferredTaskId, taskIdOverride) {
|
|
549
|
+
const preferred = preferredTaskId?.trim();
|
|
550
|
+
if (preferred) {
|
|
551
|
+
return preferred;
|
|
552
|
+
}
|
|
553
|
+
const taskOverride = taskIdOverride?.trim();
|
|
554
|
+
if (taskOverride) {
|
|
555
|
+
return taskOverride;
|
|
556
|
+
}
|
|
557
|
+
const mcpTask = process.env.MCP_RUNNER_TASK_ID?.trim();
|
|
558
|
+
if (mcpTask) {
|
|
559
|
+
return mcpTask;
|
|
560
|
+
}
|
|
561
|
+
const taskEnv = process.env.TASK?.trim();
|
|
562
|
+
if (taskEnv) {
|
|
563
|
+
return taskEnv;
|
|
564
|
+
}
|
|
565
|
+
const codexTask = process.env.CODEX_ORCHESTRATOR_TASK_ID?.trim();
|
|
566
|
+
return codexTask && codexTask.length > 0 ? codexTask : null;
|
|
567
|
+
}
|
|
477
568
|
async function handleStart(orchestrator, rawArgs) {
|
|
478
569
|
const { positionals, flags } = parseArgs(rawArgs);
|
|
570
|
+
if (isHelpRequest(positionals, flags)) {
|
|
571
|
+
printStartHelp();
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
479
574
|
const pipelineId = positionals[0];
|
|
480
575
|
const format = flags['format'] === 'json' ? 'json' : 'text';
|
|
481
576
|
const executionMode = resolveExecutionModeFlag(flags);
|
|
577
|
+
applyRepoConfigRequiredPolicy(flags);
|
|
578
|
+
const autoIssueLogEnabled = resolveAutoIssueLogEnabled(flags);
|
|
482
579
|
if (pipelineId === 'rlm') {
|
|
483
580
|
const goal = readStringFlag(flags, 'goal');
|
|
484
581
|
const warnLegacyEnvAlias = shouldWarnLegacyMultiAgentEnv(flags, process.env);
|
|
@@ -487,31 +584,51 @@ async function handleStart(orchestrator, rawArgs) {
|
|
|
487
584
|
console.warn('Warning: RLM_SYMBOLIC_COLLAB is a legacy alias; prefer RLM_SYMBOLIC_MULTI_AGENT.');
|
|
488
585
|
}
|
|
489
586
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
587
|
+
let taskIdOverride = typeof flags['task'] === 'string' ? flags['task'] : undefined;
|
|
588
|
+
try {
|
|
589
|
+
await withRunUi(flags, format, async (runEvents) => {
|
|
590
|
+
if (pipelineId === 'rlm') {
|
|
591
|
+
taskIdOverride = resolveRlmTaskId(taskIdOverride);
|
|
592
|
+
process.env.MCP_RUNNER_TASK_ID = taskIdOverride;
|
|
593
|
+
if (format !== 'json') {
|
|
594
|
+
console.log(`Task: ${taskIdOverride}`);
|
|
595
|
+
}
|
|
497
596
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
597
|
+
const result = await orchestrator.start({
|
|
598
|
+
pipelineId,
|
|
599
|
+
taskId: taskIdOverride,
|
|
600
|
+
parentRunId: typeof flags['parent-run'] === 'string' ? flags['parent-run'] : undefined,
|
|
601
|
+
approvalPolicy: typeof flags['approval-policy'] === 'string' ? flags['approval-policy'] : undefined,
|
|
602
|
+
targetStageId: resolveTargetStageId(flags),
|
|
603
|
+
executionMode,
|
|
604
|
+
runEvents
|
|
605
|
+
});
|
|
606
|
+
const issueLogCapture = result.manifest.status !== 'succeeded'
|
|
607
|
+
? await maybeCaptureAutoIssueLog({
|
|
608
|
+
enabled: autoIssueLogEnabled,
|
|
609
|
+
issueTitle: `Auto issue log: start ${pipelineId ?? 'diagnostics'} failed`,
|
|
610
|
+
issueNotes: `Automatic failure capture for run ${result.manifest.run_id} (${result.manifest.status}).`,
|
|
611
|
+
taskFilter: resolveTaskFilter(result.manifest.task_id, taskIdOverride)
|
|
612
|
+
})
|
|
613
|
+
: { issueLog: null, issueLogError: null };
|
|
614
|
+
emitRunOutput(result, format, 'Run started', issueLogCapture);
|
|
507
615
|
});
|
|
508
|
-
|
|
509
|
-
|
|
616
|
+
}
|
|
617
|
+
catch (error) {
|
|
618
|
+
const issueLogCapture = await maybeCaptureAutoIssueLog({
|
|
619
|
+
enabled: autoIssueLogEnabled,
|
|
620
|
+
issueTitle: `Auto issue log: start ${pipelineId ?? 'diagnostics'} failed before run manifest`,
|
|
621
|
+
issueNotes: 'Automatic failure capture for start setup failure before run manifest creation.',
|
|
622
|
+
taskFilter: resolveTaskFilter(undefined, taskIdOverride)
|
|
623
|
+
});
|
|
624
|
+
throw withAutoIssueLogContext(error, issueLogCapture);
|
|
625
|
+
}
|
|
510
626
|
}
|
|
511
627
|
async function handleFrontendTest(orchestrator, rawArgs) {
|
|
512
628
|
const { positionals, flags } = parseArgs(rawArgs);
|
|
513
629
|
const format = flags['format'] === 'json' ? 'json' : 'text';
|
|
514
630
|
const devtools = Boolean(flags['devtools']);
|
|
631
|
+
applyRepoConfigRequiredPolicy(flags);
|
|
515
632
|
if (positionals.length > 0) {
|
|
516
633
|
console.error(`[frontend-test] ignoring extra arguments: ${positionals.join(' ')}`);
|
|
517
634
|
}
|
|
@@ -554,75 +671,127 @@ async function handleFlow(orchestrator, rawArgs) {
|
|
|
554
671
|
}
|
|
555
672
|
const format = flags['format'] === 'json' ? 'json' : 'text';
|
|
556
673
|
const executionMode = resolveExecutionModeFlag(flags);
|
|
674
|
+
applyRepoConfigRequiredPolicy(flags);
|
|
675
|
+
const autoIssueLogEnabled = resolveAutoIssueLogEnabled(flags);
|
|
557
676
|
const taskId = typeof flags['task'] === 'string' ? flags['task'] : undefined;
|
|
558
677
|
const parentRunId = typeof flags['parent-run'] === 'string' ? flags['parent-run'] : undefined;
|
|
559
678
|
const approvalPolicy = typeof flags['approval-policy'] === 'string' ? flags['approval-policy'] : undefined;
|
|
560
679
|
const targetStageId = resolveTargetStageId(flags);
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
680
|
+
try {
|
|
681
|
+
const { docsReviewTargetStageId, implementationGateTargetStageId } = await resolveFlowTargetStageSelection(orchestrator, taskId, targetStageId);
|
|
682
|
+
await withRunUi(flags, format, async (runEvents) => {
|
|
683
|
+
const docsReviewResult = await orchestrator.start({
|
|
684
|
+
pipelineId: 'docs-review',
|
|
685
|
+
taskId,
|
|
686
|
+
parentRunId,
|
|
687
|
+
approvalPolicy,
|
|
688
|
+
targetStageId: docsReviewTargetStageId,
|
|
689
|
+
executionMode,
|
|
690
|
+
runEvents
|
|
691
|
+
});
|
|
692
|
+
const docsPayload = toRunOutputPayload(docsReviewResult);
|
|
693
|
+
if (format === 'text') {
|
|
694
|
+
emitRunOutput(docsReviewResult, format, 'Docs-review run');
|
|
695
|
+
}
|
|
696
|
+
if (docsReviewResult.manifest.status !== 'succeeded') {
|
|
697
|
+
const issueLogCapture = await maybeCaptureAutoIssueLog({
|
|
698
|
+
enabled: autoIssueLogEnabled,
|
|
699
|
+
issueTitle: 'Auto issue log: flow docs-review failed',
|
|
700
|
+
issueNotes: `Automatic failure capture for docs-review run ${docsReviewResult.manifest.run_id} (${docsReviewResult.manifest.status}).`,
|
|
701
|
+
taskFilter: resolveTaskFilter(docsReviewResult.manifest.task_id, taskId)
|
|
702
|
+
});
|
|
703
|
+
process.exitCode = 1;
|
|
704
|
+
if (format === 'json') {
|
|
705
|
+
const payload = {
|
|
706
|
+
status: docsReviewResult.manifest.status,
|
|
707
|
+
failed_stage: 'docs-review',
|
|
708
|
+
docs_review: docsPayload,
|
|
709
|
+
implementation_gate: null,
|
|
710
|
+
issue_log: issueLogCapture.issueLog,
|
|
711
|
+
issue_log_error: issueLogCapture.issueLogError
|
|
712
|
+
};
|
|
713
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
console.log('Flow halted: docs-review failed.');
|
|
717
|
+
if (issueLogCapture.issueLog) {
|
|
718
|
+
for (const line of formatDoctorIssueLogSummary(issueLogCapture.issueLog)) {
|
|
719
|
+
console.log(line);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
if (issueLogCapture.issueLogError) {
|
|
723
|
+
console.log(`Auto issue log: failed (${issueLogCapture.issueLogError})`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
const implementationGateResult = await orchestrator.start({
|
|
729
|
+
pipelineId: 'implementation-gate',
|
|
730
|
+
taskId,
|
|
731
|
+
parentRunId: docsReviewResult.manifest.run_id,
|
|
732
|
+
approvalPolicy,
|
|
733
|
+
targetStageId: implementationGateTargetStageId,
|
|
734
|
+
executionMode,
|
|
735
|
+
runEvents
|
|
736
|
+
});
|
|
737
|
+
const implementationPayload = toRunOutputPayload(implementationGateResult);
|
|
738
|
+
const issueLogCapture = implementationGateResult.manifest.status !== 'succeeded'
|
|
739
|
+
? await maybeCaptureAutoIssueLog({
|
|
740
|
+
enabled: autoIssueLogEnabled,
|
|
741
|
+
issueTitle: 'Auto issue log: flow implementation-gate failed',
|
|
742
|
+
issueNotes: `Automatic failure capture for implementation-gate run ${implementationGateResult.manifest.run_id} (${implementationGateResult.manifest.status}).`,
|
|
743
|
+
taskFilter: resolveTaskFilter(implementationGateResult.manifest.task_id, taskId)
|
|
744
|
+
})
|
|
745
|
+
: { issueLog: null, issueLogError: null };
|
|
578
746
|
if (format === 'json') {
|
|
579
747
|
const payload = {
|
|
580
|
-
status:
|
|
581
|
-
failed_stage: '
|
|
748
|
+
status: implementationGateResult.manifest.status,
|
|
749
|
+
failed_stage: implementationGateResult.manifest.status === 'succeeded' ? null : 'implementation-gate',
|
|
582
750
|
docs_review: docsPayload,
|
|
583
|
-
implementation_gate:
|
|
751
|
+
implementation_gate: implementationPayload,
|
|
752
|
+
issue_log: issueLogCapture.issueLog,
|
|
753
|
+
issue_log_error: issueLogCapture.issueLogError
|
|
584
754
|
};
|
|
585
755
|
console.log(JSON.stringify(payload, null, 2));
|
|
756
|
+
if (implementationGateResult.manifest.status !== 'succeeded') {
|
|
757
|
+
process.exitCode = 1;
|
|
758
|
+
}
|
|
759
|
+
return;
|
|
586
760
|
}
|
|
587
|
-
|
|
588
|
-
console.log('Flow halted: docs-review failed.');
|
|
589
|
-
}
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
const implementationGateResult = await orchestrator.start({
|
|
593
|
-
pipelineId: 'implementation-gate',
|
|
594
|
-
taskId,
|
|
595
|
-
parentRunId: docsReviewResult.manifest.run_id,
|
|
596
|
-
approvalPolicy,
|
|
597
|
-
targetStageId: implementationGateTargetStageId,
|
|
598
|
-
executionMode,
|
|
599
|
-
runEvents
|
|
600
|
-
});
|
|
601
|
-
const implementationPayload = toRunOutputPayload(implementationGateResult);
|
|
602
|
-
if (format === 'json') {
|
|
603
|
-
const payload = {
|
|
604
|
-
status: implementationGateResult.manifest.status,
|
|
605
|
-
failed_stage: implementationGateResult.manifest.status === 'succeeded' ? null : 'implementation-gate',
|
|
606
|
-
docs_review: docsPayload,
|
|
607
|
-
implementation_gate: implementationPayload
|
|
608
|
-
};
|
|
609
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
761
|
+
emitRunOutput(implementationGateResult, format, 'Implementation-gate run');
|
|
610
762
|
if (implementationGateResult.manifest.status !== 'succeeded') {
|
|
611
763
|
process.exitCode = 1;
|
|
764
|
+
console.log('Flow halted: implementation-gate failed.');
|
|
765
|
+
if (issueLogCapture.issueLog) {
|
|
766
|
+
for (const line of formatDoctorIssueLogSummary(issueLogCapture.issueLog)) {
|
|
767
|
+
console.log(line);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (issueLogCapture.issueLogError) {
|
|
771
|
+
console.log(`Auto issue log: failed (${issueLogCapture.issueLogError})`);
|
|
772
|
+
}
|
|
773
|
+
return;
|
|
612
774
|
}
|
|
613
|
-
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
775
|
+
console.log('Flow complete: docs-review -> implementation-gate.');
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
catch (error) {
|
|
779
|
+
const issueLogCapture = await maybeCaptureAutoIssueLog({
|
|
780
|
+
enabled: autoIssueLogEnabled,
|
|
781
|
+
issueTitle: 'Auto issue log: flow failed before run manifest',
|
|
782
|
+
issueNotes: 'Automatic failure capture for flow setup failure before run manifest creation.',
|
|
783
|
+
taskFilter: resolveTaskFilter(undefined, taskId)
|
|
784
|
+
});
|
|
785
|
+
throw withAutoIssueLogContext(error, issueLogCapture);
|
|
786
|
+
}
|
|
623
787
|
}
|
|
624
788
|
async function handlePlan(orchestrator, rawArgs) {
|
|
625
789
|
const { positionals, flags } = parseArgs(rawArgs);
|
|
790
|
+
if (isHelpRequest(positionals, flags)) {
|
|
791
|
+
printPlanHelp();
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
applyRepoConfigRequiredPolicy(flags);
|
|
626
795
|
const pipelineId = positionals[0];
|
|
627
796
|
const format = flags['format'] === 'json' ? 'json' : 'text';
|
|
628
797
|
const result = await orchestrator.plan({
|
|
@@ -642,6 +811,7 @@ async function handleRlm(orchestrator, rawArgs) {
|
|
|
642
811
|
printRlmHelp();
|
|
643
812
|
return;
|
|
644
813
|
}
|
|
814
|
+
applyRepoConfigRequiredPolicy(flags);
|
|
645
815
|
const goalFromArgs = positionals.length > 0 ? positionals.join(' ') : undefined;
|
|
646
816
|
const goal = goalFromArgs ?? readStringFlag(flags, 'goal') ?? process.env.RLM_GOAL?.trim();
|
|
647
817
|
if (!goal) {
|
|
@@ -704,6 +874,7 @@ async function handleResume(orchestrator, rawArgs) {
|
|
|
704
874
|
printResumeHelp();
|
|
705
875
|
return;
|
|
706
876
|
}
|
|
877
|
+
applyRepoConfigRequiredPolicy(flags);
|
|
707
878
|
const runId = (flags['run'] ?? positionals[0]);
|
|
708
879
|
if (!runId) {
|
|
709
880
|
throw new Error('resume requires --run <run-id>.');
|
|
@@ -778,8 +949,8 @@ async function withRunUi(flags, format, action) {
|
|
|
778
949
|
runEvents.dispose();
|
|
779
950
|
}
|
|
780
951
|
}
|
|
781
|
-
function emitRunOutput(result, format, label) {
|
|
782
|
-
const payload = toRunOutputPayload(result);
|
|
952
|
+
function emitRunOutput(result, format, label, issueLogCapture = { issueLog: null, issueLogError: null }) {
|
|
953
|
+
const payload = toRunOutputPayload(result, issueLogCapture);
|
|
783
954
|
if (format === 'json') {
|
|
784
955
|
console.log(JSON.stringify(payload, null, 2));
|
|
785
956
|
return;
|
|
@@ -797,8 +968,16 @@ function emitRunOutput(result, format, label) {
|
|
|
797
968
|
console.log(` ${line}`);
|
|
798
969
|
}
|
|
799
970
|
}
|
|
971
|
+
if (payload.issue_log) {
|
|
972
|
+
for (const line of formatDoctorIssueLogSummary(payload.issue_log)) {
|
|
973
|
+
console.log(line);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (payload.issue_log_error) {
|
|
977
|
+
console.log(`Auto issue log: failed (${payload.issue_log_error})`);
|
|
978
|
+
}
|
|
800
979
|
}
|
|
801
|
-
function toRunOutputPayload(result) {
|
|
980
|
+
function toRunOutputPayload(result, issueLogCapture = { issueLog: null, issueLogError: null }) {
|
|
802
981
|
return {
|
|
803
982
|
run_id: result.manifest.run_id,
|
|
804
983
|
status: result.manifest.status,
|
|
@@ -806,7 +985,9 @@ function toRunOutputPayload(result) {
|
|
|
806
985
|
manifest: `${result.manifest.artifact_root}/manifest.json`,
|
|
807
986
|
log_path: result.manifest.log_path,
|
|
808
987
|
summary: result.manifest.summary ?? null,
|
|
809
|
-
cloud_fallback_reason: result.manifest.cloud_fallback?.reason ?? null
|
|
988
|
+
cloud_fallback_reason: result.manifest.cloud_fallback?.reason ?? null,
|
|
989
|
+
issue_log: issueLogCapture.issueLog,
|
|
990
|
+
issue_log_error: issueLogCapture.issueLogError
|
|
810
991
|
};
|
|
811
992
|
}
|
|
812
993
|
async function handleExec(rawArgs) {
|
|
@@ -907,6 +1088,10 @@ async function handleSelfCheck(rawArgs) {
|
|
|
907
1088
|
}
|
|
908
1089
|
async function handleInit(rawArgs) {
|
|
909
1090
|
const { positionals, flags } = parseArgs(rawArgs);
|
|
1091
|
+
if (isHelpRequest(positionals, flags)) {
|
|
1092
|
+
printInitHelp();
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
910
1095
|
const template = positionals[0];
|
|
911
1096
|
if (!template) {
|
|
912
1097
|
throw new Error('init requires a template name (e.g. init codex).');
|
|
@@ -965,8 +1150,9 @@ Options:
|
|
|
965
1150
|
}
|
|
966
1151
|
const repoFlag = readStringFlag(flags, 'repo');
|
|
967
1152
|
const repoRoot = repoFlag ?? process.cwd();
|
|
968
|
-
const
|
|
969
|
-
|
|
1153
|
+
const delegationCommandPreview = repoFlag
|
|
1154
|
+
? buildCommandPreview('codex-orchestrator', ['delegation', 'setup', '--yes', '--repo', repoFlag])
|
|
1155
|
+
: 'codex-orchestrator delegation setup --yes';
|
|
970
1156
|
const bundledSkills = await listBundledSkills();
|
|
971
1157
|
if (bundledSkills.length === 0) {
|
|
972
1158
|
throw new Error('No bundled skills detected; cannot run setup.');
|
|
@@ -1000,7 +1186,7 @@ Options:
|
|
|
1000
1186
|
for (const commandLine of payload.steps.skills.commandLines) {
|
|
1001
1187
|
console.log(` - ${commandLine}`);
|
|
1002
1188
|
}
|
|
1003
|
-
console.log(`- Delegation:
|
|
1189
|
+
console.log(`- Delegation: ${delegationCommandPreview}`);
|
|
1004
1190
|
console.log('- DevTools: codex-orchestrator devtools setup --yes');
|
|
1005
1191
|
for (const line of formatSetupGuidanceSummary(guidance)) {
|
|
1006
1192
|
console.log(line);
|
|
@@ -1063,11 +1249,18 @@ async function handleDoctor(rawArgs) {
|
|
|
1063
1249
|
const format = flags['format'] === 'json' ? 'json' : 'text';
|
|
1064
1250
|
const includeUsage = Boolean(flags['usage']);
|
|
1065
1251
|
const includeCloudPreflight = Boolean(flags['cloud-preflight']);
|
|
1252
|
+
const includeIssueLog = Boolean(flags['issue-log']);
|
|
1066
1253
|
const cloudEnvIdOverride = readStringFlag(flags, 'cloud-env-id');
|
|
1067
1254
|
const cloudBranchOverride = readStringFlag(flags, 'cloud-branch');
|
|
1255
|
+
const issueTitle = readStringFlag(flags, 'issue-title');
|
|
1256
|
+
const issueNotes = readStringFlag(flags, 'issue-notes');
|
|
1257
|
+
const issueLogPath = readStringFlag(flags, 'issue-log-path');
|
|
1068
1258
|
if (!includeCloudPreflight && (cloudEnvIdOverride || cloudBranchOverride)) {
|
|
1069
1259
|
throw new Error('--cloud-env-id/--cloud-branch require --cloud-preflight.');
|
|
1070
1260
|
}
|
|
1261
|
+
if (!includeIssueLog && (issueTitle || issueNotes || issueLogPath)) {
|
|
1262
|
+
throw new Error('--issue-title/--issue-notes/--issue-log-path require --issue-log.');
|
|
1263
|
+
}
|
|
1071
1264
|
const wantsApply = Boolean(flags['apply']);
|
|
1072
1265
|
const apply = Boolean(flags['yes']);
|
|
1073
1266
|
if (wantsApply && format === 'json') {
|
|
@@ -1096,6 +1289,17 @@ async function handleDoctor(rawArgs) {
|
|
|
1096
1289
|
taskId: taskFilter
|
|
1097
1290
|
})
|
|
1098
1291
|
: null;
|
|
1292
|
+
const issueLogResult = includeIssueLog
|
|
1293
|
+
? await writeDoctorIssueLog({
|
|
1294
|
+
doctor: doctorResult,
|
|
1295
|
+
usage: usageResult,
|
|
1296
|
+
cloudPreflight: cloudPreflightResult,
|
|
1297
|
+
issueTitle,
|
|
1298
|
+
issueNotes,
|
|
1299
|
+
issueLogPath,
|
|
1300
|
+
taskFilter
|
|
1301
|
+
})
|
|
1302
|
+
: null;
|
|
1099
1303
|
if (format === 'json') {
|
|
1100
1304
|
const payload = { ...doctorResult };
|
|
1101
1305
|
if (usageResult) {
|
|
@@ -1104,6 +1308,9 @@ async function handleDoctor(rawArgs) {
|
|
|
1104
1308
|
if (cloudPreflightResult) {
|
|
1105
1309
|
payload.cloud_preflight = cloudPreflightResult;
|
|
1106
1310
|
}
|
|
1311
|
+
if (issueLogResult) {
|
|
1312
|
+
payload.issue_log = issueLogResult;
|
|
1313
|
+
}
|
|
1107
1314
|
console.log(JSON.stringify(payload, null, 2));
|
|
1108
1315
|
return;
|
|
1109
1316
|
}
|
|
@@ -1120,6 +1327,11 @@ async function handleDoctor(rawArgs) {
|
|
|
1120
1327
|
console.log(line);
|
|
1121
1328
|
}
|
|
1122
1329
|
}
|
|
1330
|
+
if (issueLogResult) {
|
|
1331
|
+
for (const line of formatDoctorIssueLogSummary(issueLogResult)) {
|
|
1332
|
+
console.log(line);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1123
1335
|
if (!wantsApply) {
|
|
1124
1336
|
return;
|
|
1125
1337
|
}
|
|
@@ -1672,6 +1884,8 @@ Commands:
|
|
|
1672
1884
|
--execution-mode <mcp|cloud> Force execution mode for this run and child subpipelines.
|
|
1673
1885
|
--cloud Shortcut for --execution-mode cloud.
|
|
1674
1886
|
--target <stage-id> Focus plan/build metadata on a specific stage (alias: --target-stage).
|
|
1887
|
+
--auto-issue-log [true|false] On failure, auto-write doctor issue bundle/log entry.
|
|
1888
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1675
1889
|
--goal "<goal>" When pipeline is rlm, set the RLM goal.
|
|
1676
1890
|
--multi-agent [auto|true|false] Preferred alias for multi-agent collab subagents (implies symbolic mode).
|
|
1677
1891
|
--collab [auto|true|false] Legacy alias for --multi-agent.
|
|
@@ -1684,6 +1898,7 @@ Commands:
|
|
|
1684
1898
|
|
|
1685
1899
|
rlm "<goal>" Run RLM loop until validator passes.
|
|
1686
1900
|
--task <id> Override task identifier.
|
|
1901
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1687
1902
|
--multi-agent [auto|true|false] Preferred alias for multi-agent collab subagents (implies symbolic mode).
|
|
1688
1903
|
--collab [auto|true|false] Legacy alias for --multi-agent.
|
|
1689
1904
|
--validator <cmd|none> Set validator command or disable validation.
|
|
@@ -1698,6 +1913,7 @@ Commands:
|
|
|
1698
1913
|
frontend-test Run frontend testing pipeline.
|
|
1699
1914
|
--devtools Enable Chrome DevTools MCP for this run.
|
|
1700
1915
|
--task <id> Override task identifier (defaults to MCP_RUNNER_TASK_ID).
|
|
1916
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1701
1917
|
--parent-run <id> Link run to parent run id.
|
|
1702
1918
|
--approval-policy <p> Record approval policy metadata.
|
|
1703
1919
|
--format json Emit machine-readable output.
|
|
@@ -1713,6 +1929,8 @@ Commands:
|
|
|
1713
1929
|
--execution-mode <mcp|cloud> Force execution mode for both runs.
|
|
1714
1930
|
--cloud Shortcut for --execution-mode cloud.
|
|
1715
1931
|
--target <stage-id> Focus plan/build metadata on a specific stage (alias: --target-stage).
|
|
1932
|
+
--auto-issue-log [true|false] On failure, auto-write doctor issue bundle/log entry.
|
|
1933
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1716
1934
|
--interactive | --ui Enable read-only HUD when running in a TTY.
|
|
1717
1935
|
--no-interactive Force disable HUD (default is off unless requested).
|
|
1718
1936
|
|
|
@@ -1720,6 +1938,7 @@ Commands:
|
|
|
1720
1938
|
--task <id> Override task identifier.
|
|
1721
1939
|
--format json Emit machine-readable output.
|
|
1722
1940
|
--target <stage-id> Highlight the stage chosen for orchestration (alias: --target-stage).
|
|
1941
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1723
1942
|
|
|
1724
1943
|
exec [command] Run a one-off command with unified exec runtime.
|
|
1725
1944
|
--json [compact] Emit final JSON summary (optional compact mode).
|
|
@@ -1734,6 +1953,7 @@ Commands:
|
|
|
1734
1953
|
--actor <name> Record who resumed the run.
|
|
1735
1954
|
--reason <text> Record why the run was resumed.
|
|
1736
1955
|
--target <stage-id> Override stage selection before resuming (alias: --target-stage).
|
|
1956
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1737
1957
|
--format json Emit machine-readable output.
|
|
1738
1958
|
--interactive | --ui Enable read-only HUD when running in a TTY.
|
|
1739
1959
|
--no-interactive Force disable HUD (default is off unless requested).
|
|
@@ -1742,6 +1962,7 @@ Commands:
|
|
|
1742
1962
|
|
|
1743
1963
|
self-check [--format json]
|
|
1744
1964
|
init codex [--cwd <path>] [--force]
|
|
1965
|
+
Installs AGENTS.md, mcp-client.json, and codex.orchestrator.json.
|
|
1745
1966
|
--codex-cli Also run CO-managed Codex CLI setup (plan unless --yes; activate with CODEX_CLI_USE_MANAGED=1).
|
|
1746
1967
|
--codex-source <path> Build from local Codex repo (or git URL).
|
|
1747
1968
|
--codex-ref <ref> Git ref (branch/tag/sha) when building from repo.
|
|
@@ -1761,6 +1982,10 @@ Commands:
|
|
|
1761
1982
|
--cloud-preflight Run cloud readiness preflight checks (env/codex/git/branch).
|
|
1762
1983
|
--cloud-env-id <id> Override env id for --cloud-preflight (default: CODEX_CLOUD_ENV_ID).
|
|
1763
1984
|
--cloud-branch <name> Override branch for --cloud-preflight (default: CODEX_CLOUD_BRANCH).
|
|
1985
|
+
--issue-log Append markdown issue entry + JSON bundle for downstream triage.
|
|
1986
|
+
--issue-title <text> Optional title for --issue-log entries.
|
|
1987
|
+
--issue-notes <text> Optional notes for --issue-log entries.
|
|
1988
|
+
--issue-log-path <p> Output markdown path (default: docs/codex-orchestrator-issues.md).
|
|
1764
1989
|
--apply Plan/apply quick fixes for DevTools + delegation wiring (use with --yes).
|
|
1765
1990
|
--yes Apply fixes when --apply is set.
|
|
1766
1991
|
--format json Emit machine-readable output (not supported with --apply).
|
|
@@ -1841,6 +2066,7 @@ Options:
|
|
|
1841
2066
|
--actor <name> Record who resumed the run.
|
|
1842
2067
|
--reason <text> Record why the run was resumed.
|
|
1843
2068
|
--target <stage-id> Override stage selection before resuming.
|
|
2069
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1844
2070
|
--format json Emit machine-readable output.
|
|
1845
2071
|
--interactive | --ui Enable read-only HUD when running in a TTY.
|
|
1846
2072
|
--no-interactive Force disable HUD.
|
|
@@ -1891,6 +2117,7 @@ function printRlmHelp() {
|
|
|
1891
2117
|
Options:
|
|
1892
2118
|
--goal "<goal>" Alternate way to set the goal (positional is preferred).
|
|
1893
2119
|
--task <id> Override task identifier (defaults to MCP_RUNNER_TASK_ID).
|
|
2120
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1894
2121
|
--multi-agent [auto|true|false] Preferred alias for multi-agent collab subagents (implies symbolic mode).
|
|
1895
2122
|
--collab [auto|true|false] Legacy alias for --multi-agent.
|
|
1896
2123
|
--validator <cmd|none> Set validator command or disable validation.
|
|
@@ -1925,7 +2152,67 @@ Options:
|
|
|
1925
2152
|
--execution-mode <mcp|cloud> Force execution mode for both runs.
|
|
1926
2153
|
--cloud Shortcut for --execution-mode cloud.
|
|
1927
2154
|
--target <stage-id> Focus plan/build metadata (applies where the stage exists).
|
|
2155
|
+
--auto-issue-log [true|false] On failure, auto-write doctor issue bundle/log entry.
|
|
2156
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
1928
2157
|
--interactive | --ui Enable read-only HUD when running in a TTY.
|
|
1929
2158
|
--no-interactive Force disable HUD.
|
|
1930
2159
|
`);
|
|
1931
2160
|
}
|
|
2161
|
+
function printStartHelp() {
|
|
2162
|
+
console.log(`Usage: codex-orchestrator start [pipeline] [options]
|
|
2163
|
+
|
|
2164
|
+
Start a new run. If no pipeline is provided, diagnostics is used.
|
|
2165
|
+
|
|
2166
|
+
Options:
|
|
2167
|
+
--task <id> Override task identifier.
|
|
2168
|
+
--parent-run <id> Link run to parent run id.
|
|
2169
|
+
--approval-policy <p> Record approval policy metadata.
|
|
2170
|
+
--format json Emit machine-readable output.
|
|
2171
|
+
--execution-mode <mcp|cloud> Force execution mode for this run.
|
|
2172
|
+
--cloud Shortcut for --execution-mode cloud.
|
|
2173
|
+
--target <stage-id> Focus plan/build metadata on a specific stage.
|
|
2174
|
+
--auto-issue-log [true|false] On failure, auto-write doctor issue bundle/log entry.
|
|
2175
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
2176
|
+
--goal "<goal>" When pipeline is rlm, set the RLM goal.
|
|
2177
|
+
--multi-agent [auto|true|false] Preferred alias for multi-agent collab subagents.
|
|
2178
|
+
--collab [auto|true|false] Legacy alias for --multi-agent.
|
|
2179
|
+
--validator <cmd|none> When pipeline is rlm, set validator command.
|
|
2180
|
+
--max-iterations <n> When pipeline is rlm, override max iterations.
|
|
2181
|
+
--max-minutes <n> When pipeline is rlm, override max minutes.
|
|
2182
|
+
--roles <single|triad> When pipeline is rlm, set role split.
|
|
2183
|
+
--interactive | --ui Enable read-only HUD when running in a TTY.
|
|
2184
|
+
--no-interactive Force disable HUD.
|
|
2185
|
+
`);
|
|
2186
|
+
}
|
|
2187
|
+
function printPlanHelp() {
|
|
2188
|
+
console.log(`Usage: codex-orchestrator plan [pipeline] [options]
|
|
2189
|
+
|
|
2190
|
+
Preview pipeline stages without executing.
|
|
2191
|
+
|
|
2192
|
+
Options:
|
|
2193
|
+
--task <id> Override task identifier.
|
|
2194
|
+
--format json Emit machine-readable output.
|
|
2195
|
+
--target <stage-id> Highlight the stage chosen for orchestration.
|
|
2196
|
+
--repo-config-required [true|false] Require repo-local codex.orchestrator.json (no package fallback).
|
|
2197
|
+
`);
|
|
2198
|
+
}
|
|
2199
|
+
function printInitHelp() {
|
|
2200
|
+
console.log(`Usage: codex-orchestrator init codex [options]
|
|
2201
|
+
|
|
2202
|
+
Install starter templates into the target repository:
|
|
2203
|
+
- AGENTS.md
|
|
2204
|
+
- mcp-client.json
|
|
2205
|
+
- codex.orchestrator.json
|
|
2206
|
+
|
|
2207
|
+
Options:
|
|
2208
|
+
--cwd <path> Target directory (default current directory).
|
|
2209
|
+
--force Overwrite existing template files.
|
|
2210
|
+
--codex-cli Also run CO-managed Codex CLI setup (plan unless --yes).
|
|
2211
|
+
--codex-source <path> Build managed Codex CLI from local repo (or git URL).
|
|
2212
|
+
--codex-ref <ref> Git ref for --codex-source.
|
|
2213
|
+
--codex-download-url <url> Download managed Codex CLI prebuilt binary.
|
|
2214
|
+
--codex-download-sha256 <sha> Expected SHA256 for the prebuilt download.
|
|
2215
|
+
--codex-force Overwrite existing managed Codex CLI binary.
|
|
2216
|
+
--yes Apply managed Codex CLI setup.
|
|
2217
|
+
`);
|
|
2218
|
+
}
|