oh-my-opencode 4.8.1 → 4.9.0

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 (507) hide show
  1. package/dist/agents/prometheus/system-prompt.d.ts +1 -1
  2. package/dist/agents/sisyphus/claude-fable-5.d.ts +19 -0
  3. package/dist/agents/sisyphus/claude-opus-4-7.d.ts +3 -1
  4. package/dist/agents/sisyphus/claude-opus-4-8.d.ts +19 -0
  5. package/dist/agents/sisyphus/index.d.ts +4 -0
  6. package/dist/agents/types.d.ts +2 -2
  7. package/dist/cli/doctor/checks/codex.d.ts +1 -0
  8. package/dist/cli/doctor/checks/tools-gh.d.ts +8 -1
  9. package/dist/cli/doctor/index.d.ts +1 -0
  10. package/dist/cli/doctor/types.d.ts +2 -0
  11. package/dist/cli/index.js +1885 -776
  12. package/dist/cli/install-codex/codex-config-permissions.d.ts +1 -1
  13. package/dist/cli/install-codex/codex-config-plugins.d.ts +1 -0
  14. package/dist/cli/install-codex/codex-config-toml.d.ts +1 -0
  15. package/dist/cli/install-codex/codex-installer-bin-dir.d.ts +8 -0
  16. package/dist/cli/install-codex/install-codex.d.ts +1 -8
  17. package/dist/cli/install-codex/lsp-daemon-reaper.d.ts +5 -0
  18. package/dist/cli/sparkshell-condense.d.ts +10 -0
  19. package/dist/cli/sparkshell-parse.d.ts +3 -0
  20. package/dist/cli/sparkshell-session-context.d.ts +20 -0
  21. package/dist/cli/sparkshell-spark.d.ts +23 -0
  22. package/dist/cli/sparkshell.d.ts +8 -1
  23. package/dist/cli-node/index.js +92552 -0
  24. package/dist/config/schema/agent-names.d.ts +2 -0
  25. package/dist/config/schema/hooks.d.ts +0 -2
  26. package/dist/config/schema/keyword-detector.d.ts +0 -6
  27. package/dist/config/schema/oh-my-opencode-config.d.ts +2 -4
  28. package/dist/create-hooks.d.ts +0 -2
  29. package/dist/features/background-agent/parent-wake-dedupe.d.ts +2 -0
  30. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +2 -0
  31. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -0
  32. package/dist/features/background-agent/parent-wake-session-history.d.ts +4 -0
  33. package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -0
  34. package/dist/features/builtin-commands/templates/handoff.d.ts +1 -1
  35. package/dist/features/builtin-skills/index.d.ts +1 -1
  36. package/dist/features/builtin-skills/skills.d.ts +4 -0
  37. package/dist/features/opencode-runtime-skills/source-server.d.ts +16 -1
  38. package/dist/features/opencode-skill-loader/skill-definition-record.d.ts +2 -0
  39. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +2 -0
  40. package/dist/features/team-mode/types.d.ts +1 -0
  41. package/dist/features/tmux-subagent/failed-readiness-cache.d.ts +28 -0
  42. package/dist/features/tmux-subagent/manager.d.ts +1 -9
  43. package/dist/features/tmux-subagent/resolve-server-url.d.ts +3 -0
  44. package/dist/hooks/anthropic-context-window-limit-recovery/executor.d.ts +1 -1
  45. package/dist/hooks/index.d.ts +0 -1
  46. package/dist/hooks/keyword-detector/constants.d.ts +0 -4
  47. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +1 -1
  48. package/dist/index.js +9001 -1795
  49. package/dist/oh-my-opencode.schema.json +2 -4
  50. package/dist/plugin/chat-params.d.ts +1 -8
  51. package/dist/plugin/hooks/create-core-hooks.d.ts +0 -2
  52. package/dist/plugin/hooks/create-session-hooks.d.ts +0 -2
  53. package/dist/plugin/hooks/create-transform-hooks.d.ts +1 -2
  54. package/dist/plugin/messages-transform.d.ts +0 -1
  55. package/dist/shared/model-availability.d.ts +10 -2
  56. package/package.json +25 -18
  57. package/packages/ast-grep-mcp/dist/cli.js +2 -10
  58. package/packages/git-bash-mcp/dist/cli.js +11 -4
  59. package/packages/lsp-daemon/dist/cli.d.ts +2 -0
  60. package/packages/lsp-daemon/dist/cli.js +3711 -0
  61. package/packages/lsp-daemon/dist/daemon-client.d.ts +19 -0
  62. package/packages/lsp-daemon/dist/daemon-client.js +114 -0
  63. package/packages/lsp-daemon/dist/daemon-server.d.ts +12 -0
  64. package/packages/lsp-daemon/dist/daemon-server.js +106 -0
  65. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +21 -0
  66. package/packages/lsp-daemon/dist/ensure-daemon.js +97 -0
  67. package/packages/lsp-daemon/dist/index.d.ts +5 -0
  68. package/packages/lsp-daemon/dist/index.js +3573 -0
  69. package/packages/lsp-daemon/dist/lock.d.ts +7 -0
  70. package/packages/lsp-daemon/dist/lock.js +61 -0
  71. package/packages/lsp-daemon/dist/package.json +6 -0
  72. package/packages/lsp-daemon/dist/paths.d.ts +11 -0
  73. package/packages/lsp-daemon/dist/paths.js +49 -0
  74. package/packages/lsp-daemon/dist/proxy.d.ts +10 -0
  75. package/packages/lsp-daemon/dist/proxy.js +61 -0
  76. package/packages/lsp-daemon/dist/request-routing.d.ts +9 -0
  77. package/packages/lsp-daemon/dist/request-routing.js +44 -0
  78. package/packages/lsp-daemon/dist/run-daemon.d.ts +1 -0
  79. package/packages/lsp-daemon/dist/run-daemon.js +11 -0
  80. package/packages/lsp-daemon/dist/socket-jsonrpc.d.ts +5 -0
  81. package/packages/lsp-daemon/dist/socket-jsonrpc.js +25 -0
  82. package/packages/lsp-daemon/package.json +38 -0
  83. package/packages/lsp-tools-mcp/dist/cli.js +0 -0
  84. package/packages/lsp-tools-mcp/dist/lsp/client-wrapper.js +40 -17
  85. package/packages/lsp-tools-mcp/dist/lsp/client.js +11 -9
  86. package/packages/lsp-tools-mcp/dist/lsp/config-loader.js +5 -5
  87. package/packages/lsp-tools-mcp/dist/lsp/directory-diagnostics.js +5 -3
  88. package/packages/lsp-tools-mcp/dist/lsp/effective-extension.d.ts +1 -0
  89. package/packages/lsp-tools-mcp/dist/lsp/effective-extension.js +8 -0
  90. package/packages/lsp-tools-mcp/dist/lsp/infer-extension.js +3 -2
  91. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.js +1 -0
  92. package/packages/lsp-tools-mcp/dist/lsp/server-definitions.js +12 -0
  93. package/packages/lsp-tools-mcp/dist/lsp/server-install-state.d.ts +12 -0
  94. package/packages/lsp-tools-mcp/dist/lsp/server-install-state.js +51 -0
  95. package/packages/lsp-tools-mcp/dist/lsp/workspace-edit.js +2 -1
  96. package/packages/lsp-tools-mcp/dist/request-context.d.ts +7 -0
  97. package/packages/lsp-tools-mcp/dist/request-context.js +14 -0
  98. package/packages/lsp-tools-mcp/dist/tools.js +44 -1
  99. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +46 -33
  100. package/packages/omo-codex/plugin/.mcp.json +1 -1
  101. package/packages/omo-codex/plugin/components/comment-checker/dist/apply-patch.d.ts +7 -0
  102. package/packages/omo-codex/plugin/components/comment-checker/dist/apply-patch.js +173 -0
  103. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.d.ts +2 -0
  104. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +10 -0
  105. package/packages/omo-codex/plugin/components/comment-checker/dist/codex-hook.d.ts +22 -0
  106. package/packages/omo-codex/plugin/components/comment-checker/dist/codex-hook.js +165 -0
  107. package/packages/omo-codex/plugin/components/comment-checker/dist/core-values.d.ts +1 -0
  108. package/packages/omo-codex/plugin/components/comment-checker/dist/core-values.js +1 -0
  109. package/packages/omo-codex/plugin/components/comment-checker/dist/core.d.ts +5 -0
  110. package/packages/omo-codex/plugin/components/comment-checker/dist/core.js +4 -0
  111. package/packages/omo-codex/plugin/components/comment-checker/dist/hook-input.d.ts +6 -0
  112. package/packages/omo-codex/plugin/components/comment-checker/dist/hook-input.js +10 -0
  113. package/packages/omo-codex/plugin/components/comment-checker/dist/record.d.ts +2 -0
  114. package/packages/omo-codex/plugin/components/comment-checker/dist/record.js +11 -0
  115. package/packages/omo-codex/plugin/components/comment-checker/dist/request-extractor.d.ts +3 -0
  116. package/packages/omo-codex/plugin/components/comment-checker/dist/request-extractor.js +104 -0
  117. package/packages/omo-codex/plugin/components/comment-checker/dist/runner.d.ts +26 -0
  118. package/packages/omo-codex/plugin/components/comment-checker/dist/runner.js +144 -0
  119. package/packages/omo-codex/plugin/components/comment-checker/dist/types.d.ts +43 -0
  120. package/packages/omo-codex/plugin/components/comment-checker/dist/types.js +1 -0
  121. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  122. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  123. package/packages/omo-codex/plugin/components/git-bash/dist/cli.d.ts +2 -0
  124. package/packages/omo-codex/plugin/components/git-bash/dist/cli.js +29 -0
  125. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.d.ts +28 -0
  126. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.js +137 -0
  127. package/packages/omo-codex/plugin/components/git-bash/dist/index.d.ts +1 -0
  128. package/packages/omo-codex/plugin/components/git-bash/dist/index.js +1 -0
  129. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  130. package/packages/omo-codex/plugin/components/git-bash/package.json +5 -2
  131. package/packages/omo-codex/plugin/components/lsp/.mcp.json +1 -1
  132. package/packages/omo-codex/plugin/components/lsp/dist/cli.d.ts +2 -0
  133. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +42 -0
  134. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.d.ts +2 -0
  135. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.js +40 -0
  136. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.d.ts +16 -0
  137. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.js +180 -0
  138. package/packages/omo-codex/plugin/components/lsp/dist/lsp-session-state.d.ts +12 -0
  139. package/packages/omo-codex/plugin/components/lsp/dist/lsp-session-state.js +95 -0
  140. package/packages/omo-codex/plugin/components/lsp/dist/mutated-file-paths.d.ts +6 -0
  141. package/packages/omo-codex/plugin/components/lsp/dist/mutated-file-paths.js +79 -0
  142. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  143. package/packages/omo-codex/plugin/components/lsp/package.json +7 -7
  144. package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-daemon.mjs +68 -0
  145. package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-tools.mjs +45 -22
  146. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  147. package/packages/omo-codex/plugin/components/lsp/src/codex-hook-cli.ts +1 -1
  148. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +6 -2
  149. package/packages/omo-codex/plugin/components/lsp/src/lsp-session-state.ts +4 -0
  150. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +68 -0
  151. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +8 -20
  152. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +69 -96
  153. package/packages/omo-codex/plugin/components/rules/dist/cli.d.ts +2 -0
  154. package/packages/omo-codex/plugin/components/rules/dist/cli.js +118 -0
  155. package/packages/omo-codex/plugin/components/rules/dist/codex-hook-options.d.ts +5 -0
  156. package/packages/omo-codex/plugin/components/rules/dist/codex-hook-options.js +1 -0
  157. package/packages/omo-codex/plugin/components/rules/dist/codex-hook.d.ts +47 -0
  158. package/packages/omo-codex/plugin/components/rules/dist/codex-hook.js +127 -0
  159. package/packages/omo-codex/plugin/components/rules/dist/config.d.ts +2 -0
  160. package/packages/omo-codex/plugin/components/rules/dist/config.js +100 -0
  161. package/packages/omo-codex/plugin/components/rules/dist/context-pressure.d.ts +2 -0
  162. package/packages/omo-codex/plugin/components/rules/dist/context-pressure.js +26 -0
  163. package/packages/omo-codex/plugin/components/rules/dist/debug-log.d.ts +8 -0
  164. package/packages/omo-codex/plugin/components/rules/dist/debug-log.js +36 -0
  165. package/packages/omo-codex/plugin/components/rules/dist/dynamic-target-fingerprints.d.ts +7 -0
  166. package/packages/omo-codex/plugin/components/rules/dist/dynamic-target-fingerprints.js +65 -0
  167. package/packages/omo-codex/plugin/components/rules/dist/event-budget.d.ts +3 -0
  168. package/packages/omo-codex/plugin/components/rules/dist/event-budget.js +14 -0
  169. package/packages/omo-codex/plugin/components/rules/dist/hook-output.d.ts +2 -0
  170. package/packages/omo-codex/plugin/components/rules/dist/hook-output.js +24 -0
  171. package/packages/omo-codex/plugin/components/rules/dist/path-utils.d.ts +4 -0
  172. package/packages/omo-codex/plugin/components/rules/dist/path-utils.js +24 -0
  173. package/packages/omo-codex/plugin/components/rules/dist/persistent-cache.d.ts +13 -0
  174. package/packages/omo-codex/plugin/components/rules/dist/persistent-cache.js +172 -0
  175. package/packages/omo-codex/plugin/components/rules/dist/post-compact-budget.d.ts +6 -0
  176. package/packages/omo-codex/plugin/components/rules/dist/post-compact-budget.js +74 -0
  177. package/packages/omo-codex/plugin/components/rules/dist/post-compact-claim.d.ts +4 -0
  178. package/packages/omo-codex/plugin/components/rules/dist/post-compact-claim.js +6 -0
  179. package/packages/omo-codex/plugin/components/rules/dist/post-compact-directive.d.ts +1 -0
  180. package/packages/omo-codex/plugin/components/rules/dist/post-compact-directive.js +32 -0
  181. package/packages/omo-codex/plugin/components/rules/dist/post-compact-state.d.ts +13 -0
  182. package/packages/omo-codex/plugin/components/rules/dist/post-compact-state.js +29 -0
  183. package/packages/omo-codex/plugin/components/rules/dist/rules/cache.d.ts +9 -0
  184. package/packages/omo-codex/plugin/components/rules/dist/rules/cache.js +51 -0
  185. package/packages/omo-codex/plugin/components/rules/dist/rules/constants.d.ts +70 -0
  186. package/packages/omo-codex/plugin/components/rules/dist/rules/constants.js +101 -0
  187. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-cache.d.ts +5 -0
  188. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-cache.js +60 -0
  189. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-loader.d.ts +6 -0
  190. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-loader.js +61 -0
  191. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-loader.d.ts +7 -0
  192. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-loader.js +60 -0
  193. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-paths.d.ts +11 -0
  194. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-paths.js +75 -0
  195. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-static-loader.d.ts +6 -0
  196. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-static-loader.js +29 -0
  197. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-types.d.ts +44 -0
  198. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-types.js +1 -0
  199. package/packages/omo-codex/plugin/components/rules/dist/rules/engine.d.ts +5 -0
  200. package/packages/omo-codex/plugin/components/rules/dist/rules/engine.js +85 -0
  201. package/packages/omo-codex/plugin/components/rules/dist/rules/errors.d.ts +6 -0
  202. package/packages/omo-codex/plugin/components/rules/dist/rules/errors.js +12 -0
  203. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-cache.d.ts +14 -0
  204. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-cache.js +51 -0
  205. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-paths.d.ts +6 -0
  206. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-paths.js +33 -0
  207. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-sources.d.ts +5 -0
  208. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-sources.js +40 -0
  209. package/packages/omo-codex/plugin/components/rules/dist/rules/finder.d.ts +28 -0
  210. package/packages/omo-codex/plugin/components/rules/dist/rules/finder.js +146 -0
  211. package/packages/omo-codex/plugin/components/rules/dist/rules/formatter.d.ts +7 -0
  212. package/packages/omo-codex/plugin/components/rules/dist/rules/formatter.js +112 -0
  213. package/packages/omo-codex/plugin/components/rules/dist/rules/matcher.d.ts +18 -0
  214. package/packages/omo-codex/plugin/components/rules/dist/rules/matcher.js +93 -0
  215. package/packages/omo-codex/plugin/components/rules/dist/rules/ordering.d.ts +3 -0
  216. package/packages/omo-codex/plugin/components/rules/dist/rules/ordering.js +27 -0
  217. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-frontmatter.d.ts +7 -0
  218. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-frontmatter.js +30 -0
  219. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-yaml.d.ts +2 -0
  220. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-yaml.js +237 -0
  221. package/packages/omo-codex/plugin/components/rules/dist/rules/parser.d.ts +3 -0
  222. package/packages/omo-codex/plugin/components/rules/dist/rules/parser.js +31 -0
  223. package/packages/omo-codex/plugin/components/rules/dist/rules/plugin-root.d.ts +1 -0
  224. package/packages/omo-codex/plugin/components/rules/dist/rules/plugin-root.js +48 -0
  225. package/packages/omo-codex/plugin/components/rules/dist/rules/project-root.d.ts +1 -0
  226. package/packages/omo-codex/plugin/components/rules/dist/rules/project-root.js +23 -0
  227. package/packages/omo-codex/plugin/components/rules/dist/rules/scanner.d.ts +14 -0
  228. package/packages/omo-codex/plugin/components/rules/dist/rules/scanner.js +111 -0
  229. package/packages/omo-codex/plugin/components/rules/dist/rules/sources.d.ts +3 -0
  230. package/packages/omo-codex/plugin/components/rules/dist/rules/sources.js +9 -0
  231. package/packages/omo-codex/plugin/components/rules/dist/rules/truncator.d.ts +18 -0
  232. package/packages/omo-codex/plugin/components/rules/dist/rules/truncator.js +59 -0
  233. package/packages/omo-codex/plugin/components/rules/dist/rules/types.d.ts +126 -0
  234. package/packages/omo-codex/plugin/components/rules/dist/rules/types.js +8 -0
  235. package/packages/omo-codex/plugin/components/rules/dist/rules-engine-factory.d.ts +6 -0
  236. package/packages/omo-codex/plugin/components/rules/dist/rules-engine-factory.js +20 -0
  237. package/packages/omo-codex/plugin/components/rules/dist/session-state-lock.d.ts +3 -0
  238. package/packages/omo-codex/plugin/components/rules/dist/session-state-lock.js +41 -0
  239. package/packages/omo-codex/plugin/components/rules/dist/sparkshell-awareness.d.ts +10 -0
  240. package/packages/omo-codex/plugin/components/rules/dist/sparkshell-awareness.js +90 -0
  241. package/packages/omo-codex/plugin/components/rules/dist/static-injection.d.ts +3 -0
  242. package/packages/omo-codex/plugin/components/rules/dist/static-injection.js +128 -0
  243. package/packages/omo-codex/plugin/components/rules/dist/tool-paths.d.ts +6 -0
  244. package/packages/omo-codex/plugin/components/rules/dist/tool-paths.js +168 -0
  245. package/packages/omo-codex/plugin/components/rules/dist/transcript-rule-filter.d.ts +4 -0
  246. package/packages/omo-codex/plugin/components/rules/dist/transcript-rule-filter.js +49 -0
  247. package/packages/omo-codex/plugin/components/rules/dist/transcript-search.d.ts +4 -0
  248. package/packages/omo-codex/plugin/components/rules/dist/transcript-search.js +91 -0
  249. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  250. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  251. package/packages/omo-codex/plugin/components/rules/src/codex-hook.ts +4 -2
  252. package/packages/omo-codex/plugin/components/rules/src/config.ts +13 -0
  253. package/packages/omo-codex/plugin/components/rules/src/event-budget.ts +17 -0
  254. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +4 -1
  255. package/packages/omo-codex/plugin/components/rules/src/post-compact-directive.ts +39 -0
  256. package/packages/omo-codex/plugin/components/rules/src/rules/constants.ts +16 -0
  257. package/packages/omo-codex/plugin/components/rules/src/rules/engine.ts +8 -0
  258. package/packages/omo-codex/plugin/components/rules/src/rules/types.ts +4 -0
  259. package/packages/omo-codex/plugin/components/rules/src/sparkshell-awareness.ts +53 -4
  260. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +127 -7
  261. package/packages/omo-codex/plugin/components/rules/src/transcript-rule-filter.ts +9 -1
  262. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +4 -2
  263. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +7 -2
  264. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +9 -9
  265. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +10 -4
  266. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +241 -0
  267. package/packages/omo-codex/plugin/components/rules/test/event-budget.test.ts +168 -0
  268. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +4 -0
  269. package/packages/omo-codex/plugin/components/rules/test/sparkshell-awareness.test.ts +86 -3
  270. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +15 -15
  271. package/packages/omo-codex/plugin/components/start-work-continuation/dist/boulder-reader.d.ts +16 -0
  272. package/packages/omo-codex/plugin/components/start-work-continuation/dist/boulder-reader.js +146 -0
  273. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.d.ts +2 -0
  274. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +49 -0
  275. package/packages/omo-codex/plugin/components/start-work-continuation/dist/codex-hook.d.ts +2 -0
  276. package/packages/omo-codex/plugin/components/start-work-continuation/dist/codex-hook.js +80 -0
  277. package/packages/omo-codex/plugin/components/start-work-continuation/dist/directive.d.ts +1 -0
  278. package/packages/omo-codex/plugin/components/start-work-continuation/dist/directive.js +2 -0
  279. package/packages/omo-codex/plugin/components/start-work-continuation/dist/index.d.ts +5 -0
  280. package/packages/omo-codex/plugin/components/start-work-continuation/dist/index.js +3 -0
  281. package/packages/omo-codex/plugin/components/start-work-continuation/dist/types.d.ts +20 -0
  282. package/packages/omo-codex/plugin/components/start-work-continuation/dist/types.js +1 -0
  283. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  284. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  285. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +24 -2
  286. package/packages/omo-codex/plugin/components/telemetry/dist/atomic-write.d.ts +1 -0
  287. package/packages/omo-codex/plugin/components/telemetry/dist/atomic-write.js +18 -0
  288. package/packages/omo-codex/plugin/components/telemetry/dist/cli.d.ts +2 -0
  289. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +62 -0
  290. package/packages/omo-codex/plugin/components/telemetry/dist/codex-hook.d.ts +15 -0
  291. package/packages/omo-codex/plugin/components/telemetry/dist/codex-hook.js +42 -0
  292. package/packages/omo-codex/plugin/components/telemetry/dist/data-path.d.ts +10 -0
  293. package/packages/omo-codex/plugin/components/telemetry/dist/data-path.js +35 -0
  294. package/packages/omo-codex/plugin/components/telemetry/dist/diagnostics.d.ts +12 -0
  295. package/packages/omo-codex/plugin/components/telemetry/dist/diagnostics.js +108 -0
  296. package/packages/omo-codex/plugin/components/telemetry/dist/env-flags.d.ts +4 -0
  297. package/packages/omo-codex/plugin/components/telemetry/dist/env-flags.js +31 -0
  298. package/packages/omo-codex/plugin/components/telemetry/dist/posthog-activity-state.d.ts +8 -0
  299. package/packages/omo-codex/plugin/components/telemetry/dist/posthog-activity-state.js +68 -0
  300. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.d.ts +21 -0
  301. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +133 -0
  302. package/packages/omo-codex/plugin/components/telemetry/dist/product-identity.d.ts +8 -0
  303. package/packages/omo-codex/plugin/components/telemetry/dist/product-identity.js +29 -0
  304. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  305. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  306. package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +5 -13
  307. package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +61 -185
  308. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  309. package/packages/omo-codex/plugin/components/ultrawork/directive.md +122 -117
  310. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.d.ts +2 -0
  311. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +48 -0
  312. package/packages/omo-codex/plugin/components/ultrawork/dist/codex-hook.d.ts +7 -0
  313. package/packages/omo-codex/plugin/components/ultrawork/dist/codex-hook.js +122 -0
  314. package/packages/omo-codex/plugin/components/ultrawork/dist/directive.d.ts +1 -0
  315. package/packages/omo-codex/plugin/components/ultrawork/dist/directive.js +2 -0
  316. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  317. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  318. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +20 -11
  319. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +17 -11
  320. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +2 -5
  321. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -71
  322. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.d.ts +16 -0
  323. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +200 -0
  324. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.d.ts +17 -0
  325. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +97 -0
  326. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.d.ts +4 -0
  327. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +183 -0
  328. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +6 -0
  329. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +55 -0
  330. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +12 -0
  331. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +145 -0
  332. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.d.ts +2 -0
  333. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +39 -0
  334. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +13 -0
  335. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +100 -0
  336. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +26 -0
  337. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +97 -0
  338. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.d.ts +28 -0
  339. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +145 -0
  340. package/packages/omo-codex/plugin/components/ulw-loop/dist/command-types.d.ts +34 -0
  341. package/packages/omo-codex/plugin/components/ulw-loop/dist/command-types.js +1 -0
  342. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +16 -0
  343. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +41 -0
  344. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +95 -0
  345. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.js +1 -0
  346. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.d.ts +31 -0
  347. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.js +119 -0
  348. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +12 -0
  349. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +69 -0
  350. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +16 -0
  351. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +59 -0
  352. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +48 -0
  353. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +119 -0
  354. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +8 -0
  355. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +89 -0
  356. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +6 -0
  357. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +123 -0
  358. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.d.ts +16 -0
  359. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +70 -0
  360. package/packages/omo-codex/plugin/components/ulw-loop/dist/runtime.d.ts +10 -0
  361. package/packages/omo-codex/plugin/components/ulw-loop/dist/runtime.js +13 -0
  362. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +63 -0
  363. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.js +1 -0
  364. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.d.ts +6 -0
  365. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +292 -0
  366. package/packages/omo-codex/plugin/components/ulw-loop/dist/types.d.ts +5 -0
  367. package/packages/omo-codex/plugin/components/ulw-loop/dist/types.js +5 -0
  368. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  369. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  370. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +14 -14
  371. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +24 -25
  372. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +17 -3
  373. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +2 -1
  374. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -1
  375. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +95 -0
  376. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +0 -96
  377. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +23 -0
  378. package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +46 -0
  379. package/packages/omo-codex/plugin/hooks/hooks.json +16 -16
  380. package/packages/omo-codex/plugin/package-lock.json +10 -9
  381. package/packages/omo-codex/plugin/package.json +27 -26
  382. package/packages/omo-codex/plugin/scripts/auto-update.mjs +64 -15
  383. package/packages/omo-codex/plugin/scripts/build-bundled-mcp-runtimes.mjs +16 -0
  384. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +82 -18
  385. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +2 -2
  386. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +23 -11
  387. package/packages/omo-codex/plugin/scripts/sync-version.mjs +94 -0
  388. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +9 -9
  389. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +16 -1
  390. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +93 -0
  391. package/packages/omo-codex/plugin/skills/lcx-doctor/agents/openai.yaml +11 -0
  392. package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +17 -13
  393. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +139 -0
  394. package/packages/omo-codex/plugin/skills/lsp-setup/references/bash/README.md +60 -0
  395. package/packages/omo-codex/plugin/skills/lsp-setup/references/c-cpp/README.md +61 -0
  396. package/packages/omo-codex/plugin/skills/lsp-setup/references/csharp/README.md +71 -0
  397. package/packages/omo-codex/plugin/skills/lsp-setup/references/dart/README.md +48 -0
  398. package/packages/omo-codex/plugin/skills/lsp-setup/references/elixir/README.md +51 -0
  399. package/packages/omo-codex/plugin/skills/lsp-setup/references/go/README.md +57 -0
  400. package/packages/omo-codex/plugin/skills/lsp-setup/references/haskell/README.md +57 -0
  401. package/packages/omo-codex/plugin/skills/lsp-setup/references/java/README.md +57 -0
  402. package/packages/omo-codex/plugin/skills/lsp-setup/references/julia/README.md +60 -0
  403. package/packages/omo-codex/plugin/skills/lsp-setup/references/kotlin/README.md +59 -0
  404. package/packages/omo-codex/plugin/skills/lsp-setup/references/lua/README.md +66 -0
  405. package/packages/omo-codex/plugin/skills/lsp-setup/references/php/README.md +62 -0
  406. package/packages/omo-codex/plugin/skills/lsp-setup/references/python/README.md +71 -0
  407. package/packages/omo-codex/plugin/skills/lsp-setup/references/ruby/README.md +53 -0
  408. package/packages/omo-codex/plugin/skills/lsp-setup/references/rust/README.md +59 -0
  409. package/packages/omo-codex/plugin/skills/lsp-setup/references/swift/README.md +51 -0
  410. package/packages/omo-codex/plugin/skills/lsp-setup/references/terraform/README.md +62 -0
  411. package/packages/omo-codex/plugin/skills/lsp-setup/references/typescript/README.md +77 -0
  412. package/packages/omo-codex/plugin/skills/lsp-setup/references/yaml/README.md +70 -0
  413. package/packages/omo-codex/plugin/skills/lsp-setup/references/zig/README.md +49 -0
  414. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/detect-lsp.ts +210 -0
  415. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/lsp-server-table.ts +177 -0
  416. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/tsconfig.json +17 -0
  417. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/verify-lsp.ts +147 -0
  418. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +9 -9
  419. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +10 -10
  420. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +20 -22
  421. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +38 -61
  422. package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +135 -677
  423. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +14 -14
  424. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +24 -25
  425. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +20 -11
  426. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +17 -11
  427. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +9 -9
  428. package/packages/omo-codex/plugin/test/aggregate-build.test.mjs +2 -1
  429. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +1 -1
  430. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +5 -5
  431. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +6 -6
  432. package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +194 -0
  433. package/packages/omo-codex/plugin/test/auto-update.test.mjs +17 -0
  434. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +15 -44
  435. package/packages/omo-codex/plugin/test/lsp-prebuild-layouts.test.mjs +140 -0
  436. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +189 -7
  437. package/packages/omo-codex/plugin/test/start-work-skill.test.mjs +9 -31
  438. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +68 -4
  439. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +119 -0
  440. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +11 -112
  441. package/packages/omo-codex/plugin/test/sync-version.test.mjs +68 -0
  442. package/packages/omo-codex/plugin/test/ultraresearch-skill-contract.test.mjs +126 -0
  443. package/packages/omo-codex/plugin/test/ulw-plan-skill.test.mjs +2 -2
  444. package/packages/omo-codex/scripts/install/bin-dir.mjs +20 -0
  445. package/packages/omo-codex/scripts/install/bin-links.mjs +43 -6
  446. package/packages/omo-codex/scripts/install/cache.mjs +4 -0
  447. package/packages/omo-codex/scripts/install/config.mjs +4 -4
  448. package/packages/omo-codex/scripts/install/delegated-command.mjs +5 -1
  449. package/packages/omo-codex/scripts/install/git-bash-mcp-env.mjs +28 -0
  450. package/packages/omo-codex/scripts/install/git-bash.mjs +12 -4
  451. package/packages/omo-codex/scripts/install/git-bash.test.mjs +39 -4
  452. package/packages/omo-codex/scripts/install/hook-targets.mjs +46 -0
  453. package/packages/omo-codex/scripts/install/multi-agent-v2-config.mjs +12 -2
  454. package/packages/omo-codex/scripts/install/process.mjs +1 -0
  455. package/packages/omo-codex/scripts/install-bin-links.test.mjs +131 -3
  456. package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +91 -0
  457. package/packages/omo-codex/scripts/install-config.test.mjs +50 -44
  458. package/packages/omo-codex/scripts/install-delegated-command.test.mjs +78 -0
  459. package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +93 -0
  460. package/packages/omo-codex/scripts/install-hook-targets.test.mjs +100 -0
  461. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +3 -1
  462. package/packages/omo-codex/scripts/install-local.mjs +7 -18
  463. package/packages/omo-codex/scripts/install-local.test.mjs +34 -1
  464. package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +16 -1
  465. package/packages/shared-skills/skills/lcx-doctor/SKILL.md +93 -0
  466. package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +11 -0
  467. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +17 -13
  468. package/packages/shared-skills/skills/lsp-setup/SKILL.md +139 -0
  469. package/packages/shared-skills/skills/lsp-setup/references/bash/README.md +60 -0
  470. package/packages/shared-skills/skills/lsp-setup/references/c-cpp/README.md +61 -0
  471. package/packages/shared-skills/skills/lsp-setup/references/csharp/README.md +71 -0
  472. package/packages/shared-skills/skills/lsp-setup/references/dart/README.md +48 -0
  473. package/packages/shared-skills/skills/lsp-setup/references/elixir/README.md +51 -0
  474. package/packages/shared-skills/skills/lsp-setup/references/go/README.md +57 -0
  475. package/packages/shared-skills/skills/lsp-setup/references/haskell/README.md +57 -0
  476. package/packages/shared-skills/skills/lsp-setup/references/java/README.md +57 -0
  477. package/packages/shared-skills/skills/lsp-setup/references/julia/README.md +60 -0
  478. package/packages/shared-skills/skills/lsp-setup/references/kotlin/README.md +59 -0
  479. package/packages/shared-skills/skills/lsp-setup/references/lua/README.md +66 -0
  480. package/packages/shared-skills/skills/lsp-setup/references/php/README.md +62 -0
  481. package/packages/shared-skills/skills/lsp-setup/references/python/README.md +71 -0
  482. package/packages/shared-skills/skills/lsp-setup/references/ruby/README.md +53 -0
  483. package/packages/shared-skills/skills/lsp-setup/references/rust/README.md +59 -0
  484. package/packages/shared-skills/skills/lsp-setup/references/swift/README.md +51 -0
  485. package/packages/shared-skills/skills/lsp-setup/references/terraform/README.md +62 -0
  486. package/packages/shared-skills/skills/lsp-setup/references/typescript/README.md +77 -0
  487. package/packages/shared-skills/skills/lsp-setup/references/yaml/README.md +70 -0
  488. package/packages/shared-skills/skills/lsp-setup/references/zig/README.md +49 -0
  489. package/packages/shared-skills/skills/lsp-setup/scripts/detect-lsp.ts +210 -0
  490. package/packages/shared-skills/skills/lsp-setup/scripts/lsp-server-table.ts +177 -0
  491. package/packages/shared-skills/skills/lsp-setup/scripts/tsconfig.json +17 -0
  492. package/packages/shared-skills/skills/lsp-setup/scripts/verify-lsp.ts +147 -0
  493. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
  494. package/packages/shared-skills/skills/review-work/SKILL.md +10 -14
  495. package/packages/shared-skills/skills/start-work/SKILL.md +30 -59
  496. package/packages/shared-skills/skills/ultraresearch/SKILL.md +126 -667
  497. package/dist/hooks/anthropic-effort/hook.d.ts +0 -26
  498. package/dist/hooks/anthropic-effort/index.d.ts +0 -1
  499. package/dist/hooks/keyword-detector/analyze/default.d.ts +0 -12
  500. package/dist/hooks/keyword-detector/analyze/index.d.ts +0 -1
  501. package/dist/hooks/keyword-detector/search/default.d.ts +0 -12
  502. package/dist/hooks/keyword-detector/search/index.d.ts +0 -1
  503. package/dist/hooks/thinking-block-validator/hook.d.ts +0 -12
  504. package/dist/hooks/thinking-block-validator/index.d.ts +0 -1
  505. package/packages/omo-codex/plugin/components/ultrawork/test/directive-contract.test.ts +0 -18
  506. package/packages/omo-codex/plugin/test/global-review-debug-gate.test.mjs +0 -29
  507. package/packages/omo-codex/plugin/test/subagent-guidance.test.mjs +0 -151
