oh-my-codex 0.16.4 → 0.17.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.
Files changed (278) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/dist/catalog/__tests__/generator.test.js +2 -0
  4. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  5. package/dist/cli/__tests__/doctor-warning-copy.test.js +80 -7
  6. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  7. package/dist/cli/__tests__/index.test.js +17 -11
  8. package/dist/cli/__tests__/index.test.js.map +1 -1
  9. package/dist/cli/__tests__/mcp-serve.test.js +4 -0
  10. package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
  11. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -0
  12. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  13. package/dist/cli/__tests__/ralph.test.js +0 -124
  14. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  15. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +8 -3
  16. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  17. package/dist/cli/__tests__/setup-install-mode.test.js +183 -4
  18. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  19. package/dist/cli/__tests__/setup-refresh.test.js +3 -3
  20. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  21. package/dist/cli/__tests__/team.test.js +166 -42
  22. package/dist/cli/__tests__/team.test.js.map +1 -1
  23. package/dist/cli/__tests__/ultragoal.test.js +22 -0
  24. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  25. package/dist/cli/doctor.d.ts.map +1 -1
  26. package/dist/cli/doctor.js +75 -14
  27. package/dist/cli/doctor.js.map +1 -1
  28. package/dist/cli/index.d.ts +8 -2
  29. package/dist/cli/index.d.ts.map +1 -1
  30. package/dist/cli/index.js +17 -7
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/cli/mcp-serve.d.ts.map +1 -1
  33. package/dist/cli/mcp-serve.js +4 -0
  34. package/dist/cli/mcp-serve.js.map +1 -1
  35. package/dist/cli/plugin-marketplace.d.ts +25 -1
  36. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  37. package/dist/cli/plugin-marketplace.js +146 -3
  38. package/dist/cli/plugin-marketplace.js.map +1 -1
  39. package/dist/cli/question.d.ts +1 -1
  40. package/dist/cli/question.d.ts.map +1 -1
  41. package/dist/cli/question.js +98 -4
  42. package/dist/cli/question.js.map +1 -1
  43. package/dist/cli/ralph.d.ts.map +1 -1
  44. package/dist/cli/ralph.js +1 -49
  45. package/dist/cli/ralph.js.map +1 -1
  46. package/dist/cli/setup.d.ts +1 -0
  47. package/dist/cli/setup.d.ts.map +1 -1
  48. package/dist/cli/setup.js +103 -18
  49. package/dist/cli/setup.js.map +1 -1
  50. package/dist/cli/team.d.ts.map +1 -1
  51. package/dist/cli/team.js +21 -29
  52. package/dist/cli/team.js.map +1 -1
  53. package/dist/cli/ultragoal.d.ts.map +1 -1
  54. package/dist/cli/ultragoal.js +7 -1
  55. package/dist/cli/ultragoal.js.map +1 -1
  56. package/dist/config/__tests__/codex-hooks.test.js +136 -9
  57. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  58. package/dist/config/__tests__/generator-idempotent.test.js +15 -0
  59. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  60. package/dist/config/codex-hooks.d.ts +13 -14
  61. package/dist/config/codex-hooks.d.ts.map +1 -1
  62. package/dist/config/codex-hooks.js +85 -7
  63. package/dist/config/codex-hooks.js.map +1 -1
  64. package/dist/config/generator.d.ts +8 -1
  65. package/dist/config/generator.d.ts.map +1 -1
  66. package/dist/config/generator.js +73 -9
  67. package/dist/config/generator.js.map +1 -1
  68. package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
  69. package/dist/config/omx-first-party-mcp.js +7 -0
  70. package/dist/config/omx-first-party-mcp.js.map +1 -1
  71. package/dist/hooks/__tests__/agents-overlay.test.js +29 -0
  72. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  73. package/dist/hooks/__tests__/design-skill.test.d.ts +2 -0
  74. package/dist/hooks/__tests__/design-skill.test.d.ts.map +1 -0
  75. package/dist/hooks/__tests__/design-skill.test.js +55 -0
  76. package/dist/hooks/__tests__/design-skill.test.js.map +1 -0
  77. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +265 -0
  78. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  79. package/dist/hooks/__tests__/session.test.js +126 -1
  80. package/dist/hooks/__tests__/session.test.js.map +1 -1
  81. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +1 -1
  82. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -1
  83. package/dist/hooks/__tests__/skill-guidance-contract.test.js +41 -0
  84. package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
  85. package/dist/hooks/agents-overlay.d.ts.map +1 -1
  86. package/dist/hooks/agents-overlay.js +6 -3
  87. package/dist/hooks/agents-overlay.js.map +1 -1
  88. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  89. package/dist/hooks/keyword-detector.js +5 -1
  90. package/dist/hooks/keyword-detector.js.map +1 -1
  91. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  92. package/dist/hooks/keyword-registry.js +2 -0
  93. package/dist/hooks/keyword-registry.js.map +1 -1
  94. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  95. package/dist/hooks/prompt-guidance-contract.js +47 -2
  96. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  97. package/dist/hooks/session.d.ts +11 -3
  98. package/dist/hooks/session.d.ts.map +1 -1
  99. package/dist/hooks/session.js +68 -6
  100. package/dist/hooks/session.js.map +1 -1
  101. package/dist/hud/__tests__/reconcile.test.js +63 -0
  102. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  103. package/dist/hud/__tests__/tmux.test.d.ts +2 -0
  104. package/dist/hud/__tests__/tmux.test.d.ts.map +1 -0
  105. package/dist/hud/__tests__/tmux.test.js +92 -0
  106. package/dist/hud/__tests__/tmux.test.js.map +1 -0
  107. package/dist/hud/reconcile.d.ts +2 -0
  108. package/dist/hud/reconcile.d.ts.map +1 -1
  109. package/dist/hud/reconcile.js +14 -1
  110. package/dist/hud/reconcile.js.map +1 -1
  111. package/dist/hud/tmux.d.ts +12 -0
  112. package/dist/hud/tmux.d.ts.map +1 -1
  113. package/dist/hud/tmux.js +88 -0
  114. package/dist/hud/tmux.js.map +1 -1
  115. package/dist/mcp/__tests__/bootstrap.test.js +3 -0
  116. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  117. package/dist/mcp/__tests__/hermes-bridge.test.d.ts +2 -0
  118. package/dist/mcp/__tests__/hermes-bridge.test.d.ts.map +1 -0
  119. package/dist/mcp/__tests__/hermes-bridge.test.js +441 -0
  120. package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -0
  121. package/dist/mcp/__tests__/state-paths.test.js +96 -13
  122. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  123. package/dist/mcp/bootstrap.d.ts +1 -1
  124. package/dist/mcp/bootstrap.d.ts.map +1 -1
  125. package/dist/mcp/bootstrap.js +2 -0
  126. package/dist/mcp/bootstrap.js.map +1 -1
  127. package/dist/mcp/hermes-bridge.d.ts +111 -0
  128. package/dist/mcp/hermes-bridge.d.ts.map +1 -0
  129. package/dist/mcp/hermes-bridge.js +474 -0
  130. package/dist/mcp/hermes-bridge.js.map +1 -0
  131. package/dist/mcp/hermes-server.d.ts +374 -0
  132. package/dist/mcp/hermes-server.d.ts.map +1 -0
  133. package/dist/mcp/hermes-server.js +158 -0
  134. package/dist/mcp/hermes-server.js.map +1 -0
  135. package/dist/mcp/state-paths.d.ts.map +1 -1
  136. package/dist/mcp/state-paths.js +41 -9
  137. package/dist/mcp/state-paths.js.map +1 -1
  138. package/dist/modes/__tests__/base-tmux-pane.test.js +31 -1
  139. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  140. package/dist/pipeline/__tests__/stages.test.js +18 -9
  141. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  142. package/dist/pipeline/stages/team-exec.d.ts.map +1 -1
  143. package/dist/pipeline/stages/team-exec.js +2 -7
  144. package/dist/pipeline/stages/team-exec.js.map +1 -1
  145. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +111 -269
  146. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -1
  147. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +31 -72
  148. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -1
  149. package/dist/planning/__tests__/artifacts.test.js +27 -372
  150. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  151. package/dist/planning/artifacts.d.ts +1 -14
  152. package/dist/planning/artifacts.d.ts.map +1 -1
  153. package/dist/planning/artifacts.js +11 -31
  154. package/dist/planning/artifacts.js.map +1 -1
  155. package/dist/question/__tests__/state.test.js +287 -1
  156. package/dist/question/__tests__/state.test.js.map +1 -1
  157. package/dist/question/__tests__/ui.test.js +8 -8
  158. package/dist/question/__tests__/ui.test.js.map +1 -1
  159. package/dist/question/events.d.ts +53 -0
  160. package/dist/question/events.d.ts.map +1 -0
  161. package/dist/question/events.js +201 -0
  162. package/dist/question/events.js.map +1 -0
  163. package/dist/question/state.d.ts +25 -1
  164. package/dist/question/state.d.ts.map +1 -1
  165. package/dist/question/state.js +259 -3
  166. package/dist/question/state.js.map +1 -1
  167. package/dist/question/types.d.ts +1 -0
  168. package/dist/question/types.d.ts.map +1 -1
  169. package/dist/question/types.js.map +1 -1
  170. package/dist/question/ui.d.ts.map +1 -1
  171. package/dist/question/ui.js +1 -18
  172. package/dist/question/ui.js.map +1 -1
  173. package/dist/ralph/__tests__/completion-audit.test.js +39 -0
  174. package/dist/ralph/__tests__/completion-audit.test.js.map +1 -1
  175. package/dist/scripts/__tests__/codex-native-hook.test.js +298 -3
  176. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  177. package/dist/scripts/__tests__/run-test-files.test.js +22 -0
  178. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  179. package/dist/scripts/codex-native-hook.d.ts +1 -0
  180. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  181. package/dist/scripts/codex-native-hook.js +137 -18
  182. package/dist/scripts/codex-native-hook.js.map +1 -1
  183. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  184. package/dist/scripts/codex-native-pre-post.js +12 -6
  185. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  186. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  187. package/dist/scripts/notify-hook/tmux-injection.js +91 -2
  188. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  189. package/dist/scripts/run-test-files.js +12 -1
  190. package/dist/scripts/run-test-files.js.map +1 -1
  191. package/dist/state/mode-state-context.d.ts +2 -0
  192. package/dist/state/mode-state-context.d.ts.map +1 -1
  193. package/dist/state/mode-state-context.js +21 -0
  194. package/dist/state/mode-state-context.js.map +1 -1
  195. package/dist/team/__tests__/approved-execution.test.js +25 -24
  196. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  197. package/dist/team/__tests__/runtime.test.js +173 -26
  198. package/dist/team/__tests__/runtime.test.js.map +1 -1
  199. package/dist/team/__tests__/scaling.test.js +66 -17
  200. package/dist/team/__tests__/scaling.test.js.map +1 -1
  201. package/dist/team/__tests__/tmux-session.test.js +42 -0
  202. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  203. package/dist/team/__tests__/worker-bootstrap.test.js +205 -0
  204. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  205. package/dist/team/approved-execution.d.ts +13 -0
  206. package/dist/team/approved-execution.d.ts.map +1 -1
  207. package/dist/team/approved-execution.js +65 -30
  208. package/dist/team/approved-execution.js.map +1 -1
  209. package/dist/team/runtime.d.ts.map +1 -1
  210. package/dist/team/runtime.js +28 -24
  211. package/dist/team/runtime.js.map +1 -1
  212. package/dist/team/scaling.d.ts.map +1 -1
  213. package/dist/team/scaling.js +7 -8
  214. package/dist/team/scaling.js.map +1 -1
  215. package/dist/team/tmux-session.d.ts.map +1 -1
  216. package/dist/team/tmux-session.js +48 -2
  217. package/dist/team/tmux-session.js.map +1 -1
  218. package/dist/team/ultragoal-context.d.ts +35 -0
  219. package/dist/team/ultragoal-context.d.ts.map +1 -0
  220. package/dist/team/ultragoal-context.js +191 -0
  221. package/dist/team/ultragoal-context.js.map +1 -0
  222. package/dist/ultragoal/__tests__/artifacts.test.js +121 -0
  223. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  224. package/dist/ultragoal/__tests__/docs-contract.test.js +19 -0
  225. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  226. package/dist/ultragoal/artifacts.d.ts +9 -1
  227. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  228. package/dist/ultragoal/artifacts.js +105 -3
  229. package/dist/ultragoal/artifacts.js.map +1 -1
  230. package/dist/utils/__tests__/paths.test.js +31 -1
  231. package/dist/utils/__tests__/paths.test.js.map +1 -1
  232. package/dist/utils/paths.d.ts +6 -0
  233. package/dist/utils/paths.d.ts.map +1 -1
  234. package/dist/utils/paths.js +18 -0
  235. package/dist/utils/paths.js.map +1 -1
  236. package/dist/wiki/lifecycle.js +3 -3
  237. package/dist/wiki/lifecycle.js.map +1 -1
  238. package/package.json +1 -1
  239. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  240. package/plugins/oh-my-codex/.mcp.json +8 -0
  241. package/plugins/oh-my-codex/skills/design/SKILL.md +180 -0
  242. package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -3
  243. package/plugins/oh-my-codex/skills/ralph/SKILL.md +2 -2
  244. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +1 -1
  245. package/plugins/oh-my-codex/skills/skill/SKILL.md +2 -1
  246. package/plugins/oh-my-codex/skills/team/SKILL.md +6 -0
  247. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +11 -0
  248. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +161 -47
  249. package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +2 -2
  250. package/skills/design/SKILL.md +180 -0
  251. package/skills/frontend-ui-ux/SKILL.md +6 -2
  252. package/skills/plan/SKILL.md +3 -3
  253. package/skills/ralph/SKILL.md +2 -2
  254. package/skills/ralplan/SKILL.md +1 -1
  255. package/skills/skill/SKILL.md +2 -1
  256. package/skills/team/SKILL.md +6 -0
  257. package/skills/ultragoal/SKILL.md +11 -0
  258. package/skills/ultraqa/SKILL.md +161 -47
  259. package/skills/visual-ralph/SKILL.md +2 -2
  260. package/src/scripts/__tests__/codex-native-hook.test.ts +339 -2
  261. package/src/scripts/__tests__/run-test-files.test.ts +32 -0
  262. package/src/scripts/codex-native-hook.ts +166 -20
  263. package/src/scripts/codex-native-pre-post.ts +12 -6
  264. package/src/scripts/notify-hook/tmux-injection.ts +110 -3
  265. package/src/scripts/run-test-files.ts +13 -2
  266. package/templates/catalog-manifest.json +9 -2
  267. package/dist/planning/__tests__/context-pack-status.test.d.ts +0 -2
  268. package/dist/planning/__tests__/context-pack-status.test.d.ts.map +0 -1
  269. package/dist/planning/__tests__/context-pack-status.test.js +0 -795
  270. package/dist/planning/__tests__/context-pack-status.test.js.map +0 -1
  271. package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts +0 -2
  272. package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts.map +0 -1
  273. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +0 -612
  274. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +0 -1
  275. package/dist/planning/context-pack-status.d.ts +0 -73
  276. package/dist/planning/context-pack-status.d.ts.map +0 -1
  277. package/dist/planning/context-pack-status.js +0 -745
  278. package/dist/planning/context-pack-status.js.map +0 -1
