@hivehub/rulebook 5.8.1 → 6.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 (514) hide show
  1. package/README.md +86 -216
  2. package/dist/cli/commands/claude.d.ts.map +1 -1
  3. package/dist/cli/commands/claude.js +10 -4
  4. package/dist/cli/commands/claude.js.map +1 -1
  5. package/dist/cli/commands/context-intelligence.d.ts.map +1 -1
  6. package/dist/cli/commands/context-intelligence.js.map +1 -1
  7. package/dist/cli/commands/index.d.ts +1 -2
  8. package/dist/cli/commands/index.d.ts.map +1 -1
  9. package/dist/cli/commands/index.js +1 -2
  10. package/dist/cli/commands/index.js.map +1 -1
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +16 -91
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/commands/mcp.d.ts.map +1 -1
  15. package/dist/cli/commands/mcp.js.map +1 -1
  16. package/dist/cli/commands/misc.d.ts +0 -1
  17. package/dist/cli/commands/misc.d.ts.map +1 -1
  18. package/dist/cli/commands/misc.js +0 -76
  19. package/dist/cli/commands/misc.js.map +1 -1
  20. package/dist/cli/commands/plans.d.ts.map +1 -1
  21. package/dist/cli/commands/plans.js.map +1 -1
  22. package/dist/cli/commands/skills.d.ts.map +1 -1
  23. package/dist/cli/commands/skills.js +6 -2
  24. package/dist/cli/commands/skills.js.map +1 -1
  25. package/dist/cli/commands/task.d.ts.map +1 -1
  26. package/dist/cli/commands/task.js +3 -1
  27. package/dist/cli/commands/task.js.map +1 -1
  28. package/dist/cli/commands/update.d.ts +7 -0
  29. package/dist/cli/commands/update.d.ts.map +1 -1
  30. package/dist/cli/commands/update.js +61 -165
  31. package/dist/cli/commands/update.js.map +1 -1
  32. package/dist/cli/commands/workspace.d.ts.map +1 -1
  33. package/dist/cli/commands/workspace.js +4 -3
  34. package/dist/cli/commands/workspace.js.map +1 -1
  35. package/dist/cli/prompts.d.ts.map +1 -1
  36. package/dist/cli/prompts.js +0 -40
  37. package/dist/cli/prompts.js.map +1 -1
  38. package/dist/core/claude/claude-mcp.d.ts.map +1 -1
  39. package/dist/core/claude/claude-mcp.js +1 -1
  40. package/dist/core/claude/claude-mcp.js.map +1 -1
  41. package/dist/core/claude/claude-md-generator.d.ts.map +1 -1
  42. package/dist/core/claude/claude-md-generator.js.map +1 -1
  43. package/dist/core/claude/claude-settings-manager.d.ts.map +1 -1
  44. package/dist/core/claude/claude-settings-manager.js +9 -6
  45. package/dist/core/claude/claude-settings-manager.js.map +1 -1
  46. package/dist/core/custom-templates.d.ts.map +1 -1
  47. package/dist/core/custom-templates.js.map +1 -1
  48. package/dist/core/detect/detector.d.ts +0 -28
  49. package/dist/core/detect/detector.d.ts.map +1 -1
  50. package/dist/core/detect/detector.js +5 -84
  51. package/dist/core/detect/detector.js.map +1 -1
  52. package/dist/core/detect/library-registry.d.ts.map +1 -1
  53. package/dist/core/detect/library-registry.js.map +1 -1
  54. package/dist/core/docs/docs-generator.d.ts.map +1 -1
  55. package/dist/core/docs/docs-generator.js.map +1 -1
  56. package/dist/core/docs/mcp-reference-generator.d.ts.map +1 -1
  57. package/dist/core/docs/mcp-reference-generator.js.map +1 -1
  58. package/dist/core/generators/generator.d.ts.map +1 -1
  59. package/dist/core/generators/generator.js +0 -72
  60. package/dist/core/generators/generator.js.map +1 -1
  61. package/dist/core/generators/gitignore-generator.d.ts.map +1 -1
  62. package/dist/core/generators/gitignore-generator.js +12 -1
  63. package/dist/core/generators/gitignore-generator.js.map +1 -1
  64. package/dist/core/generators/minimal-scaffolder.d.ts.map +1 -1
  65. package/dist/core/generators/minimal-scaffolder.js.map +1 -1
  66. package/dist/core/generators/rules-generator.d.ts.map +1 -1
  67. package/dist/core/generators/rules-generator.js.map +1 -1
  68. package/dist/core/generators/workflow-generator.d.ts +0 -10
  69. package/dist/core/generators/workflow-generator.d.ts.map +1 -1
  70. package/dist/core/generators/workflow-generator.js +0 -307
  71. package/dist/core/generators/workflow-generator.js.map +1 -1
  72. package/dist/core/logger.d.ts.map +1 -1
  73. package/dist/core/logger.js.map +1 -1
  74. package/dist/core/merger.d.ts.map +1 -1
  75. package/dist/core/merger.js.map +1 -1
  76. package/dist/core/migrator.d.ts.map +1 -1
  77. package/dist/core/migrator.js +2 -1
  78. package/dist/core/migrator.js.map +1 -1
  79. package/dist/core/quality/coverage-checker.d.ts.map +1 -1
  80. package/dist/core/quality/coverage-checker.js.map +1 -1
  81. package/dist/core/quality/dependency-checker.d.ts.map +1 -1
  82. package/dist/core/quality/dependency-checker.js +3 -1
  83. package/dist/core/quality/dependency-checker.js.map +1 -1
  84. package/dist/core/quality/doctor.d.ts.map +1 -1
  85. package/dist/core/quality/doctor.js.map +1 -1
  86. package/dist/core/quality/validator.d.ts.map +1 -1
  87. package/dist/core/quality/validator.js.map +1 -1
  88. package/dist/core/rule-engine.d.ts +5 -21
  89. package/dist/core/rule-engine.d.ts.map +1 -1
  90. package/dist/core/rule-engine.js +9 -191
  91. package/dist/core/rule-engine.js.map +1 -1
  92. package/dist/core/skills/skills-manager.d.ts.map +1 -1
  93. package/dist/core/skills/skills-manager.js.map +1 -1
  94. package/dist/core/state/config-manager.d.ts.map +1 -1
  95. package/dist/core/state/config-manager.js +6 -50
  96. package/dist/core/state/config-manager.js.map +1 -1
  97. package/dist/core/state/override-manager.js.map +1 -1
  98. package/dist/core/state/state-writer.d.ts.map +1 -1
  99. package/dist/core/state/state-writer.js.map +1 -1
  100. package/dist/core/state/version-bumper.d.ts.map +1 -1
  101. package/dist/core/state/version-bumper.js.map +1 -1
  102. package/dist/core/tasks/decision-manager.d.ts.map +1 -1
  103. package/dist/core/tasks/decision-manager.js +6 -1
  104. package/dist/core/tasks/decision-manager.js.map +1 -1
  105. package/dist/core/tasks/knowledge-manager.d.ts.map +1 -1
  106. package/dist/core/tasks/knowledge-manager.js.map +1 -1
  107. package/dist/core/tasks/learn-manager.d.ts.map +1 -1
  108. package/dist/core/tasks/learn-manager.js.map +1 -1
  109. package/dist/core/tasks/plans-manager.d.ts.map +1 -1
  110. package/dist/core/tasks/plans-manager.js.map +1 -1
  111. package/dist/core/tasks/task-manager.d.ts.map +1 -1
  112. package/dist/core/tasks/task-manager.js.map +1 -1
  113. package/dist/core/workspace/legacy-migrator.d.ts.map +1 -1
  114. package/dist/core/workspace/legacy-migrator.js.map +1 -1
  115. package/dist/core/workspace/project-worker.d.ts +0 -4
  116. package/dist/core/workspace/project-worker.d.ts.map +1 -1
  117. package/dist/core/workspace/project-worker.js +0 -28
  118. package/dist/core/workspace/project-worker.js.map +1 -1
  119. package/dist/core/workspace/workspace-manager.d.ts +0 -11
  120. package/dist/core/workspace/workspace-manager.d.ts.map +1 -1
  121. package/dist/core/workspace/workspace-manager.js +6 -30
  122. package/dist/core/workspace/workspace-manager.js.map +1 -1
  123. package/dist/core/workspace/workspace-types.d.ts +0 -1
  124. package/dist/core/workspace/workspace-types.d.ts.map +1 -1
  125. package/dist/hooks/safe-flag-io.js.map +1 -1
  126. package/dist/index.d.ts +1 -1
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js +3 -82
  129. package/dist/index.js.map +1 -1
  130. package/dist/mcp/rulebook-server.d.ts.map +1 -1
  131. package/dist/mcp/rulebook-server.js +55 -1634
  132. package/dist/mcp/rulebook-server.js.map +1 -1
  133. package/dist/mcp/tools/context.d.ts +23 -0
  134. package/dist/mcp/tools/context.d.ts.map +1 -0
  135. package/dist/mcp/tools/context.js +2 -0
  136. package/dist/mcp/tools/context.js.map +1 -0
  137. package/dist/mcp/tools/decision-tools.d.ts +5 -0
  138. package/dist/mcp/tools/decision-tools.d.ts.map +1 -0
  139. package/dist/mcp/tools/decision-tools.js +220 -0
  140. package/dist/mcp/tools/decision-tools.js.map +1 -0
  141. package/dist/mcp/tools/knowledge-tools.d.ts +5 -0
  142. package/dist/mcp/tools/knowledge-tools.d.ts.map +1 -0
  143. package/dist/mcp/tools/knowledge-tools.js +157 -0
  144. package/dist/mcp/tools/knowledge-tools.js.map +1 -0
  145. package/dist/mcp/tools/learn-tools.d.ts +5 -0
  146. package/dist/mcp/tools/learn-tools.d.ts.map +1 -0
  147. package/dist/mcp/tools/learn-tools.js +150 -0
  148. package/dist/mcp/tools/learn-tools.js.map +1 -0
  149. package/dist/mcp/tools/rules-tools.d.ts +4 -0
  150. package/dist/mcp/tools/rules-tools.d.ts.map +1 -0
  151. package/dist/mcp/tools/rules-tools.js +47 -0
  152. package/dist/mcp/tools/rules-tools.js.map +1 -0
  153. package/dist/mcp/tools/skill-tools.d.ts +5 -0
  154. package/dist/mcp/tools/skill-tools.d.ts.map +1 -0
  155. package/dist/mcp/tools/skill-tools.js +330 -0
  156. package/dist/mcp/tools/skill-tools.js.map +1 -0
  157. package/dist/mcp/tools/task-tools.d.ts +5 -0
  158. package/dist/mcp/tools/task-tools.d.ts.map +1 -0
  159. package/dist/mcp/tools/task-tools.js +185 -0
  160. package/dist/mcp/tools/task-tools.js.map +1 -0
  161. package/dist/mcp/tools/workspace-tools.d.ts +6 -0
  162. package/dist/mcp/tools/workspace-tools.d.ts.map +1 -0
  163. package/dist/mcp/tools/workspace-tools.js +118 -0
  164. package/dist/mcp/tools/workspace-tools.js.map +1 -0
  165. package/dist/types.d.ts +1 -46
  166. package/dist/types.d.ts.map +1 -1
  167. package/dist/utils/file-system.d.ts.map +1 -1
  168. package/dist/utils/file-system.js.map +1 -1
  169. package/dist/utils/git-hooks.d.ts.map +1 -1
  170. package/dist/utils/git-hooks.js.map +1 -1
  171. package/dist/utils/gitignore.d.ts.map +1 -1
  172. package/dist/utils/gitignore.js.map +1 -1
  173. package/dist/utils/rulesignore.d.ts.map +1 -1
  174. package/dist/utils/rulesignore.js.map +1 -1
  175. package/package.json +25 -27
  176. package/templates/agents/architect.md +51 -51
  177. package/templates/agents/build-engineer.md +36 -36
  178. package/templates/agents/code-reviewer.md +47 -47
  179. package/templates/agents/docs-writer.md +38 -38
  180. package/templates/agents/implementer.md +42 -42
  181. package/templates/agents/performance-engineer.md +49 -49
  182. package/templates/agents/researcher.md +38 -38
  183. package/templates/agents/security-reviewer.md +40 -40
  184. package/templates/agents/team-lead.md +37 -37
  185. package/templates/agents/tester.md +48 -48
  186. package/templates/ci/rulebook-review.yml +26 -26
  187. package/templates/claude-workflows/review-fanout.js +2 -2
  188. package/templates/claude-workflows/rulebook-driver.js +16 -4
  189. package/templates/cli/CLAUDE.md +102 -117
  190. package/templates/cli/_GENERIC_TEMPLATE.md +29 -29
  191. package/templates/commands/rulebook-decision-create.md +55 -55
  192. package/templates/commands/rulebook-decision-list.md +15 -15
  193. package/templates/commands/rulebook-knowledge-add.md +41 -41
  194. package/templates/commands/rulebook-knowledge-list.md +15 -15
  195. package/templates/commands/rulebook-learn-capture.md +1 -2
  196. package/templates/commands/rulebook-task-apply.md +67 -67
  197. package/templates/commands/rulebook-task-archive.md +94 -94
  198. package/templates/commands/rulebook-task-create.md +93 -93
  199. package/templates/commands/rulebook-task-list.md +42 -42
  200. package/templates/commands/rulebook-task-show.md +52 -52
  201. package/templates/commands/rulebook-task-validate.md +53 -53
  202. package/templates/compact-context/_default.md +23 -23
  203. package/templates/compact-context/cpp.md +26 -26
  204. package/templates/compact-context/go.md +26 -26
  205. package/templates/compact-context/python.md +26 -26
  206. package/templates/compact-context/rust.md +28 -28
  207. package/templates/compact-context/typescript.md +29 -29
  208. package/templates/core/AGENTS_LEAN.md +4 -9
  209. package/templates/core/AGENTS_OVERRIDE.md +16 -16
  210. package/templates/core/AGENT_AUTOMATION.md +273 -296
  211. package/templates/core/CLAUDE_MD_v2.md +85 -90
  212. package/templates/core/DAG.md +304 -304
  213. package/templates/core/DECISIONS.md +38 -38
  214. package/templates/core/DOCUMENTATION_RULES.md +36 -36
  215. package/templates/core/KNOWLEDGE.md +49 -49
  216. package/templates/core/MULTI_AGENT.md +74 -74
  217. package/templates/core/PLANS.md +28 -28
  218. package/templates/core/QUALITY_ENFORCEMENT.md +68 -68
  219. package/templates/core/RULEBOOK.md +1936 -1947
  220. package/templates/core/TIER1_PROHIBITIONS.md +154 -154
  221. package/templates/core/TOKEN_OPTIMIZATION.md +49 -49
  222. package/templates/core/WORKSPACE.md +4 -8
  223. package/templates/git/CI_CD_PATTERNS.md +661 -661
  224. package/templates/git/GITHUB_ACTIONS.md +728 -728
  225. package/templates/git/GITLAB_CI.md +730 -730
  226. package/templates/git/GIT_WORKFLOW.md +1192 -1192
  227. package/templates/git/SECRETS_MANAGEMENT.md +585 -585
  228. package/templates/hooks/COMMIT_MSG.md +530 -530
  229. package/templates/hooks/POST_CHECKOUT.md +546 -546
  230. package/templates/hooks/PREPARE_COMMIT_MSG.md +619 -619
  231. package/templates/hooks/PRE_COMMIT.md +414 -414
  232. package/templates/hooks/PRE_PUSH.md +601 -601
  233. package/templates/hooks/enforce-pre-tool.sh +26 -9
  234. package/templates/hooks/update-check.ps1 +84 -84
  235. package/templates/hooks/update-check.sh +45 -21
  236. package/templates/languages/C.md +333 -333
  237. package/templates/languages/CPP.md +743 -743
  238. package/templates/languages/CSHARP.md +417 -417
  239. package/templates/languages/ELIXIR.md +454 -454
  240. package/templates/languages/ERLANG.md +361 -361
  241. package/templates/languages/GO.md +645 -645
  242. package/templates/languages/HASKELL.md +177 -177
  243. package/templates/languages/JAVA.md +607 -607
  244. package/templates/languages/JAVASCRIPT.md +631 -631
  245. package/templates/languages/JULIA.md +97 -97
  246. package/templates/languages/KOTLIN.md +511 -511
  247. package/templates/languages/LISP.md +100 -100
  248. package/templates/languages/LUA.md +74 -74
  249. package/templates/languages/OBJECTIVEC.md +90 -90
  250. package/templates/languages/PHP.md +416 -416
  251. package/templates/languages/PYTHON.md +682 -682
  252. package/templates/languages/RUBY.md +421 -421
  253. package/templates/languages/RUST.md +477 -477
  254. package/templates/languages/SAS.md +73 -73
  255. package/templates/languages/SCALA.md +348 -348
  256. package/templates/languages/SOLIDITY.md +580 -580
  257. package/templates/languages/SQL.md +137 -137
  258. package/templates/languages/SWIFT.md +466 -466
  259. package/templates/languages/TYPESCRIPT.md +591 -591
  260. package/templates/languages/ZIG.md +265 -265
  261. package/templates/modules/CONTEXT7.md +54 -54
  262. package/templates/modules/GITHUB_MCP.md +64 -64
  263. package/templates/modules/PLAYWRIGHT.md +90 -90
  264. package/templates/modules/RULEBOOK_MCP.md +208 -208
  265. package/templates/modules/SERENA.md +337 -337
  266. package/templates/modules/SUPABASE.md +223 -223
  267. package/templates/modules/SYNAP.md +69 -69
  268. package/templates/modules/VECTORIZER.md +63 -63
  269. package/templates/modules/sequential-thinking.md +42 -42
  270. package/templates/rules/consult-analysis-before-implementing.md +21 -23
  271. package/templates/rules/cpp.md +46 -46
  272. package/templates/rules/csharp.md +44 -44
  273. package/templates/rules/diagnostic-first.md +39 -39
  274. package/templates/rules/fail-twice-escalate.md +46 -46
  275. package/templates/rules/follow-task-sequence.md +36 -36
  276. package/templates/rules/git-safety.md +29 -29
  277. package/templates/rules/go.md +40 -40
  278. package/templates/rules/incremental-implementation.md +56 -56
  279. package/templates/rules/incremental-tests.md +29 -29
  280. package/templates/rules/java.md +43 -43
  281. package/templates/rules/javascript.md +39 -39
  282. package/templates/rules/knowledge-base-usage.md +41 -41
  283. package/templates/rules/multi-agent-teams.md +75 -75
  284. package/templates/rules/no-deferred.md +31 -31
  285. package/templates/rules/no-shortcuts.md +30 -30
  286. package/templates/rules/python.md +43 -43
  287. package/templates/rules/research-first.md +30 -30
  288. package/templates/rules/respect-handoff-trigger.md +41 -41
  289. package/templates/rules/rust.md +40 -40
  290. package/templates/rules/sequential-editing.md +21 -21
  291. package/templates/rules/session-workflow.md +24 -24
  292. package/templates/rules/task-decomposition.md +32 -32
  293. package/templates/rules/typescript.md +40 -40
  294. package/templates/skills/cli/claude/SKILL.md +42 -42
  295. package/templates/skills/core/agent-automation/SKILL.md +194 -194
  296. package/templates/skills/core/dag/SKILL.md +314 -314
  297. package/templates/skills/core/documentation-rules/SKILL.md +46 -46
  298. package/templates/skills/core/quality-enforcement/SKILL.md +78 -78
  299. package/templates/skills/core/rulebook/SKILL.md +176 -176
  300. package/templates/skills/core/rulebook-terse/SKILL.md +116 -116
  301. package/templates/skills/core/rulebook-terse-commit/SKILL.md +96 -96
  302. package/templates/skills/core/rulebook-terse-review/SKILL.md +112 -112
  303. package/templates/skills/dev/accessibility/SKILL.md +17 -17
  304. package/templates/skills/dev/analysis/SKILL.md +19 -19
  305. package/templates/skills/dev/api-design/SKILL.md +15 -15
  306. package/templates/skills/dev/architect/SKILL.md +17 -17
  307. package/templates/skills/dev/build-fix/SKILL.md +17 -17
  308. package/templates/skills/dev/db-design/SKILL.md +15 -15
  309. package/templates/skills/dev/debug/SKILL.md +16 -16
  310. package/templates/skills/dev/deploy/SKILL.md +17 -17
  311. package/templates/skills/dev/docs/SKILL.md +17 -17
  312. package/templates/skills/dev/handoff/SKILL.md +27 -27
  313. package/templates/skills/dev/migrate/SKILL.md +15 -15
  314. package/templates/skills/dev/perf/SKILL.md +17 -17
  315. package/templates/skills/dev/refactor/SKILL.md +17 -17
  316. package/templates/skills/dev/research/SKILL.md +14 -14
  317. package/templates/skills/dev/review/SKILL.md +18 -18
  318. package/templates/skills/dev/security-audit/SKILL.md +17 -17
  319. package/templates/skills/languages/c/SKILL.md +343 -343
  320. package/templates/skills/languages/cpp/SKILL.md +753 -753
  321. package/templates/skills/languages/csharp/SKILL.md +427 -427
  322. package/templates/skills/languages/elixir/SKILL.md +464 -464
  323. package/templates/skills/languages/erlang/SKILL.md +371 -371
  324. package/templates/skills/languages/go/SKILL.md +655 -655
  325. package/templates/skills/languages/haskell/SKILL.md +187 -187
  326. package/templates/skills/languages/java/SKILL.md +617 -617
  327. package/templates/skills/languages/javascript/SKILL.md +641 -641
  328. package/templates/skills/languages/julia/SKILL.md +107 -107
  329. package/templates/skills/languages/kotlin/SKILL.md +521 -521
  330. package/templates/skills/languages/lisp/SKILL.md +110 -110
  331. package/templates/skills/languages/lua/SKILL.md +84 -84
  332. package/templates/skills/languages/objectivec/SKILL.md +100 -100
  333. package/templates/skills/languages/php/SKILL.md +426 -426
  334. package/templates/skills/languages/python/SKILL.md +692 -692
  335. package/templates/skills/languages/ruby/SKILL.md +431 -431
  336. package/templates/skills/languages/rust/SKILL.md +487 -487
  337. package/templates/skills/languages/sas/SKILL.md +83 -83
  338. package/templates/skills/languages/scala/SKILL.md +358 -358
  339. package/templates/skills/languages/solidity/SKILL.md +590 -590
  340. package/templates/skills/languages/sql/SKILL.md +147 -147
  341. package/templates/skills/languages/swift/SKILL.md +476 -476
  342. package/templates/skills/languages/typescript/SKILL.md +302 -302
  343. package/templates/skills/languages/zig/SKILL.md +275 -275
  344. package/templates/skills/modules/context7/SKILL.md +64 -64
  345. package/templates/skills/modules/github-mcp/SKILL.md +74 -74
  346. package/templates/skills/modules/playwright/SKILL.md +100 -100
  347. package/templates/skills/modules/rulebook-mcp/SKILL.md +166 -166
  348. package/templates/skills/modules/serena/SKILL.md +347 -347
  349. package/templates/skills/modules/supabase/SKILL.md +233 -233
  350. package/templates/skills/modules/synap/SKILL.md +79 -79
  351. package/templates/skills/modules/vectorizer/SKILL.md +73 -73
  352. package/.claude/commands/analysis.md +0 -35
  353. package/.claude/commands/continue.md +0 -33
  354. package/.claude/commands/rulebook-decision-create.md +0 -55
  355. package/.claude/commands/rulebook-decision-list.md +0 -15
  356. package/.claude/commands/rulebook-knowledge-add.md +0 -41
  357. package/.claude/commands/rulebook-knowledge-list.md +0 -15
  358. package/.claude/commands/rulebook-learn-capture.md +0 -41
  359. package/.claude/commands/rulebook-learn-list.md +0 -13
  360. package/.claude/commands/rulebook-memory-save.md +0 -48
  361. package/.claude/commands/rulebook-memory-search.md +0 -47
  362. package/.claude/commands/rulebook-task-apply.md +0 -67
  363. package/.claude/commands/rulebook-task-archive.md +0 -94
  364. package/.claude/commands/rulebook-task-create.md +0 -93
  365. package/.claude/commands/rulebook-task-list.md +0 -42
  366. package/.claude/commands/rulebook-task-show.md +0 -52
  367. package/.claude/commands/rulebook-task-validate.md +0 -53
  368. package/.claude-plugin/marketplace.json +0 -28
  369. package/.claude-plugin/plugin.json +0 -8
  370. package/dist/agents/claude-code.d.ts +0 -69
  371. package/dist/agents/claude-code.d.ts.map +0 -1
  372. package/dist/agents/claude-code.js +0 -180
  373. package/dist/agents/claude-code.js.map +0 -1
  374. package/dist/agents/cursor-agent.d.ts +0 -184
  375. package/dist/agents/cursor-agent.d.ts.map +0 -1
  376. package/dist/agents/cursor-agent.js +0 -299
  377. package/dist/agents/cursor-agent.js.map +0 -1
  378. package/dist/agents/gemini-cli.d.ts +0 -69
  379. package/dist/agents/gemini-cli.d.ts.map +0 -1
  380. package/dist/agents/gemini-cli.js +0 -180
  381. package/dist/agents/gemini-cli.js.map +0 -1
  382. package/dist/cli/commands/memory.d.ts +0 -30
  383. package/dist/cli/commands/memory.d.ts.map +0 -1
  384. package/dist/cli/commands/memory.js +0 -259
  385. package/dist/cli/commands/memory.js.map +0 -1
  386. package/dist/core/console/cli-bridge.d.ts +0 -113
  387. package/dist/core/console/cli-bridge.d.ts.map +0 -1
  388. package/dist/core/console/cli-bridge.js +0 -1094
  389. package/dist/core/console/cli-bridge.js.map +0 -1
  390. package/dist/core/ide/multi-tool-generator.d.ts +0 -59
  391. package/dist/core/ide/multi-tool-generator.d.ts.map +0 -1
  392. package/dist/core/ide/multi-tool-generator.js +0 -157
  393. package/dist/core/ide/multi-tool-generator.js.map +0 -1
  394. package/dist/core/ide/opencode-generator.d.ts +0 -72
  395. package/dist/core/ide/opencode-generator.d.ts.map +0 -1
  396. package/dist/core/ide/opencode-generator.js +0 -450
  397. package/dist/core/ide/opencode-generator.js.map +0 -1
  398. package/dist/core/indexer/background-indexer.d.ts +0 -35
  399. package/dist/core/indexer/background-indexer.d.ts.map +0 -1
  400. package/dist/core/indexer/background-indexer.js +0 -267
  401. package/dist/core/indexer/background-indexer.js.map +0 -1
  402. package/dist/core/indexer/file-parser.d.ts +0 -28
  403. package/dist/core/indexer/file-parser.d.ts.map +0 -1
  404. package/dist/core/indexer/file-parser.js +0 -171
  405. package/dist/core/indexer/file-parser.js.map +0 -1
  406. package/dist/core/indexer/indexer-types.d.ts +0 -37
  407. package/dist/core/indexer/indexer-types.d.ts.map +0 -1
  408. package/dist/core/indexer/indexer-types.js +0 -8
  409. package/dist/core/indexer/indexer-types.js.map +0 -1
  410. package/dist/memory/file-search.d.ts +0 -43
  411. package/dist/memory/file-search.d.ts.map +0 -1
  412. package/dist/memory/file-search.js +0 -228
  413. package/dist/memory/file-search.js.map +0 -1
  414. package/dist/memory/file-store.d.ts +0 -99
  415. package/dist/memory/file-store.d.ts.map +0 -1
  416. package/dist/memory/file-store.js +0 -615
  417. package/dist/memory/file-store.js.map +0 -1
  418. package/dist/memory/legacy-migrator.d.ts +0 -27
  419. package/dist/memory/legacy-migrator.d.ts.map +0 -1
  420. package/dist/memory/legacy-migrator.js +0 -185
  421. package/dist/memory/legacy-migrator.js.map +0 -1
  422. package/dist/memory/memory-hooks.d.ts +0 -48
  423. package/dist/memory/memory-hooks.d.ts.map +0 -1
  424. package/dist/memory/memory-hooks.js +0 -248
  425. package/dist/memory/memory-hooks.js.map +0 -1
  426. package/dist/memory/memory-manager.d.ts +0 -65
  427. package/dist/memory/memory-manager.d.ts.map +0 -1
  428. package/dist/memory/memory-manager.js +0 -223
  429. package/dist/memory/memory-manager.js.map +0 -1
  430. package/dist/memory/memory-types.d.ts +0 -85
  431. package/dist/memory/memory-types.d.ts.map +0 -1
  432. package/dist/memory/memory-types.js +0 -7
  433. package/dist/memory/memory-types.js.map +0 -1
  434. package/templates/agents/accessibility-reviewer.md +0 -43
  435. package/templates/agents/api-designer.md +0 -42
  436. package/templates/agents/compiler/codegen-debugger.md +0 -34
  437. package/templates/agents/compiler/stdlib-engineer.md +0 -28
  438. package/templates/agents/compiler/test-coverage-guardian.md +0 -31
  439. package/templates/agents/context-intelligence.md +0 -50
  440. package/templates/agents/database-architect.md +0 -41
  441. package/templates/agents/devops-engineer.md +0 -42
  442. package/templates/agents/game-engine/cpp-core-expert.md +0 -35
  443. package/templates/agents/game-engine/render-engineer.md +0 -22
  444. package/templates/agents/game-engine/shader-engineer.md +0 -38
  445. package/templates/agents/game-engine/systems-integration.md +0 -43
  446. package/templates/agents/generic/code-reviewer.md +0 -41
  447. package/templates/agents/generic/docs-writer.md +0 -25
  448. package/templates/agents/generic/project-manager.md +0 -36
  449. package/templates/agents/generic/researcher.md +0 -34
  450. package/templates/agents/generic/test-engineer.md +0 -41
  451. package/templates/agents/i18n-engineer.md +0 -42
  452. package/templates/agents/migration-engineer.md +0 -42
  453. package/templates/agents/mobile/platform-specialist.md +0 -22
  454. package/templates/agents/mobile/ui-engineer.md +0 -22
  455. package/templates/agents/project-manager.md +0 -217
  456. package/templates/agents/refactoring-agent.md +0 -41
  457. package/templates/agents/ux-reviewer.md +0 -43
  458. package/templates/agents/web-app/api-designer.md +0 -22
  459. package/templates/agents/web-app/backend-engineer.md +0 -30
  460. package/templates/agents/web-app/database-engineer.md +0 -22
  461. package/templates/agents/web-app/frontend-engineer.md +0 -29
  462. package/templates/agents/web-app/security-reviewer.md +0 -32
  463. package/templates/cli/AIDER.md +0 -49
  464. package/templates/cli/AMAZON_Q.md +0 -25
  465. package/templates/cli/AUGGIE.md +0 -32
  466. package/templates/cli/CLINE.md +0 -99
  467. package/templates/cli/CODEBUDDY.md +0 -20
  468. package/templates/cli/CODEIUM.md +0 -20
  469. package/templates/cli/CODEX.md +0 -21
  470. package/templates/cli/CONTINUE.md +0 -34
  471. package/templates/cli/CURSOR_CLI.md +0 -62
  472. package/templates/cli/FACTORY.md +0 -18
  473. package/templates/cli/GEMINI.md +0 -35
  474. package/templates/cli/KILOCODE.md +0 -18
  475. package/templates/cli/OPENCODE.md +0 -85
  476. package/templates/cli/gemini-extension.json +0 -77
  477. package/templates/commands/rulebook-memory-save.md +0 -48
  478. package/templates/commands/rulebook-memory-search.md +0 -47
  479. package/templates/ides/CONTINUE_RULES.md +0 -16
  480. package/templates/ides/COPILOT_INSTRUCTIONS.md +0 -23
  481. package/templates/ides/GEMINI_RULES.md +0 -17
  482. package/templates/ides/OPENCODE.md +0 -63
  483. package/templates/ides/WINDSURF_RULES.md +0 -14
  484. package/templates/modules/ATLASSIAN.md +0 -255
  485. package/templates/modules/FIGMA.md +0 -267
  486. package/templates/modules/GRAFANA.md +0 -328
  487. package/templates/modules/MEMORY.md +0 -126
  488. package/templates/modules/NOTION.md +0 -247
  489. package/templates/skills/cli/aider/SKILL.md +0 -59
  490. package/templates/skills/cli/amazon-q/SKILL.md +0 -35
  491. package/templates/skills/cli/auggie/SKILL.md +0 -42
  492. package/templates/skills/cli/cline/SKILL.md +0 -42
  493. package/templates/skills/cli/codebuddy/SKILL.md +0 -30
  494. package/templates/skills/cli/codeium/SKILL.md +0 -30
  495. package/templates/skills/cli/codex/SKILL.md +0 -31
  496. package/templates/skills/cli/continue/SKILL.md +0 -44
  497. package/templates/skills/cli/cursor-cli/SKILL.md +0 -38
  498. package/templates/skills/cli/factory/SKILL.md +0 -28
  499. package/templates/skills/cli/gemini/SKILL.md +0 -45
  500. package/templates/skills/cli/kilocode/SKILL.md +0 -28
  501. package/templates/skills/cli/opencode/SKILL.md +0 -82
  502. package/templates/skills/ides/copilot/SKILL.md +0 -47
  503. package/templates/skills/ides/cursor/SKILL.md +0 -53
  504. package/templates/skills/ides/jetbrains-ai/SKILL.md +0 -45
  505. package/templates/skills/ides/replit/SKILL.md +0 -46
  506. package/templates/skills/ides/tabnine/SKILL.md +0 -39
  507. package/templates/skills/ides/vscode/SKILL.md +0 -50
  508. package/templates/skills/ides/windsurf/SKILL.md +0 -46
  509. package/templates/skills/ides/zed/SKILL.md +0 -42
  510. package/templates/skills/modules/atlassian/SKILL.md +0 -265
  511. package/templates/skills/modules/figma/SKILL.md +0 -277
  512. package/templates/skills/modules/grafana/SKILL.md +0 -338
  513. package/templates/skills/modules/memory/SKILL.md +0 -73
  514. package/templates/skills/modules/notion/SKILL.md +0 -257