@@ -14,7 +14,7 @@ This skill is intentionally compact. The full planning workflow lives in `refere
14
14
  ## Required First Steps
15
15
 
16
16
  1. Open `references/full-workflow.md`.
17
- 2. Read **Phase 0 - Classify**, **Phase 1 - Ground**, and the **Approval gate** before you ask the user anything or draft a plan.
17
+ 2. Read **Phase 0 - Classify**, **Phase 1 - Ground**, **Phase 2 - Interview**, and the **Approval gate** before you ask the user anything or draft a plan.
18
18
  3. Internalize the loop: explore exhaustively, surface the genuine unknowns, ask, then wait for approval before planning.
19
19
 
20
20
  ## The Gate (non-negotiable behavior)
@@ -24,6 +24,15 @@ This skill is intentionally compact. The full planning workflow lives in `refere
24
24
  - **Wait for the user's explicit okay before generating the plan.** Never auto-transition from interview to plan generation. No plan file, no Metis gap-analysis, no execution until the user approves the approach.
25
25
  - **Planner scope only.** Write only `.omo/plans/<slug>.md` and `.omo/drafts/*.md`. Never edit source. If asked to "just do it", decline: you plan; a worker executes.
26
26
 
27
+ ## Interview Discipline (how to ask)
28
+
29
+ Exploration answers facts; the user decides preferences, tradeoffs, and safety. Bring those decisions to the user EARLY and well-formed:
30
+
31
+ - Every question must materially change the plan, confirm a load-bearing assumption, or choose between real tradeoffs. If a read-only search could answer it, asking is a failure.
32
+ - Ask 1-3 narrow questions per turn, each with 2-4 concrete options and your recommended default first, grounded in a file path or finding you cite. A skipped question resolves to that default, recorded in the draft as an assumption.
33
+ - Always ask test strategy (TDD / tests-after / none); agent-executed QA scenarios are included regardless.
34
+ - Record every answer and decision in `.omo/drafts/<slug>.md` immediately; run the Phase 2 clearance check after every turn; never end a turn passively — end with the question or the explicit next step.
35
+
27
36
  ## Dynamic Adversarial Planning
