@hivehub/rulebook 5.8.2 → 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 (512) 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/cli/CLAUDE.md +102 -117
  188. package/templates/cli/_GENERIC_TEMPLATE.md +29 -29
  189. package/templates/commands/rulebook-decision-create.md +55 -55
  190. package/templates/commands/rulebook-decision-list.md +15 -15
  191. package/templates/commands/rulebook-knowledge-add.md +41 -41
  192. package/templates/commands/rulebook-knowledge-list.md +15 -15
  193. package/templates/commands/rulebook-learn-capture.md +1 -2
  194. package/templates/commands/rulebook-task-apply.md +67 -67
  195. package/templates/commands/rulebook-task-archive.md +94 -94
  196. package/templates/commands/rulebook-task-create.md +93 -93
  197. package/templates/commands/rulebook-task-list.md +42 -42
  198. package/templates/commands/rulebook-task-show.md +52 -52
  199. package/templates/commands/rulebook-task-validate.md +53 -53
  200. package/templates/compact-context/_default.md +23 -23
  201. package/templates/compact-context/cpp.md +26 -26
  202. package/templates/compact-context/go.md +26 -26
  203. package/templates/compact-context/python.md +26 -26
  204. package/templates/compact-context/rust.md +28 -28
  205. package/templates/compact-context/typescript.md +29 -29
  206. package/templates/core/AGENTS_LEAN.md +4 -9
  207. package/templates/core/AGENTS_OVERRIDE.md +16 -16
  208. package/templates/core/AGENT_AUTOMATION.md +273 -296
  209. package/templates/core/CLAUDE_MD_v2.md +85 -90
  210. package/templates/core/DAG.md +304 -304
  211. package/templates/core/DECISIONS.md +38 -38
  212. package/templates/core/DOCUMENTATION_RULES.md +36 -36
  213. package/templates/core/KNOWLEDGE.md +49 -49
  214. package/templates/core/MULTI_AGENT.md +74 -74
  215. package/templates/core/PLANS.md +28 -28
  216. package/templates/core/QUALITY_ENFORCEMENT.md +68 -68
  217. package/templates/core/RULEBOOK.md +1936 -1947
  218. package/templates/core/TIER1_PROHIBITIONS.md +154 -154
  219. package/templates/core/TOKEN_OPTIMIZATION.md +49 -49
  220. package/templates/core/WORKSPACE.md +4 -8
  221. package/templates/git/CI_CD_PATTERNS.md +661 -661
  222. package/templates/git/GITHUB_ACTIONS.md +728 -728
  223. package/templates/git/GITLAB_CI.md +730 -730
  224. package/templates/git/GIT_WORKFLOW.md +1192 -1192
  225. package/templates/git/SECRETS_MANAGEMENT.md +585 -585
  226. package/templates/hooks/COMMIT_MSG.md +530 -530
  227. package/templates/hooks/POST_CHECKOUT.md +546 -546
  228. package/templates/hooks/PREPARE_COMMIT_MSG.md +619 -619
  229. package/templates/hooks/PRE_COMMIT.md +414 -414
  230. package/templates/hooks/PRE_PUSH.md +601 -601
  231. package/templates/hooks/enforce-pre-tool.sh +26 -9
  232. package/templates/hooks/update-check.ps1 +84 -84
  233. package/templates/hooks/update-check.sh +45 -21
  234. package/templates/languages/C.md +333 -333
  235. package/templates/languages/CPP.md +743 -743
  236. package/templates/languages/CSHARP.md +417 -417
  237. package/templates/languages/ELIXIR.md +454 -454
  238. package/templates/languages/ERLANG.md +361 -361
  239. package/templates/languages/GO.md +645 -645
  240. package/templates/languages/HASKELL.md +177 -177
  241. package/templates/languages/JAVA.md +607 -607
  242. package/templates/languages/JAVASCRIPT.md +631 -631
  243. package/templates/languages/JULIA.md +97 -97
  244. package/templates/languages/KOTLIN.md +511 -511
  245. package/templates/languages/LISP.md +100 -100
  246. package/templates/languages/LUA.md +74 -74
  247. package/templates/languages/OBJECTIVEC.md +90 -90
  248. package/templates/languages/PHP.md +416 -416
  249. package/templates/languages/PYTHON.md +682 -682
  250. package/templates/languages/RUBY.md +421 -421
  251. package/templates/languages/RUST.md +477 -477
  252. package/templates/languages/SAS.md +73 -73
  253. package/templates/languages/SCALA.md +348 -348
  254. package/templates/languages/SOLIDITY.md +580 -580
  255. package/templates/languages/SQL.md +137 -137
  256. package/templates/languages/SWIFT.md +466 -466
  257. package/templates/languages/TYPESCRIPT.md +591 -591
  258. package/templates/languages/ZIG.md +265 -265
  259. package/templates/modules/CONTEXT7.md +54 -54
  260. package/templates/modules/GITHUB_MCP.md +64 -64
  261. package/templates/modules/PLAYWRIGHT.md +90 -90
  262. package/templates/modules/RULEBOOK_MCP.md +208 -208
  263. package/templates/modules/SERENA.md +337 -337
  264. package/templates/modules/SUPABASE.md +223 -223
  265. package/templates/modules/SYNAP.md +69 -69
  266. package/templates/modules/VECTORIZER.md +63 -63
  267. package/templates/modules/sequential-thinking.md +42 -42
  268. package/templates/rules/consult-analysis-before-implementing.md +21 -23
  269. package/templates/rules/cpp.md +46 -46
  270. package/templates/rules/csharp.md +44 -44
  271. package/templates/rules/diagnostic-first.md +39 -39
  272. package/templates/rules/fail-twice-escalate.md +46 -46
  273. package/templates/rules/follow-task-sequence.md +36 -36
  274. package/templates/rules/git-safety.md +29 -29
  275. package/templates/rules/go.md +40 -40
  276. package/templates/rules/incremental-implementation.md +56 -56
  277. package/templates/rules/incremental-tests.md +29 -29
  278. package/templates/rules/java.md +43 -43
  279. package/templates/rules/javascript.md +39 -39
  280. package/templates/rules/knowledge-base-usage.md +41 -41
  281. package/templates/rules/multi-agent-teams.md +75 -75
  282. package/templates/rules/no-deferred.md +31 -31
  283. package/templates/rules/no-shortcuts.md +30 -30
  284. package/templates/rules/python.md +43 -43
  285. package/templates/rules/research-first.md +30 -30
  286. package/templates/rules/respect-handoff-trigger.md +41 -41
  287. package/templates/rules/rust.md +40 -40
  288. package/templates/rules/sequential-editing.md +21 -21
  289. package/templates/rules/session-workflow.md +24 -24
  290. package/templates/rules/task-decomposition.md +32 -32
  291. package/templates/rules/typescript.md +40 -40
  292. package/templates/skills/cli/claude/SKILL.md +42 -42
  293. package/templates/skills/core/agent-automation/SKILL.md +194 -194
  294. package/templates/skills/core/dag/SKILL.md +314 -314
  295. package/templates/skills/core/documentation-rules/SKILL.md +46 -46
  296. package/templates/skills/core/quality-enforcement/SKILL.md +78 -78
  297. package/templates/skills/core/rulebook/SKILL.md +176 -176
  298. package/templates/skills/core/rulebook-terse/SKILL.md +116 -116
  299. package/templates/skills/core/rulebook-terse-commit/SKILL.md +96 -96
  300. package/templates/skills/core/rulebook-terse-review/SKILL.md +112 -112
  301. package/templates/skills/dev/accessibility/SKILL.md +17 -17
  302. package/templates/skills/dev/analysis/SKILL.md +19 -19
  303. package/templates/skills/dev/api-design/SKILL.md +15 -15
  304. package/templates/skills/dev/architect/SKILL.md +17 -17
  305. package/templates/skills/dev/build-fix/SKILL.md +17 -17
  306. package/templates/skills/dev/db-design/SKILL.md +15 -15
  307. package/templates/skills/dev/debug/SKILL.md +16 -16
  308. package/templates/skills/dev/deploy/SKILL.md +17 -17
  309. package/templates/skills/dev/docs/SKILL.md +17 -17
  310. package/templates/skills/dev/handoff/SKILL.md +27 -27
  311. package/templates/skills/dev/migrate/SKILL.md +15 -15
  312. package/templates/skills/dev/perf/SKILL.md +17 -17
  313. package/templates/skills/dev/refactor/SKILL.md +17 -17
  314. package/templates/skills/dev/research/SKILL.md +14 -14
  315. package/templates/skills/dev/review/SKILL.md +18 -18
  316. package/templates/skills/dev/security-audit/SKILL.md +17 -17
  317. package/templates/skills/languages/c/SKILL.md +343 -343
  318. package/templates/skills/languages/cpp/SKILL.md +753 -753
  319. package/templates/skills/languages/csharp/SKILL.md +427 -427
  320. package/templates/skills/languages/elixir/SKILL.md +464 -464
  321. package/templates/skills/languages/erlang/SKILL.md +371 -371
  322. package/templates/skills/languages/go/SKILL.md +655 -655
  323. package/templates/skills/languages/haskell/SKILL.md +187 -187
  324. package/templates/skills/languages/java/SKILL.md +617 -617
  325. package/templates/skills/languages/javascript/SKILL.md +641 -641
  326. package/templates/skills/languages/julia/SKILL.md +107 -107
  327. package/templates/skills/languages/kotlin/SKILL.md +521 -521
  328. package/templates/skills/languages/lisp/SKILL.md +110 -110
  329. package/templates/skills/languages/lua/SKILL.md +84 -84
  330. package/templates/skills/languages/objectivec/SKILL.md +100 -100
  331. package/templates/skills/languages/php/SKILL.md +426 -426
  332. package/templates/skills/languages/python/SKILL.md +692 -692
  333. package/templates/skills/languages/ruby/SKILL.md +431 -431
  334. package/templates/skills/languages/rust/SKILL.md +487 -487
  335. package/templates/skills/languages/sas/SKILL.md +83 -83
  336. package/templates/skills/languages/scala/SKILL.md +358 -358
  337. package/templates/skills/languages/solidity/SKILL.md +590 -590
  338. package/templates/skills/languages/sql/SKILL.md +147 -147
  339. package/templates/skills/languages/swift/SKILL.md +476 -476
  340. package/templates/skills/languages/typescript/SKILL.md +302 -302
  341. package/templates/skills/languages/zig/SKILL.md +275 -275
  342. package/templates/skills/modules/context7/SKILL.md +64 -64
  343. package/templates/skills/modules/github-mcp/SKILL.md +74 -74
  344. package/templates/skills/modules/playwright/SKILL.md +100 -100
  345. package/templates/skills/modules/rulebook-mcp/SKILL.md +166 -166
  346. package/templates/skills/modules/serena/SKILL.md +347 -347
  347. package/templates/skills/modules/supabase/SKILL.md +233 -233
  348. package/templates/skills/modules/synap/SKILL.md +79 -79
  349. package/templates/skills/modules/vectorizer/SKILL.md +73 -73
  350. package/.claude/commands/analysis.md +0 -35
  351. package/.claude/commands/continue.md +0 -33
  352. package/.claude/commands/rulebook-decision-create.md +0 -55
  353. package/.claude/commands/rulebook-decision-list.md +0 -15
  354. package/.claude/commands/rulebook-knowledge-add.md +0 -41
  355. package/.claude/commands/rulebook-knowledge-list.md +0 -15
  356. package/.claude/commands/rulebook-learn-capture.md +0 -41
  357. package/.claude/commands/rulebook-learn-list.md +0 -13
  358. package/.claude/commands/rulebook-memory-save.md +0 -48
  359. package/.claude/commands/rulebook-memory-search.md +0 -47
  360. package/.claude/commands/rulebook-task-apply.md +0 -67
  361. package/.claude/commands/rulebook-task-archive.md +0 -94
  362. package/.claude/commands/rulebook-task-create.md +0 -93
  363. package/.claude/commands/rulebook-task-list.md +0 -42
  364. package/.claude/commands/rulebook-task-show.md +0 -52
  365. package/.claude/commands/rulebook-task-validate.md +0 -53
  366. package/.claude-plugin/marketplace.json +0 -28
  367. package/.claude-plugin/plugin.json +0 -8
  368. package/dist/agents/claude-code.d.ts +0 -69
  369. package/dist/agents/claude-code.d.ts.map +0 -1
  370. package/dist/agents/claude-code.js +0 -180
  371. package/dist/agents/claude-code.js.map +0 -1
  372. package/dist/agents/cursor-agent.d.ts +0 -184
  373. package/dist/agents/cursor-agent.d.ts.map +0 -1
  374. package/dist/agents/cursor-agent.js +0 -299
  375. package/dist/agents/cursor-agent.js.map +0 -1
  376. package/dist/agents/gemini-cli.d.ts +0 -69
  377. package/dist/agents/gemini-cli.d.ts.map +0 -1
  378. package/dist/agents/gemini-cli.js +0 -180
  379. package/dist/agents/gemini-cli.js.map +0 -1
  380. package/dist/cli/commands/memory.d.ts +0 -30
  381. package/dist/cli/commands/memory.d.ts.map +0 -1
  382. package/dist/cli/commands/memory.js +0 -259
  383. package/dist/cli/commands/memory.js.map +0 -1
  384. package/dist/core/console/cli-bridge.d.ts +0 -113
  385. package/dist/core/console/cli-bridge.d.ts.map +0 -1
  386. package/dist/core/console/cli-bridge.js +0 -1094
  387. package/dist/core/console/cli-bridge.js.map +0 -1
  388. package/dist/core/ide/multi-tool-generator.d.ts +0 -59
  389. package/dist/core/ide/multi-tool-generator.d.ts.map +0 -1
  390. package/dist/core/ide/multi-tool-generator.js +0 -157
  391. package/dist/core/ide/multi-tool-generator.js.map +0 -1
  392. package/dist/core/ide/opencode-generator.d.ts +0 -72
  393. package/dist/core/ide/opencode-generator.d.ts.map +0 -1
  394. package/dist/core/ide/opencode-generator.js +0 -450
  395. package/dist/core/ide/opencode-generator.js.map +0 -1
  396. package/dist/core/indexer/background-indexer.d.ts +0 -35
  397. package/dist/core/indexer/background-indexer.d.ts.map +0 -1
  398. package/dist/core/indexer/background-indexer.js +0 -267
  399. package/dist/core/indexer/background-indexer.js.map +0 -1
  400. package/dist/core/indexer/file-parser.d.ts +0 -28
  401. package/dist/core/indexer/file-parser.d.ts.map +0 -1
  402. package/dist/core/indexer/file-parser.js +0 -171
  403. package/dist/core/indexer/file-parser.js.map +0 -1
  404. package/dist/core/indexer/indexer-types.d.ts +0 -37
  405. package/dist/core/indexer/indexer-types.d.ts.map +0 -1
  406. package/dist/core/indexer/indexer-types.js +0 -8
  407. package/dist/core/indexer/indexer-types.js.map +0 -1
  408. package/dist/memory/file-search.d.ts +0 -43
  409. package/dist/memory/file-search.d.ts.map +0 -1
  410. package/dist/memory/file-search.js +0 -228
  411. package/dist/memory/file-search.js.map +0 -1
  412. package/dist/memory/file-store.d.ts +0 -99
  413. package/dist/memory/file-store.d.ts.map +0 -1
  414. package/dist/memory/file-store.js +0 -615
  415. package/dist/memory/file-store.js.map +0 -1
  416. package/dist/memory/legacy-migrator.d.ts +0 -27
  417. package/dist/memory/legacy-migrator.d.ts.map +0 -1
  418. package/dist/memory/legacy-migrator.js +0 -185
  419. package/dist/memory/legacy-migrator.js.map +0 -1
  420. package/dist/memory/memory-hooks.d.ts +0 -48
  421. package/dist/memory/memory-hooks.d.ts.map +0 -1
  422. package/dist/memory/memory-hooks.js +0 -248
  423. package/dist/memory/memory-hooks.js.map +0 -1
  424. package/dist/memory/memory-manager.d.ts +0 -65
  425. package/dist/memory/memory-manager.d.ts.map +0 -1
  426. package/dist/memory/memory-manager.js +0 -223
  427. package/dist/memory/memory-manager.js.map +0 -1
  428. package/dist/memory/memory-types.d.ts +0 -85
  429. package/dist/memory/memory-types.d.ts.map +0 -1
  430. package/dist/memory/memory-types.js +0 -7
  431. package/dist/memory/memory-types.js.map +0 -1
  432. package/templates/agents/accessibility-reviewer.md +0 -43
  433. package/templates/agents/api-designer.md +0 -42
  434. package/templates/agents/compiler/codegen-debugger.md +0 -34
  435. package/templates/agents/compiler/stdlib-engineer.md +0 -28
  436. package/templates/agents/compiler/test-coverage-guardian.md +0 -31
  437. package/templates/agents/context-intelligence.md +0 -50
  438. package/templates/agents/database-architect.md +0 -41
  439. package/templates/agents/devops-engineer.md +0 -42
  440. package/templates/agents/game-engine/cpp-core-expert.md +0 -35
  441. package/templates/agents/game-engine/render-engineer.md +0 -22
  442. package/templates/agents/game-engine/shader-engineer.md +0 -38
  443. package/templates/agents/game-engine/systems-integration.md +0 -43
  444. package/templates/agents/generic/code-reviewer.md +0 -41
  445. package/templates/agents/generic/docs-writer.md +0 -25
  446. package/templates/agents/generic/project-manager.md +0 -36
  447. package/templates/agents/generic/researcher.md +0 -34
  448. package/templates/agents/generic/test-engineer.md +0 -41
  449. package/templates/agents/i18n-engineer.md +0 -42
  450. package/templates/agents/migration-engineer.md +0 -42
  451. package/templates/agents/mobile/platform-specialist.md +0 -22
  452. package/templates/agents/mobile/ui-engineer.md +0 -22
  453. package/templates/agents/project-manager.md +0 -217
  454. package/templates/agents/refactoring-agent.md +0 -41
  455. package/templates/agents/ux-reviewer.md +0 -43
  456. package/templates/agents/web-app/api-designer.md +0 -22
  457. package/templates/agents/web-app/backend-engineer.md +0 -30
  458. package/templates/agents/web-app/database-engineer.md +0 -22
  459. package/templates/agents/web-app/frontend-engineer.md +0 -29
  460. package/templates/agents/web-app/security-reviewer.md +0 -32
  461. package/templates/cli/AIDER.md +0 -49
  462. package/templates/cli/AMAZON_Q.md +0 -25
  463. package/templates/cli/AUGGIE.md +0 -32
  464. package/templates/cli/CLINE.md +0 -99
  465. package/templates/cli/CODEBUDDY.md +0 -20
  466. package/templates/cli/CODEIUM.md +0 -20
  467. package/templates/cli/CODEX.md +0 -21
  468. package/templates/cli/CONTINUE.md +0 -34
  469. package/templates/cli/CURSOR_CLI.md +0 -62
  470. package/templates/cli/FACTORY.md +0 -18
  471. package/templates/cli/GEMINI.md +0 -35
  472. package/templates/cli/KILOCODE.md +0 -18
  473. package/templates/cli/OPENCODE.md +0 -85
  474. package/templates/cli/gemini-extension.json +0 -77
  475. package/templates/commands/rulebook-memory-save.md +0 -48
  476. package/templates/commands/rulebook-memory-search.md +0 -47
  477. package/templates/ides/CONTINUE_RULES.md +0 -16
  478. package/templates/ides/COPILOT_INSTRUCTIONS.md +0 -23
  479. package/templates/ides/GEMINI_RULES.md +0 -17
  480. package/templates/ides/OPENCODE.md +0 -63
  481. package/templates/ides/WINDSURF_RULES.md +0 -14
  482. package/templates/modules/ATLASSIAN.md +0 -255
  483. package/templates/modules/FIGMA.md +0 -267
  484. package/templates/modules/GRAFANA.md +0 -328
  485. package/templates/modules/MEMORY.md +0 -126
  486. package/templates/modules/NOTION.md +0 -247
  487. package/templates/skills/cli/aider/SKILL.md +0 -59
  488. package/templates/skills/cli/amazon-q/SKILL.md +0 -35
  489. package/templates/skills/cli/auggie/SKILL.md +0 -42
  490. package/templates/skills/cli/cline/SKILL.md +0 -42
  491. package/templates/skills/cli/codebuddy/SKILL.md +0 -30
  492. package/templates/skills/cli/codeium/SKILL.md +0 -30
  493. package/templates/skills/cli/codex/SKILL.md +0 -31
  494. package/templates/skills/cli/continue/SKILL.md +0 -44
  495. package/templates/skills/cli/cursor-cli/SKILL.md +0 -38
  496. package/templates/skills/cli/factory/SKILL.md +0 -28
  497. package/templates/skills/cli/gemini/SKILL.md +0 -45
  498. package/templates/skills/cli/kilocode/SKILL.md +0 -28
  499. package/templates/skills/cli/opencode/SKILL.md +0 -82
  500. package/templates/skills/ides/copilot/SKILL.md +0 -47
  501. package/templates/skills/ides/cursor/SKILL.md +0 -53
  502. package/templates/skills/ides/jetbrains-ai/SKILL.md +0 -45
  503. package/templates/skills/ides/replit/SKILL.md +0 -46
  504. package/templates/skills/ides/tabnine/SKILL.md +0 -39
  505. package/templates/skills/ides/vscode/SKILL.md +0 -50
  506. package/templates/skills/ides/windsurf/SKILL.md +0 -46
  507. package/templates/skills/ides/zed/SKILL.md +0 -42
  508. package/templates/skills/modules/atlassian/SKILL.md +0 -265
  509. package/templates/skills/modules/figma/SKILL.md +0 -277
  510. package/templates/skills/modules/grafana/SKILL.md +0 -338
  511. package/templates/skills/modules/memory/SKILL.md +0 -73
  512. 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
  }