@@ -17,6 +17,7 @@ import { shutdownTeam } from '../../team/runtime.js';
17
17
  import { sameFilePath } from '../../utils/paths.js';
18
18
  import { appendTeamEvent, createTask, initTeamState, readTeamConfig, saveTeamConfig, updateWorkerHeartbeat, writeMonitorSnapshot, writeTaskApproval, writeWorkerStatus, } from '../../team/state.js';
19
19
  import { buildApprovedTeamExecutionBinding, writePersistedApprovedTeamExecutionBinding, } from '../../team/approved-execution.js';
20
+ import { writePersistedTeamUltragoalContext } from '../../team/ultragoal-context.js';
20
21
  import { isRealTmuxAvailable, withTempTmuxSession } from '../../team/__tests__/tmux-test-fixture.js';
21
22
  const OMX_CLI_PATH = fileURLToPath(new URL('../omx.js', import.meta.url));
22
23
  const ORIGINAL_OMX_TEAM_WORKER = process.env.OMX_TEAM_WORKER;
@@ -263,7 +264,7 @@ describe('parseTeamStartArgs', () => {
263
264
  await rm(wd, { recursive: true, force: true });
264
265
  }
265
266
  });
266
- it('reuses the older same-signature approved team hint when the latest matching handoff is missing its baseline', async () => {
267
+ it('does not reuse an older approved team hint when the latest matching handoff is missing its baseline', async () => {
267
268
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-lineage-missing-baseline-'));
268
269
  const previousCwd = process.cwd();
269
270
  const approvedTask = 'Execute approved Team lineage follow-up';
@@ -275,10 +276,10 @@ describe('parseTeamStartArgs', () => {
275
276
  await writeFile(join(plansDir, 'test-spec-alpha-team-lineage.md'), '# Test spec\n');
276
277
  await writeFile(join(plansDir, 'prd-zeta-team-lineage.md'), `# Approved plan\n\nLaunch via omx team 3:executor ${JSON.stringify(approvedTask)}\n`);
277
278
  const result = parseTeamStartArgs(['team']);
278
- assert.equal(result.parsed.task, approvedTask);
279
+ assert.equal(result.parsed.task, 'team');
279
280
  assert.equal(result.parsed.workerCount, 3);
280
281
  assert.equal(result.parsed.agentType, 'executor');
281
- assert.equal(result.parsed.allowRepoAwareDagHandoff, true);
282
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
282
283
  assert.equal(result.parsed.approvedExecution, undefined);
283
284
  }
284
285
  finally {
@@ -286,7 +287,7 @@ describe('parseTeamStartArgs', () => {
286
287
  await rm(wd, { recursive: true, force: true });
287
288
  }
288
289
  });
289
- it('reuses the older ready Team handoff when the latest same-signature handoff is invalid', async () => {
290
+ it('does not reuse an older ready Team handoff when the latest same-signature handoff lacks a baseline', async () => {
290
291
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-lineage-invalid-'));
291
292
  const previousCwd = process.cwd();
292
293
  const approvedTask = 'Execute approved Team invalid lineage follow-up';
@@ -313,21 +314,19 @@ describe('parseTeamStartArgs', () => {
313
314
  '',
314
315
  `Launch via ${approvedCommand}`,
315
316
  ].join('\n'));
316
- await writeFile(join(plansDir, 'test-spec-zeta-team-lineage-invalid.md'), '# Test spec\n');
317
317
  const result = parseTeamStartArgs(['team']);
318
- assert.equal(result.parsed.task, approvedTask);
318
+ assert.equal(result.parsed.task, 'team');
319
319
  assert.equal(result.parsed.workerCount, 3);
320
320
  assert.equal(result.parsed.agentType, 'executor');
321
- assert.equal(result.parsed.allowRepoAwareDagHandoff, true);
322
- assert.equal(result.parsed.approvedExecution?.command, approvedCommand);
323
- assert.equal(sameFilePath(result.parsed.approvedExecution?.prd_path ?? '', alphaPrdPath), true);
321
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
322
+ assert.equal(result.parsed.approvedExecution, undefined);
324
323
  }
325
324
  finally {
326
325
  process.chdir(previousCwd);
327
326
  await rm(wd, { recursive: true, force: true });
328
327
  }
329
328
  });
330
- it('reuses the older ready Team handoff when the latest same-signature handoff is incomplete', async () => {
329
+ it('does not reuse an older ready Team handoff when the latest same-signature handoff is incomplete', async () => {
331
330
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-lineage-incomplete-'));
332
331
  const previousCwd = process.cwd();
333
332
  const approvedTask = 'Execute approved Team incomplete lineage follow-up';
@@ -348,7 +347,6 @@ describe('parseTeamStartArgs', () => {
348
347
  await writeFile(alphaTestSpecPath, '# Test spec\n');
349
348
  await writeReadyContextPack(wd, 'alpha-team-lineage-complete', alphaPrdPath, alphaTestSpecPath);
350
349
  const zetaPrdPath = join(plansDir, 'prd-zeta-team-lineage-incomplete.md');
351
- const zetaTestSpecPath = join(plansDir, 'test-spec-zeta-team-lineage-incomplete.md');
352
350
  await writeFile(zetaPrdPath, [
353
351
  '# Approved plan',
354
352
  '',
@@ -356,15 +354,12 @@ describe('parseTeamStartArgs', () => {
356
354
  '',
357
355
  `Launch via ${approvedCommand}`,
358
356
  ].join('\n'));
359
- await writeFile(zetaTestSpecPath, '# Test spec\n');
360
- await writeContextPack(wd, 'zeta-team-lineage-incomplete', zetaPrdPath, zetaTestSpecPath, ['scope']);
361
357
  const result = parseTeamStartArgs(['team']);
362
- assert.equal(result.parsed.task, approvedTask);
358
+ assert.equal(result.parsed.task, 'team');
363
359
  assert.equal(result.parsed.workerCount, 3);
364
360
  assert.equal(result.parsed.agentType, 'executor');
365
- assert.equal(result.parsed.allowRepoAwareDagHandoff, true);
366
- assert.equal(result.parsed.approvedExecution?.command, approvedCommand);
367
- assert.equal(sameFilePath(result.parsed.approvedExecution?.prd_path ?? '', alphaPrdPath), true);
361
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
362
+ assert.equal(result.parsed.approvedExecution, undefined);
368
363
  }
369
364
  finally {
370
365
  process.chdir(previousCwd);
@@ -523,7 +518,7 @@ describe('parseTeamStartArgs', () => {
523
518
  await rm(wd, { recursive: true, force: true });
524
519
  }
525
520
  });
526
- it('keeps plan-only short follow-ups on the generic path even when a persisted approved binding exists', async () => {
521
+ it('carries plan-only short follow-ups when a persisted binding resolves to a baseline-ready hint', async () => {
527
522
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-plan-only-'));
528
523
  const previousCwd = process.cwd();
529
524
  try {
@@ -545,14 +540,16 @@ describe('parseTeamStartArgs', () => {
545
540
  assert.equal(result.parsed.task, 'Execute approved issue 2085 plan');
546
541
  assert.equal(result.parsed.workerCount, 3);
547
542
  assert.equal(result.parsed.agentType, 'executor');
548
- assert.equal(result.parsed.approvedExecution, undefined);
543
+ assert.equal(result.parsed.approvedExecution?.task, 'Execute approved issue 2085 plan');
544
+ assert.equal(result.parsed.approvedExecution?.command, command);
545
+ assert.equal(sameFilePath(result.parsed.approvedExecution?.prd_path ?? '', prdPath), true);
549
546
  }
550
547
  finally {
551
548
  process.chdir(previousCwd);
552
549
  await rm(wd, { recursive: true, force: true });
553
550
  }
554
551
  });
555
- it('fails short follow-up reuse when the latest approved handoff is nonready', async () => {
552
+ it('keeps short follow-up generic when the latest approved handoff is non-baseline', async () => {
556
553
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-nonready-'));
557
554
  const previousCwd = process.cwd();
558
555
  try {
@@ -568,15 +565,17 @@ describe('parseTeamStartArgs', () => {
568
565
  '',
569
566
  'Launch via omx team 3:executor "Execute approved issue 2086 plan"',
570
567
  ].join('\n'));
571
- await writeFile(join(plansDir, 'test-spec-issue-2086.md'), '# Test spec\n');
572
- assert.throws(() => parseTeamStartArgs(['team']), /approved_execution_hint_nonready:team:invalid/);
568
+ const result = parseTeamStartArgs(['team']);
569
+ assert.equal(result.parsed.task, 'team');
570
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
571
+ assert.equal(result.parsed.approvedExecution, undefined);
573
572
  }
574
573
  finally {
575
574
  process.chdir(previousCwd);
576
575
  await rm(wd, { recursive: true, force: true });
577
576
  }
578
577
  });
579
- it('fails short follow-up reuse when the latest approved handoff is missing its baseline', async () => {
578
+ it('keeps short follow-up generic when the latest approved handoff is missing its baseline', async () => {
580
579
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-missing-baseline-'));
581
580
  const previousCwd = process.cwd();
582
581
  try {
@@ -584,14 +583,17 @@ describe('parseTeamStartArgs', () => {
584
583
  const plansDir = join(wd, '.omx', 'plans');
585
584
  await mkdir(plansDir, { recursive: true });
586
585
  await writeFile(join(plansDir, 'prd-issue-2086-missing-baseline.md'), '# Approved plan\n\nLaunch via omx team 3:executor "Execute approved issue 2086 missing-baseline plan"\n');
587
- assert.throws(() => parseTeamStartArgs(['team']), /approved_execution_hint_nonready:team:missing-baseline/);
586
+ const result = parseTeamStartArgs(['team']);
587
+ assert.equal(result.parsed.task, 'team');
588
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
589
+ assert.equal(result.parsed.approvedExecution, undefined);
588
590
  }
589
591
  finally {
590
592
  process.chdir(previousCwd);
591
593
  await rm(wd, { recursive: true, force: true });
592
594
  }
593
595
  });
594
- it('fails short follow-up reuse when the latest approved handoff is incomplete', async () => {
596
+ it('keeps short follow-up generic when the latest approved handoff is incomplete and non-baseline', async () => {
595
597
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-followup-incomplete-'));
596
598
  const previousCwd = process.cwd();
597
599
  try {
@@ -599,7 +601,6 @@ describe('parseTeamStartArgs', () => {
599
601
  const plansDir = join(wd, '.omx', 'plans');
600
602
  await mkdir(plansDir, { recursive: true });
601
603
  const prdPath = join(plansDir, 'prd-issue-2086-incomplete.md');
602
- const testSpecPath = join(plansDir, 'test-spec-issue-2086-incomplete.md');
603
604
  await writeFile(prdPath, [
604
605
  '# Approved plan',
605
606
  '',
@@ -607,9 +608,10 @@ describe('parseTeamStartArgs', () => {
607
608
  '',
608
609
  'Launch via omx team 3:executor "Execute approved issue 2086 incomplete plan"',
609
610
  ].join('\n'));
610
- await writeFile(testSpecPath, '# Test spec\n');
611
- await writeContextPack(wd, 'issue-2086-incomplete', prdPath, testSpecPath, ['scope']);
612
- assert.throws(() => parseTeamStartArgs(['team']), /approved_execution_hint_nonready:team:incomplete/);
611
+ const result = parseTeamStartArgs(['team']);
612
+ assert.equal(result.parsed.task, 'team');
613
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
614
+ assert.equal(result.parsed.approvedExecution, undefined);
613
615
  }
614
616
  finally {
615
617
  process.chdir(previousCwd);
@@ -981,10 +983,9 @@ describe('parseTeamStartArgs', () => {
981
983
  process.chdir(wd);
982
984
  await mkdir(join(wd, '.omx', 'plans'), { recursive: true });
983
985
  await writeFile(join(wd, '.omx', 'plans', 'prd-issue-2087.md'), '# Approved plan\n\nLaunch via omx team 3:executor "Execute approved issue 2087 plan"\n');
984
- await writeFile(join(wd, '.omx', 'plans', 'test-spec-issue-2087.md'), '# Test spec\n');
985
- await writeFile(join(wd, '.omx', 'plans', 'repo-context-issue-2087.md'), 'Do not widen plan-only context.\n');
986
+ await writeFile(join(wd, '.omx', 'plans', 'repo-context-issue-2087.md'), 'Do not widen non-baseline context.\n');
986
987
  const result = parseTeamStartArgs(['3:executor', 'Execute', 'approved', 'issue', '2087', 'plan']);
987
- assert.equal(result.parsed.allowRepoAwareDagHandoff, true);
988
+ assert.equal(result.parsed.allowRepoAwareDagHandoff, false);
988
989
  assert.equal(result.parsed.approvedExecution, undefined);
989
990
  assert.equal(result.parsed.approvedRepositoryContextSummary, undefined);
990
991
  }
@@ -993,7 +994,7 @@ describe('parseTeamStartArgs', () => {
993
994
  await rm(wd, { recursive: true, force: true });
994
995
  }
995
996
  });
996
- it('preserves lifecycle-specific DAG fallback reasons for explicit nonready approved launches', async () => {
997
+ it('uses generic DAG fallback reasons for explicit non-baseline approved launches', async () => {
997
998
  const previousCwd = process.cwd();
998
999
  const cases = [
999
1000
  {
@@ -1002,25 +1003,23 @@ describe('parseTeamStartArgs', () => {
1002
1003
  includeOutcome: false,
1003
1004
  writeTestSpec: false,
1004
1005
  packSetup: async (_wd, _prdPath, _testSpecPath) => { },
1005
- expected: 'context_pack_not_followup_ready:missing-baseline',
1006
+ expected: 'dag_handoff_not_approved_for_invocation',
1006
1007
  },
1007
1008
  {
1008
1009
  name: 'incomplete',
1009
1010
  slug: 'issue-2090-incomplete',
1010
1011
  includeOutcome: true,
1011
- writeTestSpec: true,
1012
- packSetup: async (wd, prdPath, testSpecPath) => {
1013
- await writeContextPack(wd, 'issue-2090-incomplete', prdPath, testSpecPath, ['scope']);
1014
- },
1015
- expected: 'context_pack_not_followup_ready:incomplete',
1012
+ writeTestSpec: false,
1013
+ packSetup: async (_wd, _prdPath, _testSpecPath) => { },
1014
+ expected: 'dag_handoff_not_approved_for_invocation',
1016
1015
  },
1017
1016
  {
1018
1017
  name: 'invalid',
1019
1018
  slug: 'issue-2090-invalid',
1020
1019
  includeOutcome: true,
1021
- writeTestSpec: true,
1020
+ writeTestSpec: false,
1022
1021
  packSetup: async (_wd, _prdPath, _testSpecPath) => { },
1023
- expected: 'context_pack_not_followup_ready:invalid',
1022
+ expected: 'dag_handoff_not_approved_for_invocation',
1024
1023
  },
1025
1024
  ];
1026
1025
  try {
@@ -1063,7 +1062,7 @@ describe('parseTeamStartArgs', () => {
1063
1062
  approvedRepositoryContextSummary: parsed.parsed.approvedRepositoryContextSummary,
1064
1063
  });
1065
1064
  assert.equal(parsed.parsed.allowRepoAwareDagHandoff, false);
1066
- assert.equal(parsed.parsed.dagFallbackReason, scenario.expected);
1065
+ assert.equal(parsed.parsed.dagFallbackReason, undefined);
1067
1066
  assert.equal(parsed.parsed.approvedExecution, undefined);
1068
1067
  assert.equal(executionPlan.metadata?.decomposition_source, 'legacy_text');
1069
1068
  assert.equal(executionPlan.metadata?.fallback_reason, scenario.expected);
@@ -2291,6 +2290,131 @@ describe('teamCommand status', () => {
2291
2290
  await rm(wd, { recursive: true, force: true });
2292
2291
  }
2293
2292
  });
2293
+ it('returns Ultragoal checkpoint guidance in JSON status only when approved Team context exists', async () => {
2294
+ const wd = await mkdtemp(join(tmpdir(), 'omx-team-status-ultragoal-json-'));
2295
+ const previousCwd = process.cwd();
2296
+ const logs = [];
2297
+ const originalLog = console.log;
2298
+ try {
2299
+ process.chdir(wd);
2300
+ await withoutTeamTestWorkerEnv(() => initTeamState('ultragoal-json-team', 'inspect ultragoal guidance', 'executor', 1, wd));
2301
+ const plansDir = join(wd, '.omx', 'plans');
2302
+ await mkdir(plansDir, { recursive: true });
2303
+ const prdPath = join(plansDir, 'prd-ultragoal-json.md');
2304
+ const testSpecPath = join(plansDir, 'test-spec-ultragoal-json.md');
2305
+ const task = 'Execute Team + Ultragoal G001-team-runtime-bridge plan';
2306
+ await writeFile(prdPath, [
2307
+ '# Ultragoal JSON status',
2308
+ '',
2309
+ 'Active ultragoal story G001-team-runtime-bridge uses .omx/ultragoal/goals.json and .omx/ultragoal/ledger.jsonl.',
2310
+ `Launch via omx team 1:executor "${task}"`,
2311
+ ].join('\n'));
2312
+ await writeFile(testSpecPath, '# Ultragoal JSON status test spec\n');
2313
+ const hint = readApprovedExecutionLaunchHint(wd, 'team', { prdPath, task });
2314
+ assert.ok(hint);
2315
+ await writePersistedApprovedTeamExecutionBinding('ultragoal-json-team', wd, buildApprovedTeamExecutionBinding(hint));
2316
+ await writePersistedTeamUltragoalContext('ultragoal-json-team', wd, {
2317
+ kind: 'leader_owned_ultragoal_context',
2318
+ goalsPath: '.omx/ultragoal/goals.json',
2319
+ ledgerPath: '.omx/ultragoal/ledger.jsonl',
2320
+ activeGoalId: 'G001-team-runtime-bridge',
2321
+ codexGoalMode: 'aggregate',
2322
+ checkpointPolicy: 'fresh_leader_get_goal_required',
2323
+ });
2324
+ console.log = (...args) => logs.push(args.map(String).join(' '));
2325
+ await withoutTeamTestWorkerEnv(() => teamCommand(['status', 'ultragoal-json-team', '--json']));
2326
+ const payload = JSON.parse(logs[0] ?? '{}');
2327
+ assert.equal(payload.ultragoal_checkpoint_guidance?.goal_id, 'G001-team-runtime-bridge');
2328
+ assert.equal(payload.ultragoal_checkpoint_guidance?.goals_path, '.omx/ultragoal/goals.json');
2329
+ assert.equal(payload.ultragoal_checkpoint_guidance?.ledger_path, '.omx/ultragoal/ledger.jsonl');
2330
+ assert.equal(payload.ultragoal_checkpoint_guidance?.checkpoint_policy, 'fresh_leader_get_goal_required');
2331
+ assert.match(payload.ultragoal_checkpoint_guidance?.checkpoint_command_template ?? '', /omx ultragoal checkpoint/);
2332
+ assert.match(payload.ultragoal_checkpoint_guidance?.checkpoint_command_template ?? '', /--codex-goal-json/);
2333
+ assert.ok(payload.ultragoal_checkpoint_guidance?.evidence_requirements?.some((item) => item.includes('.omx/ultragoal artifacts')));
2334
+ }
2335
+ finally {
2336
+ console.log = originalLog;
2337
+ process.chdir(previousCwd);
2338
+ await rm(wd, { recursive: true, force: true });
2339
+ }
2340
+ });
2341
+ it('omits Ultragoal checkpoint guidance in JSON status for completed plans without activeGoalId', async () => {
2342
+ const wd = await mkdtemp(join(tmpdir(), 'omx-team-status-ultragoal-idle-json-'));
2343
+ const previousCwd = process.cwd();
2344
+ const logs = [];
2345
+ const originalLog = console.log;
2346
+ try {
2347
+ process.chdir(wd);
2348
+ await withoutTeamTestWorkerEnv(() => initTeamState('ultragoal-idle-json-team', 'inspect idle ultragoal status', 'executor', 1, wd));
2349
+ await mkdir(join(wd, '.omx', 'ultragoal'), { recursive: true });
2350
+ await writeFile(join(wd, '.omx', 'ultragoal', 'goals.json'), `${JSON.stringify({
2351
+ version: 1,
2352
+ codexGoalMode: 'aggregate',
2353
+ goals: [{
2354
+ id: 'G001-completed-story',
2355
+ title: 'Completed story',
2356
+ status: 'complete',
2357
+ }],
2358
+ })}\n`);
2359
+ console.log = (...args) => logs.push(args.map(String).join(' '));
2360
+ await withoutTeamTestWorkerEnv(() => teamCommand(['status', 'ultragoal-idle-json-team', '--json']));
2361
+ const payload = JSON.parse(logs[0] ?? '{}');
2362
+ assert.equal(payload.status, 'ok');
2363
+ assert.equal('ultragoal_checkpoint_guidance' in payload, false);
2364
+ }
2365
+ finally {
2366
+ console.log = originalLog;
2367
+ process.chdir(previousCwd);
2368
+ await rm(wd, { recursive: true, force: true });
2369
+ }
2370
+ });
2371
+ it('prints Ultragoal checkpoint guidance in text status with fresh get_goal requirement', async () => {
2372
+ const wd = await mkdtemp(join(tmpdir(), 'omx-team-status-ultragoal-text-'));
2373
+ const previousCwd = process.cwd();
2374
+ const logs = [];
2375
+ const originalLog = console.log;
2376
+ try {
2377
+ process.chdir(wd);
2378
+ await withoutTeamTestWorkerEnv(() => initTeamState('ultragoal-text-team', 'inspect ultragoal text guidance', 'executor', 1, wd));
2379
+ const plansDir = join(wd, '.omx', 'plans');
2380
+ await mkdir(plansDir, { recursive: true });
2381
+ const prdPath = join(plansDir, 'prd-ultragoal-text.md');
2382
+ const testSpecPath = join(plansDir, 'test-spec-ultragoal-text.md');
2383
+ const task = 'Execute Team + Ultragoal G001-team-runtime-bridge text plan';
2384
+ await writeFile(prdPath, [
2385
+ '# Ultragoal text status',
2386
+ '',
2387
+ 'Team evidence checkpoints G001-team-runtime-bridge into .omx/ultragoal/goals.json and .omx/ultragoal/ledger.jsonl.',
2388
+ `Launch via omx team 1:executor "${task}"`,
2389
+ ].join('\n'));
2390
+ await writeFile(testSpecPath, '# Ultragoal text status test spec\n');
2391
+ const hint = readApprovedExecutionLaunchHint(wd, 'team', { prdPath, task });
2392
+ assert.ok(hint);
2393
+ await writePersistedApprovedTeamExecutionBinding('ultragoal-text-team', wd, buildApprovedTeamExecutionBinding(hint));
2394
+ await writePersistedTeamUltragoalContext('ultragoal-text-team', wd, {
2395
+ kind: 'leader_owned_ultragoal_context',
2396
+ goalsPath: '.omx/ultragoal/goals.json',
2397
+ ledgerPath: '.omx/ultragoal/ledger.jsonl',
2398
+ activeGoalId: 'G001-team-runtime-bridge',
2399
+ codexGoalMode: 'aggregate',
2400
+ checkpointPolicy: 'fresh_leader_get_goal_required',
2401
+ });
2402
+ console.log = (...args) => logs.push(args.map(String).join(' '));
2403
+ await withoutTeamTestWorkerEnv(() => teamCommand(['status', 'ultragoal-text-team']));
2404
+ const output = logs.join('\n');
2405
+ assert.match(output, /ultragoal_checkpoint_guidance/);
2406
+ assert.match(output, /G001-team-runtime-bridge/);
2407
+ assert.match(output, /\.omx\/ultragoal\/goals\.json/);
2408
+ assert.match(output, /\.omx\/ultragoal\/ledger\.jsonl/);
2409
+ assert.match(output, /leader captured fresh get_goal JSON before checkpointing/i);
2410
+ assert.match(output, /workers do not own ultragoal goal state/i);
2411
+ }
2412
+ finally {
2413
+ console.log = originalLog;
2414
+ process.chdir(previousCwd);
2415
+ await rm(wd, { recursive: true, force: true });
2416
+ }
2417
+ });
2294
2418
  it('returns a missing envelope in JSON mode when team state is absent', async () => {
2295
2419
  const wd = await mkdtemp(join(tmpdir(), 'omx-team-status-missing-'));
2296
2420
  const previousCwd = process.cwd();