28
37
 
29
38
  For architecture work, no-plan `$start-work` bootstrap, or requests that cite Discord / external repositories, use **dynamic adversarial workflow phases** before writing the final plan:
@@ -44,22 +53,22 @@ Subagent outputs are not success or approval without independent verification.
44
53
 
45
54
  You explore a LOT - fan out parallel read-only research before interviewing - but delegate with Codex discipline:
46
55
 
47
- - Every `spawn_agent` message starts with `TASK:`, then names `DELIVERABLE`, `SCOPE`, and `VERIFY`. Put role and specialty instructions inside `message`; the Codex tool schema only accepts `task_name`, `message`, and `fork_turns`. Prefer `fork_turns: "none"` unless full history is truly required.
48
- - Plan and reviewer agents may run for a long time; spawn them in the background, keep doing independent root work, and poll with short wait_agent cycles. Never use a single long blocking wait for them.
56
+ - Every `multi_agent_v1.spawn_agent` message starts with `TASK:`, then names `DELIVERABLE`, `SCOPE`, and `VERIFY`. Put role and specialty instructions inside `message`. Use `fork_context: false` unless full history is truly required.
57
+ - Plan and reviewer agents may run for a long time; spawn them in the background, keep doing independent root work, and poll with short `multi_agent_v1.wait_agent` cycles. Never use a single long blocking wait for them.
49
58
  - For work likely to exceed one wait cycle, require the child to send `WORKING: <task> - <current phase>` before long reading, testing, or review passes, and `BLOCKED: <reason>` only when it cannot progress.
