oh-my-opencode 4.19.0 → 4.19.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 (214) 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 +1 -1
  10. package/dist/agents/gpt-prompt-identity.d.ts +3 -0
  11. package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
  12. package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
  13. package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
  14. package/dist/cli/index.js +148 -94
  15. package/dist/cli-node/index.js +148 -94
  16. package/dist/config/schema/agent-overrides.d.ts +48 -48
  17. package/dist/config/schema/categories.d.ts +6 -6
  18. package/dist/config/schema/codegraph.d.ts +2 -0
  19. package/dist/config/schema/fallback-models.d.ts +5 -5
  20. package/dist/config/schema/oh-my-opencode-config.d.ts +50 -48
  21. package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
  22. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  23. package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
  24. package/dist/index.js +2612 -1473
  25. package/dist/oh-my-opencode.schema.json +11 -0
  26. package/dist/shared/omo-process-sweep.d.ts +18 -0
  27. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  28. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  29. package/dist/skills/ulw-plan/SKILL.md +20 -1
  30. package/dist/testing/create-plugin-module.d.ts +1 -0
  31. package/dist/tui.js +66 -56
  32. package/package.json +13 -13
  33. package/packages/git-bash-mcp/dist/cli.js +54 -8
  34. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +60 -0
  35. package/packages/lsp-core/src/lsp/client.ts +14 -1
  36. package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
  37. package/packages/lsp-core/src/mcp.ts +9 -0
  38. package/packages/lsp-daemon/dist/cli.js +319 -51
  39. package/packages/lsp-daemon/dist/client.js +136 -48
  40. package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
  41. package/packages/lsp-daemon/dist/daemon-client.js +4 -34
  42. package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
  43. package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
  44. package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
  45. package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
  46. package/packages/lsp-daemon/dist/daemon-server.js +5 -1
  47. package/packages/lsp-daemon/dist/index.js +137 -48
  48. package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
  49. package/packages/lsp-daemon/dist/proxy.js +1 -0
  50. package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
  51. package/packages/lsp-daemon/dist/version-reap.js +182 -0
  52. package/packages/lsp-tools-mcp/dist/cli.js +61 -10
  53. package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
  54. package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
  55. package/packages/lsp-tools-mcp/dist/tools.js +6 -1
  56. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  57. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +64 -8
  58. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  59. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  60. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
  61. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +555 -251
  62. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +178 -89
  63. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  64. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
  65. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +3 -1
  66. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
  67. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
  68. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +15 -6
  69. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +6 -2
  70. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
  71. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +148 -0
  72. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
  73. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
  74. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
  75. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
  76. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -1
  77. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
  78. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +41 -0
  79. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +109 -8
  80. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
  81. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +43 -0
  82. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  83. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  84. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  85. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  87. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  88. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  89. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
  90. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  91. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  92. package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
  93. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  94. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
  96. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
  97. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  98. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  99. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  100. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  101. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  102. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  103. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
  104. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
  105. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  106. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  107. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
  108. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  109. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
  110. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  111. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  112. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +20 -1
  113. package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
  114. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
  115. package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
  116. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
  117. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
  118. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
  119. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
  120. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  121. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  122. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
  123. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
  124. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
  125. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
  126. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
  127. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
  128. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
  129. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
  130. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
  131. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
  132. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
  133. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
  134. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
  135. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
  136. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  137. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
  138. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
  139. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
  140. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
  141. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
  142. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
  143. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
  144. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
  145. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
  146. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
  147. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  148. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  149. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
  150. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
  151. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
  152. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
  153. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
  154. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
  155. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
  156. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
  157. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
  158. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
  159. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
  160. package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
  161. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
  162. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
  163. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
  164. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
  165. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
  166. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
  167. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
  168. package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
  169. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
  170. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
  171. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
  172. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
  173. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
  174. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
  175. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
  176. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
  177. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
  178. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  184. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  185. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  186. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  187. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  188. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  189. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
  190. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  191. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
  192. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  193. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
  194. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  195. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  196. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  197. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  198. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  199. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  200. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  201. package/packages/omo-codex/plugin/package-lock.json +41 -41
  202. package/packages/omo-codex/plugin/package.json +1 -1
  203. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +43 -0
  204. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  205. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
  206. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +20 -1
  207. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
  208. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
  209. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
  210. package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
  211. package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
  212. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  213. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  214. package/packages/shared-skills/skills/ulw-plan/SKILL.md +20 -1
@@ -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)