@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
@@ -1,48 +1,41 @@
1
- ---
2
- name: /rulebook-learn-capture
3
- id: rulebook-learn-capture
4
- category: Rulebook
5
- description: Capture a learning from implementation work for future reference.
6
- ---
7
- <!-- RULEBOOK:START -->
8
- **Guardrails**
9
- - Learnings are saved to both the memory system and `.rulebook/learnings/` for offline backup.
10
- - Learnings can be promoted to patterns/decisions later via `rulebook learn promote`.
11
-
12
- **Steps**
13
- 1. **Gather the Learning**:
14
- - **Title**: Short description of what was learned
15
- - **Content**: Full explanation — what happened, what was discovered, why it matters
16
- - **Tags**: Keywords for searchability
17
- - **Related Task**: Task ID if this learning came from a specific task
18
- - **Source**: `manual` (default), `ralph`, or `task-archive`
19
-
20
- 2. **Capture**:
21
- ```bash
22
- rulebook learn capture --title "<title>" --content "<content>" --tags "tag1,tag2" --related-task <task-id>
23
- ```
24
-
25
- 3. **Verify**:
26
- ```bash
27
- rulebook learn list --limit 5
28
- ```
29
-
30
- **Promotion Flow**
31
- If a learning is significant enough to become a team pattern or decision:
32
- ```bash
33
- rulebook learn promote <id> knowledge # → creates a pattern
34
- rulebook learn promote <id> decision # → creates an ADR
35
- ```
36
-
37
- **Ralph Integration**
38
- Extract learnings from Ralph autonomous loop history:
39
- ```bash
40
- rulebook learn from-ralph
41
- ```
42
- This reads `.rulebook/ralph/history/iteration-*.json` and captures entries with non-empty learnings.
43
-
44
- **Reference**
45
- - Learnings are searchable via `rulebook memory search`
46
- - Use `rulebook learn list` to see all learnings
47
- - Learnings captured during `rulebook task archive` have source `task-archive`
48
- <!-- RULEBOOK:END -->
1
+ ---
2
+ name: /rulebook-learn-capture
3
+ id: rulebook-learn-capture
4
+ category: Rulebook
5
+ description: Capture a learning from implementation work for future reference.
6
+ ---
7
+ <!-- RULEBOOK:START -->
8
+ **Guardrails**
9
+ - Learnings are saved to both the memory system and `.rulebook/learnings/` for offline backup.
10
+ - Learnings can be promoted to patterns/decisions later via `rulebook learn promote`.
11
+
12
+ **Steps**
13
+ 1. **Gather the Learning**:
14
+ - **Title**: Short description of what was learned
15
+ - **Content**: Full explanation — what happened, what was discovered, why it matters
16
+ - **Tags**: Keywords for searchability
17
+ - **Related Task**: Task ID if this learning came from a specific task
18
+ - **Source**: `manual` (default) or `task-archive`
19
+
20
+ 2. **Capture**:
21
+ ```bash
22
+ rulebook learn capture --title "<title>" --content "<content>" --tags "tag1,tag2" --related-task <task-id>
23
+ ```
24
+
25
+ 3. **Verify**:
26
+ ```bash
27
+ rulebook learn list --limit 5
28
+ ```
29
+
30
+ **Promotion Flow**
31
+ If a learning is significant enough to become a team pattern or decision:
32
+ ```bash
33
+ rulebook learn promote <id> knowledge # → creates a pattern
34
+ rulebook learn promote <id> decision # → creates an ADR
35
+ ```
36
+
37
+ **Reference**
38
+ - Learnings are searchable via `rulebook memory search`
39
+ - Use `rulebook learn list` to see all learnings
40
+ - Learnings captured during `rulebook task archive` have source `task-archive`
41
+ <!-- RULEBOOK:END -->
@@ -1,13 +1,13 @@
1
- ---
2
- name: /rulebook-learn-list
3
- id: rulebook-learn-list
4
- category: Rulebook
5
- description: List captured learnings with source and promotion status.
6
- ---
7
- <!-- RULEBOOK:START -->
8
- **Steps**
9
- 1. Run `rulebook learn list` to see all learnings (newest first).
10
- 2. Optionally limit: `rulebook learn list --limit 10`
11
- 3. Present results with source badge (manual/ralph/archive) and promotion status.
12
- 4. Suggest promotion for significant learnings: `rulebook learn promote <id> knowledge|decision`
13
- <!-- RULEBOOK:END -->
1
+ ---
2
+ name: /rulebook-learn-list
3
+ id: rulebook-learn-list
4
+ category: Rulebook
5
+ description: List captured learnings with source and promotion status.
6
+ ---
7
+ <!-- RULEBOOK:START -->
8
+ **Steps**
9
+ 1. Run `rulebook learn list` to see all learnings (newest first).
10
+ 2. Optionally limit: `rulebook learn list --limit 10`
11
+ 3. Present results with source badge (manual/archive) and promotion status.
12
+ 4. Suggest promotion for significant learnings: `rulebook learn promote <id> knowledge|decision`
13
+ <!-- RULEBOOK:END -->
@@ -157,20 +157,6 @@ LANGUAGE_REFS
157
157
 