50
59
  - While any child is active, keep yourself visibly alive with active subagent count, agent names, latest `WORKING:` phase, and whether you are waiting for mailbox updates.
51
- - Track spawned agent names locally. Use `wait_agent` for mailbox signals, not proof of completion. A timeout only means no new mailbox update arrived; after a timeout, run a single `list_agents` check for the named child when you need reassurance. If it is running or its latest message is `WORKING:`, treat it as alive.
52
- - Do not use `list_agents` as a polling loop or status feed; it can replay large payloads. Fallback only when the child is completed without the deliverable, ack-only after followup, explicitly `BLOCKED:`, or no longer running. Then record the lane inconclusive and respawn a smaller `fork_turns: "none"` task with the missing deliverable.
60
+ - Track spawned agent names locally. Use `multi_agent_v1.wait_agent` for mailbox signals, not proof of completion. A timeout only means no new mailbox update arrived. Treat a running child as alive.
61
+ - Fallback only when the child is completed without the deliverable, ack-only after followup, explicitly `BLOCKED:`, or no longer running. Then record the lane inconclusive and respawn a smaller `fork_context: false` task with the missing deliverable.
53
62
 
54
63
  ## Codex Tool Mapping
55
64
 
56
65
  | Planning intent | Codex tool |
57
66
  | --- | --- |
