oh-my-opencode 4.19.0 → 4.19.2

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 (310) hide show
  1. package/.agents/command/omomomo.md +1 -1
  2. package/.agents/skills/omomomo/SKILL.md +1 -1
  3. package/.opencode/command/omomomo.md +1 -1
  4. package/README.ja.md +6 -6
  5. package/README.ko.md +6 -6
  6. package/README.md +6 -6
  7. package/README.ru.md +6 -6
  8. package/README.zh-cn.md +6 -6
  9. package/dist/agents/atlas/agent.d.ts +5 -3
  10. package/dist/agents/explore.d.ts +4 -2
  11. package/dist/agents/gpt-prompt-identity.d.ts +3 -0
  12. package/dist/agents/hephaestus/agent.d.ts +4 -2
  13. package/dist/agents/librarian.d.ts +4 -2
  14. package/dist/agents/metis.d.ts +4 -2
  15. package/dist/agents/momus.d.ts +3 -2
  16. package/dist/agents/multimodal-looker.d.ts +4 -2
  17. package/dist/agents/oracle.d.ts +4 -2
  18. package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -0
  19. package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
  20. package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
  21. package/dist/agents/sisyphus/index.d.ts +2 -0
  22. package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
  23. package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
  24. package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
  25. package/dist/agents/types.d.ts +2 -2
  26. package/dist/cli/index.js +23577 -19269
  27. package/dist/cli-node/index.js +23577 -19269
  28. package/dist/config/schema/agent-names.d.ts +26 -26
  29. package/dist/config/schema/agent-overrides.d.ts +400 -400
  30. package/dist/config/schema/browser-automation.d.ts +2 -2
  31. package/dist/config/schema/categories.d.ts +36 -36
  32. package/dist/config/schema/codegraph.d.ts +2 -0
  33. package/dist/config/schema/commands.d.ts +2 -2
  34. package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
  35. package/dist/config/schema/experimental.d.ts +1 -1
  36. package/dist/config/schema/fallback-models.d.ts +25 -25
  37. package/dist/config/schema/hooks.d.ts +43 -43
  38. package/dist/config/schema/internal/permission.d.ts +9 -9
  39. package/dist/config/schema/keyword-detector.d.ts +6 -6
  40. package/dist/config/schema/oh-my-opencode-config.d.ts +404 -402
  41. package/dist/config/schema/tmux.d.ts +6 -6
  42. package/dist/create-hooks.d.ts +35 -35
  43. package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
  44. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  45. package/dist/features/claude-tasks/types.d.ts +4 -4
  46. package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
  47. package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
  48. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
  49. package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
  50. package/dist/features/tmux-subagent/index.d.ts +1 -0
  51. package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
  52. package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
  53. package/dist/help/schema/acp.d.ts +3 -3
  54. package/dist/help/schema/doctor.d.ts +4 -4
  55. package/dist/help/schema/status.d.ts +3 -3
  56. package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
  57. package/dist/hooks/goal/types.d.ts +5 -5
  58. package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
  59. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  60. package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
  61. package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
  62. package/dist/hooks/start-work/worktree-block.d.ts +5 -0
  63. package/dist/index.js +27370 -21301
  64. package/dist/mcp/types.d.ts +3 -3
  65. package/dist/oh-my-opencode.schema.json +11 -0
  66. package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
  67. package/dist/plugin/command-execute-before.d.ts +3 -3
  68. package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
  69. package/dist/shared/omo-process-sweep.d.ts +18 -0
  70. package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
  71. package/dist/shared/tmux/tmux-utils.d.ts +1 -1
  72. package/dist/shared/typescript-native-source-parser.d.ts +7 -0
  73. package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
  74. package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  75. package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
  76. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  77. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  78. package/dist/skills/debugging/SKILL.md +2 -1
  79. package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  80. package/dist/skills/programming/SKILL.md +11 -1
  81. package/dist/skills/programming/references/logging.md +6 -1
  82. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  83. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
  84. package/dist/skills/start-work/SKILL.md +12 -2
  85. package/dist/skills/ulw-plan/SKILL.md +21 -2
  86. package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
  87. package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
  88. package/dist/testing/create-plugin-module.d.ts +1 -0
  89. package/dist/tools/task/types.d.ts +10 -10
  90. package/dist/tui.js +23442 -19182
  91. package/package.json +14 -14
  92. package/packages/git-bash-mcp/dist/cli.js +54 -8
  93. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +62 -2
  94. package/packages/lsp-core/src/lsp/client.ts +14 -1
  95. package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
  96. package/packages/lsp-core/src/mcp.ts +9 -0
  97. package/packages/lsp-daemon/dist/cli.js +319 -51
  98. package/packages/lsp-daemon/dist/client.js +136 -48
  99. package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
  100. package/packages/lsp-daemon/dist/daemon-client.js +4 -34
  101. package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
  102. package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
  103. package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
  104. package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
  105. package/packages/lsp-daemon/dist/daemon-server.js +5 -1
  106. package/packages/lsp-daemon/dist/index.js +137 -48
  107. package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
  108. package/packages/lsp-daemon/dist/proxy.js +1 -0
  109. package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
  110. package/packages/lsp-daemon/dist/version-reap.js +182 -0
  111. package/packages/lsp-tools-mcp/dist/cli.js +61 -10
  112. package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
  113. package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
  114. package/packages/lsp-tools-mcp/dist/tools.js +6 -1
  115. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  116. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +72 -12
  117. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  118. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  119. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
  120. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +779 -385
  121. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +302 -173
  122. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  123. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
  124. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +23 -42
  125. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
  126. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
  127. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +17 -9
  128. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +18 -25
  129. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
  130. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +5 -0
  131. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +176 -0
  132. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +6 -1
  133. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
  134. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
  135. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +6 -0
  136. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
  137. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
  138. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +2 -1
  139. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
  140. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +42 -0
  141. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +122 -10
  142. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
  143. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +101 -64
  144. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  145. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  146. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  147. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  148. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  149. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  150. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  151. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
  152. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  153. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  154. package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
  155. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  156. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  157. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
  158. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
  159. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  160. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  161. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  162. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  163. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  164. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  165. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  166. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
  167. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
  168. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  169. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  170. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
  171. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  172. package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
  173. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
  174. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  175. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  176. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
  177. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +21 -2
  178. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
  179. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
  180. package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
  181. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
  182. package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
  183. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
  184. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
  185. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
  186. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
  187. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
  188. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  189. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  190. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
  191. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
  192. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
  193. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
  194. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
  195. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
  196. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
  197. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
  198. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
  199. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
  200. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
  201. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
  202. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
  203. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
  204. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  205. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
  206. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
  207. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
  208. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
  209. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
  210. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
  211. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
  212. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
  213. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
  214. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
  215. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  216. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  217. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -1
  218. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
  219. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
  220. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
  221. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
  222. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
  223. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
  224. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
  225. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
  226. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
  227. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
  228. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
  229. package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
  230. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
  231. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
  232. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
  233. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
  234. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
  235. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
  236. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
  237. package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
  238. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
  239. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
  240. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
  241. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
  242. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
  243. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
  244. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
  245. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
  246. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
  247. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  248. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  249. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  250. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  251. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  252. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  253. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  254. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  255. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  256. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  257. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  258. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
  259. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  260. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
  261. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  262. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
  263. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  264. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  265. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  266. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  267. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  268. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  269. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  270. package/packages/omo-codex/plugin/package-lock.json +41 -41
  271. package/packages/omo-codex/plugin/package.json +1 -1
  272. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +44 -0
  273. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
  274. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  275. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
  276. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  277. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  278. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
  279. package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  280. package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
  281. package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
  282. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
  283. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
  284. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
  285. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -1
  286. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
  287. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +21 -2
  288. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
  289. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
  290. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
  291. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
  292. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
  293. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
  294. package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
  295. package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
  296. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
  297. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  298. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
  299. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  300. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  301. package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
  302. package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  303. package/packages/shared-skills/skills/programming/SKILL.md +11 -1
  304. package/packages/shared-skills/skills/programming/references/logging.md +6 -1
  305. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  306. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
  307. package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
  308. package/packages/shared-skills/skills/ulw-plan/SKILL.md +21 -2
  309. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
  310. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