158
158
  MODULE_REFS
159
159
 
160
- ## Ralph Autonomous Loop
161
-
162
- 5-gate quality enforcement (type-check, lint, tests, coverage, security) per iteration, fresh context per iteration, parallel story execution, plan checkpoints, learning extraction.
163
-
164
- ```bash
165
- rulebook ralph init # Generate PRD from tasks
166
- rulebook ralph run --max-iterations 10
167
- rulebook ralph status / history / pause / resume
168
- ```
169
-
170
- PRD format: `userStories` array with `id`, `title`, `description`, `acceptanceCriteria`, `priority`, `passes: boolean`, `notes`. Status tracked via `passes`, NOT enum.
171
-
172
- Iteration records in `.rulebook/ralph/history/iteration-N.json`. Status: `success` (5/5 gates), `partial` (2-4), `failed` (0-1).
173
-
174
160
  ## Multi-Agent Teams
175
161
 
176
162
  Requires `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`. Background `Agent` calls **must** use a Team (`team_name` parameter) — standalone background agents can't communicate via `SendMessage`. Foreground calls and `team-lead` agents are exempt.
@@ -36,18 +36,16 @@ if [[ -f "$CONFIG_FILE" ]] && command -v jq &>/dev/null; then
36
36
  FORCE_PCT=$(jq -r '.handoff.forceThresholdPct // 90' "$CONFIG_FILE" 2>/dev/null || echo 90)
37
37
  fi
38
38
 
39
- # Try to find the transcript path from the session
40
- # Claude Code stores transcripts as JSONL in ~/.claude/projects/<hash>/
41
- # The hook input may or may not contain session info; we fall back to
42
- # estimating from the input itself.
39
+ # Resolve transcript size from the payload's transcript_path. Claude Code
40
+ # always passes this in Stop hook stdin (Anthropic hook spec), so we avoid
41
+ # scanning $HOME/.claude/projects which grows linearly with session count
42
+ # and also returns the wrong file in concurrent sessions.
43
43
  transcript_size=0
44
44
 
45
- # Strategy 1: check the most recent JSONL in the project-specific Claude dir
46
- CLAUDE_PROJECTS_DIR="${HOME}/.claude/projects"
47
- if [[ -d "$CLAUDE_PROJECTS_DIR" ]]; then
48
- latest_jsonl=$(find "$CLAUDE_PROJECTS_DIR" -name "*.jsonl" -type f -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | awk '{print $2}' || true)
49
- if [[ -n "$latest_jsonl" && -f "$latest_jsonl" ]]; then
50
- transcript_size=$(stat -c%s "$latest_jsonl" 2>/dev/null || stat -f%z "$latest_jsonl" 2>/dev/null || echo 0)
45
+ if [[ -n "$input" ]] && command -v jq &>/dev/null; then
46
+ transcript_path="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null || true)"
47
+ if [[ -n "$transcript_path" && -f "$transcript_path" ]]; then
48
+ transcript_size=$(stat -c%s "$transcript_path" 2>/dev/null || stat -f%z "$transcript_path" 2>/dev/null || echo 0)
51
49
  fi
52
50
  fi
