oh-my-opencode 4.19.1 → 4.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.ja.md +2 -2
  2. package/README.ko.md +2 -2
  3. package/README.md +2 -2
  4. package/README.ru.md +2 -2
  5. package/README.zh-cn.md +2 -2
  6. package/dist/agents/atlas/agent.d.ts +4 -2
  7. package/dist/agents/explore.d.ts +4 -2
  8. package/dist/agents/hephaestus/agent.d.ts +4 -2
  9. package/dist/agents/librarian.d.ts +4 -2
  10. package/dist/agents/metis.d.ts +4 -2
  11. package/dist/agents/momus.d.ts +3 -2
  12. package/dist/agents/multimodal-looker.d.ts +4 -2
  13. package/dist/agents/oracle.d.ts +4 -2
  14. package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -0
  15. package/dist/agents/sisyphus/index.d.ts +2 -0
  16. package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
  17. package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
  18. package/dist/agents/types.d.ts +2 -2
  19. package/dist/cli/index.js +23454 -19200
  20. package/dist/cli-node/index.js +23454 -19200
  21. package/dist/config/schema/agent-names.d.ts +26 -26
  22. package/dist/config/schema/agent-overrides.d.ts +400 -400
  23. package/dist/config/schema/browser-automation.d.ts +2 -2
  24. package/dist/config/schema/categories.d.ts +36 -36
  25. package/dist/config/schema/commands.d.ts +2 -2
  26. package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
  27. package/dist/config/schema/experimental.d.ts +1 -1
  28. package/dist/config/schema/fallback-models.d.ts +25 -25
  29. package/dist/config/schema/hooks.d.ts +43 -43
  30. package/dist/config/schema/internal/permission.d.ts +9 -9
  31. package/dist/config/schema/keyword-detector.d.ts +6 -6
  32. package/dist/config/schema/oh-my-opencode-config.d.ts +402 -402
  33. package/dist/config/schema/tmux.d.ts +6 -6
  34. package/dist/create-hooks.d.ts +35 -35
  35. package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
  36. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  37. package/dist/features/claude-tasks/types.d.ts +4 -4
  38. package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
  39. package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
  40. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
  41. package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
  42. package/dist/features/tmux-subagent/index.d.ts +1 -0
  43. package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
  44. package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
  45. package/dist/help/schema/acp.d.ts +3 -3
  46. package/dist/help/schema/doctor.d.ts +4 -4
  47. package/dist/help/schema/status.d.ts +3 -3
  48. package/dist/hooks/goal/types.d.ts +5 -5
  49. package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
  50. package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
  51. package/dist/hooks/start-work/worktree-block.d.ts +5 -0
  52. package/dist/index.js +25231 -20301
  53. package/dist/mcp/types.d.ts +3 -3
  54. package/dist/oh-my-opencode.schema.json +1 -1
  55. package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
  56. package/dist/plugin/command-execute-before.d.ts +3 -3
  57. package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
  58. package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
  59. package/dist/shared/tmux/tmux-utils.d.ts +1 -1
  60. package/dist/shared/typescript-native-source-parser.d.ts +7 -0
  61. package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
  62. package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  63. package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
  64. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  65. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  66. package/dist/skills/debugging/SKILL.md +2 -1
  67. package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  68. package/dist/skills/programming/SKILL.md +11 -1
  69. package/dist/skills/programming/references/logging.md +6 -1
  70. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  71. package/dist/skills/start-work/SKILL.md +12 -2
  72. package/dist/skills/ulw-plan/SKILL.md +1 -1
  73. package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
  74. package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
  75. package/dist/tools/task/types.d.ts +10 -10
  76. package/dist/tui.js +23468 -19218
  77. package/package.json +14 -14
  78. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +2 -2
  79. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  80. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +8 -4
  81. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  82. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  83. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +296 -206
  84. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +126 -86
  85. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +21 -42
  87. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +3 -4
  88. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +12 -23
  89. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +5 -0
  90. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +33 -5
  91. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +6 -1
  92. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +6 -0
  93. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -0
  94. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +5 -5
  95. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +1 -0
  96. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +24 -13
  97. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +58 -64
  98. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  99. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  100. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  101. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  102. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  103. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  104. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  105. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  106. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  107. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  108. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  109. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  110. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  111. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  112. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  113. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  114. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  115. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  116. package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
  117. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  118. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  119. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
  120. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +1 -1
  121. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
  122. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
  123. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
  124. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  125. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  126. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -1
  127. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  128. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  129. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  130. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  131. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  132. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  133. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  134. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  135. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  136. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  137. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  138. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  139. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  140. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  141. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  142. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  143. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  144. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  145. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  146. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  147. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  148. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  149. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  150. package/packages/omo-codex/plugin/package-lock.json +13 -13
  151. package/packages/omo-codex/plugin/package.json +1 -1
  152. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +10 -9
  153. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
  154. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  155. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
  156. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  157. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  158. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
  159. package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  160. package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
  161. package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
  162. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  163. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
  164. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
  165. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -1
  166. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +1 -1
  167. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
  168. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
  169. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
  170. package/packages/omo-codex/scripts/install-dist/install-local.mjs +1 -1
  171. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
  172. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  173. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
  174. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  175. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  176. package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
  177. package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  178. package/packages/shared-skills/skills/programming/SKILL.md +11 -1
  179. package/packages/shared-skills/skills/programming/references/logging.md +6 -1
  180. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  181. package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
  182. package/packages/shared-skills/skills/ulw-plan/SKILL.md +1 -1
  183. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
  184. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: debugging
