@hivehub/rulebook 5.5.2 → 5.7.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 (325) hide show
  1. package/.claude/commands/rulebook-learn-capture.md +41 -48
  2. package/.claude/commands/rulebook-learn-list.md +13 -13
  3. package/README.md +332 -394
  4. package/dist/cli/commands/context-intelligence.d.ts +0 -1
  5. package/dist/cli/commands/context-intelligence.d.ts.map +1 -1
  6. package/dist/cli/commands/context-intelligence.js +12 -33
  7. package/dist/cli/commands/context-intelligence.js.map +1 -1
  8. package/dist/cli/commands/index.d.ts +4 -7
  9. package/dist/cli/commands/index.d.ts.map +1 -1
  10. package/dist/cli/commands/index.js +4 -7
  11. package/dist/cli/commands/index.js.map +1 -1
  12. package/dist/cli/commands/init.d.ts.map +1 -1
  13. package/dist/cli/commands/init.js +40 -81
  14. package/dist/cli/commands/init.js.map +1 -1
  15. package/dist/cli/commands/mcp.d.ts +0 -1
  16. package/dist/cli/commands/mcp.d.ts.map +1 -1
  17. package/dist/cli/commands/mcp.js +1 -7
  18. package/dist/cli/commands/mcp.js.map +1 -1
  19. package/dist/cli/commands/memory.d.ts +7 -1
  20. package/dist/cli/commands/memory.d.ts.map +1 -1
  21. package/dist/cli/commands/memory.js +51 -57
  22. package/dist/cli/commands/memory.js.map +1 -1
  23. package/dist/cli/commands/misc.d.ts +1 -15
  24. package/dist/cli/commands/misc.d.ts.map +1 -1
  25. package/dist/cli/commands/misc.js +36 -215
  26. package/dist/cli/commands/misc.js.map +1 -1
  27. package/dist/cli/commands/plans.d.ts +0 -6
  28. package/dist/cli/commands/plans.d.ts.map +1 -1
  29. package/dist/cli/commands/plans.js +9 -77
  30. package/dist/cli/commands/plans.js.map +1 -1
  31. package/dist/cli/commands/skills.js +6 -6
  32. package/dist/cli/commands/skills.js.map +1 -1
  33. package/dist/cli/commands/task.js +4 -4
  34. package/dist/cli/commands/task.js.map +1 -1
  35. package/dist/cli/commands/update.d.ts.map +1 -1
  36. package/dist/cli/commands/update.js +122 -52
  37. package/dist/cli/commands/update.js.map +1 -1
  38. package/dist/cli/prompts.d.ts.map +1 -1
  39. package/dist/cli/prompts.js +1 -78
  40. package/dist/cli/prompts.js.map +1 -1
  41. package/dist/core/claude/claude-mcp.d.ts +59 -0
  42. package/dist/core/claude/claude-mcp.d.ts.map +1 -0
  43. package/dist/core/claude/claude-mcp.js +220 -0
  44. package/dist/core/claude/claude-mcp.js.map +1 -0
  45. package/dist/core/claude/claude-md-generator.d.ts +52 -0
  46. package/dist/core/claude/claude-md-generator.d.ts.map +1 -0
  47. package/dist/core/claude/claude-md-generator.js +104 -0
  48. package/dist/core/claude/claude-md-generator.js.map +1 -0
  49. package/dist/core/claude/claude-settings-manager.d.ts +44 -0
  50. package/dist/core/claude/claude-settings-manager.d.ts.map +1 -0
  51. package/dist/core/claude/claude-settings-manager.js +194 -0
  52. package/dist/core/claude/claude-settings-manager.js.map +1 -0
  53. package/dist/core/console/cli-bridge.d.ts +113 -0
  54. package/dist/core/console/cli-bridge.d.ts.map +1 -0
  55. package/dist/core/console/cli-bridge.js +1094 -0
  56. package/dist/core/console/cli-bridge.js.map +1 -0
  57. package/dist/core/detect/detector.d.ts +35 -0
  58. package/dist/core/detect/detector.d.ts.map +1 -0
  59. package/dist/core/detect/detector.js +541 -0
  60. package/dist/core/detect/detector.js.map +1 -0
  61. package/dist/core/docs/docs-generator.d.ts +9 -0
  62. package/dist/core/docs/docs-generator.d.ts.map +1 -0
  63. package/dist/core/docs/docs-generator.js +531 -0
  64. package/dist/core/docs/docs-generator.js.map +1 -0
  65. package/dist/core/docs/mcp-reference-generator.d.ts +13 -0
  66. package/dist/core/docs/mcp-reference-generator.d.ts.map +1 -0
  67. package/dist/core/docs/mcp-reference-generator.js +66 -0
  68. package/dist/core/docs/mcp-reference-generator.js.map +1 -0
  69. package/dist/core/generators/generator.d.ts +54 -0
  70. package/dist/core/generators/generator.d.ts.map +1 -0
  71. package/dist/core/generators/generator.js +1041 -0
  72. package/dist/core/generators/generator.js.map +1 -0
  73. package/dist/core/generators/gitignore-generator.d.ts +13 -0
  74. package/dist/core/generators/gitignore-generator.d.ts.map +1 -0
  75. package/dist/core/generators/gitignore-generator.js +307 -0
  76. package/dist/core/generators/gitignore-generator.js.map +1 -0
  77. package/dist/core/generators/minimal-scaffolder.d.ts +8 -0
  78. package/dist/core/generators/minimal-scaffolder.d.ts.map +1 -0
  79. package/dist/core/generators/minimal-scaffolder.js +51 -0
  80. package/dist/core/generators/minimal-scaffolder.js.map +1 -0
  81. package/dist/core/generators/rules-generator.d.ts +73 -0
  82. package/dist/core/generators/rules-generator.d.ts.map +1 -0
  83. package/dist/core/generators/rules-generator.js +202 -0
  84. package/dist/core/generators/rules-generator.js.map +1 -0
  85. package/dist/core/generators/workflow-generator.d.ts +15 -0
  86. package/dist/core/generators/workflow-generator.d.ts.map +1 -0
  87. package/dist/core/generators/workflow-generator.js +390 -0
  88. package/dist/core/generators/workflow-generator.js.map +1 -0
  89. package/dist/core/ide/multi-tool-generator.d.ts +59 -0
  90. package/dist/core/ide/multi-tool-generator.d.ts.map +1 -0
  91. package/dist/core/ide/multi-tool-generator.js +157 -0
  92. package/dist/core/ide/multi-tool-generator.js.map +1 -0
  93. package/dist/core/ide/opencode-generator.d.ts +72 -0
  94. package/dist/core/ide/opencode-generator.d.ts.map +1 -0
  95. package/dist/core/ide/opencode-generator.js +450 -0
  96. package/dist/core/ide/opencode-generator.js.map +1 -0
  97. package/dist/core/merger.d.ts +1 -1
  98. package/dist/core/merger.d.ts.map +1 -1
  99. package/dist/core/merger.js +5 -5
  100. package/dist/core/merger.js.map +1 -1
  101. package/dist/core/migrator.d.ts +0 -1
  102. package/dist/core/migrator.d.ts.map +1 -1
  103. package/dist/core/migrator.js +4 -29
  104. package/dist/core/migrator.js.map +1 -1
  105. package/dist/core/quality/coverage-checker.d.ts +14 -0
  106. package/dist/core/quality/coverage-checker.d.ts.map +1 -0
  107. package/dist/core/quality/coverage-checker.js +176 -0
  108. package/dist/core/quality/coverage-checker.js.map +1 -0
  109. package/dist/core/quality/dependency-checker.d.ts +21 -0
  110. package/dist/core/quality/dependency-checker.d.ts.map +1 -0
  111. package/dist/core/quality/dependency-checker.js +247 -0
  112. package/dist/core/quality/dependency-checker.js.map +1 -0
  113. package/dist/core/quality/doctor.d.ts +19 -0
  114. package/dist/core/quality/doctor.d.ts.map +1 -0
  115. package/dist/core/quality/doctor.js +163 -0
  116. package/dist/core/quality/doctor.js.map +1 -0
  117. package/dist/core/quality/validator.d.ts +21 -0
  118. package/dist/core/quality/validator.d.ts.map +1 -0
  119. package/dist/core/quality/validator.js +177 -0
  120. package/dist/core/quality/validator.js.map +1 -0
  121. package/dist/core/skills/skills-manager.d.ts +126 -0
  122. package/dist/core/skills/skills-manager.d.ts.map +1 -0
  123. package/dist/core/skills/skills-manager.js +630 -0
  124. package/dist/core/skills/skills-manager.js.map +1 -0
  125. package/dist/core/state/config-manager.d.ts +86 -0
  126. package/dist/core/state/config-manager.d.ts.map +1 -0
  127. package/dist/core/state/config-manager.js +562 -0
  128. package/dist/core/state/config-manager.js.map +1 -0
  129. package/dist/core/state/override-manager.d.ts +23 -0
  130. package/dist/core/state/override-manager.d.ts.map +1 -0
  131. package/dist/core/state/override-manager.js +82 -0
  132. package/dist/core/state/override-manager.js.map +1 -0
  133. package/dist/core/state/state-writer.d.ts +34 -0
  134. package/dist/core/state/state-writer.d.ts.map +1 -0
  135. package/dist/core/state/state-writer.js +78 -0
  136. package/dist/core/state/state-writer.js.map +1 -0
  137. package/dist/core/state/version-bumper.d.ts +19 -0
  138. package/dist/core/state/version-bumper.d.ts.map +1 -0
  139. package/dist/core/state/version-bumper.js +180 -0
  140. package/dist/core/state/version-bumper.js.map +1 -0
  141. package/dist/core/tasks/decision-manager.d.ts +25 -0
  142. package/dist/core/tasks/decision-manager.d.ts.map +1 -0
  143. package/dist/core/tasks/decision-manager.js +183 -0
  144. package/dist/core/tasks/decision-manager.js.map +1 -0
  145. package/dist/core/tasks/knowledge-manager.d.ts +24 -0
  146. package/dist/core/tasks/knowledge-manager.d.ts.map +1 -0
  147. package/dist/core/tasks/knowledge-manager.js +173 -0
  148. package/dist/core/tasks/knowledge-manager.js.map +1 -0
  149. package/dist/core/tasks/learn-manager.d.ts +27 -0
  150. package/dist/core/tasks/learn-manager.d.ts.map +1 -0
  151. package/dist/core/tasks/learn-manager.js +121 -0
  152. package/dist/core/tasks/learn-manager.js.map +1 -0
  153. package/dist/core/tasks/plans-manager.d.ts +46 -0
  154. package/dist/core/tasks/plans-manager.d.ts.map +1 -0
  155. package/dist/core/tasks/plans-manager.js +158 -0
  156. package/dist/core/tasks/plans-manager.js.map +1 -0
  157. package/dist/core/tasks/task-manager.d.ts +127 -0
  158. package/dist/core/tasks/task-manager.d.ts.map +1 -0
  159. package/dist/core/tasks/task-manager.js +607 -0
  160. package/dist/core/tasks/task-manager.js.map +1 -0
  161. package/dist/core/workspace/project-worker.d.ts +6 -6
  162. package/dist/core/workspace/project-worker.d.ts.map +1 -1
  163. package/dist/core/workspace/project-worker.js +6 -6
  164. package/dist/core/workspace/project-worker.js.map +1 -1
  165. package/dist/index.d.ts +1 -1
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +19 -176
  168. package/dist/index.js.map +1 -1
  169. package/dist/mcp/rulebook-server.d.ts.map +1 -1
  170. package/dist/mcp/rulebook-server.js +16 -960
  171. package/dist/mcp/rulebook-server.js.map +1 -1
  172. package/dist/memory/file-search.d.ts +43 -0
  173. package/dist/memory/file-search.d.ts.map +1 -0
  174. package/dist/memory/file-search.js +228 -0
  175. package/dist/memory/file-search.js.map +1 -0
  176. package/dist/memory/file-store.d.ts +99 -0
  177. package/dist/memory/file-store.d.ts.map +1 -0
  178. package/dist/memory/file-store.js +615 -0
  179. package/dist/memory/file-store.js.map +1 -0
  180. package/dist/memory/legacy-migrator.d.ts +27 -0
  181. package/dist/memory/legacy-migrator.d.ts.map +1 -0
  182. package/dist/memory/legacy-migrator.js +185 -0
  183. package/dist/memory/legacy-migrator.js.map +1 -0
  184. package/dist/memory/memory-manager.d.ts +25 -24
  185. package/dist/memory/memory-manager.d.ts.map +1 -1
  186. package/dist/memory/memory-manager.js +97 -140
  187. package/dist/memory/memory-manager.js.map +1 -1
  188. package/dist/memory/memory-types.d.ts +1 -1
  189. package/dist/memory/memory-types.d.ts.map +1 -1
  190. package/dist/types.d.ts +8 -119
  191. package/dist/types.d.ts.map +1 -1
  192. package/package.json +1 -6
  193. package/templates/agents/context-intelligence.md +50 -52
  194. package/templates/cli/OPENCODE.md +85 -18
  195. package/templates/commands/rulebook-learn-capture.md +41 -48
  196. package/templates/commands/rulebook-learn-list.md +13 -13
  197. package/templates/core/AGENTS_LEAN.md +0 -14
  198. package/templates/hooks/check-context-and-handoff.sh +8 -10
  199. package/templates/hooks/enforce-pre-tool.sh +70 -0
  200. package/templates/hooks/terse-mode-tracker.sh +146 -143
  201. package/templates/ides/OPENCODE.md +63 -0
  202. package/templates/skills/cli/opencode/SKILL.md +82 -28
  203. package/.claude/commands/ralph-config.md +0 -112
  204. package/.claude/commands/ralph-history.md +0 -110
  205. package/.claude/commands/ralph-init.md +0 -72
  206. package/.claude/commands/ralph-pause-resume.md +0 -105
  207. package/.claude/commands/ralph-run.md +0 -101
  208. package/.claude/commands/ralph-status.md +0 -76
  209. package/templates/core/RALPH.md +0 -471
  210. package/templates/frameworks/ANGULAR.md +0 -36
  211. package/templates/frameworks/DJANGO.md +0 -83
  212. package/templates/frameworks/ELECTRON.md +0 -147
  213. package/templates/frameworks/FLASK.md +0 -38
  214. package/templates/frameworks/FLUTTER.md +0 -55
  215. package/templates/frameworks/JQUERY.md +0 -32
  216. package/templates/frameworks/LARAVEL.md +0 -38
  217. package/templates/frameworks/NESTJS.md +0 -43
  218. package/templates/frameworks/NEXTJS.md +0 -127
  219. package/templates/frameworks/NUXT.md +0 -40
  220. package/templates/frameworks/RAILS.md +0 -66
  221. package/templates/frameworks/REACT.md +0 -38
  222. package/templates/frameworks/REACT_NATIVE.md +0 -47
  223. package/templates/frameworks/SPRING.md +0 -39
  224. package/templates/frameworks/SYMFONY.md +0 -36
  225. package/templates/frameworks/VUE.md +0 -36
  226. package/templates/frameworks/ZEND.md +0 -35
  227. package/templates/hooks/enforce-mcp-for-tasks.sh +0 -31
  228. package/templates/hooks/enforce-no-deferred.sh +0 -21
  229. package/templates/hooks/enforce-no-shortcuts.sh +0 -31
  230. package/templates/ides/COPILOT.md +0 -37
  231. package/templates/ides/CURSOR.md +0 -43
  232. package/templates/ides/JETBRAINS_AI.md +0 -35
  233. package/templates/ides/REPLIT.md +0 -36
  234. package/templates/ides/TABNINE.md +0 -29
  235. package/templates/ides/VSCODE.md +0 -40
  236. package/templates/ides/WINDSURF.md +0 -36
  237. package/templates/ides/ZED.md +0 -32
  238. package/templates/ides/cursor-mdc/go.mdc +0 -24
  239. package/templates/ides/cursor-mdc/python.mdc +0 -24
  240. package/templates/ides/cursor-mdc/quality.mdc +0 -25
  241. package/templates/ides/cursor-mdc/ralph.mdc +0 -39
  242. package/templates/ides/cursor-mdc/rulebook.mdc +0 -38
  243. package/templates/ides/cursor-mdc/rust.mdc +0 -24
  244. package/templates/ides/cursor-mdc/typescript.mdc +0 -25
  245. package/templates/ralph/ralph-history.bat +0 -4
  246. package/templates/ralph/ralph-history.sh +0 -5
  247. package/templates/ralph/ralph-init.bat +0 -5
  248. package/templates/ralph/ralph-init.sh +0 -5
  249. package/templates/ralph/ralph-pause.bat +0 -5
  250. package/templates/ralph/ralph-pause.sh +0 -5
  251. package/templates/ralph/ralph-run.bat +0 -5
  252. package/templates/ralph/ralph-run.sh +0 -5
  253. package/templates/ralph/ralph-status.bat +0 -4
  254. package/templates/ralph/ralph-status.sh +0 -5
  255. package/templates/services/AZURE_BLOB.md +0 -184
  256. package/templates/services/CASSANDRA.md +0 -239
  257. package/templates/services/DATADOG.md +0 -26
  258. package/templates/services/DOCKER.md +0 -124
  259. package/templates/services/DOCKER_COMPOSE.md +0 -168
  260. package/templates/services/DYNAMODB.md +0 -308
  261. package/templates/services/ELASTICSEARCH.md +0 -347
  262. package/templates/services/GCS.md +0 -178
  263. package/templates/services/HELM.md +0 -194
  264. package/templates/services/INFLUXDB.md +0 -265
  265. package/templates/services/KAFKA.md +0 -341
  266. package/templates/services/KUBERNETES.md +0 -208
  267. package/templates/services/MARIADB.md +0 -183
  268. package/templates/services/MEMCACHED.md +0 -242
  269. package/templates/services/MINIO.md +0 -201
  270. package/templates/services/MONGODB.md +0 -268
  271. package/templates/services/MYSQL.md +0 -358
  272. package/templates/services/NEO4J.md +0 -247
  273. package/templates/services/OPENTELEMETRY.md +0 -25
  274. package/templates/services/ORACLE.md +0 -290
  275. package/templates/services/PINO.md +0 -24
  276. package/templates/services/POSTGRESQL.md +0 -326
  277. package/templates/services/PROMETHEUS.md +0 -33
  278. package/templates/services/RABBITMQ.md +0 -286
  279. package/templates/services/REDIS.md +0 -292
  280. package/templates/services/S3.md +0 -298
  281. package/templates/services/SENTRY.md +0 -23
  282. package/templates/services/SQLITE.md +0 -294
  283. package/templates/services/SQLSERVER.md +0 -294
  284. package/templates/services/WINSTON.md +0 -30
  285. package/templates/skills/frameworks/angular/SKILL.md +0 -46
  286. package/templates/skills/frameworks/django/SKILL.md +0 -93
  287. package/templates/skills/frameworks/electron/SKILL.md +0 -157
  288. package/templates/skills/frameworks/flask/SKILL.md +0 -48
  289. package/templates/skills/frameworks/flutter/SKILL.md +0 -65
  290. package/templates/skills/frameworks/jquery/SKILL.md +0 -42
  291. package/templates/skills/frameworks/laravel/SKILL.md +0 -48
  292. package/templates/skills/frameworks/nestjs/SKILL.md +0 -53
  293. package/templates/skills/frameworks/nextjs/SKILL.md +0 -137
  294. package/templates/skills/frameworks/nuxt/SKILL.md +0 -50
  295. package/templates/skills/frameworks/rails/SKILL.md +0 -76
  296. package/templates/skills/frameworks/react/SKILL.md +0 -48
  297. package/templates/skills/frameworks/react-native/SKILL.md +0 -57
  298. package/templates/skills/frameworks/spring/SKILL.md +0 -49
  299. package/templates/skills/frameworks/symfony/SKILL.md +0 -46
  300. package/templates/skills/frameworks/vue/SKILL.md +0 -46
  301. package/templates/skills/frameworks/zend/SKILL.md +0 -45
  302. package/templates/skills/services/azure-blob/SKILL.md +0 -194
  303. package/templates/skills/services/cassandra/SKILL.md +0 -249
  304. package/templates/skills/services/dynamodb/SKILL.md +0 -318
  305. package/templates/skills/services/elasticsearch/SKILL.md +0 -357
  306. package/templates/skills/services/gcs/SKILL.md +0 -188
  307. package/templates/skills/services/influxdb/SKILL.md +0 -275
  308. package/templates/skills/services/kafka/SKILL.md +0 -351
  309. package/templates/skills/services/mariadb/SKILL.md +0 -193
  310. package/templates/skills/services/memcached/SKILL.md +0 -252
  311. package/templates/skills/services/minio/SKILL.md +0 -211
  312. package/templates/skills/services/mongodb/SKILL.md +0 -278
  313. package/templates/skills/services/mysql/SKILL.md +0 -368
  314. package/templates/skills/services/neo4j/SKILL.md +0 -257
  315. package/templates/skills/services/oracle/SKILL.md +0 -300
  316. package/templates/skills/services/postgresql/SKILL.md +0 -336
  317. package/templates/skills/services/rabbitmq/SKILL.md +0 -296
  318. package/templates/skills/services/redis/SKILL.md +0 -302
  319. package/templates/skills/services/s3/SKILL.md +0 -308
  320. package/templates/skills/services/sqlite/SKILL.md +0 -304
  321. package/templates/skills/services/sqlserver/SKILL.md +0 -304
  322. package/templates/skills/workflows/ralph/SETUP.md +0 -228
  323. package/templates/skills/workflows/ralph/SKILL.md +0 -309
  324. package/templates/skills/workflows/ralph/install.sh +0 -87
  325. package/templates/skills/workflows/ralph/manifest.json +0 -158
