@kbediako/codex-orchestrator 0.1.23 → 0.1.25

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 CHANGED
@@ -130,6 +130,11 @@ flowchart TB
130
130
 
131
131
  ## Skills (bundled)
132
132
 
133
+ Recommended one-shot bootstrap (skills + delegation + DevTools wiring):
134
+ ```bash
135
+ codex-orchestrator setup --yes
136
+ ```
137
+
133
138
  The release ships skills under `skills/` for downstream packaging. If you already have global skills installed, treat those as the primary reference and use bundled skills as the shipped fallback. Install bundled skills into `$CODEX_HOME/skills`:
134
139
  ```bash
135
140
  codex-orchestrator skills install
@@ -142,6 +147,7 @@ Options:
142
147
 
143
148
  Bundled skills (may vary by release):
144
149
  - `collab-subagents-first`
150
+ - `chrome-devtools`
145
151
  - `delegation-usage`
146
152
  - `standalone-review`
147
153
  - `docs-first`
@@ -157,11 +163,24 @@ Check readiness (deps + capability wiring):
157
163
  codex-orchestrator doctor --format json
158
164
  ```
159
165
 
166
+ Auto-fix wiring (delegation + DevTools):
167
+ ```bash
168
+ codex-orchestrator doctor --apply --yes
169
+ ```
170
+
160
171
  Usage snapshot (scans local `.runs/`):
161
172
  ```bash
162
173
  codex-orchestrator doctor --usage
163
174
  ```
164
175
 
176
+ ## Downstream usage cheatsheet (agent-first)
177
+
178
+ - Bootstrap + wire everything: `codex-orchestrator setup --yes`
179
+ - Validate + measure adoption locally: `codex-orchestrator doctor --usage --format json`
180
+ - Delegation: `codex-orchestrator doctor --apply --yes`, then enable for a Codex run with: `codex -c 'mcp_servers.delegation.enabled=true' ...`
181
+ - Collab (symbolic RLM subagents): `codex-orchestrator rlm "<goal>" --collab auto` (requires collab feature enabled in Codex)
182
+ - Cloud: set `CODEX_CLOUD_ENV_ID` (and optional `CODEX_CLOUD_BRANCH`), then run: `codex-orchestrator start <pipeline> --cloud --target <stage-id>`
183
+
165
184
  Print DevTools MCP setup guidance:
