contextdevkit 1.8.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 (345) hide show
  1. package/CHANGELOG.md +592 -0
  2. package/LICENSE +21 -0
  3. package/README.md +401 -0
  4. package/docs/AGENT-PACKAGE-FORMAT.md +140 -0
  5. package/docs/ARCHITECTURE.md +258 -0
  6. package/docs/CHANGELOG.md +559 -0
  7. package/docs/CUSTOMIZING.md +211 -0
  8. package/docs/LEVELS.md +151 -0
  9. package/docs/ROADMAP.md +385 -0
  10. package/docs/SQUAD-PIPELINE-FORMAT.md +258 -0
  11. package/docs/SQUADS/agent-forge.md +65 -0
  12. package/docs/SQUADS/design-team.md +161 -0
  13. package/docs/token-economy-plan.md +135 -0
  14. package/install.mjs +273 -0
  15. package/instrucoes.md +274 -0
  16. package/package.json +46 -0
  17. package/templates/CLAUDE.md.tpl +133 -0
  18. package/templates/claude/agents/_TEMPLATE.md +52 -0
  19. package/templates/claude/agents/accessibility.md +36 -0
  20. package/templates/claude/agents/agent-architect.md +37 -0
  21. package/templates/claude/agents/architect.md +39 -0
  22. package/templates/claude/agents/code-reviewer.md +43 -0
  23. package/templates/claude/agents/code-security.md +59 -0
  24. package/templates/claude/agents/context-keeper.md +40 -0
  25. package/templates/claude/agents/devops.md +40 -0
  26. package/templates/claude/agents/eval-designer.md +40 -0
  27. package/templates/claude/agents/forge-orchestrator.md +42 -0
  28. package/templates/claude/agents/governance-officer.md +45 -0
  29. package/templates/claude/agents/growth.md +92 -0
  30. package/templates/claude/agents/infra-security.md +53 -0
  31. package/templates/claude/agents/landing-architect.md +154 -0
  32. package/templates/claude/agents/model-router.md +34 -0
  33. package/templates/claude/agents/packager.md +38 -0
  34. package/templates/claude/agents/privacy-lgpd.md +64 -0
  35. package/templates/claude/agents/product-owner.md +51 -0
  36. package/templates/claude/agents/prompt-engineer.md +33 -0
  37. package/templates/claude/agents/qa-e2e.md +52 -0
  38. package/templates/claude/agents/qa-fuzzer.md +24 -0
  39. package/templates/claude/agents/qa-integration.md +21 -0
  40. package/templates/claude/agents/qa-orchestrator.md +40 -0
  41. package/templates/claude/agents/qa-perf.md +40 -0
  42. package/templates/claude/agents/qa-unit.md +39 -0
  43. package/templates/claude/agents/rag-designer.md +54 -0
  44. package/templates/claude/agents/retention.md +85 -0
  45. package/templates/claude/agents/security.md +48 -0
  46. package/templates/claude/agents/seo-specialist.md +106 -0
  47. package/templates/claude/agents/test-engineer.md +48 -0
  48. package/templates/claude/agents/tool-designer.md +32 -0
  49. package/templates/claude/agents/ui-designer.md +37 -0
  50. package/templates/claude/agents/ux-designer.md +38 -0
  51. package/templates/claude/commands/README.md +95 -0
  52. package/templates/claude/commands/advise.md +80 -0
  53. package/templates/claude/commands/audit/analyze-code-ia-practices.md +75 -0
  54. package/templates/claude/commands/audit/audit.md +35 -0
  55. package/templates/claude/commands/audit/contract-check.md +21 -0
  56. package/templates/claude/commands/audit/deep-analysis.md +48 -0
  57. package/templates/claude/commands/audit/deps-audit.md +49 -0
  58. package/templates/claude/commands/audit/security-setup.md +35 -0
  59. package/templates/claude/commands/audit/seo-audit.md +63 -0
  60. package/templates/claude/commands/audit/tech-debt-sweep.md +35 -0
  61. package/templates/claude/commands/bug-hunt.md +42 -0
  62. package/templates/claude/commands/claude-md.md +36 -0
  63. package/templates/claude/commands/close-version.md +25 -0
  64. package/templates/claude/commands/context-refresh.md +19 -0
  65. package/templates/claude/commands/context-stats.md +15 -0
  66. package/templates/claude/commands/dashboard.md +66 -0
  67. package/templates/claude/commands/distill-apply.md +19 -0
  68. package/templates/claude/commands/distill-sessions.md +26 -0
  69. package/templates/claude/commands/fleet.md +47 -0
  70. package/templates/claude/commands/forge/forge-audit.md +16 -0
  71. package/templates/claude/commands/forge/forge-budget.md +16 -0
  72. package/templates/claude/commands/forge/forge-deprecate.md +16 -0
  73. package/templates/claude/commands/forge/forge-doctor.md +17 -0
  74. package/templates/claude/commands/forge/forge-eval.md +16 -0
  75. package/templates/claude/commands/forge/forge-fallback-test.md +17 -0
  76. package/templates/claude/commands/forge/forge-killswitch.md +17 -0
  77. package/templates/claude/commands/forge/forge-list.md +17 -0
  78. package/templates/claude/commands/forge/forge-new.md +41 -0
  79. package/templates/claude/commands/forge/forge-policy.md +16 -0
  80. package/templates/claude/commands/forge/forge-redteam.md +17 -0
  81. package/templates/claude/commands/forge/forge-refresh-matrix.md +20 -0
  82. package/templates/claude/commands/forge/forge-route.md +17 -0
  83. package/templates/claude/commands/forge/forge-show.md +16 -0
  84. package/templates/claude/commands/landing-page.md +71 -0
  85. package/templates/claude/commands/log-session.md +59 -0
  86. package/templates/claude/commands/media-gen.md +93 -0
  87. package/templates/claude/commands/new-adr.md +30 -0
  88. package/templates/claude/commands/pipeline/dev-start.md +64 -0
  89. package/templates/claude/commands/pipeline/pipeline.md +36 -0
  90. package/templates/claude/commands/pipeline/resume.md +70 -0
  91. package/templates/claude/commands/pipeline/retro.md +34 -0
  92. package/templates/claude/commands/pipeline/runs.md +63 -0
  93. package/templates/claude/commands/pipeline/ship.md +54 -0
  94. package/templates/claude/commands/pipeline/workflow.md +85 -0
  95. package/templates/claude/commands/playbook.md +27 -0
  96. package/templates/claude/commands/predictions-review.md +28 -0
  97. package/templates/claude/commands/qa/qa-signoff.md +24 -0
  98. package/templates/claude/commands/qa/scaffold-tests.md +27 -0
  99. package/templates/claude/commands/qa/test-plan.md +26 -0
  100. package/templates/claude/commands/qa/visual-test.md +42 -0
  101. package/templates/claude/commands/roadmap.md +48 -0
  102. package/templates/claude/commands/setup/aidevtool-from0.md +104 -0
  103. package/templates/claude/commands/setup/context-config.md +25 -0
  104. package/templates/claude/commands/setup/context-doctor.md +21 -0
  105. package/templates/claude/commands/setup/context-level.md +17 -0
  106. package/templates/claude/commands/setup/setupcontextdevkit.md +121 -0
  107. package/templates/claude/commands/simulate-impact.md +32 -0
  108. package/templates/claude/commands/squad.md +44 -0
  109. package/templates/claude/commands/state.md +21 -0
  110. package/templates/claude/commands/token-report.md +29 -0
  111. package/templates/claude/commands/tune-agents.md +35 -0
  112. package/templates/claude/commands/vcs/claim.md +18 -0
  113. package/templates/claude/commands/vcs/git.md +83 -0
  114. package/templates/claude/commands/vcs/release.md +15 -0
  115. package/templates/claude/commands/vcs/worktree-new.md +18 -0
  116. package/templates/claude/commands/watch.md +47 -0
  117. package/templates/contextkit/.env.example +36 -0
  118. package/templates/contextkit/CLAUDE.child.md.tpl +38 -0
  119. package/templates/contextkit/README.md +74 -0
  120. package/templates/contextkit/behaviors-examples.md +183 -0
  121. package/templates/contextkit/behaviors.md +116 -0
  122. package/templates/contextkit/best-practices.md +323 -0
  123. package/templates/contextkit/config.json +66 -0
  124. package/templates/contextkit/detectors/README.md +45 -0
  125. package/templates/contextkit/detectors/example-detector.mjs.example +25 -0
  126. package/templates/contextkit/instrucoes.md +114 -0
  127. package/templates/contextkit/memory/GLOSSARY.md +13 -0
  128. package/templates/contextkit/memory/SESSIONS.md +9 -0
  129. package/templates/contextkit/memory/WORKSPACE.md +7 -0
  130. package/templates/contextkit/memory/business-rules/_TEMPLATE.md +33 -0
  131. package/templates/contextkit/memory/decisions/0000-record-architecture-decisions.md +34 -0
  132. package/templates/contextkit/memory/decisions/_TEMPLATE.md +25 -0
  133. package/templates/contextkit/memory/predictions/.gitkeep +0 -0
  134. package/templates/contextkit/memory/roadmap.md +28 -0
  135. package/templates/contextkit/memory/sessions/.gitkeep +0 -0
  136. package/templates/contextkit/memory/workflows/.gitkeep +0 -0
  137. package/templates/contextkit/pipeline/backlog/.gitkeep +0 -0
  138. package/templates/contextkit/pipeline/conclusion/.gitkeep +0 -0
  139. package/templates/contextkit/pipeline/devpipeline.md +9 -0
  140. package/templates/contextkit/pipeline/testing/.gitkeep +0 -0
  141. package/templates/contextkit/pipeline/working/.gitkeep +0 -0
  142. package/templates/contextkit/review-protocol.md +214 -0
  143. package/templates/contextkit/runtime/config/defaults.mjs +215 -0
  144. package/templates/contextkit/runtime/config/levels.mjs +42 -0
  145. package/templates/contextkit/runtime/config/load.mjs +105 -0
  146. package/templates/contextkit/runtime/config/paths.mjs +92 -0
  147. package/templates/contextkit/runtime/config/presets.mjs +47 -0
  148. package/templates/contextkit/runtime/config/schema.mjs +88 -0
  149. package/templates/contextkit/runtime/config/settings-compose.mjs +55 -0
  150. package/templates/contextkit/runtime/git-hooks/commit-msg.mjs +55 -0
  151. package/templates/contextkit/runtime/git-hooks/pre-commit.mjs +47 -0
  152. package/templates/contextkit/runtime/git-hooks/pre-push.mjs +102 -0
  153. package/templates/contextkit/runtime/hooks/boot-context-readers.mjs +111 -0
  154. package/templates/contextkit/runtime/hooks/boot-signals.mjs +135 -0
  155. package/templates/contextkit/runtime/hooks/check-registration.mjs +228 -0
  156. package/templates/contextkit/runtime/hooks/concurrency-guard.mjs +110 -0
  157. package/templates/contextkit/runtime/hooks/ledger.mjs +231 -0
  158. package/templates/contextkit/runtime/hooks/md-extract.mjs +65 -0
  159. package/templates/contextkit/runtime/hooks/path-classification.mjs +62 -0
  160. package/templates/contextkit/runtime/hooks/safe-io.mjs +84 -0
  161. package/templates/contextkit/runtime/hooks/session-digest-core.mjs +85 -0
  162. package/templates/contextkit/runtime/hooks/session-start.mjs +248 -0
  163. package/templates/contextkit/runtime/hooks/simulate-gate.mjs +108 -0
  164. package/templates/contextkit/runtime/hooks/track-edits.mjs +154 -0
  165. package/templates/contextkit/runtime/providers/media/_adapter.mjs +120 -0
  166. package/templates/contextkit/runtime/providers/media/nano-banana.mjs +110 -0
  167. package/templates/contextkit/runtime/providers/media/veo.mjs +162 -0
  168. package/templates/contextkit/runtime/providers/review/_adapter.mjs +71 -0
  169. package/templates/contextkit/runtime/providers/review/detect.mjs +115 -0
  170. package/templates/contextkit/runtime/providers/review/gh.mjs +103 -0
  171. package/templates/contextkit/runtime/state/state-io.mjs +172 -0
  172. package/templates/contextkit/runtime/statusline.mjs +51 -0
  173. package/templates/contextkit/squads/README.md +115 -0
  174. package/templates/contextkit/squads/_BRIEFING.md.tpl +27 -0
  175. package/templates/contextkit/squads/agent-forge/README.md +69 -0
  176. package/templates/contextkit/squads/agent-forge/ROADMAP.md +108 -0
  177. package/templates/contextkit/squads/agent-forge/best-practices.md +89 -0
  178. package/templates/contextkit/squads/agent-forge/cli/forge-admin.mjs +132 -0
  179. package/templates/contextkit/squads/agent-forge/cli/forge-eval-cli.mjs +163 -0
  180. package/templates/contextkit/squads/agent-forge/cli/forge-new.mjs +97 -0
  181. package/templates/contextkit/squads/agent-forge/cli/forge-ops.mjs +177 -0
  182. package/templates/contextkit/squads/agent-forge/lib/architect.mjs +112 -0
  183. package/templates/contextkit/squads/agent-forge/lib/eval-designer.mjs +133 -0
  184. package/templates/contextkit/squads/agent-forge/lib/eval-runner.mjs +167 -0
  185. package/templates/contextkit/squads/agent-forge/lib/governance-officer.mjs +178 -0
  186. package/templates/contextkit/squads/agent-forge/lib/package-ops.mjs +101 -0
  187. package/templates/contextkit/squads/agent-forge/lib/packager.mjs +219 -0
  188. package/templates/contextkit/squads/agent-forge/lib/prompt-gen.mjs +122 -0
  189. package/templates/contextkit/squads/agent-forge/lib/rag-designer.mjs +102 -0
  190. package/templates/contextkit/squads/agent-forge/lib/router.mjs +165 -0
  191. package/templates/contextkit/squads/agent-forge/lib/tool-gen.mjs +113 -0
  192. package/templates/contextkit/squads/agent-forge/lib/yaml.mjs +47 -0
  193. package/templates/contextkit/squads/agent-forge/pipeline.yaml +65 -0
  194. package/templates/contextkit/squads/agent-forge/router/capability-matrix.json +112 -0
  195. package/templates/contextkit/squads/agent-forge/router/decision-rules.json +120 -0
  196. package/templates/contextkit/squads/agent-forge/templates/agent-package/.agentforgerc +12 -0
  197. package/templates/contextkit/squads/agent-forge/templates/agent-package/CHANGELOG.md +13 -0
  198. package/templates/contextkit/squads/agent-forge/templates/agent-package/LICENSE +5 -0
  199. package/templates/contextkit/squads/agent-forge/templates/agent-package/README.md +39 -0
  200. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/go/README.md +10 -0
  201. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/go/agent.go +14 -0
  202. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/go/go.mod +3 -0
  203. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/node/README.md +11 -0
  204. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/node/index.js +53 -0
  205. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/node/package.json +9 -0
  206. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/python/README.md +10 -0
  207. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/python/agent.py +16 -0
  208. package/templates/contextkit/squads/agent-forge/templates/agent-package/adapters/python/pyproject.toml +10 -0
  209. package/templates/contextkit/squads/agent-forge/templates/agent-package/evals/golden.jsonl +1 -0
  210. package/templates/contextkit/squads/agent-forge/templates/agent-package/evals/red-team.jsonl +3 -0
  211. package/templates/contextkit/squads/agent-forge/templates/agent-package/evals/rubric.yaml +14 -0
  212. package/templates/contextkit/squads/agent-forge/templates/agent-package/evals/run-eval.md +17 -0
  213. package/templates/contextkit/squads/agent-forge/templates/agent-package/evals/thresholds.yaml +18 -0
  214. package/templates/contextkit/squads/agent-forge/templates/agent-package/examples/basic.node.md +17 -0
  215. package/templates/contextkit/squads/agent-forge/templates/agent-package/examples/with-fallback.node.md +24 -0
  216. package/templates/contextkit/squads/agent-forge/templates/agent-package/examples/with-rag.python.md +20 -0
  217. package/templates/contextkit/squads/agent-forge/templates/agent-package/governance/audit.schema.json +23 -0
  218. package/templates/contextkit/squads/agent-forge/templates/agent-package/governance/compliance.policy.yaml +43 -0
  219. package/templates/contextkit/squads/agent-forge/templates/agent-package/governance/cost.policy.yaml +36 -0
  220. package/templates/contextkit/squads/agent-forge/templates/agent-package/governance/fallback-chain.yaml +16 -0
  221. package/templates/contextkit/squads/agent-forge/templates/agent-package/governance/quality.policy.yaml +43 -0
  222. package/templates/contextkit/squads/agent-forge/templates/agent-package/manifest.yaml +91 -0
  223. package/templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.anthropic.md +19 -0
  224. package/templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.canonical.md +25 -0
  225. package/templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.deepseek.md +21 -0
  226. package/templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.google.md +19 -0
  227. package/templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.ollama.md +21 -0
  228. package/templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.openai.md +20 -0
  229. package/templates/contextkit/squads/agent-forge/templates/agent-package/rag/config.yaml +17 -0
  230. package/templates/contextkit/squads/agent-forge/templates/agent-package/rag/index/.gitkeep +3 -0
  231. package/templates/contextkit/squads/agent-forge/templates/agent-package/rag/ingestion/chunker.config.yaml +6 -0
  232. package/templates/contextkit/squads/agent-forge/templates/agent-package/rag/ingestion/sources.yaml +8 -0
  233. package/templates/contextkit/squads/agent-forge/templates/agent-package/rag/retrieval/query-template.md +16 -0
  234. package/templates/contextkit/squads/agent-forge/templates/agent-package/rag/retrieval/rerank.config.yaml +6 -0
  235. package/templates/contextkit/squads/agent-forge/templates/agent-package/tools/adapters/anthropic.tools.json +11 -0
  236. package/templates/contextkit/squads/agent-forge/templates/agent-package/tools/adapters/deepseek.tools.json +14 -0
  237. package/templates/contextkit/squads/agent-forge/templates/agent-package/tools/adapters/google.tools.json +11 -0
  238. package/templates/contextkit/squads/agent-forge/templates/agent-package/tools/adapters/ollama.tools.json +14 -0
  239. package/templates/contextkit/squads/agent-forge/templates/agent-package/tools/adapters/openai.tools.json +14 -0
  240. package/templates/contextkit/squads/agent-forge/templates/agent-package/tools/schemas.canonical.json +25 -0
  241. package/templates/contextkit/starters/tanstack/README.md +86 -0
  242. package/templates/contextkit/starters/tanstack/index.html +12 -0
  243. package/templates/contextkit/starters/tanstack/package.json +25 -0
  244. package/templates/contextkit/starters/tanstack/src/main.tsx +40 -0
  245. package/templates/contextkit/starters/tanstack/src/router.tsx +12 -0
  246. package/templates/contextkit/starters/tanstack/src/routes/__root.tsx +10 -0
  247. package/templates/contextkit/starters/tanstack/src/routes/index.tsx +17 -0
  248. package/templates/contextkit/starters/tanstack/tsconfig.json +19 -0
  249. package/templates/contextkit/starters/tanstack/vite.config.ts +10 -0
  250. package/templates/contextkit/tools/scripts/adr-digest-core.mjs +42 -0
  251. package/templates/contextkit/tools/scripts/adr-digest.mjs +78 -0
  252. package/templates/contextkit/tools/scripts/agent-tuning.mjs +74 -0
  253. package/templates/contextkit/tools/scripts/aiso-audit.mjs +174 -0
  254. package/templates/contextkit/tools/scripts/audit-shared.mjs +129 -0
  255. package/templates/contextkit/tools/scripts/claim.mjs +133 -0
  256. package/templates/contextkit/tools/scripts/claude-md.mjs +123 -0
  257. package/templates/contextkit/tools/scripts/clean-drive.mjs +78 -0
  258. package/templates/contextkit/tools/scripts/context-config.mjs +111 -0
  259. package/templates/contextkit/tools/scripts/context-level.mjs +98 -0
  260. package/templates/contextkit/tools/scripts/context-pack.mjs +120 -0
  261. package/templates/contextkit/tools/scripts/contract-scan.mjs +186 -0
  262. package/templates/contextkit/tools/scripts/dashboard-data.mjs +198 -0
  263. package/templates/contextkit/tools/scripts/dashboard-html.mjs +215 -0
  264. package/templates/contextkit/tools/scripts/dashboard-server.mjs +129 -0
  265. package/templates/contextkit/tools/scripts/dashboard.mjs +107 -0
  266. package/templates/contextkit/tools/scripts/deep-analysis.mjs +62 -0
  267. package/templates/contextkit/tools/scripts/deps-audit.mjs +201 -0
  268. package/templates/contextkit/tools/scripts/detect-stack.mjs +164 -0
  269. package/templates/contextkit/tools/scripts/distill-detect.mjs +90 -0
  270. package/templates/contextkit/tools/scripts/doctor.mjs +165 -0
  271. package/templates/contextkit/tools/scripts/fleet.mjs +170 -0
  272. package/templates/contextkit/tools/scripts/generate-context.mjs +142 -0
  273. package/templates/contextkit/tools/scripts/gh-alerts.mjs +117 -0
  274. package/templates/contextkit/tools/scripts/git.mjs +97 -0
  275. package/templates/contextkit/tools/scripts/home.mjs +106 -0
  276. package/templates/contextkit/tools/scripts/mark-simulation.mjs +78 -0
  277. package/templates/contextkit/tools/scripts/media-gen.mjs +154 -0
  278. package/templates/contextkit/tools/scripts/pipeline-board.mjs +74 -0
  279. package/templates/contextkit/tools/scripts/pipeline-prioritize.mjs +68 -0
  280. package/templates/contextkit/tools/scripts/pipeline-session.mjs +99 -0
  281. package/templates/contextkit/tools/scripts/pipeline-validate.mjs +136 -0
  282. package/templates/contextkit/tools/scripts/pipeline.mjs +302 -0
  283. package/templates/contextkit/tools/scripts/playbook.mjs +123 -0
  284. package/templates/contextkit/tools/scripts/predictions-review.mjs +113 -0
  285. package/templates/contextkit/tools/scripts/release.mjs +60 -0
  286. package/templates/contextkit/tools/scripts/resume.mjs +114 -0
  287. package/templates/contextkit/tools/scripts/roadmap.mjs +86 -0
  288. package/templates/contextkit/tools/scripts/runs.mjs +116 -0
  289. package/templates/contextkit/tools/scripts/seo-audit.mjs +150 -0
  290. package/templates/contextkit/tools/scripts/session-digest.mjs +89 -0
  291. package/templates/contextkit/tools/scripts/session-reindex.mjs +91 -0
  292. package/templates/contextkit/tools/scripts/setup-complete.mjs +69 -0
  293. package/templates/contextkit/tools/scripts/squad-meta.mjs +23 -0
  294. package/templates/contextkit/tools/scripts/squad-pipeline-condition.mjs +192 -0
  295. package/templates/contextkit/tools/scripts/squad-pipeline.mjs +301 -0
  296. package/templates/contextkit/tools/scripts/squad.mjs +80 -0
  297. package/templates/contextkit/tools/scripts/stats.mjs +138 -0
  298. package/templates/contextkit/tools/scripts/sync-check.mjs +235 -0
  299. package/templates/contextkit/tools/scripts/tech-debt-detectors.mjs +76 -0
  300. package/templates/contextkit/tools/scripts/tech-debt-scan.mjs +164 -0
  301. package/templates/contextkit/tools/scripts/token-report.mjs +153 -0
  302. package/templates/contextkit/tools/scripts/visual-test.mjs +132 -0
  303. package/templates/contextkit/tools/scripts/watch.mjs +106 -0
  304. package/templates/contextkit/tools/scripts/workflow.mjs +136 -0
  305. package/templates/contextkit/tools/scripts/workspace-sync.mjs +220 -0
  306. package/templates/contextkit/tools/scripts/worktree-new.mjs +50 -0
  307. package/templates/contextkit/workflows/L1-static-loading.md +59 -0
  308. package/templates/contextkit/workflows/L2-session-ledger.md +86 -0
  309. package/templates/contextkit/workflows/L3-multi-session.md +80 -0
  310. package/templates/contextkit/workflows/L4-squads.md +68 -0
  311. package/templates/contextkit/workflows/L5-proactive.md +88 -0
  312. package/templates/contextkit/workflows/README.md +47 -0
  313. package/templates/contextkit/workflows/playbooks/distillation-cycle.md +74 -0
  314. package/templates/contextkit/workflows/playbooks/landing-page.md +197 -0
  315. package/templates/contextkit/workflows/playbooks/security-batch.md +68 -0
  316. package/templates/contextkit/workflows/playbooks/seo-aiso.md +288 -0
  317. package/templates/contextkit/workflows/playbooks/simulate-impact.md +83 -0
  318. package/templates/contextkit/workflows/playbooks/tanstack.md +164 -0
  319. package/templates/contextkit/workflows/playbooks/tech-debt-sweep.md +77 -0
  320. package/templates/docs/CHANGELOG.md.tpl +11 -0
  321. package/templates/gitattributes +3 -0
  322. package/templates/github/ISSUE_TEMPLATE/bug_report.md +30 -0
  323. package/templates/github/ISSUE_TEMPLATE/feature_request.md +22 -0
  324. package/templates/github/PULL_REQUEST_TEMPLATE.md +27 -0
  325. package/templates/github/dependabot.yml +27 -0
  326. package/templates/github/workflows/quality.yml +36 -0
  327. package/templates/github/workflows/security.yml +54 -0
  328. package/tools/install/cli.mjs +62 -0
  329. package/tools/install/fs.mjs +56 -0
  330. package/tools/install/git.mjs +114 -0
  331. package/tools/install/project.mjs +51 -0
  332. package/tools/install/uninstall.mjs +54 -0
  333. package/tools/integration-test-compozy.mjs +88 -0
  334. package/tools/integration-test-guards.mjs +269 -0
  335. package/tools/integration-test-tooling-agent-forge.mjs +189 -0
  336. package/tools/integration-test-tooling-pipeline.mjs +164 -0
  337. package/tools/integration-test-tooling.mjs +172 -0
  338. package/tools/integration-test.mjs +228 -0
  339. package/tools/it-helpers.mjs +60 -0
  340. package/tools/selfcheck-agent-forge-ops.mjs +107 -0
  341. package/tools/selfcheck-agent-forge.mjs +304 -0
  342. package/tools/selfcheck-config.mjs +80 -0
  343. package/tools/selfcheck-runtime.mjs +135 -0
  344. package/tools/selfcheck-source.mjs +326 -0
  345. package/tools/selfcheck.mjs +268 -0
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `/workflow` — thin macro that chains `/roadmap` → `/new-adr` → `/pipeline`
4
+ * → `/ship` into a single explicit narrative (ticket 041, Compozy follow-
5
+ * through). The script does NOT invoke the other commands — Claude does that
6
+ * by reading the slash-command briefing. This script owns the **breadcrumb
7
+ * file** so the user can `/workflow status` or `/workflow resume <slug>`
8
+ * across sessions / machines.
9
+ *
10
+ * Subcommands:
11
+ * workflow.mjs new <slug> — create breadcrumb, set first phase pending
12
+ * workflow.mjs advance <slug> [ref] — mark current phase done, advance pointer
13
+ * workflow.mjs status — list every workflow + its current phase
14
+ * workflow.mjs status <slug> — show one workflow's breadcrumb
15
+ * workflow.mjs status --json — machine-readable
16
+ *
17
+ * Breadcrumb path: `contextkit/memory/workflows/<slug>.md`. One file per slug;
18
+ * the YAML-ish frontmatter is parsed by hand (no yaml dep). The body carries
19
+ * one bullet per phase transition for human inspection.
20
+ *
21
+ * Zero-dep, pure ESM. Slug is kebab-case `[a-z0-9-]`.
22
+ */
23
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
24
+ import { resolve } from 'node:path';
25
+ import { pathsFor } from '../../runtime/config/paths.mjs';
26
+
27
+ const ROOT = process.cwd();
28
+ const WF_DIR = resolve(pathsFor(ROOT).memory, 'workflows');
29
+ const PHASES = ['roadmap', 'adr', 'tickets', 'ship'];
30
+ const SLUG_RE = /^[a-z0-9][a-z0-9-]{0,60}$/;
31
+
32
+ function ensureDir() { mkdirSync(WF_DIR, { recursive: true }); }
33
+
34
+ function fileFor(slug) { return resolve(WF_DIR, `${slug}.md`); }
35
+
36
+ /**
37
+ * Parses the lightweight YAML-ish frontmatter. Recognises three top-level keys
38
+ * (slug, started, currentPhase) + a `phases:` list with one entry per phase.
39
+ * Body content after `---` is preserved on update so user notes survive.
40
+ */
41
+ function parse(text) {
42
+ const fmMatch = text.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
43
+ if (!fmMatch) return null;
44
+ const fm = fmMatch[1];
45
+ const body = fmMatch[2] ?? '';
46
+ const slug = (fm.match(/^slug:\s*(.+)$/m) || [])[1]?.trim();
47
+ const started = (fm.match(/^started:\s*(.+)$/m) || [])[1]?.trim();
48
+ const currentPhase = (fm.match(/^currentPhase:\s*(.+)$/m) || [])[1]?.trim();
49
+ const phases = {};
50
+ for (const p of PHASES) {
51
+ const status = (fm.match(new RegExp(`^${p}:\\s*(\\S+)(?:\\s+(.+))?$`, 'm')) || [])[1]?.trim() || 'pending';
52
+ const ref = (fm.match(new RegExp(`^${p}-ref:\\s*(.+)$`, 'm')) || [])[1]?.trim() || '';
53
+ phases[p] = { status, ref };
54
+ }
55
+ return { slug, started, currentPhase, phases, body };
56
+ }
57
+
58
+ function render(wf) {
59
+ const lines = ['---', `slug: ${wf.slug}`, `started: ${wf.started}`, `currentPhase: ${wf.currentPhase}`];
60
+ for (const p of PHASES) { lines.push(`${p}: ${wf.phases[p].status}`); if (wf.phases[p].ref) lines.push(`${p}-ref: ${wf.phases[p].ref}`); }
61
+ lines.push('---');
62
+ lines.push('');
63
+ lines.push(`# Workflow — ${wf.slug}`);
64
+ lines.push('');
65
+ // Strip a previous identical heading from the preserved body so re-rendering doesn't dup.
66
+ const cleanBody = wf.body.replace(/^\s*#\s*Workflow\s+—\s+\S+\s*\n+/m, '').trim();
67
+ lines.push(cleanBody || '_(history will accumulate here as phases advance)_');
68
+ lines.push('');
69
+ return lines.join('\n');
70
+ }
71
+
72
+ function appendHistory(wf, line) { wf.body = (wf.body.trim() ? wf.body.trim() + '\n' : '') + `- ${line}`; return wf; }
73
+
74
+ function cmdNew(slug) {
75
+ if (!SLUG_RE.test(slug)) { console.error(`✗ slug must match ${SLUG_RE} (got "${slug}")`); process.exit(1); }
76
+ ensureDir();
77
+ if (existsSync(fileFor(slug))) { console.error(`✗ workflow "${slug}" already exists at ${fileFor(slug)}`); process.exit(1); }
78
+ const started = new Date().toISOString();
79
+ const wf = { slug, started, currentPhase: 'roadmap', phases: Object.fromEntries(PHASES.map((p) => [p, { status: 'pending', ref: '' }])), body: '' };
80
+ appendHistory(wf, `${started.slice(0, 10)} · created · next phase: roadmap`);
81
+ writeFileSync(fileFor(slug), render(wf));
82
+ console.log(`▶ Workflow "${slug}" created. Next phase: /roadmap (then \`workflow.mjs advance ${slug} <ref>\`).`);
83
+ }
84
+
85
+ function cmdAdvance(slug, ref) {
86
+ if (!existsSync(fileFor(slug))) { console.error(`✗ workflow "${slug}" not found.`); process.exit(1); }
87
+ const wf = parse(readFileSync(fileFor(slug), 'utf-8'));
88
+ if (!wf) { console.error(`✗ workflow "${slug}" has a malformed breadcrumb.`); process.exit(1); }
89
+ const idx = PHASES.indexOf(wf.currentPhase);
90
+ if (idx < 0) { console.error(`✗ workflow "${slug}" has an unknown currentPhase: ${wf.currentPhase}`); process.exit(1); }
91
+ wf.phases[wf.currentPhase].status = 'done';
92
+ if (ref) wf.phases[wf.currentPhase].ref = ref;
93
+ const nextPhase = PHASES[idx + 1];
94
+ const stamp = new Date().toISOString().slice(0, 10);
95
+ if (!nextPhase) {
96
+ wf.currentPhase = 'done';
97
+ appendHistory(wf, `${stamp} · ${PHASES[idx]} done${ref ? ` (ref: ${ref})` : ''} · workflow complete`);
98
+ writeFileSync(fileFor(slug), render(wf));
99
+ console.log(`✅ Workflow "${slug}" complete — all 4 phases done.`);
100
+ return;
101
+ }
102
+ wf.currentPhase = nextPhase;
103
+ appendHistory(wf, `${stamp} · ${PHASES[idx]} done${ref ? ` (ref: ${ref})` : ''} · next phase: ${nextPhase}`);
104
+ writeFileSync(fileFor(slug), render(wf));
105
+ console.log(`▶ Workflow "${slug}" advanced — ${PHASES[idx]} → ${nextPhase}.`);
106
+ }
107
+
108
+ function listAll() {
109
+ ensureDir();
110
+ return readdirSync(WF_DIR).filter((f) => f.endsWith('.md') && f !== '.gitkeep')
111
+ .map((f) => parse(readFileSync(resolve(WF_DIR, f), 'utf-8'))).filter(Boolean)
112
+ .sort((a, b) => b.started.localeCompare(a.started));
113
+ }
114
+
115
+ function cmdStatus(target, asJson) {
116
+ const all = listAll();
117
+ const filtered = target && target !== '--json' ? all.filter((w) => w.slug === target) : all;
118
+ if (asJson) { console.log(JSON.stringify(filtered, null, 2)); return; }
119
+ if (filtered.length === 0) { console.log(target ? ` Workflow "${target}" not found.` : ' No workflows yet. Start one with `workflow.mjs new <slug>`.'); return; }
120
+ for (const w of filtered) {
121
+ console.log(`\n ${w.slug} (started ${w.started.slice(0, 10)}) — current: ${w.currentPhase}`);
122
+ for (const p of PHASES) {
123
+ const s = w.phases[p];
124
+ const marker = s.status === 'done' ? '✓' : s.status === 'in-progress' ? '◐' : '·';
125
+ const refNote = s.ref ? ` → ${s.ref}` : '';
126
+ console.log(` ${marker} ${p.padEnd(8)} ${s.status}${refNote}`);
127
+ }
128
+ }
129
+ console.log('');
130
+ }
131
+
132
+ const cmd = process.argv[2];
133
+ if (cmd === 'new') cmdNew(process.argv[3]);
134
+ else if (cmd === 'advance') cmdAdvance(process.argv[3], process.argv[4]);
135
+ else if (cmd === 'status') cmdStatus(process.argv[3], process.argv.includes('--json'));
136
+ else { console.error('Usage: workflow.mjs <new <slug> | advance <slug> [ref] | status [<slug> | --json]>'); process.exit(1); }
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Aggregates active session claims into `contextkit/memory/WORKSPACE.md`.
4
+ *
5
+ * Each active session writes its own JSON under `.claude/.workspace/<sid>.json`
6
+ * (gitignored local state). This scans them, drops stale entries (no heartbeat
7
+ * for > 1h), and rebuilds the committed markdown summary.
8
+ *
9
+ * Since [ADR-0015 §B](../../memory/decisions/0015-pipeline-dsl-working-stage-and-multi-session-work-claims.md),
10
+ * the summary also surfaces **task ownership across sessions** — which session
11
+ * owns which DevPipeline task right now, and any cross-session collision. A
12
+ * task whose owning session has been silent past `pipeline.workingStaleAfterMinutes`
13
+ * (default 90) is auto-evicted: the task file moves from `working/` back to
14
+ * `backlog/` and the owner detaches.
15
+ *
16
+ * Usage: node contextkit/tools/scripts/workspace-sync.mjs
17
+ */
18
+ import { existsSync, renameSync, readFileSync, readdirSync } from 'node:fs';
19
+ import { readdir, readFile } from 'node:fs/promises';
20
+ import { resolve } from 'node:path';
21
+ import { loadConfigSync } from '../../runtime/config/load.mjs';
22
+ import { pathsFor } from '../../runtime/config/paths.mjs';
23
+ import { writeFileAtomic, writeFileAtomicSync } from '../../runtime/hooks/safe-io.mjs';
24
+ import { readState, writeState } from '../../runtime/state/state-io.mjs';
25
+
26
+ const ROOT = process.cwd();
27
+ const WORKSPACE_DIR = resolve(ROOT, '.claude/.workspace');
28
+ const OUTPUT_PATH = pathsFor(ROOT).workspaceIndex;
29
+ const PIPE_DIR = pathsFor(ROOT).pipeline;
30
+ const STALE_AFTER_MS = 60 * 60 * 1000;
31
+ const DEFAULT_TASK_STALE_MIN = 90;
32
+
33
+ async function loadClaims() {
34
+ let files = [];
35
+ try {
36
+ files = await readdir(WORKSPACE_DIR);
37
+ } catch {
38
+ return [];
39
+ }
40
+ const claims = [];
41
+ for (const filename of files) {
42
+ if (!filename.endsWith('.json')) continue;
43
+ try {
44
+ claims.push(JSON.parse(await readFile(resolve(WORKSPACE_DIR, filename), 'utf-8')));
45
+ } catch {
46
+ /* skip malformed */
47
+ }
48
+ }
49
+ return claims;
50
+ }
51
+
52
+ function isStale(claim) {
53
+ if (typeof claim?.lastHeartbeat !== 'number') return true;
54
+ return Date.now() - claim.lastHeartbeat > STALE_AFTER_MS;
55
+ }
56
+
57
+ function relativeTime(ms) {
58
+ const s = Math.floor((Date.now() - ms) / 1000);
59
+ if (s < 60) return `${s}s ago`;
60
+ const m = Math.floor(s / 60);
61
+ if (m < 60) return `${m}m ago`;
62
+ const h = Math.floor(m / 60);
63
+ if (h < 24) return `${h}h ago`;
64
+ return `${Math.floor(h / 24)}d ago`;
65
+ }
66
+
67
+ /**
68
+ * Walks every workspace record's `tasks[]` and evicts any whose heartbeat
69
+ * exceeds `workingStaleAfterMinutes`. Eviction moves the task file from
70
+ * `working/` back to `backlog/`, stamps an audit line in its body, and rewrites
71
+ * the workspace record without that task entry.
72
+ *
73
+ * Returns the set of evicted `{ sid, taskId }` so the caller (rendering) can
74
+ * surface the action. Best-effort I/O — failures don't throw, the workspace
75
+ * file is the source of truth either way.
76
+ *
77
+ * @param {Array<object>} claims — workspace records, in-place mutation allowed
78
+ * @param {number} maxMinutes
79
+ * @returns {Array<{ sid: string, taskId: string }>}
80
+ */
81
+ function evictStaleTasks(claims, maxMinutes) {
82
+ const limit = maxMinutes * 60 * 1000;
83
+ const evicted = [];
84
+ for (const record of claims) {
85
+ if (!Array.isArray(record.tasks) || record.tasks.length === 0) continue;
86
+ const survivors = [];
87
+ for (const task of record.tasks) {
88
+ const ageMs = Date.now() - (task.lastHeartbeat || record.lastHeartbeat || 0);
89
+ if (ageMs <= limit) {
90
+ // Living task: mirror heartbeat into state.json (best-effort, ADR-0015 §C).
91
+ try {
92
+ if (readState(PIPE_DIR, task.id)) writeState(PIPE_DIR, task.id, { lastHeartbeat: task.lastHeartbeat || Date.now() });
93
+ } catch { /* */ }
94
+ survivors.push(task);
95
+ continue;
96
+ }
97
+ const moved = moveTaskFile(task.id, 'working', 'backlog', { sid: record.sessionId, ageMs });
98
+ if (moved) {
99
+ evicted.push({ sid: record.sessionId, taskId: task.id });
100
+ try {
101
+ if (readState(PIPE_DIR, task.id)) writeState(PIPE_DIR, task.id, { status: 'backlog', endedAt: Date.now() });
102
+ } catch { /* */ }
103
+ }
104
+ }
105
+ if (survivors.length !== record.tasks.length) {
106
+ record.tasks = survivors;
107
+ try {
108
+ const sid = (record.sessionId ?? 'unknown').replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64);
109
+ const { ...body } = record;
110
+ writeFileAtomicSync(resolve(WORKSPACE_DIR, `${sid}.json`), JSON.stringify(body, null, 2));
111
+ } catch { /* best-effort */ }
112
+ }
113
+ }
114
+ return evicted;
115
+ }
116
+
117
+ function moveTaskFile(taskId, fromStage, toStage, { sid, ageMs }) {
118
+ try {
119
+ const fromDir = resolve(PIPE_DIR, fromStage);
120
+ if (!existsSync(fromDir)) return false;
121
+ const fileName = readdirSync(fromDir).find((f) => f.startsWith(String(taskId).padStart(3, '0') + '-') && f.endsWith('.md'));
122
+ if (!fileName) return false;
123
+ const fromPath = resolve(fromDir, fileName);
124
+ const toPath = resolve(PIPE_DIR, toStage, fileName);
125
+ let text = readFileSync(fromPath, 'utf-8').replace(/^(status:).*$/m, `status: ${toStage}`);
126
+ const note = `\n> auto-evicted from working/ at ${new Date().toISOString()} — session ${(sid || 'unknown').slice(0, 8)} idle for ${Math.floor(ageMs / 60000)}m\n`;
127
+ if (!text.endsWith('\n')) text += '\n';
128
+ text += note;
129
+ writeFileAtomicSync(fromPath, text);
130
+ renameSync(fromPath, toPath);
131
+ return true;
132
+ } catch {
133
+ return false;
134
+ }
135
+ }
136
+
137
+ function renderTasksTable(active) {
138
+ const rows = [];
139
+ const seen = new Map();
140
+ for (const record of active) {
141
+ if (!Array.isArray(record.tasks)) continue;
142
+ for (const task of record.tasks) {
143
+ const collision = seen.has(task.id);
144
+ seen.set(task.id, (seen.get(task.id) || 0) + 1);
145
+ rows.push({ id: task.id, sid: (record.sessionId ?? '?').slice(0, 8), user: record.user ?? '_unknown_', branch: record.branch ?? '_detached_', started: relativeTime(task.startedAt || Date.now()), heartbeat: relativeTime(task.lastHeartbeat || Date.now()), collision });
146
+ }
147
+ }
148
+ if (rows.length === 0) return [];
149
+ const out = [`## 🔵 Working tasks (${rows.length})`, '', '| Task | Session | User | Branch | Started | Heartbeat |', '| --- | --- | --- | --- | --- | --- |'];
150
+ for (const r of rows) {
151
+ const id = r.collision || (seen.get(r.id) || 0) > 1 ? `⚠️ ${r.id}` : r.id;
152
+ out.push(`| ${id} | \`${r.sid}\` | ${r.user} | \`${r.branch}\` | ${r.started} | ${r.heartbeat} |`);
153
+ }
154
+ out.push('');
155
+ return out;
156
+ }
157
+
158
+ function buildMarkdown(active, stale, evicted) {
159
+ const out = [];
160
+ out.push('# Workspace — Active Sessions');
161
+ out.push('');
162
+ out.push('> ⚠️ **AUTO-GENERATED FILE — DO NOT EDIT BY HAND**.');
163
+ out.push('> Regenerated by `workspace-sync` (runs on pre-commit) from');
164
+ out.push('> `.claude/.workspace/<sid>.json` files maintained by hooks and slash commands.');
165
+ out.push('');
166
+ const tasksSection = renderTasksTable(active);
167
+ if (active.length === 0 && stale.length === 0 && tasksSection.length === 0) {
168
+ out.push('_(No active sessions. The workspace is idle.)_');
169
+ out.push('');
170
+ return out.join('\n');
171
+ }
172
+ out.push(...tasksSection);
173
+ if (active.length > 0) {
174
+ out.push(`## 🟢 Active sessions (${active.length})`);
175
+ out.push('');
176
+ out.push('| Session | User | Branch | Started | Last activity | Claims |');
177
+ out.push('| --- | --- | --- | --- | --- | --- |');
178
+ for (const c of active) {
179
+ const sid = (c.sessionId ?? '?').slice(0, 8);
180
+ const claims = Array.isArray(c.claims) && c.claims.length > 0 ? c.claims.map((cl) => `\`${cl.path}\``).join(', ') : '_(none)_';
181
+ out.push(`| \`${sid}\` | ${c.user ?? '_unknown_'} | \`${c.branch ?? '_detached_'}\` | ${c.startedAt ? relativeTime(c.startedAt) : '?'} | ${c.lastHeartbeat ? relativeTime(c.lastHeartbeat) : '?'} | ${claims} |`);
182
+ }
183
+ out.push('');
184
+ }
185
+ if (stale.length > 0) {
186
+ out.push(`## 🟡 Stale (${stale.length}) — no heartbeat for > 1h`);
187
+ out.push('');
188
+ out.push('| Session | User | Branch | Last activity |');
189
+ out.push('| --- | --- | --- | --- |');
190
+ for (const c of stale) {
191
+ out.push(`| \`${(c.sessionId ?? '?').slice(0, 8)}\` | ${c.user ?? '_unknown_'} | \`${c.branch ?? '_detached_'}\` | ${c.lastHeartbeat ? relativeTime(c.lastHeartbeat) : '?'} |`);
192
+ }
193
+ out.push('');
194
+ }
195
+ if (evicted.length > 0) {
196
+ out.push(`## ♻️ Recently auto-evicted (this run): ${evicted.length}`);
197
+ out.push('');
198
+ for (const ev of evicted) out.push(`- task **${ev.taskId}** (was owned by session \`${ev.sid?.slice(0, 8) ?? '?'}\`) → moved back to \`backlog/\``);
199
+ out.push('');
200
+ }
201
+ out.push('---');
202
+ out.push('');
203
+ out.push('Slash commands: `/claim <path>` to reserve a path · `/pipeline start <id>` to attach a task · `/release` / `/pipeline stop <id>` to free · `/worktree-new <feature>` for parallel work.');
204
+ return out.join('\n');
205
+ }
206
+
207
+ async function main() {
208
+ const claims = await loadClaims();
209
+ const cfg = loadConfigSync(ROOT).pipeline || {};
210
+ const evicted = evictStaleTasks(claims, cfg.workingStaleAfterMinutes || DEFAULT_TASK_STALE_MIN);
211
+ const active = claims.filter((c) => !isStale(c));
212
+ const stale = claims.filter(isStale);
213
+ await writeFileAtomic(OUTPUT_PATH, buildMarkdown(active, stale, evicted));
214
+ console.log(`✅ WORKSPACE.md regenerated — ${active.length} active, ${stale.length} stale, ${evicted.length} task(s) auto-evicted.`);
215
+ }
216
+
217
+ main().catch((err) => {
218
+ console.error('❌ Failed to sync workspace:', err);
219
+ process.exit(1);
220
+ });
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Creates a git worktree + branch for a parallel session on the same machine.
4
+ *
5
+ * Each worktree gets its own `.claude/.sessions/` (it lives outside `.git`),
6
+ * so parallel Claude chats never collide on the ledger or on live edits.
7
+ *
8
+ * Usage: node contextkit/tools/scripts/worktree-new.mjs <feature> [base-branch]
9
+ * Creates branch `feat/<feature>` and worktree `../<repo>-<feature>`.
10
+ */
11
+ import { execFileSync } from 'node:child_process';
12
+ import { basename, resolve } from 'node:path';
13
+
14
+ const ROOT = process.cwd();
15
+
16
+ // execFileSync (argv array, NO shell) so a crafted base-branch arg can never
17
+ // inject — e.g. `worktree-new.mjs feat "HEAD; rm -rf ~"` is passed to git as a
18
+ // single literal revision and simply fails, instead of running the `rm`.
19
+ function git(args) {
20
+ return execFileSync('git', args, { cwd: ROOT, encoding: 'utf-8' }).trim();
21
+ }
22
+
23
+ function main() {
24
+ const feature = process.argv[2];
25
+ const base = process.argv[3] || 'HEAD';
26
+ if (!feature) {
27
+ console.error('Usage: worktree-new.mjs <feature> [base-branch]');
28
+ process.exit(1);
29
+ }
30
+ const slug = feature.replace(/[^a-z0-9-]/gi, '-').toLowerCase();
31
+ const branch = `feat/${slug}`;
32
+ const repoName = basename(ROOT);
33
+ const dest = resolve(ROOT, '..', `${repoName}-${slug}`);
34
+
35
+ try {
36
+ git(['worktree', 'add', '-b', branch, dest, base]);
37
+ } catch (err) {
38
+ console.error(`❌ Could not create worktree: ${err?.message ?? err}`);
39
+ process.exit(1);
40
+ }
41
+
42
+ console.log(`✅ Worktree created.`);
43
+ console.log(` Branch: ${branch}`);
44
+ console.log(` Path: ${dest}`);
45
+ console.log(`\nOpen it in a separate Claude Code window:`);
46
+ console.log(` code "${dest}"`);
47
+ console.log(`\nWhen done: git push -u origin ${branch} (then open a PR).`);
48
+ }
49
+
50
+ main();
@@ -0,0 +1,59 @@
1
+ # L1 — Static loading (auto-load at boot)
2
+
3
+ > Level 1 of the context system. Solves: **"How does Claude start every session
4
+ > already knowing the essentials, without the user explaining them?"**
5
+
6
+ ## How it works
7
+
8
+ When Claude Code opens a session in this directory, it automatically loads:
9
+
10
+ | File / folder | When | Content |
11
+ | --- | --- | --- |
12
+ | `CLAUDE.md` (root) | Always | Stack, immutable rules, the coding constitution, active level. |
13
+ | `<module>/CLAUDE.md` | When editing that subtree | Local rules scoped to a module (see `/claude-md`). |
14
+ | `.claude/agents/<name>.md` | Always (frontmatter) | Squad agents — auto-dispatched when the domain matches (L4+). |
15
+ | `.claude/commands/<name>.md` | Always (frontmatter) | Slash commands available in the chat. |
16
+
17
+ On top of that, the `SessionStart` hook (L2) injects **dynamic** boot context: the
18
+ last registered session, `[Unreleased]` from the changelog, detected drift, active
19
+ claims, and ahead/behind divergence vs `origin/<main>`.
20
+
21
+ ## Hard technical constraints
22
+
23
+ - Claude Code reads from fixed paths: `.claude/settings.json`, `.claude/commands/`,
24
+ `.claude/agents/`. **Do not move** these folders.
25
+ - `.claude/.sessions/` and `.claude/.workspace/` are runtime state (gitignored).
26
+ They persist between sessions but never reach the repo.
27
+ - Everything the platform owns lives under `contextkit/` — the single `PLATFORM_DIR`
28
+ (`contextkit/runtime/config/paths.mjs`). Never hardcode the folder name elsewhere.
29
+
30
+ ## End-to-end flow when Claude opens
31
+
32
+ 1. Claude Code reads root `CLAUDE.md` (the whole system, described tersely).
33
+ 2. Reads `.claude/agents/*.md` — squad agents become available for delegation (L4+).
34
+ 3. Reads `.claude/commands/*.md` — slash commands become available in the input.
35
+ 4. The `SessionStart` hook (`contextkit/runtime/hooks/session-start.mjs`) runs via
36
+ `.claude/settings.json`:
37
+ - silent `git fetch origin` (short timeout, never blocks);
38
+ - drift analysis of previous sessions;
39
+ - a fresh ledger for this session;
40
+ - injection of the boot context.
41
+ 5. Editing a file under a module that has its own `CLAUDE.md` loads those local rules.
42
+
43
+ ## Maintenance rules
44
+
45
+ - **Keep it lean.** Root `CLAUDE.md` is the overview; detail goes into ADRs or linked
46
+ docs. The file warns when it grows past ~200 lines.
47
+ - **Don't duplicate** between root and scoped `CLAUDE.md` — the child complements,
48
+ never repeats.
49
+ - **Don't inflate** `.claude/agents/<name>.md` — the frontmatter is executable; the
50
+ rich briefing lives in `contextkit/squads/<team>/<name>.md` (L4).
51
+ - Slash commands stay in `.claude/commands/`; their narrative playbooks live in
52
+ `contextkit/workflows/playbooks/`.
53
+
54
+ ## When to update
55
+
56
+ - Stack change (lib, framework, runtime) → root `CLAUDE.md` **and** an ADR.
57
+ - New squad agent → `.claude/agents/<name>.md` + `contextkit/squads/<team>/<name>.md`.
58
+ - New slash command → `.claude/commands/<name>.md` (+ a playbook here if it carries
59
+ judgment) + update the command list in root `CLAUDE.md`.
@@ -0,0 +1,86 @@
1
+ # L2 — Session ledger + drift detection
2
+
3
+ > Level 2 of the context system. Solves: **"How do we detect that a session touched
4
+ > important files but was never registered?"**
5
+
6
+ ## The problem
7
+
8
+ L1 loads context, but without instrumentation it relies on the AI's **discipline** to:
9
+ 1. read the history at the start (SESSIONS, CHANGELOG, ADRs), and
10
+ 2. update SESSIONS + CHANGELOG at the end (`/log-session`).
11
+
12
+ If step 2 is skipped, the next session starts blind — silent divergence between the
13
+ real state and the documented one. L2 instruments the system with hooks that
14
+ **detect drift** automatically.
15
+
16
+ ## Components
17
+
18
+ ### Per-session ledger
19
+
20
+ `.claude/.sessions/<sessionId>.json` — gitignored, isolated between parallel chats.
21
+ It records each modification (path, tool, timestamp), whether the session was
22
+ registered, and anti-loop flags. Shared helpers live in
23
+ [`contextkit/runtime/hooks/ledger.mjs`](../runtime/hooks/ledger.mjs).
24
+
25
+ ### Claude Code hooks
26
+
27
+ Wired in `.claude/settings.json` — every script lives in `contextkit/runtime/hooks/`:
28
+
29
+ | Hook | Matcher | Script | Job |
30
+ | --- | --- | --- | --- |
31
+ | `SessionStart` | (always) | `session-start.mjs` | Boot context + drift detection. |
32
+ | `PostToolUse` | `Edit\|Write\|MultiEdit` | `track-edits.mjs` | Append to ledger + heartbeat + cross-claim check. |
33
+ | `Stop` | (always) | `check-registration.mjs` | Nudge if there is unregistered drift. |
34
+
35
+ ### The Stop-hook nudge decision
36
+
37
+ ```
38
+ if stop_hook_active === true → silent (anti-loop)
39
+ if important paths < 2 → silent (small session)
40
+ if registered || SESSIONS touched → silent (already registered)
41
+ if already warned this session → silent
42
+ otherwise → decision: "block"
43
+ (instructs /log-session or justify)
44
+ ```
45
+
46
+ ## What counts as an "important path"
47
+
48
+ Drift detection classifies paths via
49
+ [`contextkit/runtime/hooks/path-classification.mjs`](../runtime/hooks/path-classification.mjs),
50
+ driven by `contextkit/config.json` — **not hardcoded per stack**. By default, source
51
+ code, the platform folder, and CI/config files trigger drift; generated output
52
+ (`node_modules/`, `dist/`, build caches) and the platform's own runtime state
53
+ (`.claude/.sessions/`, `.claude/.workspace/`) do not. Tune the lists with `/context-config`.
54
+
55
+ ## A full session flow
56
+
57
+ ```
58
+ [open session]
59
+ → SessionStart: silent fetch · list prior drift (clear registered ledgers) ·
60
+ init fresh ledger · inject boot context
61
+ [Claude edits]
62
+ → PostToolUse (each Edit/Write/MultiEdit): append paths · refresh heartbeat ·
63
+ warn on cross-claim with another session
64
+ [Claude stops]
65
+ → Stop: check drift · if ≥ 2 unregistered important paths and not yet warned →
66
+ block with "run /log-session OR justify a discardable session"
67
+ ```
68
+
69
+ ## When something goes wrong
70
+
71
+ - **Hook doesn't run** → check `.claude/settings.json` points to the
72
+ `contextkit/runtime/hooks/<name>.mjs` file and that it exists.
73
+ - **False-positive drift** → a classification may be too broad; adjust via
74
+ `/context-config` (record an ADR if it's a real policy change).
75
+ - **Stop hook re-nudging** → the anti-loop flag lives in the ledger; if it repeats,
76
+ the ledger may be getting recreated each Stop — investigate.
77
+ - **Two chats in one worktree** → use a `git worktree` (L3); the ledger is
78
+ per-session but live file edits still collide on one filesystem.
79
+
80
+ ## Do not
81
+
82
+ - Put business logic in a hook.
83
+ - Add external deps to `runtime/hooks/` — Node built-ins only (immutable rule #1).
84
+ - Block the user — hooks are defensive and exit 0 on error. The only intentional
85
+ block is the Stop nudge via `decision: "block"`.
86
+ - Hand-edit `SESSIONS.md` / `WORKSPACE.md` — they are auto-generated indices.
@@ -0,0 +1,80 @@
1
+ # L3 — Parallel multi-session (claims + worktrees)
2
+
3
+ > Level 3. Solves: **"How do we allow multiple Claude sessions (one dev in many
4
+ > chats, or many devs) without state corruption or merge conflicts on shared
5
+ > files?"**
6
+
7
+ ## The problem
8
+
9
+ A naive "one dev / one session" assumption breaks in three ways:
10
+ 1. **A single monolithic ledger** — two sessions overwrite each other.
11
+ 2. **A monolithic `SESSIONS.md`** — two parallel `/log-session` runs guarantee a
12
+ merge conflict.
13
+ 3. **No visible coordination** — nobody knows who is touching what.
14
+
15
+ ## The solution, in four parts
16
+
17
+ ### 1. Per-session ledger (gitignored)
18
+
19
+ `.claude/.sessions/<sid>.json` — one file per session, zero collision. Built in L2;
20
+ the foundation here.
21
+
22
+ ### 2. SESSIONS.md as a generated index
23
+
24
+ `contextkit/memory/SESSIONS.md` is no longer hand-edited. Each session writes its **own
25
+ file** at `contextkit/memory/sessions/<YYYY-MM-DD>-<NN>-<slug>.md`; the index is
26
+ regenerated and refreshed by the `pre-commit` git hook. Two sessions can register in
27
+ parallel — different files, recomposed index.
28
+
29
+ ### 3. WORKSPACE.md — aggregated claims
30
+
31
+ A session reserves paths with `/claim <path…>`:
32
+ - writes/updates `.claude/.workspace/<sid>.json` (gitignored) with session, branch,
33
+ claims, and heartbeat;
34
+ - the aggregate is rendered into `contextkit/memory/WORKSPACE.md` (versioned) and
35
+ refreshed by the pre-commit hook;
36
+ - the `PostToolUse` hook (L2, `concurrency-guard.mjs`) reads **other** sessions'
37
+ `.workspace/*.json` and emits a cross-claim warning if your edit lands inside
38
+ someone else's claim. Free a claim with `/release`.
39
+
40
+ ### 4. Git worktree for parallel chats on one machine
41
+
42
+ ```
43
+ /worktree-new <feature> [base]
44
+ # → ../<repo>-<feature> on branch feat/<feature>
45
+ # each worktree has its own .claude/.sessions/ → zero filesystem collision
46
+ ```
47
+ When the feature is done: `git push -u origin feat/<feature>`, then open a PR.
48
+
49
+ ## Slash commands of this level
50
+
51
+ - `/claim <path…>` — reserve paths for this session.
52
+ - `/release [path]` — free a specific claim, or all of them.
53
+ - `/worktree-new <feature> [base]` — create a worktree + branch for a parallel session.
54
+
55
+ ## Scenarios
56
+
57
+ **You alone, several chats on one machine** → use worktrees. Each chat gets its own
58
+ directory, branch, and isolated `.claude/.sessions/`.
59
+
60
+ **Multiple devs on different machines** → SESSIONS and WORKSPACE are generated (no
61
+ conflict). The CHANGELOG stays single; the "one bullet per line, grouped
62
+ sub-sections" format keeps conflicts small. Before starting: `git fetch && git
63
+ status` (the SessionStart hook does this). Use `/claim` to reserve, and a `feat/<x>`
64
+ branch for large changes.
65
+
66
+ **Two chats in one worktree (not recommended)** → `/log-session` resolves the active
67
+ session via a last-touched pointer; in one shared tree, "last editor wins" can pick
68
+ the wrong session. Worktrees remove the problem at the root (~30s of setup).
69
+
70
+ ## Branch & commit conventions
71
+
72
+ - Branch: `feat/` · `fix/` · `chore/` · `docs/` · `refactor/` · `test/` · `ci/` ·
73
+ `build/` · `perf/` · `style/` · `revert/`.
74
+ - Commit: `<type>(<scope>)?: <subject>` (Conventional Commits) — validated by the
75
+ `commit-msg` git hook.
76
+
77
+ ## Do not
78
+
79
+ - Hand-edit `SESSIONS.md` / `WORKSPACE.md` — regenerated by the pre-commit hook.
80
+ - Run two heavy sessions in one worktree when a worktree would isolate them.