@@ -0,0 +1,64 @@
1
+ import { checkpointUlwLoop } from "./checkpoint.js";
2
+ import { hasFlag, parseCodexGoalJson, readValue } from "./cli-arg-parser.js";
3
+ import { blockedDecisionHandoff, printJson } from "./cli-output.js";
4
+ import { buildCodexGoalInstruction } from "./codex-goal-instruction.js";
5
+ import { startNextUlwLoop, summarizeUlwLoopPlan } from "./plan-crud.js";
6
+ import { UlwLoopError } from "./types.js";
7
+ export async function checkpointAndContinue(repoRoot, args, scope) {
8
+ const result = await checkpointUlwLoop(repoRoot, args, scope);
9
+ if (args.status !== "complete" || result.aggregateCompletion !== undefined || !args.advance)
10
+ return result;
11
+ const next = await startNextUlwLoop(repoRoot, {}, scope);
12
+ if ("done" in next)
13
+ return { ...result, plan: next.plan, next: doneNext(next.plan) };
14
+ const instruction = buildCodexGoalInstruction({ plan: next.plan, goal: next.goal });
15
+ return { ...result, plan: next.plan, next: { resumed: next.resumed, goal: next.goal, instruction } };
16
+ }
17
+ export async function checkpoint(repoRoot, argv, json, scope) {
18
+ const goalId = required(argv, "--goal-id");
19
+ const statusValue = checkpointStatus(required(argv, "--status"));
20
+ const evidence = required(argv, "--evidence");
21
+ const codexGoalJson = await parseCodexGoalJson(statusValue === "complete" ? required(argv, "--codex-goal-json") : readValue(argv, "--codex-goal-json"));
22
+ if (statusValue === "complete" && codexGoalJson === undefined) {
23
+ throw new UlwLoopError("Missing --codex-goal-json.", "ULW_LOOP_CODEX_GOAL_JSON_REQUIRED");
24
+ }
25
+ const qualityGateJson = readValue(argv, "--quality-gate-json");
26
+ const args = {
27
+ goalId,
28
+ status: statusValue,
29
+ evidence,
30
+ advance: !hasFlag(argv, "--no-advance"),
31
+ ...(codexGoalJson === undefined ? {} : { codexGoalJson }),
32
+ ...(qualityGateJson === undefined ? {} : { qualityGateJson }),
33
+ };
34
+ const result = await checkpointAndContinue(repoRoot, args, scope);
35
+ if (json)
36
+ printJson({ ok: true, ...result, summary: summarizeUlwLoopPlan(result.plan) });
37
+ else
38
+ printCheckpointText(result);
39
+ return 0;
40
+ }
41
+ function printCheckpointText(result) {
42
+ process.stdout.write(`ulw-loop checkpoint: ${result.goal.id} -> ${result.goal.status}\n`);
43
+ if (result.next === undefined)
44
+ return;
45
+ if ("instruction" in result.next)
46
+ process.stdout.write(`${result.next.instruction.text}\n`);
47
+ else
48
+ process.stdout.write(`${result.next.handoff || "ulw-loop: all goals complete"}\n`);
49
+ }
50
+ function doneNext(plan) {
51
+ const handoff = blockedDecisionHandoff(plan);
52
+ return { done: true, blocked: handoff.length > 0, handoff };
53
+ }
54
+ function required(argv, flag) {
55
+ const value = readValue(argv, flag)?.trim();
56
+ if (value)
57
+ return value;
58
+ throw new UlwLoopError(`Missing ${flag}.`, "ULW_LOOP_ARGUMENT_MISSING", { details: { flag } });
59
+ }
60
+ function checkpointStatus(value) {
61
+ if (value === "complete" || value === "failed" || value === "blocked")
62
+ return value;
63
+ throw new UlwLoopError("Missing or invalid --status; expected complete, failed, or blocked.", "ULW_LOOP_STATUS_INVALID", { details: { status: value } });
64
+ }
@@ -1,4 +1,4 @@
1
- import { ulwLoopAttemptEvidenceDir } from "./paths.js";
1
+ // biome-ignore-all format: checkpoint stays under the pure LOC ceiling.
2
2
  import { existsSync, statSync } from "node:fs";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import { resolve } from "node:path";
