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,165 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ContextDevKit doctor — diagnoses an installed project's setup.
4
+ *
5
+ * Checks node version, config validity + level, that `.claude/settings.json`
6
+ * hook wiring matches the configured level, git-hook presence (L≥3), memory
7
+ * scaffolding, onboarding state, and optional zod. Prints a report and exits
8
+ * non-zero if any CRITICAL (✗) problem is found, with a suggested fix per item.
9
+ *
10
+ * Run: node contextkit/tools/scripts/doctor.mjs (or /context-doctor)
11
+ */
12
+ import { execFileSync } from 'node:child_process';
13
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
14
+ import { resolve } from 'node:path';
15
+ import { composeSettings } from '../../runtime/config/settings-compose.mjs';
16
+ import { getLevel, loadConfigSync } from '../../runtime/config/load.mjs';
17
+ import { MAX_LEVEL, MIN_LEVEL, isValidLevel } from '../../runtime/config/levels.mjs';
18
+ import { pathsFor } from '../../runtime/config/paths.mjs';
19
+ import { readJsonSafe } from '../../runtime/hooks/safe-io.mjs';
20
+
21
+ const ROOT = process.cwd();
22
+ const P = pathsFor(ROOT);
23
+ let crit = 0;
24
+ let warn = 0;
25
+ const pass = (m) => console.log(` ✓ ${m}`);
26
+ const fail = (m, fix) => {
27
+ console.error(` ✗ ${m}${fix ? `\n → ${fix}` : ''}`);
28
+ crit++;
29
+ };
30
+ const note = (m, fix) => {
31
+ console.log(` ⚠ ${m}${fix ? `\n → ${fix}` : ''}`);
32
+ warn++;
33
+ };
34
+
35
+ const readJson = (rel) => readJsonSafe(resolve(ROOT, rel));
36
+
37
+ function checkNode() {
38
+ const major = Number(process.versions.node.split('.')[0]);
39
+ major >= 18 ? pass(`Node ${process.versions.node}`) : fail(`Node ${process.versions.node} is too old`, 'install Node >= 18');
40
+ }
41
+
42
+ function checkConfig() {
43
+ if (!existsSync(P.config)) {
44
+ fail('contextkit/config.json missing', 're-run the installer');
45
+ return null;
46
+ }
47
+ const raw = readJson('contextkit/config.json');
48
+ if (!raw) {
49
+ fail('contextkit/config.json is not valid JSON', 'fix the JSON or re-run the installer');
50
+ return null;
51
+ }
52
+ const level = getLevel(ROOT);
53
+ isValidLevel(level) ? pass(`config valid — level L${level}`) : note('config.level out of range', `use /context-level <${MIN_LEVEL}-${MAX_LEVEL}>`);
54
+ return level;
55
+ }
56
+
57
+ function checkWiring(level) {
58
+ const settings = readJson('.claude/settings.json');
59
+ if (!settings) {
60
+ fail('.claude/settings.json missing or invalid', 'run /context-level ' + (level ?? 2));
61
+ return;
62
+ }
63
+ const expected = Object.keys(composeSettings(null, level ?? 2).hooks || {}).sort();
64
+ const actual = Object.keys(settings.hooks || {})
65
+ .filter((evt) => (settings.hooks[evt] || []).some((g) => (g.hooks || []).some((h) => String(h.command || '').includes('contextkit/runtime/hooks'))))
66
+ .sort();
67
+ JSON.stringify(expected) === JSON.stringify(actual)
68
+ ? pass(`hook wiring matches L${level}: ${actual.join(', ') || '(none)'}`)
69
+ : fail(`hook wiring (${actual.join(', ') || 'none'}) does not match L${level} (${expected.join(', ')})`, `run /context-level ${level} and restart Claude Code`);
70
+ }
71
+
72
+ function checkGitHooks(level) {
73
+ if ((level ?? 0) < 3) return;
74
+ if (!existsSync(resolve(ROOT, '.git'))) {
75
+ note('Level ≥ 3 but no .git directory', 'git init, then re-run the installer to add git hooks');
76
+ return;
77
+ }
78
+ for (const h of ['pre-commit', 'commit-msg']) {
79
+ existsSync(resolve(ROOT, '.git/hooks', h)) ? pass(`git hook ${h} installed`) : note(`git hook ${h} missing`, 're-run the installer');
80
+ }
81
+ }
82
+
83
+ function checkMemory() {
84
+ existsSync(P.sessions) ? pass('memory/sessions present') : note('memory/sessions missing', 're-run the installer');
85
+ existsSync(resolve(ROOT, 'docs/CHANGELOG.md')) ? pass('docs/CHANGELOG.md present') : note('CHANGELOG missing', 're-run the installer');
86
+ }
87
+
88
+ function checkSetup() {
89
+ const completed = loadConfigSync(ROOT)?.setup?.completed === true;
90
+ completed ? pass('onboarding complete') : note('onboarding not run', 'run /setupcontextdevkit');
91
+ }
92
+
93
+ function checkRoadmap() {
94
+ const p = P.roadmap;
95
+ let defined = false;
96
+ try {
97
+ const t = readFileSync(p, 'utf-8');
98
+ defined = !t.includes('ROADMAP-NOT-DEFINED') && t.trim().length > 0;
99
+ } catch {
100
+ /* missing */
101
+ }
102
+ defined ? pass('product roadmap defined') : note('product roadmap not defined', 'run /roadmap to create it (with you)');
103
+ }
104
+
105
+ function checkModuleClaudeMd() {
106
+ const groups = ['apps', 'packages', 'modules', 'services', 'libs'];
107
+ const splits = ['backend', 'frontend', 'client', 'server', 'api', 'web', 'mobile', 'functions', 'worker'];
108
+ const manifests = ['package.json', 'pyproject.toml', 'go.mod', 'Cargo.toml', 'tsconfig.json'];
109
+ const buildable = (d) => manifests.some((m) => existsSync(resolve(d, m))) || existsSync(resolve(d, 'src'));
110
+ const roots = new Set();
111
+ for (const s of splits) {
112
+ const abs = resolve(ROOT, s);
113
+ if (existsSync(abs) && buildable(abs)) roots.add(s);
114
+ }
115
+ for (const g of groups) {
116
+ const gAbs = resolve(ROOT, g);
117
+ if (!existsSync(gAbs)) continue;
118
+ let children = [];
119
+ try {
120
+ children = readdirSync(gAbs, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith('.')).map((e) => e.name);
121
+ } catch {
122
+ /* skip */
123
+ }
124
+ for (const c of children) if (buildable(resolve(gAbs, c))) roots.add(`${g}/${c}`);
125
+ }
126
+ if (roots.size === 0) return; // single-package — root CLAUDE.md is enough
127
+ const missing = [...roots].filter((r) => !existsSync(resolve(ROOT, r, 'CLAUDE.md')));
128
+ missing.length === 0
129
+ ? pass(`all ${roots.size} module(s) have a scoped CLAUDE.md`)
130
+ : note(`${missing.length} module(s) missing CLAUDE.md: ${missing.join(', ')}`, 'run /claude-md to scaffold + fill them');
131
+ }
132
+
133
+ function checkRemote() {
134
+ if (!existsSync(resolve(ROOT, '.git'))) return; // not a git repo — /git can init
135
+ try {
136
+ const url = execFileSync('git', ['remote', 'get-url', 'origin'], { cwd: ROOT, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
137
+ url ? pass(`git remote: ${url}`) : note('no git remote', 'run /git setup-remote (GitHub/GitLab/other)');
138
+ } catch {
139
+ note('no git remote configured', 'run /git setup-remote to connect GitHub/GitLab/other + CLI');
140
+ }
141
+ }
142
+
143
+ function checkZod(level) {
144
+ if ((level ?? 0) < 5) return;
145
+ const hasZod = existsSync(resolve(ROOT, 'node_modules/zod'));
146
+ hasZod ? pass('zod present (strict /context-config validation enabled)') : note('zod not installed (optional)', 'add zod for strict config validation, or ignore');
147
+ }
148
+
149
+ console.log('\n🩺 ContextDevKit doctor\n');
150
+ checkNode();
151
+ const level = checkConfig();
152
+ checkWiring(level);
153
+ checkGitHooks(level);
154
+ checkMemory();
155
+ checkSetup();
156
+ checkRoadmap();
157
+ checkModuleClaudeMd();
158
+ checkRemote();
159
+ checkZod(level);
160
+ console.log(
161
+ crit === 0
162
+ ? `\n✅ Healthy${warn ? ` (${warn} advisory note${warn > 1 ? 's' : ''})` : ''}.\n`
163
+ : `\n❌ ${crit} critical issue${crit > 1 ? 's' : ''}${warn ? ` + ${warn} note(s)` : ''}.\n`,
164
+ );
165
+ process.exit(crit === 0 ? 0 : 1);
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Fleet mode — one control plane over many ContextDevKit repos.
4
+ *
5
+ * Aggregates each registered repo's telemetry/scanners and reports cross-repo
6
+ * CLAUDE.md rule drift. The registry lives OUTSIDE any repo (a true control
7
+ * plane): `~/.contextdevkit/fleet.json` (override with `CONTEXT_FLEET_FILE`).
8
+ *
9
+ * fleet.mjs list # registered repos
10
+ * fleet.mjs add <path> # register a repo (abs path stored)
11
+ * fleet.mjs remove <path> # unregister
12
+ * fleet.mjs stats [--json] # aggregate stats.mjs across repos
13
+ * fleet.mjs audit [--json] # aggregate deep-analysis findings
14
+ * fleet.mjs propagate <rule-file> # report repos whose CLAUDE.md lacks the rule
15
+ *
16
+ * Zero-dependency and defensive: a missing/broken repo is skipped, never throws.
17
+ */
18
+ import { execFileSync } from 'node:child_process';
19
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
20
+ import { dirname, basename, resolve } from 'node:path';
21
+ import { readJsonSafe } from '../../runtime/hooks/safe-io.mjs';
22
+ import { resolveHome, readHomeFile, writeHomeFile } from './home.mjs';
23
+
24
+ const FLEET_NAME = 'fleet.json';
25
+ // CONTEXT_FLEET_FILE overrides the FULL path (used by integration tests). When
26
+ // absent, fleet.json lives in `~/.contextdevkit/` via the home helper (ADR-0020).
27
+ const FLEET_FILE_OVERRIDE = process.env.CONTEXT_FLEET_FILE || null;
28
+ const FLEET_FILE = FLEET_FILE_OVERRIDE || resolve(resolveHome(), FLEET_NAME);
29
+
30
+ function loadRegistry() {
31
+ if (FLEET_FILE_OVERRIDE) {
32
+ const reg = readJsonSafe(FLEET_FILE_OVERRIDE);
33
+ return reg && Array.isArray(reg.repos) ? reg : { repos: [] };
34
+ }
35
+ const reg = readHomeFile(FLEET_NAME);
36
+ return reg && Array.isArray(reg.repos) ? reg : { repos: [] };
37
+ }
38
+
39
+ function saveRegistry(reg) {
40
+ if (FLEET_FILE_OVERRIDE) {
41
+ const dir = dirname(FLEET_FILE_OVERRIDE);
42
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
43
+ writeFileSync(FLEET_FILE_OVERRIDE, JSON.stringify(reg, null, 2) + '\n', 'utf-8');
44
+ return;
45
+ }
46
+ writeHomeFile(FLEET_NAME, reg);
47
+ }
48
+
49
+ /** Run a repo's script with --json and parse the rows. null on any failure. */
50
+ function runRepoJson(repo, rel, args = ['--json']) {
51
+ const script = resolve(repo, rel);
52
+ if (!existsSync(script)) return null;
53
+ try {
54
+ return JSON.parse(execFileSync(process.execPath, [script, ...args], { cwd: repo, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 60000 }));
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+
60
+ function isJson() {
61
+ return process.argv.includes('--json');
62
+ }
63
+
64
+ function cmdList() {
65
+ const { repos } = loadRegistry();
66
+ if (isJson()) return void process.stdout.write(JSON.stringify({ file: FLEET_FILE, repos }, null, 2) + '\n');
67
+ if (!repos.length) return void console.log(`🛰️ fleet: no repos registered (${FLEET_FILE}).\n Add one: node contextkit/tools/scripts/fleet.mjs add <path>`);
68
+ console.log(`🛰️ fleet: ${repos.length} repo(s) — ${FLEET_FILE}`);
69
+ for (const r of repos) console.log(` ${existsSync(resolve(r, 'contextkit')) ? '✓' : '⚠'} ${r}`);
70
+ }
71
+
72
+ function cmdAdd() {
73
+ const input = process.argv[3];
74
+ if (!input) return void fail('Usage: fleet.mjs add <path>');
75
+ const abs = resolve(process.cwd(), input);
76
+ if (!existsSync(abs)) return void fail(`Path not found: ${abs}`);
77
+ const reg = loadRegistry();
78
+ if (reg.repos.includes(abs)) return void console.log(`already registered: ${abs}`);
79
+ reg.repos.push(abs);
80
+ saveRegistry(reg);
81
+ console.log(`🛰️ fleet: registered ${abs} (${reg.repos.length} total).`);
82
+ }
83
+
84
+ function cmdRemove() {
85
+ const abs = resolve(process.cwd(), process.argv[3] || '');
86
+ const reg = loadRegistry();
87
+ const next = reg.repos.filter((r) => r !== abs);
88
+ saveRegistry({ ...reg, repos: next });
89
+ console.log(next.length === reg.repos.length ? `not registered: ${abs}` : `🛰️ fleet: removed ${abs}.`);
90
+ }
91
+
92
+ function cmdStats() {
93
+ const { repos } = loadRegistry();
94
+ const rows = repos.map((repo) => {
95
+ const s = runRepoJson(repo, 'contextkit/tools/scripts/stats.mjs');
96
+ if (!s) return { path: repo, name: basename(repo), ok: false };
97
+ return { path: repo, name: basename(repo), ok: true, level: s.level, registeredSessions: s.registeredSessions, adrs: s.adrs, agents: s.agents, driftRatePct: s.driftRatePct, forge: s.forge || null };
98
+ });
99
+ const ok = rows.filter((r) => r.ok);
100
+ const forgeRows = ok.filter((r) => r.forge);
101
+ const totals = {
102
+ repos: rows.length,
103
+ withStats: ok.length,
104
+ totalSessions: ok.reduce((a, r) => a + (r.registeredSessions || 0), 0),
105
+ totalAdrs: ok.reduce((a, r) => a + (r.adrs || 0), 0),
106
+ avgDriftPct: ok.length ? +(ok.reduce((a, r) => a + (r.driftRatePct || 0), 0) / ok.length).toFixed(1) : 0,
107
+ forge: forgeRows.length ? {
108
+ repos: forgeRows.length,
109
+ packages: forgeRows.reduce((a, r) => a + (r.forge.packages || 0), 0),
110
+ evaluated: forgeRows.reduce((a, r) => a + (r.forge.evaluated || 0), 0),
111
+ monthlyTarget: +forgeRows.reduce((a, r) => a + (r.forge.monthlyTarget || 0), 0).toFixed(2),
112
+ monthlyHardCap: +forgeRows.reduce((a, r) => a + (r.forge.monthlyHardCap || 0), 0).toFixed(2),
113
+ } : null,
114
+ };
115
+ if (isJson()) return void process.stdout.write(JSON.stringify({ repos: rows, totals }, null, 2) + '\n');
116
+ console.log(`🛰️ fleet stats — ${totals.repos} repo(s), ${totals.totalSessions} sessions, ${totals.totalAdrs} ADRs, avg drift ${totals.avgDriftPct}%\n`);
117
+ for (const r of rows) {
118
+ if (!r.ok) {
119
+ console.log(` ${r.name} (no stats — not a ContextDevKit repo?)`);
120
+ continue;
121
+ }
122
+ const forge = r.forge ? ` 🔥 ${r.forge.packages} pkg (${r.forge.evaluated}✅)` : '';
123
+ console.log(` ${r.name} L${r.level} ${r.registeredSessions} sess ${r.adrs} ADR ${r.agents} agents ${r.driftRatePct}% drift${forge}`);
124
+ }
125
+ if (totals.forge) {
126
+ console.log(`\n🔥 Forge fleet: ${totals.forge.packages} packages across ${totals.forge.repos} repo(s), ${totals.forge.evaluated} eval-stamped, monthly target $${totals.forge.monthlyTarget} / hard cap $${totals.forge.monthlyHardCap}`);
127
+ }
128
+ }
129
+
130
+ function cmdAudit() {
131
+ const { repos } = loadRegistry();
132
+ const rows = repos.map((repo) => {
133
+ const a = runRepoJson(repo, 'contextkit/tools/scripts/deep-analysis.mjs');
134
+ if (!a || typeof a.total !== 'number') return { path: repo, name: basename(repo), ok: false };
135
+ return { path: repo, name: basename(repo), ok: true, total: a.total, byScan: a.byScan || {} };
136
+ });
137
+ const ok = rows.filter((r) => r.ok);
138
+ const totals = { repos: rows.length, scanned: ok.length, totalFindings: ok.reduce((a, r) => a + r.total, 0) };
139
+ if (isJson()) return void process.stdout.write(JSON.stringify({ repos: rows, totals }, null, 2) + '\n');
140
+ console.log(`🛰️ fleet audit — ${totals.totalFindings} finding(s) across ${totals.scanned}/${totals.repos} repo(s)\n`);
141
+ for (const r of rows) console.log(r.ok ? ` ${r.name} ${r.total} finding(s)` : ` ${r.name} (no analyzer)`);
142
+ }
143
+
144
+ function cmdPropagate() {
145
+ const ruleFile = process.argv[3];
146
+ if (!ruleFile || !existsSync(ruleFile)) return void fail('Usage: fleet.mjs propagate <rule-file> (a CLAUDE.md rule snippet)');
147
+ const snippet = readFileSync(ruleFile, 'utf-8').trim();
148
+ const key = snippet.split('\n').find((l) => l.trim().length > 12)?.trim() || snippet.slice(0, 40);
149
+ const { repos } = loadRegistry();
150
+ const rows = repos.map((repo) => {
151
+ const claudeMd = resolve(repo, 'CLAUDE.md');
152
+ const has = existsSync(claudeMd) && readFileSync(claudeMd, 'utf-8').includes(key);
153
+ return { path: repo, name: basename(repo), present: has };
154
+ });
155
+ const missing = rows.filter((r) => !r.present);
156
+ if (isJson()) return void process.stdout.write(JSON.stringify({ key, missing: missing.map((r) => r.path), checked: rows }, null, 2) + '\n');
157
+ console.log(`🛰️ fleet propagate (detect-only) — rule absent in ${missing.length}/${rows.length} repo(s):\n key: "${key}"\n`);
158
+ for (const r of rows) console.log(` ${r.present ? '✓ has ' : '✗ MISSING'} ${r.name}`);
159
+ if (missing.length) console.log(`\n Add the rule to each MISSING repo's CLAUDE.md (reviewed, per-repo) — fleet does not auto-edit.`);
160
+ }
161
+
162
+ function fail(msg) {
163
+ console.error(msg);
164
+ process.exit(1);
165
+ }
166
+
167
+ const cmd = process.argv[2];
168
+ const table = { list: cmdList, add: cmdAdd, remove: cmdRemove, stats: cmdStats, audit: cmdAudit, propagate: cmdPropagate };
169
+ if (table[cmd]) table[cmd]();
170
+ else fail('Usage: fleet.mjs <list|add|remove|stats|audit|propagate> [...]');
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * On-demand full-project snapshot → `.context-snapshot.md` (gitignored).
4
+ *
5
+ * STACK-AGNOSTIC. Produces a single document useful for:
6
+ * - A brutal refactor where Claude needs to see the whole tree at once.
7
+ * - Pasting into another AI (ChatGPT, Gemini) that lacks the boot hook.
8
+ * - Impact analysis ("what breaks if I change X?").
9
+ *
10
+ * Contents: folder tree (depth-limited), detected stack, latest session,
11
+ * CHANGELOG `[Unreleased]`, and a glossary excerpt. Best-effort, never throws.
12
+ *
13
+ * Usage: node contextkit/tools/scripts/generate-context.mjs
14
+ */
15
+ import { readdir, readFile, stat, writeFile } from 'node:fs/promises';
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 OUTPUT = resolve(ROOT, '.context-snapshot.md');
22
+ const MAX_DEPTH = 4;
23
+ const IGNORE = new Set(['node_modules', '.git', 'dist', 'build', 'out', '.next', '.turbo', '.expo', 'coverage', '__pycache__', 'target', 'vendor', '.claude']);
24
+
25
+ async function readSafe(rel) {
26
+ try {
27
+ return await readFile(resolve(ROOT, rel), 'utf-8');
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ async function buildTree(dir, prefix = '', depth = 0) {
34
+ if (depth > MAX_DEPTH) return [];
35
+ let entries;
36
+ try {
37
+ entries = await readdir(dir, { withFileTypes: true });
38
+ } catch {
39
+ return [];
40
+ }
41
+ entries = entries.filter((e) => !(e.isDirectory() && IGNORE.has(e.name)) && !e.name.startsWith('.tmp'));
42
+ entries.sort((a, b) => (a.isDirectory() === b.isDirectory() ? a.name.localeCompare(b.name) : a.isDirectory() ? -1 : 1));
43
+ const lines = [];
44
+ for (const e of entries.slice(0, 60)) {
45
+ lines.push(`${prefix}${e.isDirectory() ? '📁' : '📄'} ${e.name}`);
46
+ if (e.isDirectory()) lines.push(...(await buildTree(resolve(dir, e.name), prefix + ' ', depth + 1)));
47
+ }
48
+ return lines;
49
+ }
50
+
51
+ async function detectStack() {
52
+ const hints = [];
53
+ const pkgRaw = await readSafe('package.json');
54
+ if (pkgRaw) {
55
+ try {
56
+ const pkg = JSON.parse(pkgRaw);
57
+ const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
58
+ hints.push(`**package.json** — ${Object.keys(deps).length} deps. Key: ${Object.keys(deps).slice(0, 15).join(', ')}`);
59
+ } catch {
60
+ /* ignore */
61
+ }
62
+ }
63
+ for (const [file, label] of [
64
+ ['pyproject.toml', 'Python (pyproject.toml)'],
65
+ ['go.mod', 'Go (go.mod)'],
66
+ ['Cargo.toml', 'Rust (Cargo.toml)'],
67
+ ['pom.xml', 'Java (Maven)'],
68
+ ['Gemfile', 'Ruby (Gemfile)'],
69
+ ]) {
70
+ if (await readSafe(file)) hints.push(`**${label}**`);
71
+ }
72
+ return hints.length ? hints.map((h) => `- ${h}`).join('\n') : '_(no recognized manifest)_';
73
+ }
74
+
75
+ async function latestSession() {
76
+ let files = [];
77
+ try {
78
+ files = await readdir(P.sessions);
79
+ } catch {
80
+ return null;
81
+ }
82
+ const entries = files.filter((f) => /^\d{4}-\d{2}-\d{2}-\d{2,}-.+\.md$/.test(f)).sort((a, b) => Number.parseInt(b.split('-')[3], 10) - Number.parseInt(a.split('-')[3], 10));
83
+ if (!entries.length) return null;
84
+ const content = await readSafe(`contextkit/memory/sessions/${entries[0]}`);
85
+ return content ? content.split('\n').slice(0, 40).join('\n') : null;
86
+ }
87
+
88
+ function unreleased(changelog) {
89
+ if (!changelog) return null;
90
+ const lines = changelog.split('\n');
91
+ const start = lines.findIndex((l) => /^##\s+\[Unreleased\]/i.test(l));
92
+ if (start === -1) return null;
93
+ const rest = lines.slice(start + 1);
94
+ const end = rest.findIndex((l) => /^##\s+\[/.test(l) || l.trim() === '---');
95
+ return rest.slice(0, end === -1 ? 40 : end).join('\n').trim();
96
+ }
97
+
98
+ async function main() {
99
+ const out = [];
100
+ out.push(`# Context Snapshot — ${new Date().toISOString().slice(0, 10)}`);
101
+ out.push('');
102
+ out.push('> Generated by `generate-context`. Gitignored, ephemeral. Do not commit.');
103
+ out.push('');
104
+ out.push('## Detected stack');
105
+ out.push('');
106
+ out.push(await detectStack());
107
+ out.push('');
108
+ out.push('## Project tree (depth ≤ 4)');
109
+ out.push('');
110
+ out.push('```');
111
+ out.push(...(await buildTree(ROOT)));
112
+ out.push('```');
113
+ out.push('');
114
+ const session = await latestSession();
115
+ if (session) {
116
+ out.push('## Latest session');
117
+ out.push('');
118
+ out.push(session);
119
+ out.push('');
120
+ }
121
+ const unrel = unreleased(await readSafe('docs/CHANGELOG.md'));
122
+ if (unrel) {
123
+ out.push('## CHANGELOG [Unreleased]');
124
+ out.push('');
125
+ out.push(unrel);
126
+ out.push('');
127
+ }
128
+ const glossary = await readSafe('contextkit/memory/GLOSSARY.md');
129
+ if (glossary) {
130
+ out.push('## Glossary (excerpt)');
131
+ out.push('');
132
+ out.push(glossary.split('\n').slice(0, 40).join('\n'));
133
+ out.push('');
134
+ }
135
+ await writeFile(OUTPUT, out.join('\n'), 'utf-8');
136
+ console.log(`✅ .context-snapshot.md regenerated (${out.length} lines).`);
137
+ }
138
+
139
+ main().catch((err) => {
140
+ console.error('❌ Failed to generate context snapshot:', err);
141
+ process.exit(1);
142
+ });
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GitHub security alerts → findings (the loop-closer).
4
+ *
5
+ * Pulls Dependabot + code-scanning alerts via the `gh` CLI and shapes them like
6
+ * deps-audit findings, so `pipeline.mjs ingest` turns GitHub's alerts into
7
+ * prioritized, owned backlog tasks. The `code-security` agent then triages them.
8
+ *
9
+ * node .../gh-alerts.mjs # console summary
10
+ * node .../gh-alerts.mjs --json # { findings: [...] }
11
+ * node .../gh-alerts.mjs --write # → contextkit/memory/gh-alerts-findings.json
12
+ *
13
+ * Defensive: needs an authenticated `gh` + a GitHub repo. If `gh` is missing,
14
+ * unauthenticated, offline, or the repo has no GitHub remote, it reports nothing
15
+ * and exits 0 — never throws, never blocks.
16
+ */
17
+ import { execFileSync } from 'node:child_process';
18
+ import { writeFileSync } from 'node:fs';
19
+ import { resolve } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+ import { pathsFor } from '../../runtime/config/paths.mjs';
22
+
23
+ const ROOT = process.cwd();
24
+ const P = pathsFor(ROOT);
25
+ const SEV = { critical: 5, high: 4, medium: 3, moderate: 3, low: 2, warning: 2, error: 4, note: 1 };
26
+ const findings = [];
27
+
28
+ /** Maps one Dependabot alert (GitHub API shape) to a deps-audit-style finding. Pure. */
29
+ export function mapDependabotAlert(alert) {
30
+ const sev = alert?.security_advisory?.severity || alert?.security_vulnerability?.severity || 'low';
31
+ const pkg = alert?.dependency?.package?.name || 'dependency';
32
+ const file = alert?.dependency?.manifest_path || 'package.json';
33
+ return {
34
+ kind: 'dependabot',
35
+ severity: SEV[String(sev).toLowerCase()] || 2,
36
+ path: file,
37
+ message: `\`${pkg}\`: ${sev} — ${alert?.security_advisory?.summary || 'Dependabot advisory'} (${alert?.security_advisory?.ghsa_id || 'GHSA ?'}).`,
38
+ source: `gh:dependabot:${file}`,
39
+ };
40
+ }
41
+
42
+ /** Maps one code-scanning alert (GitHub API shape) to a finding. Pure. */
43
+ export function mapCodeScanningAlert(alert) {
44
+ const sev = alert?.rule?.security_severity_level || alert?.rule?.severity || 'warning';
45
+ const file = alert?.most_recent_instance?.location?.path || 'code';
46
+ return {
47
+ kind: 'code-scanning',
48
+ severity: SEV[String(sev).toLowerCase()] || 2,
49
+ path: file,
50
+ message: `${alert?.rule?.id || 'rule'}: ${alert?.rule?.description || alert?.most_recent_instance?.message?.text || 'code-scanning alert'}.`,
51
+ source: `gh:code-scanning:${file}`,
52
+ };
53
+ }
54
+
55
+ function gh(args) {
56
+ return execFileSync('gh', args, { cwd: ROOT, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 30000 });
57
+ }
58
+
59
+ function repoNwo() {
60
+ try {
61
+ return JSON.parse(gh(['repo', 'view', '--json', 'nameWithOwner'])).nameWithOwner || null;
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+
67
+ function apiJson(path) {
68
+ try {
69
+ return JSON.parse(gh(['api', '-H', 'Accept: application/vnd.github+json', '--paginate', path]) || 'null');
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+
75
+ function dependabotAlerts(repo) {
76
+ const alerts = apiJson(`repos/${repo}/dependabot/alerts?state=open&per_page=100`);
77
+ if (!Array.isArray(alerts)) return;
78
+ for (const a of alerts) findings.push(mapDependabotAlert(a));
79
+ }
80
+
81
+ function codeScanningAlerts(repo) {
82
+ const alerts = apiJson(`repos/${repo}/code-scanning/alerts?state=open&per_page=100`);
83
+ if (!Array.isArray(alerts)) return;
84
+ for (const a of alerts) findings.push(mapCodeScanningAlert(a));
85
+ }
86
+
87
+ function main() {
88
+ const repo = repoNwo();
89
+ if (!repo) {
90
+ if (process.argv.includes('--json')) process.stdout.write('{"findings":[]}\n');
91
+ else console.log('🔐 gh-alerts: no GitHub repo / `gh` unavailable — nothing to sync.');
92
+ return;
93
+ }
94
+ dependabotAlerts(repo);
95
+ codeScanningAlerts(repo);
96
+ const report = { findings };
97
+
98
+ if (process.argv.includes('--write')) {
99
+ writeFileSync(resolve(P.memory, 'gh-alerts-findings.json'), JSON.stringify(report, null, 2), 'utf-8');
100
+ console.log(`🔐 gh-alerts: ${findings.length} alert(s) → contextkit/memory/gh-alerts-findings.json`);
101
+ console.log(' → feed the backlog: node contextkit/tools/scripts/pipeline.mjs ingest contextkit/memory/gh-alerts-findings.json --type chore');
102
+ return;
103
+ }
104
+ if (process.argv.includes('--json')) {
105
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
106
+ return;
107
+ }
108
+ if (findings.length === 0) {
109
+ console.log(`🔐 gh-alerts: no open alerts for ${repo} (or none accessible).`);
110
+ return;
111
+ }
112
+ console.log(`🔐 gh-alerts: ${findings.length} open alert(s) for ${repo}.`);
113
+ for (const f of [...findings].sort((a, b) => b.severity - a.severity)) console.log(` ${'●'.repeat(f.severity)} ${f.kind} — ${f.message}`);
114
+ }
115
+
116
+ // Auto-run only when invoked as a script; importing (for tests) is side-effect-free.
117
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main();