oh-my-copilot 4.13.1 → 4.13.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +3 -3
  4. package/bridge/cli.cjs +4709 -1961
  5. package/bridge/mcp-server.cjs +112 -11
  6. package/bridge/runtime-cli.cjs +4917 -2645
  7. package/bridge/team-bridge.cjs +6 -4
  8. package/bridge/team-mcp.cjs +19607 -0
  9. package/bridge/team.js +4895 -2215
  10. package/dist/__tests__/auto-slash-aliases.test.js +91 -0
  11. package/dist/__tests__/auto-slash-aliases.test.js.map +1 -1
  12. package/dist/__tests__/hooks/learner/bridge.test.js +25 -0
  13. package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -1
  14. package/dist/__tests__/hooks/learner/parser.test.js +30 -0
  15. package/dist/__tests__/hooks/learner/parser.test.js.map +1 -1
  16. package/dist/__tests__/hud/extra-usage.test.js +42 -0
  17. package/dist/__tests__/hud/extra-usage.test.js.map +1 -1
  18. package/dist/__tests__/hud/labels.test.d.ts +2 -0
  19. package/dist/__tests__/hud/labels.test.d.ts.map +1 -0
  20. package/dist/__tests__/hud/labels.test.js +158 -0
  21. package/dist/__tests__/hud/labels.test.js.map +1 -0
  22. package/dist/__tests__/hud/render-enterprise.test.d.ts +5 -0
  23. package/dist/__tests__/hud/render-enterprise.test.d.ts.map +1 -0
  24. package/dist/__tests__/hud/render-enterprise.test.js +232 -0
  25. package/dist/__tests__/hud/render-enterprise.test.js.map +1 -0
  26. package/dist/__tests__/hud/render-rate-limits-priority.test.js +185 -0
  27. package/dist/__tests__/hud/render-rate-limits-priority.test.js.map +1 -1
  28. package/dist/__tests__/hud/stdin-session-scope.test.d.ts +2 -0
  29. package/dist/__tests__/hud/stdin-session-scope.test.d.ts.map +1 -0
  30. package/dist/__tests__/hud/stdin-session-scope.test.js +169 -0
  31. package/dist/__tests__/hud/stdin-session-scope.test.js.map +1 -0
  32. package/dist/__tests__/hud/usage-api.test.js +111 -1
  33. package/dist/__tests__/hud/usage-api.test.js.map +1 -1
  34. package/dist/__tests__/hud-marketplace-resolution.test.js +34 -0
  35. package/dist/__tests__/hud-marketplace-resolution.test.js.map +1 -1
  36. package/dist/__tests__/installer-hud-skip.test.js +6 -0
  37. package/dist/__tests__/installer-hud-skip.test.js.map +1 -1
  38. package/dist/__tests__/installer-omc-reference.test.js +1 -1
  39. package/dist/__tests__/installer-omc-reference.test.js.map +1 -1
  40. package/dist/__tests__/keyword-detector-echo-guard.test.d.ts +2 -0
  41. package/dist/__tests__/keyword-detector-echo-guard.test.d.ts.map +1 -0
  42. package/dist/__tests__/keyword-detector-echo-guard.test.js +218 -0
  43. package/dist/__tests__/keyword-detector-echo-guard.test.js.map +1 -0
  44. package/dist/__tests__/mnemosyne/detector.test.js +2 -0
  45. package/dist/__tests__/mnemosyne/detector.test.js.map +1 -1
  46. package/dist/__tests__/notepad.test.js +2 -2
  47. package/dist/__tests__/notepad.test.js.map +1 -1
  48. package/dist/__tests__/pre-tool-enforcer.test.js +84 -1
  49. package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
  50. package/dist/__tests__/preemptive-compaction-hook.test.js +63 -0
  51. package/dist/__tests__/preemptive-compaction-hook.test.js.map +1 -1
  52. package/dist/__tests__/ralph-prd-mandatory.test.js +11 -1
  53. package/dist/__tests__/ralph-prd-mandatory.test.js.map +1 -1
  54. package/dist/__tests__/ralph-prd.test.js +40 -2
  55. package/dist/__tests__/ralph-prd.test.js.map +1 -1
  56. package/dist/__tests__/skills.test.js +363 -4
  57. package/dist/__tests__/skills.test.js.map +1 -1
  58. package/dist/__tests__/state-root-resolution.test.js +120 -6
  59. package/dist/__tests__/state-root-resolution.test.js.map +1 -1
  60. package/dist/autoresearch/__tests__/runtime.test.js +225 -28
  61. package/dist/autoresearch/__tests__/runtime.test.js.map +1 -1
  62. package/dist/autoresearch/runtime.d.ts.map +1 -1
  63. package/dist/autoresearch/runtime.js +9 -5
  64. package/dist/autoresearch/runtime.js.map +1 -1
  65. package/dist/cli/__tests__/team-status-worktree.test.d.ts +2 -0
  66. package/dist/cli/__tests__/team-status-worktree.test.d.ts.map +1 -0
  67. package/dist/cli/__tests__/team-status-worktree.test.js +96 -0
  68. package/dist/cli/__tests__/team-status-worktree.test.js.map +1 -0
  69. package/dist/cli/__tests__/team.test.js +164 -0
  70. package/dist/cli/__tests__/team.test.js.map +1 -1
  71. package/dist/cli/autoresearch.d.ts +1 -1
  72. package/dist/cli/autoresearch.d.ts.map +1 -1
  73. package/dist/cli/autoresearch.js +4 -4
  74. package/dist/cli/commands/team.d.ts +1 -0
  75. package/dist/cli/commands/team.d.ts.map +1 -1
  76. package/dist/cli/commands/team.js +15 -3
  77. package/dist/cli/commands/team.js.map +1 -1
  78. package/dist/cli/index.js +3 -0
  79. package/dist/cli/index.js.map +1 -1
  80. package/dist/cli/team.d.ts +6 -0
  81. package/dist/cli/team.d.ts.map +1 -1
  82. package/dist/cli/team.js +126 -5
  83. package/dist/cli/team.js.map +1 -1
  84. package/dist/cli/utils/formatting.d.ts +0 -10
  85. package/dist/cli/utils/formatting.d.ts.map +1 -1
  86. package/dist/cli/utils/formatting.js +0 -52
  87. package/dist/cli/utils/formatting.js.map +1 -1
  88. package/dist/config/__tests__/loader.test.js.map +1 -1
  89. package/dist/features/boulder-state/constants.d.ts +1 -1
  90. package/dist/features/boulder-state/constants.d.ts.map +1 -1
  91. package/dist/features/builtin-skills/skills.d.ts.map +1 -1
  92. package/dist/features/builtin-skills/skills.js +11 -3
  93. package/dist/features/builtin-skills/skills.js.map +1 -1
  94. package/dist/features/builtin-skills/types.d.ts +7 -0
  95. package/dist/features/builtin-skills/types.d.ts.map +1 -1
  96. package/dist/features/delegation-enforcer.d.ts +2 -0
  97. package/dist/features/delegation-enforcer.d.ts.map +1 -1
  98. package/dist/features/delegation-enforcer.js +10 -0
  99. package/dist/features/delegation-enforcer.js.map +1 -1
  100. package/dist/features/magic-keywords.d.ts.map +1 -1
  101. package/dist/features/magic-keywords.js +30 -1
  102. package/dist/features/magic-keywords.js.map +1 -1
  103. package/dist/features/rate-limit-wait/tmux-detector.d.ts +4 -4
  104. package/dist/features/rate-limit-wait/tmux-detector.js +9 -9
  105. package/dist/features/rate-limit-wait/tmux-detector.js.map +1 -1
  106. package/dist/hooks/__tests__/bridge-routing.test.js +156 -0
  107. package/dist/hooks/__tests__/bridge-routing.test.js.map +1 -1
  108. package/dist/hooks/auto-slash-command/constants.d.ts.map +1 -1
  109. package/dist/hooks/auto-slash-command/constants.js +1 -0
  110. package/dist/hooks/auto-slash-command/constants.js.map +1 -1
  111. package/dist/hooks/auto-slash-command/executor.d.ts.map +1 -1
  112. package/dist/hooks/auto-slash-command/executor.js +29 -0
  113. package/dist/hooks/auto-slash-command/executor.js.map +1 -1
  114. package/dist/hooks/bridge.d.ts.map +1 -1
  115. package/dist/hooks/bridge.js +184 -1
  116. package/dist/hooks/bridge.js.map +1 -1
  117. package/dist/hooks/learner/bridge.d.ts.map +1 -1
  118. package/dist/hooks/learner/bridge.js +4 -109
  119. package/dist/hooks/learner/bridge.js.map +1 -1
  120. package/dist/hooks/learner/detector.js +1 -1
  121. package/dist/hooks/learner/parser.d.ts +9 -0
  122. package/dist/hooks/learner/parser.d.ts.map +1 -1
  123. package/dist/hooks/learner/parser.js +18 -5
  124. package/dist/hooks/learner/parser.js.map +1 -1
  125. package/dist/hooks/learner/types.d.ts +6 -0
  126. package/dist/hooks/learner/types.d.ts.map +1 -1
  127. package/dist/hooks/mode-registry/__tests__/session-isolation.test.js +16 -0
  128. package/dist/hooks/mode-registry/__tests__/session-isolation.test.js.map +1 -1
  129. package/dist/hooks/notepad/index.d.ts +4 -1
  130. package/dist/hooks/notepad/index.d.ts.map +1 -1
  131. package/dist/hooks/notepad/index.js +7 -4
  132. package/dist/hooks/notepad/index.js.map +1 -1
  133. package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.js +70 -3
  134. package/dist/hooks/persistent-mode/__tests__/ralph-verification-flow.test.js.map +1 -1
  135. package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
  136. package/dist/hooks/persistent-mode/index.js +17 -13
  137. package/dist/hooks/persistent-mode/index.js.map +1 -1
  138. package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +175 -3
  139. package/dist/hooks/persistent-mode/stop-hook-blocking.test.js.map +1 -1
  140. package/dist/hooks/project-memory/__tests__/integration.test.js +117 -3
  141. package/dist/hooks/project-memory/__tests__/integration.test.js.map +1 -1
  142. package/dist/hooks/project-memory/__tests__/storage.test.js +11 -11
  143. package/dist/hooks/project-memory/__tests__/storage.test.js.map +1 -1
  144. package/dist/hooks/project-memory/index.d.ts.map +1 -1
  145. package/dist/hooks/project-memory/index.js +24 -12
  146. package/dist/hooks/project-memory/index.js.map +1 -1
  147. package/dist/hooks/ralph/index.d.ts +1 -1
  148. package/dist/hooks/ralph/index.d.ts.map +1 -1
  149. package/dist/hooks/ralph/index.js +1 -1
  150. package/dist/hooks/ralph/index.js.map +1 -1
  151. package/dist/hooks/ralph/loop.d.ts +6 -6
  152. package/dist/hooks/ralph/loop.d.ts.map +1 -1
  153. package/dist/hooks/ralph/loop.js +18 -18
  154. package/dist/hooks/ralph/loop.js.map +1 -1
  155. package/dist/hooks/ralph/prd.d.ts +23 -12
  156. package/dist/hooks/ralph/prd.d.ts.map +1 -1
  157. package/dist/hooks/ralph/prd.js +88 -42
  158. package/dist/hooks/ralph/prd.js.map +1 -1
  159. package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.js +20 -0
  160. package/dist/hooks/session-end/__tests__/mode-state-cleanup.test.js.map +1 -1
  161. package/dist/hooks/session-end/index.d.ts +9 -0
  162. package/dist/hooks/session-end/index.d.ts.map +1 -1
  163. package/dist/hooks/session-end/index.js +110 -0
  164. package/dist/hooks/session-end/index.js.map +1 -1
  165. package/dist/hooks/skill-bridge.cjs +114 -92
  166. package/dist/hooks/skill-state/index.d.ts.map +1 -1
  167. package/dist/hooks/skill-state/index.js +1 -0
  168. package/dist/hooks/skill-state/index.js.map +1 -1
  169. package/dist/hud/__tests__/enterprise-cost.test.d.ts +5 -0
  170. package/dist/hud/__tests__/enterprise-cost.test.d.ts.map +1 -0
  171. package/dist/hud/__tests__/enterprise-cost.test.js +151 -0
  172. package/dist/hud/__tests__/enterprise-cost.test.js.map +1 -0
  173. package/dist/hud/__tests__/git-status.test.js +18 -0
  174. package/dist/hud/__tests__/git-status.test.js.map +1 -1
  175. package/dist/hud/__tests__/usage-api-enterprise.test.d.ts +5 -0
  176. package/dist/hud/__tests__/usage-api-enterprise.test.d.ts.map +1 -0
  177. package/dist/hud/__tests__/usage-api-enterprise.test.js +249 -0
  178. package/dist/hud/__tests__/usage-api-enterprise.test.js.map +1 -0
  179. package/dist/hud/elements/background.d.ts +3 -3
  180. package/dist/hud/elements/background.d.ts.map +1 -1
  181. package/dist/hud/elements/background.js +5 -4
  182. package/dist/hud/elements/background.js.map +1 -1
  183. package/dist/hud/elements/call-counts.d.ts +2 -2
  184. package/dist/hud/elements/call-counts.d.ts.map +1 -1
  185. package/dist/hud/elements/call-counts.js +7 -6
  186. package/dist/hud/elements/call-counts.js.map +1 -1
  187. package/dist/hud/elements/context.d.ts +3 -3
  188. package/dist/hud/elements/context.d.ts.map +1 -1
  189. package/dist/hud/elements/context.js +5 -4
  190. package/dist/hud/elements/context.js.map +1 -1
  191. package/dist/hud/elements/enterprise-cost.d.ts +16 -0
  192. package/dist/hud/elements/enterprise-cost.d.ts.map +1 -0
  193. package/dist/hud/elements/enterprise-cost.js +63 -0
  194. package/dist/hud/elements/enterprise-cost.js.map +1 -0
  195. package/dist/hud/elements/git.d.ts +2 -1
  196. package/dist/hud/elements/git.d.ts.map +1 -1
  197. package/dist/hud/elements/git.js +7 -6
  198. package/dist/hud/elements/git.js.map +1 -1
  199. package/dist/hud/elements/permission.d.ts.map +1 -1
  200. package/dist/hud/elements/permission.js +2 -5
  201. package/dist/hud/elements/permission.js.map +1 -1
  202. package/dist/hud/elements/ralph.d.ts +2 -2
  203. package/dist/hud/elements/ralph.d.ts.map +1 -1
  204. package/dist/hud/elements/ralph.js +3 -2
  205. package/dist/hud/elements/ralph.js.map +1 -1
  206. package/dist/hud/elements/session.d.ts.map +1 -1
  207. package/dist/hud/elements/session.js +5 -9
  208. package/dist/hud/elements/session.js.map +1 -1
  209. package/dist/hud/elements/thinking.d.ts +2 -2
  210. package/dist/hud/elements/thinking.d.ts.map +1 -1
  211. package/dist/hud/elements/thinking.js +3 -2
  212. package/dist/hud/elements/thinking.js.map +1 -1
  213. package/dist/hud/elements/token-usage.d.ts +2 -2
  214. package/dist/hud/elements/token-usage.d.ts.map +1 -1
  215. package/dist/hud/elements/token-usage.js +3 -2
  216. package/dist/hud/elements/token-usage.js.map +1 -1
  217. package/dist/hud/index.d.ts.map +1 -1
  218. package/dist/hud/index.js +5 -1
  219. package/dist/hud/index.js.map +1 -1
  220. package/dist/hud/render.d.ts.map +1 -1
  221. package/dist/hud/render.js +43 -10
  222. package/dist/hud/render.js.map +1 -1
  223. package/dist/hud/state.d.ts.map +1 -1
  224. package/dist/hud/state.js +18 -1
  225. package/dist/hud/state.js.map +1 -1
  226. package/dist/hud/stdin.d.ts.map +1 -1
  227. package/dist/hud/stdin.js +49 -5
  228. package/dist/hud/stdin.js.map +1 -1
  229. package/dist/hud/types.d.ts +42 -0
  230. package/dist/hud/types.d.ts.map +1 -1
  231. package/dist/hud/types.js +59 -1
  232. package/dist/hud/types.js.map +1 -1
  233. package/dist/hud/usage-api.d.ts +19 -1
  234. package/dist/hud/usage-api.d.ts.map +1 -1
  235. package/dist/hud/usage-api.js +101 -18
  236. package/dist/hud/usage-api.js.map +1 -1
  237. package/dist/installer/__tests__/hud-cache-wrapper.test.d.ts +2 -0
  238. package/dist/installer/__tests__/hud-cache-wrapper.test.d.ts.map +1 -0
  239. package/dist/installer/__tests__/hud-cache-wrapper.test.js +235 -0
  240. package/dist/installer/__tests__/hud-cache-wrapper.test.js.map +1 -0
  241. package/dist/installer/__tests__/standalone-hook-reconcile.test.js +2 -0
  242. package/dist/installer/__tests__/standalone-hook-reconcile.test.js.map +1 -1
  243. package/dist/installer/index.d.ts +1 -0
  244. package/dist/installer/index.d.ts.map +1 -1
  245. package/dist/installer/index.js +83 -31
  246. package/dist/installer/index.js.map +1 -1
  247. package/dist/lib/__tests__/worktree-paths.test.js +162 -39
  248. package/dist/lib/__tests__/worktree-paths.test.js.map +1 -1
  249. package/dist/lib/worktree-paths.d.ts +87 -9
  250. package/dist/lib/worktree-paths.d.ts.map +1 -1
  251. package/dist/lib/worktree-paths.js +209 -27
  252. package/dist/lib/worktree-paths.js.map +1 -1
  253. package/dist/mcp/__tests__/team-server-artifact-convergence.test.js +156 -4
  254. package/dist/mcp/__tests__/team-server-artifact-convergence.test.js.map +1 -1
  255. package/dist/mcp/omc-tools-server.d.ts +11 -17
  256. package/dist/mcp/omc-tools-server.d.ts.map +1 -1
  257. package/dist/mcp/omc-tools-server.js +22 -32
  258. package/dist/mcp/omc-tools-server.js.map +1 -1
  259. package/dist/mcp/team-job-convergence.d.ts +9 -2
  260. package/dist/mcp/team-job-convergence.d.ts.map +1 -1
  261. package/dist/mcp/team-job-convergence.js +35 -14
  262. package/dist/mcp/team-job-convergence.js.map +1 -1
  263. package/dist/mcp/team-server.d.ts.map +1 -1
  264. package/dist/mcp/team-server.js +93 -13
  265. package/dist/mcp/team-server.js.map +1 -1
  266. package/dist/ralphthon/prd.d.ts.map +1 -1
  267. package/dist/ralphthon/prd.js +13 -17
  268. package/dist/ralphthon/prd.js.map +1 -1
  269. package/dist/shared/types.d.ts +2 -0
  270. package/dist/shared/types.d.ts.map +1 -1
  271. package/dist/team/__tests__/api-interop.cleanup.test.d.ts +2 -0
  272. package/dist/team/__tests__/api-interop.cleanup.test.d.ts.map +1 -0
  273. package/dist/team/__tests__/api-interop.cleanup.test.js +234 -0
  274. package/dist/team/__tests__/api-interop.cleanup.test.js.map +1 -0
  275. package/dist/team/__tests__/api-interop.dispatch.test.js +2 -1
  276. package/dist/team/__tests__/api-interop.dispatch.test.js.map +1 -1
  277. package/dist/team/__tests__/auto-merge-restart.test.d.ts +2 -0
  278. package/dist/team/__tests__/auto-merge-restart.test.d.ts.map +1 -0
  279. package/dist/team/__tests__/auto-merge-restart.test.js +128 -0
  280. package/dist/team/__tests__/auto-merge-restart.test.js.map +1 -0
  281. package/dist/team/__tests__/auto-merge.perf.test.d.ts +2 -0
  282. package/dist/team/__tests__/auto-merge.perf.test.d.ts.map +1 -0
  283. package/dist/team/__tests__/auto-merge.perf.test.js +85 -0
  284. package/dist/team/__tests__/auto-merge.perf.test.js.map +1 -0
  285. package/dist/team/__tests__/conflict-mailbox.test.d.ts +2 -0
  286. package/dist/team/__tests__/conflict-mailbox.test.d.ts.map +1 -0
  287. package/dist/team/__tests__/conflict-mailbox.test.js +238 -0
  288. package/dist/team/__tests__/conflict-mailbox.test.js.map +1 -0
  289. package/dist/team/__tests__/git-worktree.test.js +164 -3
  290. package/dist/team/__tests__/git-worktree.test.js.map +1 -1
  291. package/dist/team/__tests__/helpers/git-fixture.d.ts +72 -0
  292. package/dist/team/__tests__/helpers/git-fixture.d.ts.map +1 -0
  293. package/dist/team/__tests__/helpers/git-fixture.js +252 -0
  294. package/dist/team/__tests__/helpers/git-fixture.js.map +1 -0
  295. package/dist/team/__tests__/leader-inbox.test.d.ts +2 -0
  296. package/dist/team/__tests__/leader-inbox.test.d.ts.map +1 -0
  297. package/dist/team/__tests__/leader-inbox.test.js +152 -0
  298. package/dist/team/__tests__/leader-inbox.test.js.map +1 -0
  299. package/dist/team/__tests__/merge-orchestrator.test.d.ts +2 -0
  300. package/dist/team/__tests__/merge-orchestrator.test.d.ts.map +1 -0
  301. package/dist/team/__tests__/merge-orchestrator.test.js +779 -0
  302. package/dist/team/__tests__/merge-orchestrator.test.js.map +1 -0
  303. package/dist/team/__tests__/model-contract.test.js +35 -21
  304. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  305. package/dist/team/__tests__/rebase-smoke.test.d.ts +2 -0
  306. package/dist/team/__tests__/rebase-smoke.test.d.ts.map +1 -0
  307. package/dist/team/__tests__/rebase-smoke.test.js +272 -0
  308. package/dist/team/__tests__/rebase-smoke.test.js.map +1 -0
  309. package/dist/team/__tests__/runtime-cli.test.js +11 -3
  310. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  311. package/dist/team/__tests__/runtime-prompt-mode.test.js +14 -16
  312. package/dist/team/__tests__/runtime-prompt-mode.test.js.map +1 -1
  313. package/dist/team/__tests__/runtime-v2-role-routing.test.js +7 -1
  314. package/dist/team/__tests__/runtime-v2-role-routing.test.js.map +1 -1
  315. package/dist/team/__tests__/runtime-v2.dispatch.test.js +293 -15
  316. package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
  317. package/dist/team/__tests__/runtime-v2.monitor.test.d.ts +2 -0
  318. package/dist/team/__tests__/runtime-v2.monitor.test.d.ts.map +1 -0
  319. package/dist/team/__tests__/runtime-v2.monitor.test.js +219 -0
  320. package/dist/team/__tests__/runtime-v2.monitor.test.js.map +1 -0
  321. package/dist/team/__tests__/runtime-v2.shutdown.test.d.ts +2 -0
  322. package/dist/team/__tests__/runtime-v2.shutdown.test.d.ts.map +1 -0
  323. package/dist/team/__tests__/runtime-v2.shutdown.test.js +292 -0
  324. package/dist/team/__tests__/runtime-v2.shutdown.test.js.map +1 -0
  325. package/dist/team/__tests__/scaling-launch-config.test.js +203 -3
  326. package/dist/team/__tests__/scaling-launch-config.test.js.map +1 -1
  327. package/dist/team/__tests__/team-summary-worktree.test.d.ts +2 -0
  328. package/dist/team/__tests__/team-summary-worktree.test.d.ts.map +1 -0
  329. package/dist/team/__tests__/team-summary-worktree.test.js +85 -0
  330. package/dist/team/__tests__/team-summary-worktree.test.js.map +1 -0
  331. package/dist/team/__tests__/teardown-invariant.test.d.ts +2 -0
  332. package/dist/team/__tests__/teardown-invariant.test.d.ts.map +1 -0
  333. package/dist/team/__tests__/teardown-invariant.test.js +176 -0
  334. package/dist/team/__tests__/teardown-invariant.test.js.map +1 -0
  335. package/dist/team/__tests__/tmux-session-liveness.test.d.ts +2 -0
  336. package/dist/team/__tests__/tmux-session-liveness.test.d.ts.map +1 -0
  337. package/dist/team/__tests__/tmux-session-liveness.test.js +37 -0
  338. package/dist/team/__tests__/tmux-session-liveness.test.js.map +1 -0
  339. package/dist/team/__tests__/worker-bootstrap.test.js +47 -1
  340. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  341. package/dist/team/__tests__/worker-commit-cadence.test.d.ts +2 -0
  342. package/dist/team/__tests__/worker-commit-cadence.test.d.ts.map +1 -0
  343. package/dist/team/__tests__/worker-commit-cadence.test.js +315 -0
  344. package/dist/team/__tests__/worker-commit-cadence.test.js.map +1 -0
  345. package/dist/team/__tests__/worktree-contract-fields.test.d.ts +2 -0
  346. package/dist/team/__tests__/worktree-contract-fields.test.d.ts.map +1 -0
  347. package/dist/team/__tests__/worktree-contract-fields.test.js +157 -0
  348. package/dist/team/__tests__/worktree-contract-fields.test.js.map +1 -0
  349. package/dist/team/__tests__/worktree-runtime-e2e.test.d.ts +2 -0
  350. package/dist/team/__tests__/worktree-runtime-e2e.test.d.ts.map +1 -0
  351. package/dist/team/__tests__/worktree-runtime-e2e.test.js +182 -0
  352. package/dist/team/__tests__/worktree-runtime-e2e.test.js.map +1 -0
  353. package/dist/team/api-interop.d.ts +2 -1
  354. package/dist/team/api-interop.d.ts.map +1 -1
  355. package/dist/team/api-interop.js +121 -14
  356. package/dist/team/api-interop.js.map +1 -1
  357. package/dist/team/capabilities.d.ts.map +1 -1
  358. package/dist/team/capabilities.js +2 -0
  359. package/dist/team/capabilities.js.map +1 -1
  360. package/dist/team/cli-worker-contract.d.ts +7 -6
  361. package/dist/team/cli-worker-contract.d.ts.map +1 -1
  362. package/dist/team/cli-worker-contract.js +7 -6
  363. package/dist/team/cli-worker-contract.js.map +1 -1
  364. package/dist/team/conflict-mailbox.d.ts +49 -0
  365. package/dist/team/conflict-mailbox.d.ts.map +1 -0
  366. package/dist/team/conflict-mailbox.js +98 -0
  367. package/dist/team/conflict-mailbox.js.map +1 -0
  368. package/dist/team/events.d.ts +3 -0
  369. package/dist/team/events.d.ts.map +1 -1
  370. package/dist/team/events.js +2 -1
  371. package/dist/team/events.js.map +1 -1
  372. package/dist/team/git-worktree.d.ts +78 -10
  373. package/dist/team/git-worktree.d.ts.map +1 -1
  374. package/dist/team/git-worktree.js +453 -97
  375. package/dist/team/git-worktree.js.map +1 -1
  376. package/dist/team/governance.d.ts +3 -2
  377. package/dist/team/governance.d.ts.map +1 -1
  378. package/dist/team/governance.js.map +1 -1
  379. package/dist/team/leader-inbox.d.ts +28 -0
  380. package/dist/team/leader-inbox.d.ts.map +1 -0
  381. package/dist/team/leader-inbox.js +68 -0
  382. package/dist/team/leader-inbox.js.map +1 -0
  383. package/dist/team/merge-coordinator.d.ts +6 -0
  384. package/dist/team/merge-coordinator.d.ts.map +1 -1
  385. package/dist/team/merge-coordinator.js +6 -2
  386. package/dist/team/merge-coordinator.js.map +1 -1
  387. package/dist/team/merge-orchestrator.d.ts +41 -0
  388. package/dist/team/merge-orchestrator.d.ts.map +1 -0
  389. package/dist/team/merge-orchestrator.js +736 -0
  390. package/dist/team/merge-orchestrator.js.map +1 -0
  391. package/dist/team/model-contract.d.ts +18 -2
  392. package/dist/team/model-contract.d.ts.map +1 -1
  393. package/dist/team/model-contract.js +55 -28
  394. package/dist/team/model-contract.js.map +1 -1
  395. package/dist/team/monitor.d.ts.map +1 -1
  396. package/dist/team/monitor.js +47 -3
  397. package/dist/team/monitor.js.map +1 -1
  398. package/dist/team/runtime-cli.d.ts +1 -0
  399. package/dist/team/runtime-cli.d.ts.map +1 -1
  400. package/dist/team/runtime-cli.js +15 -2
  401. package/dist/team/runtime-cli.js.map +1 -1
  402. package/dist/team/runtime-flags.d.ts +5 -0
  403. package/dist/team/runtime-flags.d.ts.map +1 -0
  404. package/dist/team/runtime-flags.js +12 -0
  405. package/dist/team/runtime-flags.js.map +1 -0
  406. package/dist/team/runtime-v2.d.ts +16 -1
  407. package/dist/team/runtime-v2.d.ts.map +1 -1
  408. package/dist/team/runtime-v2.js +531 -127
  409. package/dist/team/runtime-v2.js.map +1 -1
  410. package/dist/team/runtime.d.ts.map +1 -1
  411. package/dist/team/runtime.js +4 -1
  412. package/dist/team/runtime.js.map +1 -1
  413. package/dist/team/scaling.d.ts.map +1 -1
  414. package/dist/team/scaling.js +110 -13
  415. package/dist/team/scaling.js.map +1 -1
  416. package/dist/team/state/tasks.d.ts.map +1 -1
  417. package/dist/team/state/tasks.js +1 -0
  418. package/dist/team/state/tasks.js.map +1 -1
  419. package/dist/team/team-ops.d.ts.map +1 -1
  420. package/dist/team/team-ops.js +112 -16
  421. package/dist/team/team-ops.js.map +1 -1
  422. package/dist/team/tmux-session.d.ts +17 -29
  423. package/dist/team/tmux-session.d.ts.map +1 -1
  424. package/dist/team/tmux-session.js +117 -108
  425. package/dist/team/tmux-session.js.map +1 -1
  426. package/dist/team/types.d.ts +31 -17
  427. package/dist/team/types.d.ts.map +1 -1
  428. package/dist/team/types.js.map +1 -1
  429. package/dist/team/worker-bootstrap.d.ts +11 -0
  430. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  431. package/dist/team/worker-bootstrap.js +37 -14
  432. package/dist/team/worker-bootstrap.js.map +1 -1
  433. package/dist/team/worker-canonicalization.d.ts.map +1 -1
  434. package/dist/team/worker-canonicalization.js +2 -0
  435. package/dist/team/worker-canonicalization.js.map +1 -1
  436. package/dist/team/worker-commit-cadence.d.ts +70 -0
  437. package/dist/team/worker-commit-cadence.d.ts.map +1 -0
  438. package/dist/team/worker-commit-cadence.js +271 -0
  439. package/dist/team/worker-commit-cadence.js.map +1 -0
  440. package/dist/tools/__tests__/memory-tools.test.js +4 -4
  441. package/dist/tools/__tests__/memory-tools.test.js.map +1 -1
  442. package/dist/tools/__tests__/state-tools.test.js +13 -1
  443. package/dist/tools/__tests__/state-tools.test.js.map +1 -1
  444. package/dist/utils/frontmatter.d.ts.map +1 -1
  445. package/dist/utils/frontmatter.js +1 -16
  446. package/dist/utils/frontmatter.js.map +1 -1
  447. package/dist/utils/resolve-node.d.ts.map +1 -1
  448. package/dist/utils/resolve-node.js +22 -28
  449. package/dist/utils/resolve-node.js.map +1 -1
  450. package/docs/GETTING-STARTED.md +415 -0
  451. package/docs/MIGRATION.md +1003 -0
  452. package/docs/REFERENCE.md +21 -4
  453. package/docs/TEAM-WORKTREE-MODE.md +86 -0
  454. package/docs/company-context-interface.md +5 -16
  455. package/docs/copilot-instructions.md +1 -1
  456. package/package.json +1 -1
  457. package/scripts/keyword-detector.mjs +168 -20
  458. package/scripts/lib/hud-cache-wrapper.sh +122 -0
  459. package/scripts/persistent-mode.cjs +28 -2
  460. package/scripts/persistent-mode.mjs +28 -2
  461. package/scripts/plugin-setup.mjs +10 -1
  462. package/scripts/post-tool-verifier.mjs +153 -3
  463. package/scripts/pre-tool-enforcer.mjs +54 -6
  464. package/scripts/session-start.mjs +194 -2
  465. package/skills/AGENTS.md +22 -91
  466. package/skills/ai-slop-cleaner/SKILL.md +118 -120
  467. package/skills/ask/SKILL.md +6 -8
  468. package/skills/autopilot/SKILL.md +1 -28
  469. package/skills/autoresearch/SKILL.md +5 -5
  470. package/skills/cancel/SKILL.md +13 -13
  471. package/skills/cccg/SKILL.md +1 -0
  472. package/skills/configure-notifications/SKILL.md +80 -215
  473. package/skills/debug/SKILL.md +3 -2
  474. package/skills/deep-dive/SKILL.md +20 -9
  475. package/skills/deep-interview/SKILL.md +32 -4
  476. package/skills/deepinit/SKILL.md +1 -0
  477. package/skills/external-context/SKILL.md +2 -1
  478. package/skills/hud/SKILL.md +22 -52
  479. package/skills/learner/SKILL.md +90 -57
  480. package/skills/mcp-setup/SKILL.md +45 -60
  481. package/skills/omc-doctor/SKILL.md +1 -1
  482. package/skills/omc-reference/SKILL.md +6 -6
  483. package/skills/omc-setup/SKILL.md +30 -74
  484. package/skills/omc-setup/phases/01-install-claude-md.md +97 -0
  485. package/skills/omc-setup/phases/02-configure.md +25 -40
  486. package/skills/omc-setup/phases/03-integrations.md +100 -69
  487. package/skills/omc-setup/phases/04-welcome.md +102 -44
  488. package/skills/omc-teams/SKILL.md +63 -26
  489. package/skills/plan/SKILL.md +11 -9
  490. package/skills/ralph/SKILL.md +42 -41
  491. package/skills/ralplan/SKILL.md +3 -10
  492. package/skills/release/SKILL.md +168 -57
  493. package/skills/remember/SKILL.md +2 -1
  494. package/skills/sciomc/SKILL.md +12 -11
  495. package/skills/self-improve/SKILL.md +4 -4
  496. package/skills/setup/SKILL.md +1 -0
  497. package/skills/skill/SKILL.md +21 -20
  498. package/skills/skillify/SKILL.md +34 -3
  499. package/skills/team/SKILL.md +62 -44
  500. package/skills/ultraqa/SKILL.md +1 -2
  501. package/skills/ultrawork/SKILL.md +28 -21
  502. package/skills/verify/SKILL.md +2 -1
  503. package/skills/writer-memory/SKILL.md +2 -1
  504. package/templates/hooks/keyword-detector.mjs +129 -11
  505. package/templates/hooks/persistent-mode.mjs +28 -2
  506. package/templates/hooks/pre-tool-use.mjs +144 -45
  507. package/templates/hooks/session-start.mjs +25 -1