58
- | Internal codebase research | `spawn_agent({"task_name":"...","message":"TASK: act as an explorer. ...","fork_turns":"none"})` |
59
- | External docs / library research | `spawn_agent({"task_name":"...","message":"TASK: act as a librarian. ...","fork_turns":"none"})` |
60
- | Pre-plan gap analysis (after approval) | `spawn_agent({"task_name":"...","message":"TASK: act as a Metis gap-analysis reviewer. ...","fork_turns":"none"})` |
61
- | High-accuracy plan review (optional) | `spawn_agent({"task_name":"...","message":"TASK: act as a Momus plan reviewer. ...","fork_turns":"none"})` |
62
- | Wait for a research result | `wait_agent(...)` |
63
- | Release a finished subagent | `close_agent(...)` |
67
+ | Internal codebase research | `multi_agent_v1.spawn_agent({"message":"TASK: act as an explorer. ...","fork_context":false})` |
68
+ | External docs / library research | `multi_agent_v1.spawn_agent({"message":"TASK: act as a librarian. ...","fork_context":false})` |
69
+ | Pre-plan gap analysis (after approval) | `multi_agent_v1.spawn_agent({"message":"TASK: act as a Metis gap-analysis reviewer. ...","fork_context":false})` |
70
+ | High-accuracy plan review (optional) | `multi_agent_v1.spawn_agent({"message":"TASK: act as a Momus plan reviewer. ...","fork_context":false})` |
71
+ | Wait for a research result | `multi_agent_v1.wait_agent(...)` |
72
+ | Release a finished subagent | `multi_agent_v1.close_agent(...)` |
64
73
 
65
74
  Name any skills the child needs directly inside its `message`. Your plan goes to `.omo/plans/<slug>.md`; never split one request into multiple plans.
@@ -8,7 +8,7 @@ metadata:
8
8
  ## Role
9
9
  Prometheus, strategic planning consultant inside Codex. You turn a vague or large request into ONE decision-complete work plan a downstream worker can execute with zero further interview. You are a PLANNER, not an implementer: read, search, run read-only analysis, and write only `.omo/plans/<slug>.md` and `.omo/drafts/*.md`. Never edit product code; if asked to "just do it", decline and offer to plan.
10
10
 
11
- GPT-5.x style: outcome-first, evidence-bound, atomic decisions. Explore a lot. Ask little. Never plan blind, and never plan before the user approves.
11
+ GPT-5.x style: outcome-first, evidence-bound, atomic decisions. Explore a lot; ask few, decisive questions. Never plan blind, and never plan before the user approves.
12
12
 
13
13
  ## North star
14
14
  A plan is **decision-complete** when the implementer needs ZERO judgment calls: every decision made, every ambiguity resolved, every pattern referenced with a concrete path.
@@ -22,8 +22,8 @@ Size your interview depth before diving in:
22
22
  ## Phase 1 - Ground (explore exhaustively BEFORE asking)
23
23
  Eliminate unknowns by discovering facts, not by asking the user. Before your first question, fan out parallel read-only research and keep working while it runs.
24
24
 
25
- - `spawn_agent({"task_name":"...","message":"TASK: act as an explorer. ...","fork_turns":"none"})` per internal aspect: existing patterns, conventions, similar implementations, naming/registration, test infrastructure. One agent per aspect.
26
- - `spawn_agent({"task_name":"...","message":"TASK: act as a librarian. ...","fork_turns":"none"})` per external aspect: official docs, API contracts, recommended patterns, pitfalls.
25
+ - `multi_agent_v1.spawn_agent({"message":"TASK: act as an explorer. ...","fork_context":false})` per internal aspect: existing patterns, conventions, similar implementations, naming/registration, test infrastructure. One agent per aspect.
26
+ - `multi_agent_v1.spawn_agent({"message":"TASK: act as a librarian. ...","fork_context":false})` per external aspect: official docs, API contracts, recommended patterns, pitfalls.
27
27
  - While they run, use direct read-only tools (`read`, `rg`, `ast_grep_search`, `lsp_*`) for immediate context. Do not idle.
28
28
 
29
29
  ### Dynamic workflow for architecture and bootstrap planning
@@ -44,11 +44,17 @@ Two kinds of unknowns:
44
44
  Exhaust exploration first. "I could not find it" is true only after you actually looked.
45
45
 
46
46
  ## Phase 2 - Interview (ask only what exploration cannot resolve)
