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,62 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Deep analysis — the deterministic aggregator behind `/deep-analysis`.
4
+ *
5
+ * Runs every deterministic scanner the project ships and merges their findings
6
+ * into ONE report, shaped for `pipeline.mjs ingest`. The slash command adds the
7
+ * judgment layer (security/architecture/bugs) on top. Defensive: a scanner that
8
+ * errors or isn't applicable contributes nothing rather than failing the run.
9
+ *
10
+ * node .../deep-analysis.mjs # console summary
11
+ * node .../deep-analysis.mjs --json # merged { findings: [...] }
12
+ * node .../deep-analysis.mjs --write # → contextkit/memory/deep-analysis-findings.json
13
+ */
14
+ import { execFileSync } from 'node:child_process';
15
+ import { writeFileSync } from 'node:fs';
16
+ import { resolve } from 'node:path';
17
+ import { pathsFor } from '../../runtime/config/paths.mjs';
18
+
19
+ const ROOT = process.cwd();
20
+ const P = pathsFor(ROOT);
21
+ const SCANS = [
22
+ { name: 'tech-debt', script: 'tech-debt-scan.mjs' },
23
+ { name: 'deps', script: 'deps-audit.mjs' },
24
+ { name: 'contract', script: 'contract-scan.mjs' },
25
+ ];
26
+
27
+ function runScan(script) {
28
+ try {
29
+ const out = execFileSync('node', [`contextkit/tools/scripts/${script}`, '--json'], { cwd: ROOT, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 120000 });
30
+ const parsed = JSON.parse(out.replace(/^/, ''));
31
+ return Array.isArray(parsed) ? parsed : parsed.findings || [];
32
+ } catch {
33
+ return [];
34
+ }
35
+ }
36
+
37
+ function main() {
38
+ const findings = [];
39
+ const byScan = {};
40
+ for (const s of SCANS) {
41
+ const f = runScan(s.script).map((x) => ({ ...x, scan: s.name }));
42
+ byScan[s.name] = f.length;
43
+ findings.push(...f);
44
+ }
45
+ const report = { findings, byScan, total: findings.length, at: new Date().toISOString() };
46
+
47
+ if (process.argv.includes('--write')) {
48
+ writeFileSync(resolve(P.memory, 'deep-analysis-findings.json'), JSON.stringify(report, null, 2), 'utf-8');
49
+ console.log(`🔬 deep-analysis: ${findings.length} finding(s) → contextkit/memory/deep-analysis-findings.json`);
50
+ console.log(' → ingest: node contextkit/tools/scripts/pipeline.mjs ingest contextkit/memory/deep-analysis-findings.json --type chore');
51
+ return;
52
+ }
53
+ if (process.argv.includes('--json')) {
54
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
55
+ return;
56
+ }
57
+ console.log(`🔬 deep-analysis: ${findings.length} deterministic finding(s) across ${SCANS.length} scanners.`);
58
+ for (const [k, n] of Object.entries(byScan)) console.log(` ${k}: ${n}`);
59
+ console.log(' (run /deep-analysis for the full sweep: + judgment, report, ADRs, backlog.)');
60
+ }
61
+
62
+ main();
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Dependency / supply-chain audit — the security-team's deterministic check.
4
+ *
5
+ * Zero-dep checks on the manifest + lockfile + installed metadata, plus an
6
+ * OPTIONAL native audit (`npm`/`pnpm`/`yarn audit`) when the toolchain is
7
+ * present and online. Findings are shaped to feed `pipeline.mjs ingest`
8
+ * (kind/severity/path/message/source), so supply-chain issues flow into the
9
+ * DevPipeline backlog like any other finding.
10
+ *
11
+ * Policy lives in `contextkit/config.json` → `deps` (requireLockfile, license
12
+ * allow/deny); see runtime/config/defaults.mjs.
13
+ *
14
+ * node .../deps-audit.mjs # console summary
15
+ * node .../deps-audit.mjs --json # machine-readable { findings: [...] }
16
+ * node .../deps-audit.mjs --write # → contextkit/memory/deps-findings.json (for ingest)
17
+ * node .../deps-audit.mjs --sbom # → contextkit/memory/sbom.json (CycloneDX)
18
+ *
19
+ * Defensive: never throws; degrades to "nothing to report" when it can't tell.
20
+ */
21
+ import { execFileSync } from 'node:child_process';
22
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
23
+ import { resolve } from 'node:path';
24
+ import { loadConfigSync } from '../../runtime/config/load.mjs';
25
+ import { pathsFor } from '../../runtime/config/paths.mjs';
26
+ import { readJsonSafe } from '../../runtime/hooks/safe-io.mjs';
27
+
28
+ const ROOT = process.cwd();
29
+ const P = pathsFor(ROOT);
30
+ const SEV = { critical: 5, high: 4, moderate: 3, low: 2, info: 1 };
31
+ const findings = [];
32
+
33
+ function add(severity, kind, message, path = 'package.json') {
34
+ findings.push({ kind, severity, path, message, source: `deps:${kind}:${path}` });
35
+ }
36
+
37
+ const readJson = (p) => readJsonSafe(p);
38
+
39
+ function depPolicy() {
40
+ try {
41
+ return loadConfigSync(ROOT).deps || {};
42
+ } catch {
43
+ return { requireLockfile: true, licenses: { allow: [], deny: [] } };
44
+ }
45
+ }
46
+
47
+ /** All declared dependency names (prod + dev). */
48
+ function depNames(pkg) {
49
+ return Object.keys({ ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) });
50
+ }
51
+
52
+ /** Best-effort SPDX id from an installed package's metadata. null if unknown. */
53
+ function licenseOf(name) {
54
+ const meta = readJson(resolve(ROOT, 'node_modules', name, 'package.json'));
55
+ if (!meta) return null;
56
+ if (typeof meta.license === 'string') return meta.license;
57
+ if (meta.license && typeof meta.license.type === 'string') return meta.license.type;
58
+ if (Array.isArray(meta.licenses) && meta.licenses[0]?.type) return meta.licenses[0].type;
59
+ return null;
60
+ }
61
+
62
+ function auditLicenses(pkg, policy) {
63
+ const allow = (policy.licenses?.allow || []).map((s) => s.toLowerCase());
64
+ const deny = (policy.licenses?.deny || []).map((s) => s.toLowerCase());
65
+ if (!allow.length && !deny.length) return;
66
+ for (const name of depNames(pkg)) {
67
+ const lic = licenseOf(name);
68
+ if (!lic) continue; // not installed / unknown — degrade silently
69
+ const l = lic.toLowerCase();
70
+ if (deny.includes(l)) add(4, 'license-deny', `\`${name}\`: license ${lic} is denied by policy (deps.licenses.deny).`);
71
+ else if (allow.length && !allow.includes(l)) add(2, 'license-unlisted', `\`${name}\`: license ${lic} is not in the allow-list (deps.licenses.allow).`);
72
+ }
73
+ }
74
+
75
+ /** Heuristic: a declared dep that does not appear in the lockfile text. */
76
+ function auditDrift(pkg, lockText) {
77
+ for (const name of depNames(pkg)) {
78
+ const present = lockText.includes(`node_modules/${name}`) || lockText.includes(`"${name}"`) || lockText.includes(`${name}@`) || lockText.includes(`/${name}/`);
79
+ if (!present) add(2, 'lockfile-drift', `\`${name}\` is declared but not found in the lockfile — run install to sync it.`);
80
+ }
81
+ }
82
+
83
+ function buildSbom(pkg) {
84
+ const all = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
85
+ const components = Object.entries(all).map(([name, range]) => {
86
+ const meta = readJson(resolve(ROOT, 'node_modules', name, 'package.json'));
87
+ const version = meta?.version || String(range).replace(/^[^0-9]*/, '') || '0.0.0';
88
+ const lic = licenseOf(name);
89
+ return { type: 'library', name, version, purl: `pkg:npm/${name}@${version}`, ...(lic ? { licenses: [{ license: { id: lic } }] } : {}) };
90
+ });
91
+ return {
92
+ bomFormat: 'CycloneDX',
93
+ specVersion: '1.5',
94
+ metadata: {
95
+ timestamp: new Date().toISOString(),
96
+ tools: [{ vendor: 'ContextDevKit', name: 'deps-audit' }],
97
+ component: { type: 'application', name: pkg.name || 'app', version: pkg.version || '0.0.0' },
98
+ },
99
+ components,
100
+ };
101
+ }
102
+
103
+ function findLock() {
104
+ const locks = ['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'npm-shrinkwrap.json'];
105
+ return locks.find((l) => existsSync(resolve(ROOT, l)));
106
+ }
107
+
108
+ function auditNode(policy) {
109
+ if (!existsSync(resolve(ROOT, 'package.json'))) return false;
110
+ const pkg = readJson(resolve(ROOT, 'package.json')) || {};
111
+ const all = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
112
+ const hasDeps = Object.keys(all).length > 0;
113
+
114
+ const lock = findLock();
115
+ if (hasDeps && !lock && policy.requireLockfile !== false) add(4, 'no-lockfile', 'No lockfile committed — installs are not reproducible. Commit one.');
116
+
117
+ for (const [name, range] of Object.entries(all)) {
118
+ if (typeof range !== 'string') continue;
119
+ if (range === '*' || range === 'latest' || /^[><]/.test(range)) {
120
+ add(3, 'loose-range', `\`${name}\`: "${range}" is unbounded — pin a version (or a caret range with a lockfile).`);
121
+ }
122
+ }
123
+
124
+ auditLicenses(pkg, policy);
125
+ if (lock) {
126
+ auditDrift(pkg, readFileSync(resolve(ROOT, lock), 'utf-8'));
127
+ runNativeAudit(lock);
128
+ }
129
+ return true;
130
+ }
131
+
132
+ function runNativeAudit(lock) {
133
+ const pm = lock.startsWith('pnpm') ? 'pnpm' : lock.startsWith('yarn') ? 'yarn' : 'npm';
134
+ try {
135
+ parseNpmAudit(execFileSync(pm, ['audit', '--json'], { cwd: ROOT, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 60000 }));
136
+ } catch (err) {
137
+ // `npm audit` exits non-zero when vulnerabilities exist — the JSON is still on stdout.
138
+ if (err?.stdout) {
139
+ try { parseNpmAudit(err.stdout); return; } catch { /* fall through */ }
140
+ }
141
+ add(1, 'audit-skipped', `Could not run \`${pm} audit\` (offline or unavailable) — run it before release.`);
142
+ }
143
+ }
144
+
145
+ function parseNpmAudit(out) {
146
+ const parsed = JSON.parse(out);
147
+ for (const [name, v] of Object.entries(parsed.vulnerabilities || {})) { // npm v7+
148
+ add(SEV[v.severity] || 2, 'cve', `\`${name}\`: ${v.severity} advisory — see \`npm audit\`.`);
149
+ }
150
+ for (const a of Object.values(data.advisories || {})) { // npm v6
151
+ add(SEV[a.severity] || 2, 'cve', `\`${a.module_name}\`: ${a.severity} — ${a.title}.`);
152
+ }
153
+ }
154
+
155
+ function pythonHint() {
156
+ if (existsSync(resolve(ROOT, 'requirements.txt')) || existsSync(resolve(ROOT, 'pyproject.toml'))) {
157
+ add(1, 'py-audit', 'Python deps detected — run `pip-audit` / `safety check` for CVEs (not automated here yet).');
158
+ }
159
+ }
160
+
161
+ function writeSbom() {
162
+ const pkg = readJson(resolve(ROOT, 'package.json'));
163
+ if (!pkg) {
164
+ console.log('🔐 deps-audit --sbom: no package.json found.');
165
+ return;
166
+ }
167
+ const out = resolve(P.memory, 'sbom.json');
168
+ writeFileSync(out, JSON.stringify(buildSbom(pkg), null, 2), 'utf-8');
169
+ console.log('🔐 deps-audit: SBOM written → contextkit/memory/sbom.json (CycloneDX 1.5).');
170
+ }
171
+
172
+ function main() {
173
+ if (process.argv.includes('--sbom')) {
174
+ writeSbom();
175
+ return;
176
+ }
177
+ auditNode(depPolicy());
178
+ pythonHint();
179
+ const report = { findings };
180
+
181
+ if (process.argv.includes('--write')) {
182
+ writeFileSync(resolve(P.memory, 'deps-findings.json'), JSON.stringify(report, null, 2), 'utf-8');
183
+ console.log(`🔐 deps-audit: ${findings.length} finding(s) → contextkit/memory/deps-findings.json`);
184
+ console.log(' → feed the backlog: node contextkit/tools/scripts/pipeline.mjs ingest contextkit/memory/deps-findings.json --type chore');
185
+ return;
186
+ }
187
+ if (process.argv.includes('--json')) {
188
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
189
+ return;
190
+ }
191
+ if (findings.length === 0) {
192
+ console.log('🔐 deps-audit: no issues found.');
193
+ return;
194
+ }
195
+ console.log(`🔐 deps-audit: ${findings.length} finding(s).`);
196
+ for (const f of [...findings].sort((a, b) => b.severity - a.severity)) {
197
+ console.log(` ${'●'.repeat(f.severity)} ${f.kind} — ${f.message}`);
198
+ }
199
+ }
200
+
201
+ main();
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Read-only project analyzer for `/setupcontextdevkit`.
4
+ *
5
+ * Inspects the project root and prints a JSON report: languages, package
6
+ * manager, frameworks, monorepo flag, likely source dirs, README summary, and
7
+ * SUGGESTED `ledger` path lists + `l5.highRiskPaths` tuned to the detected
8
+ * stack. It writes nothing — the slash command decides what to apply.
9
+ *
10
+ * Usage: node contextkit/tools/scripts/detect-stack.mjs (prints JSON)
11
+ */
12
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
13
+ import { join, resolve } from 'node:path';
14
+
15
+ const ROOT = process.cwd();
16
+
17
+ const read = (rel) => {
18
+ try {
19
+ return readFileSync(resolve(ROOT, rel), 'utf-8').replace(/^/, '');
20
+ } catch {
21
+ return null;
22
+ }
23
+ };
24
+ const has = (rel) => existsSync(resolve(ROOT, rel));
25
+ const isDir = (rel) => {
26
+ try {
27
+ return statSync(resolve(ROOT, rel)).isDirectory();
28
+ } catch {
29
+ return false;
30
+ }
31
+ };
32
+
33
+ function detectPackageManager() {
34
+ if (has('pnpm-lock.yaml')) return 'pnpm';
35
+ if (has('yarn.lock')) return 'yarn';
36
+ if (has('bun.lockb')) return 'bun';
37
+ if (has('package-lock.json')) return 'npm';
38
+ const pkg = readJson('package.json');
39
+ if (pkg?.packageManager) return String(pkg.packageManager).split('@')[0];
40
+ return has('package.json') ? 'npm' : null;
41
+ }
42
+
43
+ function readJson(rel) {
44
+ const raw = read(rel);
45
+ if (!raw) return null;
46
+ try {
47
+ return JSON.parse(raw);
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+
53
+ function detectLanguages() {
54
+ const langs = new Set();
55
+ if (has('package.json')) langs.add('javascript');
56
+ if (has('tsconfig.json') || has('tsconfig.base.json')) langs.add('typescript');
57
+ if (has('pyproject.toml') || has('requirements.txt') || has('setup.py')) langs.add('python');
58
+ if (has('go.mod')) langs.add('go');
59
+ if (has('Cargo.toml')) langs.add('rust');
60
+ if (has('pom.xml') || has('build.gradle') || has('build.gradle.kts')) langs.add('java/kotlin');
61
+ if (has('Gemfile')) langs.add('ruby');
62
+ if (has('composer.json')) langs.add('php');
63
+ return [...langs];
64
+ }
65
+
66
+ function detectFrameworks() {
67
+ const pkg = readJson('package.json');
68
+ const deps = pkg ? Object.keys({ ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }) : [];
69
+ const known = ['next', 'react', 'react-native', 'expo', 'vue', 'nuxt', 'svelte', '@sveltejs/kit', 'astro', 'solid-js', 'angular', 'hono', 'express', 'fastify', '@nestjs/core', 'koa', 'drizzle-orm', 'prisma', '@prisma/client', 'typeorm', 'mongoose', 'vite', 'webpack', 'electron', 'tauri', '@tanstack/start', '@tanstack/react-router', '@tanstack/react-query', '@tanstack/react-table', '@tanstack/react-form', '@tanstack/react-virtual', '@tanstack/solid-query', '@tanstack/vue-query'];
70
+ const found = known.filter((k) => deps.includes(k));
71
+ if (has('manage.py')) found.push('django');
72
+ if (read('requirements.txt')?.match(/flask/i) || read('pyproject.toml')?.match(/flask/i)) found.push('flask');
73
+ if (read('pyproject.toml')?.match(/fastapi/i) || read('requirements.txt')?.match(/fastapi/i)) found.push('fastapi');
74
+ return found;
75
+ }
76
+
77
+ function detectTestRunner() {
78
+ const pkg = readJson('package.json');
79
+ const deps = pkg ? Object.keys({ ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }) : [];
80
+ for (const t of ['vitest', 'jest', 'mocha', 'ava', 'playwright', '@playwright/test', 'cypress']) if (deps.includes(t)) return t;
81
+ if (has('pytest.ini') || read('pyproject.toml')?.match(/pytest/i)) return 'pytest';
82
+ return null;
83
+ }
84
+
85
+ const CODE_DIR_CANDIDATES = ['src', 'app', 'apps', 'packages', 'lib', 'components', 'pages', 'server', 'client', 'cmd', 'internal', 'pkg', 'tests', 'test', 'spec', 'api', 'core', 'modules'];
86
+
87
+ function detectSourceDirs() {
88
+ return CODE_DIR_CANDIDATES.filter((d) => isDir(d)).map((d) => `${d}/`);
89
+ }
90
+
91
+ function detectMonorepo() {
92
+ if (has('pnpm-workspace.yaml') || has('lerna.json') || has('turbo.json') || has('nx.json')) return true;
93
+ const pkg = readJson('package.json');
94
+ return Boolean(pkg?.workspaces);
95
+ }
96
+
97
+ function suggestHighRiskPaths() {
98
+ const out = new Set();
99
+ const candidates = [
100
+ 'prisma/schema.prisma', 'db/schema.ts', 'src/db/schema.ts', 'packages/db/src/schema.ts', 'drizzle/', 'migrations/', 'db/migrations/',
101
+ 'src/auth/', 'auth/', 'src/middleware/auth.ts', 'src/lib/auth/',
102
+ 'openapi.yaml', 'openapi.json', 'schema.graphql', 'src/schema.graphql',
103
+ 'packages/shared-types/', 'packages/shared/', 'src/contracts/', 'src/types/',
104
+ 'wrangler.toml', 'serverless.yml', 'Dockerfile', '.github/workflows/',
105
+ ];
106
+ for (const c of candidates) if (has(c)) out.add(c.endsWith('/') ? c : c);
107
+ // any *.proto at root-ish
108
+ return [...out];
109
+ }
110
+
111
+ function suggestLedger(sourceDirs, languages) {
112
+ const important = new Set([...sourceDirs, 'contextkit/', '.claude/', '.github/', 'CLAUDE.md']);
113
+ for (const m of ['package.json', 'tsconfig.json', 'pyproject.toml', 'go.mod', 'Cargo.toml', 'pom.xml', 'Gemfile', 'composer.json', 'pnpm-workspace.yaml', 'turbo.json', 'wrangler.toml']) {
114
+ if (has(m)) important.add(m);
115
+ }
116
+ const irrelevant = new Set(['node_modules/', '.git/', '.context-snapshot.md', '.claude/.sessions/', '.claude/.workspace/']);
117
+ for (const d of ['dist/', 'build/', 'out/', '.next/', '.turbo/', '.expo/', '.svelte-kit/', 'coverage/', '__pycache__/', '.pytest_cache/', 'target/', 'vendor/', '.venv/', 'venv/', 'bin/', 'obj/']) {
118
+ if (isDir(d.replace(/\/$/, '')) || ['node_modules/', 'dist/', 'build/'].includes(d)) irrelevant.add(d);
119
+ }
120
+ return { important: [...important], irrelevant: [...irrelevant] };
121
+ }
122
+
123
+ function readmeSummary() {
124
+ for (const name of ['README.md', 'readme.md', 'README.MD', 'Readme.md']) {
125
+ const raw = read(name);
126
+ if (raw) {
127
+ const lines = raw.split('\n').map((l) => l.trim()).filter(Boolean).slice(0, 8);
128
+ return lines.join(' ').slice(0, 600);
129
+ }
130
+ }
131
+ return null;
132
+ }
133
+
134
+ function rootEntries() {
135
+ try {
136
+ return readdirSync(ROOT).filter((e) => !e.startsWith('.tmp')).slice(0, 60);
137
+ } catch {
138
+ return [];
139
+ }
140
+ }
141
+
142
+ const sourceDirs = detectSourceDirs();
143
+ const languages = detectLanguages();
144
+ const report = {
145
+ root: ROOT,
146
+ languages,
147
+ packageManager: detectPackageManager(),
148
+ frameworks: detectFrameworks(),
149
+ testRunner: detectTestRunner(),
150
+ monorepo: detectMonorepo(),
151
+ sourceDirs,
152
+ hasReadme: Boolean(readmeSummary()),
153
+ readmeSummary: readmeSummary(),
154
+ rootEntries: rootEntries(),
155
+ greenfield: sourceDirs.length === 0 && languages.length === 0,
156
+ suggested: {
157
+ ledger: suggestLedger(sourceDirs, languages),
158
+ highRiskPaths: suggestHighRiskPaths(),
159
+ qaCriticalPaths: suggestHighRiskPaths(),
160
+ recommendedLevel: sourceDirs.length === 0 ? 1 : 2,
161
+ },
162
+ };
163
+
164
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `/log-session` companion — scans the just-written session narrative for
4
+ * **rule-like phrases** that look constitutional ("we decided X", "from now on
5
+ * Y", "we should always Z") and surfaces them as **proposal-only** candidates
6
+ * for `/distill-sessions`. Ticket 043 (Compozy follow-through).
7
+ *
8
+ * Posture: **propose, never apply**. This script does not edit `CLAUDE.md`. It
9
+ * prints one nudge line at the end of `/log-session` and exits 0 either way —
10
+ * a session with no candidates is not an error, just quiet.
11
+ *
12
+ * Optimised for *low false-negatives*. Per the ticket: the cost of a wrong
13
+ * nudge is one ignored line; the cost of a missed nudge is silent drift.
14
+ *
15
+ * Usage:
16
+ * distill-detect.mjs <path-to-session-file.md> # nudge mode
17
+ * distill-detect.mjs <path> --json # machine-readable
18
+ *
19
+ * Zero-dep, pure ESM over `node:*`.
20
+ */
21
+ import { existsSync, readFileSync } from 'node:fs';
22
+ import { resolve } from 'node:path';
23
+ import { fileURLToPath } from 'node:url';
24
+
25
+ /**
26
+ * Regex set, ordered roughly by signal strength. Each pattern has a `kind` so
27
+ * `--json` output can be triaged downstream (e.g. by `/distill-sessions`).
28
+ *
29
+ * Keep this list tight — Tier-1 phrases only. Tier-2 phrases ("maybe we
30
+ * should…", "consider…") produce false positives that train the user to
31
+ * ignore the nudge.
32
+ */
33
+ const PATTERNS = [
34
+ { kind: 'decision', re: /\b(we|i)\s+decided\s+(that\s+|to\s+)/i },
35
+ { kind: 'decision', re: /\bdecision:\s*\S/i },
36
+ { kind: 'rule', re: /\bfrom now on\b/i },
37
+ { kind: 'rule', re: /\bwe\s+(should|must|will)\s+always\b/i },
38
+ { kind: 'rule', re: /\bwe\s+(should|must|will)\s+never\b/i },
39
+ { kind: 'rule', re: /\balways\s+(use|prefer|require|enforce)\b/i },
40
+ { kind: 'rule', re: /\bnever\s+(use|allow|skip|bypass)\b/i },
41
+ { kind: 'convention', re: /\bconvention:\s*\S/i },
42
+ { kind: 'invariant', re: /\binvariant:\s*\S/i },
43
+ { kind: 'lesson', re: /\blesson\s+learn(ed|t)\b/i },
44
+ ];
45
+
46
+ /**
47
+ * Scans `text` (typically the body of a session log) and returns every
48
+ * matched candidate sentence. Sentence boundaries are heuristic — `. `, `! `,
49
+ * `? `, and newline blocks — which is fine: the user only reads the count
50
+ * + first match.
51
+ *
52
+ * @param {string} text
53
+ * @returns {Array<{ kind: string, line: number, snippet: string }>}
54
+ */
55
+ export function detect(text) {
56
+ if (typeof text !== 'string' || text.length === 0) return [];
57
+ const lines = text.split('\n');
58
+ const hits = [];
59
+ const seenLines = new Set();
60
+ for (let i = 0; i < lines.length; i += 1) {
61
+ const line = lines[i];
62
+ if (line.trim().startsWith('#')) continue; // skip headings
63
+ if (line.trim().startsWith('>')) continue; // skip block quotes (often quoting prior decisions, not new ones)
64
+ for (const { kind, re } of PATTERNS) {
65
+ if (!re.test(line)) continue;
66
+ const key = `${i}:${kind}`;
67
+ if (seenLines.has(key)) continue;
68
+ seenLines.add(key);
69
+ const snippet = line.trim().slice(0, 120);
70
+ hits.push({ kind, line: i + 1, snippet });
71
+ }
72
+ }
73
+ return hits;
74
+ }
75
+
76
+ function main() {
77
+ const file = process.argv[2];
78
+ if (!file) { console.error('Usage: distill-detect.mjs <session-file.md> [--json]'); process.exit(1); }
79
+ if (!existsSync(file)) { console.error(`distill-detect: file not found — ${file}`); process.exit(1); }
80
+ const text = readFileSync(file, 'utf-8');
81
+ const hits = detect(text);
82
+ if (process.argv.includes('--json')) { console.log(JSON.stringify({ candidates: hits.length, hits }, null, 2)); return; }
83
+ if (hits.length === 0) return; // quiet success
84
+ const kinds = [...new Set(hits.map((h) => h.kind))].join(', ');
85
+ console.log('');
86
+ console.log(`💡 ${hits.length} rule-like phrase(s) detected (${kinds}). Consider /distill-sessions to propose them for CLAUDE.md.`);
87
+ console.log(` First match: ${hits[0].snippet}`);
88
+ }
89
+
90
+ if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) main();