@@ -6,9 +6,11 @@ import { buildTaskScopedAggregateReconciliationHint, canReconcileActiveFinalTask
6
6
  import { formatCodexGoalReconciliation, readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot, } from "./codex-goal-snapshot.js";
7
7
  import { requireAllCriteriaPass, requireAllPlanCriteriaPass, requireEssentialCriteriaPass } from "./evidence.js";
8
8
  import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective, isFinalRunCompletionCandidate, } from "./goal-status.js";
9
+ import { ulwLoopAttemptEvidenceDir } from "./paths.js";
9
10
  import { appendLedger, readUlwLoopPlan, withUlwLoopMutationLock, writePlan } from "./plan-io.js";
10
11
  import { classifyExternalAuthorizationBlocker, clearGoalBlockerFields, sameBlockerOccurrences, validateQualityGate, } from "./quality-gate.js";
11
12
  import { iso, UlwLoopError } from "./types.js";
13
+ import { batchClosedBy, requireAllValidationBatchesClosed, requireBatchFinalReady, requireBatchGate } from "./validation-batch.js";
12
14
  const QUALITY_GATE_FS = { existsSync, statSync };
13
15
  function ulwLoopFail(message, code) {
14
16
  throw new UlwLoopError(message, code);
@@ -112,9 +114,11 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
112
114
  if (args.status === "complete") {
113
115
  const aggregate = codexGoalMode(plan) === "aggregate";
114
116
  const final = isFinalRunCompletionCandidate(plan, goal);
117
+ const closesBatch = batchClosedBy(plan, goal.id) !== undefined;
115
118
  if (final) {
116
119
  requireAllCriteriaPass(goal);
117
120
  requireAllPlanCriteriaPass(plan);
121
+ requireAllValidationBatchesClosed(plan, goal.id);
118
122
  }
119
123
  else if (aggregate)
120
124
  requireEssentialCriteriaPass(goal);
@@ -144,9 +148,13 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
144
148
  if (!taskScoped)
145
149
  throw new UlwLoopError(`${formatCodexGoalReconciliation(reconciliation)}${aggregate && snapshot?.status === "complete" && objective !== undefined ? buildTaskScopedAggregateReconciliationHint(goal, final) : ""}`, "ulw_loop_codex_snapshot_mismatch");
146
150
  }
151
+ if (closesBatch)
152
+ requireBatchFinalReady(plan, goal);
153
+ if (closesBatch && args.qualityGateJson === undefined)
154
+ throw new UlwLoopError("Validation batch final checkpoint requires --quality-gate-json.", "ULW_LOOP_VALIDATION_BATCH_GATE_REQUIRED");
147
155
  if (final)
148
156
  aggregateCompletion = makeAggregateCompletion(now, evidence, codexGoal);
149
- if (final || aggregateCompletion !== undefined)
157
+ if (final || aggregateCompletion !== undefined || closesBatch) {
150
158
  qualityGate = validateQualityGate(await readJsonInput(args.qualityGateJson, repoRoot), {
151
159
  repoRoot,
152
160
  fs: QUALITY_GATE_FS,
@@ -154,6 +162,8 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
154
162
  ? { currentAttemptDir: ulwLoopAttemptEvidenceDir(goal.id, goal.attempt, scope) }
155
163
  : {}),
156
164
  });
165
+ requireBatchGate(plan, goal, qualityGate);
166
+ }
157
167
  goal.status = "complete";