53
51
 
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env bash
2
+ # PreToolUse hook (v5.6.0): consolidated deny rules.
3
+ #
4
+ # Replaces three legacy hooks (enforce-no-deferred / enforce-no-shortcuts /
5
+ # enforce-mcp-for-tasks) with a single bash + node invocation. Each rule's
6
+ # permissionDecisionReason is preserved verbatim so existing user guidance
7
+ # is unchanged.
8
+ set -euo pipefail
9
+ input="$(cat)"
10
+
11
+ result="$(node -e "
12
+ const input = JSON.parse(process.argv[1]);
13
+ const tool = input.tool_name || '';
14
+ const ti = input.tool_input || {};
15
+ const file = (ti.file_path || ti.filePath || '').replace(/\\\\/g, '/');
16
+ const content = ti.new_string || ti.content || '';
17
+ const cmd = ti.command || '';
18
+
19
+ // Rule: mcp-for-tasks — manual creation of task scaffolding is forbidden.
20
+ if (tool === 'Write' || tool === 'Edit') {
21
+ const m = file.match(/\.rulebook\/tasks\/[^/]+\/(proposal\.md|\.metadata\.json)\$/);
22
+ if (m) {
23
+ try { require('fs').accessSync(file); /* existing file: allow edit */ }
24
+ catch { console.log('DENY_MCP'); process.exit(0); }
25
+ }
26
+ }
27
+ if (tool === 'Bash' && /mkdir.*\\.rulebook\\/tasks\\//.test(cmd)) {
28
+ console.log('DENY_MCP'); process.exit(0);
29
+ }
30
+
31
+ // Rule: no-deferred — tasks.md must not contain deferred / skip / later / TODO.
32
+ if ((tool === 'Edit' || tool === 'Write') && file.endsWith('tasks.md')) {
33
+ if (/\\b(deferred|skip(ped)?|later|todo)\\b/i.test(content)) {
34
+ console.log('DENY_DEFERRED'); process.exit(0);
35
+ }
36
+ }
37
+
38
+ // Rule: no-shortcuts — source files must not contain TODO/FIXME/HACK or stub/placeholder.
39
+ if (tool === 'Edit' || tool === 'Write') {
40
+ if (/\\.(ts|tsx|js|jsx|py|rs|go|java|cs|cpp|c|hpp|h)\$/.test(file)
41
+ && !/\\.test\\.|\\.spec\\.|__tests__|\\/tests\\//.test(file)) {
42
+ if (/\\/\\/\\s*(TODO|FIXME|HACK)\\b|\\/\\*\\s*(TODO|FIXME|HACK)\\b|#\\s*(TODO|FIXME|HACK)\\b/.test(content)) {
43
+ console.log('DENY_TODO'); process.exit(0);
44
+ }
45
+ if (/\\bplaceholder\\b|\\bstub\\b/i.test(content)) {
46
+ console.log('DENY_STUB'); process.exit(0);
47
+ }
48
+ }
49
+ }
50
+
51
+ console.log('ALLOW');
52
+ " "$input" 2>/dev/null || echo "ALLOW")"
53
+
54
+ case "$result" in
55
+ DENY_MCP)
56
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"DENIED: task files must be created via rulebook_task_create MCP tool, not manually. Use: rulebook_task_create({ taskId: phase1_your-task-name })"}}'
57
+ ;;
58
+ DENY_DEFERRED)
59
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"DENIED: tasks.md cannot contain deferred, skip, later, or TODO. Implement the item now or explain why impossible. See .claude/rules/no-deferred.md"}}'
60
+ ;;
61
+ DENY_TODO)
62
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"DENIED: source code cannot contain // TODO, // FIXME, or // HACK. Implement the logic now. See .claude/rules/no-shortcuts.md"}}'
63
+ ;;
64
+ DENY_STUB)
65
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"DENIED: source code cannot contain placeholders or stubs. Implement real logic. See .claude/rules/no-shortcuts.md"}}'
66
+ ;;
67
+ *)
68
+ echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
69
+ ;;
70
+ esac
@@ -1,81 +1,75 @@
1
1
  #!/usr/bin/env bash
2
- # Claude Code UserPromptSubmit hook for rulebook-terse (v5.4.0).
2
+ # Claude Code UserPromptSubmit hook for rulebook-terse (v5.6.0).
3
3
  #
4
4
  # Parses slash commands + natural-language activation/deactivation
5
5
  # phrases in the user prompt, updates the project-local flag file,