@@ -5,10 +5,16 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync,
5
5
  import { dirname, join, resolve } from 'path';
6
6
  import { z } from 'zod';
7
7
  import { ConfigManager } from '../core/state/config-manager.js';
8
- import { BackgroundIndexer } from '../core/indexer/background-indexer.js';
9
8
  import { SkillsManager, getDefaultTemplatesPath } from '../core/skills/skills-manager.js';
10
9
  import { TaskManager } from '../core/tasks/task-manager.js';
11
10
  import { WorkspaceManager } from '../core/workspace/workspace-manager.js';
11
+ import { registerTaskTools } from './tools/task-tools.js';
12
+ import { registerSkillTools } from './tools/skill-tools.js';
13
+ import { registerWorkspaceTools } from './tools/workspace-tools.js';
14
+ import { registerDecisionTools } from './tools/decision-tools.js';
15
+ import { registerKnowledgeTools } from './tools/knowledge-tools.js';
16
+ import { registerLearnTools } from './tools/learn-tools.js';
17
+ import { registerRulesTools } from './tools/rules-tools.js';
12
18
  // --- Timeout guard for MCP tool handlers ---
13
19
  // Prevents the MCP server from hanging when a tool handler blocks (SQLite, WASM, fs).
14
20
  const MCP_TOOL_TIMEOUT_MS = parseInt(process.env.RULEBOOK_MCP_TIMEOUT_MS ?? '10000', 10);
