oh-my-opencode 4.19.0 → 4.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.agents/command/omomomo.md +1 -1
  2. package/.agents/skills/omomomo/SKILL.md +1 -1
  3. package/.opencode/command/omomomo.md +1 -1
  4. package/README.ja.md +6 -6
  5. package/README.ko.md +6 -6
  6. package/README.md +6 -6
  7. package/README.ru.md +6 -6
  8. package/README.zh-cn.md +6 -6
  9. package/dist/agents/atlas/agent.d.ts +1 -1
  10. package/dist/agents/gpt-prompt-identity.d.ts +3 -0
  11. package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
  12. package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
  13. package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
  14. package/dist/cli/index.js +148 -94
  15. package/dist/cli-node/index.js +148 -94
  16. package/dist/config/schema/agent-overrides.d.ts +48 -48
  17. package/dist/config/schema/categories.d.ts +6 -6
  18. package/dist/config/schema/codegraph.d.ts +2 -0
  19. package/dist/config/schema/fallback-models.d.ts +5 -5
  20. package/dist/config/schema/oh-my-opencode-config.d.ts +50 -48
  21. package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
  22. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  23. package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
  24. package/dist/index.js +2612 -1473
  25. package/dist/oh-my-opencode.schema.json +11 -0
  26. package/dist/shared/omo-process-sweep.d.ts +18 -0
  27. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  28. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  29. package/dist/skills/ulw-plan/SKILL.md +20 -1
  30. package/dist/testing/create-plugin-module.d.ts +1 -0
  31. package/dist/tui.js +66 -56
  32. package/package.json +13 -13
  33. package/packages/git-bash-mcp/dist/cli.js +54 -8
  34. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +60 -0
  35. package/packages/lsp-core/src/lsp/client.ts +14 -1
  36. package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
  37. package/packages/lsp-core/src/mcp.ts +9 -0
  38. package/packages/lsp-daemon/dist/cli.js +319 -51
  39. package/packages/lsp-daemon/dist/client.js +136 -48
  40. package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
  41. package/packages/lsp-daemon/dist/daemon-client.js +4 -34
  42. package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
  43. package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
  44. package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
  45. package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
  46. package/packages/lsp-daemon/dist/daemon-server.js +5 -1
  47. package/packages/lsp-daemon/dist/index.js +137 -48
  48. package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
  49. package/packages/lsp-daemon/dist/proxy.js +1 -0
  50. package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
  51. package/packages/lsp-daemon/dist/version-reap.js +182 -0
  52. package/packages/lsp-tools-mcp/dist/cli.js +61 -10
  53. package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
  54. package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
  55. package/packages/lsp-tools-mcp/dist/tools.js +6 -1
  56. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  57. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +64 -8
  58. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  59. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  60. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
  61. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +555 -251
  62. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +178 -89
  63. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  64. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
  65. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +3 -1
  66. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
  67. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
  68. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +15 -6
  69. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +6 -2
  70. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
  71. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +148 -0
  72. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
  73. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
  74. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
  75. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
  76. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -1
  77. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
  78. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +41 -0
  79. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +109 -8
  80. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
  81. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +43 -0
  82. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  83. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  84. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  85. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  87. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  88. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  89. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
  90. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  91. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  92. package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
  93. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  94. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
  96. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
  97. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  98. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  99. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  100. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  101. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  102. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  103. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
  104. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
  105. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  106. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  107. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
  108. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  109. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
  110. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  111. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  112. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +20 -1
  113. package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
  114. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
  115. package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
  116. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
  117. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
  118. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
  119. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
  120. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  121. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  122. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
  123. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
  124. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
  125. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
  126. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
  127. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
  128. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
  129. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
  130. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
  131. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
  132. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
  133. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
  134. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
  135. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
  136. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  137. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
  138. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
  139. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
  140. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
  141. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
  142. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
  143. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
  144. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
  145. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
  146. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
  147. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  148. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  149. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
  150. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
  151. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
  152. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
  153. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
  154. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
  155. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
  156. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
  157. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
  158. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
  159. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
  160. package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
  161. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
  162. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
  163. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
  164. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
  165. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
  166. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
  167. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
  168. package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
  169. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
  170. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
  171. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
  172. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
  173. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
  174. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
  175. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
  176. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
  177. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
  178. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  184. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  185. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  186. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  187. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  188. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  189. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
  190. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  191. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
  192. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  193. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
  194. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  195. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  196. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  197. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  198. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  199. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  200. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  201. package/packages/omo-codex/plugin/package-lock.json +41 -41
  202. package/packages/omo-codex/plugin/package.json +1 -1
  203. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +43 -0
  204. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  205. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
  206. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +20 -1
  207. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
  208. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
  209. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
  210. package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
  211. package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
  212. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  213. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +35 -5
  214. package/packages/shared-skills/skills/ulw-plan/SKILL.md +20 -1
