oh-my-opencode 4.18.2 → 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 (307) 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 +8 -8
  7. package/README.ru.md +6 -6
  8. package/README.zh-cn.md +6 -6
  9. package/dist/agents/atlas/agent.d.ts +7 -6
  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/index.d.ts +5 -0
  14. package/dist/agents/sisyphus/kimi-k3.d.ts +19 -0
  15. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  16. package/dist/agents/sisyphus-junior/agent.d.ts +8 -4
  17. package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
  18. package/dist/agents/sisyphus-junior/index.d.ts +2 -0
  19. package/dist/agents/sisyphus-junior/kimi-k3.d.ts +12 -0
  20. package/dist/agents/types.d.ts +2 -2
  21. package/dist/cli/index.js +781 -215
  22. package/dist/cli-node/index.js +781 -215
  23. package/dist/config/index.d.ts +1 -1
  24. package/dist/config/schema/agent-overrides.d.ts +48 -48
  25. package/dist/config/schema/browser-automation.d.ts +1 -0
  26. package/dist/config/schema/categories.d.ts +6 -6
  27. package/dist/config/schema/codegraph.d.ts +2 -0
  28. package/dist/config/schema/commands.d.ts +1 -3
  29. package/dist/config/schema/default-mode.d.ts +1 -1
  30. package/dist/config/schema/fallback-models.d.ts +5 -5
  31. package/dist/config/schema/goal.d.ts +7 -0
  32. package/dist/config/schema/hooks.d.ts +1 -1
  33. package/dist/config/schema/oh-my-opencode-config.d.ts +56 -58
  34. package/dist/config/schema/ralph-loop.d.ts +1 -1
  35. package/dist/config/schema.d.ts +1 -1
  36. package/dist/create-hooks.d.ts +1 -1
  37. package/dist/features/builtin-commands/templates/goal.d.ts +1 -0
  38. package/dist/features/builtin-commands/templates/stop-continuation.d.ts +1 -1
  39. package/dist/features/builtin-commands/types.d.ts +1 -1
  40. package/dist/hooks/auto-slash-command/executor.d.ts +1 -0
  41. package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
  42. package/dist/hooks/goal/command-arguments.d.ts +13 -0
  43. package/dist/hooks/goal/controller.d.ts +26 -0
  44. package/dist/hooks/goal/index.d.ts +23 -0
  45. package/dist/hooks/goal/prompt.d.ts +3 -0
  46. package/dist/hooks/goal/store.d.ts +8 -0
  47. package/dist/hooks/goal/tools.d.ts +10 -0
  48. package/dist/hooks/goal/types.d.ts +93 -0
  49. package/dist/hooks/goal/validation.d.ts +4 -0
  50. package/dist/hooks/index.d.ts +1 -0
  51. package/dist/hooks/keyword-detector/hook.d.ts +1 -2
  52. package/dist/hooks/ralph-loop/types.d.ts +1 -1
  53. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  54. package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
  55. package/dist/index.js +5398 -5109
  56. package/dist/oh-my-opencode.schema.json +34 -19
  57. package/dist/plugin/chat-message/loop-commands.d.ts +1 -1
  58. package/dist/plugin/chat-message/types.d.ts +23 -10
  59. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -1
  60. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -2
  61. package/dist/plugin/hooks/create-transform-hooks.d.ts +0 -2
  62. package/dist/plugin/stop-continuation.d.ts +2 -2
  63. package/dist/shared/omo-process-sweep.d.ts +18 -0
  64. package/dist/shared/system-directive.d.ts +0 -1
  65. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  66. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  67. package/dist/skills/ulw-plan/SKILL.md +31 -8
  68. package/dist/skills/ulw-plan/references/full-workflow.md +117 -6
  69. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  70. package/dist/skills/ulw-research/SKILL.md +3 -3
  71. package/dist/testing/create-plugin-module.d.ts +1 -0
  72. package/dist/tools/delegate-task/types.d.ts +0 -1
  73. package/dist/tui.js +138 -80
  74. package/package.json +14 -14
  75. package/packages/git-bash-mcp/dist/cli.js +54 -8
  76. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +60 -0
  77. package/packages/lsp-core/src/lsp/client.ts +14 -1
  78. package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
  79. package/packages/lsp-core/src/mcp.ts +9 -0
  80. package/packages/lsp-daemon/dist/cli.js +319 -51
  81. package/packages/lsp-daemon/dist/client.js +136 -48
  82. package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
  83. package/packages/lsp-daemon/dist/daemon-client.js +4 -34
  84. package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
  85. package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
  86. package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
  87. package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
  88. package/packages/lsp-daemon/dist/daemon-server.js +5 -1
  89. package/packages/lsp-daemon/dist/index.js +137 -48
  90. package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
  91. package/packages/lsp-daemon/dist/proxy.js +1 -0
  92. package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
  93. package/packages/lsp-daemon/dist/version-reap.js +182 -0
  94. package/packages/lsp-tools-mcp/dist/cli.js +61 -10
  95. package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
  96. package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
  97. package/packages/lsp-tools-mcp/dist/tools.js +6 -1
  98. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  99. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +416 -25
  100. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  101. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  102. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
  103. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +7 -6
  104. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +638 -267
  105. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +178 -89
  106. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  107. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
  108. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +3 -1
  109. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
  110. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
  111. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +15 -6
  112. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +6 -2
  113. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
  114. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +1 -1
  115. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +148 -0
  116. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
  117. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
  118. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
  119. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
  120. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -1
  121. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
  122. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +41 -0
  123. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +109 -8
  124. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
  125. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +43 -0
  126. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  127. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  128. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  129. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  130. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  131. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  132. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +1 -0
  133. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  134. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
  135. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  136. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  137. package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
  138. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  139. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  140. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
  141. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
  142. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +8 -0
  143. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +147 -60
  144. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  145. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  146. package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +3 -71
  147. package/packages/omo-codex/plugin/components/start-work-continuation/src/plan-checklist.ts +171 -0
  148. package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +198 -23
  149. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +4 -3
  150. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +6 -5
  151. package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-scaffold.md +15 -0
  152. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  153. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  154. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  155. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  156. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -10
  157. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
  158. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
  159. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  160. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  161. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
  162. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +3 -3
  163. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  164. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
  165. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  166. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  167. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +31 -8
  168. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +117 -6
  169. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  170. package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
  171. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
  172. package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
  173. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
  174. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
  175. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
  176. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
  177. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  178. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  179. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
  180. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
  181. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
  182. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
  183. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
  184. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
  185. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
  186. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
  187. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
  188. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
  189. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
  190. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
  191. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
  192. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
  193. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  194. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
  195. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
  196. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
  197. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
  198. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
  199. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
  200. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
  201. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
  202. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
  203. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
  204. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  205. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  206. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
  207. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
  208. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
  209. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
  210. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
  211. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
  212. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
  213. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
  214. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
  215. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
  216. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
  217. package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
  218. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
  219. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
  220. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
  221. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
  222. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
  223. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
  224. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
  225. package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
  226. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
  227. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
  228. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
  229. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
  230. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
  231. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
  232. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
  233. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
  234. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
  235. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  236. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  237. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  238. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  239. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  240. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  241. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  242. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  243. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  244. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  245. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  246. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
  247. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  248. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
  249. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  250. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
  251. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  252. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  253. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  254. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  255. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  256. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  257. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  258. package/packages/omo-codex/plugin/package-lock.json +41 -41
  259. package/packages/omo-codex/plugin/package.json +1 -1
  260. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +32 -28
  261. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +17 -45
  262. package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +455 -0
  263. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +3 -18
  264. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +43 -0
  265. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  266. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
  267. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +31 -8
  268. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +117 -6
  269. package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  270. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +11 -11
  271. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
  272. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
  273. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +2 -2
  274. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +6 -6
  275. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +3 -3
  276. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +62 -0
  277. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +271 -14
  278. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +3 -18
  279. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +0 -5
  280. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +293 -0
  281. package/packages/omo-codex/scripts/install-config.test.mjs +10 -10
  282. package/packages/omo-codex/scripts/install-dist/install-local.mjs +401 -22
  283. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +39 -2
  284. package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
  285. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  286. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  287. package/packages/shared-skills/skills/ulw-plan/SKILL.md +31 -8
  288. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +117 -6
  289. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  290. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
  291. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +0 -3
  292. package/dist/skills/ultraresearch/SKILL.md +0 -10
  293. package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +0 -273
  294. package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -12
  295. package/packages/shared-skills/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -107
  296. package/packages/shared-skills/skills/lcx-doctor/SKILL.md +0 -128
  297. package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +0 -11
  298. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +0 -268
  299. package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +0 -11
  300. package/packages/shared-skills/skills/ultraresearch/SKILL.md +0 -10
  301. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/SKILL.md +0 -0
  302. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -0
  303. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -0
  304. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/SKILL.md +0 -0
  305. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/agents/openai.yaml +0 -0
  306. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/SKILL.md +0 -0
  307. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/agents/openai.yaml +0 -0