@@ -260,1590 +266,52 @@ export async function startRulebookMcpServer() {
260
266
  const w = await workspaceManager.getWorker(projectId);
261
267
  return w.getSkillsManager();
262
268
  }
263
- async function getMemMgr(projectId) {
264
- if (workspaceManager) {
265
- const pid = projectId ?? workspaceManager.getDefaultProjectId();
266
- const w = await workspaceManager.getWorker(pid);
267
- return w.getMemoryManager();
268
- }
269
- return memoryManager;
270
- }
271
- const server = new McpServer({
272
- name: 'rulebook-task-management',
273
- version: '5.2.0',
274
- });
275
- // --- Wrap all tool handlers with a timeout guard ---
276
- const originalRegisterTool = server.registerTool.bind(server);
277
- server.registerTool = ((name, config, handler) => {
278
- const wrappedHandler = async (...handlerArgs) => {
279
- try {
280
- return await withTimeout(handler(...handlerArgs), MCP_TOOL_TIMEOUT_MS, name);
281
- }
282
- catch (error) {
283
- const msg = error instanceof Error ? error.message : String(error);
284
- console.error(`[rulebook-mcp] ${name} error: ${msg}`);
285
- return {
286
- content: [
287
- { type: 'text', text: JSON.stringify({ success: false, error: msg }) },
288
- ],
289
- };
290
- }
291
- };
292
- return originalRegisterTool(name, config, wrappedHandler);
293
- });
294
- // Zod schema reused across tools for workspace project targeting
295
- const projectIdSchema = z
296
- .string()
297
- .optional()
298
- .describe('Project ID (workspace mode only, defaults to default project)');
299
- // Register tool: rulebook_task_create
300
- server.registerTool('rulebook_task_create', {
301
- title: 'Create Rulebook Task',
302
- description: 'Create a new Rulebook task',
303
- inputSchema: {
304
- taskId: z
305
- .string()
306
- .describe('Task ID with phase prefix: phase<N>_<description> (e.g., phase1_add-user-auth, phase2a_fix-login-bug)'),
307
- projectId: projectIdSchema,
308
- },
309
- }, async (args) => {
310
- const tm = await getTaskMgr(args.projectId);
311
- await tm.createTask(args.taskId);
312
- const resultText = JSON.stringify({
313
- success: true,
314
- taskId: args.taskId,
315
- message: `Task ${args.taskId} created successfully`,
316
- });
317
- autoCapture('rulebook_task_create', args, resultText);
318
- return { content: [{ type: 'text', text: resultText }] };
319
- });
320
- // Register tool: rulebook_task_list
321
- server.registerTool('rulebook_task_list', {
322
- title: 'List Rulebook Tasks',
323
- description: 'List all Rulebook tasks',
324
- inputSchema: {
325
- includeArchived: z.boolean().optional().describe('Include archived tasks'),
326
- status: z
327
- .enum(['pending', 'in-progress', 'completed', 'blocked'])
328
- .optional()
329
- .describe('Filter by status'),
330
- projectId: projectIdSchema,
331
- },
332
- }, async (args) => {
333
- const tm = await getTaskMgr(args.projectId);
334
- const tasks = await tm.listTasks(args.includeArchived || false);
335
- let filtered = tasks;
336
- if (args.status) {
337
- filtered = tasks.filter((t) => t.status === args.status);
338
- }
339
- return {
340
- content: [
341
- {
342
- type: 'text',
343
- text: JSON.stringify({
344
- tasks: filtered.map((t) => ({
345
- id: t.id,
346
- title: t.title,
347
- status: t.status,
348
- createdAt: t.createdAt,
349
- updatedAt: t.updatedAt,
350
- })),
351
- count: filtered.length,
352
- }),
353
- },
354
- ],
355
- };
356
- });
357
- // Register tool: rulebook_task_show
358
- server.registerTool('rulebook_task_show', {
359
- title: 'Show Rulebook Task',
360
- description: 'Show task details',
361
- inputSchema: {
362
- taskId: z.string().describe('Task ID to show'),
363
- projectId: projectIdSchema,
364
- },
365
- }, async (args) => {
366
- const tm = await getTaskMgr(args.projectId);
367
- const task = await tm.showTask(args.taskId);
368
- return {
369
- content: [
370
- {
371
- type: 'text',
372
- text: JSON.stringify({
373
- task: task
374
- ? {
375
- id: task.id,
376
- title: task.title,
377
- status: task.status,
378
- proposal: task.proposal,
379
- tasks: task.tasks,
380
- design: task.design,
381
- specs: task.specs,
382
- createdAt: task.createdAt,
383
- updatedAt: task.updatedAt,
384
- }
385
- : null,
386
- found: task !== null,
387
- }),
388
- },
389
- ],
390
- };
391
- });
392
- // Register tool: rulebook_task_update
393
- server.registerTool('rulebook_task_update', {
394
- title: 'Update Rulebook Task',
395
- description: 'Update task status',
396
- inputSchema: {
397
- taskId: z.string().describe('Task ID to update'),
398
- status: z
399
- .enum(['pending', 'in-progress', 'completed', 'blocked'])
400
- .optional()
401
- .describe('New status'),
402
- projectId: projectIdSchema,
403
- },
404
- }, async (args) => {
405
- const tm = await getTaskMgr(args.projectId);
406
- if (args.status) {
407
- await tm.updateTaskStatus(args.taskId, args.status);
408
- }
409
- const resultText = JSON.stringify({
410
- success: true,
411
- taskId: args.taskId,
412
- message: `Task ${args.taskId} updated successfully`,
413
- });
414
- autoCapture('rulebook_task_update', args, resultText);
415
- return { content: [{ type: 'text', text: resultText }] };
416
- });
417
- // Register tool: rulebook_task_validate
418
- server.registerTool('rulebook_task_validate', {
419
- title: 'Validate Rulebook Task',
420
- description: 'Validate task format',
421
- inputSchema: {
422
- taskId: z.string().describe('Task ID to validate'),
423
- projectId: projectIdSchema,
424
- },
425
- }, async (args) => {
426
- const tm = await getTaskMgr(args.projectId);
427
- const validation = await tm.validateTask(args.taskId);
428
- return {
429
- content: [
430
- {
431
- type: 'text',
432
- text: JSON.stringify({
433
- valid: validation.valid,
434
- errors: validation.errors,
435
- warnings: validation.warnings,
436
- }),
437
- },
438
- ],
439
- };
440
- });
441
- // Register tool: rulebook_task_archive
442
- server.registerTool('rulebook_task_archive', {
443
- title: 'Archive Rulebook Task',
444
- description: 'Archive a completed task',
445
- inputSchema: {
446
- taskId: z
447
- .string()
448
- .describe('Task ID to archive (must use phase prefix, e.g., phase1_my-task)'),
449
- skipValidation: z.boolean().optional().describe('Skip validation before archiving'),
450
- projectId: projectIdSchema,
451
- },
452
- }, async (args) => {
453
- const tm = await getTaskMgr(args.projectId);
454
- await tm.archiveTask(args.taskId, args.skipValidation || false);
455
- const resultText = JSON.stringify({
456
- success: true,
457
- taskId: args.taskId,
458
- message: `Task ${args.taskId} archived successfully`,
459
- });
460
- autoCapture('rulebook_task_archive', args, resultText);
461
- return { content: [{ type: 'text', text: resultText }] };
462
- });
463
- // Register tool: rulebook_task_delete
464
- server.registerTool('rulebook_task_delete', {
465
- title: 'Delete Rulebook Task',
466
- description: 'Delete a task permanently',
467
- inputSchema: {
468
- taskId: z.string().describe('Task ID to delete'),
469
- projectId: projectIdSchema,
470
- },
471
- }, async (args) => {
472
- const tm = await getTaskMgr(args.projectId);
473
- await tm.deleteTask(args.taskId);
474
- const resultText = JSON.stringify({
475
- success: true,
476
- taskId: args.taskId,
477
- message: `Task ${args.taskId} deleted successfully`,
478
- });
479
- autoCapture('rulebook_task_delete', args, resultText);
480
- return { content: [{ type: 'text', text: resultText }] };
481
- });
482
- // ============================================
483
- // Skills Management Functions (v2.0)
484
- // ============================================
485
- // Register tool: rulebook_skill_list
486
- server.registerTool('rulebook_skill_list', {
487
- title: 'List Available Skills',
488
- description: 'List all available skills, optionally filtered by category',
489
- inputSchema: {
490
- category: z
491
- .enum([
492
- 'languages',
493
- 'frameworks',
494
- 'modules',
495
- 'services',
496
- 'workflows',
497
- 'ides',
498
- 'core',
499
- 'cli',
500
- 'git',
501
- 'hooks',
502
- ])
503
- .optional()
504
- .describe('Filter by category'),
505
- enabledOnly: z.boolean().optional().describe('Show only enabled skills'),
506
- projectId: projectIdSchema,
507
- },
508
- }, async (args) => {
509
- try {
510
- const sm = await getSkillsMgr(args.projectId);
511
- const cm = await getConfigMgr(args.projectId);
512
- let skills;
513
- if (args.category) {
514
- skills = await sm.getSkillsByCategory(args.category);
515
- }
516
- else {
517
- skills = await sm.getSkills();
518
- }
519
- const rbConfig = await cm.loadConfig();
520
- const enabledIds = new Set(rbConfig.skills?.enabled || []);
521
- let filteredSkills = skills.map((s) => ({
522
- id: s.id,
523
- name: s.metadata.name,
524
- description: s.metadata.description,
525
- category: s.category,
526
- enabled: enabledIds.has(s.id),
527
- version: s.metadata.version,
528
- tags: s.metadata.tags,
529
- }));
530
- if (args.enabledOnly) {
531
- filteredSkills = filteredSkills.filter((s) => s.enabled);
532
- }
533
- return {
534
- content: [
535
- {
536
- type: 'text',
537
- text: JSON.stringify({
538
- success: true,
539
- skills: filteredSkills,
540
- count: filteredSkills.length,
541
- category: args.category || 'all',
542
- }),
543
- },
544
- ],
545
- };
546
- }
547
- catch (error) {
548
- return {
549
- content: [
550
- {
551
- type: 'text',
552
- text: JSON.stringify({
553
- success: false,
554
- error: error instanceof Error ? error.message : 'Unknown error',
555
- }),
556
- },
557
- ],
558
- };
559
- }
560
- });
561
- // Register tool: rulebook_skill_show
562
- server.registerTool('rulebook_skill_show', {
563
- title: 'Show Skill Details',
564
- description: 'Show detailed information about a specific skill',
565
- inputSchema: {
566
- skillId: z.string().describe('Skill ID (e.g., languages/typescript)'),
567
- projectId: projectIdSchema,
568
- },
569
- }, async (args) => {
570
- try {
571
- const sm = await getSkillsMgr(args.projectId);
572
- const cm = await getConfigMgr(args.projectId);
573
- const skill = await sm.getSkillById(args.skillId);
574
- if (!skill) {
575
- return {
576
- content: [
577
- {
578
- type: 'text',
579
- text: JSON.stringify({
580
- success: false,
581
- error: `Skill not found: ${args.skillId}`,
582
- suggestion: 'Use rulebook_skill_list to see available skills',
583
- }),
584
- },
585
- ],
586
- };
587
- }
588
- const rbConfig = await cm.loadConfig();
589
- const enabled = rbConfig.skills?.enabled?.includes(args.skillId) || false;
590
- return {
591
- content: [
592
- {
593
- type: 'text',
594
- text: JSON.stringify({
595
- success: true,
596
- skill: {
597
- id: skill.id,
598
- name: skill.metadata.name,
599
- description: skill.metadata.description,
600
- category: skill.category,
601
- enabled,
602
- version: skill.metadata.version,
603
- author: skill.metadata.author,
604
- tags: skill.metadata.tags,
605
- dependencies: skill.metadata.dependencies,
606
- conflicts: skill.metadata.conflicts,
607
- content: skill.content.slice(0, 2000) + (skill.content.length > 2000 ? '...' : ''),
608
- },
609
- }),
610
- },
611
- ],
612
- };
613
- }
614
- catch (error) {
615
- return {
616
- content: [
617
- {
618
- type: 'text',
619
- text: JSON.stringify({
620
- success: false,
621
- error: error instanceof Error ? error.message : 'Unknown error',
622
- }),
623
- },
624
- ],
625
- };
626
- }
627
- });
628
- // Register tool: rulebook_skill_enable
629
- server.registerTool('rulebook_skill_enable', {
630
- title: 'Enable Skill',
631
- description: 'Enable a skill in the project configuration',
632
- inputSchema: {
633
- skillId: z.string().describe('Skill ID to enable (e.g., languages/typescript)'),
634
- projectId: projectIdSchema,
635
- },
636
- }, async (args) => {
637
- try {
638
- const sm = await getSkillsMgr(args.projectId);
639
- const cm = await getConfigMgr(args.projectId);
640
- let rbConfig = await cm.loadConfig();
641
- rbConfig = await sm.enableSkill(args.skillId, rbConfig);
642
- await cm.saveConfig(rbConfig);
643
- const validation = await sm.validateSkills(rbConfig);
644
- const resultText = JSON.stringify({
645
- success: true,
646
- skillId: args.skillId,
647
- message: `Skill ${args.skillId} enabled successfully`,
648
- warnings: validation.warnings,
649
- conflicts: validation.conflicts,
650
- });
651
- autoCapture('rulebook_skill_enable', args, resultText);
652
- return { content: [{ type: 'text', text: resultText }] };
653
- }
654
- catch (error) {
655
- return {
656
- content: [
657
- {
658
- type: 'text',
659
- text: JSON.stringify({
660
- success: false,
661
- error: error instanceof Error ? error.message : 'Unknown error',
662
- }),
663
- },
664
- ],
665
- };
666
- }
667
- });
668
- // Register tool: rulebook_skill_disable
669
- server.registerTool('rulebook_skill_disable', {
670
- title: 'Disable Skill',
671
- description: 'Disable a skill in the project configuration',
672
- inputSchema: {
673
- skillId: z.string().describe('Skill ID to disable (e.g., languages/typescript)'),
674
- projectId: projectIdSchema,
675
- },
676
- }, async (args) => {
677
- try {
678
- const sm = await getSkillsMgr(args.projectId);
679
- const cm = await getConfigMgr(args.projectId);
680
- let rbConfig = await cm.loadConfig();
681
- if (!rbConfig.skills?.enabled?.includes(args.skillId)) {
682
- return {
683
- content: [
684
- {
685
- type: 'text',
686
- text: JSON.stringify({
687
- success: false,
688
- error: `Skill ${args.skillId} is not currently enabled`,
689
- }),
690
- },
691
- ],
692
- };
693
- }
694
- rbConfig = await sm.disableSkill(args.skillId, rbConfig);
695
- await cm.saveConfig(rbConfig);
696
- const resultText = JSON.stringify({
697
- success: true,
698
- skillId: args.skillId,
699
- message: `Skill ${args.skillId} disabled successfully`,
700
- });
701
- autoCapture('rulebook_skill_disable', args, resultText);
702
- return { content: [{ type: 'text', text: resultText }] };
703
- }
704
- catch (error) {
705
- return {
706
- content: [
707
- {
708
- type: 'text',
709
- text: JSON.stringify({
710
- success: false,
711
- error: error instanceof Error ? error.message : 'Unknown error',
712
- }),
713
- },
714
- ],
715
- };
716
- }
717
- });
718
- // Register tool: rulebook_skill_search
719
- server.registerTool('rulebook_skill_search', {
720
- title: 'Search Skills',
721
- description: 'Search for skills by name, description, or tags',
722
- inputSchema: {
723
- query: z.string().describe('Search query'),
724
- projectId: projectIdSchema,
725
- },
726
- }, async (args) => {
727
- try {
728
- const sm = await getSkillsMgr(args.projectId);
729
- const cm = await getConfigMgr(args.projectId);
730
- const skills = await sm.searchSkills(args.query);
731
- const rbConfig = await cm.loadConfig();
732
- const enabledIds = new Set(rbConfig.skills?.enabled || []);
733
- return {
734
- content: [
735
- {
736
- type: 'text',
737
- text: JSON.stringify({
738
- success: true,
739
- query: args.query,
740
- skills: skills.map((s) => ({
741
- id: s.id,
742
- name: s.metadata.name,
743
- description: s.metadata.description,
744
- category: s.category,
745
- enabled: enabledIds.has(s.id),
746
- })),
747
- count: skills.length,
748
- }),
749
- },
750
- ],
751
- };
752
- }
753
- catch (error) {
754
- return {
755
- content: [
756
- {
757
- type: 'text',
758
- text: JSON.stringify({
759
- success: false,
760
- error: error instanceof Error ? error.message : 'Unknown error',
761
- }),
762
- },
763
- ],
764
- };
765
- }
766
- });
767
- // Register tool: rulebook_skill_validate
768
- server.registerTool('rulebook_skill_validate', {
769
- title: 'Validate Skills Configuration',
770
- description: 'Validate the current skills configuration for conflicts and dependencies',
771
- inputSchema: {
772
- projectId: projectIdSchema,
773
- },
774
- }, async (args) => {
775
- try {
776
- const sm = await getSkillsMgr(args.projectId);
777
- const cm = await getConfigMgr(args.projectId);
778
- const rbConfig = await cm.loadConfig();
779
- const validation = await sm.validateSkills(rbConfig);
780
- return {
781
- content: [
782
- {
783
- type: 'text',
784
- text: JSON.stringify({
785
- success: true,
786
- valid: validation.valid,
787
- errors: validation.errors,
788
- warnings: validation.warnings,
789
- conflicts: validation.conflicts,
790
- enabledCount: rbConfig.skills?.enabled?.length || 0,
791
- }),
792
- },
793
- ],
794
- };
795
- }
796
- catch (error) {
797
- return {
798
- content: [
799
- {
800
- type: 'text',
801
- text: JSON.stringify({
802
- success: false,
803
- error: error instanceof Error ? error.message : 'Unknown error',
804
- }),
805
- },
806
- ],
807
- };
808
- }
809
- });
810
- // ============================================
811
- // Memory System Functions (v3.0)
812
- // ============================================
813
- // Conditionally initialize MemoryManager (single-project mode only;
814
- // in workspace mode each worker manages its own memory)
815
- let memoryManager = null;
816
- let bgIndexer = null;
817
- let autoCaptureEnabled = false;
818
- if (!isWorkspaceMode) {
819
- const rulebookConfig = await configManager.loadConfig();
820
- if (rulebookConfig.memory?.enabled) {
821
- try {
822
- const { createMemoryManager } = await import('../memory/memory-manager.js');
823
- const memoryDbPath = join(projectRoot, rulebookConfig.memory.dbPath ?? '.rulebook/memory/memory.db');
824
- console.error(`[rulebook-mcp] Memory DB: ${memoryDbPath}`);
825
- memoryManager = createMemoryManager(projectRoot, rulebookConfig.memory);
826
- autoCaptureEnabled = rulebookConfig.memory.autoCapture !== false;
827
- // Boot Background Indexer only if memory is enabled (opt-in to save resources)
828
- const indexerEnabled = rulebookConfig.memory?.enabled === true;
829
- if (indexerEnabled) {
830
- bgIndexer = new BackgroundIndexer(memoryManager, projectRoot, {
831
- enabled: true,
832
- ...rulebookConfig.indexer,
833
- });
834
- setTimeout(() => {
835
- try {
836
- bgIndexer?.start();
837
- }
838
- catch (e) {
839
- console.error('[rulebook-mcp] BackgroundIndexer start failed:', e);
840
- }
841
- }, 5000);
842
- }
843
- global.__indexerStatus = () => bgIndexer?.getStatus();
844
- }
845
- catch (e) {
846
- console.warn('[rulebook-mcp] Failed to boot Memory/Indexer:', e);
847
- }
848
- }
849
- }
850
- // --- Graceful shutdown for both modes ---
851
- // Handles SIGINT (Ctrl+C), SIGTERM (parent exit), SIGHUP (terminal close),
852
- // and stdin close (parent process died without signaling).
853
- let isShuttingDown = false;
854
- async function gracefulShutdown(reason) {
855
- if (isShuttingDown)
856
- return; // Prevent double-shutdown races
857
- isShuttingDown = true;
858
- console.error(`[rulebook-mcp] Shutting down (${reason})...`);
859
- try {
860
- if (bgIndexer)
861
- bgIndexer.stop();
862
- if (workspaceManager) {
863
- await workspaceManager.shutdownAll();
864
- }
865
- if (memoryManager)
866
- await memoryManager.close();
867
- releasePidLock(pidFilePath);
868
- }
869
- catch (e) {
870
- console.error('[rulebook-mcp] Error during shutdown:', e);
871
- }
872
- process.exit(0);
873
- }
874
- process.on('SIGINT', () => gracefulShutdown('SIGINT'));
875
- process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
876
- process.on('SIGHUP', () => gracefulShutdown('SIGHUP'));
877
- // Detect parent process exit: when the MCP client (e.g. Claude Code) dies,
878
- // stdin closes. Without this, the server becomes an orphan that leaks memory.
879
- process.stdin.on('end', () => gracefulShutdown('stdin closed'));
880
- process.stdin.on('close', () => gracefulShutdown('stdin closed'));
881
- // Safety net: if stdin becomes unreadable but doesn't emit 'end'/'close'
882
- // (can happen on Windows), poll stdin.readable every 30s.
883
- const STDIN_POLL_INTERVAL_MS = 30_000;
884
- const stdinPollTimer = setInterval(() => {
885
- if (process.stdin.destroyed || !process.stdin.readable) {
886
- clearInterval(stdinPollTimer);
887
- gracefulShutdown('stdin unreadable');
888
- }
889
- }, STDIN_POLL_INTERVAL_MS);
890
- stdinPollTimer.unref(); // Don't keep the process alive just for this timer
891
- /**
892
- * Auto-capture: save tool interactions to memory in the background.
893
- * Fire-and-forget — never blocks or fails the original tool call.
894
- * Has its own 2s timeout to prevent hanging the event loop.
895
- *
896
- * The dynamic import is cached after the first call to avoid repeated
897
- * module loading overhead on every tool invocation.
898
- */
899
- const AUTO_CAPTURE_TIMEOUT_MS = 2000;
900
- let _captureFromToolCall = null;
901
- async function autoCapture(toolName, args, resultText) {
902
- if (!memoryManager || !autoCaptureEnabled)
903
- return;
904
- try {
905
- await withTimeout((async () => {
906
- if (!_captureFromToolCall) {
907
- const mod = await import('../memory/memory-hooks.js');
908
- _captureFromToolCall = mod.captureFromToolCall;
909
- }
910
- const captured = _captureFromToolCall(toolName, args, resultText);
911
- if (!captured)
912
- return;
913
- await memoryManager.saveMemory({
914
- type: captured.type,
915
- title: captured.title,
916
- content: captured.content,
917
- tags: captured.tags,
918
- });
919
- })(), AUTO_CAPTURE_TIMEOUT_MS, `autoCapture(${toolName})`);
920
- }
921
- catch {
922
- // Never fail the original tool call — timeout or error is silently dropped
923
- }
924
- }
925
- function memoryNotEnabled() {
926
- return {
927
- content: [
928
- {
929
- type: 'text',
930
- text: JSON.stringify({
931
- success: false,
932
- error: 'Memory system is not enabled. Set memory.enabled=true in .rulebook',
933
- }),
934
- },
935
- ],
936
- };
937
- }
938
- // Register tool: rulebook_memory_search
939
- server.registerTool('rulebook_memory_search', {
940
- title: 'Search Memories',
941
- description: 'Search persistent memories using hybrid BM25+vector search',
942
- inputSchema: {
943
- query: z.string().describe('Search query'),
944
- limit: z.number().optional().describe('Max results (default 20)'),
945
- mode: z.enum(['bm25', 'vector', 'hybrid']).optional().describe('Search mode'),
946
- type: z.string().optional().describe('Filter by memory type'),
947
- projectId: projectIdSchema,
948
- },
949
- }, async (args) => {
950
- const mm = await getMemMgr(args.projectId);
951
- if (!mm)
952
- return memoryNotEnabled();
953
- try {
954
- const results = await mm.searchMemories({
955
- query: args.query,
956
- limit: args.limit,
957
- mode: args.mode,
958
- type: args.type,
959
- });
960
- return {
961
- content: [
962
- {
963
- type: 'text',
964
- text: JSON.stringify({ success: true, results, total: results.length }),
965
- },
966
- ],
967
- };
968
- }
969
- catch (error) {
970
- return {
971
- content: [
972
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
973
- ],
974
- };
975
- }
976
- });
977
- // Register tool: rulebook_memory_timeline
978
- server.registerTool('rulebook_memory_timeline', {
979
- title: 'Memory Timeline',
980
- description: 'Get chronological context around a specific memory',
981
- inputSchema: {
982
- memoryId: z.string().describe('Memory ID to anchor timeline'),
983
- window: z.number().optional().describe('Number of memories before/after (default 5)'),
984
- projectId: projectIdSchema,
985
- },
986
- }, async (args) => {
987
- const mm = await getMemMgr(args.projectId);
988
- if (!mm)
989
- return memoryNotEnabled();
990
- try {
991
- const timeline = await mm.getTimeline(args.memoryId, args.window);
992
- return {
993
- content: [{ type: 'text', text: JSON.stringify({ success: true, timeline }) }],
994
- };
995
- }
996
- catch (error) {
997
- return {
998
- content: [
999
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1000
- ],
1001
- };
1002
- }
1003
- });
1004
- // Register tool: rulebook_memory_get
1005
- server.registerTool('rulebook_memory_get', {
1006
- title: 'Get Memory Details',
1007
- description: 'Get full details for specific memory IDs',
1008
- inputSchema: {
1009
- ids: z.array(z.string()).describe('Memory IDs to fetch'),
1010
- projectId: projectIdSchema,
1011
- },
1012
- }, async (args) => {
1013
- const mm = await getMemMgr(args.projectId);
1014
- if (!mm)
1015
- return memoryNotEnabled();
1016
- try {
1017
- const memories = await mm.getFullDetails(args.ids);
1018
- return {
1019
- content: [{ type: 'text', text: JSON.stringify({ success: true, memories }) }],
1020
- };
1021
- }
1022
- catch (error) {
1023
- return {
1024
- content: [
1025
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1026
- ],
1027
- };
1028
- }
1029
- });
1030
- // Register tool: rulebook_memory_save
1031
- server.registerTool('rulebook_memory_save', {
1032
- title: 'Save Memory',
1033
- description: 'Save a new memory manually',
1034
- inputSchema: {
1035
- type: z
1036
- .string()
1037
- .describe('Memory type (bugfix, feature, refactor, decision, discovery, change, observation)'),
1038
- title: z.string().describe('Memory title'),
1039
- content: z.string().describe('Memory content'),
1040
- tags: z.array(z.string()).optional().describe('Tags'),
1041
- projectId: projectIdSchema,
1042
- },
1043
- }, async (args) => {
1044
- const mm = await getMemMgr(args.projectId);
1045
- if (!mm)
1046
- return memoryNotEnabled();
1047
- try {
1048
- const memory = await mm.saveMemory({
1049
- type: args.type,
1050
- title: args.title,
1051
- content: args.content,
1052
- tags: args.tags,
1053
- });
1054
- return {
1055
- content: [
1056
- {
1057
- type: 'text',
1058
- text: JSON.stringify({
1059
- success: true,
1060
- memory: { id: memory.id, type: memory.type, title: memory.title },
1061
- }),
1062
- },
1063
- ],
1064
- };
1065
- }
1066
- catch (error) {
1067
- return {
1068
- content: [
1069
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1070
- ],
1071
- };
1072
- }
1073
- });
1074
- // Register tool: rulebook_memory_stats
1075
- server.registerTool('rulebook_memory_stats', {
1076
- title: 'Memory Statistics',
1077
- description: 'Get memory database statistics',
1078
- inputSchema: {
1079
- projectId: projectIdSchema,
1080
- },
1081
- }, async (args) => {
1082
- const mm = await getMemMgr(args.projectId);
1083
- if (!mm)
1084
- return memoryNotEnabled();
1085
- try {
1086
- const stats = await mm.getStats();
1087
- return {
1088
- content: [{ type: 'text', text: JSON.stringify({ success: true, stats }) }],
1089
- };
1090
- }
1091
- catch (error) {
1092
- return {
1093
- content: [
1094
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1095
- ],
1096
- };
1097
- }
1098
- });
1099
- // Register tool: rulebook_memory_cleanup
1100
- server.registerTool('rulebook_memory_cleanup', {
1101
- title: 'Memory Cleanup',
1102
- description: 'Force memory eviction and cleanup',
1103
- inputSchema: {
1104
- force: z.boolean().optional().describe('Force cleanup regardless of size'),
1105
- projectId: projectIdSchema,
1106
- },
1107
- }, async (args) => {
1108
- const mm = await getMemMgr(args.projectId);
1109
- if (!mm)
1110
- return memoryNotEnabled();
1111
- try {
1112
- const result = await mm.cleanup(args.force ?? false);
1113
- return {
1114
- content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }) }],
1115
- };
1116
- }
1117
- catch (error) {
1118
- return {
1119
- content: [
1120
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1121
- ],
1122
- };
1123
- }
1124
- });
1125
- // --- Background Indexer Tools ---
1126
- // Register tool: rulebook_codebase_search
1127
- server.registerTool('rulebook_codebase_search', {
1128
- title: 'Codebase Semantic Search',
1129
- description: 'Search the entire project semantically (via AST chunks and paragraphs)',
1130
- inputSchema: {
1131
- query: z.string().describe('The code or concept you are looking for'),
1132
- limit: z.number().optional().describe('Result limit (default 10)'),
1133
- },
1134
- }, async (args) => {
1135
- if (!memoryManager)
1136
- return memoryNotEnabled();
1137
- try {
1138
- const results = await memoryManager.searchMemories({
1139
- query: args.query,
1140
- limit: args.limit ?? 10,
1141
- mode: 'hybrid', // Force hybrid search for best code-chunk matching
1142
- });
1143
- // Filter out normal memories, keep only code nodes
1144
- const codeResults = results.filter((r) => r.id.startsWith('__code__'));
1145
- return {
1146
- content: [
1147
- { type: 'text', text: JSON.stringify({ success: true, results: codeResults }) },
1148
- ],
1149
- };
1150
- }
1151
- catch (error) {
1152
- return {
1153
- content: [
1154
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1155
- ],
1156
- };
1157
- }
1158
- });
1159
- // Register tool: rulebook_codebase_graph
1160
- server.registerTool('rulebook_codebase_graph', {
1161
- title: 'Codebase Graph Explorer',
1162
- description: 'Find relationships (imports, exports) of a specific code node or file',
1163
- inputSchema: {
1164
- filePath: z.string().describe('The strict file path to query (e.g. src/core/app.ts)'),
1165
- },
1166
- }, async (args) => {
1167
- if (!memoryManager)
1168
- return memoryNotEnabled();
1169
- try {
1170
- // Since V1 has limited Graph search implementation in memory-search,
1171
- // we'll return a placeholder indicating the edge relations.
1172
- // In a real implementation we would call a memoryManager.getGraphAdjacent(args.filePath)
1173
- return {
1174
- content: [
1175
- {
1176
- type: 'text',
1177
- text: JSON.stringify({
1178
- success: true,
1179
- message: `Graph query for ${args.filePath} accepted. (Note: Graph deep-search pending V2 implementation, use codebase_search for now.)`,
1180
- filePath: args.filePath,
1181
- }),
1182
- },
1183
- ],
1184
- };
1185
- }
1186
- catch (error) {
1187
- return {
1188
- content: [
1189
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1190
- ],
1191
- };
1192
- }
1193
- });
1194
- // Register tool: rulebook_indexer_status
1195
- server.registerTool('rulebook_indexer_status', {
1196
- title: 'Background Indexer Status',
1197
- description: 'Get the status of the local autonomous filesystem indexer',
1198
- inputSchema: {},
1199
- }, async () => {
1200
- try {
1201
- // Because the BackgroundIndexer runs asynchronously, we fetch its global state
1202
- // assuming it was attached to the server context during boot.
1203
- const status = global.__indexerStatus
1204
- ? global.__indexerStatus()
1205
- : { running: false, error: 'Indexer not attached to global context' };
1206
- return {
1207
- content: [{ type: 'text', text: JSON.stringify({ success: true, status }) }],
1208
- };
1209
- }
1210
- catch (error) {
1211
- return {
1212
- content: [
1213
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1214
- ],
1215
- };
1216
- }
1217
- });
1218
- // ============================================
1219
- // Workspace Tools (v4.2 — workspace mode only)
1220
- // ============================================
1221
- if (workspaceManager) {
1222
- // Register tool: rulebook_workspace_list
1223
- server.registerTool('rulebook_workspace_list', {
1224
- title: 'List Workspace Projects',
1225
- description: 'List all projects in the current workspace',
1226
- inputSchema: {},
1227
- }, async () => {
1228
- const projects = workspaceManager.getProjects();
1229
- const activeIds = workspaceManager.getActiveWorkerIds();
1230
- return {
1231
- content: [
1232
- {
1233
- type: 'text',
1234
- text: JSON.stringify({
1235
- success: true,
1236
- workspace: workspaceManager.getConfig().name,
1237
- defaultProject: workspaceManager.getDefaultProjectId(),
1238
- projects: projects.map((p) => ({
1239
- name: p.name,
1240
- path: p.path,
1241
- workerActive: activeIds.includes(p.name),
1242
- })),
1243
- count: projects.length,
1244
- }),
1245
- },
1246
- ],
1247
- };
1248
- });
1249
- // Register tool: rulebook_workspace_status
1250
- server.registerTool('rulebook_workspace_status', {
1251
- title: 'Workspace Status',
1252
- description: 'Get detailed status of all workspace projects (workers, tasks, memory)',
1253
- inputSchema: {},
1254
- }, async () => {
1255
- try {
1256
- const status = await workspaceManager.getStatus();
1257
- return {
1258
- content: [{ type: 'text', text: JSON.stringify({ success: true, ...status }) }],
1259
- };
1260
- }
1261
- catch (error) {
1262
- return {
1263
- content: [
1264
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1265
- ],
1266
- };
1267
- }
1268
- });
1269
- // Register tool: rulebook_workspace_search
1270
- server.registerTool('rulebook_workspace_search', {
1271
- title: 'Cross-Project Memory Search',
1272
- description: 'Search memories across all projects in the workspace',
1273
- inputSchema: {
1274
- query: z.string().describe('Search query'),
1275
- limit: z.number().optional().describe('Max results per project (default 10)'),
1276
- },
1277
- }, async (args) => {
1278
- try {
1279
- const results = await workspaceManager.searchMemoryAcrossProjects(args.query, {
1280
- limit: args.limit,
1281
- });
1282
- return {
1283
- content: [
1284
- {
1285
- type: 'text',
1286
- text: JSON.stringify({
1287
- success: true,
1288
- results,
1289
- projectsSearched: results.length,
1290
- }),
1291
- },
1292
- ],
1293
- };
1294
- }
1295
- catch (error) {
1296
- return {
1297
- content: [
1298
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1299
- ],
1300
- };
1301
- }
1302
- });
1303
- // Register tool: rulebook_workspace_tasks
1304
- server.registerTool('rulebook_workspace_tasks', {
1305
- title: 'List Tasks Across Projects',
1306
- description: 'List tasks from all workspace projects',
1307
- inputSchema: {
1308
- status: z
1309
- .enum(['pending', 'in-progress', 'completed', 'blocked'])
1310
- .optional()
1311
- .describe('Filter by status'),
1312
- },
1313
- }, async (args) => {
1314
- try {
1315
- const allTasks = [];
1316
- for (const project of workspaceManager.getProjects()) {
1317
- try {
1318
- const tm = await getTaskMgr(project.name);
1319
- const tasks = await tm.listTasks(false);
1320
- const filtered = args.status ? tasks.filter((t) => t.status === args.status) : tasks;
1321
- if (filtered.length > 0) {
1322
- allTasks.push({
1323
- project: project.name,
1324
- tasks: filtered.map((t) => ({
1325
- id: t.id,
1326
- title: t.title,
1327
- status: t.status,
1328
- })),
1329
- });
1330
- }
1331
- }
1332
- catch {
1333
- // Skip projects that fail
1334
- }
1335
- }
1336
- return {
1337
- content: [
1338
- {
1339
- type: 'text',
1340
- text: JSON.stringify({
1341
- success: true,
1342
- projects: allTasks,
1343
- totalTasks: allTasks.reduce((sum, p) => sum + p.tasks.length, 0),
1344
- }),
1345
- },
1346
- ],
1347
- };
1348
- }
1349
- catch (error) {
1350
- return {
1351
- content: [
1352
- { type: 'text', text: JSON.stringify({ success: false, error: String(error) }) },
1353
- ],
1354
- };
1355
- }
1356
- });
1357
- }
1358
- // ============================================
1359
- // Context Intelligence Layer Tools (v4.4)
1360
- // ============================================
1361
- // Register tool: rulebook_decision_create
1362
- server.registerTool('rulebook_decision_create', {
1363
- title: 'Create Decision Record',
1364
- description: 'Create a new architectural decision record (ADR)',
1365
- inputSchema: {
1366
- title: z.string().describe('Decision title'),
1367
- context: z.string().optional().describe('Context and problem statement'),
1368
- decision: z.string().optional().describe('The decision made'),
1369
- alternatives: z.array(z.string()).optional().describe('Alternatives considered'),
1370
- consequences: z.string().optional().describe('Consequences and tradeoffs'),
1371
- relatedTasks: z.array(z.string()).optional().describe('Related task IDs'),
1372
- projectId: projectIdSchema,
1373
- },
1374
- }, async (args) => {
1375
- try {
1376
- const root = args.projectId && workspaceManager
1377
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1378
- : projectRoot;
1379
- const { DecisionManager } = await import('../core/tasks/decision-manager.js');
1380
- const dm = new DecisionManager(root);
1381
- const decision = await dm.create(args.title, {
1382
- context: args.context,
1383
- decision: args.decision,
1384
- alternatives: args.alternatives,
1385
- consequences: args.consequences,
1386
- relatedTasks: args.relatedTasks,
1387
- });
1388
- return {
1389
- content: [
1390
- {
1391
- type: 'text',
1392
- text: JSON.stringify({ success: true, decision }),
1393
- },
1394
- ],
1395
- };
1396
- }
1397
- catch (error) {
1398
- return {
1399
- content: [
1400
- {
1401
- type: 'text',
1402
- text: JSON.stringify({
1403
- success: false,
1404
- error: error instanceof Error ? error.message : String(error),
1405
- }),
1406
- },
1407
- ],
1408
- };
1409
- }
1410
- });
1411
- // Register tool: rulebook_decision_list
1412
- server.registerTool('rulebook_decision_list', {
1413
- title: 'List Decision Records',
1414
- description: 'List all architectural decision records',
1415
- inputSchema: {
1416
- status: z
1417
- .string()
1418
- .optional()
1419
- .describe('Filter by status (proposed, accepted, rejected, superseded, deprecated)'),
1420
- projectId: projectIdSchema,
1421
- },
1422
- }, async (args) => {
1423
- try {
1424
- const root = args.projectId && workspaceManager
1425
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1426
- : projectRoot;
1427
- const { DecisionManager } = await import('../core/tasks/decision-manager.js');
1428
- const dm = new DecisionManager(root);
1429
- const decisions = await dm.list(args.status);
1430
- return {
1431
- content: [
1432
- {
1433
- type: 'text',
1434
- text: JSON.stringify({ success: true, decisions, count: decisions.length }),
1435
- },
1436
- ],
1437
- };
1438
- }
1439
- catch (error) {
1440
- return {
1441
- content: [
1442
- {
1443
- type: 'text',
1444
- text: JSON.stringify({
1445
- success: false,
1446
- error: error instanceof Error ? error.message : String(error),
1447
- }),
1448
- },
1449
- ],
1450
- };
1451
- }
1452
- });
1453
- // Register tool: rulebook_decision_show
1454
- server.registerTool('rulebook_decision_show', {
1455
- title: 'Show Decision Record',
1456
- description: 'Show full details of a decision record',
1457
- inputSchema: {
1458
- id: z.number().describe('Decision ID'),
1459
- projectId: projectIdSchema,
1460
- },
1461
- }, async (args) => {
1462
- try {
1463
- const root = args.projectId && workspaceManager
1464
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1465
- : projectRoot;
1466
- const { DecisionManager } = await import('../core/tasks/decision-manager.js');
1467
- const dm = new DecisionManager(root);
1468
- const result = await dm.show(args.id);
1469
- if (!result) {
1470
- return {
1471
- content: [
1472
- {
1473
- type: 'text',
1474
- text: JSON.stringify({ success: false, error: `Decision ${args.id} not found` }),
1475
- },
1476
- ],
1477
- };
1478
- }
1479
- return {
1480
- content: [
1481
- {
1482
- type: 'text',
1483
- text: JSON.stringify({
1484
- success: true,
1485
- decision: result.decision,
1486
- content: result.content,
1487
- }),
1488
- },
1489
- ],
1490
- };
1491
- }
1492
- catch (error) {
1493
- return {
1494
- content: [
1495
- {
1496
- type: 'text',
1497
- text: JSON.stringify({
1498
- success: false,
1499
- error: error instanceof Error ? error.message : String(error),
1500
- }),
1501
- },
1502
- ],
1503
- };
1504
- }
1505
- });
1506
- // Register tool: rulebook_decision_update
1507
- server.registerTool('rulebook_decision_update', {
1508
- title: 'Update Decision Record',
1509
- description: 'Update an existing architectural decision record',
1510
- inputSchema: {
1511
- id: z.number().describe('Decision ID to update'),
1512
- status: z
1513
- .string()
1514
- .optional()
1515
- .describe('New status (proposed, accepted, rejected, superseded, deprecated)'),
1516
- context: z.string().optional().describe('Updated context'),
1517
- decision: z.string().optional().describe('Updated decision text'),
1518
- projectId: projectIdSchema,
1519
- },
1520
- }, async (args) => {
1521
- try {
1522
- const root = args.projectId && workspaceManager
1523
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1524
- : projectRoot;
1525
- const { DecisionManager } = await import('../core/tasks/decision-manager.js');
1526
- const dm = new DecisionManager(root);
1527
- const updated = await dm.update(args.id, {
1528
- status: args.status,
1529
- context: args.context,
1530
- decision: args.decision,
1531
- });
1532
- if (!updated) {
1533
- return {
1534
- content: [
1535
- {
1536
- type: 'text',
1537
- text: JSON.stringify({ success: false, error: `Decision ${args.id} not found` }),
1538
- },
1539
- ],
1540
- };
1541
- }
1542
- return {
1543
- content: [
1544
- {
1545
- type: 'text',
1546
- text: JSON.stringify({ success: true, decision: updated }),
1547
- },
1548
- ],
1549
- };
1550
- }
1551
- catch (error) {
1552
- return {
1553
- content: [
1554
- {
1555
- type: 'text',
1556
- text: JSON.stringify({
1557
- success: false,
1558
- error: error instanceof Error ? error.message : String(error),
1559
- }),
1560
- },
1561
- ],
1562
- };
1563
- }
1564
- });
1565
- // Register tool: rulebook_knowledge_add
1566
- server.registerTool('rulebook_knowledge_add', {
1567
- title: 'Add Knowledge Entry',
1568
- description: 'Add a new pattern or anti-pattern to the project knowledge base',
1569
- inputSchema: {
1570
- type: z.string().describe('Knowledge type: "pattern" or "anti-pattern"'),
1571
- title: z.string().describe('Entry title'),
1572
- category: z.string().describe('Category (e.g. code, architecture, testing, security)'),
1573
- description: z.string().describe('Description of the pattern'),
1574
- example: z.string().optional().describe('Code or usage example'),
1575
- whenToUse: z.string().optional().describe('When to use this pattern'),
1576
- whenNotToUse: z.string().optional().describe('When NOT to use this pattern'),
1577
- tags: z.array(z.string()).optional().describe('Tags for search'),
1578
- projectId: projectIdSchema,
1579
- },
1580
- }, async (args) => {
1581
- try {
1582
- const root = args.projectId && workspaceManager
1583
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1584
- : projectRoot;
1585
- const { KnowledgeManager } = await import('../core/tasks/knowledge-manager.js');
1586
- const km = new KnowledgeManager(root);
1587
- const entry = await km.add(args.type, args.title, {
1588
- category: args.category,
1589
- description: args.description,
1590
- example: args.example,
1591
- whenToUse: args.whenToUse,
1592
- whenNotToUse: args.whenNotToUse,
1593
- tags: args.tags,
1594
- });
1595
- return {
1596
- content: [
1597
- {
1598
- type: 'text',
1599
- text: JSON.stringify({ success: true, entry }),
1600
- },
1601
- ],
1602
- };
1603
- }
1604
- catch (error) {
1605
- return {
1606
- content: [
1607
- {
1608
- type: 'text',
1609
- text: JSON.stringify({
1610
- success: false,
1611
- error: error instanceof Error ? error.message : String(error),
1612
- }),
1613
- },
1614
- ],
1615
- };
1616
- }
1617
- });
1618
- // Register tool: rulebook_knowledge_list
1619
- server.registerTool('rulebook_knowledge_list', {
1620
- title: 'List Knowledge Entries',
1621
- description: 'List patterns and anti-patterns in the project knowledge base',
1622
- inputSchema: {
1623
- type: z.string().optional().describe('Filter by type: "pattern" or "anti-pattern"'),
1624
- category: z.string().optional().describe('Filter by category'),
1625
- projectId: projectIdSchema,
1626
- },
1627
- }, async (args) => {
1628
- try {
1629
- const root = args.projectId && workspaceManager
1630
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1631
- : projectRoot;
1632
- const { KnowledgeManager } = await import('../core/tasks/knowledge-manager.js');
1633
- const km = new KnowledgeManager(root);
1634
- const entries = await km.list(args.type, args.category);
1635
- return {
1636
- content: [
1637
- {
1638
- type: 'text',
1639
- text: JSON.stringify({ success: true, entries, count: entries.length }),
1640
- },
1641
- ],
1642
- };
1643
- }
1644
- catch (error) {
1645
- return {
1646
- content: [
1647
- {
1648
- type: 'text',
1649
- text: JSON.stringify({
1650
- success: false,
1651
- error: error instanceof Error ? error.message : String(error),
1652
- }),
1653
- },
1654
- ],
1655
- };
1656
- }
269
+ const server = new McpServer({
270
+ name: 'rulebook-task-management',
271
+ version: '5.2.0',
1657
272
  });
1658
- // Register tool: rulebook_knowledge_show
1659
- server.registerTool('rulebook_knowledge_show', {
1660
- title: 'Show Knowledge Entry',
1661
- description: 'Show full details of a knowledge entry',
1662
- inputSchema: {
1663
- id: z.string().describe('Knowledge entry ID (slug)'),
1664
- projectId: projectIdSchema,
1665
- },
1666
- }, async (args) => {
1667
- try {
1668
- const root = args.projectId && workspaceManager
1669
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1670
- : projectRoot;
1671
- const { KnowledgeManager } = await import('../core/tasks/knowledge-manager.js');
1672
- const km = new KnowledgeManager(root);
1673
- const result = await km.show(args.id);
1674
- if (!result) {
1675
- return {
1676
- content: [
1677
- {
1678
- type: 'text',
1679
- text: JSON.stringify({
1680
- success: false,
1681
- error: `Knowledge entry "${args.id}" not found`,
1682
- }),
1683
- },
1684
- ],
1685
- };
273
+ // --- Wrap all tool handlers with a timeout guard ---
274
+ const originalRegisterTool = server.registerTool.bind(server);
275
+ server.registerTool = ((name, config, handler) => {
276
+ const wrappedHandler = async (...handlerArgs) => {
277
+ try {
278
+ return await withTimeout(handler(...handlerArgs), MCP_TOOL_TIMEOUT_MS, name);
1686
279
  }
1687
- return {
1688
- content: [
1689
- {
1690
- type: 'text',
1691
- text: JSON.stringify({ success: true, entry: result.entry, content: result.content }),
1692
- },
1693
- ],
1694
- };
1695
- }
1696
- catch (error) {
1697
- return {
1698
- content: [
1699
- {
1700
- type: 'text',
1701
- text: JSON.stringify({
1702
- success: false,
1703
- error: error instanceof Error ? error.message : String(error),
1704
- }),
1705
- },
1706
- ],
1707
- };
1708
- }
1709
- });
1710
- // Register tool: rulebook_learn_capture
1711
- server.registerTool('rulebook_learn_capture', {
1712
- title: 'Capture Learning',
1713
- description: 'Capture a learning or insight for future reference',
1714
- inputSchema: {
1715
- title: z.string().describe('Brief title for the learning'),
1716
- content: z.string().describe('Full content of the learning'),
1717
- tags: z.array(z.string()).optional().describe('Tags for search'),
1718
- relatedTask: z.string().optional().describe('Related task ID'),
1719
- projectId: projectIdSchema,
1720
- },
1721
- }, async (args) => {
1722
- try {
1723
- const root = args.projectId && workspaceManager
1724
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1725
- : projectRoot;
1726
- const { LearnManager } = await import('../core/tasks/learn-manager.js');
1727
- const lm = new LearnManager(root);
1728
- const learning = await lm.capture(args.title, args.content, {
1729
- tags: args.tags,
1730
- relatedTask: args.relatedTask,
1731
- });
1732
- return {
1733
- content: [
1734
- {
1735
- type: 'text',
1736
- text: JSON.stringify({ success: true, learning }),
1737
- },
1738
- ],
1739
- };
1740
- }
1741
- catch (error) {
1742
- return {
1743
- content: [
1744
- {
1745
- type: 'text',
1746
- text: JSON.stringify({
1747
- success: false,
1748
- error: error instanceof Error ? error.message : String(error),
1749
- }),
1750
- },
1751
- ],
1752
- };
1753
- }
1754
- });
1755
- // Register tool: rulebook_learn_list
1756
- server.registerTool('rulebook_learn_list', {
1757
- title: 'List Learnings',
1758
- description: 'List captured learnings, newest first',
1759
- inputSchema: {
1760
- limit: z.number().optional().describe('Maximum number of learnings to return'),
1761
- projectId: projectIdSchema,
1762
- },
1763
- }, async (args) => {
1764
- try {
1765
- const root = args.projectId && workspaceManager
1766
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1767
- : projectRoot;
1768
- const { LearnManager } = await import('../core/tasks/learn-manager.js');
1769
- const lm = new LearnManager(root);
1770
- const learnings = await lm.list(args.limit);
1771
- return {
1772
- content: [
1773
- {
1774
- type: 'text',
1775
- text: JSON.stringify({ success: true, learnings, count: learnings.length }),
1776
- },
1777
- ],
1778
- };
1779
- }
1780
- catch (error) {
1781
- return {
1782
- content: [
1783
- {
1784
- type: 'text',
1785
- text: JSON.stringify({
1786
- success: false,
1787
- error: error instanceof Error ? error.message : String(error),
1788
- }),
1789
- },
1790
- ],
1791
- };
1792
- }
1793
- });
1794
- // Register tool: rulebook_learn_promote
1795
- server.registerTool('rulebook_learn_promote', {
1796
- title: 'Promote Learning',
1797
- description: 'Promote a learning to a knowledge entry or decision record',
1798
- inputSchema: {
1799
- id: z.string().describe('Learning ID to promote'),
1800
- target: z
1801
- .enum(['knowledge', 'decision'])
1802
- .describe('Promote to knowledge base or decision record'),
1803
- title: z.string().optional().describe('Override title for the promoted entry'),
1804
- projectId: projectIdSchema,
1805
- },
1806
- }, async (args) => {
1807
- try {
1808
- const root = args.projectId && workspaceManager
1809
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1810
- : projectRoot;
1811
- const { LearnManager } = await import('../core/tasks/learn-manager.js');
1812
- const lm = new LearnManager(root);
1813
- const result = await lm.promote(args.id, args.target, { title: args.title });
1814
- if (!result) {
280
+ catch (error) {
281
+ const msg = error instanceof Error ? error.message : String(error);
282
+ console.error(`[rulebook-mcp] ${name} error: ${msg}`);
1815
283
  return {
1816
284
  content: [
1817
285
  {
1818
286
  type: 'text',
1819
- text: JSON.stringify({ success: false, error: `Learning "${args.id}" not found` }),
287
+ text: JSON.stringify({ success: false, error: msg }),
1820
288
  },
1821
289
  ],
1822
290
  };
1823
291
  }
1824
- return {
1825
- content: [
1826
- {
1827
- type: 'text',
1828
- text: JSON.stringify({ success: true, promoted: result }),
1829
- },
1830
- ],
1831
- };
1832
- }
1833
- catch (error) {
1834
- return {
1835
- content: [
1836
- {
1837
- type: 'text',
1838
- text: JSON.stringify({
1839
- success: false,
1840
- error: error instanceof Error ? error.message : String(error),
1841
- }),
1842
- },
1843
- ],
1844
- };
1845
- }
292
+ };
293
+ return originalRegisterTool(name, config, wrappedHandler);
1846
294
  });
295
+ // Zod schema reused across tools for workspace project targeting
296
+ const projectIdSchema = z
297
+ .string()
298
+ .optional()
299
+ .describe('Project ID (workspace mode only, defaults to default project)');
300
+ // Shared context handed to each extracted domain tool module.
301
+ const ctx = {
302
+ projectRoot,
303
+ workspaceManager,
304
+ projectIdSchema,
305
+ getTaskMgr,
306
+ getConfigMgr,
307
+ getSkillsMgr,
308
+ };
309
+ registerTaskTools(server, ctx);
310
+ registerSkillTools(server, ctx);
311
+ registerWorkspaceTools(server, ctx);
312
+ registerDecisionTools(server, ctx);
313
+ registerKnowledgeTools(server, ctx);
314
+ registerLearnTools(server, ctx);
1847
315
  // ── v5.0 Tools: Session Management, Rules, Blockers ──────────────────
1848
316
  // Register tool: rulebook_session_start
1849
317
  server.registerTool('rulebook_session_start', {
@@ -1870,15 +338,6 @@ export async function startRulebookMcpServer() {
1870
338
  if (existsSync(plansPath)) {
1871
339
  result.plans = await readFile(plansPath, 'utf-8');
1872
340
  }
1873
- // Search relevant memories
1874
- if (args.query && memoryManager) {
1875
- const searchResults = await memoryManager.searchMemories({
1876
- query: args.query,
1877
- mode: 'hybrid',
1878
- limit: 5,
1879
- });
1880
- result.memories = searchResults;
1881
- }
1882
341
  return {
1883
342
  content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }) }],
1884
343
  };
@@ -1938,63 +397,13 @@ export async function startRulebookMcpServer() {
1938
397
  mkdirSync(dir, { recursive: true });
1939
398
  await writeFile(plansPath, newContent, 'utf-8');
1940
399
  }
1941
- // Also save to memory if available
1942
- if (memoryManager) {
1943
- await memoryManager.saveMemory({
1944
- type: 'observation',
1945
- title: `Session summary ${date}`,
1946
- content: args.summary,
1947
- tags: ['session', 'summary'],
1948
- });
1949
- }
1950
- return {
1951
- content: [
1952
- {
1953
- type: 'text',
1954
- text: JSON.stringify({ success: true, message: 'Session summary saved to PLANS.md' }),
1955
- },
1956
- ],
1957
- };
1958
- }
1959
- catch (error) {
1960
- return {
1961
- content: [
1962
- {
1963
- type: 'text',
1964
- text: JSON.stringify({
1965
- success: false,
1966
- error: error instanceof Error ? error.message : String(error),
1967
- }),
1968
- },
1969
- ],
1970
- };
1971
- }
1972
- });
1973
- // Register tool: rulebook_rules_list
1974
- server.registerTool('rulebook_rules_list', {
1975
- title: 'List Rules',
1976
- description: 'List canonical rules from .rulebook/rules/ AND path-scoped language rules from .claude/rules/. Each entry is classified by source (generated by rulebook vs user-authored).',
1977
- inputSchema: {
1978
- projectId: projectIdSchema,
1979
- },
1980
- }, async (args) => {
1981
- try {
1982
- const root = args.projectId && workspaceManager
1983
- ? (await workspaceManager.getWorker(args.projectId)).projectRoot
1984
- : projectRoot;
1985
- const { listRules } = await import('../core/rule-engine.js');
1986
- const { listRulesWithSource } = await import('../core/generators/rules-generator.js');
1987
- const canonical = await listRules(root);
1988
- const languageRules = await listRulesWithSource(root);
1989
400
  return {
1990
401
  content: [
1991
402
  {
1992
403
  type: 'text',
1993
404
  text: JSON.stringify({
1994
405
  success: true,
1995
- canonical,
1996
- languageRules,
1997
- count: canonical.length + languageRules.length,
406
+ message: 'Session summary saved to PLANS.md',
1998
407
  }),
1999
408
  },
2000
409
  ],
@@ -2014,6 +423,18 @@ export async function startRulebookMcpServer() {
2014
423
  };
2015
424
  }
2016
425
  });
426
+ registerRulesTools(server, ctx);
427
+ // Release the PID lock on shutdown so a restart can re-acquire it.
428
+ const releaseLock = () => releasePidLock(pidFilePath);
429
+ process.on('SIGINT', () => {
430
+ releaseLock();
431
+ process.exit(0);
432
+ });
433
+ process.on('SIGTERM', () => {
434
+ releaseLock();
435
+ process.exit(0);
436
+ });
437
+ process.on('exit', releaseLock);
2017
438
  const transport = new StdioServerTransport();
2018
439
  await server.connect(transport);
2019
440
  }