@@ -225,6 +225,32 @@ test("#given aggregate SessionStart hooks #when inspected #then LazyCodex auto-u
225
225
  assert(sessionStartCommands.some((command) => command.includes("scripts/auto-update.mjs")));
226
226
  });
227
227
 
228
+ test("#given aggregate SessionStart hooks #when inspected #then cold-start-prone hooks carry 15s timeout headroom", async () => {
229
+ // given
230
+ const manifests = await readAggregateHookManifests();
231
+
232
+ // when
233
+ const sessionStartHooks = manifests
234
+ .filter(({ hooks }) => hooks.hooks.SessionStart)
235
+ .flatMap(({ source, hooks }) =>
236
+ hooks.hooks.SessionStart.flatMap((group) =>
237
+ group.hooks.map((handler) => ({ source, command: handler.command, timeout: handler.timeout })),
238
+ ),
239
+ );
240
+ const coldStartHooks = sessionStartHooks.filter(
241
+ ({ command }) =>
242
+ command.includes("components/telemetry/dist/cli.js") ||
243
+ command.includes("scripts/auto-update.mjs") ||
244
+ command.includes("components/codegraph/dist/cli.js"),
245
+ );
246
+
247
+ // then
248
+ assert.equal(coldStartHooks.length, 3);
249
+ for (const hook of coldStartHooks) {
250
+ assert.equal(hook.timeout, 15, `${hook.source} must carry timeout 15 for cold-start headroom`);
251
+ }
252
+ });
253
+
228
254
  test("#given aggregate PostToolUse hooks #when inspected #then CodeGraph init guidance is registered for CodeGraph tools", async () => {
229
255
  // given
230
256
  const commandHooks = await readAggregateCommandHooks();
@@ -127,6 +127,47 @@ test("#given a completed first run #when the worker setup runs again #then confi
127
127
  });
128
128
  });
129
129
 