6
6
  # and emits a short (~45 token) attention anchor as hookSpecificOutput
7
- # when a persistent mode is active — keeps the compression register in
8
- # the model's attention on every user message.
7
+ # when a persistent mode is active.
9
8
  #
10
- # Independent sub-skill modes (commit / review) do NOT get the anchor:
11
- # their own SKILL.md files drive behavior for the single turn they're
12
- # invoked.
9
+ # Performance: fast-path bash trigger scan avoids spawning node when the
10
+ # prompt cannot change state. When state can change, a single node call
11
+ # parses stdin + configs and returns a pre-resolved decision
12
+ # (`set:<mode>` / `unset` / `noop`) plus the resolved cwd. Bash only
13
+ # applies filesystem changes after that.
13
14
  #
14
15
  # Silent-fails on every filesystem error.
15
16
 
16
17
  set -u
17
18
 
18
19
  input="$(cat || true)"
19
- prompt=""
20
- cwd=""
21
- if [ -n "$input" ]; then
22
- # Parse JSON via node (always available in Claude Code hook env).
23
- # Emits two lines: prompt on line 1, cwd on line 2.
24
- parsed="$(printf '%s' "$input" | node -e "
25
- try {
26
- const data = JSON.parse(require('fs').readFileSync(0, 'utf8'));
27
- process.stdout.write((data.prompt || '') + '\\n' + (data.cwd || ''));
28
- } catch { process.stdout.write('\\n'); }
29
- " 2>/dev/null || printf '\n')"
30
- prompt="$(printf '%s' "$parsed" | head -n 1)"
31
- cwd="$(printf '%s' "$parsed" | tail -n +2)"
32
- fi
33
20
 
34
- PROJECT_ROOT="${cwd:-${CLAUDE_PROJECT_DIR:-$(pwd)}}"
35
- FLAG_PATH="${PROJECT_ROOT}/.rulebook/.terse-mode"
36
- CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/rulebook"
37
- USER_CONFIG="${CONFIG_DIR}/config.json"
38
- PROJECT_CONFIG="${PROJECT_ROOT}/.rulebook/rulebook.json"
21
+ # Fast-path trigger scan over raw stdin payload. JSON-escaped string
22
+ # values still match these literal substrings (the trigger words contain
23
+ # no JSON-special characters), so this is a safe coarse filter. If none
24
+ # match, we skip node entirely.
25
+ TRIGGER_RE='(/rulebook-terse|terse mode|be terse|stop terse|disable terse|deactivate terse|turn off terse|enable terse|activate terse|turn on terse|normal mode|less tokens?)'
26
+ prompt_has_trigger=0
27
+ if [ -n "$input" ] && printf '%s' "$input" | grep -qiE "$TRIGGER_RE"; then
28
+ prompt_has_trigger=1
29
+ fi
39
30
 
40
31
  VALID_MODES_RE='^(off|brief|terse|ultra|commit|review)$'
41
32
  MAX_FLAG_BYTES=32
42
33
 
