claudecode-omc 4.8.2 → 4.8.3

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 (667) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +3 -3
  3. package/README.de.md +60 -0
  4. package/README.es.md +60 -0
  5. package/README.fr.md +60 -0
  6. package/README.it.md +60 -0
  7. package/README.ja.md +60 -0
  8. package/README.ko.md +60 -0
  9. package/README.md +101 -16
  10. package/README.pt.md +60 -0
  11. package/README.ru.md +60 -0
  12. package/README.tr.md +60 -0
  13. package/README.vi.md +60 -0
  14. package/README.zh.md +60 -0
  15. package/agents/code-reviewer.md +107 -6
  16. package/agents/critic.md +212 -42
  17. package/agents/debugger.md +52 -4
  18. package/agents/document-specialist.md +39 -60
  19. package/agents/executor.md +29 -9
  20. package/agents/explore.md +3 -1
  21. package/agents/security-reviewer.md +57 -0
  22. package/agents/test-engineer.md +21 -0
  23. package/agents/verifier.md +2 -0
  24. package/agents/writer.md +2 -0
  25. package/bridge/cli.cjs +7402 -3580
  26. package/bridge/mcp-server.cjs +558 -43
  27. package/bridge/runtime-cli.cjs +3034 -1801
  28. package/bridge/team-bridge.cjs +25 -1
  29. package/bridge/team-mcp.cjs +257 -88
  30. package/bridge/team.js +5226 -413
  31. package/dist/__tests__/agent-boundary-guidance.test.d.ts +2 -0
  32. package/dist/__tests__/agent-boundary-guidance.test.d.ts.map +1 -0
  33. package/dist/__tests__/agent-boundary-guidance.test.js +48 -0
  34. package/dist/__tests__/agent-boundary-guidance.test.js.map +1 -0
  35. package/dist/__tests__/agent-registry.test.js +48 -11
  36. package/dist/__tests__/agent-registry.test.js.map +1 -1
  37. package/dist/__tests__/auto-slash-aliases.test.js +25 -0
  38. package/dist/__tests__/auto-slash-aliases.test.js.map +1 -1
  39. package/dist/__tests__/bedrock-model-routing.test.d.ts +21 -0
  40. package/dist/__tests__/bedrock-model-routing.test.d.ts.map +1 -0
  41. package/dist/__tests__/bedrock-model-routing.test.js +397 -0
  42. package/dist/__tests__/bedrock-model-routing.test.js.map +1 -0
  43. package/dist/__tests__/cleanup-validation.test.js +7 -3
  44. package/dist/__tests__/cleanup-validation.test.js.map +1 -1
  45. package/dist/__tests__/cli-win32-warning.test.js +15 -2
  46. package/dist/__tests__/cli-win32-warning.test.js.map +1 -1
  47. package/dist/__tests__/consolidation-contracts.test.js +28 -3
  48. package/dist/__tests__/consolidation-contracts.test.js.map +1 -1
  49. package/dist/__tests__/context-guard-stop.test.d.ts +2 -0
  50. package/dist/__tests__/context-guard-stop.test.d.ts.map +1 -0
  51. package/dist/__tests__/context-guard-stop.test.js +58 -0
  52. package/dist/__tests__/context-guard-stop.test.js.map +1 -0
  53. package/dist/__tests__/delegation-enforcer.test.js +76 -11
  54. package/dist/__tests__/delegation-enforcer.test.js.map +1 -1
  55. package/dist/__tests__/doctor-conflicts.test.js +62 -1
  56. package/dist/__tests__/doctor-conflicts.test.js.map +1 -1
  57. package/dist/__tests__/hooks.test.js +165 -4
  58. package/dist/__tests__/hooks.test.js.map +1 -1
  59. package/dist/__tests__/hud/defaults.test.js +4 -0
  60. package/dist/__tests__/hud/defaults.test.js.map +1 -1
  61. package/dist/__tests__/hud/limits-error.test.js +2 -4
  62. package/dist/__tests__/hud/limits-error.test.js.map +1 -1
  63. package/dist/__tests__/hud/mission-board-state.test.d.ts +2 -0
  64. package/dist/__tests__/hud/mission-board-state.test.d.ts.map +1 -0
  65. package/dist/__tests__/hud/mission-board-state.test.js +170 -0
  66. package/dist/__tests__/hud/mission-board-state.test.js.map +1 -0
  67. package/dist/__tests__/hud/mission-board.test.d.ts +2 -0
  68. package/dist/__tests__/hud/mission-board.test.d.ts.map +1 -0
  69. package/dist/__tests__/hud/mission-board.test.js +143 -0
  70. package/dist/__tests__/hud/mission-board.test.js.map +1 -0
  71. package/dist/__tests__/hud/rate-limits-error.test.js +13 -0
  72. package/dist/__tests__/hud/rate-limits-error.test.js.map +1 -1
  73. package/dist/__tests__/hud/render-rate-limits-priority.test.d.ts +8 -0
  74. package/dist/__tests__/hud/render-rate-limits-priority.test.d.ts.map +1 -0
  75. package/dist/__tests__/hud/render-rate-limits-priority.test.js +145 -0
  76. package/dist/__tests__/hud/render-rate-limits-priority.test.js.map +1 -0
  77. package/dist/__tests__/hud/render.test.js +22 -0
  78. package/dist/__tests__/hud/render.test.js.map +1 -1
  79. package/dist/__tests__/hud/stale-indicator.test.d.ts +9 -0
  80. package/dist/__tests__/hud/stale-indicator.test.d.ts.map +1 -0
  81. package/dist/__tests__/hud/stale-indicator.test.js +81 -0
  82. package/dist/__tests__/hud/stale-indicator.test.js.map +1 -0
  83. package/dist/__tests__/hud/state.test.js +30 -0
  84. package/dist/__tests__/hud/state.test.js.map +1 -1
  85. package/dist/__tests__/hud/usage-api-lock.test.d.ts +2 -0
  86. package/dist/__tests__/hud/usage-api-lock.test.d.ts.map +1 -0
  87. package/dist/__tests__/hud/usage-api-lock.test.js +245 -0
  88. package/dist/__tests__/hud/usage-api-lock.test.js.map +1 -0
  89. package/dist/__tests__/hud/usage-api-stale.test.d.ts +9 -0
  90. package/dist/__tests__/hud/usage-api-stale.test.d.ts.map +1 -0
  91. package/dist/__tests__/hud/usage-api-stale.test.js +297 -0
  92. package/dist/__tests__/hud/usage-api-stale.test.js.map +1 -0
  93. package/dist/__tests__/hud/usage-api.test.js +223 -0
  94. package/dist/__tests__/hud/usage-api.test.js.map +1 -1
  95. package/dist/__tests__/hud/watch-mode-init.test.d.ts +2 -0
  96. package/dist/__tests__/hud/watch-mode-init.test.d.ts.map +1 -0
  97. package/dist/__tests__/hud/watch-mode-init.test.js +133 -0
  98. package/dist/__tests__/hud/watch-mode-init.test.js.map +1 -0
  99. package/dist/__tests__/hud-agents.test.js +12 -10
  100. package/dist/__tests__/hud-agents.test.js.map +1 -1
  101. package/dist/__tests__/hud-build-guidance.test.js +6 -2
  102. package/dist/__tests__/hud-build-guidance.test.js.map +1 -1
  103. package/dist/__tests__/hud-marketplace-resolution.test.d.ts +2 -0
  104. package/dist/__tests__/hud-marketplace-resolution.test.d.ts.map +1 -0
  105. package/dist/__tests__/hud-marketplace-resolution.test.js +53 -0
  106. package/dist/__tests__/hud-marketplace-resolution.test.js.map +1 -0
  107. package/dist/__tests__/installer-hud-skip.test.js +12 -0
  108. package/dist/__tests__/installer-hud-skip.test.js.map +1 -1
  109. package/dist/__tests__/installer-plugin-agents.test.d.ts +2 -0
  110. package/dist/__tests__/installer-plugin-agents.test.d.ts.map +1 -0
  111. package/dist/__tests__/installer-plugin-agents.test.js +111 -0
  112. package/dist/__tests__/installer-plugin-agents.test.js.map +1 -0
  113. package/dist/__tests__/installer-version-guard.test.d.ts +2 -0
  114. package/dist/__tests__/installer-version-guard.test.d.ts.map +1 -0
  115. package/dist/__tests__/installer-version-guard.test.js +75 -0
  116. package/dist/__tests__/installer-version-guard.test.js.map +1 -0
  117. package/dist/__tests__/installer.test.js +58 -4
  118. package/dist/__tests__/installer.test.js.map +1 -1
  119. package/dist/__tests__/omc-tools-server.test.js +8 -5
  120. package/dist/__tests__/omc-tools-server.test.js.map +1 -1
  121. package/dist/__tests__/pre-tool-enforcer.test.js +38 -0
  122. package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
  123. package/dist/__tests__/prompt-injection.test.js +3 -3
  124. package/dist/__tests__/prompt-injection.test.js.map +1 -1
  125. package/dist/__tests__/ralph-prd-mandatory.test.js +53 -2
  126. package/dist/__tests__/ralph-prd-mandatory.test.js.map +1 -1
  127. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.js +42 -0
  128. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.js.map +1 -1
  129. package/dist/__tests__/rate-limit-wait/tmux-detector.test.js +1 -1
  130. package/dist/__tests__/session-history-search.test.d.ts +2 -0
  131. package/dist/__tests__/session-history-search.test.d.ts.map +1 -0
  132. package/dist/__tests__/session-history-search.test.js +115 -0
  133. package/dist/__tests__/session-history-search.test.js.map +1 -0
  134. package/dist/__tests__/session-start-script-context.test.d.ts +2 -0
  135. package/dist/__tests__/session-start-script-context.test.d.ts.map +1 -0
  136. package/dist/__tests__/session-start-script-context.test.js +49 -0
  137. package/dist/__tests__/session-start-script-context.test.js.map +1 -0
  138. package/dist/__tests__/skills.test.js +71 -24
  139. package/dist/__tests__/skills.test.js.map +1 -1
  140. package/dist/__tests__/standalone-server.test.js +8 -4
  141. package/dist/__tests__/standalone-server.test.js.map +1 -1
  142. package/dist/__tests__/tier0-docs-consistency.test.js +10 -2
  143. package/dist/__tests__/tier0-docs-consistency.test.js.map +1 -1
  144. package/dist/agents/definitions.d.ts +5 -15
  145. package/dist/agents/definitions.d.ts.map +1 -1
  146. package/dist/agents/definitions.js +48 -49
  147. package/dist/agents/definitions.js.map +1 -1
  148. package/dist/agents/document-specialist.d.ts +1 -1
  149. package/dist/agents/document-specialist.d.ts.map +1 -1
  150. package/dist/agents/document-specialist.js +46 -21
  151. package/dist/agents/document-specialist.js.map +1 -1
  152. package/dist/agents/explore.d.ts.map +1 -1
  153. package/dist/agents/explore.js +3 -2
  154. package/dist/agents/explore.js.map +1 -1
  155. package/dist/agents/index.d.ts +2 -4
  156. package/dist/agents/index.d.ts.map +1 -1
  157. package/dist/agents/index.js +3 -6
  158. package/dist/agents/index.js.map +1 -1
  159. package/dist/agents/types.d.ts +2 -2
  160. package/dist/agents/types.d.ts.map +1 -1
  161. package/dist/cli/__tests__/ask.test.js +255 -8
  162. package/dist/cli/__tests__/ask.test.js.map +1 -1
  163. package/dist/cli/__tests__/session-search-help.test.d.ts +2 -0
  164. package/dist/cli/__tests__/session-search-help.test.d.ts.map +1 -0
  165. package/dist/cli/__tests__/session-search-help.test.js +13 -0
  166. package/dist/cli/__tests__/session-search-help.test.js.map +1 -0
  167. package/dist/cli/__tests__/session-search.test.d.ts +2 -0
  168. package/dist/cli/__tests__/session-search.test.d.ts.map +1 -0
  169. package/dist/cli/__tests__/session-search.test.js +72 -0
  170. package/dist/cli/__tests__/session-search.test.js.map +1 -0
  171. package/dist/cli/__tests__/team-help.test.js +1 -1
  172. package/dist/cli/__tests__/team-help.test.js.map +1 -1
  173. package/dist/cli/__tests__/team.test.js +256 -4
  174. package/dist/cli/__tests__/team.test.js.map +1 -1
  175. package/dist/cli/commands/__tests__/team.test.js +52 -2
  176. package/dist/cli/commands/__tests__/team.test.js.map +1 -1
  177. package/dist/cli/commands/doctor-conflicts.d.ts.map +1 -1
  178. package/dist/cli/commands/doctor-conflicts.js +15 -1
  179. package/dist/cli/commands/doctor-conflicts.js.map +1 -1
  180. package/dist/cli/commands/session-search.d.ts +18 -0
  181. package/dist/cli/commands/session-search.d.ts.map +1 -0
  182. package/dist/cli/commands/session-search.js +47 -0
  183. package/dist/cli/commands/session-search.js.map +1 -0
  184. package/dist/cli/commands/team.d.ts +11 -0
  185. package/dist/cli/commands/team.d.ts.map +1 -1
  186. package/dist/cli/commands/team.js +94 -24
  187. package/dist/cli/commands/team.js.map +1 -1
  188. package/dist/cli/commands/wait.d.ts.map +1 -1
  189. package/dist/cli/commands/wait.js +12 -1
  190. package/dist/cli/commands/wait.js.map +1 -1
  191. package/dist/cli/index.js +70 -2
  192. package/dist/cli/index.js.map +1 -1
  193. package/dist/cli/team.d.ts +1 -0
  194. package/dist/cli/team.d.ts.map +1 -1
  195. package/dist/cli/team.js +100 -214
  196. package/dist/cli/team.js.map +1 -1
  197. package/dist/cli/win32-warning.d.ts +2 -1
  198. package/dist/cli/win32-warning.d.ts.map +1 -1
  199. package/dist/cli/win32-warning.js +20 -6
  200. package/dist/cli/win32-warning.js.map +1 -1
  201. package/dist/config/__tests__/loader.test.d.ts +2 -0
  202. package/dist/config/__tests__/loader.test.d.ts.map +1 -0
  203. package/dist/config/__tests__/loader.test.js +145 -0
  204. package/dist/config/__tests__/loader.test.js.map +1 -0
  205. package/dist/config/__tests__/models.test.d.ts +2 -0
  206. package/dist/config/__tests__/models.test.d.ts.map +1 -0
  207. package/dist/config/__tests__/models.test.js +147 -0
  208. package/dist/config/__tests__/models.test.js.map +1 -0
  209. package/dist/config/__tests__/test-helpers.d.ts +3 -0
  210. package/dist/config/__tests__/test-helpers.d.ts.map +1 -0
  211. package/dist/config/__tests__/test-helpers.js +19 -0
  212. package/dist/config/__tests__/test-helpers.js.map +1 -0
  213. package/dist/config/loader.d.ts +3 -1
  214. package/dist/config/loader.d.ts.map +1 -1
  215. package/dist/config/loader.js +140 -126
  216. package/dist/config/loader.js.map +1 -1
  217. package/dist/config/models.d.ts +29 -10
  218. package/dist/config/models.d.ts.map +1 -1
  219. package/dist/config/models.js +96 -10
  220. package/dist/config/models.js.map +1 -1
  221. package/dist/features/builtin-skills/skills.d.ts.map +1 -1
  222. package/dist/features/builtin-skills/skills.js +8 -1
  223. package/dist/features/builtin-skills/skills.js.map +1 -1
  224. package/dist/features/builtin-skills/types.d.ts +3 -0
  225. package/dist/features/builtin-skills/types.d.ts.map +1 -1
  226. package/dist/features/delegation-enforcer.d.ts +5 -12
  227. package/dist/features/delegation-enforcer.d.ts.map +1 -1
  228. package/dist/features/delegation-enforcer.js +48 -54
  229. package/dist/features/delegation-enforcer.js.map +1 -1
  230. package/dist/features/delegation-routing/__tests__/resolver.test.js +4 -3
  231. package/dist/features/delegation-routing/__tests__/resolver.test.js.map +1 -1
  232. package/dist/features/delegation-routing/types.d.ts.map +1 -1
  233. package/dist/features/delegation-routing/types.js +7 -4
  234. package/dist/features/delegation-routing/types.js.map +1 -1
  235. package/dist/features/index.d.ts +1 -0
  236. package/dist/features/index.d.ts.map +1 -1
  237. package/dist/features/index.js +2 -0
  238. package/dist/features/index.js.map +1 -1
  239. package/dist/features/rate-limit-wait/daemon.d.ts.map +1 -1
  240. package/dist/features/rate-limit-wait/daemon.js +8 -5
  241. package/dist/features/rate-limit-wait/daemon.js.map +1 -1
  242. package/dist/features/rate-limit-wait/index.d.ts +1 -1
  243. package/dist/features/rate-limit-wait/index.d.ts.map +1 -1
  244. package/dist/features/rate-limit-wait/index.js +1 -1
  245. package/dist/features/rate-limit-wait/index.js.map +1 -1
  246. package/dist/features/rate-limit-wait/rate-limit-monitor.d.ts +9 -0
  247. package/dist/features/rate-limit-wait/rate-limit-monitor.d.ts.map +1 -1
  248. package/dist/features/rate-limit-wait/rate-limit-monitor.js +38 -0
  249. package/dist/features/rate-limit-wait/rate-limit-monitor.js.map +1 -1
  250. package/dist/features/rate-limit-wait/tmux-detector.d.ts +2 -1
  251. package/dist/features/rate-limit-wait/tmux-detector.d.ts.map +1 -1
  252. package/dist/features/rate-limit-wait/tmux-detector.js +8 -9
  253. package/dist/features/rate-limit-wait/tmux-detector.js.map +1 -1
  254. package/dist/features/rate-limit-wait/types.d.ts +11 -0
  255. package/dist/features/rate-limit-wait/types.d.ts.map +1 -1
  256. package/dist/features/session-history-search/index.d.ts +6 -0
  257. package/dist/features/session-history-search/index.d.ts.map +1 -0
  258. package/dist/features/session-history-search/index.js +480 -0
  259. package/dist/features/session-history-search/index.js.map +1 -0
  260. package/dist/features/session-history-search/types.d.ts +36 -0
  261. package/dist/features/session-history-search/types.d.ts.map +1 -0
  262. package/dist/features/session-history-search/types.js +2 -0
  263. package/dist/features/session-history-search/types.js.map +1 -0
  264. package/dist/hooks/__tests__/background-process-guard.test.js +101 -5
  265. package/dist/hooks/__tests__/background-process-guard.test.js.map +1 -1
  266. package/dist/hooks/__tests__/bridge-openclaw.test.js +16 -5
  267. package/dist/hooks/__tests__/bridge-openclaw.test.js.map +1 -1
  268. package/dist/hooks/__tests__/bridge-routing.test.js +48 -1
  269. package/dist/hooks/__tests__/bridge-routing.test.js.map +1 -1
  270. package/dist/hooks/auto-slash-command/executor.d.ts.map +1 -1
  271. package/dist/hooks/auto-slash-command/executor.js +9 -1
  272. package/dist/hooks/auto-slash-command/executor.js.map +1 -1
  273. package/dist/hooks/auto-slash-command/types.d.ts +2 -0
  274. package/dist/hooks/auto-slash-command/types.d.ts.map +1 -1
  275. package/dist/hooks/auto-slash-command/types.js +0 -7
  276. package/dist/hooks/auto-slash-command/types.js.map +1 -1
  277. package/dist/hooks/autopilot/adapters/execution-adapter.js +3 -3
  278. package/dist/hooks/autopilot/prompts.js +1 -1
  279. package/dist/hooks/bridge-normalize.d.ts.map +1 -1
  280. package/dist/hooks/bridge-normalize.js +2 -0
  281. package/dist/hooks/bridge-normalize.js.map +1 -1
  282. package/dist/hooks/bridge.d.ts.map +1 -1
  283. package/dist/hooks/bridge.js +248 -39
  284. package/dist/hooks/bridge.js.map +1 -1
  285. package/dist/hooks/keyword-detector/__tests__/index.test.js +41 -0
  286. package/dist/hooks/keyword-detector/__tests__/index.test.js.map +1 -1
  287. package/dist/hooks/keyword-detector/index.d.ts +1 -1
  288. package/dist/hooks/keyword-detector/index.d.ts.map +1 -1
  289. package/dist/hooks/keyword-detector/index.js +3 -1
  290. package/dist/hooks/keyword-detector/index.js.map +1 -1
  291. package/dist/hooks/permission-handler/index.d.ts +8 -0
  292. package/dist/hooks/permission-handler/index.d.ts.map +1 -1
  293. package/dist/hooks/permission-handler/index.js +76 -0
  294. package/dist/hooks/permission-handler/index.js.map +1 -1
  295. package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.d.ts +2 -0
  296. package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.d.ts.map +1 -0
  297. package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.js +90 -0
  298. package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.js.map +1 -0
  299. package/dist/hooks/persistent-mode/__tests__/team-ralplan-stop.test.d.ts +2 -0
  300. package/dist/hooks/persistent-mode/__tests__/team-ralplan-stop.test.d.ts.map +1 -0
  301. package/dist/hooks/persistent-mode/__tests__/team-ralplan-stop.test.js +535 -0
  302. package/dist/hooks/persistent-mode/__tests__/team-ralplan-stop.test.js.map +1 -0
  303. package/dist/hooks/persistent-mode/index.d.ts +1 -1
  304. package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
  305. package/dist/hooks/persistent-mode/index.js +296 -21
  306. package/dist/hooks/persistent-mode/index.js.map +1 -1
  307. package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +156 -0
  308. package/dist/hooks/persistent-mode/stop-hook-blocking.test.js.map +1 -1
  309. package/dist/hooks/project-memory/__tests__/integration.test.js +27 -2
  310. package/dist/hooks/project-memory/__tests__/integration.test.js.map +1 -1
  311. package/dist/hooks/project-memory/__tests__/storage.test.js +37 -0
  312. package/dist/hooks/project-memory/__tests__/storage.test.js.map +1 -1
  313. package/dist/hooks/project-memory/storage.d.ts +1 -1
  314. package/dist/hooks/project-memory/storage.d.ts.map +1 -1
  315. package/dist/hooks/project-memory/storage.js +5 -4
  316. package/dist/hooks/project-memory/storage.js.map +1 -1
  317. package/dist/hooks/ralph/index.d.ts +1 -1
  318. package/dist/hooks/ralph/index.d.ts.map +1 -1
  319. package/dist/hooks/ralph/index.js +1 -1
  320. package/dist/hooks/ralph/index.js.map +1 -1
  321. package/dist/hooks/ralph/loop.d.ts +18 -0
  322. package/dist/hooks/ralph/loop.d.ts.map +1 -1
  323. package/dist/hooks/ralph/loop.js +31 -0
  324. package/dist/hooks/ralph/loop.js.map +1 -1
  325. package/dist/hooks/ralph/verifier.d.ts +4 -1
  326. package/dist/hooks/ralph/verifier.d.ts.map +1 -1
  327. package/dist/hooks/ralph/verifier.js +56 -21
  328. package/dist/hooks/ralph/verifier.js.map +1 -1
  329. package/dist/hooks/recovery/__tests__/storage.test.d.ts +2 -0
  330. package/dist/hooks/recovery/__tests__/storage.test.d.ts.map +1 -0
  331. package/dist/hooks/recovery/__tests__/storage.test.js +65 -0
  332. package/dist/hooks/recovery/__tests__/storage.test.js.map +1 -0
  333. package/dist/hooks/recovery/storage.d.ts +5 -1
  334. package/dist/hooks/recovery/storage.d.ts.map +1 -1
  335. package/dist/hooks/recovery/storage.js +7 -29
  336. package/dist/hooks/recovery/storage.js.map +1 -1
  337. package/dist/hooks/recovery/types.d.ts +1 -1
  338. package/dist/hooks/recovery/types.d.ts.map +1 -1
  339. package/dist/hooks/session-end/__tests__/duplicate-notifications.test.d.ts +2 -0
  340. package/dist/hooks/session-end/__tests__/duplicate-notifications.test.d.ts.map +1 -0
  341. package/dist/hooks/session-end/__tests__/duplicate-notifications.test.js +140 -0
  342. package/dist/hooks/session-end/__tests__/duplicate-notifications.test.js.map +1 -0
  343. package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.d.ts +2 -0
  344. package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.d.ts.map +1 -0
  345. package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.js +122 -0
  346. package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.js.map +1 -0
  347. package/dist/hooks/session-end/__tests__/openclaw-session-end.test.js +38 -12
  348. package/dist/hooks/session-end/__tests__/openclaw-session-end.test.js.map +1 -1
  349. package/dist/hooks/session-end/callbacks.d.ts +4 -1
  350. package/dist/hooks/session-end/callbacks.d.ts.map +1 -1
  351. package/dist/hooks/session-end/callbacks.js +5 -4
  352. package/dist/hooks/session-end/callbacks.js.map +1 -1
  353. package/dist/hooks/session-end/index.d.ts.map +1 -1
  354. package/dist/hooks/session-end/index.js +162 -36
  355. package/dist/hooks/session-end/index.js.map +1 -1
  356. package/dist/hooks/skill-state/__tests__/skill-state.test.js +35 -33
  357. package/dist/hooks/skill-state/__tests__/skill-state.test.js.map +1 -1
  358. package/dist/hooks/skill-state/index.d.ts +3 -3
  359. package/dist/hooks/skill-state/index.d.ts.map +1 -1
  360. package/dist/hooks/skill-state/index.js +7 -11
  361. package/dist/hooks/skill-state/index.js.map +1 -1
  362. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  363. package/dist/hooks/subagent-tracker/index.js +22 -0
  364. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  365. package/dist/hooks/think-mode/__tests__/index.test.js +20 -20
  366. package/dist/hooks/think-mode/__tests__/index.test.js.map +1 -1
  367. package/dist/hooks/think-mode/switcher.d.ts.map +1 -1
  368. package/dist/hooks/think-mode/switcher.js +13 -10
  369. package/dist/hooks/think-mode/switcher.js.map +1 -1
  370. package/dist/hooks/thinking-block-validator/__tests__/index.test.d.ts +2 -0
  371. package/dist/hooks/thinking-block-validator/__tests__/index.test.d.ts.map +1 -0
  372. package/dist/hooks/thinking-block-validator/__tests__/index.test.js +56 -0
  373. package/dist/hooks/thinking-block-validator/__tests__/index.test.js.map +1 -0
  374. package/dist/hooks/thinking-block-validator/index.d.ts.map +1 -1
  375. package/dist/hooks/thinking-block-validator/index.js +7 -6
  376. package/dist/hooks/thinking-block-validator/index.js.map +1 -1
  377. package/dist/hooks/todo-continuation/index.d.ts +6 -0
  378. package/dist/hooks/todo-continuation/index.d.ts.map +1 -1
  379. package/dist/hooks/todo-continuation/index.js +14 -5
  380. package/dist/hooks/todo-continuation/index.js.map +1 -1
  381. package/dist/hud/elements/agents.d.ts.map +1 -1
  382. package/dist/hud/elements/agents.js +8 -14
  383. package/dist/hud/elements/agents.js.map +1 -1
  384. package/dist/hud/elements/index.d.ts +1 -0
  385. package/dist/hud/elements/index.d.ts.map +1 -1
  386. package/dist/hud/elements/index.js +1 -0
  387. package/dist/hud/elements/index.js.map +1 -1
  388. package/dist/hud/elements/limits.d.ts +3 -3
  389. package/dist/hud/elements/limits.d.ts.map +1 -1
  390. package/dist/hud/elements/limits.js +26 -18
  391. package/dist/hud/elements/limits.js.map +1 -1
  392. package/dist/hud/elements/mission-board.d.ts +2 -0
  393. package/dist/hud/elements/mission-board.d.ts.map +1 -0
  394. package/dist/hud/elements/mission-board.js +2 -0
  395. package/dist/hud/elements/mission-board.js.map +1 -0
  396. package/dist/hud/index.d.ts +1 -1
  397. package/dist/hud/index.d.ts.map +1 -1
  398. package/dist/hud/index.js +10 -2
  399. package/dist/hud/index.js.map +1 -1
  400. package/dist/hud/mission-board.d.ts +75 -0
  401. package/dist/hud/mission-board.d.ts.map +1 -0
  402. package/dist/hud/mission-board.js +420 -0
  403. package/dist/hud/mission-board.js.map +1 -0
  404. package/dist/hud/render.d.ts.map +1 -1
  405. package/dist/hud/render.js +16 -8
  406. package/dist/hud/render.js.map +1 -1
  407. package/dist/hud/state.d.ts.map +1 -1
  408. package/dist/hud/state.js +13 -0
  409. package/dist/hud/state.js.map +1 -1
  410. package/dist/hud/types.d.ts +11 -0
  411. package/dist/hud/types.d.ts.map +1 -1
  412. package/dist/hud/types.js +10 -0
  413. package/dist/hud/types.js.map +1 -1
  414. package/dist/hud/usage-api.d.ts +1 -1
  415. package/dist/hud/usage-api.d.ts.map +1 -1
  416. package/dist/hud/usage-api.js +207 -106
  417. package/dist/hud/usage-api.js.map +1 -1
  418. package/dist/index.d.ts +1 -0
  419. package/dist/index.d.ts.map +1 -1
  420. package/dist/index.js +2 -3
  421. package/dist/index.js.map +1 -1
  422. package/dist/installer/__tests__/claude-md-merge.test.js +53 -9
  423. package/dist/installer/__tests__/claude-md-merge.test.js.map +1 -1
  424. package/dist/installer/__tests__/hook-templates.test.d.ts +2 -0
  425. package/dist/installer/__tests__/hook-templates.test.d.ts.map +1 -0
  426. package/dist/installer/__tests__/hook-templates.test.js +76 -0
  427. package/dist/installer/__tests__/hook-templates.test.js.map +1 -0
  428. package/dist/installer/hooks.d.ts +15 -0
  429. package/dist/installer/hooks.d.ts.map +1 -1
  430. package/dist/installer/hooks.js +51 -0
  431. package/dist/installer/hooks.js.map +1 -1
  432. package/dist/installer/index.d.ts +25 -0
  433. package/dist/installer/index.d.ts.map +1 -1
  434. package/dist/installer/index.js +273 -64
  435. package/dist/installer/index.js.map +1 -1
  436. package/dist/lib/mode-names.d.ts.map +1 -1
  437. package/dist/lib/mode-names.js +2 -0
  438. package/dist/lib/mode-names.js.map +1 -1
  439. package/dist/mcp/__tests__/team-server-artifact-convergence.test.js +30 -3
  440. package/dist/mcp/__tests__/team-server-artifact-convergence.test.js.map +1 -1
  441. package/dist/mcp/__tests__/team-server-deprecation.test.js +2 -0
  442. package/dist/mcp/__tests__/team-server-deprecation.test.js.map +1 -1
  443. package/dist/mcp/team-job-convergence.d.ts.map +1 -1
  444. package/dist/mcp/team-job-convergence.js +12 -3
  445. package/dist/mcp/team-job-convergence.js.map +1 -1
  446. package/dist/mcp/team-server.d.ts.map +1 -1
  447. package/dist/mcp/team-server.js +18 -4
  448. package/dist/mcp/team-server.js.map +1 -1
  449. package/dist/notifications/__tests__/config-merge.test.js +36 -1
  450. package/dist/notifications/__tests__/config-merge.test.js.map +1 -1
  451. package/dist/notifications/__tests__/formatter.test.js +13 -5
  452. package/dist/notifications/__tests__/formatter.test.js.map +1 -1
  453. package/dist/notifications/__tests__/notify-registry-integration.test.js +27 -1
  454. package/dist/notifications/__tests__/notify-registry-integration.test.js.map +1 -1
  455. package/dist/notifications/__tests__/verbosity.test.js +33 -1
  456. package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
  457. package/dist/notifications/config.d.ts +7 -0
  458. package/dist/notifications/config.d.ts.map +1 -1
  459. package/dist/notifications/config.js +18 -0
  460. package/dist/notifications/config.js.map +1 -1
  461. package/dist/notifications/formatter.d.ts +2 -2
  462. package/dist/notifications/formatter.d.ts.map +1 -1
  463. package/dist/notifications/formatter.js +7 -6
  464. package/dist/notifications/formatter.js.map +1 -1
  465. package/dist/notifications/index.d.ts +1 -1
  466. package/dist/notifications/index.d.ts.map +1 -1
  467. package/dist/notifications/index.js +5 -3
  468. package/dist/notifications/index.js.map +1 -1
  469. package/dist/notifications/template-engine.js +1 -1
  470. package/dist/notifications/template-engine.js.map +1 -1
  471. package/dist/notifications/types.d.ts +4 -0
  472. package/dist/notifications/types.d.ts.map +1 -1
  473. package/dist/openclaw/__tests__/dispatcher.test.js +26 -0
  474. package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
  475. package/dist/openclaw/__tests__/index.test.js +42 -0
  476. package/dist/openclaw/__tests__/index.test.js.map +1 -1
  477. package/dist/openclaw/__tests__/signal.test.d.ts +2 -0
  478. package/dist/openclaw/__tests__/signal.test.d.ts.map +1 -0
  479. package/dist/openclaw/__tests__/signal.test.js +69 -0
  480. package/dist/openclaw/__tests__/signal.test.js.map +1 -0
  481. package/dist/openclaw/dispatcher.d.ts +5 -1
  482. package/dist/openclaw/dispatcher.d.ts.map +1 -1
  483. package/dist/openclaw/dispatcher.js +13 -2
  484. package/dist/openclaw/dispatcher.js.map +1 -1
  485. package/dist/openclaw/index.d.ts +2 -1
  486. package/dist/openclaw/index.d.ts.map +1 -1
  487. package/dist/openclaw/index.js +29 -15
  488. package/dist/openclaw/index.js.map +1 -1
  489. package/dist/openclaw/signal.d.ts +3 -0
  490. package/dist/openclaw/signal.d.ts.map +1 -0
  491. package/dist/openclaw/signal.js +215 -0
  492. package/dist/openclaw/signal.js.map +1 -0
  493. package/dist/openclaw/types.d.ts +35 -0
  494. package/dist/openclaw/types.d.ts.map +1 -1
  495. package/dist/shared/types.d.ts +2 -12
  496. package/dist/shared/types.d.ts.map +1 -1
  497. package/dist/skills/__tests__/mingw-escape.test.js +41 -11
  498. package/dist/skills/__tests__/mingw-escape.test.js.map +1 -1
  499. package/dist/team/__tests__/api-interop.cwd-resolution.test.d.ts +2 -0
  500. package/dist/team/__tests__/api-interop.cwd-resolution.test.d.ts.map +1 -0
  501. package/dist/team/__tests__/api-interop.cwd-resolution.test.js +78 -0
  502. package/dist/team/__tests__/api-interop.cwd-resolution.test.js.map +1 -0
  503. package/dist/team/__tests__/api-interop.dispatch.test.d.ts +2 -0
  504. package/dist/team/__tests__/api-interop.dispatch.test.d.ts.map +1 -0
  505. package/dist/team/__tests__/api-interop.dispatch.test.js +125 -0
  506. package/dist/team/__tests__/api-interop.dispatch.test.js.map +1 -0
  507. package/dist/team/__tests__/cli-detection.test.d.ts +2 -0
  508. package/dist/team/__tests__/cli-detection.test.d.ts.map +1 -0
  509. package/dist/team/__tests__/cli-detection.test.js +36 -0
  510. package/dist/team/__tests__/cli-detection.test.js.map +1 -0
  511. package/dist/team/__tests__/model-contract.test.js +79 -2
  512. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  513. package/dist/team/__tests__/runtime-done-recovery.test.js +1 -0
  514. package/dist/team/__tests__/runtime-done-recovery.test.js.map +1 -1
  515. package/dist/team/__tests__/runtime-prompt-mode.test.js +84 -8
  516. package/dist/team/__tests__/runtime-prompt-mode.test.js.map +1 -1
  517. package/dist/team/__tests__/runtime-v2.dispatch.test.d.ts +2 -0
  518. package/dist/team/__tests__/runtime-v2.dispatch.test.d.ts.map +1 -0
  519. package/dist/team/__tests__/runtime-v2.dispatch.test.js +237 -0
  520. package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -0
  521. package/dist/team/__tests__/runtime-v2.monitor.test.d.ts +2 -0
  522. package/dist/team/__tests__/runtime-v2.monitor.test.d.ts.map +1 -0
  523. package/dist/team/__tests__/runtime-v2.monitor.test.js +103 -0
  524. package/dist/team/__tests__/runtime-v2.monitor.test.js.map +1 -0
  525. package/dist/team/__tests__/runtime-v2.shutdown.test.d.ts +2 -0
  526. package/dist/team/__tests__/runtime-v2.shutdown.test.d.ts.map +1 -0
  527. package/dist/team/__tests__/runtime-v2.shutdown.test.js +49 -0
  528. package/dist/team/__tests__/runtime-v2.shutdown.test.js.map +1 -0
  529. package/dist/team/__tests__/runtime-watchdog-retry.test.js +3 -0
  530. package/dist/team/__tests__/runtime-watchdog-retry.test.js.map +1 -1
  531. package/dist/team/__tests__/tmux-session.create-team.test.js +29 -12
  532. package/dist/team/__tests__/tmux-session.create-team.test.js.map +1 -1
  533. package/dist/team/__tests__/tmux-session.kill-team-session.test.js +6 -0
  534. package/dist/team/__tests__/tmux-session.kill-team-session.test.js.map +1 -1
  535. package/dist/team/__tests__/tmux-session.test.js +9 -0
  536. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  537. package/dist/team/__tests__/worker-bootstrap.test.js +32 -3
  538. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  539. package/dist/team/api-interop.d.ts.map +1 -1
  540. package/dist/team/api-interop.js +153 -2
  541. package/dist/team/api-interop.js.map +1 -1
  542. package/dist/team/cli-detection.d.ts.map +1 -1
  543. package/dist/team/cli-detection.js +6 -2
  544. package/dist/team/cli-detection.js.map +1 -1
  545. package/dist/team/idle-nudge.js +1 -1
  546. package/dist/team/idle-nudge.js.map +1 -1
  547. package/dist/team/mcp-team-bridge.d.ts.map +1 -1
  548. package/dist/team/mcp-team-bridge.js +2 -1
  549. package/dist/team/mcp-team-bridge.js.map +1 -1
  550. package/dist/team/model-contract.d.ts +1 -1
  551. package/dist/team/model-contract.d.ts.map +1 -1
  552. package/dist/team/model-contract.js +35 -4
  553. package/dist/team/model-contract.js.map +1 -1
  554. package/dist/team/runtime-cli.d.ts.map +1 -1
  555. package/dist/team/runtime-cli.js +10 -7
  556. package/dist/team/runtime-cli.js.map +1 -1
  557. package/dist/team/runtime-v2.d.ts +4 -0
  558. package/dist/team/runtime-v2.d.ts.map +1 -1
  559. package/dist/team/runtime-v2.js +231 -59
  560. package/dist/team/runtime-v2.js.map +1 -1
  561. package/dist/team/runtime.d.ts +6 -1
  562. package/dist/team/runtime.d.ts.map +1 -1
  563. package/dist/team/runtime.js +39 -14
  564. package/dist/team/runtime.js.map +1 -1
  565. package/dist/team/tmux-session.d.ts +20 -11
  566. package/dist/team/tmux-session.d.ts.map +1 -1
  567. package/dist/team/tmux-session.js +108 -51
  568. package/dist/team/tmux-session.js.map +1 -1
  569. package/dist/team/types.d.ts +1 -0
  570. package/dist/team/types.d.ts.map +1 -1
  571. package/dist/team/types.js.map +1 -1
  572. package/dist/team/worker-bootstrap.d.ts +2 -0
  573. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  574. package/dist/team/worker-bootstrap.js +46 -12
  575. package/dist/team/worker-bootstrap.js.map +1 -1
  576. package/dist/tools/__tests__/memory-tools.test.js +29 -1
  577. package/dist/tools/__tests__/memory-tools.test.js.map +1 -1
  578. package/dist/tools/lsp/client.d.ts +11 -0
  579. package/dist/tools/lsp/client.d.ts.map +1 -1
  580. package/dist/tools/lsp/client.js +46 -0
  581. package/dist/tools/lsp/client.js.map +1 -1
  582. package/dist/tools/session-history-tools.d.ts +23 -0
  583. package/dist/tools/session-history-tools.d.ts.map +1 -0
  584. package/dist/tools/session-history-tools.js +41 -0
  585. package/dist/tools/session-history-tools.js.map +1 -0
  586. package/dist/tools/trace-tools.d.ts +9 -0
  587. package/dist/tools/trace-tools.d.ts.map +1 -1
  588. package/dist/tools/trace-tools.js +2 -1
  589. package/dist/tools/trace-tools.js.map +1 -1
  590. package/dist/utils/frontmatter.d.ts +5 -0
  591. package/dist/utils/frontmatter.d.ts.map +1 -1
  592. package/dist/utils/frontmatter.js +22 -0
  593. package/dist/utils/frontmatter.js.map +1 -1
  594. package/dist/utils/skill-pipeline.d.ts +9 -0
  595. package/dist/utils/skill-pipeline.d.ts.map +1 -0
  596. package/dist/utils/skill-pipeline.js +97 -0
  597. package/dist/utils/skill-pipeline.js.map +1 -0
  598. package/docs/AGENTS.md +1 -1
  599. package/docs/ANALYTICS-SYSTEM.md +23 -132
  600. package/docs/CLAUDE.md +40 -139
  601. package/docs/MIGRATION.md +4 -4
  602. package/docs/OPENCLAW-ROUTING.md +102 -0
  603. package/docs/PERFORMANCE-MONITORING.md +30 -55
  604. package/docs/REFERENCE.md +62 -35
  605. package/docs/TIERED_AGENTS_V2.md +3 -2
  606. package/docs/design/SKILL_AUDIT_1445.md +75 -0
  607. package/docs/ko/MIGRATION.md +2 -2
  608. package/docs/ko/REFERENCE.md +14 -22
  609. package/docs/partials/agent-tiers.md +11 -15
  610. package/docs/partials/features.md +2 -2
  611. package/docs/partials/mode-selection-guide.md +2 -2
  612. package/docs/shared/agent-tiers.md +11 -15
  613. package/docs/shared/features.md +2 -2
  614. package/docs/shared/mode-selection-guide.md +2 -2
  615. package/package.json +4 -1
  616. package/scripts/code-simplifier.mjs +1 -1
  617. package/scripts/context-guard-stop.mjs +26 -10
  618. package/scripts/keyword-detector.mjs +99 -39
  619. package/scripts/persistent-mode.cjs +295 -34
  620. package/scripts/persistent-mode.mjs +79 -21
  621. package/scripts/plugin-setup.mjs +10 -1
  622. package/scripts/post-tool-verifier.mjs +57 -3
  623. package/scripts/pre-tool-enforcer.mjs +207 -2
  624. package/scripts/run-provider-advisor.js +30 -3
  625. package/scripts/session-start.mjs +3 -3
  626. package/scripts/setup-claude-md.sh +159 -0
  627. package/scripts/setup-progress.sh +123 -0
  628. package/scripts/sync-metadata.ts +11 -1
  629. package/skills/AGENTS.md +13 -17
  630. package/skills/ai-slop-cleaner/SKILL.md +130 -0
  631. package/skills/ask/SKILL.md +51 -0
  632. package/skills/ccg/SKILL.md +6 -6
  633. package/skills/deep-interview/SKILL.md +4 -0
  634. package/skills/omc-doctor/SKILL.md +2 -2
  635. package/skills/omc-setup/SKILL.md +75 -1206
  636. package/skills/omc-setup/phases/01-install-claude-md.md +76 -0
  637. package/skills/omc-setup/phases/02-configure.md +211 -0
  638. package/skills/omc-setup/phases/03-integrations.md +192 -0
  639. package/skills/omc-setup/phases/04-welcome.md +192 -0
  640. package/skills/omc-teams/SKILL.md +35 -2
  641. package/skills/plan/SKILL.md +3 -0
  642. package/skills/ralph/SKILL.md +16 -10
  643. package/skills/release/SKILL.md +4 -0
  644. package/skills/setup/SKILL.md +40 -0
  645. package/skills/team/SKILL.md +6 -6
  646. package/templates/hooks/code-simplifier.mjs +1 -1
  647. package/templates/hooks/keyword-detector.mjs +100 -32
  648. package/templates/hooks/persistent-mode.mjs +43 -4
  649. package/templates/hooks/pre-tool-use.mjs +115 -1
  650. package/templates/hooks/session-start.mjs +1 -1
  651. package/agents/build-fixer.md +0 -90
  652. package/agents/deep-executor.md +0 -112
  653. package/agents/harsh-critic.md +0 -254
  654. package/agents/quality-reviewer.md +0 -151
  655. package/skills/analyze/SKILL.md +0 -87
  656. package/skills/ask-codex/SKILL.md +0 -47
  657. package/skills/ask-gemini/SKILL.md +0 -47
  658. package/skills/build-fix/SKILL.md +0 -123
  659. package/skills/code-review/SKILL.md +0 -573
  660. package/skills/configure-openclaw/SKILL.md +0 -383
  661. package/skills/learn-about-omc/SKILL.md +0 -37
  662. package/skills/note/SKILL.md +0 -62
  663. package/skills/omc-help/SKILL.md +0 -192
  664. package/skills/ralph-init/SKILL.md +0 -40
  665. package/skills/security-review/SKILL.md +0 -282
  666. package/skills/tdd/SKILL.md +0 -104
  667. package/skills/trace/SKILL.md +0 -33