@@ -417,6 +417,32 @@ function readStateFileWithSession(stateDir, globalStateDir, filename, sessionId)
417
417
  return readStateFile(stateDir, globalStateDir, filename);
418
418
  }
419
419
 
420
+ const WORKFLOW_SLOT_TOMBSTONE_TTL_MS = 24 * 60 * 60 * 1000;
421
+
422
+ function isWorkflowSlotTombstonedForMode(stateDir, mode, sessionId) {
423
+ const safeSessionId = sanitizeSessionId(sessionId);
424
+ const ledgerPath = safeSessionId
425
+ ? join(stateDir, "sessions", safeSessionId, "skill-active-state.json")
426
+ : join(stateDir, "skill-active-state.json");
427
+ const ledger = readJsonFile(ledgerPath);
428
+ const slot = ledger?.active_skills?.[mode];
429
+ if (!slot || typeof slot !== "object") return false;
430
+ if (typeof slot.completed_at !== "string" || !slot.completed_at) return false;
431
+ const completedAt = new Date(slot.completed_at).getTime();
432
+ if (!Number.isFinite(completedAt)) return true;
433
+ return Date.now() - completedAt < WORKFLOW_SLOT_TOMBSTONE_TTL_MS;
434
+ }
435
+
436
+ function isAuthoritativeModeActive(stateDir, mode, loaded, sessionId) {
437
+ const state = loaded?.state;
438
+ if (!state?.active) return false;
439
+ if (isWorkflowSlotTombstonedForMode(stateDir, mode, sessionId)) return false;
440
+ const safeSessionId = sanitizeSessionId(sessionId);
441
+ if (safeSessionId && state.session_id && state.session_id !== safeSessionId) return false;
442
+ return true;
443
+ }
444
+
445
+
420
446
  function getActiveSubagentCount(stateDir) {
421
447
  try {
422
448
  const tracking = readJsonFile(join(stateDir, "subagent-tracking.json"));
@@ -741,7 +767,7 @@ async function main() {
741
767
  // Priority 1: Ralph Loop (explicit persistence mode)
742
768
  // Skip if state is stale (older than 2 hours) - prevents blocking new sessions
743
769
  if (
744
- ralph.state?.active && !isAwaitingConfirmation(ralph.state) &&
770
+ isAuthoritativeModeActive(stateDir, "ralph", ralph, sessionId) && !isAwaitingConfirmation(ralph.state) &&
745
771
  !isStaleState(ralph.state) &&
746
772
  isStateForCurrentProject(ralph.state, directory, ralph.isGlobal)
747
773
  ) {
@@ -1036,7 +1062,7 @@ async function main() {
1036
1062
  // Session isolation: only block if state belongs to this session (issue #311)
1037
1063
  // If state has session_id, it must match. If no session_id (legacy), allow.
1038
1064
  if (
1039
- ultrawork.state?.active && !isAwaitingConfirmation(ultrawork.state) &&
1065
+ isAuthoritativeModeActive(stateDir, "ultrawork", ultrawork, sessionId) && !isAwaitingConfirmation(ultrawork.state) &&
1040
1066
  !isStaleState(ultrawork.state) &&
1041
1067
  (hasValidSessionId
1042
1068
  ? ultrawork.state.session_id === sessionId
@@ -16,6 +16,150 @@ const __dirname = dirname(__filename);
16
16
  // Dynamic import for the shared stdin module
17
17
  const { readStdin } = await import(pathToFileURL(path.join(__dirname, 'lib', 'stdin.mjs')).href);
18
18
 
19
+ // ---------------------------------------------------------------------------
20
+ // Skill Active State (issue #1033)
21
+ // Writes skill-active-state.json so the persistent-mode Stop hook can prevent
22
+ // premature session termination while a skill is executing.
23
+ // ---------------------------------------------------------------------------
24
+
25
+ /**
26
+ * Skill protection levels: none/light/medium/heavy.
27
+ * - 'none': Already has dedicated mode state (ralph, autopilot) or instant/read-only
28
+ * - 'light': Quick agent shortcuts (3 reinforcements, 5 min TTL)
29
+ * - 'medium': Review/planning skills that run multiple agents (5 reinforcements, 15 min TTL)
30
+ * - 'heavy': Long-running skills (10 reinforcements, 30 min TTL)
31
+ */
32
+ const PROTECTION_CONFIGS = {
33
+ none: { maxReinforcements: 0, staleTtlMs: 0 },
34
+ light: { maxReinforcements: 3, staleTtlMs: 5 * 60 * 1000 },
35
+ medium: { maxReinforcements: 5, staleTtlMs: 15 * 60 * 1000 },
36
+ heavy: { maxReinforcements: 10, staleTtlMs: 30 * 60 * 1000 },
37
+ };
38
+
39
+ const SKILL_PROTECTION = {
40
+ // Already have mode state → no protection needed
41
+ autopilot: 'none', ralph: 'none', ultrawork: 'none', team: 'none',
42
+ 'omc-teams': 'none', ultraqa: 'none', cancel: 'none',
43
+ // Instant / read-only → no protection needed
44
+ trace: 'none', hud: 'none', 'omc-doctor': 'none', 'omc-help': 'none',
45
+ 'learn-about-omc': 'none', note: 'none',
46
+ // Light protection (3 reinforcements)
47
+ tdd: 'light', 'build-fix': 'light', analyze: 'light', skill: 'light',
48
+ 'configure-notifications': 'light',
49
+ // Medium protection (5 reinforcements)
50
+ 'code-review': 'medium', 'security-review': 'medium', plan: 'medium',
51
+ ralplan: 'medium', review: 'medium', 'external-context': 'medium',
52
+ sciomc: 'medium', skillify: 'medium', learner: 'medium', 'omc-setup': 'medium',
53
+ 'mcp-setup': 'medium', 'project-session-manager': 'medium',
54
+ 'writer-memory': 'medium', 'ralph-init': 'medium', ccg: 'medium',
55
+ // Heavy protection (10 reinforcements)
56
+ deepinit: 'heavy',
57
+ };
58
+
59
+ function getSkillProtection(skillName) {
60
+ const normalized = (skillName || '').toLowerCase().replace(/^oh-my-(?:claudecode|copilot):/, '');
61
+ return SKILL_PROTECTION[normalized] || 'light';
62
+ }
63
+
64
+ function getInvokedSkillName(toolInput) {
65
+ if (!toolInput || typeof toolInput !== 'object') return null;
66
+ const rawSkill = toolInput.skill || toolInput.skill_name || toolInput.skillName || toolInput.command || null;
67
+ if (typeof rawSkill !== 'string' || !rawSkill.trim()) return null;
68
+ const normalized = rawSkill.trim();
69
+ return normalized.includes(':') ? normalized.split(':').at(-1).toLowerCase() : normalized.toLowerCase();
70
+ }
71
+
72
+ const SESSION_ID_ALLOWLIST = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$/;
73
+
74
+ function writeSkillActiveState(directory, skillName, sessionId) {
75
+ const protection = getSkillProtection(skillName);
76
+ if (protection === 'none') return;
77
+
78
+ const config = PROTECTION_CONFIGS[protection];
79
+ const now = new Date().toISOString();
80
+ const normalized = (skillName || '').toLowerCase().replace(/^oh-my-(?:claudecode|copilot):/, '');
81
+
82
+ const state = {
83
+ active: true,
84
+ skill_name: normalized,
85
+ session_id: sessionId || undefined,
86
+ started_at: now,
87
+ last_checked_at: now,
88
+ reinforcement_count: 0,
89
+ max_reinforcements: config.maxReinforcements,
90
+ stale_ttl_ms: config.staleTtlMs,
91
+ };
92
+
93
+ const stateDir = path.join(directory, '.omc', 'state');
94
+
95
+ // Write to session-scoped path when sessionId is available (must match persistent-mode.mjs reads)
96
+ const safeSessionId = sessionId && SESSION_ID_ALLOWLIST.test(sessionId) ? sessionId : '';
97
+ const targetDir = safeSessionId
98
+ ? path.join(stateDir, 'sessions', safeSessionId)
99
+ : stateDir;
100
+ const targetPath = path.join(targetDir, 'skill-active-state.json');
101
+
102
+ try {
103
+ if (!existsSync(targetDir)) {
104
+ mkdirSync(targetDir, { recursive: true });
105
+ }
106
+ const tmpPath = targetPath + '.tmp';
107
+ writeFileSync(tmpPath, JSON.stringify(state, null, 2), { mode: 0o600 });
108
+ renameSync(tmpPath, targetPath);
109
+ } catch {
110
+ // Best-effort; don't fail the hook
111
+ }
112
+ }
113
+
114
+
115
+ function clearAwaitingConfirmationFlag(directory, stateName, sessionId) {
116
+ const stateDir = path.join(directory, '.omc', 'state');
117
+ const safeSessionId = sessionId && SESSION_ID_ALLOWLIST.test(sessionId) ? sessionId : '';
118
+ const paths = [
119
+ safeSessionId ? path.join(stateDir, 'sessions', safeSessionId, `${stateName}-state.json`) : null,
120
+ path.join(stateDir, `${stateName}-state.json`),
121
+ path.join(homedir(), '.omc', 'state', `${stateName}-state.json`),
122
+ ].filter(Boolean);
123
+
124
+ for (const statePath of paths) {
125
+ try {
126
+ if (!existsSync(statePath)) continue;
127
+ const state = JSON.parse(readFileSync(statePath, 'utf-8'));
128
+ if (!state || typeof state !== 'object' || !state.awaiting_confirmation) continue;
129
+ delete state.awaiting_confirmation;
130
+ const tmpPath = statePath + '.tmp';
131
+ writeFileSync(tmpPath, JSON.stringify(state, null, 2), { mode: 0o600 });
132
+ renameSync(tmpPath, statePath);
133
+ } catch {
134
+ // Best-effort; don't fail the hook
135
+ }
136
+ }
137
+ }
138
+
139
+ function confirmSkillModeStates(directory, skillName, sessionId) {
140
+ switch (skillName) {
141
+ case 'ralph':
142
+ clearAwaitingConfirmationFlag(directory, 'ralph', sessionId);
143
+ clearAwaitingConfirmationFlag(directory, 'ultrawork', sessionId);
144
+ break;
145
+ case 'ultrawork':
146
+ clearAwaitingConfirmationFlag(directory, 'ultrawork', sessionId);
147
+ break;
148
+ case 'autopilot':
149
+ clearAwaitingConfirmationFlag(directory, 'autopilot', sessionId);
150
+ break;
151
+ case 'ralplan':
152
+ clearAwaitingConfirmationFlag(directory, 'ralplan', sessionId);
153
+ break;
154
+ default:
155
+ break;
156
+ }
157
+ }
158
+
159
+ // ---------------------------------------------------------------------------
160
+ // Delegation enforcement
161
+ // ---------------------------------------------------------------------------
162
+
19
163
  // Allowed path patterns (no warning)
20
164
  // Paths are normalized to forward slashes before matching
21
165
  const ALLOWED_PATH_PATTERNS = [
@@ -87,51 +231,6 @@ function workerCommandViolation(command) {
87
231
  return null;
88
232
  }
89
233
 
90
- const SESSION_ID_ALLOWLIST = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$/;
91
-
92
- function clearAwaitingConfirmationFlag(directory, stateName, sessionId) {
93
- const stateDir = path.join(directory, '.omcp', 'state');
94
- const safeSessionId = sessionId && SESSION_ID_ALLOWLIST.test(sessionId) ? sessionId : '';
95
- const paths = [
96
- safeSessionId ? path.join(stateDir, 'sessions', safeSessionId, `${stateName}-state.json`) : null,
97
- path.join(stateDir, `${stateName}-state.json`),
98
- path.join(homedir(), '.omcp', 'state', `${stateName}-state.json`),
99
- ].filter(Boolean);
100
-
101
- for (const statePath of paths) {
102
- try {
103
- if (!existsSync(statePath)) continue;
104
- const state = JSON.parse(readFileSync(statePath, 'utf-8'));
105
- if (!state || typeof state !== 'object' || !state.awaiting_confirmation) continue;
106
- delete state.awaiting_confirmation;
107
- const tmpPath = statePath + '.tmp';
108
- writeFileSync(tmpPath, JSON.stringify(state, null, 2), { mode: 0o600 });
109
- renameSync(tmpPath, statePath);
110
- } catch {
111
- // Best-effort; don't fail the hook
112
- }
113
- }
114
- }
115
-
116
- function confirmSkillModeStates(directory, skillName, sessionId) {
117
- switch (skillName) {
118
- case 'ralph':
119
- clearAwaitingConfirmationFlag(directory, 'ralph', sessionId);
120
- clearAwaitingConfirmationFlag(directory, 'ultrawork', sessionId);
121
- break;
122
- case 'ultrawork':
123
- clearAwaitingConfirmationFlag(directory, 'ultrawork', sessionId);
124
- break;
125
- case 'autopilot':
126
- clearAwaitingConfirmationFlag(directory, 'autopilot', sessionId);
127
- break;
128
- case 'ralplan':
129
- clearAwaitingConfirmationFlag(directory, 'ralplan', sessionId);
130
- break;
131
- default:
132
- break;
133
- }
134
- }
135
234
 
136
235
  function checkBashCommand(command) {
137
236
  // Check if command might modify files
@@ -54,6 +54,30 @@ function writeJsonFile(path, data) {
54
54
  }
55
55
  }
56
56
 
57
+
58
+ const SESSION_ID_ALLOWLIST = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$/;
59
+ const WORKFLOW_SLOT_TOMBSTONE_TTL_MS = 24 * 60 * 60 * 1000;
60
+
61
+ function isWorkflowSlotTombstonedForMode(directory, mode, sessionId) {
62
+ const safeSessionId = typeof sessionId === 'string' && SESSION_ID_ALLOWLIST.test(sessionId) ? sessionId : '';
63
+ const ledgerPath = safeSessionId
64
+ ? join(directory, '.omc', 'state', 'sessions', safeSessionId, 'skill-active-state.json')
65
+ : join(directory, '.omc', 'state', 'skill-active-state.json');
66
+ const ledger = readJsonFile(ledgerPath);
67
+ const slot = ledger?.active_skills?.[mode];
68
+ if (!slot || typeof slot !== 'object') return false;
69
+ if (typeof slot.completed_at !== 'string' || !slot.completed_at) return false;
70
+ const completedAt = new Date(slot.completed_at).getTime();
71
+ if (!Number.isFinite(completedAt)) return true;
72
+ return Date.now() - completedAt < WORKFLOW_SLOT_TOMBSTONE_TTL_MS;
73
+ }
74
+
75
+ function shouldRestoreModeState(directory, mode, state, sessionId) {
76
+ if (!state?.active) return false;
77
+ if (isWorkflowSlotTombstonedForMode(directory, mode, sessionId)) return false;
78
+ return true;
79
+ }
80
+
57
81
  async function checkForUpdates(currentVersion) {
58
82
  const cacheFile = join(homedir(), '.omcp', 'update-check.json');
59
83
  const now = Date.now();
@@ -439,7 +463,7 @@ To update, run: omc update
439
463
  ultraworkCandidate.collision.state,
440
464
  ),
441
465
  );
442
- } else if (ultraworkCandidate.restore) {
466
+ } else if (shouldRestoreModeState(directory, 'ultrawork', ultraworkCandidate.restore, sessionId)) {
443
467
  const ultraworkState = ultraworkCandidate.restore;
444
468
  messages.push(`<session-restore>
445
469