158
168
  goal.completedAt = now;
159
169
  goal.evidence = evidence;
@@ -172,6 +182,9 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
172
182
  await writePlan(repoRoot, plan, scope);
173
183
  const ledgerEntry = buildLedger(now, args, goal, qualityGate, codexGoal, aggregateCompletion);
174
184
  await appendLedger(repoRoot, ledgerEntry, scope);
185
+ const closedBatch = args.status === "complete" ? batchClosedBy(plan, goal.id) : undefined;
186
+ if (closedBatch !== undefined)
187
+ await appendLedger(repoRoot, { at: now, kind: "batch_closed", goalId: goal.id, message: closedBatch.batchId }, scope);
175
188
  return aggregateCompletion === undefined
176
189
  ? { plan, goal, ledgerEntry }
177
190
  : { plan, goal, ledgerEntry, aggregateCompletion };
@@ -1,7 +1,7 @@
1
1
  // biome-ignore-all format: keep this module under the mandated pure LOC budget.
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { UlwLoopError } from "./types.js";
4
- const VALUE_FLAGS = new Set("--brief --brief-file --session-id --codex-goal-mode --goal --goal-id --criterion-id --status --evidence --notes --codex-goal-json --quality-gate-json --kind --rationale --title --objective --target-goal-id --source --after-json --directive-json --directive-file --idempotency-key".split(" "));
4
+ const VALUE_FLAGS = new Set("--brief --brief-file --session-id --codex-goal-mode --validation-batch-json --goal --goal-id --criterion-id --status --evidence --notes --codex-goal-json --quality-gate-json --kind --rationale --title --objective --target-goal-id --source --after-json --directive-json --directive-file --idempotency-key --proposals-json".split(" "));
5
5
  const SUBCOMMANDS = new Set("create-goals status complete-goals criteria record-evidence checkpoint steer add-goal record-review-blockers".split(" "));
6
6
  export function hasFlag(argv, flag) { return argv.includes(flag); }