@@ -107,11 +107,73 @@ test("#given parseArgs #when the slug is missing or unsafe #then it throws, and
107
107
  assert.equal(ok.intent, "unclear");
108
108
  assert.equal(ok.reset, true);
109
109
  assert.equal(ok.force, true);
110
+ assert.equal(ok.draftOnly, false);
111
+ assert.equal(ok.reviewRequired, false);
112
+ const draftOnly = parseArgs(["node", "s", "my-plan", "--draft-only"]);
113
+ assert.equal(draftOnly.draftOnly, true);
114
+ const reviewRequired = parseArgs(["node", "s", "my-plan", "--draft-only", "--review-required"]);
115
+ assert.equal(reviewRequired.reviewRequired, true);
110
116
  const plain = parseArgs(["node", "s", "my-plan"]);
111
117
  assert.equal(plain.reset, false);
112
118
  assert.equal(plain.force, false);
113
119
  });
114
120
 
121
+ test("#given an explicit review modifier at startup #when draft-only scaffold runs #then the first durable write contains the complete pending review request", async () => {
122
+ const { scaffold } = await import(scriptUrl);
123
+ const dir = await mkdtemp(join(tmpdir(), "ulwp-"));
124
+ try {
125
+ await scaffold(dir, { slug: "demo", intent: "clear", draftOnly: true, reviewRequired: true });
126
+ const draft = await readFile(join(dir, ".omo", "drafts", "demo.md"), "utf8");
127
+ assert.match(draft, /review_required: true/);
128
+ assert.match(draft, /plan_path: \.omo\/plans\/demo\.md/);
129
+ assert.match(draft, /pending-action: write and review \.omo\/plans\/demo\.md/);
130
+ assert.match(draft, /momus:\n\s+status: pending/);
131
+ assert.match(draft, /independent:\n\s+status: pending/);
132
+ await assert.rejects(() => readFile(join(dir, ".omo", "plans", "demo.md"), "utf8"), /ENOENT/);
133
+ } finally {
134
+ await rm(dir, { recursive: true, force: true });
135
+ }
136
+ });
137
+
138
+ test("#given automatic review for non-Trivial UNCLEAR intent #when draft-only scaffold runs #then the first durable write contains the complete pending review request", async () => {
139
+ const { scaffold } = await import(scriptUrl);
140
+ const dir = await mkdtemp(join(tmpdir(), "ulwp-"));
141
+ try {
142
+ await scaffold(dir, { slug: "demo", intent: "unclear", draftOnly: true, reviewRequired: true });
143
+ const draft = await readFile(join(dir, ".omo", "drafts", "demo.md"), "utf8");
144
+ assert.match(draft, /intent: unclear/);
145
+ assert.match(draft, /review_required: true/);
146
+ assert.match(draft, /plan_path: \.omo\/plans\/demo\.md/);
147
+ assert.match(draft, /plan_sha256: null/);
148
+ assert.match(draft, /review_round_id: null/);
149
+ assert.match(draft, /pending-action: write and review \.omo\/plans\/demo\.md/);
150
+ assert.match(draft, /momus:\n\s+status: pending[\s\S]*?target: \.omo\/plans\/demo\.md[\s\S]*?result: null/);
151
+ assert.match(draft, /independent:\n\s+status: pending[\s\S]*?target: \.omo\/plans\/demo\.md[\s\S]*?result: null/);
152
+ await assert.rejects(() => readFile(join(dir, ".omo", "plans", "demo.md"), "utf8"), /ENOENT/);
153
+ } finally {
154
+ await rm(dir, { recursive: true, force: true });
155
+ }
156
+ });
157
+
158
+ test("#given Trivial UNCLEAR pre-approval planning #when draft-only scaffold runs #then it creates a review-optional draft without creating a plan", async () => {
159
+ const { scaffold } = await import(scriptUrl);
160
+ const dir = await mkdtemp(join(tmpdir(), "ulwp-"));
161
+ try {
162
+ const first = await scaffold(dir, { slug: "demo", intent: "unclear", draftOnly: true });
163
+ assert.equal(first.length, 1);
164
+ assert.equal(first[0].status, "created");
165
+ assert.match(await readFile(join(dir, ".omo", "drafts", "demo.md"), "utf8"), /intent: unclear/);
166
+ assert.match(await readFile(join(dir, ".omo", "drafts", "demo.md"), "utf8"), /review_required: false/);
167
+ await assert.rejects(() => readFile(join(dir, ".omo", "plans", "demo.md"), "utf8"), /ENOENT/);
168
+
169
+ const afterApproval = await scaffold(dir, { slug: "demo", intent: "unclear" });
170
+ assert.equal(afterApproval[0].status, "exists");
171
+ assert.equal(afterApproval[1].status, "created");
172
+ } finally {
173
+ await rm(dir, { recursive: true, force: true });
174
+ }
175
+ });
176
+
115
177
  test("#given an already-scaffolded plan #when the script is re-run plain #then it is a no-op that preserves appended todos (resume-safe, no crash, no clobber)", async () => {
116
178
  // given
117
179
  const { scaffold } = await import(scriptUrl);
@@ -1,4 +1,5 @@
1
1
  import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
2
3
  import { mkdtemp, readFile, writeFile } from "node:fs/promises";
3
4
  import { tmpdir } from "node:os";
4
5
  import { join } from "node:path";
@@ -6,7 +7,26 @@ import test from "node:test";
6
7
 
7
8
  import { migrateConfigFile } from "../scripts/migrate-codex-config.mjs";
8
9
 
9
- test("#given SessionStart config migration sees a low subagent cap #when migrating #then raises it to 1000", async () => {
10
+ function parseTomlWithPython(config) {
11
+ const python = resolvePython();
12
+ const result = spawnSync(
13
+ python,
14
+ ["-c", "import json, sys, tomllib; print(json.dumps(tomllib.loads(sys.stdin.read())))"],
15
+ { encoding: "utf8", input: config },
16
+ );
17
+ assert.equal(result.status, 0, result.stderr);
18
+ return JSON.parse(result.stdout);
19
+ }
20
+
21
+ function resolvePython() {
22
+ for (const command of ["python3", "python"]) {
23
+ const result = spawnSync(command, ["-c", "import tomllib"], { encoding: "utf8" });
24
+ if (result.status === 0) return command;
25
+ }
26
+ assert.fail("Python with tomllib is required for TOML parse assertions");
27
+ }
28
+
29
+ test("#given SessionStart migration sees an inline-commented V2 cap #when migrating twice #then preserves the line and ordering byte-for-byte", async () => {
10
30
  const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-migration-"));
11
31
  const configPath = join(root, "config.toml");
12
32
  await writeFile(
@@ -26,24 +46,240 @@ test("#given SessionStart config migration sees a low subagent cap #when migrati
26
46
  "",
27
47
  "[features.multi_agent_v2]",
28
48
  "enabled = false",
29
- "max_concurrent_threads_per_session = 6",
49
+ "usage_hint_enabled = false",
50
+ "max_concurrent_threads_per_session = 7 # user cap",
51
+ "show_tool_use = false",
30
52
  "",
31
53
  ].join("\n"),
32
54
  );
33
55
 
34
- const result = await migrateConfigFile(configPath);
56
+ const firstResult = await migrateConfigFile(configPath);
57
+ const firstPass = await readFile(configPath, "utf8");
58
+ const secondResult = await migrateConfigFile(configPath);
59
+
60
+ const secondPass = await readFile(configPath, "utf8");
61
+ assert.equal(firstResult.changed, true);
62
+ assert.equal(secondResult.changed, false);
63
+ assert.equal(secondPass, firstPass);
64
+ assert.match(
65
+ secondPass,
66
+ /usage_hint_enabled = false\nmax_concurrent_threads_per_session = 7 # user cap\nshow_tool_use = false/,
67
+ );
68
+ assert.match(secondPass, /\[agents\][\s\S]*?max_threads = 1000/);
69
+ assert.match(secondPass, /max_depth = 4/);
70
+ assert.match(secondPass, /\[agents\.explorer\]\nconfig_file = "\.\/agents\/explorer\.toml"/);
71
+ assert.match(secondPass, /\[features\.multi_agent_v2\][\s\S]*?enabled = false/);
72
+ assert.doesNotMatch(secondPass, /^max_threads\s*=\s*6$/m);
73
+ });
74
+
75
+ for (const header of [
76
+ '["features"."multi_agent_v2"]',
77
+ "[ features . multi_agent_v2 ]",
78
+ '["features"."multi_agent_v\\u0032"]',
79
+ ]) {
80
+ test(`#given SessionStart migration sees equivalent V2 header ${header} #when migrating twice #then preserves one valid table and the explicit cap`, async () => {
81
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-equivalent-header-"));
82
+ const configPath = join(root, "config.toml");
83
+ await writeFile(
84
+ configPath,
85
+ [
86
+ 'model = "gpt-5.4"',
87
+ "",
88
+ header,
89
+ "usage_hint_enabled = false",
90
+ "max_concurrent_threads_per_session = 7 # user cap",
91
+ "show_tool_use = false",
92
+ "",
93
+ ].join("\n"),
94
+ );
95
+
96
+ await migrateConfigFile(configPath);
97
+ const firstPass = await readFile(configPath, "utf8");
98
+ const parsed = parseTomlWithPython(firstPass);
99
+ const secondResult = await migrateConfigFile(configPath);
100
+ const secondPass = await readFile(configPath, "utf8");
101
+
102
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 7);
103
+ assert.equal(secondResult.changed, false);
104
+ assert.equal(secondPass, firstPass);
105
+ assert.equal((secondPass.match(/max_concurrent_threads_per_session\s*=/g) ?? []).length, 1);
106
+ assert.match(
107
+ secondPass,
108
+ /usage_hint_enabled = false\nmax_concurrent_threads_per_session = 7 # user cap\nshow_tool_use = false/,
109
+ );
110
+ assert.match(secondPass, new RegExp(header.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
111
+ });
112
+ }
113
+
114
+ for (const fixture of [
115
+ {
116
+ name: "quoted cap key",
117
+ lines: [
118
+ "[features.multi_agent_v2]",
119
+ '"max_concurrent_threads_per_session" = 7 # user cap',
120
+ ],
121
+ preservedLine: '"max_concurrent_threads_per_session" = 7 # user cap',
122
+ },
123
+ {
124
+ name: "escaped quoted cap key",
125
+ lines: [
126
+ "[features.multi_agent_v2]",
127
+ '"max_concurrent_threads_per_sessio\\u006e" = 7 # user cap',
128
+ ],
129
+ preservedLine: '"max_concurrent_threads_per_sessio\\u006e" = 7 # user cap',
130
+ },
131
+ {
132
+ name: "dotted cap key",
133
+ lines: [
134
+ "[features]",
135
+ "multi_agent_v2.max_concurrent_threads_per_session = 7 # user cap",
136
+ ],
137
+ preservedLine: "multi_agent_v2.max_concurrent_threads_per_session = 7 # user cap",
138
+ },
139
+ {
140
+ name: "root-qualified dotted cap key",
141
+ lines: ["features.multi_agent_v2.max_concurrent_threads_per_session = 7 # user cap"],
142
+ preservedLine: "features.multi_agent_v2.max_concurrent_threads_per_session = 7 # user cap",
143
+ },
144
+ ]) {
145
+ test(`#given SessionStart migration sees a ${fixture.name} #when migrating twice #then preserves the semantic cap without duplication`, async () => {
146
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-semantic-key-"));
147
+ const configPath = join(root, "config.toml");
148
+ await writeFile(configPath, ['model = "gpt-5.4"', "", ...fixture.lines, ""].join("\n"));
149
+
150
+ await migrateConfigFile(configPath);
151
+ const firstPass = await readFile(configPath, "utf8");
152
+ const parsed = parseTomlWithPython(firstPass);
153
+ const secondResult = await migrateConfigFile(configPath);
154
+ const secondPass = await readFile(configPath, "utf8");
155
+
156
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 7);
157
+ assert.equal(secondResult.changed, false);
158
+ assert.equal(secondPass, firstPass);
159
+ assert.match(secondPass, new RegExp(fixture.preservedLine.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
160
+ assert.doesNotMatch(secondPass, /^max_concurrent_threads_per_session = 16$/m);
161
+ if (fixture.name === "root-qualified dotted cap key") {
162
+ assert.equal(parsed.features.multi_agent_v2.enabled, false);
163
+ }
164
+ });
165
+ }
166
+
167
+ test("#given multiline string contains V2 cap lookalikes #when SessionStart migrates #then writes the absent semantic default", async () => {
168
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-multiline-lookalike-"));
169
+ const configPath = join(root, "config.toml");
170
+ await writeFile(
171
+ configPath,
172
+ [
173
+ 'model = "gpt-5.4"',
174
+ 'notes = """',
175
+ "[features.multi_agent_v2]",
176
+ "max_concurrent_threads_per_session = 7",
177
+ '"""',
178
+ "",
179
+ ].join("\n"),
180
+ );
35
181
 
182
+ await migrateConfigFile(configPath);
36
183
  const content = await readFile(configPath, "utf8");
37
- assert.equal(result.changed, true);
38
- assert.match(content, /\[agents\][\s\S]*?max_threads = 1000/);
39
- assert.match(content, /max_depth = 4/);
40
- assert.match(content, /\[agents\.explorer\]\nconfig_file = "\.\/agents\/explorer\.toml"/);
41
- assert.match(content, /\[features\.multi_agent_v2\][\s\S]*?enabled = false/);
42
- assert.match(content, /max_concurrent_threads_per_session = 1000/);
43
- assert.doesNotMatch(content, /^max_threads\s*=\s*6$/m);
184
+ const parsed = parseTomlWithPython(content);
185
+
186
+ assert.match(parsed.notes, /max_concurrent_threads_per_session = 7/);
187
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 16);
188
+ });
189
+
190
+ test("#given V2 section multiline value contains a cap lookalike #when SessionStart migrates #then writes the absent default", async () => {
191
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-section-multiline-lookalike-"));
192
+ const configPath = join(root, "config.toml");
193
+ await writeFile(
194
+ configPath,
195
+ [
196
+ 'model = "gpt-5.4"',
197
+ "[features.multi_agent_v2]",
198
+ 'notes = """',
199
+ "max_concurrent_threads_per_session = 7",
200
+ '"""',
201
+ "",
202
+ ].join("\n"),
203
+ );
204
+
205
+ await migrateConfigFile(configPath);
206
+ const parsed = parseTomlWithPython(await readFile(configPath, "utf8"));
207
+
208
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 16);
44
209
  });
45
210
 
46
- test("#given gpt-5.6 session model with no models_cache #when migrating #then does not write agents.max_threads", async () => {
211
+ test("#given V2 root-dotted disable and cap #when gpt-5.6 SessionStart migrates #then removes disable and V1 agents cap", async () => {
212
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-root-dotted-v2-cleanup-"));
213
+ const configPath = join(root, "config.toml");
214
+ await writeFile(
215
+ configPath,
216
+ [
217
+ 'model = "gpt-5.6-terra"',
218
+ "features.multi_agent_v2.max_concurrent_threads_per_session = 7",
219
+ "features.multi_agent_v2.enabled = false",
220
+ "",
221
+ "[agents]",
222
+ "max_threads = 1000",
223
+ "",
224
+ ].join("\n"),
225
+ );
226
+
227
+ await migrateConfigFile(configPath, { sessionModel: "gpt-5.6-terra" });
228
+ const content = await readFile(configPath, "utf8");
229
+ const parsed = parseTomlWithPython(content);
230
+
231
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 7);
232
+ assert.equal(parsed.features.multi_agent_v2.enabled, undefined);
233
+ assert.equal(parsed.agents, undefined);
234
+ });
235
+
236
+ test("#given quoted dotted V1 keys under features #when SessionStart migrates #then replaces enabled without a duplicate", async () => {
237
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-quoted-dotted-v1-"));
238
+ const configPath = join(root, "config.toml");
239
+ await writeFile(
240
+ configPath,
241
+ [
242
+ 'model = "gpt-5.4"',
243
+ "",
244
+ "[features]",
245
+ '"multi_agent_v2".enabled = true',
246
+ '"multi_agent_v2".max_concurrent_threads_per_session = 7',
247
+ "",
248
+ ].join("\n"),
249
+ );
250
+
251
+ await migrateConfigFile(configPath);
252
+ const content = await readFile(configPath, "utf8");
253
+ const parsed = parseTomlWithPython(content);
254
+
255
+ assert.equal(parsed.features.multi_agent_v2.enabled, false);
256
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 7);
257
+ assert.equal((content.match(/enabled\s*=/g) ?? []).length, 1);
258
+ });
259
+
260
+ test("#given multiline string closes after an escaped quote #when SessionStart migrates #then preserves the following explicit cap", async () => {
261
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-overlapping-closer-"));
262
+ const configPath = join(root, "config.toml");
263
+ await writeFile(
264
+ configPath,
265
+ [
266
+ 'model = "gpt-5.4"',
267
+ 'notes = """abc\\\""""',
268
+ "[features.multi_agent_v2]",
269
+ "max_concurrent_threads_per_session = 7",
270
+ "",
271
+ ].join("\n"),
272
+ );
273
+
274
+ await migrateConfigFile(configPath);
275
+ const content = await readFile(configPath, "utf8");
276
+ const parsed = parseTomlWithPython(content);
277
+
278
+ assert.equal(parsed.features.multi_agent_v2.max_concurrent_threads_per_session, 7);
279
+ assert.equal((content.match(/^\[features\.multi_agent_v2\]$/gm) ?? []).length, 1);
280
+ });
281
+
282
+ test("#given gpt-5.6 session model with no models_cache and an explicit V2 cap #when migrating #then removes agents.max_threads but preserves the cap", async () => {
47
283
  const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-gpt56-nocache-"));
48
284
  const configPath = join(root, "config.toml");
49
285
  await writeFile(
@@ -58,7 +294,7 @@ test("#given gpt-5.6 session model with no models_cache #when migrating #then do
58
294
  "",
59
295
  "[features.multi_agent_v2]",
60
296
  "enabled = false",
61
- "max_concurrent_threads_per_session = 1000",
297
+ "max_concurrent_threads_per_session = 6",
62
298
  "",
63
299
  ].join("\n"),
64
300
  );
@@ -73,7 +309,28 @@ test("#given gpt-5.6 session model with no models_cache #when migrating #then do
73
309
  assert.doesNotMatch(content, /^\s*max_threads\s*=/m);
74
310
  assert.doesNotMatch(content, /^\s*enabled\s*=\s*false/m);
75
311
  assert.match(content, /max_depth = 4/);
76
- assert.match(content, /max_concurrent_threads_per_session = 1000/);
312
+ assert.match(content, /max_concurrent_threads_per_session = 6/);
313
+ });
314
+
315
+ test("#given SessionStart config migration has no V2 cap #when migrating #then writes the conservative managed default", async () => {
316
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-subagent-limit-missing-cap-"));
317
+ const configPath = join(root, "config.toml");
318
+ await writeFile(
319
+ configPath,
320
+ [
321
+ 'model = "gpt-5.4"',
322
+ "",
323
+ "[features.multi_agent_v2]",
324
+ "enabled = false",
325
+ "",
326
+ ].join("\n"),
327
+ );
328
+
329
+ await migrateConfigFile(configPath);
330
+
331
+ const content = await readFile(configPath, "utf8");
332
+ assert.match(content, /max_concurrent_threads_per_session = 16/);
333
+ assert.doesNotMatch(content, /max_concurrent_threads_per_session = 1000/);
77
334
  });
78
335
 
79
336
  test("#given config without any model #when migrating #then does not introduce agents.max_threads", async () => {
@@ -89,7 +346,7 @@ test("#given config without any model #when migrating #then does not introduce a
89
346
  const content = await readFile(configPath, "utf8");
90
347
  assert.doesNotMatch(content, /^\s*max_threads\s*=/m);
91
348
  assert.match(content, /max_depth = 4/);
92
- assert.match(content, /max_concurrent_threads_per_session = 1000/);
349
+ assert.match(content, /max_concurrent_threads_per_session = 16/);
93
350
  });
94
351
 
95
352
  test("#given config without any model but an existing low cap #when migrating #then still raises the existing cap", async () => {
@@ -32,10 +32,11 @@ export const expectedSkills = [
32
32
  "visual-qa",
33
33
  ];
34
34
 
35
- export const hiddenSharedSkills = ["ultraresearch"];
36
-
37
35
  export const componentSkillSources = [
38
36
  ["comment-checker", "components/comment-checker/skills/comment-checker"],
37
+ ["lcx-contribute-bug-fix", "components/lcx/skills/lcx-contribute-bug-fix"],
38
+ ["lcx-doctor", "components/lcx/skills/lcx-doctor"],
39
+ ["lcx-report-bug", "components/lcx/skills/lcx-report-bug"],
39
40
  ["lsp", "components/lsp/skills/lsp"],
40
41
  ["rules", "components/rules/skills/rules"],
41
42
  ["teammode", "components/teammode/skills/teammode"],
@@ -126,22 +127,6 @@ prefixes when identity is needed.
126
127
  const reviewWorkCodexGatePattern = new RegExp(reviewWorkCodexGate.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
127
128
 
128
129
  export function removeCodexSkillOverlays(skillName, content) {
129
- if (skillName === "ulw-research") {
130
- return content
131
- .replace(
132
- ", any 'ulw' research wording,",
133
- ", the legacy alias 'ultraresearch', any 'ulw' research wording,",
134
- )
135
- .replace(
136
- "the word \"ulw-research\" (also `/ulw-research`, `$ulw-research`), ",
137
- "the word \"ulw-research\" (also `/ulw-research`, `$ulw-research`), the legacy alias \"ultraresearch\" (also `/ultraresearch`, `$ultraresearch`), ",
138
- )
139
- .replace(
140
- "answer those normally, and mention that `ulw-research` is available when a question would clearly benefit from it.",
141
- "answer those normally, and mention that `ulw-research` is available (legacy alias: `ultraresearch`) when a question would clearly benefit from it.",
142
- )
143
- .replace("# ULW-Research Synthesis: <query>", "# Ultraresearch Synthesis: <query>");
144
- }
145
130
  if (skillName === "start-work") {
146
131
  return content
147
132
  .replace(startWorkCodexCompletion, startWorkOriginalCompletion)
@@ -9,7 +9,6 @@ import {
9
9
  assertPackagedContentMatches,
10
10
  componentSkillSources,
11
11
  expectedSkills,
12
- hiddenSharedSkills,
13
12
  listSkillFiles,
14
13
  removeCodexCompatibilityGuidance,
15
14
  removeCodexSkillOverlays,
@@ -113,7 +112,6 @@ test("#given shared skill package source #when aggregate Codex shared skills are
113
112
  // when / then
114
113
  for (const skillName of sharedSkillNames) {
115
114
  if (componentSkillNames.has(skillName)) continue;
116
- if (hiddenSharedSkills.includes(skillName)) continue;
117
115
  const sharedContent = await readFile(join(sharedSkillsRoot, skillName, "SKILL.md"), "utf8");
118
116
  const aggregateContent = await readFile(join(aggregateSkillsRoot, skillName, "SKILL.md"), "utf8");
119
117
  assert.equal(
@@ -213,11 +211,8 @@ test("#given synced ulw-loop skill #when Codex hint metadata is inspected #then
213
211
  test("#given shipped Codex skill payloads #when legacy ultraresearch alias is inspected #then it is not packaged", async () => {
214
212
  // given
215
213
  const skillsRoot = join(root, "skills");
216
- const skillRoot = join(skillsRoot, "ultraresearch");
217
214
 
218
215
  // then
219
- await assert.rejects(readFile(join(skillRoot, "SKILL.md"), "utf8"), { code: "ENOENT" });
220
- await assert.rejects(readFile(join(skillRoot, "agents", "openai.yaml"), "utf8"), { code: "ENOENT" });
221
216
  await assertNoLegacyResearchAliasInTree(skillsRoot, "skills");
222
217
  for (const [skillName, sourcePath] of componentSkillSources) {
223
218
  await assertNoLegacyResearchAliasInTree(join(root, sourcePath), `components/${skillName}`);