43
- resolve_default_mode() {
44
- if [ -n "${RULEBOOK_TERSE_MODE:-}" ]; then
45
- local m="$(printf '%s' "$RULEBOOK_TERSE_MODE" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
46
- if [[ "$m" =~ $VALID_MODES_RE ]]; then printf '%s' "$m"; return; fi
47
- fi
48
- if [ -f "$PROJECT_CONFIG" ]; then
49
- local m
50
- m="$(node -e "
51
- try {
52
- const cfg = JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'));
53
- if (cfg.terse && cfg.terse.defaultMode) process.stdout.write(String(cfg.terse.defaultMode));
54
- } catch { }
55
- " "$PROJECT_CONFIG" 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]' || true)"
56
- if [ -n "$m" ] && [[ "$m" =~ $VALID_MODES_RE ]]; then printf '%s' "$m"; return; fi
34
+ read_flag() {
35
+ # Symlink-safe, size-capped, whitelist-validated read.
36
+ local flag_path="$1"
37
+ [ ! -f "$flag_path" ] && return 1
38
+ [ -L "$flag_path" ] && return 1
39
+ local size
40
+ size="$(wc -c < "$flag_path" 2>/dev/null || echo "$MAX_FLAG_BYTES")"
41
+ [ "$size" -gt "$MAX_FLAG_BYTES" ] && return 1
42
+ local raw
43
+ raw="$(head -c "$MAX_FLAG_BYTES" "$flag_path" 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
44
+ if [[ "$raw" =~ $VALID_MODES_RE ]]; then
45
+ printf '%s' "$raw"
46
+ return 0
57
47
  fi
58
- if [ -f "$USER_CONFIG" ]; then
59
- local m
60
- m="$(node -e "
61
- try {
62
- const cfg = JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'));
63
- if (cfg.terse && cfg.terse.defaultMode) process.stdout.write(String(cfg.terse.defaultMode));
64
- } catch { }
65
- " "$USER_CONFIG" 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]' || true)"
66
- if [ -n "$m" ] && [[ "$m" =~ $VALID_MODES_RE ]]; then printf '%s' "$m"; return; fi
48
+ return 1
49
+ }
50
+
51
+ emit_anchor() {
52
+ # Hand-construct the JSON. The text below contains no quotes,
53
+ # backslashes, or control chars, so this is safe.
54
+ local mode="$1"
55
+ local keep_clause
56
+ if [ "$mode" = "brief" ]; then
57
+ keep_clause="Keep articles and full sentences."
58
+ else
59
+ keep_clause="Fragments OK."
67
60
  fi
68
- printf 'terse'
61
+ local text="RULEBOOK-TERSE ACTIVE (${mode}). Drop filler/hedging/pleasantries. ${keep_clause} Code/tests/commits/security: write full. Quality-gate failures + destructive ops: write full."
62
+ printf '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"%s"}}' "$text"
69
63
  }
70
64
 
71
65
  safe_write_flag() {
72
- local content="$1"
66
+ local flag_path="$1"
67
+ local content="$2"
73
68
  local dir
74
- dir="$(dirname "$FLAG_PATH")"
69
+ dir="$(dirname "$flag_path")"
75
70
  mkdir -p "$dir" 2>/dev/null || return 0
76
71
  [ -L "$dir" ] && return 0
77
- [ -L "$FLAG_PATH" ] && return 0
78
-
72
+ [ -L "$flag_path" ] && return 0
79
73
  local tmp
80
74
  tmp="$(mktemp "$dir/.terse-mode.XXXXXX" 2>/dev/null)" || return 0
81
75
  {
@@ -83,105 +77,114 @@ safe_write_flag() {
83
77
  printf '%s' "$content" > "$tmp" 2>/dev/null || { rm -f "$tmp"; return 0; }
84
78
  }
85
79
  chmod 600 "$tmp" 2>/dev/null || true
86
- mv -f "$tmp" "$FLAG_PATH" 2>/dev/null || rm -f "$tmp"
80
+ mv -f "$tmp" "$flag_path" 2>/dev/null || rm -f "$tmp"
87
81
  }
88
82
 
89
- read_flag() {
90
- # Symlink-safe, size-capped, whitelist-validated read.
91
- [ ! -f "$FLAG_PATH" ] && return 1
92
- [ -L "$FLAG_PATH" ] && return 1
93
- local size
94
- size="$(wc -c < "$FLAG_PATH" 2>/dev/null || echo "$MAX_FLAG_BYTES")"
95
- [ "$size" -gt "$MAX_FLAG_BYTES" ] && return 1
96
-
97
- local raw
98
- raw="$(head -c "$MAX_FLAG_BYTES" "$FLAG_PATH" 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
99
- if [[ "$raw" =~ $VALID_MODES_RE ]]; then
100
- printf '%s' "$raw"
101
- return 0
102
- fi
103
- return 1
104
- }
105
-
106
- default_mode="$(resolve_default_mode)"
107
- lower_prompt="$(printf '%s' "$prompt" | tr '[:upper:]' '[:lower:]')"
108
-
109
- # Parse intent. Order matters: deactivation wins over accidental
110
- # activation, slash commands win over natural-language patterns.
111
- new_mode=""
112
- deactivate=0
113
-
114
- # Slash commands
115
- if [[ "$lower_prompt" == /rulebook-terse-commit* ]]; then
116
- new_mode="commit"
117
- elif [[ "$lower_prompt" == /rulebook-terse-review* ]]; then
118
- new_mode="review"
119
- elif [[ "$lower_prompt" == /rulebook-terse ]]; then
120
- new_mode="$default_mode"
121
- elif [[ "$lower_prompt" == /rulebook-terse\ * ]]; then
122
- arg="$(printf '%s' "$lower_prompt" | awk '{print $2}')"
123
- case "$arg" in
124
- off) deactivate=1 ;;
125
- brief|terse|ultra|commit|review) new_mode="$arg" ;;
126
- *) : ;; # unknown subcommand → leave state unchanged
83
+ # Fast exit: no trigger in prompt → state cannot change. Just emit the
84
+ # anchor for the active persistent mode (if any) and return.
85
+ if [ "$prompt_has_trigger" -eq 0 ]; then
86
+ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
87
+ active_mode="$(read_flag "${PROJECT_ROOT}/.rulebook/.terse-mode" || true)"
88
+ case "$active_mode" in
89
+ brief|terse|ultra) emit_anchor "$active_mode" ;;
127
90
  esac
