oh-my-claude-sisyphus 2.6.1 → 3.0.0

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 (548) hide show
  1. package/README.md +59 -785
  2. package/agents/analyst.md +85 -0
  3. package/agents/architect-low.md +88 -0
  4. package/agents/architect-medium.md +108 -0
  5. package/agents/architect.md +77 -0
  6. package/agents/critic.md +97 -0
  7. package/agents/designer-high.md +113 -0
  8. package/agents/designer-low.md +89 -0
  9. package/agents/designer.md +80 -0
  10. package/agents/executor-high.md +116 -0
  11. package/agents/executor-low.md +94 -0
  12. package/agents/executor.md +62 -0
  13. package/agents/explore-medium.md +113 -0
  14. package/agents/explore.md +86 -0
  15. package/agents/planner.md +164 -0
  16. package/agents/qa-tester.md +109 -0
  17. package/agents/researcher-low.md +84 -0
  18. package/agents/researcher.md +70 -0
  19. package/agents/vision.md +39 -0
  20. package/agents/writer.md +152 -0
  21. package/commands/.gitkeep +0 -0
  22. package/dist/__tests__/hooks.test.js +22 -22
  23. package/dist/__tests__/hooks.test.js.map +1 -1
  24. package/dist/__tests__/hud-agents.test.d.ts +7 -0
  25. package/dist/__tests__/hud-agents.test.d.ts.map +1 -0
  26. package/dist/__tests__/hud-agents.test.js +363 -0
  27. package/dist/__tests__/hud-agents.test.js.map +1 -0
  28. package/dist/__tests__/installer.test.js +184 -116
  29. package/dist/__tests__/installer.test.js.map +1 -1
  30. package/dist/__tests__/learned-skills/config.test.d.ts +2 -0
  31. package/dist/__tests__/learned-skills/config.test.d.ts.map +1 -0
  32. package/dist/__tests__/learned-skills/config.test.js +37 -0
  33. package/dist/__tests__/learned-skills/config.test.js.map +1 -0
  34. package/dist/__tests__/learned-skills/detector.test.d.ts +2 -0
  35. package/dist/__tests__/learned-skills/detector.test.d.ts.map +1 -0
  36. package/dist/__tests__/learned-skills/detector.test.js +99 -0
  37. package/dist/__tests__/learned-skills/detector.test.js.map +1 -0
  38. package/dist/__tests__/learned-skills/finder.test.d.ts +2 -0
  39. package/dist/__tests__/learned-skills/finder.test.d.ts.map +1 -0
  40. package/dist/__tests__/learned-skills/finder.test.js +59 -0
  41. package/dist/__tests__/learned-skills/finder.test.js.map +1 -0
  42. package/dist/__tests__/learned-skills/loader.test.d.ts +2 -0
  43. package/dist/__tests__/learned-skills/loader.test.d.ts.map +1 -0
  44. package/dist/__tests__/learned-skills/loader.test.js +69 -0
  45. package/dist/__tests__/learned-skills/loader.test.js.map +1 -0
  46. package/dist/__tests__/learned-skills/parser.test.d.ts +2 -0
  47. package/dist/__tests__/learned-skills/parser.test.d.ts.map +1 -0
  48. package/dist/__tests__/learned-skills/parser.test.js +81 -0
  49. package/dist/__tests__/learned-skills/parser.test.js.map +1 -0
  50. package/dist/__tests__/learned-skills/validator.test.d.ts +2 -0
  51. package/dist/__tests__/learned-skills/validator.test.d.ts.map +1 -0
  52. package/dist/__tests__/learned-skills/validator.test.js +85 -0
  53. package/dist/__tests__/learned-skills/validator.test.js.map +1 -0
  54. package/dist/__tests__/mnemosyne/config.test.d.ts +2 -0
  55. package/dist/__tests__/mnemosyne/config.test.d.ts.map +1 -0
  56. package/dist/__tests__/mnemosyne/config.test.js +37 -0
  57. package/dist/__tests__/mnemosyne/config.test.js.map +1 -0
  58. package/dist/__tests__/mnemosyne/detector.test.d.ts +2 -0
  59. package/dist/__tests__/mnemosyne/detector.test.d.ts.map +1 -0
  60. package/dist/__tests__/mnemosyne/detector.test.js +99 -0
  61. package/dist/__tests__/mnemosyne/detector.test.js.map +1 -0
  62. package/dist/__tests__/mnemosyne/finder.test.d.ts +2 -0
  63. package/dist/__tests__/mnemosyne/finder.test.d.ts.map +1 -0
  64. package/dist/__tests__/mnemosyne/finder.test.js +61 -0
  65. package/dist/__tests__/mnemosyne/finder.test.js.map +1 -0
  66. package/dist/__tests__/mnemosyne/loader.test.d.ts +2 -0
  67. package/dist/__tests__/mnemosyne/loader.test.d.ts.map +1 -0
  68. package/dist/__tests__/mnemosyne/loader.test.js +73 -0
  69. package/dist/__tests__/mnemosyne/loader.test.js.map +1 -0
  70. package/dist/__tests__/mnemosyne/parser.test.d.ts +2 -0
  71. package/dist/__tests__/mnemosyne/parser.test.d.ts.map +1 -0
  72. package/dist/__tests__/mnemosyne/parser.test.js +81 -0
  73. package/dist/__tests__/mnemosyne/parser.test.js.map +1 -0
  74. package/dist/__tests__/mnemosyne/validator.test.d.ts +2 -0
  75. package/dist/__tests__/mnemosyne/validator.test.d.ts.map +1 -0
  76. package/dist/__tests__/mnemosyne/validator.test.js +85 -0
  77. package/dist/__tests__/mnemosyne/validator.test.js.map +1 -0
  78. package/dist/__tests__/model-routing.test.js +34 -34
  79. package/dist/__tests__/model-routing.test.js.map +1 -1
  80. package/dist/__tests__/notepad.test.js +7 -7
  81. package/dist/__tests__/notepad.test.js.map +1 -1
  82. package/dist/__tests__/ralph-prd.test.js +12 -12
  83. package/dist/__tests__/ralph-prd.test.js.map +1 -1
  84. package/dist/__tests__/ralph-progress.test.js +12 -12
  85. package/dist/__tests__/ralph-progress.test.js.map +1 -1
  86. package/dist/__tests__/skills.test.js +50 -17
  87. package/dist/__tests__/skills.test.js.map +1 -1
  88. package/dist/__tests__/types.test.js +5 -5
  89. package/dist/__tests__/types.test.js.map +1 -1
  90. package/dist/agents/analyst.d.ts +11 -0
  91. package/dist/agents/analyst.d.ts.map +1 -0
  92. package/dist/agents/analyst.js +115 -0
  93. package/dist/agents/analyst.js.map +1 -0
  94. package/dist/agents/architect.d.ts +12 -0
  95. package/dist/agents/architect.d.ts.map +1 -0
  96. package/dist/agents/architect.js +189 -0
  97. package/dist/agents/architect.js.map +1 -0
  98. package/dist/agents/coordinator.d.ts +11 -0
  99. package/dist/agents/coordinator.d.ts.map +1 -0
  100. package/dist/agents/coordinator.js +115 -0
  101. package/dist/agents/coordinator.js.map +1 -0
  102. package/dist/agents/critic.d.ts +11 -0
  103. package/dist/agents/critic.d.ts.map +1 -0
  104. package/dist/agents/critic.js +127 -0
  105. package/dist/agents/critic.js.map +1 -0
  106. package/dist/agents/definitions.d.ts +33 -70
  107. package/dist/agents/definitions.d.ts.map +1 -1
  108. package/dist/agents/definitions.js +140 -1268
  109. package/dist/agents/definitions.js.map +1 -1
  110. package/dist/agents/designer.d.ts +11 -0
  111. package/dist/agents/designer.d.ts.map +1 -0
  112. package/dist/agents/designer.js +115 -0
  113. package/dist/agents/designer.js.map +1 -0
  114. package/dist/agents/executor.d.ts +12 -0
  115. package/dist/agents/executor.d.ts.map +1 -0
  116. package/dist/agents/executor.js +93 -0
  117. package/dist/agents/executor.js.map +1 -0
  118. package/dist/agents/explore.js +4 -4
  119. package/dist/agents/explore.js.map +1 -1
  120. package/dist/agents/index.d.ts +12 -11
  121. package/dist/agents/index.d.ts.map +1 -1
  122. package/dist/agents/index.js +15 -16
  123. package/dist/agents/index.js.map +1 -1
  124. package/dist/agents/planner.d.ts +11 -0
  125. package/dist/agents/planner.d.ts.map +1 -0
  126. package/dist/agents/planner.js +194 -0
  127. package/dist/agents/planner.js.map +1 -0
  128. package/dist/agents/qa-tester.js +16 -16
  129. package/dist/agents/qa-tester.js.map +1 -1
  130. package/dist/agents/researcher.d.ts +12 -0
  131. package/dist/agents/researcher.d.ts.map +1 -0
  132. package/dist/agents/researcher.js +103 -0
  133. package/dist/agents/researcher.js.map +1 -0
  134. package/dist/agents/vision.d.ts +11 -0
  135. package/dist/agents/vision.d.ts.map +1 -0
  136. package/dist/agents/vision.js +70 -0
  137. package/dist/agents/vision.js.map +1 -0
  138. package/dist/agents/writer.d.ts +11 -0
  139. package/dist/agents/writer.d.ts.map +1 -0
  140. package/dist/agents/writer.js +209 -0
  141. package/dist/agents/writer.js.map +1 -0
  142. package/dist/cli/index.js +32 -32
  143. package/dist/cli/index.js.map +1 -1
  144. package/dist/commands/index.d.ts +4 -4
  145. package/dist/commands/index.js +4 -4
  146. package/dist/config/loader.js +25 -25
  147. package/dist/config/loader.js.map +1 -1
  148. package/dist/features/auto-update.d.ts +5 -5
  149. package/dist/features/auto-update.d.ts.map +1 -1
  150. package/dist/features/auto-update.js +17 -17
  151. package/dist/features/auto-update.js.map +1 -1
  152. package/dist/features/background-agent/manager.js +1 -1
  153. package/dist/features/background-agent/manager.js.map +1 -1
  154. package/dist/features/boulder-state/constants.d.ts +5 -5
  155. package/dist/features/boulder-state/constants.d.ts.map +1 -1
  156. package/dist/features/boulder-state/constants.js +3 -3
  157. package/dist/features/boulder-state/constants.js.map +1 -1
  158. package/dist/features/boulder-state/index.d.ts +2 -2
  159. package/dist/features/boulder-state/index.d.ts.map +1 -1
  160. package/dist/features/boulder-state/index.js +2 -2
  161. package/dist/features/boulder-state/index.js.map +1 -1
  162. package/dist/features/boulder-state/storage.d.ts +3 -3
  163. package/dist/features/boulder-state/storage.d.ts.map +1 -1
  164. package/dist/features/boulder-state/storage.js +6 -6
  165. package/dist/features/boulder-state/storage.js.map +1 -1
  166. package/dist/features/builtin-skills/skills.d.ts +15 -1
  167. package/dist/features/builtin-skills/skills.d.ts.map +1 -1
  168. package/dist/features/builtin-skills/skills.js +100 -1110
  169. package/dist/features/builtin-skills/skills.js.map +1 -1
  170. package/dist/features/context-injector/types.d.ts +1 -1
  171. package/dist/features/context-injector/types.d.ts.map +1 -1
  172. package/dist/features/index.d.ts +1 -1
  173. package/dist/features/index.d.ts.map +1 -1
  174. package/dist/features/index.js +2 -2
  175. package/dist/features/index.js.map +1 -1
  176. package/dist/features/magic-keywords.js +14 -14
  177. package/dist/features/magic-keywords.js.map +1 -1
  178. package/dist/features/model-routing/prompts/opus.d.ts +1 -1
  179. package/dist/features/model-routing/prompts/opus.d.ts.map +1 -1
  180. package/dist/features/model-routing/prompts/opus.js +1 -1
  181. package/dist/features/model-routing/router.d.ts +1 -1
  182. package/dist/features/model-routing/router.js +14 -14
  183. package/dist/features/model-routing/router.js.map +1 -1
  184. package/dist/features/model-routing/rules.js +31 -31
  185. package/dist/features/model-routing/rules.js.map +1 -1
  186. package/dist/features/model-routing/types.js +1 -1
  187. package/dist/features/model-routing/types.js.map +1 -1
  188. package/dist/hooks/agent-usage-reminder/constants.d.ts +2 -2
  189. package/dist/hooks/agent-usage-reminder/constants.d.ts.map +1 -1
  190. package/dist/hooks/agent-usage-reminder/constants.js +5 -5
  191. package/dist/hooks/agent-usage-reminder/constants.js.map +1 -1
  192. package/dist/hooks/auto-slash-command/constants.d.ts +1 -1
  193. package/dist/hooks/auto-slash-command/constants.d.ts.map +1 -1
  194. package/dist/hooks/auto-slash-command/constants.js +9 -2
  195. package/dist/hooks/auto-slash-command/constants.js.map +1 -1
  196. package/dist/hooks/bridge.d.ts +2 -2
  197. package/dist/hooks/bridge.d.ts.map +1 -1
  198. package/dist/hooks/bridge.js +50 -18
  199. package/dist/hooks/bridge.js.map +1 -1
  200. package/dist/hooks/directory-readme-injector/constants.d.ts +1 -1
  201. package/dist/hooks/directory-readme-injector/constants.d.ts.map +1 -1
  202. package/dist/hooks/directory-readme-injector/constants.js +2 -2
  203. package/dist/hooks/directory-readme-injector/constants.js.map +1 -1
  204. package/dist/hooks/index.d.ts +3 -2
  205. package/dist/hooks/index.d.ts.map +1 -1
  206. package/dist/hooks/index.js +9 -4
  207. package/dist/hooks/index.js.map +1 -1
  208. package/dist/hooks/learned-skills/config.d.ts +53 -0
  209. package/dist/hooks/learned-skills/config.d.ts.map +1 -0
  210. package/dist/hooks/learned-skills/config.js +103 -0
  211. package/dist/hooks/learned-skills/config.js.map +1 -0
  212. package/dist/hooks/learned-skills/constants.d.ts +24 -0
  213. package/dist/hooks/learned-skills/constants.d.ts.map +1 -0
  214. package/dist/hooks/learned-skills/constants.js +26 -0
  215. package/dist/hooks/learned-skills/constants.js.map +1 -0
  216. package/dist/hooks/learned-skills/detection-hook.d.ts +39 -0
  217. package/dist/hooks/learned-skills/detection-hook.d.ts.map +1 -0
  218. package/dist/hooks/learned-skills/detection-hook.js +83 -0
  219. package/dist/hooks/learned-skills/detection-hook.js.map +1 -0
  220. package/dist/hooks/learned-skills/detector.d.ts +30 -0
  221. package/dist/hooks/learned-skills/detector.d.ts.map +1 -0
  222. package/dist/hooks/learned-skills/detector.js +150 -0
  223. package/dist/hooks/learned-skills/detector.js.map +1 -0
  224. package/dist/hooks/learned-skills/finder.d.ts +21 -0
  225. package/dist/hooks/learned-skills/finder.d.ts.map +1 -0
  226. package/dist/hooks/learned-skills/finder.js +117 -0
  227. package/dist/hooks/learned-skills/finder.js.map +1 -0
  228. package/dist/hooks/learned-skills/index.d.ts +62 -0
  229. package/dist/hooks/learned-skills/index.d.ts.map +1 -0
  230. package/dist/hooks/learned-skills/index.js +137 -0
  231. package/dist/hooks/learned-skills/index.js.map +1 -0
  232. package/dist/hooks/learned-skills/loader.d.ts +20 -0
  233. package/dist/hooks/learned-skills/loader.d.ts.map +1 -0
  234. package/dist/hooks/learned-skills/loader.js +107 -0
  235. package/dist/hooks/learned-skills/loader.js.map +1 -0
  236. package/dist/hooks/learned-skills/parser.d.ts +21 -0
  237. package/dist/hooks/learned-skills/parser.d.ts.map +1 -0
  238. package/dist/hooks/learned-skills/parser.js +190 -0
  239. package/dist/hooks/learned-skills/parser.js.map +1 -0
  240. package/dist/hooks/learned-skills/promotion.d.ts +29 -0
  241. package/dist/hooks/learned-skills/promotion.d.ts.map +1 -0
  242. package/dist/hooks/learned-skills/promotion.js +87 -0
  243. package/dist/hooks/learned-skills/promotion.js.map +1 -0
  244. package/dist/hooks/learned-skills/types.d.ts +109 -0
  245. package/dist/hooks/learned-skills/types.d.ts.map +1 -0
  246. package/dist/hooks/learned-skills/types.js +8 -0
  247. package/dist/hooks/learned-skills/types.js.map +1 -0
  248. package/dist/hooks/learned-skills/validator.d.ts +15 -0
  249. package/dist/hooks/learned-skills/validator.d.ts.map +1 -0
  250. package/dist/hooks/learned-skills/validator.js +87 -0
  251. package/dist/hooks/learned-skills/validator.js.map +1 -0
  252. package/dist/hooks/learned-skills/writer.d.ts +27 -0
  253. package/dist/hooks/learned-skills/writer.d.ts.map +1 -0
  254. package/dist/hooks/learned-skills/writer.js +126 -0
  255. package/dist/hooks/learned-skills/writer.js.map +1 -0
  256. package/dist/hooks/learner/config.d.ts +53 -0
  257. package/dist/hooks/learner/config.d.ts.map +1 -0
  258. package/dist/hooks/learner/config.js +103 -0
  259. package/dist/hooks/learner/config.js.map +1 -0
  260. package/dist/hooks/learner/constants.d.ts +24 -0
  261. package/dist/hooks/learner/constants.d.ts.map +1 -0
  262. package/dist/hooks/learner/constants.js +26 -0
  263. package/dist/hooks/learner/constants.js.map +1 -0
  264. package/dist/hooks/learner/detection-hook.d.ts +39 -0
  265. package/dist/hooks/learner/detection-hook.d.ts.map +1 -0
  266. package/dist/hooks/learner/detection-hook.js +83 -0
  267. package/dist/hooks/learner/detection-hook.js.map +1 -0
  268. package/dist/hooks/learner/detector.d.ts +30 -0
  269. package/dist/hooks/learner/detector.d.ts.map +1 -0
  270. package/dist/hooks/learner/detector.js +150 -0
  271. package/dist/hooks/learner/detector.js.map +1 -0
  272. package/dist/hooks/learner/finder.d.ts +21 -0
  273. package/dist/hooks/learner/finder.d.ts.map +1 -0
  274. package/dist/hooks/learner/finder.js +117 -0
  275. package/dist/hooks/learner/finder.js.map +1 -0
  276. package/dist/hooks/learner/index.d.ts +62 -0
  277. package/dist/hooks/learner/index.d.ts.map +1 -0
  278. package/dist/hooks/learner/index.js +137 -0
  279. package/dist/hooks/learner/index.js.map +1 -0
  280. package/dist/hooks/learner/loader.d.ts +20 -0
  281. package/dist/hooks/learner/loader.d.ts.map +1 -0
  282. package/dist/hooks/learner/loader.js +113 -0
  283. package/dist/hooks/learner/loader.js.map +1 -0
  284. package/dist/hooks/learner/parser.d.ts +21 -0
  285. package/dist/hooks/learner/parser.d.ts.map +1 -0
  286. package/dist/hooks/learner/parser.js +190 -0
  287. package/dist/hooks/learner/parser.js.map +1 -0
  288. package/dist/hooks/learner/promotion.d.ts +29 -0
  289. package/dist/hooks/learner/promotion.d.ts.map +1 -0
  290. package/dist/hooks/learner/promotion.js +87 -0
  291. package/dist/hooks/learner/promotion.js.map +1 -0
  292. package/dist/hooks/learner/types.d.ts +109 -0
  293. package/dist/hooks/learner/types.d.ts.map +1 -0
  294. package/dist/hooks/learner/types.js +8 -0
  295. package/dist/hooks/learner/types.js.map +1 -0
  296. package/dist/hooks/learner/validator.d.ts +15 -0
  297. package/dist/hooks/learner/validator.d.ts.map +1 -0
  298. package/dist/hooks/learner/validator.js +87 -0
  299. package/dist/hooks/learner/validator.js.map +1 -0
  300. package/dist/hooks/learner/writer.d.ts +27 -0
  301. package/dist/hooks/learner/writer.d.ts.map +1 -0
  302. package/dist/hooks/learner/writer.js +126 -0
  303. package/dist/hooks/learner/writer.js.map +1 -0
  304. package/dist/hooks/mnemosyne/config.d.ts +53 -0
  305. package/dist/hooks/mnemosyne/config.d.ts.map +1 -0
  306. package/dist/hooks/mnemosyne/config.js +103 -0
  307. package/dist/hooks/mnemosyne/config.js.map +1 -0
  308. package/dist/hooks/mnemosyne/constants.d.ts +24 -0
  309. package/dist/hooks/mnemosyne/constants.d.ts.map +1 -0
  310. package/dist/hooks/mnemosyne/constants.js +26 -0
  311. package/dist/hooks/mnemosyne/constants.js.map +1 -0
  312. package/dist/hooks/mnemosyne/detection-hook.d.ts +39 -0
  313. package/dist/hooks/mnemosyne/detection-hook.d.ts.map +1 -0
  314. package/dist/hooks/mnemosyne/detection-hook.js +83 -0
  315. package/dist/hooks/mnemosyne/detection-hook.js.map +1 -0
  316. package/dist/hooks/mnemosyne/detector.d.ts +30 -0
  317. package/dist/hooks/mnemosyne/detector.d.ts.map +1 -0
  318. package/dist/hooks/mnemosyne/detector.js +150 -0
  319. package/dist/hooks/mnemosyne/detector.js.map +1 -0
  320. package/dist/hooks/mnemosyne/finder.d.ts +21 -0
  321. package/dist/hooks/mnemosyne/finder.d.ts.map +1 -0
  322. package/dist/hooks/mnemosyne/finder.js +117 -0
  323. package/dist/hooks/mnemosyne/finder.js.map +1 -0
  324. package/dist/hooks/mnemosyne/index.d.ts +62 -0
  325. package/dist/hooks/mnemosyne/index.d.ts.map +1 -0
  326. package/dist/hooks/mnemosyne/index.js +137 -0
  327. package/dist/hooks/mnemosyne/index.js.map +1 -0
  328. package/dist/hooks/mnemosyne/loader.d.ts +20 -0
  329. package/dist/hooks/mnemosyne/loader.d.ts.map +1 -0
  330. package/dist/hooks/mnemosyne/loader.js +113 -0
  331. package/dist/hooks/mnemosyne/loader.js.map +1 -0
  332. package/dist/hooks/mnemosyne/parser.d.ts +21 -0
  333. package/dist/hooks/mnemosyne/parser.d.ts.map +1 -0
  334. package/dist/hooks/mnemosyne/parser.js +190 -0
  335. package/dist/hooks/mnemosyne/parser.js.map +1 -0
  336. package/dist/hooks/mnemosyne/promotion.d.ts +29 -0
  337. package/dist/hooks/mnemosyne/promotion.d.ts.map +1 -0
  338. package/dist/hooks/mnemosyne/promotion.js +87 -0
  339. package/dist/hooks/mnemosyne/promotion.js.map +1 -0
  340. package/dist/hooks/mnemosyne/types.d.ts +109 -0
  341. package/dist/hooks/mnemosyne/types.d.ts.map +1 -0
  342. package/dist/hooks/mnemosyne/types.js +8 -0
  343. package/dist/hooks/mnemosyne/types.js.map +1 -0
  344. package/dist/hooks/mnemosyne/validator.d.ts +15 -0
  345. package/dist/hooks/mnemosyne/validator.d.ts.map +1 -0
  346. package/dist/hooks/mnemosyne/validator.js +87 -0
  347. package/dist/hooks/mnemosyne/validator.js.map +1 -0
  348. package/dist/hooks/mnemosyne/writer.d.ts +27 -0
  349. package/dist/hooks/mnemosyne/writer.d.ts.map +1 -0
  350. package/dist/hooks/mnemosyne/writer.js +126 -0
  351. package/dist/hooks/mnemosyne/writer.js.map +1 -0
  352. package/dist/hooks/notepad/index.d.ts +2 -2
  353. package/dist/hooks/notepad/index.js +7 -7
  354. package/dist/hooks/notepad/index.js.map +1 -1
  355. package/dist/hooks/omc-orchestrator/constants.d.ts +23 -0
  356. package/dist/hooks/omc-orchestrator/constants.d.ts.map +1 -0
  357. package/dist/hooks/omc-orchestrator/constants.js +142 -0
  358. package/dist/hooks/omc-orchestrator/constants.js.map +1 -0
  359. package/dist/hooks/omc-orchestrator/index.d.ts +113 -0
  360. package/dist/hooks/omc-orchestrator/index.d.ts.map +1 -0
  361. package/dist/hooks/omc-orchestrator/index.js +309 -0
  362. package/dist/hooks/omc-orchestrator/index.js.map +1 -0
  363. package/dist/hooks/persistent-mode/index.d.ts +4 -4
  364. package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
  365. package/dist/hooks/persistent-mode/index.js +37 -37
  366. package/dist/hooks/persistent-mode/index.js.map +1 -1
  367. package/dist/hooks/ralph-loop/index.d.ts +33 -5
  368. package/dist/hooks/ralph-loop/index.d.ts.map +1 -1
  369. package/dist/hooks/ralph-loop/index.js +91 -17
  370. package/dist/hooks/ralph-loop/index.js.map +1 -1
  371. package/dist/hooks/ralph-prd/index.d.ts +4 -4
  372. package/dist/hooks/ralph-prd/index.d.ts.map +1 -1
  373. package/dist/hooks/ralph-prd/index.js +13 -13
  374. package/dist/hooks/ralph-prd/index.js.map +1 -1
  375. package/dist/hooks/ralph-progress/index.d.ts +5 -5
  376. package/dist/hooks/ralph-progress/index.d.ts.map +1 -1
  377. package/dist/hooks/ralph-progress/index.js +14 -14
  378. package/dist/hooks/ralph-progress/index.js.map +1 -1
  379. package/dist/hooks/ralph-verifier/index.d.ts +23 -23
  380. package/dist/hooks/ralph-verifier/index.d.ts.map +1 -1
  381. package/dist/hooks/ralph-verifier/index.js +41 -41
  382. package/dist/hooks/ralph-verifier/index.js.map +1 -1
  383. package/dist/hooks/rules-injector/constants.d.ts +1 -1
  384. package/dist/hooks/rules-injector/constants.d.ts.map +1 -1
  385. package/dist/hooks/rules-injector/constants.js +2 -2
  386. package/dist/hooks/rules-injector/constants.js.map +1 -1
  387. package/dist/hooks/todo-continuation/index.js +1 -1
  388. package/dist/hooks/todo-continuation/index.js.map +1 -1
  389. package/dist/hooks/ultraqa-loop/index.d.ts +1 -1
  390. package/dist/hooks/ultraqa-loop/index.js +8 -8
  391. package/dist/hooks/ultraqa-loop/index.js.map +1 -1
  392. package/dist/hooks/ultrawork-state/index.js +7 -7
  393. package/dist/hooks/ultrawork-state/index.js.map +1 -1
  394. package/dist/hud/background-tasks.d.ts +26 -0
  395. package/dist/hud/background-tasks.d.ts.map +1 -0
  396. package/dist/hud/background-tasks.js +116 -0
  397. package/dist/hud/background-tasks.js.map +1 -0
  398. package/dist/hud/colors.d.ts +54 -0
  399. package/dist/hud/colors.d.ts.map +1 -0
  400. package/dist/hud/colors.js +156 -0
  401. package/dist/hud/colors.js.map +1 -0
  402. package/dist/hud/elements/agents.d.ts +73 -0
  403. package/dist/hud/elements/agents.d.ts.map +1 -0
  404. package/dist/hud/elements/agents.js +405 -0
  405. package/dist/hud/elements/agents.js.map +1 -0
  406. package/dist/hud/elements/background.d.ts +20 -0
  407. package/dist/hud/elements/background.d.ts.map +1 -0
  408. package/dist/hud/elements/background.js +70 -0
  409. package/dist/hud/elements/background.js.map +1 -0
  410. package/dist/hud/elements/context.d.ts +19 -0
  411. package/dist/hud/elements/context.d.ts.map +1 -0
  412. package/dist/hud/elements/context.js +58 -0
  413. package/dist/hud/elements/context.js.map +1 -0
  414. package/dist/hud/elements/index.d.ts +17 -0
  415. package/dist/hud/elements/index.d.ts.map +1 -0
  416. package/dist/hud/elements/index.js +17 -0
  417. package/dist/hud/elements/index.js.map +1 -0
  418. package/dist/hud/elements/limits.d.ts +19 -0
  419. package/dist/hud/elements/limits.d.ts.map +1 -0
  420. package/dist/hud/elements/limits.js +54 -0
  421. package/dist/hud/elements/limits.js.map +1 -0
  422. package/dist/hud/elements/permission.d.ts +13 -0
  423. package/dist/hud/elements/permission.d.ts.map +1 -0
  424. package/dist/hud/elements/permission.js +20 -0
  425. package/dist/hud/elements/permission.js.map +1 -0
  426. package/dist/hud/elements/prd.d.ts +20 -0
  427. package/dist/hud/elements/prd.d.ts.map +1 -0
  428. package/dist/hud/elements/prd.js +52 -0
  429. package/dist/hud/elements/prd.js.map +1 -0
  430. package/dist/hud/elements/ralph.d.ts +14 -0
  431. package/dist/hud/elements/ralph.d.ts.map +1 -0
  432. package/dist/hud/elements/ralph.js +36 -0
  433. package/dist/hud/elements/ralph.js.map +1 -0
  434. package/dist/hud/elements/session.d.ts +13 -0
  435. package/dist/hud/elements/session.d.ts.map +1 -0
  436. package/dist/hud/elements/session.js +24 -0
  437. package/dist/hud/elements/session.js.map +1 -0
  438. package/dist/hud/elements/skills.d.ts +24 -0
  439. package/dist/hud/elements/skills.d.ts.map +1 -0
  440. package/dist/hud/elements/skills.js +81 -0
  441. package/dist/hud/elements/skills.js.map +1 -0
  442. package/dist/hud/elements/thinking.d.ts +13 -0
  443. package/dist/hud/elements/thinking.d.ts.map +1 -0
  444. package/dist/hud/elements/thinking.js +19 -0
  445. package/dist/hud/elements/thinking.js.map +1 -0
  446. package/dist/hud/elements/todos.d.ts +20 -0
  447. package/dist/hud/elements/todos.d.ts.map +1 -0
  448. package/dist/hud/elements/todos.js +70 -0
  449. package/dist/hud/elements/todos.js.map +1 -0
  450. package/dist/hud/index.d.ts +9 -0
  451. package/dist/hud/index.d.ts.map +1 -0
  452. package/dist/hud/index.js +89 -0
  453. package/dist/hud/index.js.map +1 -0
  454. package/dist/hud/omc-state.d.ts +31 -0
  455. package/dist/hud/omc-state.d.ts.map +1 -0
  456. package/dist/hud/omc-state.js +163 -0
  457. package/dist/hud/omc-state.js.map +1 -0
  458. package/dist/hud/render.d.ts +11 -0
  459. package/dist/hud/render.d.ts.map +1 -0
  460. package/dist/hud/render.js +121 -0
  461. package/dist/hud/render.js.map +1 -0
  462. package/dist/hud/sisyphus-state.d.ts +31 -0
  463. package/dist/hud/sisyphus-state.d.ts.map +1 -0
  464. package/dist/hud/sisyphus-state.js +163 -0
  465. package/dist/hud/sisyphus-state.js.map +1 -0
  466. package/dist/hud/state.d.ts +43 -0
  467. package/dist/hud/state.d.ts.map +1 -0
  468. package/dist/hud/state.js +201 -0
  469. package/dist/hud/state.js.map +1 -0
  470. package/dist/hud/stdin.d.ts +22 -0
  471. package/dist/hud/stdin.d.ts.map +1 -0
  472. package/dist/hud/stdin.js +65 -0
  473. package/dist/hud/stdin.js.map +1 -0
  474. package/dist/hud/transcript.d.ts +32 -0
  475. package/dist/hud/transcript.d.ts.map +1 -0
  476. package/dist/hud/transcript.js +364 -0
  477. package/dist/hud/transcript.js.map +1 -0
  478. package/dist/hud/types.d.ts +178 -0
  479. package/dist/hud/types.d.ts.map +1 -0
  480. package/dist/hud/types.js +119 -0
  481. package/dist/hud/types.js.map +1 -0
  482. package/dist/hud/usage-api.d.ts +24 -0
  483. package/dist/hud/usage-api.d.ts.map +1 -0
  484. package/dist/hud/usage-api.js +234 -0
  485. package/dist/hud/usage-api.js.map +1 -0
  486. package/dist/index.d.ts +7 -7
  487. package/dist/index.d.ts.map +1 -1
  488. package/dist/index.js +10 -12
  489. package/dist/index.js.map +1 -1
  490. package/dist/installer/hooks.d.ts +36 -64
  491. package/dist/installer/hooks.d.ts.map +1 -1
  492. package/dist/installer/hooks.js +91 -1298
  493. package/dist/installer/hooks.js.map +1 -1
  494. package/dist/installer/index.d.ts +23 -22
  495. package/dist/installer/index.d.ts.map +1 -1
  496. package/dist/installer/index.js +307 -2575
  497. package/dist/installer/index.js.map +1 -1
  498. package/dist/shared/types.d.ts +6 -6
  499. package/dist/shared/types.d.ts.map +1 -1
  500. package/docs/ARCHITECTURE.md +386 -0
  501. package/docs/CLAUDE.md +281 -0
  502. package/docs/FULL-README.md +822 -0
  503. package/docs/LOCAL_PLUGIN_INSTALL.md +94 -0
  504. package/docs/MIGRATION-v3.md +186 -0
  505. package/docs/MIGRATION.md +460 -0
  506. package/docs/TIERED_AGENTS_V2.md +322 -0
  507. package/hooks/hooks.json +70 -0
  508. package/hooks/keyword-detector.sh +102 -0
  509. package/hooks/persistent-mode.sh +172 -0
  510. package/hooks/session-start.sh +62 -0
  511. package/hooks/stop-continuation.sh +40 -0
  512. package/package.json +14 -8
  513. package/scripts/install.sh +90 -72
  514. package/scripts/keyword-detector.mjs +1 -1
  515. package/scripts/persistent-mode.mjs +9 -9
  516. package/scripts/persistent-mode.sh +21 -10
  517. package/scripts/plugin-setup.mjs +109 -0
  518. package/scripts/pre-tool-enforcer.mjs +1 -1
  519. package/scripts/pre-tool-enforcer.sh +1 -1
  520. package/scripts/session-start.mjs +38 -3
  521. package/scripts/skill-injector.mjs +231 -0
  522. package/scripts/uninstall.sh +8 -8
  523. package/skills/analyze/SKILL.md +47 -0
  524. package/skills/cancel-ralph/SKILL.md +43 -0
  525. package/skills/cancel-ultraqa/SKILL.md +29 -0
  526. package/skills/cancel-ultrawork/SKILL.md +42 -0
  527. package/skills/deepinit/SKILL.md +321 -0
  528. package/skills/deepsearch/SKILL.md +39 -0
  529. package/skills/doctor/SKILL.md +192 -0
  530. package/skills/frontend-ui-ux/SKILL.md +53 -0
  531. package/skills/git-master/SKILL.md +58 -0
  532. package/skills/help/SKILL.md +66 -0
  533. package/skills/hud/SKILL.md +142 -0
  534. package/skills/learner/SKILL.md +136 -0
  535. package/skills/note/SKILL.md +63 -0
  536. package/skills/omc-default/SKILL.md +78 -0
  537. package/skills/omc-default-global/SKILL.md +75 -0
  538. package/skills/omc-setup/SKILL.md +144 -0
  539. package/skills/orchestrate/SKILL.md +409 -0
  540. package/skills/plan/SKILL.md +37 -0
  541. package/skills/planner/SKILL.md +43 -0
  542. package/skills/ralph/SKILL.md +101 -0
  543. package/skills/ralph-init/SKILL.md +61 -0
  544. package/skills/ralplan/SKILL.md +219 -0
  545. package/skills/release/SKILL.md +84 -0
  546. package/skills/review/SKILL.md +37 -0
  547. package/skills/ultraqa/SKILL.md +123 -0
  548. package/skills/ultrawork/SKILL.md +89 -0