@@ -14,6 +14,7 @@ const {
14
14
  writeFileSync,
15
15
  readdirSync,
16
16
  mkdirSync,
17
+ unlinkSync,
17
18
  } = require("fs");
18
19
  const { join, dirname, resolve, normalize } = require("path");
19
20
  const { homedir } = require("os");
@@ -130,6 +131,35 @@ async function sendStopNotification(modeName, stateData, sessionId, directory) {
130
131
  */
131
132
  const STALE_STATE_THRESHOLD_MS = 2 * 60 * 60 * 1000; // 2 hours
132
133
 
134
+ // Stop breaker constants for first-class mode enforcement
135
+ const TEAM_PIPELINE_STOP_BLOCKER_MAX = 20;
136
+ const TEAM_PIPELINE_STOP_BLOCKER_TTL_MS = 5 * 60 * 1000; // 5 min
137
+ const RALPLAN_STOP_BLOCKER_MAX = 30;
138
+ const RALPLAN_STOP_BLOCKER_TTL_MS = 45 * 60 * 1000; // 45 min
139
+ const TEAM_TERMINAL_PHASES = new Set([
140
+ "completed",
141
+ "complete",
142
+ "failed",
143
+ "cancelled",
144
+ "canceled",
145
+ "aborted",
146
+ "terminated",
147
+ "done",
148
+ ]);
149
+ const TEAM_ACTIVE_PHASES = new Set([
150
+ "team-plan",
151
+ "team-prd",
152
+ "team-exec",
153
+ "team-verify",
154
+ "team-fix",
155
+ "planning",
156
+ "executing",
157
+ "verify",
158
+ "verification",
159
+ "fix",
160
+ "fixing",
161
+ ]);
162
+
133
163
  /**
134
164
  * Check if a state is stale based on its timestamps.
135
165
  * A state is considered stale if it hasn't been updated recently.
@@ -150,6 +180,63 @@ function isStaleState(state) {
150
180
  return age > STALE_STATE_THRESHOLD_MS;
151
181
  }
152
182
 
183
+ function normalizeTeamPhase(state) {
184
+ if (!state || typeof state !== "object") return null;
185
+
186
+ const rawPhase = state.current_phase ?? state.phase ?? state.stage;
187
+ if (typeof rawPhase !== "string") return null;
188
+
189
+ const phase = rawPhase.trim().toLowerCase();
190
+ if (!phase || TEAM_TERMINAL_PHASES.has(phase)) return null;
191
+ return TEAM_ACTIVE_PHASES.has(phase) ? phase : null;
192
+ }
193
+
194
+ function getSafeReinforcementCount(value) {
195
+ return typeof value === "number" && Number.isFinite(value) && value >= 0
196
+ ? Math.floor(value)
197
+ : 0;
198
+ }
199
+
200
+ // ---------------------------------------------------------------------------
201
+ // Stop Breaker helpers (shared by team pipeline and ralplan)
202
+ // ---------------------------------------------------------------------------
203
+
204
+ function readStopBreaker(stateDir, name, sessionId, ttlMs) {
205
+ const dir = sessionId
206
+ ? join(stateDir, "sessions", sessionId)
207
+ : stateDir;
208
+ const breakerPath = join(dir, `${name}-stop-breaker.json`);
209
+
210
+ try {
211
+ if (!existsSync(breakerPath)) return 0;
212
+ const raw = JSON.parse(readFileSync(breakerPath, "utf-8"));
213
+ if (ttlMs && raw.updated_at) {
214
+ const updatedAt = new Date(raw.updated_at).getTime();
215
+ if (Number.isFinite(updatedAt) && Date.now() - updatedAt > ttlMs) {
216
+ unlinkSync(breakerPath);
217
+ return 0;
218
+ }
219
+ }
220
+ return typeof raw.count === "number" ? raw.count : 0;
221
+ } catch {
222
+ return 0;
223
+ }
224
+ }
225
+
226
+ function writeStopBreaker(stateDir, name, count, sessionId) {
227
+ const dir = sessionId
228
+ ? join(stateDir, "sessions", sessionId)
229
+ : stateDir;
230
+
231
+ try {
232
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
233
+ const breakerPath = join(dir, `${name}-stop-breaker.json`);
234
+ writeJsonFile(breakerPath, { count, updated_at: new Date().toISOString() });
235
+ } catch {
236
+ // Fail-open
237
+ }
238
+ }
239
+
153
240
  /**
154
241
  * Check if a cancel signal is in progress for the session.
155
242
  * Cancel signals are written by state_clear and expire after 30 seconds.
@@ -255,7 +342,26 @@ function readStateFileWithSession(stateDir, filename, sessionId) {
255
342
  if (state) {
256
343
  return { state, path: sessionPath, isGlobal: false };
257
344
  }
258
- // Session path not found — do NOT fall back to legacy
345
+ // Session path not found — fallback: scan ALL session dirs for a state
346
+ // whose session_id matches ours (handles path mismatches)
347
+ try {
348
+ const allSessionsDir = join(stateDir, 'sessions');
349
+ if (existsSync(allSessionsDir)) {
350
+ const dirs = readdirSync(allSessionsDir).filter(d => /^[a-zA-Z0-9]/.test(d));
351
+ for (const dir of dirs) {
352
+ const candidatePath = join(allSessionsDir, dir, filename);
353
+ const candidateState = readJsonFile(candidatePath);
354
+ if (candidateState && candidateState.session_id === sessionId) {
355
+ return { state: candidateState, path: candidatePath, isGlobal: false };
356
+ }
357
+ }
358
+ }
359
+ } catch { /* ignore scan errors */ }
360
+ // Also check legacy path if its session_id matches
361
+ const legacyResult = readStateFile(stateDir, filename);
362
+ if (legacyResult.state && legacyResult.state.session_id === sessionId) {
363
+ return legacyResult;
364
+ }
259
365
  return { state: null, path: null, isGlobal: false };