91
+ exit 0
128
92
  fi
129
93
 
130
- # Natural-language deactivation checked first so "stop terse" wins.
131
- if [ -z "$new_mode" ] && [ "$deactivate" -eq 0 ]; then
132
- if echo "$prompt" | grep -qiE '\b(stop|disable|turn off|deactivate)\b.*\brulebook[- ]?terse\b' \
133
- || echo "$prompt" | grep -qiE '\brulebook[- ]?terse\b.*\b(stop|disable|turn off|deactivate)\b' \
134
- || echo "$prompt" | grep -qiE '\b(stop|disable) terse\b' \
135
- || echo "$prompt" | grep -qiE '\bnormal mode\b'; then
136
- deactivate=1
137
- fi
138
- fi
94
+ # Slow path: ONE node call does the entire parse + decision logic, then
95
+ # emits two lines: `cwd` and `decision` (one of `set:<mode>`, `unset`,
96
+ # `noop`). Bash only handles filesystem ops after that.
97
+ result="$(printf '%s' "$input" | RULEBOOK_TERSE_MODE="${RULEBOOK_TERSE_MODE:-}" node -e '
98
+ const fs = require("fs");
99
+ function readJson(p) { try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return null; } }
100
+ const VALID = /^(off|brief|terse|ultra|commit|review)$/;
101
+
102
+ let data = {};
103
+ try { data = JSON.parse(fs.readFileSync(0, "utf8")); } catch { }
104
+ const prompt = String(data.prompt || "");
105
+ const cwd = String(data.cwd || "");
106
+ const lower = prompt.toLowerCase();
107
+
108
+ // Resolve default mode: env > project config > user config > "terse".
109
+ function norm(s) { return String(s || "").toLowerCase().replace(/\s+/g, ""); }
110
+ let def = norm(process.env.RULEBOOK_TERSE_MODE);
111
+ if (!VALID.test(def)) def = "";
112
+ if (!def && cwd) {
113
+ const pc = readJson(cwd + "/.rulebook/rulebook.json");
114
+ const m = norm(pc && pc.terse && pc.terse.defaultMode);
115
+ if (VALID.test(m)) def = m;
116
+ }
117
+ if (!def) {
118
+ const home = process.env.HOME || process.env.USERPROFILE || "";
119
+ const xdg = process.env.XDG_CONFIG_HOME || (home ? home + "/.config" : "");
120
+ if (xdg) {
121
+ const uc = readJson(xdg + "/rulebook/config.json");
122
+ const m = norm(uc && uc.terse && uc.terse.defaultMode);
123
+ if (VALID.test(m)) def = m;
124
+ }
125
+ }
126
+ if (!def) def = "terse";
127
+
128
+ // Slash commands.
129
+ let newMode = "";
130
+ let deact = false;
131
+ if (lower.startsWith("/rulebook-terse-commit")) newMode = "commit";
132
+ else if (lower.startsWith("/rulebook-terse-review")) newMode = "review";
133
+ else if (lower === "/rulebook-terse") newMode = def;
134
+ else if (lower.startsWith("/rulebook-terse ")) {
135
+ const arg = lower.split(/\s+/)[1] || "";
136
+ if (arg === "off") deact = true;
137
+ else if (/^(brief|terse|ultra|commit|review)$/.test(arg)) newMode = arg;
138
+ }
139
139
 