@@ -10,11 +10,43 @@
10
10
  * - Node.js scripts (.mjs) for cross-platform support (Windows, macOS, Linux)
11
11
  *
12
12
  * The platform is detected at install time, or can be overridden with:
13
- * SISYPHUS_USE_NODE_HOOKS=1 - Force Node.js hooks on any platform
14
- * SISYPHUS_USE_BASH_HOOKS=1 - Force Bash hooks (Unix only)
13
+ * OMC_USE_NODE_HOOKS=1 - Force Node.js hooks on any platform
14
+ * OMC_USE_BASH_HOOKS=1 - Force Bash hooks (Unix only)
15
15
  */
16
16
  import { homedir } from 'os';
17
- import { join } from 'path';
17
+ import { join, dirname } from 'path';
18
+ import { readFileSync, existsSync } from 'fs';
19
+ import { fileURLToPath } from 'url';
20
+ // =============================================================================
21
+ // TEMPLATE LOADER (loads hook scripts from templates/hooks/)
22
+ // =============================================================================
23
+ /**
24
+ * Get the package root directory (where templates/ lives)
25
+ * Works for both development (src/) and production (dist/)
26
+ */
27
+ function getPackageDir() {
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = dirname(__filename);
30
+ // From src/installer/ or dist/installer/, go up two levels to package root
31
+ return join(__dirname, '..', '..');
32
+ }
33
+ /**
34
+ * Load a hook template file from templates/hooks/
35
+ * @param filename - The template filename (e.g., 'keyword-detector.sh')
36
+ * @returns The template content
37
+ * @throws If the template file is not found
38
+ */
39
+ function loadTemplate(filename) {
40
+ const templatePath = join(getPackageDir(), 'templates', 'hooks', filename);
41
+ if (!existsSync(templatePath)) {
42
+ console.error(`FATAL: Hook template not found: ${templatePath}`);
43
+ process.exit(1);
44
+ }
45
+ return readFileSync(templatePath, 'utf-8');
46
+ }
47
+ // =============================================================================
48
+ // CONSTANTS AND UTILITIES
49
+ // =============================================================================
18
50
  /** Minimum required Node.js version for hooks */