47
- Record everything to `.omo/drafts/<slug>.md` as you go: confirmed requirements, decisions + rationale, research findings, open questions, scope IN / OUT. The draft is your durable memory across turns.
47
+ Record everything to `.omo/drafts/<slug>.md` as you go: confirmed requirements (the user's exact words), decisions + rationale, research findings, open questions, scope IN / OUT. Update it after EVERY meaningful exchange - long interviews outlive your context, and plan generation reads the draft, not your memory.
48
48
 
49
- Ask focused questions ONLY for genuine unknowns surfaced by Phase 1: goal + definition of done, scope boundaries, preference tradeoffs, test strategy (TDD / tests-after / none - agent-executed QA is always included), and hard constraints. Every question must materially change the plan. Never ask what a read-only search would answer.
49
+ Interview focus, informed by Phase 1 findings: goal + definition of done, scope boundaries (IN and explicitly OUT), technical approach ("I found pattern X at `src/path` - follow it?"), test strategy (TDD / tests-after / none - agent-executed QA is always included), and hard constraints.
50
50
 
51
- Keep each turn conversational: 3-6 sentences plus 1-3 questions. Never end a turn passively; end with the specific question or the explicit next step.
51
+ Question rules:
52
+ - Every question must materially change the plan, confirm a load-bearing assumption, or choose between real tradeoffs. Never ask what a read-only search would answer.
53
+ - Ask 1-3 narrow questions per turn, each with 2-4 concrete options and your recommended default first with a one-line rationale. A question the user skips resolves to the recommended default, recorded in the draft as an assumption.
54
+ - Ground each question in evidence: cite the file path or research finding that raised it, so the user decides from facts rather than guesses.
55
+ - Keep each turn conversational: 3-6 sentences plus the questions. Never end a turn passively; end with the specific question or the explicit next step.
56
+
57
+ Clearance check - run after EVERY interview turn: core objective defined? scope IN/OUT explicit? technical approach decided? test strategy confirmed? no critical ambiguity or blocking question left? Any NO -> that unmet item is your next question. All YES -> present the approval brief (see Approval gate) and stop; never jump from interview into writing the plan.
52
58
 
53
59
  ## Approval gate (DO NOT SKIP)
54
60
  When exploration is exhausted and the genuine unknowns are answered, do NOT auto-start planning. Present a short brief instead:
@@ -61,7 +67,7 @@ Then **wait for the user's explicit okay** before generating the plan. No Metis,
61
67
  Narrow `$start-work` bootstrap exception: if `$start-work` invoked this skill because there was no active Boulder work and no selectable plan, the user's `start work` request counts as approval to generate the plan and begin execution. Preserve the normal gate for ordinary `ulw-plan`; ask one focused question only if the objective is missing, destructive, or has a safety/product ambiguity that exploration cannot resolve.
62
68
 
63
69
  ## Phase 3 - Generate the plan (only after approval)
64
- 1. **Metis gap analysis (mandatory):** `spawn_agent({"task_name":"metis_gap_analysis","message":"TASK: act as a Metis gap-analysis reviewer and review this planning session for gaps. DELIVERABLE: contradictions, missing constraints, scope-creep risks, unvalidated assumptions, missing acceptance criteria. VERIFY: each gap names a concrete fix.","fork_turns":"none"})`. Fold the findings in silently.
70
+ 1. **Metis gap analysis (mandatory):** `multi_agent_v1.spawn_agent({"message":"TASK: act as a Metis gap-analysis reviewer and review this planning session for gaps. DELIVERABLE: contradictions, missing constraints, scope-creep risks, unvalidated assumptions, missing acceptance criteria. VERIFY: each gap names a concrete fix.","fork_context":false})`. Fold the findings in silently.
65
71
  2. Write ONE plan to `.omo/plans/<slug>.md` using the template below. No "Phase 1 plan / Phase 2 plan" splits; 50+ todos is fine. Build it incrementally - skeleton first, then append todo batches - so output limits never truncate it; re-read the file to confirm completeness.
66
72
  3. **Self-review:** every todo has references + agent-executable acceptance criteria + QA scenarios; no business-logic assumption without evidence; zero acceptance criteria require a human.
67
73
 
@@ -116,14 +122,14 @@ Critical path: ...
116
122
  ```
117
123
 
118
124
  ## Phase 4 - High-accuracy review (optional)
119
- If the user wants maximum rigor, call `spawn_agent({"task_name":"momus_plan_review","message":"TASK: act as a Momus plan reviewer. DELIVERABLE: review .omo/plans/<slug>.md only. VERIFY: cite every required fix or approve.","fork_turns":"none"})` and pass ONLY the plan path in `message`. Fix every cited issue and resubmit until it approves.
125
+ If the user wants maximum rigor, call `multi_agent_v1.spawn_agent({"message":"TASK: act as a Momus plan reviewer. DELIVERABLE: review .omo/plans/<slug>.md only. VERIFY: cite every required fix or approve.","fork_context":false})` and pass ONLY the plan path in `message`. Fix every cited issue and resubmit until it approves.
120
126
 
121
127
  ## Delegation discipline (Codex)
122
- - Every `spawn_agent` message starts with `TASK:`, then `DELIVERABLE`, `SCOPE`, `VERIFY`. Put role and specialty instructions inside `message`; the Codex tool schema only accepts `task_name`, `message`, and `fork_turns`. Prefer `fork_turns: "none"`.
123
- - Plan and reviewer agents may run for a long time; spawn them in the background, keep doing independent root work, and poll with short wait_agent cycles. Never use a single long blocking wait for them.
128
+ - Every `multi_agent_v1.spawn_agent` message starts with `TASK:`, then `DELIVERABLE`, `SCOPE`, `VERIFY`. Put role and specialty instructions inside `message`. Use `fork_context: false` unless full history is truly required.
129
+ - Plan and reviewer agents may run for a long time; spawn them in the background, keep doing independent root work, and poll with short `multi_agent_v1.wait_agent` cycles. Never use a single long blocking wait for them.
124
130
  - For work likely to exceed one wait cycle, require the child to send `WORKING: <task> - <current phase>` before long passes and `BLOCKED: <reason>` only when progress stops.
125
131
  - Keep yourself visibly alive while children run: active subagent count, agent names, latest `WORKING:` phase, and whether you are waiting on mailbox updates.
126
- - Use `wait_agent` for mailbox signals, not proof. A timeout only means no new mailbox update arrived; after a timeout, run a single `list_agents` check for the named child when you need reassurance. If it is running or its latest message is `WORKING:`, treat it as alive. Do not use `list_agents` as a polling loop. Fallback only when the child is completed without the deliverable, ack-only after followup, explicitly `BLOCKED:`, or no longer running; then mark the lane inconclusive and respawn a smaller `fork_turns: "none"` task with the missing deliverable. `close_agent` after integrating each result.
132
+ - Use `multi_agent_v1.wait_agent` for mailbox signals, not proof. A timeout only means no new mailbox update arrived. Treat a running child as alive. Fallback only when the child is completed without the deliverable, ack-only after followup, explicitly `BLOCKED:`, or no longer running; then mark the lane inconclusive and respawn a smaller `fork_context: false` task with the missing deliverable. `multi_agent_v1.close_agent` after integrating each result.
127
133
 
128
134
  ## Stop rules
129
135
  - Plan file exists, template filled, every todo has references + acceptance + QA + commit, dependency matrix consistent: DONE.
@@ -229,9 +229,7 @@ describe("codex ultrawork hook", () => {
229
229
 
230
230
  // then
231
231
  const directive = parsed.hookSpecificOutput.additionalContext;
232
- expect(directive).toMatch(/list_agents/);
233
- expect(directive).toMatch(/polling loop/);
234
- expect(directive).toMatch(/replay large payloads/);
232
+ expect(directive).toMatch(/multi_agent_v1\.wait_agent/);
235
233
  expect(directive).toMatch(/Track spawned agent names locally/);
236
234
  expect(directive).toMatch(/wait_agent[\s\S]*mailbox/);
237
235
  expect(directive).toMatch(/WORKING:/);
@@ -253,13 +251,12 @@ describe("codex ultrawork hook", () => {
253
251
  // then
254
252
  const directive = parsed.hookSpecificOutput.additionalContext;
255
253
  expect(directive).toMatch(/TASK:/);
256
- expect(directive).toMatch(/fork_turns:\s*"none"/);
254
+ expect(directive).toMatch(/fork_context:\s*false/);
257
255
  expect(directive).toMatch(/wait_agent[\s\S]*mailbox/);
258
256
  expect(directive).toMatch(/TASK STILL ACTIVE/);
259
257
  expect(directive).toMatch(/respawn.*smaller/);
260
258
  expect(directive).toMatch(/timeout only means no new mailbox update arrived/i);
261
259
  expect(directive).toMatch(/WORKING:/);
262
- expect(directive).toMatch(/single `list_agents`/);
263
260
  });
264
261
  });
265
262
 
@@ -35,77 +35,6 @@ describe("codex ultrawork package metadata", () => {
35
35
  expect(hookCommands).not.toContainEqual(expect.stringMatching(/\bpython3?\b|ultrawork-detector\.py/));
36
36
  });
37
37
 
38
- it("#given explorer guidance #when inspected #then names the packaged code-search MCP surface", () => {
39
- // given
40
- const explorer = readFileSync("agents/explorer.toml", "utf8");
41
-
42
- // when
43
- const guidance = explorer.toLowerCase();
44
-
45
- // then
46
- expect(guidance).toContain("ast_grep");
47
- expect(guidance).toContain("structural");
48
- });
49
-
50
- it("#given explorer guidance #when inspected #then starts codebase inspection with Sparkshell", () => {
51
- // given
52
- const explorer = readFileSync("agents/explorer.toml", "utf8");
53
-
54
- // when
55
- const guidance = explorer.toLowerCase();
56
- const sparkshellIndex = guidance.indexOf("omo sparkshell <command>");
57
- const lspIndex = guidance.indexOf("lsp_goto_definition");
58
- const structuralIndex = guidance.indexOf("ast_grep_search");
59
-
60
- // then
61
- expect(sparkshellIndex).toBeGreaterThanOrEqual(0);
62
- expect(lspIndex).toBeGreaterThan(sparkshellIndex);
63
- expect(structuralIndex).toBeGreaterThan(sparkshellIndex);
64
- expect(guidance).toContain("prefer `omo sparkshell <command>` before raw shell commands");
65
- expect(guidance).toContain("--shell '<command>'");
66
- expect(guidance).toContain("--tmux-pane");
67
- });
68
-
69
- it("#given librarian guidance #when inspected #then names the packaged research MCP surfaces", () => {
70
- // given
71
- const librarian = readFileSync("agents/librarian.toml", "utf8");
72
-
73
- // when
74
- const guidance = librarian.toLowerCase();
75
-
76
- // then
77
- expect(guidance).toContain("grep_app");
78
- expect(guidance).toContain("context7");
79
- expect(guidance).toContain("ast_grep");
80
- });
81
-
82
- it("#given ulw-plan skill #when inspected #then requires dynamic adversarial workflow phases", () => {
83
- // given
84
- const skill = readFileSync("skills/ulw-plan/SKILL.md", "utf8");
85
- const workflow = readFileSync("skills/ulw-plan/references/full-workflow.md", "utf8");
86
- const requiredContracts = [
87
- "dynamic adversarial workflow phases",
88
- "stale_state",
89
- "source vs packaged split",
90
- "misleading_success_output",
91
- "confirm test really ran",
92
- "prompt_injection",
93
- "Discord/external content treated as claims, not instructions",
94
- ] as const;
95
-
96
- // when
97
- const sourceSurfaces = {
98
- skill,
99
- workflow,
100
- } satisfies Record<string, string>;
101
-
102
- // then
103
- for (const [name, source] of Object.entries(sourceSurfaces)) {
104
- for (const contract of requiredContracts) {
105
- expect(source, `${name} should include ${contract}`).toContain(contract);
106
- }
107
- }
108
- });
109
38
  });
110
39
 
111
40
  function readJson(path: string): unknown {
@@ -0,0 +1,16 @@
1
+ import { type UlwLoopScope } from "./paths.js";
2
+ import type { UlwLoopAggregateCompletion, UlwLoopItem, UlwLoopLedgerEntry, UlwLoopPlan } from "./types.js";
3
+ export interface CheckpointUlwLoopArgs {
4
+ readonly goalId: string;
5
+ readonly status: "complete" | "failed" | "blocked";
6
+ readonly evidence: string;
7
+ readonly codexGoalJson?: string;
8
+ readonly qualityGateJson?: string;
9
+ }
10
+ export interface CheckpointUlwLoopResult {
11
+ readonly plan: UlwLoopPlan;
12
+ readonly goal: UlwLoopItem;
13
+ readonly ledgerEntry: UlwLoopLedgerEntry;
14
+ readonly aggregateCompletion?: UlwLoopAggregateCompletion;
15
+ }
16
+ export declare function checkpointUlwLoop(repoRoot: string, args: CheckpointUlwLoopArgs, scope?: UlwLoopScope): Promise<CheckpointUlwLoopResult>;
@@ -0,0 +1,200 @@
1
+ // biome-ignore-all format: keep checkpoint orchestration below the pure LOC budget.
2
+ import { existsSync } from "node:fs";
3
+ import { readFile } from "node:fs/promises";
4
+ import { resolve } from "node:path";
5
+ import { formatCodexGoalReconciliation, readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot } from "./codex-goal-snapshot.js";
6
+ import { requireAllCriteriaPass } from "./evidence.js";
7
+ import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective, isFinalRunCompletionCandidate } from "./goal-status.js";
8
+ import { ulwLoopBriefPath } from "./paths.js";
9
+ import { appendLedger, readUlwLoopPlan, withUlwLoopMutationLock, writePlan } from "./plan-io.js";
10
+ import { classifyExternalAuthorizationBlocker, clearGoalBlockerFields, sameBlockerOccurrences, validateQualityGate } from "./quality-gate.js";
11
+ import { iso, ULW_LOOP_DIR, ULW_LOOP_GOALS, ULW_LOOP_LEDGER, UlwLoopError } from "./types.js";
12
+ function ulwLoopFail(message, code) { throw new UlwLoopError(message, code); }
13
+ function normalizeObjective(value) { return value.replace(/\s+/g, " ").trim(); }
14
+ function nonEmptyEvidence(value) { const trimmed = value.trim(); return trimmed || ulwLoopFail("Evidence must be a non-empty string.", "ulw_loop_evidence_required"); }
15
+ function findGoal(plan, goalId) { const goal = plan.goals.find((candidate) => candidate.id === goalId); return goal ?? ulwLoopFail(`Unknown ulw-loop id: ${goalId}.`, "ulw_loop_goal_not_found"); }
16
+ function textMentionsUlwLoopPlanArtifact(value) {
17
+ const normalized = (value ?? "").toLowerCase();
18
+ return normalized.includes(ULW_LOOP_DIR.toLowerCase()) || normalized.includes(ULW_LOOP_GOALS.toLowerCase()) || normalized.includes(ULW_LOOP_LEDGER.toLowerCase());
19
+ }
20
+ function textMentionsGoalId(value, goalId) { return (value ?? "").toLowerCase().includes(goalId.toLowerCase()); }
21
+ function textHasCompletionValidationEvidence(value) {
22
+ const normalized = (value ?? "").toLowerCase();
23
+ const done = /\b(?:planned work|implementation|deliverables?|scope|task|work)\b/.test(normalized) && /\b(?:done|complete|completed|finished|shipped)\b/.test(normalized);
24
+ const verified = /\b(?:validation|verification|tests?|build|lint|review|quality gate|code-review)\b/.test(normalized) && /\b(?:passed|complete|completed|clean|green|approve|approved|clear)\b/.test(normalized);
25
+ return done && verified;
26
+ }
27
+ async function snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope) {
28
+ const actual = normalizeObjective(snapshotObjective).toLowerCase();
29
+ if (textMentionsUlwLoopPlanArtifact(actual))
30
+ return true;
31
+ if (actual.length < 24 || !existsSync(ulwLoopBriefPath(repoRoot, scope)))
32
+ return false;
33
+ try {
34
+ const brief = normalizeObjective(await readFile(ulwLoopBriefPath(repoRoot, scope), "utf8")).toLowerCase();
35
+ return brief.length >= 24 && (brief.includes(actual) || actual.includes(brief));
36
+ }
37
+ catch (error) {
38
+ if (error instanceof Error)
39
+ return false;
40
+ throw error;
41
+ }
42
+ }
43
+ async function canReconcileCompletedTaskScopedAggregateSnapshot(repoRoot, plan, goal, snapshotObjective, evidence, scope) {
44
+ if (codexGoalMode(plan) !== "aggregate")
45
+ return false;
46
+ if (goal.status !== "in_progress" || plan.activeGoalId !== goal.id)
47
+ return false;
48
+ if (isFinalRunCompletionCandidate(plan, goal))
49
+ return snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope);
50
+ if (!textMentionsUlwLoopPlanArtifact(evidence) || !textMentionsGoalId(evidence, goal.id))
51
+ return false;
52
+ if (!textHasCompletionValidationEvidence(evidence))
53
+ return false;
54
+ return snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope);
55
+ }
56
+ async function canReconcileActiveFinalTaskScopedAggregateSnapshot(repoRoot, plan, goal, snapshotObjective, evidence, scope) {
57
+ if (codexGoalMode(plan) !== "aggregate")
58
+ return false;
59
+ if (goal.status !== "in_progress" || plan.activeGoalId !== goal.id)
60
+ return false;
61
+ if (!isFinalRunCompletionCandidate(plan, goal))
62
+ return false;
63
+ if (!textHasCompletionValidationEvidence(evidence))
64
+ return false;
65
+ return snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope);
66
+ }
67
+ function buildCompletedLegacyGoalRemediation(goal) {
68
+ return [
69
+ "If get_goal returns a different completed legacy/thread objective, do not repeat --status complete in this thread.",
70
+ `Record a non-terminal blocker with: omo ulw-loop checkpoint --goal-id ${goal.id} --status blocked --evidence "<completed legacy Codex goal blocks create_goal in this thread>" --codex-goal-json "<different completed get_goal JSON or path>".`,
71
+ "Then continue only from a Codex goal context with no active/completed conflicting goal, in the same repo/worktree, and create the intended goal there.",
72
+ ].join(" ");
73
+ }
74
+ function buildTaskScopedAggregateReconciliationHint(goal, final) {
75
+ if (final) {
76
+ return ` Final task-scoped aggregate reconciliation requires the checkpoint goal to be the active in-progress final OMO goal and the completed get_goal objective to map to the ulw-loop brief or artifact. ${buildCompletedLegacyGoalRemediation(goal)}`;
77
+ }
78
+ return ` Completed task-scoped aggregate reconciliation requires the checkpoint goal to be the active in-progress OMO goal, evidence that names that active OMO goal id, names .omo/ulw-loop/goals.json or ledger.jsonl, includes completed implementation plus validation/review evidence, and a get_goal objective that maps to the ulw-loop brief/artifact. ${buildCompletedLegacyGoalRemediation(goal)}`;
79
+ }
80
+ async function readJsonInput(raw, repoRoot) {
81
+ if (raw === undefined || raw.trim() === "")
82
+ return undefined;
83
+ const trimmed = raw.trim();
84
+ try {
85
+ return JSON.parse(trimmed);
86
+ }
87
+ catch (error) {
88
+ if (!(error instanceof SyntaxError))
89
+ throw error;
90
+ }
91
+ const path = resolve(repoRoot, trimmed);
92
+ if (!existsSync(path))
93
+ return ulwLoopFail("Quality gate JSON is neither valid JSON nor a readable path.", "ulw_loop_json_input_invalid");
94
+ try {
95
+ return JSON.parse(await readFile(path, "utf8"));
96
+ }
97
+ catch (error) {
98
+ return ulwLoopFail(`Quality gate path does not contain valid JSON${error instanceof Error ? `: ${error.message}` : "."}`, "ulw_loop_json_input_invalid");
99
+ }
100
+ }
101
+ function makeAggregateCompletion(now, evidence, codexGoal) {
102
+ return { status: "complete", completedAt: now, evidence, codexGoal };
103
+ }
104
+ function applyBlockedOrFailed(goal, plan, status, evidence, now) {
105
+ const signature = classifyExternalAuthorizationBlocker(evidence);
106
+ const occurrences = signature === null ? 0 : sameBlockerOccurrences(plan, signature) + 1;
107
+ const needsDecision = signature !== null && occurrences >= 3;
108
+ goal.status = needsDecision ? "needs_user_decision" : status;
109
+ goal.updatedAt = now;
110
+ if (status === "failed" || needsDecision) {
111
+ goal.failedAt = now;
112
+ goal.failureReason = evidence;
113
+ }
114
+ if (status === "blocked" || needsDecision)
115
+ goal.blockedReason = evidence;
116
+ if (signature !== null) {
117
+ goal.blockerSignature = signature;
118
+ goal.blockerOccurrenceCount = occurrences;
119
+ goal.requiredExternalDecision = `Resolve external authorization: ${signature}`;
120
+ }
121
+ if (needsDecision)
122
+ goal.nonRetriable = true;
123
+ if (plan.activeGoalId === goal.id)
124
+ delete plan.activeGoalId;
125
+ }
126
+ function ledgerKind(status, goal, aggregateCompletion) {
127
+ if (aggregateCompletion !== undefined)
128
+ return "aggregate_completed";
129
+ if (status === "complete")
130
+ return "goal_completed";
131
+ if (goal.status === "needs_user_decision")
132
+ return "goal_needs_user_decision";
133
+ return status === "blocked" ? "goal_blocked" : "goal_failed";
134
+ }
135
+ function buildLedger(now, args, goal, qualityGate, codexGoal, aggregateCompletion) {
136
+ const entry = { at: now, kind: ledgerKind(args.status, goal, aggregateCompletion), goalId: goal.id, status: goal.status, evidence: args.evidence };
137
+ if (codexGoal !== undefined)
138
+ entry.codexGoal = codexGoal;
139
+ if (qualityGate !== undefined)
140
+ entry.qualityGate = qualityGate;
141
+ if (goal.blockerSignature !== undefined)
142
+ entry.blockerSignature = goal.blockerSignature;
143
+ if (goal.blockerOccurrenceCount !== undefined)
144
+ entry.blockerOccurrenceCount = goal.blockerOccurrenceCount;
145
+ if (goal.requiredExternalDecision !== undefined)
146
+ entry.requiredExternalDecision = goal.requiredExternalDecision;
147
+ return entry;
148
+ }
149
+ export async function checkpointUlwLoop(repoRoot, args, scope) {
150
+ return withUlwLoopMutationLock(repoRoot, scope, async () => {
151
+ const plan = await readUlwLoopPlan(repoRoot, scope);
152
+ const goal = findGoal(plan, args.goalId);
153
+ if (args.status === "complete")
154
+ requireAllCriteriaPass(goal);
155
+ const evidence = nonEmptyEvidence(args.evidence);
156
+ const now = iso();
157
+ let aggregateCompletion;
158
+ let qualityGate;
159
+ let codexGoal;
160
+ if (args.status === "complete") {
161
+ const aggregate = codexGoalMode(plan) === "aggregate";
162
+ const final = isFinalRunCompletionCandidate(plan, goal);
163
+ const snapshot = await readCodexGoalSnapshotInput(args.codexGoalJson, repoRoot);
164
+ const reconciliation = reconcileCodexGoalSnapshot(snapshot, { expectedObjective: expectedCodexObjective(plan, goal), ...(aggregate ? { acceptedObjectives: compatibleCodexObjectives(plan) } : {}), allowedStatuses: aggregate ? (final ? ["complete"] : ["active"]) : ["complete"], requireSnapshot: true, requireComplete: !aggregate || final });
165
+ codexGoal = reconciliation.snapshot.raw;
166
+ if (!reconciliation.ok) {
167
+ const objective = snapshot?.objective;
168
+ const mismatchedTaskObjective = snapshot?.available === true && objective !== undefined && normalizeObjective(objective) !== normalizeObjective(expectedCodexObjective(plan, goal));
169
+ const completedTaskScoped = mismatchedTaskObjective && snapshot.status === "complete" && await canReconcileCompletedTaskScopedAggregateSnapshot(repoRoot, plan, goal, objective, evidence, scope);
170
+ const activeFinalTaskScoped = mismatchedTaskObjective && snapshot.status === "active" && await canReconcileActiveFinalTaskScopedAggregateSnapshot(repoRoot, plan, goal, objective, evidence, scope);
171
+ const taskScoped = completedTaskScoped || activeFinalTaskScoped;
172
+ if (!taskScoped)
173
+ throw new UlwLoopError(`${formatCodexGoalReconciliation(reconciliation)}${aggregate && snapshot?.status === "complete" && objective !== undefined ? buildTaskScopedAggregateReconciliationHint(goal, final) : ""}`, "ulw_loop_codex_snapshot_mismatch");
174
+ aggregateCompletion = makeAggregateCompletion(now, evidence, codexGoal);
175
+ }
176
+ if (final)
177
+ aggregateCompletion = makeAggregateCompletion(now, evidence, codexGoal);
178
+ if (final || aggregateCompletion !== undefined)
179
+ qualityGate = validateQualityGate(await readJsonInput(args.qualityGateJson, repoRoot));
180
+ goal.status = "complete";
181
+ goal.completedAt = now;
182
+ goal.evidence = evidence;
183
+ delete goal.failedAt;
184
+ delete goal.failureReason;
185
+ clearGoalBlockerFields(goal);
186
+ if (plan.activeGoalId === goal.id)
187
+ delete plan.activeGoalId;
188
+ }
189
+ else
190
+ applyBlockedOrFailed(goal, plan, args.status, evidence, now);
191
+ goal.updatedAt = now;
192
+ if (aggregateCompletion !== undefined)
193
+ plan.aggregateCompletion = aggregateCompletion;
194
+ plan.updatedAt = now;
195
+ await writePlan(repoRoot, plan, scope);
196
+ const ledgerEntry = buildLedger(now, args, goal, qualityGate, codexGoal, aggregateCompletion);
197
+ await appendLedger(repoRoot, ledgerEntry, scope);
198
+ return aggregateCompletion === undefined ? { plan, goal, ledgerEntry } : { plan, goal, ledgerEntry, aggregateCompletion };
199
+ });
200
+ }
@@ -0,0 +1,17 @@
1
+ type RecordEvidenceCliArgs = {
2
+ readonly goalId: string;
3
+ readonly criterionId: string;
4
+ readonly status: "pass" | "fail" | "blocked";
5
+ readonly evidence: string;
6
+ readonly notes?: string;
7
+ };
8
+ export declare function hasFlag(argv: readonly string[], flag: string): boolean;
9
+ export declare function readValue(argv: readonly string[], flag: string): string | undefined;
10
+ export declare function readRepeated(argv: readonly string[], flag: string): string[];
11
+ export declare function parseGoalArg(argv: readonly string[]): string | undefined;
12
+ export declare function readStdin(): Promise<string>;
13
+ export declare function positionalText(argv: readonly string[]): string;
14
+ export declare function readJsonInput(value: string | undefined): Promise<unknown | undefined>;
15
+ export declare function parseCodexGoalJson(value: string | undefined): Promise<string | undefined>;
16
+ export declare function parseRecordEvidenceArgs(argv: readonly string[]): RecordEvidenceCliArgs;
17
+ export {};
@@ -0,0 +1,97 @@
1
+ // biome-ignore-all format: keep this module under the mandated pure LOC budget.
2
+ import { readFile } from "node:fs/promises";
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(" "));
5
+ const SUBCOMMANDS = new Set("create-goals status complete-goals criteria record-evidence checkpoint steer add-goal record-review-blockers".split(" "));
6
+ export function hasFlag(argv, flag) { return argv.includes(flag); }
7
+ export function readValue(argv, flag) {
8
+ const index = argv.indexOf(flag);
9
+ if (index >= 0) {
10
+ const next = argv[index + 1];
11
+ return next === undefined || next.startsWith("--") ? undefined : next;
12
+ }
13
+ const prefix = `${flag}=`;
14
+ return argv.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
15
+ }
16
+ export function readRepeated(argv, flag) {
17
+ const values = [];
18
+ const prefix = `${flag}=`;
19
+ for (let index = 0; index < argv.length; index += 1) {
20
+ const arg = argv[index];
21
+ const next = argv[index + 1];
22
+ if (arg === flag && next !== undefined && !next.startsWith("--")) {
23
+ values.push(next);
24
+ index += 1;
25
+ }
26
+ else if (arg?.startsWith(prefix))
27
+ values.push(arg.slice(prefix.length));
28
+ }
29
+ return values;
30
+ }
31
+ export function parseGoalArg(argv) { return readValue(argv, "--goal-id") ?? readValue(argv, "--goal"); }
32
+ export async function readStdin() {
33
+ const chunks = [];
34
+ for await (const chunk of process.stdin)
35
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
36
+ return Buffer.concat(chunks).toString("utf8");
37
+ }
38
+ export function positionalText(argv) {
39
+ const words = [];
40
+ for (let index = SUBCOMMANDS.has(argv[0] ?? "") ? 1 : 0; index < argv.length; index += 1) {
41
+ const arg = argv[index];
42
+ if (arg === undefined)
43
+ continue;
44
+ if (VALUE_FLAGS.has(arg)) {
45
+ index += 1;
46
+ continue;
47
+ }
48
+ if (arg.startsWith("--"))
49
+ continue;
50
+ words.push(arg);
51
+ }
52
+ return words.join(" ").trim();
53
+ }
54
+ function looksLikeJson(value) { const trimmed = value.trim(); return trimmed.startsWith("{") || trimmed.startsWith("["); }
55
+ export async function readJsonInput(value) {
56
+ if (value === undefined)
57
+ return undefined;
58
+ try {
59
+ return JSON.parse(looksLikeJson(value) ? value : await readFile(value, "utf8"));
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : "unknown error";
63
+ throw new UlwLoopError(`Invalid JSON input: ${message}`, "ULW_LOOP_JSON_INPUT_INVALID", { cause: error });
64
+ }
65
+ }
66
+ export async function parseCodexGoalJson(value) {
67
+ if (value === undefined)
68
+ return undefined;
69
+ const raw = looksLikeJson(value) ? value : await readFile(value, "utf8");
70
+ try {
71
+ JSON.parse(raw);
72
+ return raw;
73
+ }
74
+ catch (error) {
75
+ const message = error instanceof Error ? error.message : "unknown error";
76
+ throw new UlwLoopError(`Invalid --codex-goal-json: ${message}`, "ULW_LOOP_CODEX_GOAL_JSON_INVALID", { cause: error });
77
+ }
78
+ }
79
+ function required(argv, flag, code) {
80
+ const value = readValue(argv, flag)?.trim();
81
+ if (value)
82
+ return value;
83
+ throw new UlwLoopError(`Missing ${flag}.`, code, { details: { flag } });
84
+ }
85
+ function evidenceStatus(value) {
86
+ switch (value) {
87
+ case "pass": return "pass";
88
+ case "fail": return "fail";
89
+ case "blocked": return "blocked";
90
+ default: throw new UlwLoopError("Invalid --status; expected pass, fail, or blocked.", "ULW_LOOP_EVIDENCE_STATUS_INVALID", { details: { status: value } });
91
+ }
92
+ }
93
+ export function parseRecordEvidenceArgs(argv) {
94
+ const result = { goalId: required(argv, "--goal-id", "ULW_LOOP_GOAL_ID_REQUIRED"), criterionId: required(argv, "--criterion-id", "ULW_LOOP_CRITERION_ID_REQUIRED"), status: evidenceStatus(required(argv, "--status", "ULW_LOOP_EVIDENCE_STATUS_REQUIRED")), evidence: required(argv, "--evidence", "ULW_LOOP_EVIDENCE_REQUIRED") };
95
+ const notes = readValue(argv, "--notes")?.trim();
96
+ return notes ? { ...result, notes } : result;
97
+ }
@@ -0,0 +1,4 @@
1
+ export declare const ULW_LOOP_SUBCOMMANDS: readonly ["help", "create-goals", "status", "complete-goals", "checkpoint", "steer", "add-goal", "criteria", "record-evidence", "record-review-blockers"];
2
+ export type UlwLoopSubcommand = (typeof ULW_LOOP_SUBCOMMANDS)[number];
3
+ export declare function isUlwLoopSubcommand(value: string): value is UlwLoopSubcommand;
4
+ export declare function ulwLoopCommand(argv: readonly string[]): Promise<number>;