130
+ test("#given a config.toml that already declares [agents.explorer] at a different path (Orca mirror) #when the worker setup runs #then no second colliding registration is added for that role", async () => {
131
+ await withSetupFixture(async (fixture) => {
132
+ const orcaMirrorPath = "/orca-mirrored-home/.codex/agents/explorer.toml";
133
+ await writeFile(
134
+ join(fixture.codexHome, "config.toml"),
135
+ `[marketplaces.sisyphuslabs]\n${MARKETPLACE_SOURCE_LINE}\n\n[agents.explorer]\nconfig_file = "${orcaMirrorPath}"\n`,
136
+ );
137
+
138
+ const outcome = await runWorkerSetup(setupOptions(fixture));
139
+
140
+ assert.deepEqual(outcome.degraded, []);
141
+ const config = await readConfig(fixture);
142
+ assert.equal(config.match(/\[agents\.explorer\]/g)?.length, 1, "exactly one [agents.explorer] block");
143
+ assert.ok(
144
+ config.includes(`[agents.explorer]\nconfig_file = "${orcaMirrorPath}"`),
145
+ "the pre-existing mirrored entry stays untouched",
146
+ );
147
+ assert.ok(
148
+ !config.includes('config_file = "./agents/explorer.toml"'),
149
+ "no colliding ./agents registration for the mirrored role",
150
+ );
151
+ assert.match(config, /\[agents\.metis\]\nconfig_file = "\.\/agents\/metis\.toml"/);
152
+ assert.equal(
153
+ await readFile(join(fixture.codexHome, "agents", "explorer.toml"), "utf8"),
154
+ BUNDLED_EXPLORER_TOML,
155
+ "the linked toml is still staged for Codex directory discovery",
156
+ );
157
+ });
158
+ });
159
+
160
+ test("#given a config.toml with no pre-existing agent entries #when the worker setup runs #then all bundled registrations are written", async () => {
161
+ await withSetupFixture(async (fixture) => {
162
+ const outcome = await runWorkerSetup(setupOptions(fixture));
163
+
164
+ assert.deepEqual(outcome.degraded, []);
165
+ const config = await readConfig(fixture);
166
+ assert.match(config, /\[agents\.explorer\]\nconfig_file = "\.\/agents\/explorer\.toml"/);
167
+ assert.match(config, /\[agents\.metis\]\nconfig_file = "\.\/agents\/metis\.toml"/);
168
+ });
169
+ });
170
+
130
171
  test("#given a package-relative CodeGraph MCP path #when worker setup runs #then the path is stamped absolute", async () => {
131
172
  await withSetupFixture(async (fixture) => {
132
173
  await writeFile(
@@ -5903,7 +5903,7 @@ var package_default;
5903
5903
  var init_package = __esm(() => {
5904
5904
  package_default = {
5905
5905
  name: "@oh-my-opencode/omo-codex",
5906
- version: "4.19.0",
5906
+ version: "4.19.1",
5907
5907
  type: "module",
5908
5908
  private: true,
5909
5909
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -6429,7 +6429,7 @@ function whereCommand(command) {
6429
6429
  }
6430
6430
  }
6431
6431
  // packages/omo-codex/src/install/codex-process.ts
6432
- var WINDOWS_CMD_SHIM_COMMANDS = new Set(["npm", "npx"]);
6432
+ var WINDOWS_CMD_SHIM_COMMANDS = new Set(["codex", "npm", "npx"]);
6433
6433
  function resolveRunCommandInvocation(command, args, platform = process.platform) {
6434
6434
  if (platform !== "win32" || !WINDOWS_CMD_SHIM_COMMANDS.has(command.toLowerCase())) {
6435
6435
  return { command, args: [...args] };
@@ -7068,6 +7068,7 @@ async function rewriteCachedPackageLocalFileDependencies(pluginRoot, sourceRoot)
7068
7068
  const packageJsonPaths = [];
7069
7069
  await collectPackageJsonPaths(pluginRoot, pluginRoot, packageJsonPaths);
7070
7070
  const packageLock = await readPackageLock(pluginRoot);
7071
+ let rewroteAnyPackageJson = false;
7071
7072
  for (const packageJsonPath of packageJsonPaths) {
7072
7073
  const raw = await readFile5(packageJsonPath, "utf8");
7073
7074
  const parsed = JSON.parse(raw);
@@ -7103,13 +7104,16 @@ async function rewriteCachedPackageLocalFileDependencies(pluginRoot, sourceRoot)
7103
7104
  changed = true;
7104
7105
  }
7105
7106
  }
7106
- if (changed)
7107
+ if (changed) {
7107
7108
  await writeFile2(packageJsonPath, `${JSON.stringify(parsed, null, "\t")}
7108
7109
  `);
7110
+ rewroteAnyPackageJson = true;
7111
+ }
7109
7112
  }
7110
7113
  if (packageLock.changed)
7111
7114
  await writeFile2(packageLock.path, `${JSON.stringify(packageLock.value, null, "\t")}
7112
7115
  `);
7116
+ return rewroteAnyPackageJson;
7113
7117
  }
7114
7118
  async function readPackageLock(pluginRoot) {
7115
7119
  const path = join8(pluginRoot, "package-lock.json");
@@ -7530,10 +7534,11 @@ async function installCachedPlugin(input) {
7530
7534
  await rm4(tempPath, { recursive: true, force: true });
7531
7535
  try {
7532
7536
  await copyDirectory(input.sourcePath, tempPath);
7533
- await rewriteCachedPackageLocalFileDependencies(tempPath, input.sourcePath);
7537
+ const rewroteLocalFileDependencies = await rewriteCachedPackageLocalFileDependencies(tempPath, input.sourcePath);
7534
7538
  await copyBundledMcpRuntimeDists({ pluginRoot: tempPath, sourceRoot: input.sourcePath });
7535
7539
  await copyRootRuntimeDists({ pluginRoot: tempPath, sourcePath: input.sourcePath });
7536
- await maybeRunNpmInstall(tempPath, input.runCommand, npmInstallEnv, ["ci", "--omit=dev"]);
7540
+ const installArgs = rewroteLocalFileDependencies ? ["install", "--omit=dev", "--no-audit", "--no-fund"] : ["ci", "--omit=dev"];
7541
+ await maybeRunNpmInstall(tempPath, input.runCommand, npmInstallEnv, installArgs);
7537
7542
  await removeCachedManagedNpmBinShims(tempPath);
7538
7543
  if (input.buildSource === false)
7539
7544
  await maybeRunNpmSyncSkills(tempPath, input.runCommand, env);
@@ -9405,6 +9410,10 @@ var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
9405
9410
  {
9406
9411
  previous: { model: "gpt-5.6-sol", effort: "xhigh" },
9407
9412
  current: { model: "gpt-5.6-sol", effort: "max" }
9413
+ },
9414
+ {
9415
+ previous: { model: "gpt-5.6-sol", effort: "max" },
9416
+ current: { model: "gpt-5.6-sol", effort: "high" }
9408
9417
  }
9409
9418
  ]
9410
9419
  ],
@@ -9414,6 +9423,37 @@ var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
9414
9423
  {
9415
9424
  previous: { model: "gpt-5.6-sol", effort: "high" },
9416
9425
  current: { model: "gpt-5.6-luna", effort: "max" }
9426
+ },
9427
+ {
9428
+ previous: { model: "gpt-5.6-luna", effort: "max" },
9429
+ current: { model: "gpt-5.6-terra", effort: "high" }
9430
+ }
9431
+ ]
9432
+ ],
9433
+ [
9434
+ "lazycodex-worker-high",
9435
+ [
9436
+ {
9437
+ previous: { model: "gpt-5.6-sol", effort: "max" },
9438
+ current: { model: "gpt-5.6-sol", effort: "medium" }
9439
+ }
9440
+ ]
9441
+ ],
9442
+ [
9443
+ "lazycodex-code-reviewer",
9444
+ [
9445
+ {
9446
+ previous: { model: "gpt-5.6-sol", effort: "xhigh" },
9447
+ current: { model: "gpt-5.6-terra", effort: "medium" }
9448
+ }
9449
+ ]
9450
+ ],
9451
+ [
9452
+ "lazycodex-clone-fidelity-reviewer",
9453
+ [
9454
+ {
9455
+ previous: { model: "gpt-5.6-sol", effort: "xhigh" },
9456
+ current: { model: "gpt-5.6-terra", effort: "high" }
9417
9457
  }
9418
9458
  ]
9419
9459
  ],
@@ -9432,6 +9472,10 @@ var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
9432
9472
  {
9433
9473
  previous: { model: "gpt-5.6-sol", effort: "xhigh" },
9434
9474
  current: { model: "gpt-5.6-sol", effort: "high" }
9475
+ },
9476
+ {
9477
+ previous: { model: "gpt-5.6-sol", effort: "high" },
9478
+ current: { model: "gpt-5.6-sol", effort: "low" }
9435
9479
  }
9436
9480
  ]
9437
9481
  ]
@@ -94,7 +94,10 @@ test("#given local marketplace #when installing #then copies versioned plugins a
94
94
  ["npm", "run build", pluginRoot],
95
95
  ]);
96
96
  assert.equal(commandLog[2][0], "npm");
97
- assert.equal(commandLog[2][1], "ci --omit=dev");
97
+ // The @example/shared-lsp file: dep points outside the plugin, so the cache
98
+ // installer rewrites package.json and switches to `npm install` to avoid the
99
+ // npm ci lock-desync (lazycodex#137).
100
+ assert.equal(commandLog[2][1], "install --omit=dev --no-audit --no-fund");
98
101
  assert.equal(commandLog[2][2].startsWith(join(codexHome, "plugins", "cache", "debug-marketplace", "alpha", ".tmp-1.2.3-")), true);
99
102
 
100
103
  const config = await readFile(join(codexHome, "config.toml"), "utf8");
@@ -0,0 +1,87 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test"
2
+ import { spawnSync } from "node:child_process"
3
+ import { copyFileSync, mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs"
4
+ import { createRequire } from "node:module"
5
+ import { tmpdir } from "node:os"
6
+ import { dirname, join } from "node:path"
7
+
8
+ // Regression for lazycodex#111: the script must resolve `typescript` from the
9
+ // caller project (cwd), not from the script's own location, so it works when
10
+ // executed from an installed `~/.codex/...` skill cache.
11
+
12
+ const scriptSource = join(import.meta.dir, "check-no-excuse-rules.ts")
13
+ const repoRequire = createRequire(import.meta.url)
14
+ const typescriptPackageDir = dirname(repoRequire.resolve("typescript/package.json"))
15
+
16
+ let tempRoot = ""
17
+ let cachedScript = ""
18
+ let callerDir = ""
19
+ let callerWithoutTypescriptDir = ""
20
+
21
+ function runNoExcuse(cwd: string, target: string) {
22
+ return spawnSync(process.execPath, ["--no-install", cachedScript, target], {
23
+ cwd,
24
+ encoding: "utf8",
25
+ timeout: 60_000,
26
+ })
27
+ }
28
+
29
+ describe("#given the no-excuse script is executed from an installed ~/.codex-style skill cache", () => {
30
+ beforeAll(() => {
31
+ // given a cache copy of the script outside any project, and two caller projects:
32
+ // one providing node_modules/typescript, one without typescript at all
33
+ tempRoot = mkdtempSync(join(tmpdir(), "no-excuse-cache-repro-"))
34
+ const cacheDir = join(tempRoot, ".codex", "skills", "programming", "scripts", "typescript")
35
+ mkdirSync(cacheDir, { recursive: true })
36
+ cachedScript = join(cacheDir, "check-no-excuse-rules.ts")
37
+ copyFileSync(scriptSource, cachedScript)
38
+
39
+ callerDir = join(tempRoot, "caller-project")
40
+ mkdirSync(join(callerDir, "node_modules"), { recursive: true })
41
+ symlinkSync(typescriptPackageDir, join(callerDir, "node_modules", "typescript"), "junction")
42
+ writeFileSync(join(callerDir, "clean.ts"), "export const answer: number = 42\n")
43
+ writeFileSync(join(callerDir, "violating.ts"), "const x = foo as any\nexport default x\n")
44
+
45
+ callerWithoutTypescriptDir = join(tempRoot, "caller-without-typescript")
46
+ mkdirSync(callerWithoutTypescriptDir, { recursive: true })
47
+ writeFileSync(join(callerWithoutTypescriptDir, "clean.ts"), "export const answer: number = 42\n")
48
+ })
49
+
50
+ afterAll(() => {
51
+ rmSync(tempRoot, { recursive: true, force: true })
52
+ })
53
+
54
+ // A generous timeout: the first run does a cold TypeScript program load in a
55
+ // spawned subprocess, which can exceed bun test's 5s default on a cold cache
56
+ // (matches the 60s spawnSync ceiling). This bounds the subprocess, it does not
57
+ // wait on wall-clock time as behavior.
58
+ test("#when the caller project provides typescript #then it resolves the caller's typescript and exits 0", () => {
59
+ // when no-excuse runs from the cache copy against the caller project
60
+ const result = runNoExcuse(callerDir, "clean.ts")
61
+
62
+ // then the caller's own typescript is used and the clean file passes
63
+ expect(result.error).toBeUndefined()
64
+ expect(result.status).toBe(0)
65
+ expect(result.stdout).toContain("No violations in 1 file(s).")
66
+ }, 60_000)
67
+
68
+ test("#when a checked file violates the rules #then violations are still reported with exit 1", () => {
69
+ // when no-excuse runs against a file containing `as any`
70
+ const result = runNoExcuse(callerDir, "violating.ts")
71
+
72
+ // then the existing CLI behavior is unchanged
73
+ expect(result.error).toBeUndefined()
74
+ expect(result.status).toBe(1)
75
+ expect(result.stderr).toContain("[no-any-assertion]")
76
+ }, 60_000)
77
+
78
+ test("#when the caller project genuinely lacks typescript #then it fails with a clear error and exit 2", () => {
79
+ // when no-excuse runs from a caller project with no local typescript
80
+ const result = runNoExcuse(callerWithoutTypescriptDir, "clean.ts")
81
+
82
+ // then it reports the resolution problem instead of crashing mid-analysis
83
+ expect(result.error).toBeUndefined()
84
+ expect(result.status).toBe(2)
85
+ expect(result.stderr).toContain('cannot resolve "typescript" from the caller project')
86
+ }, 60_000)
87
+ })
@@ -19,6 +19,10 @@
19
19
  * Usage:
20
20
  * bun run scripts/check-no-excuse-rules.ts <file-or-dir>...
21
21
  *
22
+ * The `typescript` package is resolved from the caller project (process.cwd()),
23
+ * not from this script's location, so the script works when executed from an
24
+ * installed skill-cache path (e.g. ~/.codex/...) against a project checkout.
25
+ *
22
26
  * Exit codes:
23
27
  * 0 - no violations
24
28
  * 1 - violations found
@@ -26,9 +30,35 @@
26
30
  */
27
31
 
28
32
  import fs from "node:fs"
33
+ import { createRequire } from "node:module"
29
34
  import path from "node:path"
30
35
  import process from "node:process"
31
- import ts from "typescript"
36
+ import type * as tsTypes from "typescript"
37
+
38
+ type TsModule = typeof import("typescript")
39
+
40
+ function loadTypescriptFromCaller(): TsModule {
41
+ // A static `import ts from "typescript"` resolves from this script's location —
42
+ // an installed skill-cache path (e.g. ~/.codex/...) with no node_modules of its
43
+ // own — and fails even when the checked project has typescript. Resolve from the
44
+ // caller project (cwd) instead. When the caller has no local typescript, Bun
45
+ // falls back to a version-only stub from its global install cache instead of
46
+ // throwing, so the loaded module's API shape is verified as well.
47
+ const callerRequire = createRequire(path.join(process.cwd(), "no-excuse-anchor.cjs"))
48
+ try {
49
+ const loaded: Partial<TsModule> = callerRequire("typescript")
50
+ if (typeof loaded.createSourceFile === "function") return loaded as TsModule
51
+ } catch { // no-excuse-ok: catch
52
+ // fall through to the clear error below
53
+ }
54
+ console.error(
55
+ `error: cannot resolve "typescript" from the caller project (${process.cwd()}). ` +
56
+ "Install it in the project being checked (e.g. `bun add -d typescript`) and re-run.",
57
+ )
58
+ process.exit(2)
59
+ }
60
+
61
+ const ts: TsModule = loadTypescriptFromCaller()
32
62
 
33
63
  type RuleId =
34
64
  | "no-any-assertion"
@@ -95,7 +125,7 @@ function discoverFiles(inputs: string[]): string[] {
95
125
  return files
96
126
  }
97
127
 
98
- function getLineText(sourceFile: ts.SourceFile, line: number): string {
128
+ function getLineText(sourceFile: tsTypes.SourceFile, line: number): string {
99
129
  const lineStarts = sourceFile.getLineStarts()
100
130
  const start = lineStarts[line]
101
131
  const end = line + 1 < lineStarts.length ? lineStarts[line + 1] : sourceFile.getEnd()
@@ -107,17 +137,17 @@ function analyzeFile(filePath: string): Violation[] {
107
137
  const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true)
108
138
  const violations: Violation[] = []
109
139
 
110
- function pos(node: ts.Node): { line: number; column: number } {
140
+ function pos(node: tsTypes.Node): { line: number; column: number } {
111
141
  const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))
112
142
  return { line: line + 1, column: character + 1 }
113
143
  }
114
144
 
115
- function lineHasOptOut(node: ts.Node): boolean {
145
+ function lineHasOptOut(node: tsTypes.Node): boolean {
116
146
  const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))
117
147
  return OPT_OUT_RE.test(getLineText(sourceFile, line))
118
148
  }
119
149
 
120
- function visit(node: ts.Node): void {
150
+ function visit(node: tsTypes.Node): void {
121
151
  // ── as any / as unknown ──
122
152
  if (ts.isAsExpression(node)) {
123
153
  const typeText = node.type.getText(sourceFile)
@@ -13,11 +13,30 @@ You are **Prometheus**, a planning consultant. You turn a vague or large request
13
13
 
14
14
  Outcome-first: explore a lot, ask few sharp questions - or none, when the intent is fuzzy (see routing) - and stop the moment the plan is done.
15
15
 
16
+ ## MANDATORY OPENING ANNOUNCEMENT
17
+
18
+ The FIRST user-visible line of the turn that activates this skill MUST be exactly:
19
+
20
+ `ULW-PLAN MODE ENABLED!`
21
+
22
+ If another active mode mandates its own first line (ultrawork does), print that line first and this marker on the next line - both contracts stay satisfied.
23
+
24
+ Directly under the marker, before any exploration, state the working contract once, in your own words, carrying ALL of these commitments:
25
+
26
+ 1. **Persona + no-implementation pledge** - from now on you work as Prometheus, a planning consultant, and you will never start implementation - no product-code edits, no implementer subagents - until the user explicitly says okay; even then, approval authorizes writing the plan only, and execution starts in a separate worker session (e.g. `$start-work`).
27
+ 2. **Workflow preview** - the order of what happens next: parallel read-only exploration (plus outside research when the repo cannot answer) until the open unknowns are resolved; the intent verdict from INTENT ROUTING, announced; questions to the user ONLY when a genuine owner-decision survives exploration - or when exploration and research both come back empty on a fork the plan cannot proceed without; then the approval brief, and the plan is written only after the explicit okay.
28
+
29
+ Example opening (adapt the wording, keep every commitment):
30
+
31
+ > ULW-PLAN MODE ENABLED!
32
+ > From now on I am working as Prometheus, a planning consultant. I will not start any implementation until you explicitly say okay - and approval authorizes writing the plan only; execution starts separately (e.g. `$start-work`).
33
+ > Next, in order: (1) parallel read-only exploration and research, (2) intent verdict announced (CLEAR or UNCLEAR, plus whether high-accuracy review is required), (3) questions only for the forks exploration cannot settle - or where research finds nothing on a blocking decision, (4) approval brief, then (5) the plan is written after your okay.
34
+
16
35
  ## INTENT ROUTING - pick ONE intent reference
17
36
 
18
37
  **Review modifiers are a gate trigger, not a style cue.** If the user says "high accuracy", "ultra high accuracy", "고정밀", "deep review", or equivalent - in ANY turn, even appended to a follow-up question and even after the plan already exists - set `review_required: true` in the draft: the dual high-accuracy review (native `momus` + the independent Oracle review) is now REQUIRED before handoff, and if the plan already exists you run it this same turn. Answering the current question more carefully does NOT satisfy it. This does NOT choose CLEAR/UNCLEAR and does NOT suppress interview.
19
38
 
20
- After grounding, make ONE judgment, record `intent: clear|unclear` plus `review_required`, **ANNOUNCE both to the user in one line**, then load ONE intent reference (you ALSO read `references/full-workflow.md` for the shared mechanics - see below). The test keys on whether the desired **OUTCOME** is clear, NOT on request length. The announcement is the user's first signal of whether they will be interviewed and whether high-accuracy review is already requested - never skip it.
39
+ After grounding, make ONE judgment, record `intent: clear|unclear` plus `review_required`, **ANNOUNCE both to the user in one line**, then load ONE intent reference (you ALSO read `references/full-workflow.md` for the shared mechanics - see below). The test keys on whether the desired **OUTCOME** is clear, NOT on request length. This verdict line and the opening announcement above are the two mandatory user-visible signals of a planning session - it tells the user whether they will be interviewed and whether high-accuracy review is already requested; never skip either.
21
40
 
22
41
  > "Intent: **CLEAR**, review required - you specified the endpoint and asked for high accuracy. I will ask only the genuine forks, then run the high-accuracy review after approval."
23
42
  > "Intent: **UNCLEAR**, review required - 'make auth better' is open-ended and you asked for high accuracy. I will choose best-practice defaults, then run the high-accuracy review automatically."