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,172 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ContextDevKit integration test — TOOLING scripts.
4
+ *
5
+ * Installs the kit into a throwaway temp project and exercises the tool scripts
6
+ * (modular CLAUDE.md, git, deep-analysis, security mode, deps-audit, gh-alerts,
7
+ * fleet, agent-tuning, …). Two focused siblings carry the longer subsystems:
8
+ * `integration-test-tooling-pipeline.mjs` (DevPipeline, ADR-0016 H1 split)
9
+ * and `integration-test-tooling-agent-forge.mjs` (forge round-trip + Fase 6
10
+ * pipeline DSL — split when Fase 6 pushed this file past the RED zone, as the
11
+ * cohesion note had anticipated). The core hooks/engine are covered by
12
+ * `integration-test.mjs`. Shared harness: `it-helpers.mjs`.
13
+ *
14
+ * Cohesion note (line budget): the remaining ~13 tool checks share ONE
15
+ * fixture install at L5 and run in dependency order under a single
16
+ * try/finally — that is the responsibility seam (one install, many tool
17
+ * scripts). The next natural extraction when budget pressure returns is the
18
+ * deps-audit + GitHub security batch (the next-longest cohesive subsystem).
19
+ *
20
+ * Run: node tools/integration-test-tooling.mjs (exit 0 = healthy)
21
+ */
22
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
23
+ import { tmpdir } from 'node:os';
24
+ import { join } from 'node:path';
25
+ import { KIT, run, readJson, reporter, installFixture } from './it-helpers.mjs';
26
+
27
+ const rep = reporter();
28
+ const { ok, bad } = rep;
29
+ console.log('\n🌀 ContextDevKit integration test — tooling\n');
30
+ const fx = installFixture(rep);
31
+ const { proj, cfgPath, hook, script } = fx;
32
+
33
+ try {
34
+ // Modular CLAUDE.md: two apps lacking CLAUDE.md → scaffold creates both.
35
+ mkdirSync(join(proj, 'apps', 'api'), { recursive: true });
36
+ mkdirSync(join(proj, 'apps', 'web'), { recursive: true });
37
+ writeFileSync(join(proj, 'apps', 'api', 'package.json'), '{"name":"api"}');
38
+ writeFileSync(join(proj, 'apps', 'web', 'package.json'), '{"name":"web"}');
39
+ const cmFind = script('claude-md.mjs', 'find', '--json');
40
+ (() => { try { return JSON.parse(cmFind.stdout).moduleRoots.length === 2; } catch { return false; } })()
41
+ ? ok('claude-md detects 2 module roots') : bad(`claude-md find failed: ${cmFind.stdout || cmFind.stderr}`);
42
+ script('claude-md.mjs', 'scaffold');
43
+ existsSync(join(proj, 'apps', 'api', 'CLAUDE.md')) && existsSync(join(proj, 'apps', 'web', 'CLAUDE.md'))
44
+ ? ok('claude-md scaffolds scoped CLAUDE.md per module') : bad('module CLAUDE.md not scaffolded');
45
+
46
+ // Version control: git.mjs reports a repo with no remote (temp project has none).
47
+ const gitStatus = script('git.mjs', 'status', '--json');
48
+ (() => { try { const g = JSON.parse(gitStatus.stdout); return g.isRepo === true && g.remoteUrl === null; } catch { return false; } })()
49
+ ? ok('git.mjs reports repo + missing remote') : bad(`git.mjs failed: ${gitStatus.stdout || gitStatus.stderr}`);
50
+
51
+ // DevPipeline tests live in `integration-test-tooling-pipeline.mjs` (sibling).
52
+
53
+ // Deep analysis: aggregates the deterministic scanners into one report.
54
+ const deep = JSON.parse(script('deep-analysis.mjs', '--json').stdout || '{}');
55
+ deep.byScan && typeof deep.total === 'number' && Array.isArray(deep.findings)
56
+ ? ok('deep-analysis aggregates scanners into one report') : bad(`deep-analysis failed: ${JSON.stringify(deep).slice(0, 120)}`);
57
+
58
+ // Security mode: SessionStart reminds to /deep-analysis on the cadence (default-on).
59
+ const secCfg = readJson(cfgPath);
60
+ secCfg.securityMode = { active: true, everyNSessions: 1 };
61
+ writeFileSync(cfgPath, JSON.stringify(secCfg, null, 2));
62
+ writeFileSync(join(proj, 'contextkit', 'memory', 'sessions', '2026-01-01-01-x.md'), '# x');
63
+ hook('session-start.mjs', { session_id: 'sec' }).includes('Security mode')
64
+ ? ok('security-mode boot trigger fires on cadence') : bad('security-mode banner missing');
65
+ secCfg.securityMode.active = false;
66
+ writeFileSync(cfgPath, JSON.stringify(secCfg, null, 2));
67
+ !hook('session-start.mjs', { session_id: 'sec' }).includes('Security mode')
68
+ ? ok('security-mode disabled via config (active:false)') : bad('security-mode fired while disabled');
69
+
70
+ // Security: a crafted base-branch arg must reach git LITERALLY (one invalid ref →
71
+ // non-zero exit), not be split by a shell — proves no shell was involved.
72
+ const wt = script('worktree-new.mjs', 'feat', 'HEAD; echo INJECTED_PWNED');
73
+ wt.status !== 0
74
+ ? ok('worktree-new passes the base-branch arg literally (no shell injection)')
75
+ : bad('worktree-new shell injection NOT neutralized (a shell split the arg)');
76
+
77
+ // tech-debt --ci gate: a clean project has no RED-zone finding → exits 0.
78
+ const debtCi = script('tech-debt-scan.mjs', '--ci');
79
+ debtCi.status === 0 && /CI gate/.test(debtCi.stdout || '')
80
+ ? ok('tech-debt --ci gate passes on a clean project')
81
+ : bad(`tech-debt --ci gate failed: ${debtCi.stdout || debtCi.stderr}`);
82
+
83
+ // Pluggable detectors: a drop-in contextkit/detectors/*.mjs is loaded and its findings appear.
84
+ mkdirSync(join(proj, 'contextkit', 'detectors'), { recursive: true });
85
+ writeFileSync(join(proj, 'contextkit', 'detectors', 'custom.mjs'),
86
+ "export default function detectFooBar(p, c) { return c.includes('FOOBAR') ? [{ kind: 'custom-foobar', severity: 2, path: p, line: 1, message: 'FOOBAR marker' }] : []; }\n");
87
+ mkdirSync(join(proj, 'src'), { recursive: true });
88
+ writeFileSync(join(proj, 'src', 'marker.js'), '// FOOBAR\n');
89
+ JSON.parse(script('tech-debt-scan.mjs', '--json').stdout || '{"findings":[]}').findings.some((f) => f.kind === 'custom-foobar')
90
+ ? ok('tech-debt-scan loads a drop-in custom detector (contextkit/detectors/)') : bad('custom detector not loaded');
91
+
92
+ // Stack presets: install --preset merges stack paths into config (union with defaults).
93
+ run([join(KIT, 'install.mjs'), '--target', proj, '--update', '--preset', 'go']);
94
+ (readJson(cfgPath).ledger?.important || []).includes('internal/')
95
+ ? ok('install --preset merges a stack preset into config') : bad('preset paths not merged into config');
96
+
97
+ // Recommended start level (ADR-0009): greenfield auto-picks L3, existing auto-picks L7
98
+ // (the latter also proves the level cap accepts 7 — a broken cap would downgrade to 2).
99
+ const gdir = mkdtempSync(join(tmpdir(), 'contextkit-gf-'));
100
+ const edir = mkdtempSync(join(tmpdir(), 'contextkit-ex-'));
101
+ try {
102
+ run([join(KIT, 'install.mjs'), '--target', gdir, '--yes']);
103
+ readJson(join(gdir, 'contextkit', 'config.json')).level === 3
104
+ ? ok('install auto-picks L3 for a greenfield project') : bad(`greenfield default not L3: ${readJson(join(gdir, 'contextkit', 'config.json')).level}`);
105
+ mkdirSync(join(edir, 'src'), { recursive: true });
106
+ writeFileSync(join(edir, 'src', 'index.js'), 'export const x = 1;\n');
107
+ run([join(KIT, 'install.mjs'), '--target', edir, '--yes']);
108
+ readJson(join(edir, 'contextkit', 'config.json')).level === 7
109
+ ? ok('install auto-picks L7 for an existing project (+ level cap accepts 7)') : bad(`existing default not L7: ${readJson(join(edir, 'contextkit', 'config.json')).level}`);
110
+ } finally {
111
+ rmSync(gdir, { recursive: true, force: true });
112
+ rmSync(edir, { recursive: true, force: true });
113
+ }
114
+
115
+ // Quality CI workflow scaffolded (contract-drift + tech-debt gates).
116
+ existsSync(join(proj, '.github', 'workflows', 'quality.yml')) ? ok('quality CI workflow installed') : bad('quality.yml not installed');
117
+
118
+ // Visual testing harness (#6): the scaffolder writes a Playwright starter; status detects it.
119
+ script('visual-test.mjs', 'scaffold', '--js');
120
+ existsSync(join(proj, 'playwright.config.js')) && existsSync(join(proj, 'tests', 'visual', 'home.spec.js'))
121
+ ? ok('visual-test scaffolds a Playwright starter') : bad('visual-test did not scaffold');
122
+ (() => { try { return JSON.parse(script('visual-test.mjs', 'status', '--json').stdout).set === true; } catch { return false; } })()
123
+ ? ok('visual-test status detects the scaffolded harness') : bad('visual-test status missed the harness');
124
+
125
+ // Dependency audit: flags no-lockfile + loose version ranges as findings.
126
+ writeFileSync(join(proj, 'package.json'), JSON.stringify({ name: 'it', dependencies: { leftpad: '*' } }));
127
+ const deps = JSON.parse(script('deps-audit.mjs', '--json').stdout || '{"findings":[]}').findings || [];
128
+ deps.some((f) => f.kind === 'no-lockfile') && deps.some((f) => f.kind === 'loose-range')
129
+ ? ok('deps-audit flags no-lockfile + loose ranges') : bad(`deps-audit findings: ${JSON.stringify(deps)}`);
130
+
131
+ // Dependency policy: a denied license is flagged; --sbom writes a CycloneDX SBOM.
132
+ const depCfg = readJson(cfgPath);
133
+ depCfg.deps = { requireLockfile: true, licenses: { allow: [], deny: ['GPL-3.0'] } };
134
+ writeFileSync(cfgPath, JSON.stringify(depCfg, null, 2));
135
+ writeFileSync(join(proj, 'package.json'), JSON.stringify({ name: 'it', version: '1.0.0', dependencies: { gpllib: '1.0.0' } }));
136
+ mkdirSync(join(proj, 'node_modules', 'gpllib'), { recursive: true });
137
+ writeFileSync(join(proj, 'node_modules', 'gpllib', 'package.json'), JSON.stringify({ name: 'gpllib', version: '1.0.0', license: 'GPL-3.0' }));
138
+ JSON.parse(script('deps-audit.mjs', '--json').stdout || '{"findings":[]}').findings.some((f) => f.kind === 'license-deny')
139
+ ? ok('deps-audit flags a denied license (deps policy)') : bad('deps-audit did not flag the denied license');
140
+ script('deps-audit.mjs', '--sbom');
141
+ (() => { try { const s = readJson(join(proj, 'contextkit', 'memory', 'sbom.json')); return s.bomFormat === 'CycloneDX' && (s.components || []).some((c) => c.name === 'gpllib'); } catch { return false; } })()
142
+ ? ok('deps-audit --sbom writes a CycloneDX SBOM') : bad('SBOM not written/invalid');
143
+
144
+ // GitHub-native security: scaffolding + code-security agent installed; alert sync degrades safely.
145
+ existsSync(join(proj, '.github', 'dependabot.yml')) && existsSync(join(proj, '.github', 'workflows', 'security.yml'))
146
+ ? ok('GitHub security scaffolding installed (dependabot.yml + security workflow)') : bad('security scaffolding not installed');
147
+ existsSync(join(proj, '.claude', 'agents', 'code-security.md')) ? ok('code-security agent installed (L5)') : bad('code-security agent missing');
148
+ const ghAlerts = script('gh-alerts.mjs', '--json');
149
+ ghAlerts.status === 0 && (() => { try { return Array.isArray(JSON.parse(ghAlerts.stdout).findings); } catch { return false; } })()
150
+ ? ok('gh-alerts degrades safely without a GitHub repo (exit 0, empty findings)') : bad(`gh-alerts failed: ${ghAlerts.stdout || ghAlerts.stderr}`);
151
+
152
+ // Fleet mode: register this project in a temp registry, aggregate stats across the fleet.
153
+ const fleetEnv = { ...process.env, CONTEXT_FLEET_FILE: join(proj, '.fleet.json') };
154
+ const fleet = (...a) => run([join(proj, 'contextkit', 'tools', 'scripts', 'fleet.mjs'), ...a], { cwd: proj, env: fleetEnv });
155
+ fleet('add', proj);
156
+ const fleetStats = fleet('stats', '--json');
157
+ (() => { try { const d = JSON.parse(fleetStats.stdout); return d.totals.repos === 1 && d.repos[0]?.ok === true && typeof d.totals.totalSessions === 'number'; } catch { return false; } })()
158
+ ? ok('fleet stats aggregates a registered repo (control plane)') : bad(`fleet failed: ${fleetStats.stdout || fleetStats.stderr}`);
159
+
160
+ // Agent tuning: signal aggregation lists the installed agent roster (proposes only).
161
+ const tuning = script('agent-tuning.mjs', '--json');
162
+ (() => { try { const d = JSON.parse(tuning.stdout); return Array.isArray(d.agents) && d.agents.length >= 1 && typeof d.sessionsAnalyzed === 'number'; } catch { return false; } })()
163
+ ? ok('agent-tuning aggregates the agent roster + signals') : bad(`agent-tuning failed: ${tuning.stdout || tuning.stderr}`);
164
+
165
+ // agent-forge round-trip + Fase 6 pipeline DSL → integration-test-tooling-agent-forge.mjs.
166
+ } catch (err) {
167
+ bad(`crashed: ${err?.stack || err}`);
168
+ } finally {
169
+ fx.cleanup();
170
+ }
171
+
172
+ rep.finish('Integration (tooling)');
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ContextDevKit integration test — CORE engine (install + the real hooks).
4
+ *
5
+ * Installs the kit into a throwaway temp project and drives the runtime hooks
6
+ * end-to-end (drift block, L5 gate, predictions, concurrency, --update, …). The
7
+ * tool scripts (pipeline, deps, fleet, agent-tuning, …) are covered by
8
+ * `integration-test-tooling.mjs`. Shared harness: `it-helpers.mjs`.
9
+ *
10
+ * Run: node tools/integration-test.mjs (exit 0 = healthy)
11
+ */
12
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
13
+ import { join } from 'node:path';
14
+ import { KIT, run, readJson, reporter, installFixture } from './it-helpers.mjs';
15
+
16
+ const rep = reporter();
17
+ const { ok, bad } = rep;
18
+ console.log('\n🌀 ContextDevKit integration test — core\n');
19
+ const fx = installFixture(rep);
20
+ const { proj, cfgPath, hook, script } = fx;
21
+
22
+ try {
23
+ // L3 git hooks installed (pre-push conflict check).
24
+ existsSync(join(proj, '.git', 'hooks', 'pre-push')) ? ok('pre-push git hook installed') : bad('pre-push hook missing');
25
+
26
+ // First-run trigger.
27
+ hook('session-start.mjs', {}).includes('First run')
28
+ ? ok('SessionStart fires the first-run trigger')
29
+ : bad('first-run banner missing');
30
+
31
+ // Drift ledger + Stop block.
32
+ hook('track-edits.mjs', { session_id: 'it', tool_name: 'Write', tool_input: { file_path: 'src/a.js' } });
33
+ hook('track-edits.mjs', { session_id: 'it', tool_name: 'Write', tool_input: { file_path: 'src/b.js' } });
34
+ existsSync(join(proj, '.claude', '.sessions', 'it.json')) ? ok('PostToolUse writes the ledger') : bad('ledger not written');
35
+ hook('check-registration.mjs', { session_id: 'it' }).includes('"decision":"block"')
36
+ ? ok('Stop blocks on drift')
37
+ : bad('Stop did not block on drift');
38
+
39
+ // L5 gate: block, then allow after a simulation record.
40
+ const cfg = readJson(cfgPath);
41
+ cfg.l5.highRiskPaths = ['src/secure/'];
42
+ writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
43
+ hook('simulate-gate.mjs', { session_id: 'it', tool_name: 'Write', tool_input: { file_path: 'src/secure/x.js' } }).includes('"decision":"block"')
44
+ ? ok('L5 gate blocks an unsimulated high-risk edit')
45
+ : bad('L5 gate did not block');
46
+ script('mark-simulation.mjs', 'cover secure', 'src/secure/');
47
+ hook('simulate-gate.mjs', { session_id: 'it', tool_name: 'Write', tool_input: { file_path: 'src/secure/x.js' } }).trim() === ''
48
+ ? ok('L5 gate allows after /simulate-impact')
49
+ : bad('L5 gate still blocked after simulation');
50
+ // Ancestor parity: /simulate-impact leaves a prediction trail file.
51
+ existsSync(join(proj, 'contextkit', 'memory', 'predictions')) && readdirSync(join(proj, 'contextkit', 'memory', 'predictions')).some((f) => f.endsWith('.md'))
52
+ ? ok('simulate-impact writes a prediction file (predictions/)')
53
+ : bad('no prediction file written');
54
+ // Pluggable-detector seed (026): README + inert example install (discoverable, not auto-run).
55
+ existsSync(join(proj, 'contextkit', 'detectors', 'README.md')) && existsSync(join(proj, 'contextkit', 'detectors', 'example-detector.mjs.example'))
56
+ ? ok('detectors seed installed (README + .example, discoverable)') : bad('detectors seed not installed');
57
+ // Ancestor parity: workflow guides (L1–L6) + reusable playbooks are installed.
58
+ existsSync(join(proj, 'contextkit', 'workflows', 'README.md')) &&
59
+ ['tech-debt-sweep.md', 'simulate-impact.md', 'distillation-cycle.md', 'security-batch.md']
60
+ .every((f) => existsSync(join(proj, 'contextkit', 'workflows', 'playbooks', f)))
61
+ ? ok('workflows + playbooks installed (workflows/playbooks/)')
62
+ : bad('workflows/playbooks not installed');
63
+ // Ancestor parity #1 (loop closed): predictions-review fills the Actual section.
64
+ script('predictions-review.mjs');
65
+ const predMd = readdirSync(join(proj, 'contextkit', 'memory', 'predictions')).find((f) => f.endsWith('.md'));
66
+ const predBody = predMd ? readFileSync(join(proj, 'contextkit', 'memory', 'predictions', predMd), 'utf-8') : '';
67
+ predBody.includes('## Actual (reviewed') && predBody.includes('src/a.js') && !predBody.includes('fill on review')
68
+ ? ok('predictions-review closes the predicted-vs-actual loop (Actual filled)')
69
+ : bad('predictions-review did not fill the Actual section');
70
+
71
+ // Concurrency guard (L3+): warn before overwriting a file another session edited.
72
+ hook('track-edits.mjs', { session_id: 'other', tool_name: 'Write', tool_input: { file_path: 'src/shared.js' } });
73
+ hook('concurrency-guard.mjs', { session_id: 'me', tool_name: 'Write', tool_input: { file_path: 'src/shared.js' } }).includes('Concurrency')
74
+ ? ok('concurrency-guard warns on cross-session collision')
75
+ : bad('concurrency-guard did not warn');
76
+ const l5settings = readJson(join(proj, '.claude', 'settings.json'));
77
+ (l5settings.hooks?.PreToolUse || []).some((g) => (g.hooks || []).some((h) => h.command.includes('concurrency-guard')))
78
+ ? ok('L5 wires the concurrency guard (PreToolUse)') : bad('concurrency-guard not wired at L5');
79
+
80
+ // 008 — a booting session must NOT delete a concurrent session's fresh/empty ledger.
81
+ const concLedger = join(proj, '.claude', '.sessions', 'concurrent.json');
82
+ writeFileSync(concLedger, JSON.stringify({ sessionId: 'concurrent', startedAt: Date.now(), modifications: [], registered: false, stopWarnedAt: null, simulations: [] }));
83
+ hook('session-start.mjs', { session_id: 'booting-now' });
84
+ existsSync(concLedger) ? ok('session-start preserves a concurrent session fresh ledger (008)') : bad('session-start deleted a concurrent fresh ledger');
85
+
86
+ // Safe --update: preserves CLAUDE.md, config (level + overrides), memory.
87
+ writeFileSync(join(proj, 'CLAUDE.md'), readFileSync(join(proj, 'CLAUDE.md'), 'utf-8') + '\n## USER MARKER\n');
88
+ run([join(KIT, 'install.mjs'), '--target', proj, '--update']);
89
+ const afterCfg = readJson(join(proj, 'contextkit', 'config.json'));
90
+ readFileSync(join(proj, 'CLAUDE.md'), 'utf-8').includes('USER MARKER') && afterCfg.level === 5 && !existsSync(join(proj, 'CLAUDE.contextdevkit.md'))
91
+ ? ok('--update preserves CLAUDE.md + level (no data loss)')
92
+ : bad('--update lost data (CLAUDE.md/level/side-file)');
93
+
94
+ // setup-complete silences the trigger.
95
+ script('setup-complete.mjs');
96
+ !hook('session-start.mjs', {}).includes('First run')
97
+ ? ok('first-run trigger silent after setup-complete')
98
+ : bad('trigger still firing after setup-complete');
99
+
100
+ // context-level down to L2 removes PreToolUse wiring.
101
+ script('context-level.mjs', '2');
102
+ const settings = readJson(join(proj, '.claude', 'settings.json'));
103
+ !settings.hooks?.PreToolUse ? ok('context-level 2 removes the L5 PreToolUse hook') : bad('PreToolUse still wired at L2');
104
+ settings.hooks?.SessionStart && settings.hooks?.Stop ? ok('context-level 2 keeps L1/L2 hooks') : bad('L1/L2 hooks lost');
105
+ // L7 is a valid capability-tier level (no new hook beyond L5/L6).
106
+ script('context-level.mjs', '7');
107
+ readJson(join(proj, 'contextkit', 'config.json')).level === 7 ? ok('context-level 7 sets the L7 capability tier') : bad('context-level 7 not applied');
108
+
109
+ // GitHub templates + QA/compliance/design/security agents + two-tier briefings.
110
+ existsSync(join(proj, '.github', 'PULL_REQUEST_TEMPLATE.md')) ? ok('GitHub PR template installed') : bad('PR template not installed');
111
+ existsSync(join(proj, '.claude', 'agents', 'qa-orchestrator.md')) ? ok('QA squad agents installed (L5)') : bad('qa-orchestrator agent missing');
112
+ existsSync(join(proj, 'contextkit', 'squads', 'README.md')) ? ok('squad manifest installed') : bad('squads/README.md missing');
113
+ existsSync(join(proj, '.claude', 'agents', 'privacy-lgpd.md')) && existsSync(join(proj, '.claude', 'agents', 'ux-designer.md'))
114
+ ? ok('compliance + design squads installed') : bad('new squad agents missing');
115
+ existsSync(join(proj, '.claude', 'agents', 'infra-security.md')) ? ok('security-team infra-security agent installed') : bad('infra-security agent missing');
116
+ script('squad.mjs', 'brief', 'security');
117
+ existsSync(join(proj, 'contextkit', 'squads', 'security-team', 'security.md'))
118
+ ? ok('squad brief scaffolds a tier-2 briefing (squads/<team>/)') : bad('squad brief did not scaffold');
119
+
120
+ // Status-line widget: wired into settings.json + runs and prints a line.
121
+ readJson(join(proj, '.claude', 'settings.json')).statusLine?.command?.includes('contextkit/runtime/statusline')
122
+ ? ok('statusLine widget wired into settings.json') : bad('statusLine not wired into settings.json');
123
+ (run([join(proj, 'contextkit', 'runtime', 'statusline.mjs')], { cwd: proj }).stdout || '').includes('🌀')
124
+ ? ok('statusline.mjs prints a status line') : bad('statusline.mjs produced no output');
125
+
126
+ // context-config show/set round-trip.
127
+ script('context-config.mjs', 'set', 'qa.coverageTarget.lines', '90');
128
+ const showOut = script('context-config.mjs', 'show', 'qa.coverageTarget.lines').stdout || '';
129
+ showOut.trim() === '90' ? ok('context-config set/show round-trips') : bad(`context-config round-trip failed: ${showOut}`);
130
+
131
+ // doctor runs and reports — and accepts the current level (L7 set above) as valid,
132
+ // not "out of range" (regression guard for the level-range cap).
133
+ const doc = script('doctor.mjs');
134
+ /ContextDevKit doctor/i.test(doc.stdout || '') && !/level.*out of range/i.test(doc.stdout || '')
135
+ ? ok('doctor runs + accepts L7 as a valid level') : bad(`doctor failed/flagged level: ${doc.stdout || doc.stderr}`);
136
+
137
+ // L5/L6 scanners run and produce JSON.
138
+ const debt = script('tech-debt-scan.mjs', '--json');
139
+ (() => { try { return Array.isArray(JSON.parse(debt.stdout).findings); } catch { return false; } })()
140
+ ? ok('tech-debt-scan emits JSON findings') : bad(`tech-debt-scan failed: ${debt.stderr}`);
141
+ const stats = script('stats.mjs', '--json');
142
+ (() => { try { return typeof JSON.parse(stats.stdout).driftRatePct === 'number'; } catch { return false; } })()
143
+ ? ok('stats emits JSON metrics') : bad(`stats failed: ${stats.stderr}`);
144
+
145
+ // best-practices doc + business-rules scaffold installed.
146
+ existsSync(join(proj, 'contextkit', 'best-practices.md')) ? ok('best-practices.md installed') : bad('best-practices.md missing');
147
+ existsSync(join(proj, 'contextkit', 'memory', 'business-rules', '_TEMPLATE.md')) ? ok('business-rules/ scaffolded (ancestor parity)') : bad('business-rules template missing');
148
+
149
+ // Contract drift: deepened extractor catches default / export* / abstract / type-only.
150
+ const ccfg = readJson(cfgPath);
151
+ ccfg.l5 = ccfg.l5 || {};
152
+ ccfg.l5.contractGlobs = ['src/contract/'];
153
+ writeFileSync(cfgPath, JSON.stringify(ccfg, null, 2));
154
+ mkdirSync(join(proj, 'src', 'contract'), { recursive: true });
155
+ const apiPath = join(proj, 'src', 'contract', 'api.ts');
156
+ writeFileSync(apiPath, [
157
+ 'export default function main() {}',
158
+ 'export const alpha = 1;',
159
+ 'export abstract class Beta {}',
160
+ "export * from './other';",
161
+ 'export type Gamma = { x: number };',
162
+ "export { delta, epsilon as zeta } from './m';",
163
+ ].join('\n'));
164
+ script('contract-scan.mjs', '--save');
165
+ writeFileSync(apiPath, ['export const alpha = 1;', "export { delta, epsilon as zeta } from './m';"].join('\n'));
166
+ const drift = script('contract-scan.mjs', '--json');
167
+ (() => {
168
+ try {
169
+ const removed = JSON.parse(drift.stdout).removals.join('\n');
170
+ return ['default', 'Beta', 'Gamma'].every((n) => removed.includes(n)) && removed.includes('* from ./other');
171
+ } catch { return false; }
172
+ })()
173
+ ? ok('contract-scan detects removed default / export* / abstract / type-only exports')
174
+ : bad(`contract-scan drift miss: ${drift.stdout || drift.stderr}`);
175
+ // Optional AST contract drift (#001): with a parser available (fake via CONTEXT_CONTRACT_PARSER),
176
+ // extraction uses the AST, not regex — the baseline reflects AST-derived names.
177
+ const astCfg = readJson(cfgPath);
178
+ astCfg.l5.contractGlobs = ['src/ast/'];
179
+ writeFileSync(cfgPath, JSON.stringify(astCfg, null, 2));
180
+ mkdirSync(join(proj, 'src', 'ast'), { recursive: true });
181
+ writeFileSync(join(proj, 'src', 'ast', 'mod.js'), 'export const regexName = 1;\n');
182
+ writeFileSync(join(proj, '_fakeparser.mjs'), 'export function parse(){return{body:[{type:"ExportDefaultDeclaration"},{type:"ExportNamedDeclaration",specifiers:[{exported:{name:"astOnly"}}]}]};}\n');
183
+ run([join(proj, 'contextkit', 'tools', 'scripts', 'contract-scan.mjs'), '--save'], { cwd: proj, env: { ...process.env, CONTEXT_CONTRACT_PARSER: join(proj, '_fakeparser.mjs') } });
184
+ const astBaseline = readFileSync(join(proj, 'contextkit', 'memory', 'contract-baseline.json'), 'utf-8');
185
+ astBaseline.includes('astOnly') && !astBaseline.includes('regexName')
186
+ ? ok('contract-scan uses the optional AST parser when importable') : bad(`AST path not used: ${astBaseline}`);
187
+
188
+ // Playbook management (#8): the registry lists installed playbooks; run records a tracked entry.
189
+ const pbList = script('playbook.mjs', 'list').stdout || '';
190
+ pbList.includes('tech-debt-sweep') && pbList.includes('security-batch')
191
+ ? ok('playbook list shows the registry') : bad(`playbook list missing entries: ${pbList}`);
192
+ script('playbook.mjs', 'run', 'tech-debt-sweep', 'IT run');
193
+ const pbRuns = existsSync(join(proj, 'contextkit', 'memory', 'playbook-runs.md'))
194
+ && readFileSync(join(proj, 'contextkit', 'memory', 'playbook-runs.md'), 'utf-8');
195
+ pbRuns && pbRuns.includes('tech-debt-sweep')
196
+ ? ok('playbook run records a tracked entry') : bad('playbook run did not track');
197
+
198
+ // Token economy (#7): token-report aggregates usage from transcripts (fake --from dir; also
199
+ // exercises the cwd filter + defensive JSON parsing of a bad line).
200
+ const ttx = join(proj, '_ttx');
201
+ mkdirSync(ttx, { recursive: true });
202
+ const usageLine = (i, o) => JSON.stringify({ type: 'assistant', sessionId: 'sess1', timestamp: '2026-05-24T00:00:00Z', cwd: proj, message: { role: 'assistant', usage: { input_tokens: i, output_tokens: o, cache_read_input_tokens: 0, cache_creation_input_tokens: 0 } } });
203
+ writeFileSync(join(ttx, 'sess1.jsonl'), [usageLine(100, 200), usageLine(50, 25), '{ bad json'].join('\n'));
204
+ const tr = script('token-report.mjs', '--from', ttx, '--json');
205
+ (() => { try { const j = JSON.parse(tr.stdout); return j.sessions === 1 && j.totals.total === 375 && j.totals.input === 150; } catch { return false; } })()
206
+ ? ok('token-report aggregates token usage from transcripts') : bad(`token-report failed: ${tr.stdout || tr.stderr}`);
207
+
208
+ // Predictions-review cadence (#002): cadence on + an unreviewed prediction → SessionStart reminds.
209
+ const prCfg = readJson(cfgPath);
210
+ prCfg.predictionsReview = { active: true, everyNSessions: 1 };
211
+ writeFileSync(cfgPath, JSON.stringify(prCfg, null, 2));
212
+ writeFileSync(join(proj, 'contextkit', 'memory', 'sessions', '2026-01-01-01-x.md'), '# x\n');
213
+ writeFileSync(join(proj, 'contextkit', 'memory', 'predictions', 'unrev.md'), '# Prediction\n\n## Actual — fill on review\n');
214
+ hook('session-start.mjs', {}).includes('/predictions-review')
215
+ ? ok('predictions-review cadence reminds when a review is due') : bad('no predictions-review cadence reminder');
216
+
217
+ // Roadmap seeded (undefined) + find reports it as not-defined.
218
+ existsSync(join(proj, 'contextkit', 'memory', 'roadmap.md')) ? ok('roadmap.md installed') : bad('roadmap.md missing');
219
+ const rm = script('roadmap.mjs', 'find', '--json');
220
+ (() => { try { return JSON.parse(rm.stdout).canonicalDefined === false; } catch { return false; } })()
221
+ ? ok('roadmap find reports undefined (seed placeholder)') : bad(`roadmap find failed: ${rm.stderr || rm.stdout}`);
222
+ } catch (err) {
223
+ bad(`crashed: ${err?.stack || err}`);
224
+ } finally {
225
+ fx.cleanup();
226
+ }
227
+
228
+ rep.finish('Integration (core)');
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Shared harness for the integration tests.
3
+ *
4
+ * The end-to-end suite is split by responsibility to stay within the line budget:
5
+ * - `integration-test.mjs` — core engine: install + the real hooks.
6
+ * - `integration-test-tooling.mjs` — the tool scripts (deps, fleet, agent-forge, …).
7
+ * - `integration-test-tooling-pipeline.mjs` — the DevPipeline chain (ADR-0016 H1 split).
8
+ * - `integration-test-guards.mjs` — guards that REJECT bad input (commit-msg, pre-push, loader).
9
+ * Each installs a throwaway temp project via `installFixture` and drives it through
10
+ * `child_process` with a real stdin pipe — exactly how Claude Code invokes hooks.
11
+ * Cross-platform (avoids PowerShell's broken string-to-stdin piping), self-cleaning.
12
+ */
13
+ import { spawnSync } from 'node:child_process';
14
+ import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
15
+ import { tmpdir } from 'node:os';
16
+ import { dirname, join } from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ export const KIT = dirname(dirname(fileURLToPath(import.meta.url)));
20
+ export const node = process.execPath;
21
+ export const run = (args, opts = {}) => spawnSync(node, args, { encoding: 'utf-8', ...opts });
22
+ export const git = (args, cwd) => spawnSync('git', args, { cwd, encoding: 'utf-8' });
23
+ export const readJson = (p) => JSON.parse(readFileSync(p, 'utf-8').replace(/^/, ''));
24
+
25
+ /** A pass/fail reporter with its own failure counter. `finish` sets the exit code. */
26
+ export function reporter() {
27
+ let failures = 0;
28
+ return {
29
+ ok: (m) => console.log(` ✓ ${m}`),
30
+ bad: (m) => {
31
+ console.error(` ✗ ${m}`);
32
+ failures += 1;
33
+ },
34
+ finish: (label) => {
35
+ console.log(failures === 0 ? `\n✅ ${label} passed.\n` : `\n❌ ${failures} check(s) failed.\n`);
36
+ process.exit(failures === 0 ? 0 : 1);
37
+ },
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Fresh temp git repo with the kit installed at Level 5. Returns helpers bound to
43
+ * it: `hook(name, payload)` pipes JSON to a runtime hook; `script(rel, ...args)`
44
+ * runs a tool script; `cleanup()` removes the temp project.
45
+ */
46
+ export function installFixture(rep) {
47
+ const proj = mkdtempSync(join(tmpdir(), 'contextkit-it-'));
48
+ git(['init', '-b', 'main'], proj);
49
+ git(['config', 'user.email', 'it@example.com'], proj);
50
+ git(['config', 'user.name', 'IT'], proj);
51
+ const inst = run([join(KIT, 'install.mjs'), '--target', proj, '--level', '5', '--name', 'IT App', '--yes']);
52
+ inst.status === 0 ? rep.ok('install at Level 5') : rep.bad(`install failed (status ${inst.status}): ${inst.stderr}`);
53
+ return {
54
+ proj,
55
+ cfgPath: join(proj, 'contextkit', 'config.json'),
56
+ hook: (name, payload) => run([join(proj, 'contextkit', 'runtime', 'hooks', name)], { cwd: proj, input: JSON.stringify(payload) }).stdout || '',
57
+ script: (rel, ...a) => run([join(proj, 'contextkit', 'tools', 'scripts', rel), ...a], { cwd: proj }),
58
+ cleanup: () => rmSync(proj, { recursive: true, force: true }),
59
+ };
60
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Self-check assertions for the agent-forge **operations** surface — Fase 4 + 5:
3
+ * package discovery / diagnosis, the rag-designer extension, and the L5 high-risk
4
+ * paths default that gates `agent-packages/**` edits.
5
+ *
6
+ * Split out of `selfcheck-agent-forge.mjs` once the core file (foundational +
7
+ * build-pipeline checks) reached the 308 hard block — a real responsibility seam
8
+ * (build engine vs. running fleet), not a premature split.
9
+ *
10
+ * Entry point: `runAgentForgeOpsChecks(rep, KIT)`.
11
+ */
12
+ import { resolve } from 'node:path';
13
+
14
+ /** package-ops discovers `<name>@<semver>/` dirs without needing yaml; diagnose
15
+ * flags missing files + unresolved `{{TOKEN}}` placeholders in governance YAMLs. */
16
+ async function checkPackageOps(rep, KIT) {
17
+ const { ok, bad } = rep;
18
+ console.log('Checking agent-forge package-ops (Fase 4)...');
19
+ const opsUrl = 'file://' + resolve(KIT, 'templates/contextkit/squads/agent-forge/lib/package-ops.mjs').replaceAll('\\', '/');
20
+ let discoverPackages;
21
+ let diagnosePackage;
22
+ try {
23
+ ({ discoverPackages, diagnosePackage } = await import(opsUrl));
24
+ } catch (err) {
25
+ bad(`package-ops import failed: ${err.message}`);
26
+ return;
27
+ }
28
+ const { mkdtempSync, writeFileSync, mkdirSync, rmSync } = await import('node:fs');
29
+ const { tmpdir } = await import('node:os');
30
+ const { join } = await import('node:path');
31
+ const root = mkdtempSync(join(tmpdir(), 'forge-ops-'));
32
+ try {
33
+ mkdirSync(join(root, 'demo@0.1.0/governance'), { recursive: true });
34
+ mkdirSync(join(root, 'demo@0.1.0/prompts'));
35
+ mkdirSync(join(root, 'demo@0.1.0/tools'));
36
+ mkdirSync(join(root, 'demo@0.1.0/evals'));
37
+ mkdirSync(join(root, 'not-a-package'));
38
+ writeFileSync(join(root, 'demo@0.1.0/manifest.yaml'), 'apiVersion: x\n');
39
+ const pkgs = await discoverPackages(root);
40
+ pkgs.length === 1 && pkgs[0].name === 'demo' && pkgs[0].version === '0.1.0'
41
+ ? ok('package-ops.discoverPackages finds <name>@<semver> dirs and skips others (Fase 4)')
42
+ : bad(`discoverPackages wrong: ${JSON.stringify(pkgs)}`);
43
+ const diag = await diagnosePackage(join(root, 'demo@0.1.0'));
44
+ diag.ok === false && diag.problems.some((problem) => problem.includes('missing'))
45
+ ? ok('package-ops.diagnosePackage reports missing required files (Fase 4)')
46
+ : bad(`diagnose wrong: ${JSON.stringify(diag)}`);
47
+ writeFileSync(join(root, 'demo@0.1.0/governance/cost.policy.yaml'), 'budgets:\n per_call: {{0.015}}\n');
48
+ const diag2 = await diagnosePackage(join(root, 'demo@0.1.0'));
49
+ diag2.problems.some((problem) => problem.includes('placeholders'))
50
+ ? ok('package-ops.diagnosePackage refuses governance YAML with {{TOKEN}} placeholders (Fase 4)')
51
+ : bad(`diagnose missed placeholders: ${JSON.stringify(diag2)}`);
52
+ } finally {
53
+ rmSync(root, { recursive: true, force: true });
54
+ }
55
+ }
56
+
57
+ /** rag-designer shapes the bundle from blueprint (residency drives backend,
58
+ * domain drives embedding language, category drives chunk size, complexity drives top_k). */
59
+ async function checkRagDesigner(rep, KIT) {
60
+ const { ok, bad } = rep;
61
+ console.log('Checking agent-forge rag-designer (Fase 5)...');
62
+ const ragUrl = 'file://' + resolve(KIT, 'templates/contextkit/squads/agent-forge/lib/rag-designer.mjs').replaceAll('\\', '/');
63
+ let designRagConfig;
64
+ try {
65
+ ({ designRagConfig } = await import(ragUrl));
66
+ } catch (err) {
67
+ bad(`rag-designer import failed: ${err.message}`);
68
+ return;
69
+ }
70
+ const onPrem = designRagConfig({ intent: { category: 'rag-answer', complexity: 'high', domain: 'legal-pt-br' }, privacy: { allow_cloud_providers: false, data_residency: 'on-prem' } });
71
+ onPrem.config.index.backend === 'pgvector'
72
+ ? ok('rag-designer routes to pgvector under no-cloud / on-prem (Fase 5)')
73
+ : bad(`rag-designer leaked to cloud backend: ${onPrem.config.index.backend}`);
74
+ onPrem.config.embedding.model === 'multilingual-e5'
75
+ ? ok('rag-designer picks multilingual embedding for non `-en` domain (Fase 5)')
76
+ : bad(`embedding wrong for multilingual domain: ${onPrem.config.embedding.model}`);
77
+ onPrem.config.retrieval.top_k === 12
78
+ ? ok('rag-designer raises top_k for high-complexity intents (Fase 5)')
79
+ : bad(`top_k wrong for complexity=high: ${onPrem.config.retrieval.top_k}`);
80
+ const englishExtraction = designRagConfig({ intent: { category: 'extraction', complexity: 'low', domain: 'finance-en' }, privacy: { allow_cloud_providers: true } });
81
+ englishExtraction.config.embedding.model === 'text-embedding-3-large' && englishExtraction.chunker.chunk_size_tokens === 256
82
+ ? ok('rag-designer picks english embedding + tight chunks for extraction-en (Fase 5)')
83
+ : bad(`english-en + extraction wrong: ${JSON.stringify({ embed: englishExtraction.config.embedding.model, chunk: englishExtraction.chunker.chunk_size_tokens })}`);
84
+ }
85
+
86
+ /** defaults.mjs ships `agent-packages/**` in L5 highRiskPaths so the simulate-impact
87
+ * gate triggers on forged-agent edits (ADR-0012). */
88
+ async function checkL5ForgePath(rep, KIT) {
89
+ const { ok, bad } = rep;
90
+ console.log('Checking L5 high-risk paths default (Fase 5)...');
91
+ const defaultsUrl = 'file://' + resolve(KIT, 'templates/contextkit/runtime/config/defaults.mjs').replaceAll('\\', '/');
92
+ try {
93
+ const { DEFAULT_CONFIG } = await import(defaultsUrl);
94
+ DEFAULT_CONFIG?.l5?.highRiskPaths?.includes('agent-packages/**')
95
+ ? ok('defaults.l5.highRiskPaths includes agent-packages/** by default (Fase 5)')
96
+ : bad(`agent-packages/** missing from l5.highRiskPaths: ${JSON.stringify(DEFAULT_CONFIG?.l5?.highRiskPaths)}`);
97
+ } catch (err) {
98
+ bad(`defaults.mjs import failed: ${err.message}`);
99
+ }
100
+ }
101
+
102
+ /** Runs every agent-forge operations check in order. */
103
+ export async function runAgentForgeOpsChecks(rep, KIT) {
104
+ await checkPackageOps(rep, KIT);
105
+ await checkRagDesigner(rep, KIT);
106
+ await checkL5ForgePath(rep, KIT);
107
+ }