7
7
  export function readValue(argv, flag) {
@@ -1,6 +1,7 @@
1
+ import { checkpoint } from "./checkpoint-continuation.js";
1
2
  import { hasFlag, readValue } from "./cli-arg-parser.js";
2
3
  import { printJsonError, ULW_LOOP_HELP } from "./cli-output.js";
3
- import { addGoal, captureEvidence, checkpoint, completeGoals, createGoals, criteria, reviewBlockers, status, steer, } from "./cli-subcommands.js";
4
+ import { addGoal, captureEvidence, completeGoals, createGoals, criteria, reviewBlockers, status, steer, } from "./cli-subcommands.js";
4
5
  import { resolveUlwLoopSessionIdFromEnv } from "./paths.js";
5
6
  import { UlwLoopError } from "./types.js";
6
7
  export const ULW_LOOP_SUBCOMMANDS = [
@@ -1,5 +1,5 @@
1
1
  import type { UlwLoopCodexGoalMode, UlwLoopPlan } from "./types.js";
2
- export declare const ULW_LOOP_HELP = "Usage:\n omo ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--force] [--json]\n omo ulw-loop status [--json]\n omo ulw-loop complete-goals [--retry-failed] [--json]\n omo ulw-loop criteria --goal-id <id> [--json]\n omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--json]\n omo ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--json]\n omo ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
2
+ export declare const ULW_LOOP_HELP = "Usage:\n omo ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]\n omo ulw-loop status [--json]\n omo ulw-loop complete-goals [--retry-failed] [--json]\n omo ulw-loop criteria --goal-id <id> [--json]\n omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]\n omo ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--proposals-json <json-or-path>] [--json]\n omo ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
3
3
  export declare function printJson(value: unknown): void;
4
4
  export declare function printJsonError(error: unknown): void;
5
5
  export declare function printStatus(plan: UlwLoopPlan): void;
@@ -1,12 +1,12 @@
1
1
  import { UlwLoopError } from "./types.js";
2
2
  export const ULW_LOOP_HELP = `Usage:
3
- omo ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--force] [--json]
3
+ omo ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]
4
4
  omo ulw-loop status [--json]
5
5
  omo ulw-loop complete-goals [--retry-failed] [--json]
6
6
  omo ulw-loop criteria --goal-id <id> [--json]
7
7
  omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence "..." [--notes "..."] [--json]
8
- omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence "..." --codex-goal-json <...> [--quality-gate-json <...>] [--json]
9
- omo ulw-loop steer --kind <kind> ... --evidence "..." --rationale "..." [--json]
8
+ omo ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence "..." --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]
9
+ omo ulw-loop steer --kind <kind> ... --evidence "..." --rationale "..." [--proposals-json <json-or-path>] [--json]
10
10
  omo ulw-loop add-goal --title "..." --objective "..." [--json]
11
11
  omo ulw-loop record-review-blockers --goal-id <id> --title "..." --objective "..." --evidence "..." --codex-goal-json <...> [--json]
12
12
 
@@ -1,3 +1,4 @@
1
+ import type { SteerUlwLoopBatchResult } from "./steering-batch.js";
1
2
  import type { SteerUlwLoopResult, UlwLoopSteeringMutationKind, UlwLoopSteeringProposal, UlwLoopSteeringSource, UlwLoopSuccessCriterionUserModel } from "./types.js";
2
3
  export type CliSteeringProposal = UlwLoopSteeringProposal & {
3
4
  readonly goalId?: string;
@@ -9,4 +10,6 @@ export declare function parseSteeringKind(argv: readonly string[]): UlwLoopSteer
9
10
  export declare function parseSteeringSource(argv: readonly string[]): UlwLoopSteeringSource;
10
11
  export declare function parseSteeringProposal(argv: readonly string[]): Promise<CliSteeringProposal>;
11
12
  export declare function normalizeSteeringProposal(proposal: CliSteeringProposal): CliSteeringProposal;
13
+ export declare function parseSteeringProposals(argv: readonly string[]): Promise<readonly CliSteeringProposal[]>;
12
14
  export declare function printSteerResult(result: SteerUlwLoopResult, json: boolean): void;
15
+ export declare function printSteerBatchResult(result: SteerUlwLoopBatchResult, json: boolean): void;
@@ -28,6 +28,16 @@ function requiredGoal(argv) { const value = text(parseGoalArg(argv), "--goal-id"
28
28
  function readObject(value, key) { return Object.entries(value).find(([name]) => name === key)?.[1]; }
29
29
  function isPlain(value) { return typeof value === "object" && value !== null && !Array.isArray(value); }
30
30
  function objectText(value, key) { const candidate = readObject(value, key); return typeof candidate === "string" ? candidate : undefined; }
31
+ function objectStrings(value, key) { const candidate = readObject(value, key); return Array.isArray(candidate) && candidate.every((item) => typeof item === "string") ? candidate : undefined; }
32
+ function objectChildren(value, key) { const candidate = readObject(value, key); if (!Array.isArray(candidate))
33
+ return undefined; const parsed = []; for (const item of candidate) {
34
+ const next = child(item);
35
+ if (next === null)
36
+ return fail(`${key} entries require title/objective.`, "ULW_LOOP_STEERING_CHILD_INVALID", { key });
37
+ parsed.push(next);
38
+ } return parsed; }
39
+ function isProposalKind(value) { return typeof value === "string" && ULW_LOOP_STEERING_MUTATION_KINDS.some((kind) => kind === value); }
40
+ function isProposalSource(value) { return typeof value === "string" && SOURCES.some((source) => source === value); }
31
41
  export function parseSteeringKind(argv) {
32
42
  const value = readValue(argv, "--kind");
33
43
  if (isKind(value))
@@ -144,6 +154,71 @@ export function normalizeSteeringProposal(proposal) {
144
154
  const pendingOrder = normalizedStrings(proposal.pendingOrder, "pendingOrder");
145
155
  return { kind: proposal.kind, source: proposal.source, evidence, rationale, ...(goalId === undefined ? {} : { goalId }), ...(targetGoalId === undefined ? {} : { targetGoalId }), ...(targetGoalIds === undefined ? {} : { targetGoalIds }), ...(criterionId === undefined ? {} : { criterionId }), ...(title === undefined ? {} : { title }), ...(objective === undefined ? {} : { objective }), ...(childGoals === undefined ? {} : { childGoals }), ...(revisedTitle === undefined ? {} : { revisedTitle }), ...(revisedObjective === undefined ? {} : { revisedObjective }), ...(pendingOrder === undefined ? {} : { pendingOrder }), ...(blockedReason === undefined ? {} : { blockedReason }), ...(proposal.after === undefined ? {} : { after: proposal.after }), ...(directiveText === undefined ? {} : { directiveText }), ...(promptSignature === undefined ? {} : { promptSignature }), ...(idempotencyKey === undefined ? {} : { idempotencyKey }), ...(proposal.now === undefined ? {} : { now: proposal.now }), ...(scenario === undefined ? {} : { scenario }), ...(expectedEvidence === undefined ? {} : { expectedEvidence }), ...(proposal.userModel === undefined ? {} : { userModel: proposal.userModel }) };
146
156
  }
157
+ export async function parseSteeringProposals(argv) {
158
+ const input = text(readValue(argv, "--proposals-json"), "--proposals-json");
159
+ if (input === undefined)
160
+ return [await parseSteeringProposal(argv)];
161
+ if (readValue(argv, "--kind") !== undefined)
162
+ return fail("--kind and --proposals-json are mutually exclusive.", "ULW_LOOP_STEERING_BATCH_CONFLICT", { flags: ["--kind", "--proposals-json"] });
163
+ const raw = await readJsonInput(input);
164
+ if (!Array.isArray(raw) || raw.length === 0)
165
+ return fail("--proposals-json must be a non-empty JSON array.", "ULW_LOOP_STEERING_BATCH_ARRAY_REQUIRED", { flag: "--proposals-json" });
166
+ const proposals = [];
167
+ for (const item of raw)
168
+ proposals.push(normalizeSteeringProposal(proposalFromObject(item)));
169
+ return proposals;
170
+ }
171
+ function proposalFromObject(value) {
172
+ if (!isPlain(value))
173
+ return fail("--proposals-json entries must be objects.", "ULW_LOOP_STEERING_BATCH_ITEM_INVALID", { flag: "--proposals-json" });
174
+ const kind = readObject(value, "kind");
175
+ const source = readObject(value, "source") ?? "cli";
176
+ if (!isProposalKind(kind))
177
+ return fail(`Invalid batch steering kind: ${String(kind)}.`, "ULW_LOOP_STEERING_KIND_INVALID", { value: kind });
178
+ if (!isProposalSource(source))
179
+ return fail(`Invalid batch steering source: ${String(source)}.`, "ULW_LOOP_STEERING_SOURCE_INVALID", { value: source });
180
+ let proposal = { kind, source, evidence: objectText(value, "evidence") ?? "", rationale: objectText(value, "rationale") ?? "" };
181
+ const goalId = objectText(value, "goalId");
182
+ const targetGoalId = objectText(value, "targetGoalId");
183
+ const criterionId = objectText(value, "criterionId");
184
+ const title = objectText(value, "title");
185
+ const objective = objectText(value, "objective");
186
+ const revisedTitle = objectText(value, "revisedTitle");
187
+ const revisedObjective = objectText(value, "revisedObjective");
188
+ const scenario = objectText(value, "scenario");
189
+ const expectedEvidence = objectText(value, "expectedEvidence");
190
+ const idempotencyKey = objectText(value, "idempotencyKey");
191
+ const targetGoalIds = objectStrings(value, "targetGoalIds");
192
+ const pendingOrder = objectStrings(value, "pendingOrder");
193
+ const childGoals = objectChildren(value, "childGoals");
194
+ if (goalId !== undefined)
195
+ proposal = { ...proposal, goalId };
196
+ if (targetGoalId !== undefined)
197
+ proposal = { ...proposal, targetGoalId };
198
+ if (criterionId !== undefined)
199
+ proposal = { ...proposal, criterionId };
200
+ if (title !== undefined)
201
+ proposal = { ...proposal, title };
202
+ if (objective !== undefined)
203
+ proposal = { ...proposal, objective };
204
+ if (revisedTitle !== undefined)
205
+ proposal = { ...proposal, revisedTitle };
206
+ if (revisedObjective !== undefined)
207
+ proposal = { ...proposal, revisedObjective };
208
+ if (scenario !== undefined)
209
+ proposal = { ...proposal, scenario };
210
+ if (expectedEvidence !== undefined)
211
+ proposal = { ...proposal, expectedEvidence };
212
+ if (idempotencyKey !== undefined)
213
+ proposal = { ...proposal, idempotencyKey };
214
+ if (targetGoalIds !== undefined)
215
+ proposal = { ...proposal, targetGoalIds };
216
+ if (pendingOrder !== undefined)
217
+ proposal = { ...proposal, pendingOrder };
218
+ if (childGoals !== undefined)
219
+ proposal = { ...proposal, childGoals };
220
+ return proposal;
221
+ }
147
222
  export function printSteerResult(result, json) {
148
223
  if (json) {
149
224
  printJson({ ok: result.accepted, accepted: result.accepted, rejectedReasons: result.rejectedReasons, deduped: result.deduped, audit: result.audit, plan: result.plan });
@@ -157,3 +232,13 @@ export function printSteerResult(result, json) {
157
232
  process.stdout.write(`idempotency-key: ${result.audit.idempotencyKey}\n`);
158
233
  printStatus(result.plan);
159
234
  }
235
+ export function printSteerBatchResult(result, json) {
236
+ if (json) {
237
+ printJson({ ok: result.accepted, accepted: result.accepted, rejectedReasons: result.rejectedReasons, results: result.results, plan: result.plan });
238
+ return;
239
+ }
240
+ process.stdout.write(`ulw-loop steer batch: ${result.accepted ? "accepted" : "rejected"} ${result.results.length} proposal(s)\n`);
241
+ if (result.rejectedReasons.length > 0)
242
+ process.stdout.write(`rejected: ${result.rejectedReasons.join("; ")}\n`);
243
+ printStatus(result.plan);
244
+ }
@@ -2,7 +2,6 @@ import { type UlwLoopScope } from "./paths.js";
2
2
  export declare function createGoals(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
3
3
  export declare function status(repoRoot: string, json: boolean, scope?: UlwLoopScope): Promise<number>;
4
4
  export declare function completeGoals(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
5
- export declare function checkpoint(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
6
5
  export declare function steer(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
7
6
  export declare function addGoal(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
8
7
  export declare function criteria(repoRoot: string, argv: readonly string[], json: boolean, scope?: UlwLoopScope): Promise<number>;
@@ -1,8 +1,7 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { checkpointUlwLoop } from "./checkpoint.js";
3
2
  import { hasFlag, parseCodexGoalJson, parseRecordEvidenceArgs, positionalText, readStdin, readValue, } from "./cli-arg-parser.js";
4
3
  import { blockedDecisionHandoff, normalizeCodexGoalMode, printJson, printStatus } from "./cli-output.js";
5
- import { parseSteeringProposal, printSteerResult } from "./cli-steering.js";
4
+ import { parseSteeringProposals, printSteerBatchResult, printSteerResult } from "./cli-steering.js";
6
5
  import { buildCodexGoalInstruction } from "./codex-goal-instruction.js";
7
6
  import { recordEvidence } from "./evidence.js";
8
7
  import { isEssentialCriterion } from "./goal-status.js";
@@ -11,6 +10,7 @@ import { addUlwLoopGoal, createUlwLoopPlan, startNextUlwLoop, summarizeUlwLoopPl
11
10
  import { readUlwLoopPlan } from "./plan-io.js";
12
11
  import { recordFinalReviewBlockers } from "./review-blockers.js";
13
12
  import { steerUlwLoop } from "./steering.js";
13
+ import { steerUlwLoopBatch } from "./steering-batch.js";
14
14
  import { UlwLoopError } from "./types.js";
15
15
  export async function createGoals(repoRoot, argv, json, scope) {
16
16
  const briefFile = readValue(argv, "--brief-file");
@@ -21,10 +21,12 @@ export async function createGoals(repoRoot, argv, json, scope) {
21
21
  if (!brief.trim()) {
22
22
  throw new UlwLoopError("Missing brief text. Pass --brief, --brief-file, --from-stdin, or positional text.", "ULW_LOOP_BRIEF_REQUIRED");
23
23
  }
24
+ const validationBatchesJson = readValue(argv, "--validation-batch-json");
24
25
  const plan = await createUlwLoopPlan(repoRoot, {
25
26
  brief,
26
27
  codexGoalMode: normalizeCodexGoalMode(readValue(argv, "--codex-goal-mode")),
27
28
  force: hasFlag(argv, "--force"),
29
+ ...(validationBatchesJson === undefined ? {} : { validationBatchesJson }),
28
30
  }, scope);
29
31
  if (json)
30
32
  printJson({ ok: true, plan, summary: summarizeUlwLoopPlan(plan) });
@@ -76,33 +78,16 @@ export async function completeGoals(repoRoot, argv, json, scope) {
76
78
  process.stdout.write(`${instruction.text}\n`);
77
79
  return 0;
78
80
  }
79
- export async function checkpoint(repoRoot, argv, json, scope) {
80
- const goalId = required(argv, "--goal-id");
81
- const statusValue = checkpointStatus(required(argv, "--status"));
82
- const evidence = required(argv, "--evidence");
83
- const codexGoalJson = await parseCodexGoalJson(statusValue === "complete" ? required(argv, "--codex-goal-json") : readValue(argv, "--codex-goal-json"));
84
- if (statusValue === "complete" && codexGoalJson === undefined) {
85
- throw new UlwLoopError("Missing --codex-goal-json.", "ULW_LOOP_CODEX_GOAL_JSON_REQUIRED");
86
- }
87
- const qualityGateJson = readValue(argv, "--quality-gate-json");
88
- const args = {
89
- goalId,
90
- status: statusValue,
91
- evidence,
92
- ...(codexGoalJson === undefined ? {} : { codexGoalJson }),
93
- ...(qualityGateJson === undefined ? {} : { qualityGateJson }),
94
- };
95
- const result = await checkpointUlwLoop(repoRoot, args, scope);
96
- if (json)
97
- printJson({ ok: true, ...result, summary: summarizeUlwLoopPlan(result.plan) });
98
- else
99
- process.stdout.write(`ulw-loop checkpoint: ${result.goal.id} -> ${result.goal.status}\n`);
100
- return 0;
101
- }
102
81
  export async function steer(repoRoot, argv, json, scope) {
103
- const proposal = await parseSteeringProposal(argv);
104
- const result = await steerUlwLoop(repoRoot, proposal, scope);
105
- printSteerResult(result, json);
82
+ const proposals = await parseSteeringProposals(argv);
83
+ const single = proposals[0];
84
+ if (single !== undefined && proposals.length === 1 && readValue(argv, "--proposals-json") === undefined) {
85
+ const result = await steerUlwLoop(repoRoot, single, scope);
86
+ printSteerResult(result, json);
87
+ return result.accepted ? 0 : 1;
88
+ }
89
+ const result = await steerUlwLoopBatch(repoRoot, proposals, scope);
90
+ printSteerBatchResult(result, json);
106
91
  return result.accepted ? 0 : 1;
107
92
  }
108
93
  export async function addGoal(repoRoot, argv, json, scope) {
@@ -171,11 +156,6 @@ function required(argv, flag) {
171
156
  return value;
172
157
  throw new UlwLoopError(`Missing ${flag}.`, "ULW_LOOP_ARGUMENT_MISSING", { details: { flag } });
173
158
  }
174
- function checkpointStatus(value) {
175
- if (value === "complete" || value === "failed" || value === "blocked")
176
- return value;
177
- throw new UlwLoopError("Missing or invalid --status; expected complete, failed, or blocked.", "ULW_LOOP_STATUS_INVALID", { details: { status: value } });
178
- }
179
159
  function findGoal(plan, goalId) {
180
160
  const goal = plan.goals.find((candidate) => candidate.id === goalId);
181
161
  if (goal !== undefined)