166
185
  ```bash
167
186
  codex-orchestrator devtools setup
@@ -173,6 +192,7 @@ codex-orchestrator devtools setup
173
192
  - `codex-orchestrator plan <pipeline>` — preview pipeline stages.
174
193
  - `codex-orchestrator exec <cmd>` — run a one-off command with the exec runtime.
175
194
  - `codex-orchestrator init codex` — install starter templates (`mcp-client.json`, `AGENTS.md`) into a repo.
195
+ - `codex-orchestrator setup --yes` — install bundled skills and configure delegation + DevTools wiring.
176
196
  - `codex-orchestrator init codex --codex-cli --yes --codex-source <path>` — optionally provision a CO-managed Codex CLI binary (build-from-source default; set `CODEX_CLI_SOURCE` to avoid passing `--codex-source` every time).
177
197
  - `codex-orchestrator init codex --codex-cli --yes --codex-download-url <url> --codex-download-sha256 <sha>` — opt-in to a prebuilt Codex CLI download.
178
198
  - `codex-orchestrator codex setup` — plan/apply a CO-managed Codex CLI install (optional managed/pinned path; use `--download-url` + `--download-sha256` for prebuilts).
@@ -18,7 +18,7 @@ import { formatDoctorUsageSummary, runDoctorUsage } from '../orchestrator/src/cl
18
18
  import { formatDevtoolsSetupSummary, runDevtoolsSetup } from '../orchestrator/src/cli/devtoolsSetup.js';
19
19
  import { formatCodexCliSetupSummary, runCodexCliSetup } from '../orchestrator/src/cli/codexCliSetup.js';
20
20
  import { formatDelegationSetupSummary, runDelegationSetup } from '../orchestrator/src/cli/delegationSetup.js';
21
- import { formatSkillsInstallSummary, installSkills } from '../orchestrator/src/cli/skills.js';
21
+ import { formatSkillsInstallSummary, installSkills, listBundledSkills } from '../orchestrator/src/cli/skills.js';
22
22
  import { loadPackageInfo } from '../orchestrator/src/cli/utils/packageInfo.js';
23
23
  import { slugify } from '../orchestrator/src/cli/utils/strings.js';
24
24
  import { serveMcp } from '../orchestrator/src/cli/mcp.js';
@@ -65,6 +65,9 @@ async function main() {
65
65
  case 'init':
66
66
  await handleInit(args);
67
67
  break;
68
+ case 'setup':
69
+ await handleSetup(args);
70
+ break;
68
71
  case 'doctor':
69
72
  await handleDoctor(args);
70
73
  break;
@@ -556,10 +559,106 @@ async function handleInit(rawArgs) {
556
559
  }
557
560
  }
558
561
  }
562
+ async function handleSetup(rawArgs) {
563
+ const { positionals, flags } = parseArgs(rawArgs);
564
+ if (isHelpRequest(positionals, flags)) {
565
+ console.log(`Usage: codex-orchestrator setup [--yes] [--format json]
566
+
567
+ One-shot bootstrap for downstream users. Installs bundled skills and configures
568
+ delegation + DevTools MCP wiring.
569
+
570
+ Options:
571
+ --yes Apply setup (otherwise plan only).
572
+ --repo <path> Repo root for delegation wiring (default cwd).
573
+ --format json Emit machine-readable output (dry-run only).
574
+ `);
575
+ return;
576
+ }
577
+ const format = flags['format'] === 'json' ? 'json' : 'text';
578
+ const apply = Boolean(flags['yes']);
579
+ if (format === 'json' && apply) {
580
+ throw new Error('setup does not support --format json with --yes.');
581
+ }
582
+ const repoFlag = readStringFlag(flags, 'repo');
583
+ const repoRoot = repoFlag ?? process.cwd();
584
+ const repoFlagValue = repoFlag ? (/\s/u.test(repoFlag) ? JSON.stringify(repoFlag) : repoFlag) : null;
585
+ const delegationRepoArg = repoFlagValue ? ` --repo ${repoFlagValue}` : '';
586
+ const bundledSkills = await listBundledSkills();
587
+ if (bundledSkills.length === 0) {
588
+ throw new Error('No bundled skills detected; cannot run setup.');
589
+ }
590
+ const forceSkills = bundledSkills.filter((skill) => skill !== 'chrome-devtools');
591
+ if (!apply) {
592
+ const forceOnly = forceSkills.join(',');
593
+ const forceCommand = forceOnly ? `codex-orchestrator skills install --force --only ${forceOnly}` : null;
594
+ const devtoolsCommand = bundledSkills.includes('chrome-devtools')
595
+ ? 'codex-orchestrator skills install --only chrome-devtools'
596
+ : null;
597
+ const delegation = await runDelegationSetup({ repoRoot });
598
+ const devtools = await runDevtoolsSetup();
599
+ const payload = {
600
+ status: 'planned',
601
+ steps: {
602
+ skills: {
603
+ commandLines: [forceCommand, devtoolsCommand].filter((entry) => Boolean(entry)),
604
+ note: 'Installs bundled skills into $CODEX_HOME/skills (setup avoids overwriting chrome-devtools when already present).'
605
+ },
606
+ delegation,
607
+ devtools
608
+ }
609
+ };
610
+ if (format === 'json') {
611
+ console.log(JSON.stringify(payload, null, 2));
612
+ return;
613
+ }
614
+ console.log('Setup plan:');
615
+ console.log('- Skills:');
616
+ for (const commandLine of payload.steps.skills.commandLines) {
617
+ console.log(` - ${commandLine}`);
618
+ }
619
+ console.log(`- Delegation: codex-orchestrator delegation setup --yes${delegationRepoArg}`);
620
+ console.log('- DevTools: codex-orchestrator devtools setup --yes');
621
+ console.log('Run with --yes to apply this setup.');
622
+ return;
623
+ }
624
+ const primarySkills = forceSkills.length > 0 ? await installSkills({ force: true, only: forceSkills }) : null;
625
+ const devtoolsSkill = bundledSkills.includes('chrome-devtools')
626
+ ? await installSkills({ force: false, only: ['chrome-devtools'] })
627
+ : null;
628
+ const skills = primarySkills && devtoolsSkill
629
+ ? {
630
+ sourceRoot: primarySkills.sourceRoot,
631
+ targetRoot: primarySkills.targetRoot,
632
+ skills: [...new Set([...primarySkills.skills, ...devtoolsSkill.skills])],
633
+ written: [...primarySkills.written, ...devtoolsSkill.written],
634
+ skipped: [...primarySkills.skipped, ...devtoolsSkill.skipped]
635
+ }
636
+ : devtoolsSkill ?? primarySkills;
637
+ if (!skills) {
638
+ throw new Error('No bundled skills detected; cannot run setup.');
639
+ }
640
+ const delegation = await runDelegationSetup({ apply: true, repoRoot });
641
+ const devtools = await runDevtoolsSetup({ apply: true });
642
+ for (const line of formatSkillsInstallSummary(skills)) {
643
+ console.log(line);
644
+ }
645
+ for (const line of formatDelegationSetupSummary(delegation)) {
646
+ console.log(line);
647
+ }
648
+ for (const line of formatDevtoolsSetupSummary(devtools)) {
649
+ console.log(line);
650
+ }
651
+ console.log('Next: codex-orchestrator doctor --usage');
652
+ }
559
653
  async function handleDoctor(rawArgs) {
560
654
  const { flags } = parseArgs(rawArgs);
561
655
  const format = flags['format'] === 'json' ? 'json' : 'text';
562
656
  const includeUsage = Boolean(flags['usage']);
657
+ const wantsApply = Boolean(flags['apply']);
658
+ const apply = Boolean(flags['yes']);
659
+ if (wantsApply && format === 'json') {
660
+ throw new Error('doctor --apply does not support --format json.');
661
+ }
563
662
  const windowDaysRaw = readStringFlag(flags, 'window-days');
564
663
  let windowDays = undefined;
565
664
  if (windowDaysRaw) {
@@ -591,6 +690,63 @@ async function handleDoctor(rawArgs) {
591
690
  console.log(line);
592
691
  }
593
692
  }
693
+ if (!wantsApply) {
694
+ return;
695
+ }
696
+ const repoRoot = process.cwd();
697
+ const delegationPlan = await runDelegationSetup({ repoRoot });
698
+ const devtoolsPlan = await runDevtoolsSetup();
699
+ const needsDelegation = !delegationPlan.readiness.configured;
700
+ const needsDevtoolsSkill = devtoolsPlan.readiness.skill.status !== 'ok';
701
+ const devtoolsConfigStatus = devtoolsPlan.readiness.config.status;
702
+ const needsDevtoolsConfig = devtoolsConfigStatus === 'missing';
703
+ const hasInvalidDevtoolsConfig = devtoolsConfigStatus === 'invalid';
704
+ if (!needsDelegation && !needsDevtoolsSkill && !needsDevtoolsConfig && !hasInvalidDevtoolsConfig) {
705
+ console.log('Doctor apply: nothing to do.');
706
+ return;
707
+ }
708
+ console.log('Doctor apply plan:');
709
+ if (needsDevtoolsSkill) {
710
+ console.log('- Install skill: chrome-devtools (codex-orchestrator skills install --only chrome-devtools)');
711
+ }
712
+ if (hasInvalidDevtoolsConfig) {
713
+ console.log(`- DevTools MCP config is invalid: ${devtoolsPlan.readiness.config.path} (fix config.toml then rerun doctor --apply)`);
714
+ }
715
+ if (needsDevtoolsConfig) {
716
+ console.log('- Configure DevTools MCP: codex-orchestrator devtools setup --yes');
717
+ }
718
+ if (needsDelegation) {
719
+ console.log('- Configure delegation MCP: codex-orchestrator delegation setup --yes');
720
+ }
721
+ if (!apply) {
722
+ console.log('Run with --apply --yes to apply these fixes.');
723
+ return;
724
+ }
725
+ if (needsDevtoolsSkill) {
726
+ const skills = await installSkills({ only: ['chrome-devtools'] });
727
+ for (const line of formatSkillsInstallSummary(skills)) {
728
+ console.log(line);
729
+ }
730
+ }
731
+ if (needsDelegation) {
732
+ const delegation = await runDelegationSetup({ apply: true, repoRoot });
733
+ for (const line of formatDelegationSetupSummary(delegation)) {
734
+ console.log(line);
735
+ }
736
+ }
737
+ if (hasInvalidDevtoolsConfig) {
738
+ console.log(`DevTools setup: skipped (config.toml is invalid: ${devtoolsPlan.readiness.config.path}). Fix it and rerun doctor --apply --yes.`);
739
+ }
740
+ else if (needsDevtoolsConfig) {
741
+ const devtools = await runDevtoolsSetup({ apply: true });
742
+ for (const line of formatDevtoolsSetupSummary(devtools)) {
743
+ console.log(line);
744
+ }
745
+ }
746
+ const doctorAfter = runDoctor();
747
+ for (const line of formatDoctorSummary(doctorAfter)) {
748
+ console.log(line);
749
+ }
594
750
  }
595
751
  async function handleDevtools(rawArgs) {
596
752
  const { positionals, flags } = parseArgs(rawArgs);
@@ -1023,11 +1179,17 @@ Commands:
1023
1179
  --codex-download-sha256 <sha> Expected SHA256 for the prebuilt download.
1024
1180
  --codex-force Overwrite existing CO-managed codex binary.
1025
1181
  --yes Apply codex CLI setup (otherwise plan only).
1026
- doctor [--format json] [--usage] [--window-days <n>] [--task <id>]
1182
+ setup [--yes] [--format json]
1183
+ --yes Apply setup (otherwise plan only).
1184
+ --repo <path> Repo root for delegation wiring (default cwd).
1185
+ --format json Emit machine-readable output (dry-run only).
1186
+ doctor [--format json] [--usage] [--window-days <n>] [--task <id>] [--apply]
1027
1187
  --usage Include a local usage snapshot (scans .runs/).
1028
1188
  --window-days <n> Window for --usage (default 30).
1029
1189
  --task <id> Limit --usage scan to a specific task directory.
1030
- --format json Emit machine-readable output.
1190
+ --apply Plan/apply quick fixes for DevTools + delegation wiring (use with --yes).
1191
+ --yes Apply fixes when --apply is set.
1192
+ --format json Emit machine-readable output (not supported with --apply).
1031
1193
  codex setup
1032
1194
  --source <path> Build from local Codex repo (or git URL).
1033
1195
  --ref <ref> Git ref (branch/tag/sha) when building from repo.
@@ -20,7 +20,8 @@ export async function runDevtoolsSetup(options = {}) {
20
20
  throw new Error(`Cannot apply DevTools setup because config.toml is invalid: ${readiness.config.path}`);
21
21
  }
22
22
  await applyDevtoolsSetup(plan, env);
23
- return { status: 'applied', plan, readiness };
23
+ const readinessAfter = resolveDevtoolsReadiness(env);
24
+ return { status: 'applied', plan, readiness: readinessAfter };
24
25
  }
25
26
  export function formatDevtoolsSetupSummary(result) {
26
27
  const lines = [];
@@ -51,6 +51,7 @@ export function runDoctor(cwd = process.cwd()) {
51
51
  install: readiness.config.status === 'ok'
52
52
  ? undefined
53
53
  : [
54
+ 'Quick fix: codex-orchestrator doctor --apply --yes',
54
55
  'Run: codex-orchestrator devtools setup',
55
56
  `Run: ${setupPlan.commandLine}`,
56
57
  `Config path: ${setupPlan.configPath}`,
@@ -115,6 +116,7 @@ export function runDoctor(cwd = process.cwd()) {
115
116
  status: delegationStatus,
116
117
  config: delegationConfig,
117
118
  enablement: [
119
+ 'Quick fix: codex-orchestrator doctor --apply --yes',
118
120
  'Run: codex-orchestrator delegation setup --yes',
119
121
  'Or manually: codex mcp add delegation -- codex-orchestrator delegate-server',
120
122
  "Enable for a run with: codex -c 'mcp_servers.delegation.enabled=true' ...",
@@ -14,14 +14,25 @@ export async function runDoctorUsage(options = {}) {
14
14
  const seenRunIds = new Set();
15
15
  const pipelines = new Map();
16
16
  const cloudByStatus = {};
17
+ const cloudByDiffStatus = {};
18
+ const cloudByApplyStatus = {};
19
+ const cloudEnvIds = new Map();
20
+ const cloudTasks = new Set();
17
21
  const statusCounts = { total: 0, succeeded: 0, failed: 0, cancelled: 0, other: 0 };
18
22
  let cloudRuns = 0;
19
23
  let rlmRuns = 0;
24
+ const rlmTasks = new Set();
20
25
  let collabRunsWithToolCalls = 0;
21
26
  let collabTotalToolCalls = 0;
27
+ const collabTasks = new Set();
28
+ const collabByStatus = {};
29
+ const collabByEventType = {};
30
+ const collabTools = new Map();
22
31
  const collabCaptureDisabled = String(process.env.CODEX_ORCHESTRATOR_COLLAB_MAX_EVENTS ?? '').trim() === '0';
23
32
  const activeIndexTasks = new Set();
24
33
  const taskKeys = readTaskIndexKeys(env.repoRoot);
34
+ const tasksWithChildRuns = new Set();
35
+ let totalChildRuns = 0;
25
36
  for (const manifestPath of manifestPaths) {
26
37
  const runIdFromPath = extractRunIdFromManifestPath(manifestPath);
27
38
  if (!runIdFromPath) {
@@ -68,19 +79,54 @@ export async function runDoctorUsage(options = {}) {
68
79
  pipelines.set(pipelineId, (pipelines.get(pipelineId) ?? 0) + 1);
69
80
  if (pipelineId === 'rlm') {
70
81
  rlmRuns += 1;
82
+ if (typeof manifest.task_id === 'string' && manifest.task_id) {
83
+ rlmTasks.add(manifest.task_id);
84
+ }
71
85
  }
72
86
  if (manifest.cloud_execution) {
73
87
  cloudRuns += 1;
74
- const status = (manifest.cloud_execution.status ?? 'unknown').trim() || 'unknown';
88
+ const cloudStatusRaw = manifest.cloud_execution.status;
89
+ const status = typeof cloudStatusRaw === 'string' ? cloudStatusRaw.trim() || 'unknown' : 'unknown';
75
90
  cloudByStatus[status] = (cloudByStatus[status] ?? 0) + 1;
91
+ const cloudDiffRaw = manifest.cloud_execution.diff_status;
92
+ const diffStatus = typeof cloudDiffRaw === 'string' ? cloudDiffRaw.trim() || 'unknown' : 'unknown';
93
+ cloudByDiffStatus[diffStatus] = (cloudByDiffStatus[diffStatus] ?? 0) + 1;
94
+ const cloudApplyRaw = manifest.cloud_execution.apply_status;
95
+ const applyStatus = typeof cloudApplyRaw === 'string' ? cloudApplyRaw.trim() || 'unknown' : 'unknown';
96
+ cloudByApplyStatus[applyStatus] = (cloudByApplyStatus[applyStatus] ?? 0) + 1;
97
+ const cloudEnvIdRaw = manifest.cloud_execution.environment_id;
98
+ const envId = typeof cloudEnvIdRaw === 'string' ? cloudEnvIdRaw.trim() : '';
99
+ if (envId) {
100
+ cloudEnvIds.set(envId, (cloudEnvIds.get(envId) ?? 0) + 1);
101
+ }
102
+ if (typeof manifest.task_id === 'string' && manifest.task_id) {
103
+ cloudTasks.add(manifest.task_id);
104
+ }
76
105
  }
77
106
  if (Array.isArray(manifest.collab_tool_calls) && manifest.collab_tool_calls.length > 0) {
78
107
  collabRunsWithToolCalls += 1;
79
108
  collabTotalToolCalls += manifest.collab_tool_calls.length;
109
+ if (typeof manifest.task_id === 'string' && manifest.task_id) {
110
+ collabTasks.add(manifest.task_id);
111
+ }
112
+ for (const entry of manifest.collab_tool_calls) {
113
+ const tool = typeof entry?.tool === 'string' && entry.tool ? entry.tool : 'unknown';
114
+ const status = typeof entry?.status === 'string' && entry.status ? entry.status : 'unknown';
115
+ const eventType = typeof entry?.event_type === 'string' && entry.event_type ? entry.event_type : 'unknown';
116
+ collabByStatus[status] = (collabByStatus[status] ?? 0) + 1;
117
+ collabByEventType[eventType] = (collabByEventType[eventType] ?? 0) + 1;
118
+ collabTools.set(tool, (collabTools.get(tool) ?? 0) + 1);
119
+ }
80
120
  }
81
- if (taskKeys.has(manifest.task_id)) {
121
+ if (typeof manifest.task_id === 'string' && manifest.task_id && taskKeys.has(manifest.task_id)) {
82
122
  activeIndexTasks.add(manifest.task_id);
83
123
  }
124
+ if (Array.isArray(manifest.child_runs) && manifest.child_runs.length > 0) {
125
+ totalChildRuns += manifest.child_runs.length;
126
+ if (typeof manifest.task_id === 'string' && manifest.task_id) {
127
+ tasksWithChildRuns.add(manifest.task_id);
128
+ }
129
+ }
84
130
  }
85
131
  const pipelineTop = [...pipelines.entries()]
86
132
  .sort((a, b) => b[1] - a[1])
@@ -103,26 +149,45 @@ export async function runDoctorUsage(options = {}) {
103
149
  activeWithSubagents += 1;
104
150
  }
105
151
  }
152
+ const cloudTopEnvIds = [...cloudEnvIds.entries()]
153
+ .sort((a, b) => b[1] - a[1])
154
+ .slice(0, 5)
155
+ .map(([id, runs]) => ({ id, runs }));
156
+ const collabTopTools = [...collabTools.entries()]
157
+ .sort((a, b) => b[1] - a[1])
158
+ .slice(0, 5)
159
+ .map(([tool, calls]) => ({ tool, calls }));
106
160
  return {
107
161
  window_days: windowDays,
108
162
  cutoff_iso: cutoffIso,
109
163
  runs: statusCounts,
110
164
  cloud: {
111
165
  runs: cloudRuns,
112
- by_status: cloudByStatus
166
+ unique_tasks: cloudTasks.size,
167
+ by_status: cloudByStatus,
168
+ by_diff_status: cloudByDiffStatus,
169
+ by_apply_status: cloudByApplyStatus,
170
+ top_environment_ids: cloudTopEnvIds
113
171
  },
114
172
  rlm: {
115
- runs: rlmRuns
173
+ runs: rlmRuns,
174
+ unique_tasks: rlmTasks.size
116
175
  },
117
176
  collab: {
118
177
  runs_with_tool_calls: collabRunsWithToolCalls,
119
178
  total_tool_calls: collabTotalToolCalls,
179
+ unique_tasks: collabTasks.size,
180
+ by_status: collabByStatus,
181
+ by_event_type: collabByEventType,
182
+ top_tools: collabTopTools,
120
183
  capture_disabled: collabCaptureDisabled
121
184
  },
122
185
  delegation: {
123
186
  active_top_level_tasks: activeTasks.length,
124
187
  active_with_subagents: activeWithSubagents,
125
188
  total_subagent_manifests: totalSubagentManifests,
189
+ tasks_with_child_runs: tasksWithChildRuns.size,
190
+ total_child_runs: totalChildRuns,
126
191
  errors: delegationErrors
127
192
  },
128
193
  pipelines: {
@@ -135,12 +200,31 @@ export function formatDoctorUsageSummary(result) {
135
200
  const lines = [];
136
201
  lines.push(`Usage (last ${result.window_days}d, cutoff ${result.cutoff_iso})`);
137
202
  lines.push(` - runs: ${result.runs.total} (ok=${result.runs.succeeded}, failed=${result.runs.failed}, cancelled=${result.runs.cancelled}, other=${result.runs.other})`);
138
- lines.push(` - cloud: ${result.cloud.runs} (${formatPercent(result.cloud.runs, result.runs.total)})${formatCloudStatuses(result.cloud.by_status)}`);
139
- lines.push(` - rlm: ${result.rlm.runs} (${formatPercent(result.rlm.runs, result.runs.total)})`);
203
+ const cloudSuffix = result.cloud.unique_tasks > 0
204
+ ? ` over ${result.cloud.unique_tasks} task${result.cloud.unique_tasks === 1 ? '' : 's'}`
205
+ : '';
206
+ const cloudDiff = formatTopCounts(result.cloud.by_diff_status, 2, 'diff');
207
+ const cloudApply = formatTopCounts(result.cloud.by_apply_status, 2, 'apply');
208
+ const cloudEnv = formatTopList(result.cloud.top_environment_ids.map((entry) => ({ key: entry.id, value: entry.runs })), 2, 'env');
209
+ lines.push(` - cloud: ${result.cloud.runs}${cloudSuffix} (${formatPercent(result.cloud.runs, result.runs.total)})${formatCloudStatuses(result.cloud.by_status)}${cloudDiff}${cloudApply}${cloudEnv}`);
210
+ const rlmSuffix = result.rlm.unique_tasks > 0
211
+ ? ` over ${result.rlm.unique_tasks} task${result.rlm.unique_tasks === 1 ? '' : 's'}`
212
+ : '';
213
+ lines.push(` - rlm: ${result.rlm.runs}${rlmSuffix} (${formatPercent(result.rlm.runs, result.runs.total)})`);
140
214
  const collabSuffix = result.collab.capture_disabled ? ' (capture disabled)' : '';
141
- lines.push(` - collab: ${result.collab.runs_with_tool_calls} (${formatPercent(result.collab.runs_with_tool_calls, result.runs.total)})${collabSuffix}`);
215
+ const collabTaskSuffix = result.collab.unique_tasks > 0
216
+ ? ` over ${result.collab.unique_tasks} task${result.collab.unique_tasks === 1 ? '' : 's'}`
217
+ : '';
218
+ const collabAvg = result.collab.runs_with_tool_calls > 0
219
+ ? ` (avg ${Math.round((result.collab.total_tool_calls / result.collab.runs_with_tool_calls) * 10) / 10}/run)`
220
+ : '';
221
+ const collabOk = result.collab.by_status.completed ?? 0;
222
+ const collabFailed = result.collab.by_status.failed ?? 0;
223
+ const collabToolList = formatTopList(result.collab.top_tools.map((entry) => ({ key: entry.tool, value: entry.calls })), 3, 'tools');
224
+ lines.push(` - collab: ${result.collab.runs_with_tool_calls} (${formatPercent(result.collab.runs_with_tool_calls, result.runs.total)})${collabSuffix}`
225
+ + `${collabTaskSuffix}, events=${result.collab.total_tool_calls}${collabAvg} (ok=${collabOk}, failed=${collabFailed})${collabToolList}`);
142
226
  if (result.delegation.active_top_level_tasks > 0) {
143
- lines.push(` - delegation: ${result.delegation.active_with_subagents}/${result.delegation.active_top_level_tasks} top-level tasks have subagent manifests`);
227
+ lines.push(` - delegation: ${result.delegation.active_with_subagents}/${result.delegation.active_top_level_tasks} top-level tasks have subagent manifests (${result.delegation.total_subagent_manifests} total); child_runs=${result.delegation.total_child_runs} over ${result.delegation.tasks_with_child_runs} tasks`);
144
228
  }
145
229
  else {
146
230
  lines.push(' - delegation: no top-level tasks detected in tasks/index.json for this window');
@@ -193,6 +277,30 @@ function formatCloudStatuses(byStatus) {
193
277
  .join(', ');
194
278
  return ` [${top}]`;
195
279
  }
280
+ function formatTopCounts(byKey, limit, label) {
281
+ const entries = Object.entries(byKey);
282
+ if (entries.length === 0) {
283
+ return '';
284
+ }
285
+ entries.sort((a, b) => b[1] - a[1]);
286
+ const top = entries
287
+ .slice(0, limit)
288
+ .map(([key, value]) => `${key}=${value}`)
289
+ .join(', ');
290
+ return ` ${label}[${top}]`;
291
+ }
292
+ function formatTopList(entries, limit, label) {
293
+ const filtered = entries.filter((entry) => entry.key && Number.isFinite(entry.value) && entry.value > 0);
294
+ if (filtered.length === 0) {
295
+ return '';
296
+ }
297
+ const top = filtered
298
+ .sort((a, b) => b.value - a.value || a.key.localeCompare(b.key))
299
+ .slice(0, limit)
300
+ .map((entry) => `${entry.key}=${entry.value}`)
301
+ .join(', ');
302
+ return ` ${label}[${top}]`;
303
+ }
196
304
  function readTaskIndexKeys(repoRoot) {
197
305
  const indexPath = join(repoRoot, 'tasks', 'index.json');
198
306
  try {
@@ -61,7 +61,7 @@ export function formatInitSummary(result, cwd) {
61
61
  lines.push('No files written.');
62
62
  }
63
63
  lines.push('Next steps (recommended):');
64
- lines.push(' - codex-orchestrator delegation setup --yes');
64
+ lines.push(' - codex-orchestrator setup --yes # installs bundled skills + configures delegation/devtools wiring');
65
65
  lines.push(' - codex-orchestrator codex setup # optional: managed/pinned Codex CLI (stock CLI works by default)');
66
66
  return lines;
67
67
  }
@@ -36,6 +36,12 @@ export async function installSkills(options = {}) {
36
36
  skills: selectedSkills
37
37
  };
38
38
  }
39
+ export async function listBundledSkills() {
40
+ const pkgRoot = findPackageRoot();
41
+ const sourceRoot = join(pkgRoot, 'skills');
42
+ await assertDirectory(sourceRoot);
43
+ return await listSkillNames(sourceRoot);
44
+ }
39
45
  export function formatSkillsInstallSummary(result, cwd = process.cwd()) {
40
46
  const lines = [];
41
47
  lines.push(`Skills source: ${result.sourceRoot}`);
package/docs/README.md CHANGED
@@ -101,7 +101,8 @@ Use `npx @kbediako/codex-orchestrator resume --run <run-id>` to continue interru
101
101
  ## Companion Package Commands
102
102
  - `codex-orchestrator mcp serve [--repo <path>] [--dry-run] [-- <extra args>]`: launch the MCP stdio server (delegates to `codex mcp-server`; stdout guard keeps protocol-only output, logs to stderr).
103
103
  - `codex-orchestrator init codex [--cwd <path>] [--force]`: copy starter templates into a repo (includes `mcp-client.json` and `AGENTS.md`; no overwrite unless `--force`).
104
- - `codex-orchestrator doctor [--format json] [--usage]`: check optional tooling dependencies plus collab/cloud/delegation readiness and print enablement commands. `--usage` appends a local usage snapshot (scans `.runs/`).
104
+ - `codex-orchestrator setup [--yes]`: one-shot bootstrap for downstream users (installs bundled skills and configures delegation + DevTools wiring).
105
+ - `codex-orchestrator doctor [--format json] [--usage] [--apply]`: check optional tooling dependencies plus collab/cloud/delegation readiness and print enablement commands. `--usage` appends a local usage snapshot (scans `.runs/`). `--apply` plans/applies quick fixes (use with `--yes`).
105
106
  - `codex-orchestrator devtools setup [--yes]`: print DevTools MCP setup instructions (`--yes` applies `codex mcp add ...`).
106
107
  - `codex-orchestrator delegation setup [--yes]`: configure delegation MCP wiring (`--yes` applies `codex mcp add ...`).
107
108
  - `codex-orchestrator skills install [--force] [--only <skills>] [--codex-home <path>]`: install bundled skills into `$CODEX_HOME/skills` (global skills remain the primary reference when installed).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbediako/codex-orchestrator",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: chrome-devtools
3
+ description: Control and inspect Chrome via the Chrome DevTools MCP server (navigate, interact, screenshots, console, network, perf).
4
+ allowed-tools: mcp__chrome-devtools__*
5
+ ---
6
+
7
+ # Chrome DevTools (MCP)
8
+
9
+ Use this skill when you need browser-grounded evidence (UI screenshots, console errors, network failures, perf traces) or when a task requires real page interaction.
10
+
11
+ ## Preflight
12
+
13
+ - Ensure the MCP server is configured: `codex-orchestrator devtools setup --yes`.
14
+ - If tools are missing in the current run, enable the server and restart the run:
15
+ - `codex -c 'mcp_servers.chrome-devtools.enabled=true' ...`
16
+
17
+ ## Default Workflow
18
+
19
+ 1. Open a new page and navigate to the target URL.
20
+ 2. Wait for the page to be stable (avoid racing async renders).
21
+ 3. Interact with the UI (click/fill/press) to reproduce the behavior.
22
+ 4. Collect evidence:
23
+ - Screenshot(s) for visual state
24
+ - Console messages for runtime errors
25
+ - Network requests for failed/slow calls
26
+ 5. Close pages when finished.
27
+
28
+ ## Evidence Discipline
29
+
30
+ - Always capture at least one screenshot when validating UI behavior.
31
+ - When debugging, always include:
32
+ - `list_console_messages`
33
+ - `list_network_requests` (and fetch details for failures)
34
+
@@ -64,8 +64,10 @@ For runner + delegation coordination (short `--task` flow), see `docs/delegation
64
64
  ### 0) One-time setup (register the MCP server)
65
65
 
66
66
  - Register the delegation server once:
67
- - Preferred: `codex-orchestrator delegation setup --yes`
68
- - This wraps `codex mcp add delegation ...` and keeps wiring discoverable via `codex-orchestrator doctor`.
67
+ - Preferred: `codex-orchestrator setup --yes`
68
+ - One-shot bootstrap (installs bundled skills + configures delegation/DevTools wiring).
69
+ - `codex-orchestrator delegation setup --yes`
70
+ - Delegation-only setup (wraps `codex mcp add delegation ...` and keeps wiring discoverable via `codex-orchestrator doctor`).
69
71
  - `codex mcp add delegation -- codex-orchestrator delegate-server`
70
72
  - Optional: append `--repo /path/to/repo` to pin the server to one repo (not recommended if you work across repos).
71
73
  - `delegate-server` is the canonical name; `delegation-server` is supported as an alias.