140
- # Natural-language activation
141
- if [ -z "$new_mode" ] && [ "$deactivate" -eq 0 ]; then
142
- if echo "$prompt" | grep -qiE '\b(activate|enable|turn on|start)\b.*\brulebook[- ]?terse\b' \
143
- || echo "$prompt" | grep -qiE '\brulebook[- ]?terse\b.*\b(mode|activate|enable|turn on|start)\b' \
144
- || echo "$prompt" | grep -qiE '\bbe terse\b' \
145
- || echo "$prompt" | grep -qiE '\bterse mode\b' \
146
- || echo "$prompt" | grep -qiE '\bless tokens?\b'; then
147
- new_mode="$default_mode"
148
- fi
149
- fi
140
+ // Natural-language deactivation (checked first so "stop terse" wins).
141
+ if (!newMode && !deact) {
142
+ if (
143
+ /\b(stop|disable|turn off|deactivate)\b.*\brulebook[- ]?terse\b/i.test(prompt) ||
144
+ /\brulebook[- ]?terse\b.*\b(stop|disable|turn off|deactivate)\b/i.test(prompt) ||
145
+ /\b(stop|disable) terse\b/i.test(prompt) ||
146
+ /\bnormal mode\b/i.test(prompt)
147
+ ) deact = true;
148
+ }
149
+ // Natural-language activation.
150
+ if (!newMode && !deact) {
151
+ if (
152
+ /\b(activate|enable|turn on|start)\b.*\brulebook[- ]?terse\b/i.test(prompt) ||
153
+ /\brulebook[- ]?terse\b.*\b(mode|activate|enable|turn on|start)\b/i.test(prompt) ||
154
+ /\bbe terse\b/i.test(prompt) ||
155
+ /\bterse mode\b/i.test(prompt) ||
156
+ /\bless tokens?\b/i.test(prompt)
157
+ ) newMode = def;
158
+ }
159
+
160
+ let decision = "noop";
161
+ if (deact || newMode === "off") decision = "unset";
162
+ else if (newMode) decision = "set:" + newMode;
163
+
164
+ process.stdout.write(cwd + "\n" + decision);
165
+ ' 2>/dev/null || printf '\nnoop')"
150
166
 
151
- # Apply intent
152
- if [ "$deactivate" -eq 1 ]; then
153
- rm -f "$FLAG_PATH" 2>/dev/null || true
154
- elif [ -n "$new_mode" ]; then
155
- if [ "$new_mode" = "off" ]; then
167
+ # First line = cwd, rest = decision.
168
+ cwd="$(printf '%s' "$result" | sed -n '1p')"
169
+ decision="$(printf '%s' "$result" | sed -n '2p')"
170
+
171
+ PROJECT_ROOT="${cwd:-${CLAUDE_PROJECT_DIR:-$(pwd)}}"
172
+ FLAG_PATH="${PROJECT_ROOT}/.rulebook/.terse-mode"
173
+
174
+ case "$decision" in
175
+ unset)
156
176
  rm -f "$FLAG_PATH" 2>/dev/null || true
157
- else
158
- safe_write_flag "$new_mode"
159
- fi
160
- fi
177
+ ;;
178
+ set:*)
179
+ new_mode="${decision#set:}"
180
+ safe_write_flag "$FLAG_PATH" "$new_mode"
181
+ ;;
182
+ *) # noop
183
+ ;;
184
+ esac
161
185
 
162
186
  # Emit attention anchor for persistent modes only.
163
- active_mode="$(read_flag || true)"
187
+ active_mode="$(read_flag "$FLAG_PATH" || true)"
164
188
  case "$active_mode" in
165
- brief|terse|ultra)
166
- if [ "$active_mode" = "brief" ]; then
167
- keep_clause="Keep articles and full sentences."
168
- else
169
- keep_clause="Fragments OK."
170
- fi
171
- text="RULEBOOK-TERSE ACTIVE (${active_mode}). Drop filler/hedging/pleasantries. ${keep_clause} Code/tests/commits/security: write full. Quality-gate failures + destructive ops: write full."
172
- # Emit hookSpecificOutput JSON via node — universal across platforms.
173
- node -e "
174
- const text = process.argv[1];
175
- process.stdout.write(JSON.stringify({
176
- hookSpecificOutput: {
177
- hookEventName: 'UserPromptSubmit',
178
- additionalContext: text
179
- }
180
- }));
181
- " "$text" 2>/dev/null || true
182
- ;;
183
- *)
184
- # No active persistent mode, or commit/review sub-skill — no anchor.
185
- :
186
- ;;
189
+ brief|terse|ultra) emit_anchor "$active_mode" ;;
187
190
  esac