3
- description: "MUST USE for any real runtime debugging across ANY language or binary — crashes, silent failures, wrong responses, stuck processes, memory leaks, async misbehavior, unexplained timing, reverse engineering. Runs a hypothesis-driven loop: form ≥3 hypotheses, investigate in parallel, after 2 failed rounds spawn Oracles from orthogonal angles, confirm root cause, lock with a failing test, fix minimally, QA by actually USING the system, scrub artifacts. The actual HOW lives in `references/` — READ THEM. Triggers: 'debug this', 'why is X not working', 'hanging', 'attach a debugger', 'reverse engineer', 'pwndbg', 'gdb', 'lldb', 'node inspect', 'tsx debug', 'pdb', 'dlv', 'delve', 'rust-gdb', 'set a breakpoint', 'context window exploded', 'why is the response empty', 'attach the debugger', 'debug it', 'why is this happening', 'trace this bug', 'reproduce and fix', 'silent failure', 'HTTP 200 but empty', 'why did it stop', 'inspect the binary', 'reverse engineering', 'playwright'."
3
+ description: "MUST USE for any real runtime debugging across ANY language or binary — crashes, silent failures, wrong responses, stuck processes, memory leaks, async misbehavior, unexplained timing, reverse engineering. Runs a hypothesis-driven loop: form ≥3 hypotheses, investigate in parallel, after 2 failed rounds spawn Oracles from orthogonal angles, confirm root cause, lock with a failing test, fix minimally, QA by actually USING the system, scrub artifacts. The actual HOW lives in `references/` — READ THEM. Triggers: 'debug this', 'why is X not working', 'hanging', 'attach a debugger', 'reverse engineer', 'pwndbg', 'gdb', 'lldb', 'node inspect', 'tsx debug', 'pdb', 'dlv', 'delve', 'rust-gdb', 'set a breakpoint', 'context window exploded', 'why is the response empty', 'why is this happening', 'trace this bug', 'reproduce and fix', 'silent failure', 'HTTP 200 but empty', 'why did it stop', 'inspect the binary', 'playwright', 'flaky test', 'fails intermittently', 'passes in isolation', 'only fails in CI'."
4
4
  ---
5
5
 
6
6
  # Debugging
@@ -84,6 +84,7 @@ These are not phases — read them when the situation calls for them:
84
84
 
85
85
  | Situation | Reference |
86
86
  |---|---|
87
+ | The failure is intermittent — fails sometimes, a different test each run, passes in isolation, or only fails in CI | 📖 **[references/methodology/03-flaky-triage.md](references/methodology/03-flaky-triage.md)** — read BEFORE Phase 2; the failure signature usually collapses the search space in one round |
87
88
  | You cannot run the actual operation (paid API, blocked network, missing hardware) but still need runtime evidence | 📖 **[references/methodology/partial-runtime-evidence.md](references/methodology/partial-runtime-evidence.md)** |
88
89
  | You're about to declare an extraction / audit / reverse-engineering task done and want a skeptical pass | 📖 **[references/methodology/partial-runtime-evidence.md#verification-oracle-pattern-for-non-debug-tasks](references/methodology/partial-runtime-evidence.md#verification-oracle-pattern-for-non-debug-tasks)** (Verification Oracle is *not* the same as Oracle Triple — read the file) |
89
90
 