260
366
  }
261
367
  // No sessionId: fall back to legacy path (backward compat)
@@ -355,7 +461,15 @@ function countIncompleteTodos(sessionId, projectDir) {
355
461
  * See: https://github.com/Yeachan-Heo/oh-my-claudecode/issues/213
356
462
  */
357
463
  function isContextLimitStop(data) {
358
- const reason = (data.stop_reason || data.stopReason || "").toLowerCase();
464
+ const reasons = [
465
+ data.stop_reason,
466
+ data.stopReason,
467
+ data.end_turn_reason,
468
+ data.endTurnReason,
469
+ data.reason,
470
+ ]
471
+ .filter((value) => typeof value === "string" && value.trim().length > 0)
472
+ .map((value) => value.toLowerCase().replace(/[\s-]+/g, "_"));
359
473
 
360
474
  const contextPatterns = [
361
475
  "context_limit",
@@ -369,20 +483,27 @@ function isContextLimitStop(data) {
369
483
  "input_too_long",
370
484
  ];
371
485
 
372
- if (contextPatterns.some((p) => reason.includes(p))) {
373
- return true;
374
- }
486
+ return reasons.some((reason) => contextPatterns.some((p) => reason.includes(p)));
487
+ }
375
488
 
376
- const endTurnReason = (
377
- data.end_turn_reason ||
378
- data.endTurnReason ||
379
- ""
380
- ).toLowerCase();
381
- if (endTurnReason && contextPatterns.some((p) => endTurnReason.includes(p))) {
382
- return true;
383
- }
489
+ const CRITICAL_CONTEXT_STOP_PERCENT = 95;
384
490
 
385
- return false;
491
+ function estimateContextPercent(transcriptPath) {
492
+ if (!transcriptPath || !existsSync(transcriptPath)) return 0;
493
+
494
+ try {
495
+ const content = readFileSync(transcriptPath, "utf-8");
496
+ const windowMatch = content.match(/"context_window"\s{0,5}:\s{0,5}(\d+)/g);
497
+ const inputMatch = content.match(/"input_tokens"\s{0,5}:\s{0,5}(\d+)/g);
498
+ if (!windowMatch || !inputMatch) return 0;
499
+
500
+ const lastWindow = parseInt(windowMatch[windowMatch.length - 1].match(/(\d+)/)[1], 10);
501
+ const lastInput = parseInt(inputMatch[inputMatch.length - 1].match(/(\d+)/)[1], 10);
502
+ if (!Number.isFinite(lastWindow) || lastWindow <= 0 || !Number.isFinite(lastInput)) return 0;
503
+ return Math.round((lastInput / lastWindow) * 100);
504
+ } catch {
505
+ return 0;
506
+ }
386
507
  }
387
508
 
388
509
  /**
@@ -460,6 +581,12 @@ async function main() {
460
581
  return;
461
582
  }
462
583
 
584
+ const criticalTranscriptPath = data.transcript_path || data.transcriptPath || "";
585
+ if (estimateContextPercent(criticalTranscriptPath) >= CRITICAL_CONTEXT_STOP_PERCENT) {
586
+ console.log(JSON.stringify({ continue: true, suppressOutput: true }));
587
+ return;
588
+ }
589
+
463
590
  // Respect user abort (Ctrl+C, cancel)
464
591
  if (isUserAbort(data)) {
465
592
  console.log(JSON.stringify({ continue: true, suppressOutput: true }));
@@ -480,6 +607,7 @@ async function main() {
480
607
  const ultraqa = readStateFileWithSession(stateDir, "ultraqa-state.json", sessionId);
481
608
  const pipeline = readStateFileWithSession(stateDir, "pipeline-state.json", sessionId);
482
609
  const team = readStateFileWithSession(stateDir, "team-state.json", sessionId);
610
+ const ralplan = readStateFileWithSession(stateDir, "ralplan-state.json", sessionId);
483
611
  const omcTeams = readStateFileWithSession(stateDir, "omc-teams-state.json", sessionId);
484
612
 
485
613
  // Swarm uses swarm-summary.json (not swarm-state.json) + marker file
@@ -492,7 +620,9 @@ async function main() {
492
620
  const totalIncomplete = taskCount + todoCount;
493
621
 
494
622
  // Check if cancel is in progress - if so, allow stop immediately
495
- if (isSessionCancelInProgress(stateDir, sessionId)) {
623
+ // Cache the result to pass to sub-checks (avoids TOCTOU re-reads, issue #1058)
624
+ const cancelInProgress = isSessionCancelInProgress(stateDir, sessionId);
625
+ if (cancelInProgress) {
496
626
  console.log(JSON.stringify({ continue: true, suppressOutput: true }));
497
627
  return;
498
628
  }
@@ -513,7 +643,7 @@ async function main() {
513
643
 
514
644
  console.log(
515
645
  JSON.stringify({
516
- decision: "block",
646
+ continue: false, decision: "block",
517
647
  reason: `[RALPH LOOP - ITERATION ${iteration + 1}/${maxIter}] Work is NOT done. Continue working.\nWhen FULLY complete (after Architect verification), run /oh-my-claudecode:cancel to cleanly exit ralph mode and clean up all state files. If cancel fails, retry with /oh-my-claudecode:cancel --force.\n${ralph.state.prompt ? `Task: ${ralph.state.prompt}` : ""}`,
518
648
  }),
519
649
  );
@@ -536,7 +666,7 @@ async function main() {
536
666
 
537
667
  console.log(
538
668
  JSON.stringify({
539
- decision: "block",
669
+ continue: false, decision: "block",
540
670
  reason: `[AUTOPILOT - Phase: ${phase}] Autopilot not complete. Continue working. When all phases are complete, run /oh-my-claudecode:cancel to cleanly exit and clean up state files. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
541
671
  }),
542
672
  );
@@ -545,6 +675,102 @@ async function main() {
545
675
  }
546
676
  }
547
677
 
678
+ // Priority 2.5: Team Pipeline (standalone team mode — first-class enforcement)
679
+ // When team runs WITHOUT ralph, this provides stop-hook blocking.
680
+ // When team runs WITH ralph, checkRalphLoop (Priority 1) handles it.
681
+ let teamPipelineHandled = false;
682
+ if (team.state && isSessionMatch(team.state, sessionId)) {
683
+ if (!team.state.active) {
684
+ // Inactive — reset breaker, allow stop, mark as handled
685
+ writeStopBreaker(stateDir, "team-pipeline", 0, sessionId);
686
+ teamPipelineHandled = true;
687
+ } else if (!isStaleState(team.state)) {
688
+ teamPipelineHandled = true;
689
+
690
+ // Cancel-in-progress bypass (TOCTOU defense, issue #1058)
691
+ if (!cancelInProgress) {
692
+ // Read phase: canonical field priority matching bridge code
693
+ const rawPhase = team.state.phase
694
+ ?? team.state.current_phase
695
+ ?? team.state.currentStage
696
+ ?? team.state.current_stage
697
+ ?? team.state.stage;
698
+
699
+ if (typeof rawPhase !== "string") {
700
+ // No valid phase — fail-open (don't block)
701
+ } else {
702
+ const phase = rawPhase.trim().toLowerCase();
703
+
704
+ if (TEAM_TERMINAL_PHASES.has(phase) || phase === "cancel") {
705
+ // Terminal — reset breaker, allow stop
706
+ writeStopBreaker(stateDir, "team-pipeline", 0, sessionId);
707
+ } else if (!TEAM_ACTIVE_PHASES.has(phase)) {
708
+ // Unknown phase — fail-open (don't block)
709
+ } else {
710
+ // Status-level terminal check
711
+ const rawStatus = team.state.status;
712
+ const status = typeof rawStatus === "string" ? rawStatus.trim().toLowerCase() : null;
713
+ if (status && TEAM_TERMINAL_PHASES.has(status)) {
714
+ writeStopBreaker(stateDir, "team-pipeline", 0, sessionId);
715
+ } else if (team.state.cancel?.requested) {
716
+ // Cancel requested — allow stop
717
+ writeStopBreaker(stateDir, "team-pipeline", 0, sessionId);
718
+ } else {
719
+ // Active phase — block with circuit breaker
720
+ const breakerCount = readStopBreaker(stateDir, "team-pipeline", sessionId, TEAM_PIPELINE_STOP_BLOCKER_TTL_MS) + 1;
721
+ if (breakerCount > TEAM_PIPELINE_STOP_BLOCKER_MAX) {
722
+ writeStopBreaker(stateDir, "team-pipeline", 0, sessionId);
723
+ // Circuit breaker tripped — allow stop
724
+ } else {
725
+ writeStopBreaker(stateDir, "team-pipeline", breakerCount, sessionId);
726
+ sendStopNotification("team", team.state, sessionId, directory).catch(() => {});
727
+
728
+ console.log(JSON.stringify({
729
+ continue: false, decision: "block",
730
+ reason: `[TEAM PIPELINE - PHASE: ${phase.toUpperCase()} | REINFORCEMENT ${breakerCount}/${TEAM_PIPELINE_STOP_BLOCKER_MAX}] The team pipeline is active in phase "${phase}". Continue working on the team workflow. Do not stop until the pipeline reaches a terminal state (complete/failed/cancelled). When done, run /oh-my-claudecode:cancel to cleanly exit.`,
731
+ }));
732
+ return;
733
+ }
734
+ }
735
+ }
736
+ }
737
+ }
738
+ }
739
+ }
740
+
741
+ // Priority 2.6: Ralplan (standalone consensus planning — first-class enforcement)
742
+ if (ralplan.state?.active && !isStaleState(ralplan.state) && isSessionMatch(ralplan.state, sessionId)) {
743
+ // Terminal phase detection
744
+ const currentPhase = ralplan.state.current_phase;
745
+ let ralplanTerminal = false;
746
+ if (typeof currentPhase === "string") {
747
+ const terminal = ["complete", "completed", "failed", "cancelled", "canceled", "done"];
748
+ if (terminal.includes(currentPhase.toLowerCase())) {
749
+ writeStopBreaker(stateDir, "ralplan", 0, sessionId);
750
+ ralplanTerminal = true;
751
+ }
752
+ }
753
+
754
+ if (!ralplanTerminal && !cancelInProgress) {
755
+ // Circuit breaker
756
+ const breakerCount = readStopBreaker(stateDir, "ralplan", sessionId, RALPLAN_STOP_BLOCKER_TTL_MS) + 1;
757
+ if (breakerCount > RALPLAN_STOP_BLOCKER_MAX) {
758
+ writeStopBreaker(stateDir, "ralplan", 0, sessionId);
759
+ // Circuit breaker tripped — allow stop
760
+ } else {
761
+ writeStopBreaker(stateDir, "ralplan", breakerCount, sessionId);
762
+
763
+ sendStopNotification("ralplan", ralplan.state, sessionId, directory).catch(() => {});
764
+
765
+ console.log(JSON.stringify({
766
+ continue: false, decision: "block",
767
+ reason: `[RALPLAN - CONSENSUS PLANNING | REINFORCEMENT ${breakerCount}/${RALPLAN_STOP_BLOCKER_MAX}] The ralplan consensus workflow is active. Continue the Planner/Architect/Critic loop. Do not stop until consensus is reached or the workflow completes. When done, run /oh-my-claudecode:cancel to cleanly exit.`,
768
+ }));
769
+ return;
770
+ }
771
+ }
772
+ }
773
+
548
774
  // Priority 3: Ultrapilot (parallel autopilot)
549
775
  if (ultrapilot.state?.active && !isStaleState(ultrapilot.state) && isSessionMatch(ultrapilot.state, sessionId)) {
550
776
  const workers = ultrapilot.state.workers || [];
@@ -563,7 +789,7 @@ async function main() {
563
789
 
564
790
  console.log(
565
791
  JSON.stringify({
566
- decision: "block",
792
+ continue: false, decision: "block",
567
793
  reason: `[ULTRAPILOT] ${incomplete} workers still running. Continue working. When all workers complete, run /oh-my-claudecode:cancel to cleanly exit and clean up state files. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
568
794
  }),
569
795
  );
@@ -588,7 +814,7 @@ async function main() {
588
814
 
589
815
  console.log(
590
816
  JSON.stringify({
591
- decision: "block",
817
+ continue: false, decision: "block",
592
818
  reason: `[SWARM ACTIVE] ${pending} tasks remain. Continue working. When all tasks are done, run /oh-my-claudecode:cancel to cleanly exit and clean up state files. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
593
819
  }),
594
820
  );
@@ -613,7 +839,7 @@ async function main() {
613
839
 
614
840
  console.log(
615
841
  JSON.stringify({
616
- decision: "block",
842
+ continue: false, decision: "block",
617
843
  reason: `[PIPELINE - Stage ${currentStage + 1}/${totalStages}] Pipeline not complete. Continue working. When all stages complete, run /oh-my-claudecode:cancel to cleanly exit and clean up state files. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
618
844
  }),
619
845
  );
@@ -622,12 +848,11 @@ async function main() {
622
848
  }
623
849
  }
624
850
 
625
- // Priority 6: Team (native Claude Code teams)
626
- if (team.state?.active && !isStaleState(team.state) && isSessionMatch(team.state, sessionId)) {
627
- const phase = team.state.current_phase || "executing";
628
- const terminalPhases = ["completed", "complete", "failed", "cancelled"];
629
- if (!terminalPhases.includes(phase)) {
630
- const newCount = (team.state.reinforcement_count || 0) + 1;
851
+ // Priority 6: Team (native Claude Code teams) — fallback for cases not handled by Priority 2.5
852
+ if (!teamPipelineHandled && team.state?.active && !isStaleState(team.state) && isSessionMatch(team.state, sessionId)) {
853
+ const phase = normalizeTeamPhase(team.state);
854
+ if (phase) {
855
+ const newCount = getSafeReinforcementCount(team.state.reinforcement_count) + 1;
631
856
  if (newCount <= 20) {
632
857
  team.state.reinforcement_count = newCount;
633
858
  team.state.last_checked_at = new Date().toISOString();
@@ -638,7 +863,7 @@ async function main() {
638
863
 
639
864
  console.log(
640
865
  JSON.stringify({
641
- decision: "block",
866
+ continue: false, decision: "block",
642
867
  reason: `[TEAM - Phase: ${phase}] Team mode active. Continue working. When all team tasks complete, run /oh-my-claudecode:cancel to cleanly exit. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
643
868
  }),
644
869
  );
@@ -649,10 +874,9 @@ async function main() {
649
874
 
650
875
  // Priority 6.5: OMC Teams (tmux CLI workers — independent of native team state)
651
876
  if (omcTeams.state?.active && !isStaleState(omcTeams.state) && isSessionMatch(omcTeams.state, sessionId)) {
652
- const phase = omcTeams.state.current_phase || "executing";
653
- const terminalPhases = ["completed", "complete", "failed", "cancelled"];
654
- if (!terminalPhases.includes(phase)) {
655
- const newCount = (omcTeams.state.reinforcement_count || 0) + 1;
877
+ const phase = normalizeTeamPhase(omcTeams.state);
878
+ if (phase) {
879
+ const newCount = getSafeReinforcementCount(omcTeams.state.reinforcement_count) + 1;
656
880
  if (newCount <= 20) {
657
881
  omcTeams.state.reinforcement_count = newCount;
658
882
  omcTeams.state.last_checked_at = new Date().toISOString();
@@ -663,7 +887,7 @@ async function main() {
663
887
 
664
888
  console.log(
665
889
  JSON.stringify({
666
- decision: "block",
890
+ continue: false, decision: "block",
667
891
  reason: `[OMC TEAMS - Phase: ${phase}] OMC Teams workers active. Continue working. When all workers complete, run /oh-my-claudecode:cancel to cleanly exit. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
668
892
  }),
669
893
  );
@@ -686,7 +910,7 @@ async function main() {
686
910
 
687
911
  console.log(
688
912
  JSON.stringify({
689
- decision: "block",
913
+ continue: false, decision: "block",
690
914
  reason: `[ULTRAQA - Cycle ${cycle + 1}/${maxCycles}] Tests not all passing. Continue fixing. When all tests pass, run /oh-my-claudecode:cancel to cleanly exit and clean up state files. If cancel fails, retry with /oh-my-claudecode:cancel --force.`,
691
915
  }),
692
916
  );
@@ -737,10 +961,47 @@ async function main() {
737
961
  reason += `\nTask: ${ultrawork.state.original_prompt}`;
738
962
  }
739
963
 
740
- console.log(JSON.stringify({ decision: "block", reason }));
964
+ console.log(JSON.stringify({ continue: false, decision: "block", reason }));
741
965
  return;
742
966
  }
743
967
 
968
+ // Priority 9: Skill Active State (issue #1033)
969
+ // Skills like code-review, plan, ralplan, tdd, etc. write skill-active-state.json
970
+ // when invoked via the Skill tool. This prevents premature stops mid-skill.
971
+ {
972
+ const skillState = readStateFileWithSession(stateDir, "skill-active-state.json", sessionId);
973
+ if (skillState.state?.active) {
974
+ // Staleness check (per-skill TTL)
975
+ const sLastChecked = skillState.state.last_checked_at ? new Date(skillState.state.last_checked_at).getTime() : 0;
976
+ const sStartedAt = skillState.state.started_at ? new Date(skillState.state.started_at).getTime() : 0;
977
+ const sMostRecent = Math.max(sLastChecked, sStartedAt);
978
+ const sTtl = skillState.state.stale_ttl_ms || 5 * 60 * 1000;
979
+ const sAge = sMostRecent > 0 ? Date.now() - sMostRecent : Infinity;
980
+ const isStale = sMostRecent === 0 || sAge > sTtl;
981
+
982
+ if (!isStale && isSessionMatch(skillState.state, sessionId)) {
983
+ const count = skillState.state.reinforcement_count || 0;
984
+ const maxReinforcements = skillState.state.max_reinforcements || 3;
985
+
986
+ if (count < maxReinforcements) {
987
+ skillState.state.reinforcement_count = count + 1;
988
+ skillState.state.last_checked_at = new Date().toISOString();
989
+ writeJsonFile(skillState.path, skillState.state);
990
+
991
+ const skillName = skillState.state.skill_name || "unknown";
992
+ console.log(JSON.stringify({
993
+ continue: false, decision: "block",
994
+ reason: `[SKILL ACTIVE: ${skillName}] The "${skillName}" skill is still executing (reinforcement ${count + 1}/${maxReinforcements}). Continue working on the skill's instructions. Do not stop until the skill completes its workflow.`,
995
+ }));
996
+ return;
997
+ } else {
998
+ // Reinforcement limit reached - clear state and allow stop
999
+ try { if (skillState.path && existsSync(skillState.path)) unlinkSync(skillState.path); } catch {}
1000
+ }
1001
+ }
1002
+ }
1003
+ }
1004
+
744
1005
  // No blocking needed — Claude is truly idle.
745
1006
  // Send session-idle notification (fire-and-forget) so external integrations
746
1007
  // (Telegram, Discord) know the session went idle without any active mode.
@@ -132,6 +132,29 @@ Do NOT skip this step. Do NOT move on without fixing the error.
132
132
  * from causing the stop hook to malfunction in new sessions.
133
133
  */
134
134
  const STALE_STATE_THRESHOLD_MS = 2 * 60 * 60 * 1000; // 2 hours
135
+ const TEAM_TERMINAL_PHASES = new Set([
136
+ "completed",
137
+ "complete",
138
+ "failed",
139
+ "cancelled",
140
+ "canceled",
141
+ "aborted",
142
+ "terminated",
143
+ "done",
144
+ ]);
145
+ const TEAM_ACTIVE_PHASES = new Set([
146
+ "team-plan",
147
+ "team-prd",
148
+ "team-exec",
149
+ "team-verify",
150
+ "team-fix",
151
+ "planning",
152
+ "executing",
153
+ "verify",
154
+ "verification",
155
+ "fix",
156
+ "fixing",
157
+ ]);
135
158
 
136
159
  /**
137
160
  * Check if a state is stale based on its timestamps.
@@ -153,6 +176,23 @@ function isStaleState(state) {
153
176
  return age > STALE_STATE_THRESHOLD_MS;
154
177
  }
155
178
 
179
+ function normalizeTeamPhase(state) {
180
+ if (!state || typeof state !== "object") return null;
181
+
182
+ const rawPhase = state.current_phase ?? state.phase ?? state.stage;
183
+ if (typeof rawPhase !== "string") return null;
184
+
185
+ const phase = rawPhase.trim().toLowerCase();
186
+ if (!phase || TEAM_TERMINAL_PHASES.has(phase)) return null;
187
+ return TEAM_ACTIVE_PHASES.has(phase) ? phase : null;
188
+ }
189
+
190
+ function getSafeReinforcementCount(value) {
191
+ return typeof value === "number" && Number.isFinite(value) && value >= 0
192
+ ? Math.floor(value)
193
+ : 0;
194
+ }
195
+
156
196
  /**
157
197
  * Normalize a path for comparison.
158
198
  */
@@ -325,7 +365,15 @@ function countIncompleteTodos(sessionId, projectDir) {
325
365
  * See: https://github.com/Yeachan-Heo/oh-my-claudecode/issues/213
326
366
  */
327
367
  function isContextLimitStop(data) {
328
- const reason = (data.stop_reason || data.stopReason || "").toLowerCase();
368
+ const reasons = [
369
+ data.stop_reason,
370
+ data.stopReason,
371
+ data.end_turn_reason,
372
+ data.endTurnReason,
373
+ data.reason,
374
+ ]
375
+ .filter((value) => typeof value === "string" && value.trim().length > 0)
376
+ .map((value) => value.toLowerCase().replace(/[\s-]+/g, "_"));
329
377
 
330
378
  const contextPatterns = [
331
379
  "context_limit",
@@ -339,20 +387,26 @@ function isContextLimitStop(data) {
339
387
  "input_too_long",
340
388
  ];
341
389
 
342
- if (contextPatterns.some((p) => reason.includes(p))) {
343
- return true;
344
- }
390
+ return reasons.some((reason) => contextPatterns.some((p) => reason.includes(p)));
391
+ }
345
392
 
346
- const endTurnReason = (
347
- data.end_turn_reason ||
348
- data.endTurnReason ||
349
- ""
350
- ).toLowerCase();
351
- if (endTurnReason && contextPatterns.some((p) => endTurnReason.includes(p))) {
352
- return true;
353
- }
393
+ const CRITICAL_CONTEXT_STOP_PERCENT = 95;
354
394
 
355
- return false;
395
+ function estimateContextPercent(transcriptPath) {
396
+ if (!transcriptPath || !existsSync(transcriptPath)) return 0;
397
+ try {
398
+ const content = readFileSync(transcriptPath, "utf-8");
399
+ const windowMatch = content.match(/"context_window"\s{0,5}:\s{0,5}(\d+)/g);
400
+ const inputMatch = content.match(/"input_tokens"\s{0,5}:\s{0,5}(\d+)/g);
401
+ if (!windowMatch || !inputMatch) return 0;
402
+
403
+ const lastWindow = parseInt(windowMatch[windowMatch.length - 1].match(/(\d+)/)[1], 10);
404
+ const lastInput = parseInt(inputMatch[inputMatch.length - 1].match(/(\d+)/)[1], 10);
405
+ if (!Number.isFinite(lastWindow) || lastWindow <= 0 || !Number.isFinite(lastInput)) return 0;
406
+ return Math.round((lastInput / lastWindow) * 100);
407
+ } catch {
408
+ return 0;
409
+ }
356
410
  }
357
411
 
358
412
  /**
@@ -433,6 +487,12 @@ async function main() {
433
487
  return;
434
488
  }
435
489
 
490
+ const criticalTranscriptPath = data.transcript_path || data.transcriptPath || "";
491
+ if (estimateContextPercent(criticalTranscriptPath) >= CRITICAL_CONTEXT_STOP_PERCENT) {
492
+ console.log(JSON.stringify({ continue: true, suppressOutput: true }));
493
+ return;
494
+ }
495
+
436
496
  // Respect user abort (Ctrl+C, cancel)
437
497
  if (isUserAbort(data)) {
438
498
  console.log(JSON.stringify({ continue: true, suppressOutput: true }));
@@ -720,10 +780,9 @@ async function main() {
720
780
  ? team.state.session_id === sessionId
721
781
  : !team.state.session_id || team.state.session_id === sessionId;
722
782
  if (sessionMatches) {
723
- const phase = team.state.current_phase || "executing";
724
- const terminalPhases = ["completed", "complete", "failed", "cancelled"];
725
- if (!terminalPhases.includes(phase)) {
726
- const newCount = (team.state.reinforcement_count || 0) + 1;
783
+ const phase = normalizeTeamPhase(team.state);
784
+ if (phase) {
785
+ const newCount = getSafeReinforcementCount(team.state.reinforcement_count) + 1;
727
786
  if (newCount <= 20) {
728
787
  const toolError = readLastToolError(stateDir);
729
788
  const errorGuidance = getToolErrorRetryGuidance(toolError);
@@ -760,10 +819,9 @@ async function main() {
760
819
  ? omcTeams.state.session_id === sessionId
761
820
  : !omcTeams.state.session_id || omcTeams.state.session_id === sessionId;
762
821
  if (sessionMatches) {
763
- const phase = omcTeams.state.current_phase || "executing";
764
- const terminalPhases = ["completed", "complete", "failed", "cancelled"];
765
- if (!terminalPhases.includes(phase)) {
766
- const newCount = (omcTeams.state.reinforcement_count || 0) + 1;
822
+ const phase = normalizeTeamPhase(omcTeams.state);
823
+ if (phase) {
824
+ const newCount = getSafeReinforcementCount(omcTeams.state.reinforcement_count) + 1;
767
825
  if (newCount <= 20) {
768
826
  const toolError = readLastToolError(stateDir);
769
827
  const errorGuidance = getToolErrorRetryGuidance(toolError);
@@ -104,7 +104,16 @@ async function main() {
104
104
  }
105
105
  }
106
106
 
107
- // 3. Fallback: provide targeted repair guidance
107
+ // 3. Marketplace clone (for marketplace installs without a populated cache)
108
+ const marketplaceHudPath = join(configDir, "plugins", "marketplaces", "omc", "dist/hud/index.js");
109
+ if (existsSync(marketplaceHudPath)) {
110
+ try {
111
+ await import(pathToFileURL(marketplaceHudPath).href);
112
+ return;
113
+ } catch { /* continue */ }
114
+ }
115
+
116
+ // 4. Fallback: provide targeted repair guidance
108
117
  if (pluginCacheDir && existsSync(pluginCacheDir)) {
109
118
  const distDir = join(pluginCacheDir, "dist");
110
119
  if (!existsSync(distDir)) {