19
51
  export const MIN_NODE_VERSION = 18;
20
52
  /** Check if running on Windows */
@@ -24,10 +56,10 @@ export function isWindows() {
24
56
  /** Check if Node.js hooks should be used (env override or Windows) */
25
57
  export function shouldUseNodeHooks() {
26
58
  // Environment variable overrides
27
- if (process.env.SISYPHUS_USE_NODE_HOOKS === '1') {
59
+ if (process.env.OMC_USE_NODE_HOOKS === '1') {
28
60
  return true;
29
61
  }
30
- if (process.env.SISYPHUS_USE_BASH_HOOKS === '1') {
62
+ if (process.env.OMC_USE_BASH_HOOKS === '1') {
31
63
  return false;
32
64
  }
33
65
  // Default: use Node.js on Windows, Bash elsewhere
@@ -63,7 +95,7 @@ TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
63
95
 
64
96
  ## AGENT UTILIZATION PRINCIPLES (by capability, not by name)
65
97
  - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure
66
- - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs
98
+ - **Documentation & References**: Use researcher-type agents via BACKGROUND TASKS for API references, examples, external library docs
67
99
  - **Planning & Strategy**: NEVER plan yourself - ALWAYS spawn a dedicated planning agent for work breakdown
68
100
  - **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning
69
101
  - **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation
@@ -77,7 +109,7 @@ TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
77
109
 
78
110
  ## WORKFLOW
79
111
  1. Analyze the request and identify required capabilities
80
- 2. Spawn exploration/librarian agents via Task(run_in_background=true) in PARALLEL (10+ if needed)
112
+ 2. Spawn exploration/researcher agents via Task(run_in_background=true) in PARALLEL (10+ if needed)
81
113
  3. Always Use Plan agent with gathered context to create detailed work breakdown
82
114
  4. Execute with continuous verification against original requirements
83
115
 
@@ -172,7 +204,7 @@ Use your extended thinking capabilities to provide the most thorough and well-re
172
204
  export const SEARCH_MESSAGE = `<search-mode>
173
205
  MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:
174
206
  - explore agents (codebase patterns, file structures)
175
- - librarian agents (remote repos, official docs, GitHub examples)
207
+ - researcher agents (remote repos, official docs, GitHub examples)
176
208
  Plus direct tools: Grep, Glob
177
209
  NEVER stop at first result - be exhaustive.
178
210
  </search-mode>
@@ -189,11 +221,11 @@ ANALYSIS MODE. Gather context before diving deep:
189
221
 
190
222
  CONTEXT GATHERING (parallel):
191
223
  - 1-2 explore agents (codebase patterns, implementations)
192
- - 1-2 librarian agents (if external library involved)
224
+ - 1-2 researcher agents (if external library involved)
193
225
  - Direct tools: Grep, Glob, LSP for targeted searches
194
226
 
195
227
  IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
196
- - Consult oracle agent for strategic guidance
228
+ - Consult architect agent for strategic guidance
197
229
 
198
230
  SYNTHESIZE findings before proceeding.
199
231
  </analyze-mode>
@@ -212,1282 +244,35 @@ Incomplete tasks remain in your todo list. Continue working on the next pending
212
244
  - Proceed without asking for permission
213
245
  - Mark each task complete when finished
214
246
  - Do not stop until all tasks are done`;
215
- /**
216
- * Keyword detector hook script
217
- * This script is installed to ~/.claude/hooks/keyword-detector.sh
218
- */
219
- export const KEYWORD_DETECTOR_SCRIPT = `#!/bin/bash
220
- # Sisyphus Keyword Detector Hook
221
- # Detects ultrawork/ultrathink/search/analyze keywords and injects enhanced mode messages
222
- # Also activates persistent ultrawork state when ultrawork keyword is detected
223
-
224
- # Read stdin (JSON input from Claude Code)
225
- INPUT=$(cat)
226
-
227
- # Extract directory from input
228
- DIRECTORY=""
229
- if command -v jq &> /dev/null; then
230
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
231
- fi
232
- if [ -z "$DIRECTORY" ] || [ "$DIRECTORY" = "null" ]; then
233
- DIRECTORY=$(pwd)
234
- fi
235
-
236
- # Extract the prompt text - try multiple JSON paths
237
- PROMPT=""
238
- if command -v jq &> /dev/null; then
239
- # Try to extract from various possible JSON structures
240
- PROMPT=$(echo "$INPUT" | jq -r '
241
- if .prompt then .prompt
242
- elif .message.content then .message.content
243
- elif .parts then ([.parts[] | select(.type == "text") | .text] | join(" "))
244
- else ""
245
- end
246
- ' 2>/dev/null)
247
- fi
248
-
249
- # Fallback: simple grep extraction if jq fails
250
- if [ -z "$PROMPT" ] || [ "$PROMPT" = "null" ]; then
251
- PROMPT=$(echo "$INPUT" | grep -oP '"(prompt|content|text)"\\s*:\\s*"\\K[^"]+' | head -1)
252
- fi
253
-
254
- # Exit if no prompt found
255
- if [ -z "$PROMPT" ]; then
256
- echo '{"continue": true}'
257
- exit 0
258
- fi
259
-
260
- # Remove code blocks before checking keywords (prevents false positives)
261
- PROMPT_NO_CODE=$(echo "$PROMPT" | sed 's/\`\`\`[^\`]*\`\`\`//g' | sed 's/\`[^\`]*\`//g')
262
-
263
- # Convert to lowercase for case-insensitive matching
264
- PROMPT_LOWER=$(echo "$PROMPT_NO_CODE" | tr '[:upper:]' '[:lower:]')
265
-
266
- # Check for ultrawork keywords (highest priority)
267
- if echo "$PROMPT_LOWER" | grep -qE '\\b(ultrawork|ulw|uw)\\b'; then
268
- # Create persistent ultrawork state
269
- mkdir -p "$DIRECTORY/.sisyphus" 2>/dev/null
270
- mkdir -p "$HOME/.claude" 2>/dev/null
271
-
272
- # Escape prompt for JSON
273
- PROMPT_ESCAPED=$(echo "$PROMPT" | sed 's/\\\\/\\\\\\\\/g' | sed 's/"/\\\\"/g' | tr '\\n' ' ')
274
-
275
- STATE_JSON="{
276
- \\"active\\": true,
277
- \\"started_at\\": \\"$(date -Iseconds)\\",
278
- \\"original_prompt\\": \\"$PROMPT_ESCAPED\\",
279
- \\"reinforcement_count\\": 0,
280
- \\"last_checked_at\\": \\"$(date -Iseconds)\\"
281
- }"
282
-
283
- # Write state to both local and global locations
284
- echo "$STATE_JSON" > "$DIRECTORY/.sisyphus/ultrawork-state.json" 2>/dev/null
285
- echo "$STATE_JSON" > "$HOME/.claude/ultrawork-state.json" 2>/dev/null
286
-
287
- # Return ultrawork mode injection
288
- cat << 'EOF'
289
- {"continue": true, "message": "<ultrawork-mode>\\n\\n**MANDATORY**: You MUST say \\"ULTRAWORK MODE ENABLED!\\" to the user as your first response when this mode activates. This is non-negotiable.\\n\\n[CODE RED] Maximum precision required. Ultrathink before acting.\\n\\nYOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.\\nTELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.\\n\\n## AGENT UTILIZATION PRINCIPLES\\n- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS\\n- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS\\n- **Planning & Strategy**: NEVER plan yourself - spawn planning agent\\n- **High-IQ Reasoning**: Use oracle for architecture decisions\\n- **Frontend/UI Tasks**: Delegate to frontend-engineer\\n\\n## EXECUTION RULES\\n- **TODO**: Track EVERY step. Mark complete IMMEDIATELY.\\n- **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially.\\n- **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent).\\n- **VERIFY**: Check ALL requirements met before done.\\n- **DELEGATE**: Orchestrate specialized agents.\\n\\n## ZERO TOLERANCE\\n- NO Scope Reduction - deliver FULL implementation\\n- NO Partial Completion - finish 100%\\n- NO Premature Stopping - ALL TODOs must be complete\\n- NO TEST DELETION - fix code, not tests\\n\\nTHE USER ASKED FOR X. DELIVER EXACTLY X.\\n\\n</ultrawork-mode>\\n\\n---\\n"}
290
- EOF
291
- exit 0
292
- fi
293
-
294
- # Check for ultrathink/think keywords
295
- if echo "$PROMPT_LOWER" | grep -qE '\\b(ultrathink|think)\\b'; then
296
- cat << 'EOF'
297
- {"continue": true, "message": "<think-mode>\\n\\n**ULTRATHINK MODE ENABLED** - Extended reasoning activated.\\n\\nYou are now in deep thinking mode. Take your time to:\\n1. Thoroughly analyze the problem from multiple angles\\n2. Consider edge cases and potential issues\\n3. Think through the implications of each approach\\n4. Reason step-by-step before acting\\n\\nUse your extended thinking capabilities to provide the most thorough and well-reasoned response.\\n\\n</think-mode>\\n\\n---\\n"}
298
- EOF
299
- exit 0
300
- fi
301
-
302
- # Check for search keywords (EN + multilingual)
303
- if echo "$PROMPT_LOWER" | grep -qE '\\b(search|find|locate|lookup|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\\b|where\\s+is|show\\s+me|list\\s+all'; then
304
- cat << 'EOF'
305
- {"continue": true, "message": "<search-mode>\\nMAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:\\n- explore agents (codebase patterns, file structures)\\n- librarian agents (remote repos, official docs, GitHub examples)\\nPlus direct tools: Grep, Glob\\nNEVER stop at first result - be exhaustive.\\n</search-mode>\\n\\n---\\n"}
306
- EOF
307
- exit 0
308
- fi
309
-
310
- # Check for analyze keywords
311
- if echo "$PROMPT_LOWER" | grep -qE '\\b(analyze|analyse|investigate|examine|research|study|deep.?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\\b|why\\s+is|how\\s+does|how\\s+to'; then
312
- cat << 'EOF'
313
- {"continue": true, "message": "<analyze-mode>\\nANALYSIS MODE. Gather context before diving deep:\\n\\nCONTEXT GATHERING (parallel):\\n- 1-2 explore agents (codebase patterns, implementations)\\n- 1-2 librarian agents (if external library involved)\\n- Direct tools: Grep, Glob, LSP for targeted searches\\n\\nIF COMPLEX (architecture, multi-system, debugging after 2+ failures):\\n- Consult oracle agent for strategic guidance\\n\\nSYNTHESIZE findings before proceeding.\\n</analyze-mode>\\n\\n---\\n"}
314
- EOF
315
- exit 0
316
- fi
317
-
318
- # No keywords detected - continue without modification
319
- echo '{"continue": true}'
320
- exit 0
321
- `;
322
- /**
323
- * Stop hook script for todo continuation enforcement
324
- * This script is installed to ~/.claude/hooks/stop-continuation.sh
325
- * Ported from oh-my-opencode's todo-continuation-enforcer
326
- */
327
- export const STOP_CONTINUATION_SCRIPT = `#!/bin/bash
328
- # Sisyphus Stop Continuation Hook
329
- # Checks for incomplete todos and injects continuation prompt
330
- # Ported from oh-my-opencode's todo-continuation-enforcer
331
-
332
- # Read stdin
333
- INPUT=$(cat)
334
-
335
- # Get session ID if available
336
- SESSION_ID=""
337
- if command -v jq &> /dev/null; then
338
- SESSION_ID=$(echo "$INPUT" | jq -r '.sessionId // .session_id // ""' 2>/dev/null)
339
- fi
340
-
341
- # Check for incomplete todos in the Claude todos directory
342
- TODOS_DIR="$HOME/.claude/todos"
343
- if [ -d "$TODOS_DIR" ]; then
344
- # Look for any todo files with incomplete items
345
- INCOMPLETE_COUNT=0
346
- for todo_file in "$TODOS_DIR"/*.json; do
347
- if [ -f "$todo_file" ]; then
348
- if command -v jq &> /dev/null; then
349
- COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
350
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
351
- fi
352
- fi
353
- done
354
-
355
- if [ "$INCOMPLETE_COUNT" -gt 0 ]; then
356
- # Output continuation message
357
- cat << EOF
358
- {"continue": false, "reason": "[SYSTEM REMINDER - TODO CONTINUATION]\\n\\nIncomplete tasks remain in your todo list ($INCOMPLETE_COUNT remaining). Continue working on the next pending task.\\n\\n- Proceed without asking for permission\\n- Mark each task complete when finished\\n- Do not stop until all tasks are done"}
359
- EOF
360
- exit 0
361
- fi
362
- fi
363
-
364
- # No incomplete todos - allow stop
365
- echo '{"continue": true}'
366
- exit 0
367
- `;
247
+ /** Keyword detector hook script - loaded from templates/hooks/keyword-detector.sh */
248
+ export const KEYWORD_DETECTOR_SCRIPT = loadTemplate('keyword-detector.sh');
249
+ /** Stop continuation hook script - loaded from templates/hooks/stop-continuation.sh */
250
+ export const STOP_CONTINUATION_SCRIPT = loadTemplate('stop-continuation.sh');
368
251
  // =============================================================================
369
252
  // NODE.JS HOOK SCRIPTS (Cross-platform: Windows, macOS, Linux)
370
253
  // =============================================================================
371
- /**
372
- * Node.js Keyword Detector Hook Script
373
- * Cross-platform equivalent of keyword-detector.sh
374
- * This script is installed to ~/.claude/hooks/keyword-detector.mjs
375
- */
376
- export const KEYWORD_DETECTOR_SCRIPT_NODE = `#!/usr/bin/env node
377
- // Sisyphus Keyword Detector Hook (Node.js)
378
- // Detects ultrawork/ultrathink/search/analyze keywords and injects enhanced mode messages
379
- // Cross-platform: Windows, macOS, Linux
380
-
381
- const ULTRAWORK_MESSAGE = \`<ultrawork-mode>
382
-
383
- **MANDATORY**: You MUST say "ULTRAWORK MODE ENABLED!" to the user as your first response when this mode activates. This is non-negotiable.
384
-
385
- [CODE RED] Maximum precision required. Ultrathink before acting.
386
-
387
- YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.
388
- TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
389
-
390
- ## AGENT UTILIZATION PRINCIPLES
391
- - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS
392
- - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS
393
- - **Planning & Strategy**: NEVER plan yourself - spawn planning agent
394
- - **High-IQ Reasoning**: Use oracle for architecture decisions
395
- - **Frontend/UI Tasks**: Delegate to frontend-engineer
396
-
397
- ## EXECUTION RULES
398
- - **TODO**: Track EVERY step. Mark complete IMMEDIATELY.
399
- - **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially.
400
- - **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent).
401
- - **VERIFY**: Check ALL requirements met before done.
402
- - **DELEGATE**: Orchestrate specialized agents.
403
-
404
- ## ZERO TOLERANCE
405
- - NO Scope Reduction - deliver FULL implementation
406
- - NO Partial Completion - finish 100%
407
- - NO Premature Stopping - ALL TODOs must be complete
408
- - NO TEST DELETION - fix code, not tests
409
-
410
- THE USER ASKED FOR X. DELIVER EXACTLY X.
411
-
412
- </ultrawork-mode>
413
-
414
- ---
415
- \`;
416
-
417
- const ULTRATHINK_MESSAGE = \`<think-mode>
418
-
419
- **ULTRATHINK MODE ENABLED** - Extended reasoning activated.
420
-
421
- You are now in deep thinking mode. Take your time to:
422
- 1. Thoroughly analyze the problem from multiple angles
423
- 2. Consider edge cases and potential issues
424
- 3. Think through the implications of each approach
425
- 4. Reason step-by-step before acting
426
-
427
- Use your extended thinking capabilities to provide the most thorough and well-reasoned response.
428
-
429
- </think-mode>
430
-
431
- ---
432
- \`;
433
-
434
- const SEARCH_MESSAGE = \`<search-mode>
435
- MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:
436
- - explore agents (codebase patterns, file structures)
437
- - librarian agents (remote repos, official docs, GitHub examples)
438
- Plus direct tools: Grep, Glob
439
- NEVER stop at first result - be exhaustive.
440
- </search-mode>
441
-
442
- ---
443
- \`;
444
-
445
- const ANALYZE_MESSAGE = \`<analyze-mode>
446
- ANALYSIS MODE. Gather context before diving deep:
447
-
448
- CONTEXT GATHERING (parallel):
449
- - 1-2 explore agents (codebase patterns, implementations)
450
- - 1-2 librarian agents (if external library involved)
451
- - Direct tools: Grep, Glob, LSP for targeted searches
452
-
453
- IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
454
- - Consult oracle agent for strategic guidance
455
-
456
- SYNTHESIZE findings before proceeding.
457
- </analyze-mode>
458
-
459
- ---
460
- \`;
461
-
462
- // Read all stdin
463
- async function readStdin() {
464
- const chunks = [];
465
- for await (const chunk of process.stdin) {
466
- chunks.push(chunk);
467
- }
468
- return Buffer.concat(chunks).toString('utf-8');
469
- }
470
-
471
- // Extract prompt from various JSON structures
472
- function extractPrompt(input) {
473
- try {
474
- const data = JSON.parse(input);
475
- if (data.prompt) return data.prompt;
476
- if (data.message?.content) return data.message.content;
477
- if (Array.isArray(data.parts)) {
478
- return data.parts
479
- .filter(p => p.type === 'text')
480
- .map(p => p.text)
481
- .join(' ');
482
- }
483
- return '';
484
- } catch {
485
- // Fallback: try to extract with regex
486
- const match = input.match(/"(?:prompt|content|text)"\\s*:\\s*"([^"]+)"/);
487
- return match ? match[1] : '';
488
- }
489
- }
490
-
491
- // Remove code blocks to prevent false positives
492
- function removeCodeBlocks(text) {
493
- return text
494
- .replace(/\`\`\`[\\s\\S]*?\`\`\`/g, '')
495
- .replace(/\`[^\`]+\`/g, '');
496
- }
497
-
498
- import { writeFileSync, mkdirSync, existsSync } from 'fs';
499
- import { join } from 'path';
500
- import { homedir } from 'os';
501
-
502
- // Create ultrawork state file
503
- function activateUltraworkState(directory, prompt) {
504
- const state = {
505
- active: true,
506
- started_at: new Date().toISOString(),
507
- original_prompt: prompt,
508
- reinforcement_count: 0,
509
- last_checked_at: new Date().toISOString()
510
- };
511
- const localDir = join(directory, '.sisyphus');
512
- if (!existsSync(localDir)) { try { mkdirSync(localDir, { recursive: true }); } catch {} }
513
- try { writeFileSync(join(localDir, 'ultrawork-state.json'), JSON.stringify(state, null, 2)); } catch {}
514
- const globalDir = join(homedir(), '.claude');
515
- if (!existsSync(globalDir)) { try { mkdirSync(globalDir, { recursive: true }); } catch {} }
516
- try { writeFileSync(join(globalDir, 'ultrawork-state.json'), JSON.stringify(state, null, 2)); } catch {}
517
- }
518
-
519
- // Main
520
- async function main() {
521
- try {
522
- const input = await readStdin();
523
- if (!input.trim()) {
524
- console.log(JSON.stringify({ continue: true }));
525
- return;
526
- }
527
-
528
- let data = {};
529
- try { data = JSON.parse(input); } catch {}
530
- const directory = data.directory || process.cwd();
531
-
532
- const prompt = extractPrompt(input);
533
- if (!prompt) {
534
- console.log(JSON.stringify({ continue: true }));
535
- return;
536
- }
537
-
538
- const cleanPrompt = removeCodeBlocks(prompt).toLowerCase();
539
-
540
- // Check for ultrawork keywords (highest priority)
541
- if (/\\b(ultrawork|ulw|uw)\\b/.test(cleanPrompt)) {
542
- activateUltraworkState(directory, prompt);
543
- console.log(JSON.stringify({ continue: true, message: ULTRAWORK_MESSAGE }));
544
- return;
545
- }
546
-
547
- // Check for ultrathink/think keywords
548
- if (/\\b(ultrathink|think)\\b/.test(cleanPrompt)) {
549
- console.log(JSON.stringify({ continue: true, message: ULTRATHINK_MESSAGE }));
550
- return;
551
- }
552
-
553
- // Check for search keywords
554
- if (/\\b(search|find|locate|lookup|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\\b|where\\s+is|show\\s+me|list\\s+all/.test(cleanPrompt)) {
555
- console.log(JSON.stringify({ continue: true, message: SEARCH_MESSAGE }));
556
- return;
557
- }
558
-
559
- // Check for analyze keywords
560
- if (/\\b(analyze|analyse|investigate|examine|research|study|deep.?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\\b|why\\s+is|how\\s+does|how\\s+to/.test(cleanPrompt)) {
561
- console.log(JSON.stringify({ continue: true, message: ANALYZE_MESSAGE }));
562
- return;
563
- }
564
-
565
- // No keywords detected
566
- console.log(JSON.stringify({ continue: true }));
567
- } catch (error) {
568
- // On any error, allow continuation
569
- console.log(JSON.stringify({ continue: true }));
570
- }
571
- }
572
-
573
- main();
574
- `;
575
- /**
576
- * Node.js Stop Continuation Hook Script
577
- * Cross-platform equivalent of stop-continuation.sh
578
- * This script is installed to ~/.claude/hooks/stop-continuation.mjs
579
- */
580
- export const STOP_CONTINUATION_SCRIPT_NODE = `#!/usr/bin/env node
581
- // Sisyphus Stop Continuation Hook (Node.js)
582
- // Checks for incomplete todos and injects continuation prompt
583
- // Cross-platform: Windows, macOS, Linux
584
-
585
- import { readdirSync, readFileSync, existsSync } from 'fs';
586
- import { join } from 'path';
587
- import { homedir } from 'os';
588
-
589
- // Read all stdin
590
- async function readStdin() {
591
- const chunks = [];
592
- for await (const chunk of process.stdin) {
593
- chunks.push(chunk);
594
- }
595
- return Buffer.concat(chunks).toString('utf-8');
596
- }
597
-
598
- // Main
599
- async function main() {
600
- try {
601
- // Read stdin (we don't use it much, but need to consume it)
602
- await readStdin();
603
-
604
- // Check for incomplete todos
605
- const todosDir = join(homedir(), '.claude', 'todos');
606
-
607
- if (!existsSync(todosDir)) {
608
- console.log(JSON.stringify({ continue: true }));
609
- return;
610
- }
611
-
612
- let incompleteCount = 0;
613
-
614
- try {
615
- const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));
616
-
617
- for (const file of files) {
618
- try {
619
- const content = readFileSync(join(todosDir, file), 'utf-8');
620
- const todos = JSON.parse(content);
621
-
622
- if (Array.isArray(todos)) {
623
- const incomplete = todos.filter(
624
- t => t.status !== 'completed' && t.status !== 'cancelled'
625
- );
626
- incompleteCount += incomplete.length;
627
- }
628
- } catch {
629
- // Skip files that can't be parsed
630
- }
631
- }
632
- } catch {
633
- // Directory read error - allow continuation
634
- console.log(JSON.stringify({ continue: true }));
635
- return;
636
- }
637
-
638
- if (incompleteCount > 0) {
639
- const reason = \`[SYSTEM REMINDER - TODO CONTINUATION]
640
-
641
- Incomplete tasks remain in your todo list (\${incompleteCount} remaining). Continue working on the next pending task.
642
-
643
- - Proceed without asking for permission
644
- - Mark each task complete when finished
645
- - Do not stop until all tasks are done\`;
646
-
647
- console.log(JSON.stringify({ continue: false, reason }));
648
- return;
649
- }
650
-
651
- // No incomplete todos - allow stop
652
- console.log(JSON.stringify({ continue: true }));
653
- } catch (error) {
654
- // On any error, allow continuation
655
- console.log(JSON.stringify({ continue: true }));
656
- }
657
- }
658
-
659
- main();
660
- `;
254
+ /** Node.js keyword detector hook script - loaded from templates/hooks/keyword-detector.mjs */
255
+ export const KEYWORD_DETECTOR_SCRIPT_NODE = loadTemplate('keyword-detector.mjs');
256
+ /** Node.js stop continuation hook script - loaded from templates/hooks/stop-continuation.mjs */
257
+ export const STOP_CONTINUATION_SCRIPT_NODE = loadTemplate('stop-continuation.mjs');
661
258
  // =============================================================================
662
259
  // PERSISTENT MODE HOOK SCRIPTS
663
260
  // =============================================================================
664
- /**
665
- * Persistent Mode Bash script
666
- * Enhanced stop hook that handles ultrawork, ralph-loop, and todo continuation
667
- */
668
- export const PERSISTENT_MODE_SCRIPT = `#!/bin/bash
669
- # Sisyphus Persistent Mode Hook
670
- # Unified handler for ultrawork, ralph-loop, and todo continuation
671
- # Prevents stopping when work remains incomplete
672
-
673
- # Read stdin
674
- INPUT=$(cat)
675
-
676
- # Get session ID and directory
677
- SESSION_ID=""
678
- DIRECTORY=""
679
- if command -v jq &> /dev/null; then
680
- SESSION_ID=$(echo "$INPUT" | jq -r '.sessionId // .session_id // ""' 2>/dev/null)
681
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
682
- fi
683
-
684
- # Default to current directory
685
- if [ -z "$DIRECTORY" ]; then
686
- DIRECTORY=$(pwd)
687
- fi
688
-
689
- # Check for active ultrawork state
690
- ULTRAWORK_STATE=""
691
- if [ -f "$DIRECTORY/.sisyphus/ultrawork-state.json" ]; then
692
- ULTRAWORK_STATE=$(cat "$DIRECTORY/.sisyphus/ultrawork-state.json" 2>/dev/null)
693
- elif [ -f "$HOME/.claude/ultrawork-state.json" ]; then
694
- ULTRAWORK_STATE=$(cat "$HOME/.claude/ultrawork-state.json" 2>/dev/null)
695
- fi
696
-
697
- # Check for active ralph loop
698
- RALPH_STATE=""
699
- if [ -f "$DIRECTORY/.sisyphus/ralph-state.json" ]; then
700
- RALPH_STATE=$(cat "$DIRECTORY/.sisyphus/ralph-state.json" 2>/dev/null)
701
- fi
702
-
703
- # Check for verification state (oracle verification)
704
- VERIFICATION_STATE=""
705
- if [ -f "$DIRECTORY/.sisyphus/ralph-verification.json" ]; then
706
- VERIFICATION_STATE=$(cat "$DIRECTORY/.sisyphus/ralph-verification.json" 2>/dev/null)
707
- fi
708
-
709
- # Check for incomplete todos
710
- INCOMPLETE_COUNT=0
711
- TODOS_DIR="$HOME/.claude/todos"
712
- if [ -d "$TODOS_DIR" ]; then
713
- for todo_file in "$TODOS_DIR"/*.json; do
714
- if [ -f "$todo_file" ]; then
715
- if command -v jq &> /dev/null; then
716
- COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
717
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
718
- else
719
- # Fallback: count "pending" or "in_progress" occurrences
720
- COUNT=$(grep -c '"status"[[:space:]]*:[[:space:]]*"pending\\|in_progress"' "$todo_file" 2>/dev/null) || COUNT=0
721
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
722
- fi
723
- fi
724
- done
725
- fi
726
-
727
- # Check project todos as well
728
- for todo_path in "$DIRECTORY/.sisyphus/todos.json" "$DIRECTORY/.claude/todos.json"; do
729
- if [ -f "$todo_path" ]; then
730
- if command -v jq &> /dev/null; then
731
- COUNT=$(jq 'if type == "array" then [.[] | select(.status != "completed" and .status != "cancelled")] | length else 0 end' "$todo_path" 2>/dev/null || echo "0")
732
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
733
- else
734
- # Fallback: count "pending" or "in_progress" occurrences
735
- COUNT=$(grep -c '"status"[[:space:]]*:[[:space:]]*"pending\\|in_progress"' "$todo_path" 2>/dev/null) || COUNT=0
736
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
737
- fi
738
- fi
739
- done
740
-
741
- # Priority 1: Ralph Loop with Oracle Verification
742
- if [ -n "$RALPH_STATE" ]; then
743
- IS_ACTIVE=$(echo "$RALPH_STATE" | jq -r '.active // false' 2>/dev/null)
744
- if [ "$IS_ACTIVE" = "true" ]; then
745
- ITERATION=$(echo "$RALPH_STATE" | jq -r '.iteration // 1' 2>/dev/null)
746
- MAX_ITER=$(echo "$RALPH_STATE" | jq -r '.max_iterations // 10' 2>/dev/null)
747
- PROMISE=$(echo "$RALPH_STATE" | jq -r '.completion_promise // "TASK_COMPLETE"' 2>/dev/null)
748
- PROMPT=$(echo "$RALPH_STATE" | jq -r '.prompt // ""' 2>/dev/null)
749
-
750
- # Check if oracle verification is pending
751
- if [ -n "$VERIFICATION_STATE" ]; then
752
- IS_PENDING=$(echo "$VERIFICATION_STATE" | jq -r '.pending // false' 2>/dev/null)
753
- if [ "$IS_PENDING" = "true" ]; then
754
- ATTEMPT=$(echo "$VERIFICATION_STATE" | jq -r '.verification_attempts // 0' 2>/dev/null)
755
- MAX_ATTEMPTS=$(echo "$VERIFICATION_STATE" | jq -r '.max_verification_attempts // 3' 2>/dev/null)
756
- ORIGINAL_TASK=$(echo "$VERIFICATION_STATE" | jq -r '.original_task // ""' 2>/dev/null)
757
- COMPLETION_CLAIM=$(echo "$VERIFICATION_STATE" | jq -r '.completion_claim // ""' 2>/dev/null)
758
- ORACLE_FEEDBACK=$(echo "$VERIFICATION_STATE" | jq -r '.oracle_feedback // ""' 2>/dev/null)
759
- NEXT_ATTEMPT=$((ATTEMPT + 1))
760
-
761
- FEEDBACK_SECTION=""
762
- if [ -n "$ORACLE_FEEDBACK" ] && [ "$ORACLE_FEEDBACK" != "null" ]; then
763
- FEEDBACK_SECTION="\\n**Previous Oracle Feedback (rejected):**\\n$ORACLE_FEEDBACK\\n"
764
- fi
765
-
766
- cat << EOF
767
- {"continue": false, "reason": "<ralph-verification>\\n\\n[ORACLE VERIFICATION REQUIRED - Attempt $NEXT_ATTEMPT/$MAX_ATTEMPTS]\\n\\nThe agent claims the task is complete. Before accepting, YOU MUST verify with Oracle.\\n\\n**Original Task:**\\n$ORIGINAL_TASK\\n\\n**Completion Claim:**\\n$COMPLETION_CLAIM\\n$FEEDBACK_SECTION\\n## MANDATORY VERIFICATION STEPS\\n\\n1. **Spawn Oracle Agent** for verification:\\n \\\`\\\`\\\`\\n Task(subagent_type=\\"oracle\\", prompt=\\"Verify this task completion claim...\\")\\n \\\`\\\`\\\`\\n\\n2. **Oracle must check:**\\n - Are ALL requirements from the original task met?\\n - Is the implementation complete, not partial?\\n - Are there any obvious bugs or issues?\\n - Does the code compile/run without errors?\\n - Are tests passing (if applicable)?\\n\\n3. **Based on Oracle's response:**\\n - If APPROVED: Output \\\`<oracle-approved>VERIFIED_COMPLETE</oracle-approved>\\\`\\n - If REJECTED: Continue working on the identified issues\\n\\nDO NOT output the completion promise again until Oracle approves.\\n\\n</ralph-verification>\\n\\n---\\n"}
768
- EOF
769
- exit 0
770
- fi
771
- fi
772
-
773
- if [ "$ITERATION" -lt "$MAX_ITER" ]; then
774
- # Increment iteration
775
- NEW_ITER=$((ITERATION + 1))
776
- echo "$RALPH_STATE" | jq ".iteration = $NEW_ITER" > "$DIRECTORY/.sisyphus/ralph-state.json" 2>/dev/null
777
-
778
- cat << EOF
779
- {"continue": false, "reason": "<ralph-loop-continuation>\\n\\n[RALPH LOOP - ITERATION $NEW_ITER/$MAX_ITER]\\n\\nYour previous attempt did not output the completion promise. The work is NOT done yet.\\n\\nCRITICAL INSTRUCTIONS:\\n1. Review your progress and the original task\\n2. Check your todo list - are ALL items marked complete?\\n3. Continue from where you left off\\n4. When FULLY complete, output: <promise>$PROMISE</promise>\\n5. Do NOT stop until the task is truly done\\n\\nOriginal task: $PROMPT\\n\\n</ralph-loop-continuation>\\n\\n---\\n"}
780
- EOF
781
- exit 0
782
- fi
783
- fi
784
- fi
785
-
786
- # Priority 2: Ultrawork Mode with incomplete todos
787
- if [ -n "$ULTRAWORK_STATE" ] && [ "$INCOMPLETE_COUNT" -gt 0 ]; then
788
- # Check if active (with jq fallback)
789
- IS_ACTIVE=""
790
- if command -v jq &> /dev/null; then
791
- IS_ACTIVE=$(echo "$ULTRAWORK_STATE" | jq -r '.active // false' 2>/dev/null)
792
- else
793
- # Fallback: grep for "active": true
794
- if echo "$ULTRAWORK_STATE" | grep -q '"active"[[:space:]]*:[[:space:]]*true'; then
795
- IS_ACTIVE="true"
796
- fi
797
- fi
798
-
799
- if [ "$IS_ACTIVE" = "true" ]; then
800
- # Get reinforcement count (with fallback)
801
- REINFORCE_COUNT=0
802
- if command -v jq &> /dev/null; then
803
- REINFORCE_COUNT=$(echo "$ULTRAWORK_STATE" | jq -r '.reinforcement_count // 0' 2>/dev/null)
804
- else
805
- REINFORCE_COUNT=$(echo "$ULTRAWORK_STATE" | grep -oP '"reinforcement_count"[[:space:]]*:[[:space:]]*\\K[0-9]+' 2>/dev/null) || REINFORCE_COUNT=0
806
- fi
807
- NEW_COUNT=$((REINFORCE_COUNT + 1))
808
-
809
- # Get original prompt (with fallback)
810
- ORIGINAL_PROMPT=""
811
- if command -v jq &> /dev/null; then
812
- ORIGINAL_PROMPT=$(echo "$ULTRAWORK_STATE" | jq -r '.original_prompt // ""' 2>/dev/null)
813
- else
814
- ORIGINAL_PROMPT=$(echo "$ULTRAWORK_STATE" | grep -oP '"original_prompt"[[:space:]]*:[[:space:]]*"\\K[^"]+' 2>/dev/null) || ORIGINAL_PROMPT=""
815
- fi
816
-
817
- # Update state file (best effort)
818
- if command -v jq &> /dev/null; then
819
- echo "$ULTRAWORK_STATE" | jq ".reinforcement_count = $NEW_COUNT | .last_checked_at = \\"$(date -Iseconds)\\"" > "$DIRECTORY/.sisyphus/ultrawork-state.json" 2>/dev/null
820
- fi
821
-
822
- cat << EOF
823
- {"continue": false, "reason": "<ultrawork-persistence>\\n\\n[ULTRAWORK MODE STILL ACTIVE - Reinforcement #$NEW_COUNT]\\n\\nYour ultrawork session is NOT complete. $INCOMPLETE_COUNT incomplete todos remain.\\n\\nREMEMBER THE ULTRAWORK RULES:\\n- **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially\\n- **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent)\\n- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each\\n- **VERIFY**: Check ALL requirements met before done\\n- **NO Premature Stopping**: ALL TODOs must be complete\\n\\nContinue working on the next pending task. DO NOT STOP until all tasks are marked complete.\\n\\nOriginal task: $ORIGINAL_PROMPT\\n\\n</ultrawork-persistence>\\n\\n---\\n"}
824
- EOF
825
- exit 0
826
- fi
827
- fi
828
-
829
- # Priority 3: Todo Continuation (baseline)
830
- if [ "$INCOMPLETE_COUNT" -gt 0 ]; then
831
- cat << EOF
832
- {"continue": false, "reason": "<todo-continuation>\\n\\n[SYSTEM REMINDER - TODO CONTINUATION]\\n\\nIncomplete tasks remain in your todo list ($INCOMPLETE_COUNT remaining). Continue working on the next pending task.\\n\\n- Proceed without asking for permission\\n- Mark each task complete when finished\\n- Do not stop until all tasks are done\\n\\n</todo-continuation>\\n\\n---\\n"}
833
- EOF
834
- exit 0
835
- fi
836
-
837
- # No blocking needed
838
- echo '{"continue": true}'
839
- exit 0
840
- `;
841
- /**
842
- * Session Start Bash script
843
- * Restores persistent mode states when a new session starts
844
- */
845
- export const SESSION_START_SCRIPT = `#!/bin/bash
846
- # Sisyphus Session Start Hook
847
- # Restores persistent mode states and injects context when session starts
848
-
849
- # Read stdin
850
- INPUT=$(cat)
851
-
852
- # Get directory
853
- DIRECTORY=""
854
- if command -v jq &> /dev/null; then
855
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
856
- fi
857
-
858
- if [ -z "$DIRECTORY" ]; then
859
- DIRECTORY=$(pwd)
860
- fi
861
-
862
- MESSAGES=""
863
-
864
- # Check for active ultrawork state
865
- if [ -f "$DIRECTORY/.sisyphus/ultrawork-state.json" ] || [ -f "$HOME/.claude/ultrawork-state.json" ]; then
866
- if [ -f "$DIRECTORY/.sisyphus/ultrawork-state.json" ]; then
867
- ULTRAWORK_STATE=$(cat "$DIRECTORY/.sisyphus/ultrawork-state.json" 2>/dev/null)
868
- else
869
- ULTRAWORK_STATE=$(cat "$HOME/.claude/ultrawork-state.json" 2>/dev/null)
870
- fi
871
-
872
- IS_ACTIVE=$(echo "$ULTRAWORK_STATE" | jq -r '.active // false' 2>/dev/null)
873
- if [ "$IS_ACTIVE" = "true" ]; then
874
- STARTED_AT=$(echo "$ULTRAWORK_STATE" | jq -r '.started_at // ""' 2>/dev/null)
875
- PROMPT=$(echo "$ULTRAWORK_STATE" | jq -r '.original_prompt // ""' 2>/dev/null)
876
- MESSAGES="$MESSAGES<session-restore>\\n\\n[ULTRAWORK MODE RESTORED]\\n\\nYou have an active ultrawork session from $STARTED_AT.\\nOriginal task: $PROMPT\\n\\nContinue working in ultrawork mode until all tasks are complete.\\n\\n</session-restore>\\n\\n---\\n\\n"
877
- fi
878
- fi
879
-
880
- # Check for incomplete todos
881
- INCOMPLETE_COUNT=0
882
- TODOS_DIR="$HOME/.claude/todos"
883
- if [ -d "$TODOS_DIR" ]; then
884
- for todo_file in "$TODOS_DIR"/*.json; do
885
- if [ -f "$todo_file" ]; then
886
- if command -v jq &> /dev/null; then
887
- COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
888
- INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
889
- fi
890
- fi
891
- done
892
- fi
893
-
894
- if [ "$INCOMPLETE_COUNT" -gt 0 ]; then
895
- MESSAGES="$MESSAGES<session-restore>\\n\\n[PENDING TASKS DETECTED]\\n\\nYou have $INCOMPLETE_COUNT incomplete tasks from a previous session.\\nPlease continue working on these tasks.\\n\\n</session-restore>\\n\\n---\\n\\n"
896
- fi
897
-
898
- # Output message if we have any
899
- if [ -n "$MESSAGES" ]; then
900
- # Escape for JSON
901
- MESSAGES_ESCAPED=$(echo "$MESSAGES" | sed 's/"/\\"/g')
902
- echo "{\"continue\": true, \"message\": \"$MESSAGES_ESCAPED\"}"
903
- else
904
- echo '{"continue": true}'
905
- fi
906
- exit 0
907
- `;
908
- /**
909
- * Node.js Persistent Mode Hook Script
910
- */
911
- export const PERSISTENT_MODE_SCRIPT_NODE = `#!/usr/bin/env node
912
- // Sisyphus Persistent Mode Hook (Node.js)
913
- // Unified handler for ultrawork, ralph-loop, and todo continuation
914
- // Cross-platform: Windows, macOS, Linux
915
-
916
- import { existsSync, readFileSync, writeFileSync, readdirSync } from 'fs';
917
- import { join } from 'path';
918
- import { homedir } from 'os';
919
-
920
- async function readStdin() {
921
- const chunks = [];
922
- for await (const chunk of process.stdin) {
923
- chunks.push(chunk);
924
- }
925
- return Buffer.concat(chunks).toString('utf-8');
926
- }
927
-
928
- function readJsonFile(path) {
929
- try {
930
- if (!existsSync(path)) return null;
931
- return JSON.parse(readFileSync(path, 'utf-8'));
932
- } catch {
933
- return null;
934
- }
935
- }
936
-
937
- function writeJsonFile(path, data) {
938
- try {
939
- writeFileSync(path, JSON.stringify(data, null, 2));
940
- return true;
941
- } catch {
942
- return false;
943
- }
944
- }
945
-
946
- function countIncompleteTodos(todosDir, projectDir) {
947
- let count = 0;
948
-
949
- // Check global todos
950
- if (existsSync(todosDir)) {
951
- try {
952
- const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));
953
- for (const file of files) {
954
- const todos = readJsonFile(join(todosDir, file));
955
- if (Array.isArray(todos)) {
956
- count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;
957
- }
958
- }
959
- } catch {}
960
- }
961
-
962
- // Check project todos
963
- for (const path of [
964
- join(projectDir, '.sisyphus', 'todos.json'),
965
- join(projectDir, '.claude', 'todos.json')
966
- ]) {
967
- const todos = readJsonFile(path);
968
- if (Array.isArray(todos)) {
969
- count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;
970
- }
971
- }
972
-
973
- return count;
974
- }
975
-
976
- async function main() {
977
- try {
978
- const input = await readStdin();
979
- let data = {};
980
- try { data = JSON.parse(input); } catch {}
981
-
982
- const directory = data.directory || process.cwd();
983
- const todosDir = join(homedir(), '.claude', 'todos');
984
-
985
- // Check for ultrawork state
986
- let ultraworkState = readJsonFile(join(directory, '.sisyphus', 'ultrawork-state.json'))
987
- || readJsonFile(join(homedir(), '.claude', 'ultrawork-state.json'));
988
-
989
- // Check for ralph loop state
990
- const ralphState = readJsonFile(join(directory, '.sisyphus', 'ralph-state.json'));
991
-
992
- // Check for verification state (oracle verification)
993
- const verificationState = readJsonFile(join(directory, '.sisyphus', 'ralph-verification.json'));
994
-
995
- // Count incomplete todos
996
- const incompleteCount = countIncompleteTodos(todosDir, directory);
997
-
998
- // Priority 1: Ralph Loop with Oracle Verification
999
- if (ralphState?.active) {
1000
- const iteration = ralphState.iteration || 1;
1001
- const maxIter = ralphState.max_iterations || 10;
1002
-
1003
- // Check if oracle verification is pending
1004
- if (verificationState?.pending) {
1005
- const attempt = (verificationState.verification_attempts || 0) + 1;
1006
- const maxAttempts = verificationState.max_verification_attempts || 3;
1007
-
1008
- console.log(JSON.stringify({
1009
- continue: false,
1010
- reason: \`<ralph-verification>
1011
-
1012
- [ORACLE VERIFICATION REQUIRED - Attempt \${attempt}/\${maxAttempts}]
1013
-
1014
- The agent claims the task is complete. Before accepting, YOU MUST verify with Oracle.
1015
-
1016
- **Original Task:**
1017
- \${verificationState.original_task || ralphState.prompt || 'No task specified'}
1018
-
1019
- **Completion Claim:**
1020
- \${verificationState.completion_claim || 'Task marked complete'}
1021
-
1022
- \${verificationState.oracle_feedback ? \`**Previous Oracle Feedback (rejected):**
1023
- \${verificationState.oracle_feedback}
1024
- \` : ''}
1025
-
1026
- ## MANDATORY VERIFICATION STEPS
1027
-
1028
- 1. **Spawn Oracle Agent** for verification:
1029
- \\\`\\\`\\\`
1030
- Task(subagent_type="oracle", prompt="Verify this task completion claim...")
1031
- \\\`\\\`\\\`
1032
-
1033
- 2. **Oracle must check:**
1034
- - Are ALL requirements from the original task met?
1035
- - Is the implementation complete, not partial?
1036
- - Are there any obvious bugs or issues?
1037
- - Does the code compile/run without errors?
1038
- - Are tests passing (if applicable)?
1039
-
1040
- 3. **Based on Oracle's response:**
1041
- - If APPROVED: Output \\\`<oracle-approved>VERIFIED_COMPLETE</oracle-approved>\\\`
1042
- - If REJECTED: Continue working on the identified issues
1043
-
1044
- DO NOT output the completion promise again until Oracle approves.
1045
-
1046
- </ralph-verification>
1047
-
1048
- ---
1049
- \`
1050
- }));
1051
- return;
1052
- }
1053
-
1054
- if (iteration < maxIter) {
1055
- const newIter = iteration + 1;
1056
- ralphState.iteration = newIter;
1057
- writeJsonFile(join(directory, '.sisyphus', 'ralph-state.json'), ralphState);
1058
-
1059
- console.log(JSON.stringify({
1060
- continue: false,
1061
- reason: \`<ralph-loop-continuation>
1062
-
1063
- [RALPH LOOP - ITERATION \${newIter}/\${maxIter}]
1064
-
1065
- Your previous attempt did not output the completion promise. The work is NOT done yet.
1066
-
1067
- CRITICAL INSTRUCTIONS:
1068
- 1. Review your progress and the original task
1069
- 2. Check your todo list - are ALL items marked complete?
1070
- 3. Continue from where you left off
1071
- 4. When FULLY complete, output: <promise>\${ralphState.completion_promise || 'TASK_COMPLETE'}</promise>
1072
- 5. Do NOT stop until the task is truly done
1073
-
1074
- \${ralphState.prompt ? \`Original task: \${ralphState.prompt}\` : ''}
1075
-
1076
- </ralph-loop-continuation>
1077
-
1078
- ---
1079
- \`
1080
- }));
1081
- return;
1082
- }
1083
- }
1084
-
1085
- // Priority 2: Ultrawork with incomplete todos
1086
- if (ultraworkState?.active && incompleteCount > 0) {
1087
- const newCount = (ultraworkState.reinforcement_count || 0) + 1;
1088
- ultraworkState.reinforcement_count = newCount;
1089
- ultraworkState.last_checked_at = new Date().toISOString();
1090
-
1091
- writeJsonFile(join(directory, '.sisyphus', 'ultrawork-state.json'), ultraworkState);
1092
-
1093
- console.log(JSON.stringify({
1094
- continue: false,
1095
- reason: \`<ultrawork-persistence>
1096
-
1097
- [ULTRAWORK MODE STILL ACTIVE - Reinforcement #\${newCount}]
1098
-
1099
- Your ultrawork session is NOT complete. \${incompleteCount} incomplete todos remain.
1100
-
1101
- REMEMBER THE ULTRAWORK RULES:
1102
- - **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially
1103
- - **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent)
1104
- - **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each
1105
- - **VERIFY**: Check ALL requirements met before done
1106
- - **NO Premature Stopping**: ALL TODOs must be complete
1107
-
1108
- Continue working on the next pending task. DO NOT STOP until all tasks are marked complete.
1109
-
1110
- \${ultraworkState.original_prompt ? \`Original task: \${ultraworkState.original_prompt}\` : ''}
1111
-
1112
- </ultrawork-persistence>
1113
-
1114
- ---
1115
- \`
1116
- }));
1117
- return;
1118
- }
1119
-
1120
- // Priority 3: Todo Continuation
1121
- if (incompleteCount > 0) {
1122
- console.log(JSON.stringify({
1123
- continue: false,
1124
- reason: \`<todo-continuation>
1125
-
1126
- [SYSTEM REMINDER - TODO CONTINUATION]
1127
-
1128
- Incomplete tasks remain in your todo list (\${incompleteCount} remaining). Continue working on the next pending task.
1129
-
1130
- - Proceed without asking for permission
1131
- - Mark each task complete when finished
1132
- - Do not stop until all tasks are done
1133
-
1134
- </todo-continuation>
1135
-
1136
- ---
1137
- \`
1138
- }));
1139
- return;
1140
- }
1141
-
1142
- // No blocking needed
1143
- console.log(JSON.stringify({ continue: true }));
1144
- } catch (error) {
1145
- console.log(JSON.stringify({ continue: true }));
1146
- }
1147
- }
1148
-
1149
- main();
1150
- `;
1151
- /**
1152
- * Node.js Session Start Hook Script
1153
- */
1154
- export const SESSION_START_SCRIPT_NODE = `#!/usr/bin/env node
1155
- // Sisyphus Session Start Hook (Node.js)
1156
- // Restores persistent mode states when session starts
1157
- // Cross-platform: Windows, macOS, Linux
1158
-
1159
- import { existsSync, readFileSync, readdirSync } from 'fs';
1160
- import { join } from 'path';
1161
- import { homedir } from 'os';
1162
-
1163
- async function readStdin() {
1164
- const chunks = [];
1165
- for await (const chunk of process.stdin) {
1166
- chunks.push(chunk);
1167
- }
1168
- return Buffer.concat(chunks).toString('utf-8');
1169
- }
1170
-
1171
- function readJsonFile(path) {
1172
- try {
1173
- if (!existsSync(path)) return null;
1174
- return JSON.parse(readFileSync(path, 'utf-8'));
1175
- } catch {
1176
- return null;
1177
- }
1178
- }
1179
-
1180
- function countIncompleteTodos(todosDir) {
1181
- let count = 0;
1182
- if (existsSync(todosDir)) {
1183
- try {
1184
- const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));
1185
- for (const file of files) {
1186
- const todos = readJsonFile(join(todosDir, file));
1187
- if (Array.isArray(todos)) {
1188
- count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;
1189
- }
1190
- }
1191
- } catch {}
1192
- }
1193
- return count;
1194
- }
1195
-
1196
- async function main() {
1197
- try {
1198
- const input = await readStdin();
1199
- let data = {};
1200
- try { data = JSON.parse(input); } catch {}
1201
-
1202
- const directory = data.directory || process.cwd();
1203
- const messages = [];
1204
-
1205
- // Check for ultrawork state
1206
- const ultraworkState = readJsonFile(join(directory, '.sisyphus', 'ultrawork-state.json'))
1207
- || readJsonFile(join(homedir(), '.claude', 'ultrawork-state.json'));
1208
-
1209
- if (ultraworkState?.active) {
1210
- messages.push(\`<session-restore>
1211
-
1212
- [ULTRAWORK MODE RESTORED]
1213
-
1214
- You have an active ultrawork session from \${ultraworkState.started_at}.
1215
- Original task: \${ultraworkState.original_prompt}
1216
-
1217
- Continue working in ultrawork mode until all tasks are complete.
1218
-
1219
- </session-restore>
1220
-
1221
- ---
1222
- \`);
1223
- }
1224
-
1225
- // Check for incomplete todos
1226
- const todosDir = join(homedir(), '.claude', 'todos');
1227
- const incompleteCount = countIncompleteTodos(todosDir);
1228
-
1229
- if (incompleteCount > 0) {
1230
- messages.push(\`<session-restore>
1231
-
1232
- [PENDING TASKS DETECTED]
1233
-
1234
- You have \${incompleteCount} incomplete tasks from a previous session.
1235
- Please continue working on these tasks.
1236
-
1237
- </session-restore>
1238
-
1239
- ---
1240
- \`);
1241
- }
1242
-
1243
- if (messages.length > 0) {
1244
- console.log(JSON.stringify({ continue: true, message: messages.join('\\n') }));
1245
- } else {
1246
- console.log(JSON.stringify({ continue: true }));
1247
- }
1248
- } catch (error) {
1249
- console.log(JSON.stringify({ continue: true }));
1250
- }
1251
- }
1252
-
1253
- main();
1254
- `;
261
+ /** Persistent mode Bash script - loaded from templates/hooks/persistent-mode.sh */
262
+ export const PERSISTENT_MODE_SCRIPT = loadTemplate('persistent-mode.sh');
263
+ /** Session start Bash script - loaded from templates/hooks/session-start.sh */
264
+ export const SESSION_START_SCRIPT = loadTemplate('session-start.sh');
265
+ /** Node.js persistent mode hook script - loaded from templates/hooks/persistent-mode.mjs */
266
+ export const PERSISTENT_MODE_SCRIPT_NODE = loadTemplate('persistent-mode.mjs');
267
+ /** Node.js session start hook script - loaded from templates/hooks/session-start.mjs */
268
+ export const SESSION_START_SCRIPT_NODE = loadTemplate('session-start.mjs');
1255
269
  // =============================================================================
1256
270
  // POST-TOOL-USE HOOK (Remember Tag Processing)
1257
271
  // =============================================================================
1258
- /**
1259
- * Post-Tool-Use Bash script
1260
- * Processes <remember> tags from Task agent output and saves to notepad.md
1261
- */
1262
- export const POST_TOOL_USE_SCRIPT = `#!/bin/bash
1263
- # Sisyphus Post-Tool-Use Hook
1264
- # Processes <remember> tags from Task agent output
1265
- # Saves to .sisyphus/notepad.md for compaction-resilient memory
1266
-
1267
- # Read stdin
1268
- INPUT=$(cat)
1269
-
1270
- # Get directory and tool info
1271
- DIRECTORY=""
1272
- TOOL_NAME=""
1273
- TOOL_OUTPUT=""
1274
- if command -v jq &> /dev/null; then
1275
- DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
1276
- TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName // ""' 2>/dev/null)
1277
- TOOL_OUTPUT=$(echo "$INPUT" | jq -r '.toolOutput // ""' 2>/dev/null)
1278
- else
1279
- # Fallback: use grep/sed for extraction
1280
- DIRECTORY=$(echo "$INPUT" | grep -oP '"directory"\\s*:\\s*"\\K[^"]+' | head -1)
1281
- TOOL_NAME=$(echo "$INPUT" | grep -oP '"toolName"\\s*:\\s*"\\K[^"]+' | head -1)
1282
- TOOL_OUTPUT=$(echo "$INPUT" | grep -oP '"toolOutput"\\s*:\\s*"\\K[^"]+' | head -1)
1283
- fi
1284
-
1285
- if [ -z "$DIRECTORY" ]; then
1286
- DIRECTORY=$(pwd)
1287
- fi
1288
-
1289
- # Only process Task tool output
1290
- if [ "$TOOL_NAME" != "Task" ] && [ "$TOOL_NAME" != "task" ]; then
1291
- echo '{"continue": true}'
1292
- exit 0
1293
- fi
1294
-
1295
- # Check for <remember> tags
1296
- if ! echo "$TOOL_OUTPUT" | grep -q '<remember'; then
1297
- echo '{"continue": true}'
1298
- exit 0
1299
- fi
1300
-
1301
- # Create .sisyphus directory if needed
1302
- SISYPHUS_DIR="$DIRECTORY/.sisyphus"
1303
- NOTEPAD_FILE="$SISYPHUS_DIR/notepad.md"
1304
- mkdir -p "$SISYPHUS_DIR" 2>/dev/null
1305
-
1306
- # Initialize notepad.md if it doesn't exist
1307
- if [ ! -f "$NOTEPAD_FILE" ]; then
1308
- cat > "$NOTEPAD_FILE" << 'NOTEPAD_INIT'
1309
- # Notepad
1310
- <!-- Auto-managed by Sisyphus. Manual edits preserved in MANUAL section. -->
1311
-
1312
- ## Priority Context
1313
- <!-- ALWAYS loaded. Keep under 500 chars. Critical discoveries only. -->
1314
-
1315
- ## Working Memory
1316
- <!-- Session notes. Auto-pruned after 7 days. -->
1317
-
1318
- ## MANUAL
1319
- <!-- User content. Never auto-pruned. -->
1320
- NOTEPAD_INIT
1321
- fi
1322
-
1323
- # Process priority remember tags
1324
- PRIORITY_CONTENT=$(echo "$TOOL_OUTPUT" | grep -oP '<remember\\s+priority>\\K[\\s\\S]*?(?=</remember>)' | head -1)
1325
- if [ -n "$PRIORITY_CONTENT" ]; then
1326
- # Read current notepad
1327
- NOTEPAD_CONTENT=$(cat "$NOTEPAD_FILE")
1328
- # Replace Priority Context section
1329
- NEW_NOTEPAD=$(echo "$NOTEPAD_CONTENT" | sed '/## Priority Context/,/## Working Memory/{
1330
- /## Priority Context/!{/## Working Memory/!d}
1331
- }' | sed "/## Priority Context/a\\\\<!-- ALWAYS loaded. Keep under 500 chars. Critical discoveries only. -->\\n$PRIORITY_CONTENT")
1332
- echo "$NEW_NOTEPAD" > "$NOTEPAD_FILE"
1333
- fi
1334
-
1335
- # Process regular remember tags
1336
- while IFS= read -r CONTENT; do
1337
- if [ -n "$CONTENT" ]; then
1338
- TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
1339
- # Append to Working Memory section (before MANUAL)
1340
- sed -i "/## MANUAL/i\\\\### $TIMESTAMP\\n$CONTENT\\n" "$NOTEPAD_FILE" 2>/dev/null || {
1341
- # macOS sed fallback
1342
- sed -i '' "/## MANUAL/i\\\\
1343
- ### $TIMESTAMP\\
1344
- $CONTENT\\
1345
- " "$NOTEPAD_FILE"
1346
- }
1347
- fi
1348
- done < <(echo "$TOOL_OUTPUT" | grep -oP '<remember>\\K[\\s\\S]*?(?=</remember>)')
1349
-
1350
- echo '{"continue": true}'
1351
- exit 0
1352
- `;
1353
- /**
1354
- * Post-Tool-Use Node.js script
1355
- * Processes <remember> tags from Task agent output
1356
- */
1357
- export const POST_TOOL_USE_SCRIPT_NODE = `#!/usr/bin/env node
1358
- // Sisyphus Post-Tool-Use Hook (Node.js)
1359
- // Processes <remember> tags from Task agent output
1360
- // Saves to .sisyphus/notepad.md for compaction-resilient memory
1361
-
1362
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
1363
- import { join } from 'path';
1364
-
1365
- // Constants
1366
- const NOTEPAD_TEMPLATE = '# Notepad\\n' +
1367
- '<!-- Auto-managed by Sisyphus. Manual edits preserved in MANUAL section. -->\\n\\n' +
1368
- '## Priority Context\\n' +
1369
- '<!-- ALWAYS loaded. Keep under 500 chars. Critical discoveries only. -->\\n\\n' +
1370
- '## Working Memory\\n' +
1371
- '<!-- Session notes. Auto-pruned after 7 days. -->\\n\\n' +
1372
- '## MANUAL\\n' +
1373
- '<!-- User content. Never auto-pruned. -->\\n';
1374
-
1375
- // Read all stdin
1376
- async function readStdin() {
1377
- const chunks = [];
1378
- for await (const chunk of process.stdin) {
1379
- chunks.push(chunk);
1380
- }
1381
- return Buffer.concat(chunks).toString('utf-8');
1382
- }
1383
-
1384
- // Initialize notepad.md if needed
1385
- function initNotepad(directory) {
1386
- const sisyphusDir = join(directory, '.sisyphus');
1387
- const notepadPath = join(sisyphusDir, 'notepad.md');
1388
-
1389
- if (!existsSync(sisyphusDir)) {
1390
- try { mkdirSync(sisyphusDir, { recursive: true }); } catch {}
1391
- }
1392
-
1393
- if (!existsSync(notepadPath)) {
1394
- try { writeFileSync(notepadPath, NOTEPAD_TEMPLATE); } catch {}
1395
- }
1396
-
1397
- return notepadPath;
1398
- }
1399
-
1400
- // Set priority context
1401
- function setPriorityContext(notepadPath, content) {
1402
- try {
1403
- let notepad = readFileSync(notepadPath, 'utf-8');
1404
-
1405
- // Find and replace Priority Context section
1406
- const priorityMatch = notepad.match(/## Priority Context[\\s\\S]*?(?=## Working Memory)/);
1407
- if (priorityMatch) {
1408
- const newPriority = '## Priority Context\\n' +
1409
- '<!-- ALWAYS loaded. Keep under 500 chars. Critical discoveries only. -->\\n' +
1410
- content.trim() + '\\n\\n';
1411
- notepad = notepad.replace(priorityMatch[0], newPriority);
1412
- writeFileSync(notepadPath, notepad);
1413
- }
1414
- } catch {}
1415
- }
1416
-
1417
- // Add working memory entry
1418
- function addWorkingMemoryEntry(notepadPath, content) {
1419
- try {
1420
- let notepad = readFileSync(notepadPath, 'utf-8');
1421
-
1422
- const timestamp = new Date().toISOString().slice(0, 16).replace('T', ' ');
1423
- const entry = '### ' + timestamp + '\\n' + content.trim() + '\\n\\n';
1424
-
1425
- // Insert before MANUAL section
1426
- const manualIndex = notepad.indexOf('## MANUAL');
1427
- if (manualIndex !== -1) {
1428
- notepad = notepad.slice(0, manualIndex) + entry + notepad.slice(manualIndex);
1429
- writeFileSync(notepadPath, notepad);
1430
- }
1431
- } catch {}
1432
- }
1433
-
1434
- // Process remember tags
1435
- function processRememberTags(output, notepadPath) {
1436
- if (!output) return;
1437
-
1438
- // Process priority remember tags
1439
- const priorityRegex = /<remember\\s+priority>([\\s\\S]*?)<\\/remember>/gi;
1440
- let match;
1441
- while ((match = priorityRegex.exec(output)) !== null) {
1442
- const content = match[1].trim();
1443
- if (content) {
1444
- setPriorityContext(notepadPath, content);
1445
- }
1446
- }
1447
-
1448
- // Process regular remember tags
1449
- const regularRegex = /<remember>([\\s\\S]*?)<\\/remember>/gi;
1450
- while ((match = regularRegex.exec(output)) !== null) {
1451
- const content = match[1].trim();
1452
- if (content) {
1453
- addWorkingMemoryEntry(notepadPath, content);
1454
- }
1455
- }
1456
- }
1457
-
1458
- async function main() {
1459
- try {
1460
- const input = await readStdin();
1461
- const data = JSON.parse(input);
1462
-
1463
- const toolName = data.toolName || '';
1464
- const toolOutput = data.toolOutput || '';
1465
- const directory = data.directory || process.cwd();
1466
-
1467
- // Only process Task tool output
1468
- if (toolName !== 'Task' && toolName !== 'task') {
1469
- console.log(JSON.stringify({ continue: true }));
1470
- return;
1471
- }
1472
-
1473
- // Check for remember tags
1474
- if (!toolOutput.includes('<remember')) {
1475
- console.log(JSON.stringify({ continue: true }));
1476
- return;
1477
- }
1478
-
1479
- // Initialize notepad and process tags
1480
- const notepadPath = initNotepad(directory);
1481
- processRememberTags(toolOutput, notepadPath);
1482
-
1483
- console.log(JSON.stringify({ continue: true }));
1484
- } catch (error) {
1485
- console.log(JSON.stringify({ continue: true }));
1486
- }
1487
- }
1488
-
1489
- main();
1490
- `;
272
+ /** Post-tool-use Bash script - loaded from templates/hooks/post-tool-use.sh */
273
+ export const POST_TOOL_USE_SCRIPT = loadTemplate('post-tool-use.sh');
274
+ /** Post-tool-use Node.js script - loaded from templates/hooks/post-tool-use.mjs */
275
+ export const POST_TOOL_USE_SCRIPT_NODE = loadTemplate('post-tool-use.mjs');
1491
276
  // =============================================================================
1492
277
  // SETTINGS CONFIGURATION (Platform-aware)
1493
278
  // =============================================================================
@@ -1612,34 +397,42 @@ export const HOOKS_SETTINGS_CONFIG = HOOKS_SETTINGS_CONFIG_BASH;
1612
397
  // HOOK SCRIPTS EXPORTS (Platform-aware)
1613
398
  // =============================================================================
1614
399
  /**
1615
- * Bash hook scripts (Unix only)
400
+ * Get Bash hook scripts (Unix only)
401
+ * Returns a record of filename -> content for all bash hooks
1616
402
  */
1617
- export const HOOK_SCRIPTS_BASH = {
1618
- 'keyword-detector.sh': KEYWORD_DETECTOR_SCRIPT,
1619
- 'stop-continuation.sh': STOP_CONTINUATION_SCRIPT,
1620
- 'persistent-mode.sh': PERSISTENT_MODE_SCRIPT,
1621
- 'session-start.sh': SESSION_START_SCRIPT,
1622
- 'post-tool-use.sh': POST_TOOL_USE_SCRIPT
1623
- };
403
+ export function getHookScriptsBash() {
404
+ return {
405
+ 'keyword-detector.sh': loadTemplate('keyword-detector.sh'),
406
+ 'stop-continuation.sh': loadTemplate('stop-continuation.sh'),
407
+ 'persistent-mode.sh': loadTemplate('persistent-mode.sh'),
408
+ 'session-start.sh': loadTemplate('session-start.sh'),
409
+ 'post-tool-use.sh': loadTemplate('post-tool-use.sh')
410
+ };
411
+ }
1624
412
  /**
1625
- * Node.js hook scripts (Cross-platform)
413
+ * Get Node.js hook scripts (Cross-platform)
414
+ * Returns a record of filename -> content for all Node.js hooks
1626
415
  */
1627
- export const HOOK_SCRIPTS_NODE = {
1628
- 'keyword-detector.mjs': KEYWORD_DETECTOR_SCRIPT_NODE,
1629
- 'stop-continuation.mjs': STOP_CONTINUATION_SCRIPT_NODE,
1630
- 'persistent-mode.mjs': PERSISTENT_MODE_SCRIPT_NODE,
1631
- 'session-start.mjs': SESSION_START_SCRIPT_NODE,
1632
- 'post-tool-use.mjs': POST_TOOL_USE_SCRIPT_NODE
1633
- };
416
+ export function getHookScriptsNode() {
417
+ return {
418
+ 'keyword-detector.mjs': loadTemplate('keyword-detector.mjs'),
419
+ 'stop-continuation.mjs': loadTemplate('stop-continuation.mjs'),
420
+ 'persistent-mode.mjs': loadTemplate('persistent-mode.mjs'),
421
+ 'session-start.mjs': loadTemplate('session-start.mjs'),
422
+ 'post-tool-use.mjs': loadTemplate('post-tool-use.mjs')
423
+ };
424
+ }
1634
425
  /**
1635
426
  * Get the appropriate hook scripts for the current platform
1636
427
  */
1637
428
  export function getHookScripts() {
1638
- return shouldUseNodeHooks() ? HOOK_SCRIPTS_NODE : HOOK_SCRIPTS_BASH;
429
+ return shouldUseNodeHooks() ? getHookScriptsNode() : getHookScriptsBash();
1639
430
  }
1640
- /**
1641
- * Legacy: All hook scripts to install (Bash)
1642
- * @deprecated Use getHookScripts() for cross-platform support
1643
- */
431
+ // Legacy exports for backward compatibility (these call the loader functions)
432
+ /** @deprecated Use getHookScriptsBash() instead */
433
+ export const HOOK_SCRIPTS_BASH = getHookScriptsBash();
434
+ /** @deprecated Use getHookScriptsNode() instead */
435
+ export const HOOK_SCRIPTS_NODE = getHookScriptsNode();
436
+ /** @deprecated Use getHookScripts() for cross-platform support */
1644
437
  export const HOOK_SCRIPTS = HOOK_SCRIPTS_BASH;
1645
438
  //# sourceMappingURL=hooks.js.map