@@ -0,0 +1,47 @@
1
+ # Intermittent / Flaky Failure Triage
2
+
3
+ Read this when a failure does not reproduce on every run — "fails sometimes", "a different test each run", "passes in isolation", "only fails in CI". Do not enter the hypothesis loop blind: **intermittence itself is evidence.** This triage usually collapses the search space in one round, before Phase 2 hypothesis formation.
4
+
5
+ ---
6
+
7
+ ## Step 1 — Capture the failure signature (three cheap reruns)
8
+
9
+ Run these before forming any hypothesis. Journal each result.
10
+
11
+ | Rerun | Command shape | Question it answers |
12
+ |---|---|---|
13
+ | Same scope, same command | exactly what just failed | Does the SAME test fail again, or a different one? |
14
+ | Failing test in isolation | single file / test filter | Does it pass alone? |
15
+ | Full scope on a quiet machine | stop concurrent builds, suites, background agents first | Does the whole suite go green when nothing else runs? |
16
+ | (When order is suspect) shuffled | `-shuffle=on` / `pytest-randomly` / runner's random seed | Does a specific order reproduce it? Record the seed. |
17
+
18
+ ## Step 2 — Read the signature
19
+
20
+ | Signature | Dominant hypothesis | Next move |
21
+ |---|---|---|
22
+ | Same test fails intermittently, everywhere | Real race in the code under test, or an async test bug (fixed sleep, unawaited promise, poll-for-time) | Standard phase loop from `02-investigate.md`; reproduce deterministically by subscribing to the completion event or injecting a clock |
23
+ | **A different test/file each run; each passes in isolation; quiet machine is green** | **Environment contention between concurrent runs — not the code** | Step 3 checklist |
24
+ | Always the same test, but only in the full suite; isolation green | Test-order dependence / fixture leak (unreset module state, leaked env var, shared singleton) | Bisect with the shuffle seed; find the test that leaks, fix its teardown |
25
+ | Fails only on CI, never locally | Resource ceilings (slower disk/CPU → timeouts), different parallelism defaults, container clock | Reproduce locally under constraint (`taskset`, low `--maxWorkers`); raise the *signal* not the sleep |
26
+ | Green on plain rerun of the same commit | Still a flake — classify it with this table before ignoring it; an unclassified flake is a hidden bug report | Step 1 again with journaling |
27
+
28
+ ## Step 3 — Concurrent-run contention checklist
29
+
30
+ The classic modern cause: **two checkouts or worktrees of the same repo — or one checkout plus a background agent — running suites at the same time while sharing a global mutable resource.** Multi-agent workstations make this the default failure mode, not an exotic one. Check each:
31
+
32
+ - **Shared tmp roots** — a sandbox/cache dir derived from a *fixed* tmpdir path (`$TMPDIR/<project>-fixed-name`) instead of a per-run `mktemp`. Both runs read/write the same tree; the loser sees half-deleted state.
33
+ - **Fixed ports** — hardcoded listen ports in test servers. Two suites race to bind; the loser gets 404/ECONNREFUSED mid-run, in whichever file happened to be running.
34
+ - **Global env / config mutation** — tests writing process-external state (dotfiles, shared config, global env) the other run reads.
35
+ - **Shared containers / databases** — same-named containers, same schema, same volume.
36
+ - **Caches and locks** — package-manager caches, lockfiles, `.git` index contention.
37
+
38
+ Evidence to capture while it is live: `lsof -i :<port>` during the failure window, a listing of the shared tmp path, a process list showing the concurrent runners.
39
+
40
+ ## Step 4 — Fix policy
41
+
42
+ - **Environment contention** → fix the **test infrastructure**, never the individual test: namespace every suite-global resource per run — `mktemp` for roots, port `0`/ephemeral allocation, unique container names. The bar: *two checkouts of this repo running the suite concurrently must not interfere.* (The programming skill's test-isolation rules own this bar.)
43
+ - **Order dependence** → find the leaking fixture via the recorded shuffle seed; reset at teardown; re-run shuffled until the seed class is clean.
44
+ - **Real race** → normal phase loop (`02-investigate.md` onward); the fix ships with a failing-first test that reproduces deterministically.
45
+ - **Forbidden regardless of cause**: retry wrappers around the test, enlarged sleeps, `.retry(N)`, quarantining, or deleting the test. Each one buries a bug report.
46
+
47
+ A flake you classified but did not fix is a **finding to report**, not to hide: journal the signature, the evidence, and the classification, and say it in your final report.
@@ -102,7 +102,7 @@ Mocks are a last resort, not a default. The priority order:
102
102
  - **Accurate**: the test fails for the bug it names, and only that bug. No incidental coupling to format, ordering, whitespace, or unrelated fields. Assert on the *contract*, not on the dump.
103
103
  - **Efficient**: the whole unit suite runs in < 30 seconds on a developer laptop. The whole integration suite in < 5 minutes. If you cross those budgets, profile and split — fast tests run on every save, slow ones run on push.
104
104
  - **Deterministic**: no `sleep`, no wall-clock dependence, no order dependence (`-shuffle=on`, pytest-randomly, vitest random seed). Inject a `Clock`. Subscribe to the event, do not poll for it. Time-based flake is a bug, not a test issue.
105
- - **Isolated**: every test starts from a known fixture and tears down. `t.TempDir()`, `t.Setenv()`, transactional rollback for DB tests. Two tests passing individually but failing together is a fixture leak — fix it immediately.
105
+ - **Isolated**: every test starts from a known fixture and tears down. `t.TempDir()`, `t.Setenv()`, transactional rollback for DB tests. Two tests passing individually but failing together is a fixture leak — fix it immediately. Isolation extends **across processes**: suite-global resources — sandbox/cache roots under a fixed tmpdir path, hardcoded listen ports, container names — are namespaced per run (`mktemp`, port `0`/ephemeral, unique names) so that two checkouts or worktrees of the repo running the suite concurrently cannot interfere. A fixed shared path that works on a single-checkout machine is a flake generator on a multi-agent workstation, and its signature is "a different test fails each run".
106
106
 
107
107
  ### Prompt tests: NEVER assert prose
108
108
 
@@ -113,6 +113,7 @@ Assert ONLY what a machine consumes:
113
113
  - the builder's routing decision — `expect(getPromptSource(model)).toBe("gpt-5-6")`, never the sentence that routing produces
114
114
  - a structural token the runtime dispatches on — a tool name, a tag like `<agent-identity>`, a parsed frontmatter field
115
115
  - the conditional the code enforces — skill loaded → tool present; `verbose=false` → directive absent
116
+ - a routing-bearing trigger fragment inside a parsed frontmatter `description` that a router (code or an LLM skill-picker) dispatches on — pin the *minimal fragment that carries the routing decision*, never the surrounding style prose. Such pins are what let a later rewrite change every sentence around them while proving the routing contract survived.
116
117
 
117
118
  If no machine consumes the text, there is no seam: write NO test and say so in the PR; review guards prose. When you DELEGATE test-writing, hand the child the behavior the test must distinguish ("fails if override precedence breaks"), never a ready-made assertion string, prompt fragment, or marker to copy — a prescribed mechanism that is wrong gets implemented faithfully, and the error ships with a green suite.
118
119
 
@@ -234,6 +235,15 @@ Logging is part of the code you ship, and it has iron rules of its own: levels c
234
235
 
235
236
  ---
236
237
 
238
+ ## DEPENDENCY UPGRADES — CROSS-CUTTING RULES
239
+
240
+ - **`0.x` minor = major.** Semver promises nothing below 1.0: treat `0.N → 0.N+1` as a breaking upgrade — read the changelog, build, and run the full suite before trusting it. A required field appearing in a public options type is a routine `0.x` "minor".
241
+ - **Version literals live outside the manifest.** Before committing a bump, grep the repo for the old version string: Dockerfiles pinning a global CLI, CI workflows, docs, and contract tests all carry copies. A bump that updates only the package manifest ships a split-brain deploy.
242
+ - **Pin-parity contract tests are a pattern, not a nuisance.** A small test asserting the lockfile-resolved version equals the deploy artifact's pin (Dockerfile, image tag) turns silent drift into a red test. If the project has one, update it deliberately; if the bump reveals unguarded drift, add the test with the bump.
243
+ - **Never hand-merge a lockfile.** On conflict, take either side whole and regenerate with the package manager — the resolver owns that file, not you.
244
+
245
+ ---
246
+
237
247
  ## MANDATORY POST-WRITE REVIEW LOOP
238
248
 
239
249
  **This runs EVERY time you finish writing or substantively editing code, before you claim the task is done.** No exceptions.
@@ -56,9 +56,11 @@ Log where the system decides something, not where it does something:
56
56
  - **Decision points** — retry chosen, fallback engaged, cache bypassed, degraded mode entered.
57
57
  - **The one place an error is finally handled.**
58
58
 
59
- Never log inside pure functions, utilities, or private helpers — callers with context log outcomes; internals stay silent. Two mechanical rules:
59
+ Never log inside pure functions, utilities, or private helpers — callers with context log outcomes; internals stay silent. The mechanical rules:
60
60
 
61
61
  - **One event, one line.** Log-and-rethrow at every layer turns one incident into five look-alike incidents. Log where the error is handled; layers that only propagate stay silent.
62
+ - **Answering the caller is not logging.** Converting a failure into a response — an HTTP 5xx body, an SSE error event, an error string returned to an LLM as a tool result, a non-zero exit code — satisfies the caller and leaves operations blind. This is the dominant finding when error paths are audited: the caller got an answer, the on-call got nothing. Every path that converts a failure into a caller-facing signal logs that failure exactly once, at the layer that handles it. When conversion layers stack, mark the error as logged at the handling layer (a symbol/flag on the error object) so outer catch-all handlers skip it — one incident, one line.
63
+ - **Expected feedback returned to the caller is not an event.** Validation results delivered as a normal response — including tool output an LLM agent consumes ("string not found", lint findings, a sandbox-boundary notice) — are response content, not anomalies. Log only the genuine I/O and subprocess failures behind them, and security rejections.
62
64
  - **Mechanical logging belongs to middleware.** Request/response logging is wired once at the framework layer, never hand-assembled per handler. High-volume zero-signal paths (health probes, metrics scrapes) are excluded there as data — an exclusion set — not as scattered `if` statements.
63
65
 
64
66
  **No speculative logs.** "Might need it later" is not a consumer. A log line earns its place through evidence: a debugging session that burned rounds because this state was invisible (see the debugging bridge below), an incident postmortem, an alert that needs the field.
@@ -69,6 +71,7 @@ Never log inside pure functions, utilities, or private helpers — callers with
69
71
  - **Correlation or it did not happen.** Request-scoped lines carry the trace/request id; entity-scoped lines carry the entity id. A line you cannot join to its request is noise during the only moments logs matter.
70
72
  - **Name events semantically** (`session.destroy`, `payment.fallback`), never positionally ("Step 3"). Step numbers couple the log stream to today's call structure; the first refactor makes them lie.
71
73
  - **No secrets.** Tokens, credentials, session cookies, and PII never enter a log line; URLs are sanitized (strip or redact query params like `token`, `key`) before logging. A leaked log is a leaked credential.
74
+ - **Payload content belongs to the tracing channel, not the log stream.** In LLM/agent systems, user messages, model responses, and tool outputs are captured by the tracing product (turn recorder, trace exporter); a log line carries a hash, a length, and at most a short excerpt for correlation. Dumping conversation content into logs bloats the store and leaks data the log pipeline was never hardened for.
72
75
  - **The logging path may not break the program.** If a log call can itself fail (serializing exotic state, a wrapper that touches I/O), that failure is caught, downgraded to a `warn` through a channel that cannot fail, and the operation continues. An empty catch around logging is still an empty catch.
73
76
 
74
77
  ## Anti-patterns
@@ -79,6 +82,8 @@ Never log inside pure functions, utilities, or private helpers — callers with
79
82
  | Introducing a logging framework to a project that has none | Uninvited behavior change; Rule 0 violation |
80
83
  | 4xx logged as `error` | Alert noise buries real pages |
81
84
  | Log-and-rethrow at every layer | One incident looks like five |
85
+ | Failure converted to a caller response (5xx body, SSE error, LLM tool-error string, exit code) with no log | The caller got an answer; operations got nothing |
86
+ | Logging expected validation feedback that is returned to the caller | Response content, not an event — buries real failures |
82
87
  | Variables interpolated into the message string | Un-aggregatable, un-alertable |
83
88
  | "Might need it later" logs | No consumer → pure cost |
84
89
  | Debug-time prints promoted to permanent `info` | Narration, not state transitions |
@@ -33,21 +33,26 @@ import fs from "node:fs"
33
33
  import { createRequire } from "node:module"
34
34
  import path from "node:path"
35
35
  import process from "node:process"
36
- import type * as tsTypes from "typescript"
36
+ import type * as tsTypes from "typescript/unstable/ast"
37
37
 
38
- type TsModule = typeof import("typescript")
38
+ type TsApiModule = typeof import("typescript/unstable/async")
39
+ type TsAstModule = typeof import("typescript/unstable/ast")
40
+ type TsModule = {
41
+ readonly api: TsApiModule
42
+ readonly ast: TsAstModule
43
+ }
39
44
 
40
45
  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.
46
+ // A static import resolves from this script's installed skill-cache path
47
+ // instead of the caller project. Resolve each TypeScript 7 API subpath from
48
+ // the caller so the script uses the project it audits.
47
49
  const callerRequire = createRequire(path.join(process.cwd(), "no-excuse-anchor.cjs"))
48
50
  try {
49
- const loaded: Partial<TsModule> = callerRequire("typescript")
50
- if (typeof loaded.createSourceFile === "function") return loaded as TsModule
51
+ const api: Partial<TsApiModule> = callerRequire("typescript/unstable/async")
52
+ const ast: Partial<TsAstModule> = callerRequire("typescript/unstable/ast")
53
+ if (typeof api.API === "function" && typeof ast.isAsExpression === "function") {
54
+ return { api: api as TsApiModule, ast: ast as TsAstModule }
55
+ }
51
56
  } catch { // no-excuse-ok: catch
52
57
  // fall through to the clear error below
53
58
  }
@@ -58,7 +63,8 @@ function loadTypescriptFromCaller(): TsModule {
58
63
  process.exit(2)
59
64
  }
60
65
 
61
- const ts: TsModule = loadTypescriptFromCaller()
66
+ const typescript = loadTypescriptFromCaller()
67
+ const ts = typescript.ast
62
68
 
63
69
  type RuleId =
64
70
  | "no-any-assertion"
@@ -132,9 +138,30 @@ function getLineText(sourceFile: tsTypes.SourceFile, line: number): string {
132
138
  return sourceFile.text.slice(start, end)
133
139
  }
134
140
 
135
- function analyzeFile(filePath: string): Violation[] {
141
+ async function parseSourceFiles(filePaths: readonly string[]): Promise<ReadonlyMap<string, tsTypes.SourceFile>> {
142
+ const compiler = new typescript.api.API({ cwd: process.cwd() })
143
+ try {
144
+ const snapshot = await compiler.updateSnapshot({ openFiles: [...filePaths] })
145
+ try {
146
+ const sourceFiles = await Promise.all(filePaths.map(async (filePath) => {
147
+ const project = await snapshot.getDefaultProjectForFile(filePath)
148
+ const sourceFile = await project?.program.getSourceFile(filePath)
149
+ if (!sourceFile) {
150
+ throw new Error(`TypeScript did not parse ${filePath}`)
151
+ }
152
+ return [filePath, sourceFile] as const
153
+ }))
154
+ return new Map(sourceFiles)
155
+ } finally {
156
+ await snapshot.dispose()
157
+ }
158
+ } finally {
159
+ await compiler.close()
160
+ }
161
+ }
162
+
163
+ function analyzeFile(filePath: string, sourceFile: tsTypes.SourceFile): Violation[] {
136
164
  const source = fs.readFileSync(filePath, "utf-8")
137
- const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true)
138
165
  const violations: Violation[] = []
139
166
 
140
167
  function pos(node: tsTypes.Node): { line: number; column: number } {
@@ -251,7 +278,7 @@ function analyzeFile(filePath: string): Violation[] {
251
278
  }
252
279
  }
253
280
 
254
- ts.forEachChild(node, visit)
281
+ node.forEachChild(visit)
255
282
  }
256
283
 
257
284
  visit(sourceFile)
@@ -282,7 +309,7 @@ function formatViolation(v: Violation): string {
282
309
  return `${v.filePath}:${v.line}:${v.column}: [${v.ruleId}] ${v.message}`
283
310
  }
284
311
 
285
- function main(): void {
312
+ async function main(): Promise<void> {
286
313
  const args = process.argv.slice(2)
287
314
  if (args.length === 0) {
288
315
  console.error("usage: check-no-excuse-rules.ts <file-or-dir>...")
@@ -295,7 +322,14 @@ function main(): void {
295
322
  process.exit(2)
296
323
  }
297
324
 
298
- const violations = files.flatMap((f) => analyzeFile(f))
325
+ const sourceFiles = await parseSourceFiles(files)
326
+ const violations = files.flatMap((filePath) => {
327
+ const sourceFile = sourceFiles.get(filePath)
328
+ if (!sourceFile) {
329
+ throw new Error(`TypeScript did not parse ${filePath}`)
330
+ }
331
+ return analyzeFile(filePath, sourceFile)
332
+ })
299
333
 
300
334
  if (violations.length === 0) {
301
335
  console.log(`No violations in ${files.length} file(s).`)
@@ -309,4 +343,4 @@ function main(): void {
309
343
  process.exit(1)
310
344
  }
311
345
 
312
- main()
346
+ await main()
@@ -38,11 +38,21 @@ Execute a Prometheus work plan until every top-level checkbox is complete. This
38
38
  ## Usage
39
39
 
40
40
  ```text
41
- $start-work [plan-name] [--worktree <absolute-path>]
41
+ $start-work [plan-name] [--worktree <absolute-path>] [--make-pr] [--ship]
42
42
  ```
43
43
 
44
44
  - `plan-name` (optional): a full or partial file stem under `.omo/plans/`.
45
45
  - `--worktree` (required for PR/branch work; otherwise optional): the task-owned git worktree path.
46
+ - `--make-pr` (optional): deliver the work as a pull request. IMPLIES worktree mode: when `--worktree` is absent, create a task-owned worktree (`git worktree add <absolute-path> <base-branch>`) before implementation and record it as `worktree_path`. On completion, push the branch and open a reviewer-readable PR, then hand off with the PR URL - merge only if the user asks.
47
+ - `--ship` (optional): full delivery lifecycle; implies `--make-pr`. After the PR opens, stay on the job until it is MERGED: watch CI and review gates, fix failures and address feedback from the worktree (fresh QA evidence for behavior changes), merge per the repository's merge policy, then remove the worktree and sync `.omo/` state back.
48
+
49
+ ## Goal and todo discipline (MANDATORY)
50
+
51
+ Do ALL of this immediately after the plan is selected, BEFORE the first implementation dispatch. Skipping any step is a defect.
52
+
53
+ 1. **Set the goal, in detail.** When a goal tool is available (`create_goal`), call it with a DETAILED objective: the plan name and path, the concrete end state, the phase and task counts, the delivery mode (direct, `--make-pr`, or `--ship`), and how completion will be verified. One work session = one goal. No goal tool -> record the same objective as the first ledger entry.
54
+ 2. **Register every phase and task as todos.** Mirror the plan into the todo/plan tool of your harness: one phase per plan wave, one todo per column-zero checkbox (including the final verification wave). Register ALL of them up front - never keep tasks in memory only.
55
+ 3. **Keep them current at every moment.** Mark a todo in_progress when its work dispatches and done immediately after its verification passes. Never batch-complete at the end, never execute work that is not a registered todo; discovered work is appended as a todo before it runs. The todo list, Boulder state, and plan checkboxes must always tell the same story.
46
56
 
47
57
  ## Phase 1: Select the plan
48
58
 
@@ -85,7 +95,7 @@ Write `.omo/boulder.json` before implementation starts. Prefix session ids with
85
95
  }
86
96
  ```
87
97
 
88
- For PR/branch work, `--worktree` is mandatory before implementation starts. Verify the path with `git worktree list --porcelain` or create it with `git worktree add <path> <branch-or-HEAD>`, then store the absolute path as `worktree_path`. All edits, commands, tests, and evidence capture must run inside that worktree.
98
+ For PR/branch work, a task-owned worktree is mandatory before implementation starts: pass `--worktree`, or use `--make-pr`/`--ship`, which auto-create one. Verify the path with `git worktree list --porcelain` or create it with `git worktree add <path> <branch-or-HEAD>`, then store the absolute path as `worktree_path`. All edits, commands, tests, and evidence capture must run inside that worktree.
89
99
 
90
100
  ## Phase 3: Execute the next checkbox
91
101
 
@@ -95,5 +95,5 @@ Roles - the ONLY subagents you may spawn (all read-only, plus `oracle` for the h
95
95
 
96
96
  ## Stop rules
97
97
 
98
- - Plan file exists, template filled, every todo has references + acceptance + QA + commit, dependency matrix consistent, and any required high-accuracy receipts are recorded: present the summary, then (CLEAR without `review_required`) ask the start-or-high-accuracy question, or (CLEAR with `review_required` / UNCLEAR) report the review result - and stop. **Never begin execution yourself.**
98
+ - Plan file exists, template filled, every todo has references + acceptance + QA + commit, dependency matrix consistent, and any required high-accuracy receipts are recorded: present the handoff explanation (Phase 4 delivery format in `references/full-workflow.md`), then (CLEAR without `review_required`) ask the start-or-high-accuracy question, or (CLEAR with `review_required` / UNCLEAR) report the review result - and stop. **Never begin execution yourself.**
99
99
  - Brief presented and `status: awaiting-approval` recorded: wait. Do not re-explore unless the user changes scope.
@@ -168,6 +168,17 @@ Runs in parallel; ALL must APPROVE; surface results and wait for the user's expl
168
168
  - CLEAR with `review_required: true`: run the high-accuracy review before delivery, record receipts, then present the plan summary and review result. Do not ask whether to run the review; the user already asked.
169
169
  - UNCLEAR: run the high-accuracy review AUTOMATICALLY before presenting (unless Classify=Trivial), then present a brief that LEADS with the derived approach and the adopted defaults; still wait for the user's explicit okay.
170
170
 
171
+ ### Handoff explanation (the mandatory shape of every plan summary)
172
+
173
+ Every "present the plan summary/brief" above delivers THIS structure, in the user's language, derived from the finished plan file (COUNT the rows - never estimate):
174
+
175
+ 1. **What this plan drives** - the work it performs, in 1-2 sentences.
176
+ 2. **End state** - the concrete things that will exist or behave differently once execution finishes.
177
+ 3. **Shape** - how many phases/waves and how many tasks: N implementation todos (`- [ ] N.` rows) + F final-verification tasks (`- [ ] F<n>.` rows).
178
+ 4. **Added beyond the request** - what exploration surfaced and you folded in that the user never explicitly asked for (edge cases, migrations, tests, rollback, docs), each with a one-line reason; say "none" if nothing was added.
179
+ 5. **Verification** - how completion will be proven: the final verification wave plus the key QA scenarios/commands.
180
+ 6. **Execution handoff** - the plan runs in a worker session via `$start-work <plan-name>`; introduce the options: `--worktree <absolute-path>` (task-owned worktree; required for PR/branch work), `--make-pr` (deliver as a PR; auto-creates a task-owned worktree), `--ship` (implies `--make-pr`, keeps working until the PR is reviewed and MERGED).
181
+
171
182
  ### High-accuracy review (dual review)
172
183
  The high-accuracy review is DUAL and both passes must return OKAY before handoff: (1) the native `momus` reviewer subagent, and (2) an independent Oracle review via `task(subagent_type="oracle", ...)` on the strongest available reasoning model, in a fully isolated sub-session with normal approval and sandbox policy. Do not add flags that disable approvals or sandboxing. Momus runs at High and may take substantially longer than other agents. One round = exactly ONE `momus` + ONE independent review, dispatched together against the COMPLETE plan file (todos + TL;DR filled) at the draft's exact recorded `plan_path`. Keep Momus in flight and wait for its terminal result: elapsed time alone never justifies cancelling, duplicating, replacing, or treating it as failed. After both verdicts return, fix every cited issue and resubmit both fresh until each approves. CLEAR: runs when the user opts in or `review_required: true`. UNCLEAR: runs automatically unless Classify=Trivial.
173
184
 
@@ -210,6 +221,6 @@ task(subagent_type="explore", description="Map the implementation surface", prom
210
221
  Roles - the ONLY spawnable subagents (all read-only, plus `oracle` for the high-accuracy review): `explore`, `librarian`, `metis`, `momus`. Never dispatch with `category=` and never instruct a child to edit files. Spawn long plan/reviewer agents in the background through the OpenCode task surface; between waits, back off — double the timeout up to ~5 minutes — instead of spinning short cycles. Require the child to send `WORKING: <task> - <phase>` before long passes and `BLOCKED: <reason>` only when progress stops. A timeout only means no new update arrived; treat a running child as alive. Fall back only when the child completed without the deliverable, is ack-only after followup, explicitly `BLOCKED:`, or no longer running; then respawn a smaller delegated job. Close each agent after integrating its result.
211
222
 
212
223
  ## Stop rules
213
- - Plan file exists, template filled, every todo has references + acceptance + QA + commit, dependency matrix consistent, and any required high-accuracy receipts recorded: present the summary, then (CLEAR without `review_required`) ask the start-or-high-accuracy question, or (CLEAR with `review_required` / UNCLEAR) report the review result - and stop. Execution belongs to the worker, never to you.
224
+ - Plan file exists, template filled, every todo has references + acceptance + QA + commit, dependency matrix consistent, and any required high-accuracy receipts recorded: present the handoff explanation (Phase 4 format), then (CLEAR without `review_required`) ask the start-or-high-accuracy question, or (CLEAR with `review_required` / UNCLEAR) report the review result - and stop. Execution belongs to the worker, never to you.
214
225
  - Brief presented and `status: awaiting-approval` recorded: wait. Do not re-explore unless the user changes scope.
215
226
  - Two research waves with no new useful facts: stop exploring, present the brief.
@@ -30,7 +30,7 @@ CLEARANCE CHECK after each turn: objective defined? scope IN/OUT explicit? appro
30
30
  </interview>
31
31
 
32
32
  <approval_and_deliver>
33
- Run the durable approval gate (mechanics in `full-workflow.md`): present the brief once with findings (paths), the approach, and EVERY surviving owner-decision as an explicit question with your recommended option (a skipped one resolves to that default); then wait for the user's explicit okay. If "start now, or review first?" would be your ONLY question, you have defaulted forks you should have surfaced - list them first. After approval: scaffold the files, run mandatory Metis, APPEND the todos, fill the human TL;DR last. Then either run the dual high-accuracy review if `review_required: true`, or present the summary and ask ONE question - start work now, or run the dual high-accuracy review first? Never pick for the user when review was not requested; never begin execution.
33
+ Run the durable approval gate (mechanics in `full-workflow.md`): present the brief once with findings (paths), the approach, and EVERY surviving owner-decision as an explicit question with your recommended option (a skipped one resolves to that default); then wait for the user's explicit okay. If "start now, or review first?" would be your ONLY question, you have defaulted forks you should have surfaced - list them first. After approval: scaffold the files, run mandatory Metis, APPEND the todos, fill the human TL;DR last. Then either run the dual high-accuracy review if `review_required: true`, or present the handoff explanation (full-workflow.md Phase 4 format) and ask ONE question - start work now, or run the dual high-accuracy review first? Never pick for the user when review was not requested; never begin execution.
34
34
  </approval_and_deliver>
35
35
 
36
36
  <worked_example>