@@ -0,0 +1,163 @@
1
+ import path from 'path';
2
+ import { fileExists, readFile } from '../../utils/file-system.js';
3
+ const LINE_BUDGET = 200;
4
+ const STALE_DAYS = 14;
5
+ export async function runDoctor(projectRoot) {
6
+ const checks = [];
7
+ await checkFileSize(projectRoot, 'CLAUDE.md', LINE_BUDGET, checks);
8
+ await checkFileSize(projectRoot, 'AGENTS.md', 6000, checks);
9
+ await checkStateStaleness(projectRoot, checks);
10
+ await checkBrokenImports(projectRoot, checks);
11
+ await checkOrphanedRules(projectRoot, checks);
12
+ await checkOverrideConflicts(projectRoot, checks);
13
+ await checkMissingFiles(projectRoot, checks);
14
+ return {
15
+ checks,
16
+ passCount: checks.filter((c) => c.status === 'pass').length,
17
+ warnCount: checks.filter((c) => c.status === 'warn').length,
18
+ failCount: checks.filter((c) => c.status === 'fail').length,
19
+ };
20
+ }
21
+ async function checkFileSize(root, file, budget, checks) {
22
+ const filePath = path.join(root, file);
23
+ if (!(await fileExists(filePath))) {
24
+ checks.push({ name: `${file} size`, status: 'warn', message: `${file} not found` });
25
+ return;
26
+ }
27
+ const content = await readFile(filePath);
28
+ const lines = content.split('\n').length;
29
+ if (lines > budget) {
30
+ checks.push({
31
+ name: `${file} size`,
32
+ status: 'warn',
33
+ message: `${file} is ${lines} lines (budget: ${budget}). Consider splitting with @imports or .claude/rules/.`,
34
+ });
35
+ }
36
+ else {
37
+ checks.push({
38
+ name: `${file} size`,
39
+ status: 'pass',
40
+ message: `${file} is ${lines} lines (within ${budget}-line budget)`,
41
+ });
42
+ }
43
+ }
44
+ async function checkStateStaleness(root, checks) {
45
+ const statePath = path.join(root, '.rulebook', 'STATE.md');
46
+ if (!(await fileExists(statePath))) {
47
+ checks.push({
48
+ name: 'STATE.md freshness',
49
+ status: 'warn',
50
+ message: '.rulebook/STATE.md not found — session continuity may be impaired',
51
+ });
52
+ return;
53
+ }
54
+ const { promises: fs } = await import('fs');
55
+ const stat = await fs.stat(statePath);
56
+ const ageDays = (Date.now() - stat.mtimeMs) / (1000 * 60 * 60 * 24);
57
+ if (ageDays > STALE_DAYS) {
58
+ checks.push({
59
+ name: 'STATE.md freshness',
60
+ status: 'warn',
61
+ message: `STATE.md last modified ${Math.floor(ageDays)} days ago (threshold: ${STALE_DAYS}). Run a task update to refresh it.`,
62
+ });
63
+ }
64
+ else {
65
+ checks.push({
66
+ name: 'STATE.md freshness',
67
+ status: 'pass',
68
+ message: `STATE.md is fresh (${Math.floor(ageDays)} days old)`,
69
+ });
70
+ }
71
+ }
72
+ async function checkBrokenImports(root, checks) {
73
+ const claudePath = path.join(root, 'CLAUDE.md');
74
+ if (!(await fileExists(claudePath)))
75
+ return;
76
+ const content = await readFile(claudePath);
77
+ const importRegex = /^@(.+)$/gm;
78
+ let match;
79
+ const broken = [];
80
+ while ((match = importRegex.exec(content)) !== null) {
81
+ const target = match[1].trim();
82
+ const resolved = path.join(root, target);
83
+ if (!(await fileExists(resolved))) {
84
+ broken.push(target);
85
+ }
86
+ }
87
+ if (broken.length > 0) {
88
+ checks.push({
89
+ name: 'CLAUDE.md @imports',
90
+ status: 'fail',
91
+ message: `Broken @imports: ${broken.join(', ')}. Claude Code will warn about missing files.`,
92
+ });
93
+ }
94
+ else {
95
+ checks.push({
96
+ name: 'CLAUDE.md @imports',
97
+ status: 'pass',
98
+ message: 'All @imports resolve to existing files',
99
+ });
100
+ }
101
+ }
102
+ async function checkOrphanedRules(root, checks) {
103
+ const rulesDir = path.join(root, '.claude', 'rules');
104
+ if (!(await fileExists(rulesDir))) {
105
+ checks.push({
106
+ name: 'Orphaned rules',
107
+ status: 'pass',
108
+ message: 'No .claude/rules/ directory',
109
+ });
110
+ return;
111
+ }
112
+ const { promises: fs } = await import('fs');
113
+ const entries = await fs.readdir(rulesDir);
114
+ const mdFiles = entries.filter((e) => e.endsWith('.md'));
115
+ // A rule is "orphaned" if it has paths: frontmatter but the glob
116
+ // does not match any files. This is a simplified heuristic check —
117
+ // we just confirm the paths: field exists and is non-empty.
118
+ checks.push({
119
+ name: 'Orphaned rules',
120
+ status: 'pass',
121
+ message: `${mdFiles.length} rule file(s) in .claude/rules/`,
122
+ });
123
+ }
124
+ async function checkOverrideConflicts(root, checks) {
125
+ const overridePath = path.join(root, 'AGENTS.override.md');
126
+ if (!(await fileExists(overridePath))) {
127
+ checks.push({
128
+ name: 'Override conflicts',
129
+ status: 'pass',
130
+ message: 'No AGENTS.override.md',
131
+ });
132
+ return;
133
+ }
134
+ checks.push({
135
+ name: 'Override conflicts',
136
+ status: 'pass',
137
+ message: 'AGENTS.override.md present (manual conflict review recommended)',
138
+ });
139
+ }
140
+ async function checkMissingFiles(root, checks) {
141
+ const expected = ['CLAUDE.md', 'AGENTS.md', '.rulebook/rulebook.json'];
142
+ const missing = [];
143
+ for (const f of expected) {
144
+ if (!(await fileExists(path.join(root, f)))) {
145
+ missing.push(f);
146
+ }
147
+ }
148
+ if (missing.length > 0) {
149
+ checks.push({
150
+ name: 'Required files',
151
+ status: 'fail',
152
+ message: `Missing: ${missing.join(', ')}. Run \`rulebook init\` to bootstrap.`,
153
+ });
154
+ }
155
+ else {
156
+ checks.push({
157
+ name: 'Required files',
158
+ status: 'pass',
159
+ message: 'All required files present',
160
+ });
161
+ }
162
+ }
163
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/core/quality/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ errors: ValidationError[];
4
+ warnings: ValidationWarning[];
5
+ score: number;
6
+ }
7
+ export interface ValidationError {
8
+ type: 'error';
9
+ category: string;
10
+ message: string;
11
+ file?: string;
12
+ }
13
+ export interface ValidationWarning {
14
+ type: 'warning';
15
+ category: string;
16
+ message: string;
17
+ file?: string;
18
+ }
19
+ export declare function validateProject(cwd?: string): Promise<ValidationResult>;
20
+ export declare function formatValidationReport(result: ValidationResult): string;
21
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/core/quality/validator.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4B5F;AA6JD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAwCvE"}
@@ -0,0 +1,177 @@
1
+ import path from 'path';
2
+ import { fileExists, readFile, findFiles } from '../../utils/file-system.js';
3
+ export async function validateProject(cwd = process.cwd()) {
4
+ const errors = [];
5
+ const warnings = [];
6
+ // Check for AGENTS.md
7
+ await validateAgentsFile(cwd, errors, warnings);
8
+ // Check rulebook directory (if modular mode)
9
+ await validateRulebookDirectory(cwd, errors, warnings);
10
+ // Check documentation structure
11
+ await validateDocumentation(cwd, errors, warnings);
12
+ // Check for tests directory
13
+ await validateTests(cwd, errors, warnings);
14
+ // Check for .rulesignore if present
15
+ await validateRulesIgnore(cwd, warnings, errors);
16
+ // Calculate score (errors -10 points, warnings -5 points each)
17
+ const score = Math.max(0, 100 - (errors.length * 10 + warnings.length * 5));
18
+ return {
19
+ valid: errors.length === 0,
20
+ errors,
21
+ warnings,
22
+ score,
23
+ };
24
+ }
25
+ async function validateAgentsFile(cwd, errors, warnings) {
26
+ const agentsPath = path.join(cwd, 'AGENTS.md');
27
+ if (!(await fileExists(agentsPath))) {
28
+ errors.push({
29
+ type: 'error',
30
+ category: 'standards',
31
+ message: 'AGENTS.md not found in project root',
32
+ file: 'AGENTS.md',
33
+ });
34
+ return;
35
+ }
36
+ // Read and validate AGENTS.md content
37
+ const content = await readFile(agentsPath);
38
+ if (!content.includes('<!-- RULEBOOK:START -->')) {
39
+ warnings.push({
40
+ type: 'warning',
41
+ category: 'standards',
42
+ message: 'AGENTS.md missing RULEBOOK block (not generated by @hivellm/rulebook)',
43
+ file: 'AGENTS.md',
44
+ });
45
+ }
46
+ if (content.length < 100) {
47
+ warnings.push({
48
+ type: 'warning',
49
+ category: 'standards',
50
+ message: 'AGENTS.md seems incomplete (very short)',
51
+ file: 'AGENTS.md',
52
+ });
53
+ }
54
+ }
55
+ async function validateRulebookDirectory(cwd, _errors, warnings) {
56
+ const rulebookPath = path.join(cwd, '.rulebook');
57
+ // Check if .rulebook directory exists (optional but recommended for modular mode)
58
+ const rulebookExists = await fileExists(rulebookPath);
59
+ if (rulebookExists) {
60
+ // Validate that .rulebook/specs directory contains .md files
61
+ const rulebookFiles = await findFiles('.rulebook/specs/*.md', cwd);
62
+ if (rulebookFiles.length === 0) {
63
+ warnings.push({
64
+ type: 'warning',
65
+ category: 'structure',
66
+ message: '.rulebook/specs/ directory exists but contains no .md files',
67
+ file: '.rulebook/specs/',
68
+ });
69
+ }
70
+ }
71
+ }
72
+ async function validateDocumentation(cwd, _errors, warnings) {
73
+ const docsDir = path.join(cwd, 'docs');
74
+ if (!(await fileExists(docsDir))) {
75
+ warnings.push({
76
+ type: 'warning',
77
+ category: 'documentation',
78
+ message: '/docs directory not found (recommended for organization)',
79
+ });
80
+ return;
81
+ }
82
+ // Check for important docs
83
+ const importantDocs = ['ROADMAP.md', 'ARCHITECTURE.md'];
84
+ for (const doc of importantDocs) {
85
+ const docPath = path.join(docsDir, doc);
86
+ if (!(await fileExists(docPath))) {
87
+ warnings.push({
88
+ type: 'warning',
89
+ category: 'documentation',
90
+ message: `${doc} not found in /docs (recommended)`,
91
+ file: `docs/${doc}`,
92
+ });
93
+ }
94
+ }
95
+ // Check for specs directory
96
+ const specsDir = path.join(docsDir, 'specs');
97
+ if (!(await fileExists(specsDir))) {
98
+ warnings.push({
99
+ type: 'warning',
100
+ category: 'documentation',
101
+ message: '/docs/specs directory not found (recommended for feature specifications)',
102
+ });
103
+ }
104
+ }
105
+ async function validateTests(cwd, errors, _warnings) {
106
+ const testsDir = path.join(cwd, 'tests');
107
+ const testDir = path.join(cwd, 'test');
108
+ const hasTests = (await fileExists(testsDir)) || (await fileExists(testDir));
109
+ if (!hasTests) {
110
+ errors.push({
111
+ type: 'error',
112
+ category: 'testing',
113
+ message: '/tests directory not found (required by rulebook standards)',
114
+ });
115
+ }
116
+ }
117
+ async function validateRulesIgnore(cwd, warnings, _errors) {
118
+ const rulesIgnorePath = path.join(cwd, '.rulesignore');
119
+ if (await fileExists(rulesIgnorePath)) {
120
+ const content = await readFile(rulesIgnorePath);
121
+ const lines = content.split('\n').filter((l) => l.trim() && !l.startsWith('#'));
122
+ if (lines.length > 10) {
123
+ warnings.push({
124
+ type: 'warning',
125
+ category: 'configuration',
126
+ message: `.rulesignore has ${lines.length} rules ignored (consider reducing)`,
127
+ file: '.rulesignore',
128
+ });
129
+ }
130
+ // Check for wildcard ignores
131
+ if (lines.some((l) => l === '*' || l === '**/*')) {
132
+ warnings.push({
133
+ type: 'warning',
134
+ category: 'configuration',
135
+ message: '.rulesignore ignores all rules (defeats purpose)',
136
+ file: '.rulesignore',
137
+ });
138
+ }
139
+ }
140
+ }
141
+ export function formatValidationReport(result) {
142
+ const lines = [];
143
+ lines.push('# Validation Report');
144
+ lines.push('');
145
+ lines.push(`**Score**: ${result.score}/100`);
146
+ lines.push(`**Status**: ${result.valid ? '✅ PASSED' : '❌ FAILED'}`);
147
+ lines.push('');
148
+ if (result.errors.length > 0) {
149
+ lines.push('## Errors');
150
+ lines.push('');
151
+ for (const error of result.errors) {
152
+ lines.push(`- ❌ **${error.category}**: ${error.message}`);
153
+ if (error.file) {
154
+ lines.push(` File: ${error.file}`);
155
+ }
156
+ }
157
+ lines.push('');
158
+ }
159
+ if (result.warnings.length > 0) {
160
+ lines.push('## Warnings');
161
+ lines.push('');
162
+ for (const warning of result.warnings) {
163
+ lines.push(`- ⚠️ **${warning.category}**: ${warning.message}`);
164
+ if (warning.file) {
165
+ lines.push(` File: ${warning.file}`);
166
+ }
167
+ }
168
+ lines.push('');
169
+ }
170
+ if (result.valid && result.warnings.length === 0) {
171
+ lines.push('## Summary');
172
+ lines.push('');
173
+ lines.push('✅ All checks passed! Your project follows rulebook standards.');
174
+ }
175
+ return lines.join('\n');
176
+ }
177
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/core/quality/validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Skills Manager Module
3
+ *
4
+ * Handles discovery, loading, merging, and management of skills for Rulebook v2.0.
5
+ * Skills are self-contained capability modules with SKILL.md files containing
6
+ * YAML frontmatter (metadata) and guidance content.
7
+ *
8
+ * Compatible with:
9
+ * - Hugging Face Skills format
10
+ * - Claude Code plugin system
11
+ * - Codex AGENTS.md format
12
+ * - Gemini CLI extensions
13
+ */
14
+ import type { Skill, SkillMetadata, SkillCategory, SkillsIndex, SkillValidationResult, RulebookConfig } from '../../types.js';
15
+ /**
16
+ * Parse YAML frontmatter from SKILL.md content
17
+ */
18
+ export declare function parseSkillFrontmatter(content: string): {
19
+ metadata: SkillMetadata;
20
+ body: string;
21
+ };
22
+ /**
23
+ * Generate YAML frontmatter from metadata
24
+ */
25
+ export declare function generateSkillFrontmatter(metadata: SkillMetadata): string;
26
+ /**
27
+ * Convert legacy template to skill format
28
+ */
29
+ export declare function convertLegacyTemplateToSkill(templateContent: string, templateName: string, category: SkillCategory): {
30
+ metadata: SkillMetadata;
31
+ content: string;
32
+ };
33
+ /**
34
+ * Skills Manager Class
35
+ */
36
+ export declare class SkillsManager {
37
+ private templatesPath;
38
+ private skillsPath;
39
+ private skillsIndex;
40
+ constructor(templatesPath: string, _projectPath?: string);
41
+ /**
42
+ * Discover all available skills from templates directory
43
+ */
44
+ discoverSkills(): Promise<SkillsIndex>;
45
+ /**
46
+ * Scan skills directory for SKILL.md files
47
+ */
48
+ private scanSkillsDirectory;
49
+ /**
50
+ * Scan legacy template directories
51
+ */
52
+ private scanLegacyTemplates;
53
+ /**
54
+ * Load skill from SKILL.md file
55
+ */
56
+ private loadSkillFromFile;
57
+ /**
58
+ * Load legacy template as skill
59
+ */
60
+ private loadLegacyTemplate;
61
+ /**
62
+ * Generate unique skill ID
63
+ */
64
+ private generateSkillId;
65
+ /**
66
+ * Get all available skills
67
+ */
68
+ getSkills(): Promise<Skill[]>;
69
+ /**
70
+ * Get skills by category
71
+ */
72
+ getSkillsByCategory(category: SkillCategory): Promise<Skill[]>;
73
+ /**
74
+ * Get skill by ID
75
+ */
76
+ getSkillById(id: string): Promise<Skill | null>;
77
+ /**
78
+ * Search skills by name or description
79
+ */
80
+ searchSkills(query: string): Promise<Skill[]>;
81
+ /**
82
+ * Enable a skill in the configuration
83
+ */
84
+ enableSkill(skillId: string, config: RulebookConfig): Promise<RulebookConfig>;
85
+ /**
86
+ * Disable a skill in the configuration
87
+ */
88
+ disableSkill(skillId: string, config: RulebookConfig): Promise<RulebookConfig>;
89
+ /**
90
+ * Validate skills configuration
91
+ */
92
+ validateSkills(config: RulebookConfig): Promise<SkillValidationResult>;
93
+ /**
94
+ * Get enabled skills in order
95
+ */
96
+ getEnabledSkills(config: RulebookConfig): Promise<Skill[]>;
97
+ /**
98
+ * Merge enabled skills into single content for AGENTS.md
99
+ */
100
+ mergeSkillsContent(config: RulebookConfig): Promise<string>;
101
+ /**
102
+ * Auto-detect skills based on project configuration
103
+ */
104
+ autoDetectSkills(config: Partial<RulebookConfig>): Promise<string[]>;
105
+ /**
106
+ * Create a new skill from template
107
+ */
108
+ createSkill(name: string, description: string, category: SkillCategory, content?: string): Promise<Skill>;
109
+ /**
110
+ * Get skills summary for display
111
+ */
112
+ getSkillsSummary(): Promise<{
113
+ total: number;
114
+ byCategory: Record<string, number>;
115
+ categories: SkillCategory[];
116
+ }>;
117
+ }
118
+ /**
119
+ * Create a new SkillsManager instance
120
+ */
121
+ export declare function createSkillsManager(templatesPath: string, projectPath?: string): SkillsManager;
122
+ /**
123
+ * Get the default templates path
124
+ */
125
+ export declare function getDefaultTemplatesPath(): string;
126
+ //# sourceMappingURL=skills-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-manager.d.ts","sourceRoot":"","sources":["../../../src/core/skills/skills-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,qBAAqB,EACrB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAmBxB;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IACtD,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd,CAmBA;AA6CD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CA4BxE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GACtB;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA+B9C;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAA4B;gBAEnC,aAAa,EAAE,MAAM,EAAE,YAAY,GAAE,MAAsB;IAMvE;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IA8B5C;;OAEG;YACW,mBAAmB;IA+BjC;;OAEG;YACW,mBAAmB;IAoCjC;;OAEG;YACW,iBAAiB;IA2B/B;;OAEG;YACW,kBAAkB;IA4BhC;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAOnC;;OAEG;IACG,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAOpE;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAKrD;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAanD;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAwCnF;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAsCpF;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA8E5E;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAuBhE;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAgCjE;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoC1E;;OAEG;IACG,WAAW,CACf,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,MAAW,GACnB,OAAO,CAAC,KAAK,CAAC;IA8BjB;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,UAAU,EAAE,aAAa,EAAE,CAAC;KAC7B,CAAC;CAmBH;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,aAAa,CAE9F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD"}