@@ -0,0 +1,63 @@
1
+ <!-- OPENCODE:START -->
2
+ # OpenCode Integration
3
+
4
+ This project is managed by [@hivellm/rulebook](https://github.com/hivellm/rulebook).
5
+ The OpenCode integration mirrors the Claude Code experience inside the
6
+ [OpenCode](https://opencode.ai) terminal coding agent.
7
+
8
+ ## What Rulebook generates for OpenCode
9
+
10
+ | File / Path | Purpose |
11
+ |---|---|
12
+ | `opencode.json` | Adds `$schema`, `mcp.rulebook`, and `instructions` (lazy-loads `AGENTS.md`, `AGENTS.override.md`, `.rulebook/specs/*.md`). Preserves all user-defined keys. |
13
+ | `.opencode/commands/<name>.md` | One file per user-invocable Rulebook slash command. |
14
+ | `.opencode/agents/<role>.md` | One file per Rulebook role agent, frontmatter translated. |
15
+ | `.opencode/skills/<name>/SKILL.md` | One directory per Rulebook dev skill, name-normalized to OpenCode's regex. |
16
+ | `.opencode/.rulebook-managed.json` | Sidecar so `rulebook update` knows which keys to refresh. |
17
+
18
+ ## Critical rules
19
+
20
+ These mirror the rules every other Rulebook-supported tool follows:
21
+
22
+ 1. **Read `AGENTS.md` and `AGENTS.override.md`** before making changes.
23
+ 2. **Never revert or discard uncommitted work** — fix forward.
24
+ 3. **Edit files sequentially**, not in parallel. For 3+ files, decompose
25
+ into 1–2 file sub-tasks.
26
+ 4. **Run type-check / lint before tests** — diagnostic-first.
27
+ 5. **If a fix fails twice, escalate** — research, ask, or open a team.
28
+ 6. **Prefer MCP tools** (`mcp__rulebook__*`) over shell commands.
29
+ 7. **Capture learnings** at the end of significant work.
30
+ 8. **Never archive a task** without docs updated, tests written, and
31
+ tests passing.
32
+
33
+ ## Model tier mapping
34
+
35
+ | Rulebook tier | OpenCode model |
36
+ |---|---|
37
+ | `haiku` | `anthropic/claude-haiku-4-5` |
38
+ | `sonnet` | `anthropic/claude-sonnet-4-6` |
39
+ | `opus` | `anthropic/claude-opus-4-7` |
40
+
41
+ ## Permission synthesis
42
+
43
+ | Role type | `permission.edit` | `permission.bash` |
44
+ |---|---|---|
45
+ | Read-only (researcher, code-reviewer, security-reviewer, accessibility-reviewer, ux-reviewer, performance-engineer) | `deny` | `ask` |
46
+ | All other roles | `allow` | `allow` |
47
+
48
+ ## Isolation
49
+
50
+ Set `OPENCODE_DISABLE_CLAUDE_CODE=*` if you want OpenCode to ignore a
51
+ `CLAUDE.md` shared with Claude Code, so only `AGENTS.md` is consulted.
52
+
53
+ ## Documentation
54
+
55
+ - [opencode.ai/docs/rules](https://opencode.ai/docs/rules/)
56
+ - [opencode.ai/docs/config](https://opencode.ai/docs/config/)
57
+ - [opencode.ai/docs/mcp-servers](https://opencode.ai/docs/mcp-servers/)
58
+ - [opencode.ai/docs/commands](https://opencode.ai/docs/commands/)
59
+ - [opencode.ai/docs/agents](https://opencode.ai/docs/agents/)
60
+ - [opencode.ai/docs/skills](https://opencode.ai/docs/skills/)
61
+ - [opencode.ai/docs/permissions](https://opencode.ai/docs/permissions/)
62
+
63
+ <!-- OPENCODE:END -->