@kbediako/codex-orchestrator 0.1.24 → 0.1.26

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
@@ -89,7 +89,7 @@ Delegation guard profile:
89
89
  ## Delegation + RLM flow
90
90
 
91
91
  RLM (Recursive Language Model) is the long-horizon loop used by the `rlm` pipeline (`codex-orchestrator rlm "<goal>"` or `codex-orchestrator start rlm --goal "<goal>"`). Delegated runs only enter RLM when the child is launched with the `rlm` pipeline (or the rlm runner directly). In auto mode it resolves to symbolic when delegated, when `RLM_CONTEXT_PATH` is set, or when the context exceeds `RLM_SYMBOLIC_MIN_BYTES`; otherwise it stays iterative. The runner writes state to `.runs/<task-id>/cli/<run-id>/rlm/state.json` and stops when the validator passes or budgets are exhausted.
92
- Symbolic subcalls can optionally use collab tools. Fast path: `codex-orchestrator rlm --collab "<goal>"` (sets `RLM_SYMBOLIC_COLLAB=1` and implies symbolic mode). Collab requires `collab=true` in `codex features list`. Collab tool calls parsed from `codex exec --json --enable collab` are stored in `manifest.collab_tool_calls` (bounded by `CODEX_ORCHESTRATOR_COLLAB_MAX_EVENTS`, set to `0` to disable). `codex-orchestrator codex setup` remains available when you want a managed/pinned CLI path.
92
+ Symbolic subcalls can optionally use collab tools. Fast path: `codex-orchestrator rlm --collab auto "<goal>"` (sets `RLM_SYMBOLIC_COLLAB=1` and implies symbolic mode). Collab requires `collab=true` in `codex features list`. Collab tool calls parsed from `codex exec --json --enable collab` are stored in `manifest.collab_tool_calls` (bounded by `CODEX_ORCHESTRATOR_COLLAB_MAX_EVENTS`, set to `0` to disable). `codex-orchestrator codex setup` remains available when you want a managed/pinned CLI path.
93
93
 
94
94
  ### Delegation flow
95
95
  ```mermaid
@@ -173,6 +173,14 @@ Usage snapshot (scans local `.runs/`):
173
173
  codex-orchestrator doctor --usage
174
174
  ```
175
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 --collab auto "<goal>"` (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
+
176
184
  Print DevTools MCP setup guidance:
177
185
  ```bash
178
186
  codex-orchestrator devtools setup
@@ -97,7 +97,7 @@ export function runDoctor(cwd = process.cwd()) {
97
97
  status: collabStatus,
98
98
  enabled: collabEnabled,
99
99
  enablement: [
100
- 'Enable collab for symbolic RLM runs with: codex-orchestrator rlm --collab "<goal>"',
100
+ 'Enable collab for symbolic RLM runs with: codex-orchestrator rlm --collab auto "<goal>"',
101
101
  'Or set: RLM_SYMBOLIC_COLLAB=1 (implies symbolic mode when using --collab).',
102
102
  'If collab is disabled in codex features: codex features enable collab'
103
103
  ]
@@ -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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbediako/codex-orchestrator",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",