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,326 @@
1
+ /**
2
+ * Self-check — SOURCE / STRUCTURAL invariants.
3
+ *
4
+ * Owns the static-pattern checks that scan SHIPPED source files for
5
+ * properties that would silently regress if removed:
6
+ * - `checkSourceInvariants` — required patterns per file (timeouts,
7
+ * atomic writes, sid sanitization, single-sourced labels, etc.).
8
+ * - `checkNoHardcodedPaths` — rule 4 enforcement (no `contextkit/` path
9
+ * constructed via `resolve(...)`/`join(...)` in shipped runtime/scripts).
10
+ * - `checkWorkflowsPinned` — shipped GitHub Actions are SHA-pinned;
11
+ * CI declares least-privilege permissions.
12
+ *
13
+ * Split out of the legacy `selfcheck-checks.mjs` (ADR-0016 H1 / task 037 —
14
+ * by invariant category). The recursive-`.mjs`-listing helper `listMjs`
15
+ * lives here because this is the module that scans source trees; it is
16
+ * imported by `selfcheck-agent-forge.mjs` for the same reason.
17
+ *
18
+ * Every function takes the reporter `rep` ({ ok, bad }) plus only what it
19
+ * needs. Entry point: `runSourceChecks(rep, ctx)` where `ctx = { KIT }`.
20
+ */
21
+ import { readFile, readdir } from 'node:fs/promises';
22
+ import { resolve } from 'node:path';
23
+
24
+ const srcTextFor = (KIT) => (rel) => readFile(resolve(KIT, rel), 'utf-8').catch(() => '');
25
+
26
+ /** All `.mjs` under a directory, recursively. Shared with the agent-forge selfcheck. */
27
+ export async function listMjs(absDir) {
28
+ const out = [];
29
+ let entries = [];
30
+ try {
31
+ entries = await readdir(absDir, { withFileTypes: true });
32
+ } catch {
33
+ return out;
34
+ }
35
+ for (const e of entries) {
36
+ const p = resolve(absDir, e.name);
37
+ if (e.isDirectory()) out.push(...(await listMjs(p)));
38
+ else if (e.name.endsWith('.mjs')) out.push(p);
39
+ }
40
+ return out;
41
+ }
42
+
43
+ /** Source-level invariants — structural guarantees that would silently regress. */
44
+ async function checkSourceInvariants(rep, KIT) {
45
+ const { ok, bad } = rep;
46
+ const srcText = srcTextFor(KIT);
47
+ console.log('Checking source-level invariants...');
48
+ const cases = [
49
+ ['network git calls time out (git.mjs)', 'templates/contextkit/tools/scripts/git.mjs', /timeout:\s*\w/],
50
+ ['network git calls time out (pre-push.mjs)', 'templates/contextkit/runtime/git-hooks/pre-push.mjs', /timeout:\s*\w/],
51
+ ['ledger writes are atomic', 'templates/contextkit/runtime/hooks/ledger.mjs', /writeFileAtomic/],
52
+ ['pipeline writers are atomic', 'templates/contextkit/tools/scripts/pipeline.mjs', /writeFileAtomicSync/],
53
+ ['workspace-sync write is atomic', 'templates/contextkit/tools/scripts/workspace-sync.mjs', /writeFileAtomic/],
54
+ ['pipeline allocates ids with exclusive create', 'templates/contextkit/tools/scripts/pipeline.mjs', /flag:\s*'wx'/],
55
+ ['claim sanitizes the session id', 'templates/contextkit/tools/scripts/claim.mjs', /sanitizeSid/],
56
+ ['release sanitizes the session id', 'templates/contextkit/tools/scripts/release.mjs', /sanitizeSid/],
57
+ ['track-edits sanitizes the session id', 'templates/contextkit/runtime/hooks/track-edits.mjs', /sanitizeSid/],
58
+ ['session-start guards live ledgers from deletion', 'templates/contextkit/runtime/hooks/session-start.mjs', /maybeLive/],
59
+ ['config schema is passthrough', 'templates/contextkit/runtime/config/schema.mjs', /\.passthrough\(\)/],
60
+ ['config schema bounds level by MAX_LEVEL', 'templates/contextkit/runtime/config/schema.mjs', /max\(MAX_LEVEL\)/],
61
+ ['installer labels single-sourced from levels.mjs', 'tools/install/cli.mjs', /levels\.mjs/],
62
+ ['context-level labels single-sourced from levels.mjs', 'templates/contextkit/tools/scripts/context-level.mjs', /levels\.mjs/],
63
+ ['squad detection single-sourced (squad.mjs)', 'templates/contextkit/tools/scripts/squad.mjs', /squad-meta/],
64
+ ['squad detection single-sourced (agent-tuning.mjs)', 'templates/contextkit/tools/scripts/agent-tuning.mjs', /squad-meta/],
65
+ ['installer backs up an existing git hook', 'tools/install/git.mjs', /\.bak/],
66
+ ['installer follows .git pointer in worktrees (bug 038)', 'tools/install/git.mjs', /resolveGitDir/],
67
+ ['installer parses the gitdir: pointer', 'tools/install/git.mjs', /gitdir:\\s\*\(\.\+\)/],
68
+ ['agent-forge yaml loader uses optional dynamic import', 'templates/contextkit/squads/agent-forge/lib/yaml.mjs', /import\(\s*['"]yaml['"]\s*\)/],
69
+ ['installer copies the agent-forge squad at L>=4', 'install.mjs', /copyTree\(join\(TPL, 'contextkit', 'squads', 'agent-forge'\)/],
70
+ ['installer copies curated-stack starters', 'install.mjs', /copyTree\(join\(TPL, 'contextkit', 'starters'\)/],
71
+ ['detect-stack recognises TanStack family', 'templates/contextkit/tools/scripts/detect-stack.mjs', /@tanstack\/react-router/],
72
+ ['tanstack playbook present', 'templates/contextkit/workflows/playbooks/tanstack.md', /Playbook — TanStack/],
73
+ ['tanstack starter declares react-router dep', 'templates/contextkit/starters/tanstack/package.json', /@tanstack\/react-router/],
74
+ ['tanstack starter declares react-query dep', 'templates/contextkit/starters/tanstack/package.json', /@tanstack\/react-query/],
75
+ ['tanstack starter mounts QueryClientProvider', 'templates/contextkit/starters/tanstack/src/main.tsx', /QueryClientProvider/],
76
+ ['tanstack starter mounts RouterProvider', 'templates/contextkit/starters/tanstack/src/main.tsx', /RouterProvider/],
77
+ // ADR-0015 §B — DevPipeline working/ stage.
78
+ ['pipeline STAGES includes working (ADR-0015 §B)', 'templates/contextkit/tools/scripts/pipeline.mjs', /STAGES\s*=\s*\{[^}]*working:\s*'working'/],
79
+ ['pipeline STATUS includes working', 'templates/contextkit/tools/scripts/pipeline.mjs', /STATUS\s*=\s*\{[^}]*working:\s*'working'/],
80
+ ['pipeline.mjs wires start subcommand (ADR-0015 §B)', 'templates/contextkit/tools/scripts/pipeline.mjs', /cmd === 'start'/],
81
+ ['pipeline.mjs wires stop subcommand', 'templates/contextkit/tools/scripts/pipeline.mjs', /cmd === 'stop'/],
82
+ ['claim.mjs exports attachTask (ADR-0015 §B)', 'templates/contextkit/tools/scripts/claim.mjs', /export async function attachTask/],
83
+ ['claim.mjs exports detachTask', 'templates/contextkit/tools/scripts/claim.mjs', /export async function detachTask/],
84
+ ['workspace-sync evicts stale tasks (ADR-0015 §B)', 'templates/contextkit/tools/scripts/workspace-sync.mjs', /evictStaleTasks/],
85
+ ['pipeline-board renders the Working stage', 'templates/contextkit/tools/scripts/pipeline-board.mjs', /## šŸ”µ Working/],
86
+ ['defaults expose workingStaleAfterMinutes', 'templates/contextkit/runtime/config/defaults.mjs', /workingStaleAfterMinutes:\s*\d+/],
87
+ // ADR-0015 §C — canonical state.json substrate + /runs command.
88
+ ['state-io exports readState (ADR-0015 §C)', 'templates/contextkit/runtime/state/state-io.mjs', /export function readState/],
89
+ ['state-io exports writeState', 'templates/contextkit/runtime/state/state-io.mjs', /export function writeState/],
90
+ ['state-io exports listStates', 'templates/contextkit/runtime/state/state-io.mjs', /export function listStates/],
91
+ ['state-io exports prune', 'templates/contextkit/runtime/state/state-io.mjs', /export function prune/],
92
+ ['pipeline-session stamps state.json on start (ADR-0015 §C)', 'templates/contextkit/tools/scripts/pipeline-session.mjs', /writeState\(pipeDir,\s*id,\s*\{\s*kind:\s*'task'/],
93
+ ['pipeline-session stamps endedAt on stop', 'templates/contextkit/tools/scripts/pipeline-session.mjs', /endedAt:\s*Date\.now\(\)/],
94
+ ['workspace-sync mirrors heartbeat into state.json', 'templates/contextkit/tools/scripts/workspace-sync.mjs', /lastHeartbeat:\s*task\.lastHeartbeat/],
95
+ ['/runs reads listStates from state-io (ADR-0015 §C follow-up)', 'templates/contextkit/tools/scripts/runs.mjs', /import\s*\{\s*listStates\s*\}\s*from\s*['"]\.\.\/\.\.\/runtime\/state\/state-io\.mjs/],
96
+ ['/runs supports --kind filter', 'templates/contextkit/tools/scripts/runs.mjs', /\bkind:\s*kindFilter/],
97
+ ['/runs supports --json output', 'templates/contextkit/tools/scripts/runs.mjs', /flag\(['"]json['"]\)/],
98
+ ['/runs refuses cleanly when no states exist', 'templates/contextkit/tools/scripts/runs.mjs', /No runs yet/],
99
+ ['/runs command briefing ships', 'templates/claude/commands/pipeline/runs.md', /Lists the \*\*last N in-flight items\*\*/],
100
+ // ADR-0019 — MCP injection convention seeded in agent template (commented).
101
+ ['agent _TEMPLATE documents mcpServers convention (ADR-0019)', 'templates/claude/agents/_TEMPLATE.md', /mcpServers/],
102
+ ['agent _TEMPLATE flags rationale requirement (ADR-0019)', 'templates/claude/agents/_TEMPLATE.md', /rationale/],
103
+ // ADR-0021 — review-provider adapter contract + seed adapter.
104
+ ['provider _adapter exports validateAdapter (ADR-0021)', 'templates/contextkit/runtime/providers/review/_adapter.mjs', /export function validateAdapter/],
105
+ ['provider _adapter defines ProviderError (ADR-0021)', 'templates/contextkit/runtime/providers/review/_adapter.mjs', /export class ProviderError/],
106
+ ['provider gh adapter declares id (ADR-0021)', 'templates/contextkit/runtime/providers/review/gh.mjs', /export const id\s*=\s*'gh'/],
107
+ ['provider gh adapter declares cliBinary (ADR-0021)', 'templates/contextkit/runtime/providers/review/gh.mjs', /export const cliBinary/],
108
+ ['provider gh adapter exports detectsRemote (ADR-0021)', 'templates/contextkit/runtime/providers/review/gh.mjs', /export const detectsRemote/],
109
+ ['provider gh adapter exports createPullRequest (ADR-0021)', 'templates/contextkit/runtime/providers/review/gh.mjs', /export async function createPullRequest/],
110
+ ['provider detect exports resolveAdapter (ADR-0021)', 'templates/contextkit/runtime/providers/review/detect.mjs', /export async function resolveAdapter/],
111
+ // Ticket 045 — /watch slash command + script.
112
+ ['watch script exports parseLedgerEntry (ticket 045)', 'templates/contextkit/tools/scripts/watch.mjs', /export function parseLedgerEntry/],
113
+ ['watch command file present (ticket 045)', 'templates/claude/commands/watch.md', /watch the active session ledger/i],
114
+ // Ticket 042 — two-tier memory: per-task scratch gitignored under pipeline/.
115
+ ['pipeline .gitignore excludes scratch files (ticket 042)', 'templates/contextkit/pipeline/.gitignore', /\*\.scratch\.md/],
116
+ ['dev-start documents per-task scratch convention (ticket 042)', 'templates/claude/commands/pipeline/dev-start.md', /scratch\.md/],
117
+ // Ticket 048 / ADR-0020 — home.mjs helper for ~/.contextdevkit/ access.
118
+ ['home.mjs exports resolveHome (ADR-0020)', 'templates/contextkit/tools/scripts/home.mjs', /export function resolveHome/],
119
+ ['home.mjs exports readHomeFile (ADR-0020)', 'templates/contextkit/tools/scripts/home.mjs', /export function readHomeFile/],
120
+ ['home.mjs exports writeHomeFile (ADR-0020)', 'templates/contextkit/tools/scripts/home.mjs', /export function writeHomeFile/],
121
+ ['home.mjs writes atomically via renameSync (ADR-0020)', 'templates/contextkit/tools/scripts/home.mjs', /renameSync\(tmp, path\)/],
122
+ ['home.mjs honours CONTEXTDEVKIT_HOME override (ADR-0020)', 'templates/contextkit/tools/scripts/home.mjs', /CONTEXTDEVKIT_HOME/],
123
+ ['fleet.mjs delegates to home helper (ticket 048)', 'templates/contextkit/tools/scripts/fleet.mjs', /from '\.\/home\.mjs'/],
124
+ // Ticket 051 — /dashboard (snapshot + --watch live mode).
125
+ ['dashboard-data exports buildDashboardData (ticket 051)', 'templates/contextkit/tools/scripts/dashboard-data.mjs', /export function buildDashboardData/],
126
+ ['dashboard-data exports parseFrontmatter helper', 'templates/contextkit/tools/scripts/dashboard-data.mjs', /export function parseFrontmatter/],
127
+ ['dashboard-data single-sources PLATFORM_DIR (rule 4)', 'templates/contextkit/tools/scripts/dashboard-data.mjs', /PLATFORM_DIR/],
128
+ ['dashboard-html exports renderDashboardHTML (ticket 051)', 'templates/contextkit/tools/scripts/dashboard-html.mjs', /export function renderDashboardHTML/],
129
+ ['dashboard-html escapes user content', 'templates/contextkit/tools/scripts/dashboard-html.mjs', /escapeHtml/],
130
+ ['dashboard-server exports startDashboardServer', 'templates/contextkit/tools/scripts/dashboard-server.mjs', /export async function startDashboardServer/],
131
+ ['dashboard-server exports resolvePort', 'templates/contextkit/tools/scripts/dashboard-server.mjs', /export function resolvePort/],
132
+ ['dashboard-server binds 127.0.0.1 only (no remote access)', 'templates/contextkit/tools/scripts/dashboard-server.mjs', /listen\(port,\s*'127\.0\.0\.1'/],
133
+ ['dashboard-server emits SSE Content-Type', 'templates/contextkit/tools/scripts/dashboard-server.mjs', /text\/event-stream/],
134
+ ['dashboard.mjs dispatches snapshot vs --watch', 'templates/contextkit/tools/scripts/dashboard.mjs', /WANT_WATCH\s*\?\s*runLive/],
135
+ ['dashboard command file ships (ticket 051)', 'templates/claude/commands/dashboard.md', /Visual dashboard/i],
136
+ // Ticket 040 — task metadata v2 (DAG dependencies + complexity + extended types).
137
+ ['pipeline-validate exports detectCycles (ticket 040)', 'templates/contextkit/tools/scripts/pipeline-validate.mjs', /export function detectCycles/],
138
+ ['pipeline-validate exports blockedBy', 'templates/contextkit/tools/scripts/pipeline-validate.mjs', /export function blockedBy/],
139
+ ['pipeline-validate exports parseInlineArray', 'templates/contextkit/tools/scripts/pipeline-validate.mjs', /export function parseInlineArray/],
140
+ ['pipeline-validate enum covers spike + docs (ticket 040)', 'templates/contextkit/tools/scripts/pipeline-validate.mjs', /VALID_TYPES.*spike.*docs|VALID_TYPES.*docs.*spike/s],
141
+ ['pipeline.mjs writes complexity + dependencies fields', 'templates/contextkit/tools/scripts/pipeline.mjs', /complexity:\s*\$\{complexity\}/],
142
+ ['pipeline.mjs parses dependencies inline array', 'templates/contextkit/tools/scripts/pipeline.mjs', /parseInlineArray\(fm\.dependencies\)/],
143
+ ['pipeline.mjs wires validate subcommand', 'templates/contextkit/tools/scripts/pipeline.mjs', /cmd === 'validate'/],
144
+ ['pipeline-board renders blocked-by hint', 'templates/contextkit/tools/scripts/pipeline-board.mjs', /blocked by/],
145
+ // Ticket 046 — /resume for interrupted sessions.
146
+ ['/resume reads listAllLedgers from runtime (ticket 046)', 'templates/contextkit/tools/scripts/resume.mjs', /import.*listAllLedgers.*runtime\/hooks\/ledger\.mjs/],
147
+ ['/resume refuses unknown session id', 'templates/contextkit/tools/scripts/resume.mjs', /not found among unregistered drift candidates/],
148
+ ['/resume refuses cross-session claim conflict', 'templates/contextkit/tools/scripts/resume.mjs', /claimed by another active session/],
149
+ ['/resume rewrites LAST_TOUCHED_PATH atomically', 'templates/contextkit/tools/scripts/resume.mjs', /writeFileAtomicSync\(LAST_TOUCHED_PATH/],
150
+ ['/resume command briefing ships', 'templates/claude/commands/pipeline/resume.md', /Re-bind the current Claude Code session/],
151
+ // Ticket 043 — distill-detect proposal-only at /log-session end.
152
+ ['distill-detect exports detect (ticket 043)', 'templates/contextkit/tools/scripts/distill-detect.mjs', /export function detect/],
153
+ ['distill-detect surfaces "we decided" pattern', 'templates/contextkit/tools/scripts/distill-detect.mjs', /we\|i\)\\s\+decided/],
154
+ ['distill-detect surfaces "from now on" pattern', 'templates/contextkit/tools/scripts/distill-detect.mjs', /from now on/],
155
+ ['log-session briefing wires distill-detect (ticket 043)', 'templates/claude/commands/log-session.md', /distill-detect\.mjs/],
156
+ ['log-session briefing flags distill as proposal-only', 'templates/claude/commands/log-session.md', /proposal-only/],
157
+ // Ticket 041 — /workflow macro chains roadmap → ADR → pipeline → ship.
158
+ ['workflow.mjs ships 4 phases (ticket 041)', 'templates/contextkit/tools/scripts/workflow.mjs', /PHASES\s*=\s*\['roadmap',\s*'adr',\s*'tickets',\s*'ship'\]/],
159
+ ['workflow.mjs exposes new subcommand', 'templates/contextkit/tools/scripts/workflow.mjs', /cmd === 'new'/],
160
+ ['workflow.mjs exposes advance subcommand', 'templates/contextkit/tools/scripts/workflow.mjs', /cmd === 'advance'/],
161
+ ['workflow.mjs exposes status subcommand', 'templates/contextkit/tools/scripts/workflow.mjs', /cmd === 'status'/],
162
+ ['workflow.mjs slug regex blocks invalid slugs', 'templates/contextkit/tools/scripts/workflow.mjs', /SLUG_RE\s*=\s*\/\^/],
163
+ ['/workflow command briefing ships (ticket 041)', 'templates/claude/commands/pipeline/workflow.md', /chain \/roadmap → \/new-adr → \/pipeline → \/ship/],
164
+ // ADR-0023 / ticket 052 — landing-page posture (playbook + slash command).
165
+ ['landing-page playbook ships fold rules (ADR-0023)', 'templates/contextkit/workflows/playbooks/landing-page.md', /Folds — the strategic minimum/],
166
+ ['landing-page playbook lists anti-Lovable refusals', 'templates/contextkit/workflows/playbooks/landing-page.md', /Anti-Lovable refusals/],
167
+ ['landing-page playbook references seo-aiso gate', 'templates/contextkit/workflows/playbooks/landing-page.md', /seo-aiso\.md/],
168
+ ['/landing-page command briefing ships', 'templates/claude/commands/landing-page.md', /anti-cookie-cutter/i],
169
+ // ADR-0024 / ticket 053 — media-gen (Veo + Nano Banana adapters).
170
+ ['media _adapter exports validateAdapter (ADR-0024)', 'templates/contextkit/runtime/providers/media/_adapter.mjs', /export function validateAdapter/],
171
+ ['media _adapter defines MediaProviderError', 'templates/contextkit/runtime/providers/media/_adapter.mjs', /export class MediaProviderError/],
172
+ ['media _adapter exports assertCredentials', 'templates/contextkit/runtime/providers/media/_adapter.mjs', /export function assertCredentials/],
173
+ ['media _adapter exports noteCostOrThrow', 'templates/contextkit/runtime/providers/media/_adapter.mjs', /export function noteCostOrThrow/],
174
+ ['media _adapter exports MEDIA_ERROR_CODES', 'templates/contextkit/runtime/providers/media/_adapter.mjs', /export const MEDIA_ERROR_CODES/],
175
+ ['nano-banana adapter declares id (ADR-0024)', 'templates/contextkit/runtime/providers/media/nano-banana.mjs', /export const id\s*=\s*'nano-banana'/],
176
+ ['nano-banana adapter declares kind=image', 'templates/contextkit/runtime/providers/media/nano-banana.mjs', /export const kind\s*=\s*'image'/],
177
+ ['nano-banana adapter exports generate()', 'templates/contextkit/runtime/providers/media/nano-banana.mjs', /export async function generate/],
178
+ ['nano-banana adapter declares GOOGLE_AI_API_KEY env var', 'templates/contextkit/runtime/providers/media/nano-banana.mjs', /GOOGLE_AI_API_KEY/],
179
+ ['veo adapter declares id', 'templates/contextkit/runtime/providers/media/veo.mjs', /export const id\s*=\s*'veo'/],
180
+ ['veo adapter declares kind=video', 'templates/contextkit/runtime/providers/media/veo.mjs', /export const kind\s*=\s*'video'/],
181
+ ['veo adapter exports generate()', 'templates/contextkit/runtime/providers/media/veo.mjs', /export async function generate/],
182
+ ['veo adapter polls long-running operation', 'templates/contextkit/runtime/providers/media/veo.mjs', /predictLongRunning/],
183
+ ['media-gen CLI dispatches image|video kinds', 'templates/contextkit/tools/scripts/media-gen.mjs', /image['"]?\s*&&\s*kind\s*!==\s*['"]video/],
184
+ ['media-gen CLI honours --dry-run', 'templates/contextkit/tools/scripts/media-gen.mjs', /args\.dryRun/],
185
+ ['/media-gen command briefing ships', 'templates/claude/commands/media-gen.md', /Veo \+ Nano Banana/i],
186
+ ['.env.example template references GOOGLE_AI_API_KEY (ADR-0024)', 'templates/contextkit/.env.example', /GOOGLE_AI_API_KEY/],
187
+ ['.env.example template references cost cap', 'templates/contextkit/.env.example', /CONTEXTDEVKIT_MEDIA_MAX_USD/],
188
+ ['installer copies .env.example template (ADR-0024)', 'install.mjs', /\.env\.example/],
189
+ // ADR-0025 / ticket 054 — SEO + AISO audit + seo-specialist agent.
190
+ ['seo-specialist agent ships', 'templates/claude/agents/seo-specialist.md', /SEO \+ AISO specialist/],
191
+ ['seo-specialist refuses unindexable SPAs', 'templates/claude/agents/seo-specialist.md', /Refuse-on-unindexable/],
192
+ ['seo-aiso playbook ships (ADR-0025)', 'templates/contextkit/workflows/playbooks/seo-aiso.md', /Two indexes, two rule sets/],
193
+ ['seo-aiso playbook lists llms.txt convention', 'templates/contextkit/workflows/playbooks/seo-aiso.md', /`llms\.txt`/],
194
+ ['seo-aiso playbook lists FAQ schema as load-bearing', 'templates/contextkit/workflows/playbooks/seo-aiso.md', /FAQ schema — the load-bearing AISO move/],
195
+ ['audit-shared exports walkProject', 'templates/contextkit/tools/scripts/audit-shared.mjs', /export function\* walkProject/],
196
+ ['audit-shared exports detectFramework', 'templates/contextkit/tools/scripts/audit-shared.mjs', /export function detectFramework/],
197
+ ['audit-shared exports renderFindings', 'templates/contextkit/tools/scripts/audit-shared.mjs', /export function renderFindings/],
198
+ ['audit-shared exports exitCodeFor', 'templates/contextkit/tools/scripts/audit-shared.mjs', /export const exitCodeFor/],
199
+ ['seo-audit exports runSeoAudit', 'templates/contextkit/tools/scripts/seo-audit.mjs', /export function runSeoAudit/],
200
+ ['seo-audit flags SPA_ENTRYPOINT as critical', 'templates/contextkit/tools/scripts/seo-audit.mjs', /SPA_ENTRYPOINT:\s*'critical'/],
201
+ ['aiso-audit exports runAisoAudit', 'templates/contextkit/tools/scripts/aiso-audit.mjs', /export function runAisoAudit/],
202
+ ['aiso-audit names the AI crawlers list', 'templates/contextkit/tools/scripts/aiso-audit.mjs', /GPTBot.*ClaudeBot.*PerplexityBot/s],
203
+ ['/seo-audit command in audit/ pack', 'templates/claude/commands/audit/seo-audit.md', /SEO \+ AISO audit/i],
204
+ // landing-architect agent — closes the gap left by ADR-0023 / ticket 052.
205
+ ['landing-architect agent ships (ADR-0023)', 'templates/claude/agents/landing-architect.md', /Landing-page & high-conversion site specialist/],
206
+ ['landing-architect refuses cookie-cutter on sight', 'templates/claude/agents/landing-architect.md', /refuses the cookie-cutter/],
207
+ ['landing-architect names the three decisions in order', 'templates/claude/agents/landing-architect.md', /three decisions, in order/],
208
+ ['landing-architect delegation matrix points at seo-specialist gate', 'templates/claude/agents/landing-architect.md', /seo-specialist.*mandatory gate/],
209
+ // ADR-0026 — GitHub sync awareness (sync-check.mjs: preflight + prepr).
210
+ ['sync-check exposes preflight mode (ADR-0026)', 'templates/contextkit/tools/scripts/sync-check.mjs', /function preflight\(\)/],
211
+ ['sync-check exposes prepr mode (ADR-0026)', 'templates/contextkit/tools/scripts/sync-check.mjs', /function prepr\(\)/],
212
+ ['sync-check times out network calls (ADR-0026)', 'templates/contextkit/tools/scripts/sync-check.mjs', /timeout:\s*\w/],
213
+ ['sync-check degrades without gh — skip, not pass (rule 8)', 'templates/contextkit/tools/scripts/sync-check.mjs', /PR checks skipped/],
214
+ ['sync-check queries PR status fields', 'templates/contextkit/tools/scripts/sync-check.mjs', /PR_FIELDS\s*=/],
215
+ ['/dev-start runs sync-check preflight (ADR-0026)', 'templates/claude/commands/pipeline/dev-start.md', /sync-check\.mjs\s+preflight/],
216
+ ['/dev-start re-checks with sync-check prepr before a PR', 'templates/claude/commands/pipeline/dev-start.md', /sync-check\.mjs\s+prepr/],
217
+ ['/git pr runs sync-check prepr first (ADR-0026)', 'templates/claude/commands/vcs/git.md', /sync-check\.mjs\s+prepr/],
218
+ // ADR-0028 — Proactive Advisor (six-lane improvement engine).
219
+ ['defaults expose the advisor config block (ADR-0028)', 'templates/contextkit/runtime/config/defaults.mjs', /advisor:\s*\{/],
220
+ ['advisor config declares the six lanes in order', 'templates/contextkit/runtime/config/defaults.mjs', /architecture:[\s\S]*features:[\s\S]*deepen:[\s\S]*security:[\s\S]*ux:[\s\S]*growth:/],
221
+ ['advisor wires all six lanes to an owner (ADR-0028)', 'templates/contextkit/runtime/config/defaults.mjs', /deepen:\s*\{\s*owner:\s*'product-owner'\s*\},[\s\S]*growth:\s*\{\s*owner:\s*'growth'\s*\}/],
222
+ ['Stop hook proposes the advisor after real work (ADR-0028)', 'templates/contextkit/runtime/hooks/check-registration.mjs', /maybeProposeAdvisor/],
223
+ ['advisor nudge is debounced like distill', 'templates/contextkit/runtime/hooks/check-registration.mjs', /ADVISOR_NUDGE_DEBOUNCE_MS/],
224
+ ['/advise command ships the six lanes (ADR-0028)', 'templates/claude/commands/advise.md', /architecture[\s\S]*features[\s\S]*deepen[\s\S]*security[\s\S]*ux[\s\S]*growth/i],
225
+ ['/advise runs before/after modes', 'templates/claude/commands/advise.md', /--before|--after/],
226
+ ['/advise feeds the DevPipeline backlog', 'templates/claude/commands/advise.md', /pipeline\.mjs/],
227
+ ['/advise skips unowned lanes, never fakes them (rule 8)', 'templates/claude/commands/advise.md', /no\s+owner/i],
228
+ ['/advise growth lane routes to retention (ADR-0028)', 'templates/claude/commands/advise.md', /retention/i],
229
+ // ADR-0028 — growth-team squad (growth + retention) + product-owner deepen lens.
230
+ ['growth agent ships in growth-team (ADR-0028)', 'templates/claude/agents/growth.md', /\(growth-team squad\)/],
231
+ ['growth agent refuses dark patterns', 'templates/claude/agents/growth.md', /dark pattern/i],
232
+ ['retention agent ships in growth-team', 'templates/claude/agents/retention.md', /\(growth-team squad\)/],
233
+ ['retention agent splits voluntary vs involuntary churn', 'templates/claude/agents/retention.md', /involuntary/i],
234
+ ['product-owner owns the deepen-existing-features lens (ADR-0028)', 'templates/claude/agents/product-owner.md', /deepen[- ]existing[- ]features/i],
235
+ ['squads README registers the growth-team', 'templates/contextkit/squads/README.md', /growth-team/],
236
+ // ADR-0029 — Behavioral discipline layer (Karpathy-derived, MIT).
237
+ ['behaviors.md ships the four guidelines (ADR-0029)', 'templates/contextkit/behaviors.md', /Think before coding[\s\S]*Simplicity first[\s\S]*Surgical changes[\s\S]*Goal-driven execution/i],
238
+ ['behaviors.md credits the MIT Karpathy source', 'templates/contextkit/behaviors.md', /MIT-licensed[\s\S]*Karpathy|Karpathy[\s\S]*MIT-licensed/],
239
+ ['behaviors.md reconciles surgical vs deliberate refactor', 'templates/contextkit/behaviors.md', /deliberate.{0,24}task|opportunistic/i],
240
+ ['behaviors-examples ships before/after diffs (ADR-0029)', 'templates/contextkit/behaviors-examples.md', /Disciplined/],
241
+ ['constitution template adds the behavioral-discipline section (ADR-0029)', 'templates/CLAUDE.md.tpl', /Behavioral discipline/],
242
+ ['constitution names ask-when-ambiguous (think before coding)', 'templates/CLAUDE.md.tpl', /ask when the request is ambiguous/i],
243
+ ['defaults expose the behaviors flag (ADR-0029)', 'templates/contextkit/runtime/config/defaults.mjs', /behaviors:\s*\{\s*active:\s*true\s*\}/],
244
+ ['boot reminds behavioral discipline when active', 'templates/contextkit/runtime/hooks/session-start.mjs', /Behavioral discipline is ACTIVE/],
245
+ ['installer seeds behaviors.md (ADR-0029)', 'install.mjs', /'behaviors\.md'/],
246
+ ['installer seeds behaviors-examples.md', 'install.mjs', /'behaviors-examples\.md'/],
247
+ // ADR-0027 — token-economy digest layer (session/ADR pre-digestion).
248
+ ['md-extract exposes shared section() helper (ADR-0027)', 'templates/contextkit/runtime/hooks/md-extract.mjs', /export function section/],
249
+ ['md-extract exposes firstParagraph() helper (ADR-0027)', 'templates/contextkit/runtime/hooks/md-extract.mjs', /export function firstParagraph/],
250
+ ['session-digest-core parses a session log (ADR-0027)', 'templates/contextkit/runtime/hooks/session-digest-core.mjs', /export function parseSessionLog/],
251
+ ['session-digest-core renders a compact digest (ADR-0027)', 'templates/contextkit/runtime/hooks/session-digest-core.mjs', /export function renderDigest/],
252
+ ['session-digest single-sources the parser (ADR-0027)', 'templates/contextkit/tools/scripts/session-digest.mjs', /session-digest-core/],
253
+ ['session-digest exposes --last mode (ADR-0027)', 'templates/contextkit/tools/scripts/session-digest.mjs', /--last/],
254
+ ['/distill-sessions reasons over the session digest (ADR-0027)', 'templates/claude/commands/distill-sessions.md', /session-digest\.mjs/],
255
+ ['/retro reasons over the session digest (ADR-0027)', 'templates/claude/commands/pipeline/retro.md', /session-digest\.mjs/],
256
+ ['boot exposes digestLatestSession (ADR-0027)', 'templates/contextkit/runtime/hooks/boot-context-readers.mjs', /export async function digestLatestSession/],
257
+ ['boot keeps the raw extractor as a fallback (ADR-0027)', 'templates/contextkit/runtime/hooks/boot-context-readers.mjs', /export async function extractLatestSession/],
258
+ ['boot digest degrades to raw — never empty (rule 2/8)', 'templates/contextkit/runtime/hooks/boot-context-readers.mjs', /mode:\s*'raw'/],
259
+ ['session-start renders the session digest (ADR-0027)', 'templates/contextkit/runtime/hooks/session-start.mjs', /digestLatestSession/],
260
+ ['context-pack reuses the boot session digest (ADR-0027)', 'templates/contextkit/tools/scripts/context-pack.mjs', /digestLatestSession/],
261
+ ['context-pack reuses the ADR core (ADR-0027)', 'templates/contextkit/tools/scripts/context-pack.mjs', /adr-digest-core/],
262
+ ['/dev-start opens with the context pack (ADR-0027)', 'templates/claude/commands/pipeline/dev-start.md', /context-pack\.mjs/],
263
+ ['/state opens with the context pack (ADR-0027)', 'templates/claude/commands/state.md', /context-pack\.mjs/],
264
+ ['adr-digest-core parses an ADR (ADR-0027)', 'templates/contextkit/tools/scripts/adr-digest-core.mjs', /export function parseAdr/],
265
+ ['adr-digest single-sources the parser (ADR-0027)', 'templates/contextkit/tools/scripts/adr-digest.mjs', /adr-digest-core/],
266
+ ['adr-digest supports keyword search (ADR-0027)', 'templates/contextkit/tools/scripts/adr-digest.mjs', /--search/],
267
+ ['adr-digest excludes the ADR template (ADR-0027)', 'templates/contextkit/tools/scripts/adr-digest.mjs', /_TEMPLATE\.md/],
268
+ ['/ship scopes via the ADR catalog (ADR-0027)', 'templates/claude/commands/pipeline/ship.md', /adr-digest\.mjs/],
269
+ ['/new-adr checks for an existing decision first (ADR-0027)', 'templates/claude/commands/new-adr.md', /adr-digest\.mjs/],
270
+ ['/deep-analysis scans existing ADRs before drafting (ADR-0027)', 'templates/claude/commands/audit/deep-analysis.md', /adr-digest\.mjs/],
271
+ ];
272
+ for (const [label, rel, re] of cases) {
273
+ re.test(await srcText(rel)) ? ok(label) : bad(`${label} — pattern ${re} missing in ${rel}`);
274
+ }
275
+ }
276
+
277
+ /** Rule 4: no shipped runtime/script constructs a `contextkit/` path via resolve/join. */
278
+ async function checkNoHardcodedPaths(rep, KIT) {
279
+ const { ok, bad } = rep;
280
+ console.log('Checking platform paths are single-sourced (rule 4)...');
281
+ const re = /\b(resolve|join)\(.*['"]contextkit\//;
282
+ const offenders = [];
283
+ for (const d of ['templates/contextkit/runtime', 'templates/contextkit/tools/scripts']) {
284
+ for (const file of await listMjs(resolve(KIT, d))) {
285
+ const lines = (await readFile(file, 'utf-8').catch(() => '')).split('\n');
286
+ lines.forEach((line, i) => {
287
+ if (/^\s*(\*|\/\/)/.test(line)) return;
288
+ if (re.test(line)) offenders.push(`${file.replace(KIT, '').replaceAll('\\', '/')}:${i + 1}`);
289
+ });
290
+ }
291
+ }
292
+ offenders.length === 0
293
+ ? ok('no hardcoded contextkit/ path construction (all via pathsFor/PLATFORM_DIR)')
294
+ : offenders.forEach((o) => bad(`hardcoded contextkit/ path: ${o}`));
295
+ }
296
+
297
+ /** Shipped GitHub Actions must be SHA-pinned; CI must be least-privilege. */
298
+ async function checkWorkflowsPinned(rep, KIT) {
299
+ const { ok, bad } = rep;
300
+ const srcText = srcTextFor(KIT);
301
+ console.log('Checking GitHub Actions are SHA-pinned...');
302
+ const files = [
303
+ '.github/workflows/ci.yml',
304
+ '.github/workflows/release.yml',
305
+ 'templates/github/workflows/quality.yml',
306
+ 'templates/github/workflows/security.yml',
307
+ ];
308
+ const floating = /uses:\s*[\w./-]+@v\d/;
309
+ for (const rel of files) {
310
+ const text = await srcText(rel);
311
+ if (!text) {
312
+ bad(`workflow missing: ${rel}`);
313
+ continue;
314
+ }
315
+ floating.test(text) ? bad(`${rel} has an unpinned (floating) action tag`) : ok(`${rel} actions are SHA-pinned`);
316
+ }
317
+ /permissions:[\s\S]*?contents:\s*read/.test(await srcText('.github/workflows/ci.yml'))
318
+ ? ok('ci.yml declares least-privilege permissions (contents: read)') : bad('ci.yml missing contents:read permissions');
319
+ }
320
+
321
+ /** Runs every source/structural check in order. `ctx` = { KIT }. */
322
+ export async function runSourceChecks(rep, { KIT }) {
323
+ await checkSourceInvariants(rep, KIT);
324
+ await checkNoHardcodedPaths(rep, KIT);
325
+ await checkWorkflowsPinned(rep, KIT);
326
+ }
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ContextDevKit self-check — smoke test for the kit BEFORE you ship it.
4
+ *
5
+ * - Imports every library engine module to catch syntax / import errors.
6
+ * (Does NOT import the hook entrypoints — those self-execute `main()`.)
7
+ * - Asserts `composeSettings` wires the right hooks per level + config defaults.
8
+ * - Confirms the expected template files are present.
9
+ * - Delegates the deeper invariants to sibling modules split by category
10
+ * (ADR-0016 H1 / task 037):
11
+ * - `selfcheck-runtime.mjs` — boot readers, atomic I/O, sid, squad meta.
12
+ * - `selfcheck-config.mjs` — level taxonomy + zod schema agreement.
13
+ * - `selfcheck-source.mjs` — source-level patterns, rule 4, SHA-pinning.
14
+ * - `selfcheck-agent-forge.mjs` / `-ops.mjs` — agent-forge squad checks.
15
+ *
16
+ * Cohesion note (line budget): this file is the harness — engine-module
17
+ * loading, settings composition, config/loader checks, paths/presets,
18
+ * template inventory, plus dispatch to the five runners. They share one
19
+ * `ok`/`bad` reporter and run in a single `main()`. Splitting harness from
20
+ * inventory would scatter the one concern this file exists to express
21
+ * (smoke-test the kit before ship). Kept whole within the +10% tolerance.
22
+ *
23
+ * Run: node tools/selfcheck.mjs (exit 0 = healthy)
24
+ */
25
+ import { existsSync } from 'node:fs';
26
+ import { readdir } from 'node:fs/promises';
27
+ import { dirname, resolve } from 'node:path';
28
+ import { fileURLToPath } from 'node:url';
29
+ import { runRuntimeChecks } from './selfcheck-runtime.mjs';
30
+ import { runConfigChecks } from './selfcheck-config.mjs';
31
+ import { runSourceChecks } from './selfcheck-source.mjs';
32
+ import { runAgentForgeChecks } from './selfcheck-agent-forge.mjs';
33
+ import { runAgentForgeOpsChecks } from './selfcheck-agent-forge-ops.mjs';
34
+
35
+ const KIT = dirname(dirname(fileURLToPath(import.meta.url)));
36
+ const RT = resolve(KIT, 'templates/contextkit/runtime');
37
+ let failures = 0;
38
+ const ok = (m) => console.log(` āœ“ ${m}`);
39
+ const bad = (m) => {
40
+ console.error(` āœ— ${m}`);
41
+ failures++;
42
+ };
43
+
44
+ async function importLibs() {
45
+ console.log('Loading engine library modules...');
46
+ const libs = [
47
+ 'config/paths.mjs',
48
+ 'config/levels.mjs',
49
+ 'config/defaults.mjs',
50
+ 'config/load.mjs',
51
+ 'config/settings-compose.mjs',
52
+ 'config/presets.mjs',
53
+ 'hooks/path-classification.mjs',
54
+ 'hooks/safe-io.mjs',
55
+ 'hooks/boot-context-readers.mjs',
56
+ 'hooks/boot-signals.mjs',
57
+ 'hooks/ledger.mjs',
58
+ ];
59
+ const mods = {};
60
+ for (const rel of libs) {
61
+ try {
62
+ mods[rel] = await import('file://' + resolve(RT, rel).replaceAll('\\', '/'));
63
+ ok(rel);
64
+ } catch (err) {
65
+ bad(`${rel} — ${err?.message ?? err}`);
66
+ }
67
+ }
68
+ return mods;
69
+ }
70
+
71
+ function checkCompose(composeSettings) {
72
+ console.log('Checking settings composition per level...');
73
+ const events = (lvl) => Object.keys(composeSettings(null, lvl).hooks || {}).sort();
74
+ const expect = {
75
+ 1: ['SessionStart'],
76
+ 2: ['PostToolUse', 'SessionStart', 'Stop'],
77
+ 3: ['PostToolUse', 'PreToolUse', 'SessionStart', 'Stop'],
78
+ 4: ['PostToolUse', 'PreToolUse', 'SessionStart', 'Stop'],
79
+ 5: ['PostToolUse', 'PreToolUse', 'SessionStart', 'Stop'],
80
+ 6: ['PostToolUse', 'PreToolUse', 'SessionStart', 'Stop'],
81
+ 7: ['PostToolUse', 'PreToolUse', 'SessionStart', 'Stop'],
82
+ };
83
+ for (const [lvl, want] of Object.entries(expect)) {
84
+ const got = events(Number(lvl));
85
+ if (JSON.stringify(got) === JSON.stringify(want.sort())) ok(`L${lvl} → ${got.join(', ')}`);
86
+ else bad(`L${lvl} expected [${want}] got [${got}]`);
87
+ }
88
+ // Idempotency: re-composing existing settings must not duplicate entries.
89
+ const once = composeSettings(null, 5);
90
+ const twice = composeSettings(structuredClone(once), 5);
91
+ const dup = (twice.hooks.PostToolUse || []).length;
92
+ if (dup === 1) ok('re-running installer is idempotent (no duplicate hooks)');
93
+ else bad(`idempotency broken — PostToolUse has ${dup} groups after re-compose`);
94
+ // Status-line widget wired at L1+, and a user's own statusLine is preserved.
95
+ const sl = composeSettings(null, 1).statusLine;
96
+ sl && String(sl.command).includes('contextkit/runtime/statusline') ? ok('statusLine widget wired (L1+)') : bad('statusLine widget not wired');
97
+ composeSettings({ statusLine: { type: 'command', command: 'mine' } }, 5).statusLine?.command === 'mine'
98
+ ? ok('composeSettings preserves a user statusLine') : bad('composeSettings clobbered a user statusLine');
99
+ }
100
+
101
+ function checkConfig(load) {
102
+ console.log('Checking zero-dep config loader...');
103
+ const cfg = load.loadConfigSync(KIT);
104
+ if (Array.isArray(cfg?.ledger?.important) && cfg.ledger.important.length > 0) ok('defaults.ledger.important populated');
105
+ else bad('config defaults missing ledger.important');
106
+ if (Number.isInteger(load.getLevel(KIT))) ok(`getLevel() → L${load.getLevel(KIT)}`);
107
+ else bad('getLevel() did not return an integer');
108
+ }
109
+
110
+ function checkPresets(presets) {
111
+ if (!presets?.applyPreset) {
112
+ bad('presets.applyPreset not exported');
113
+ return;
114
+ }
115
+ const merged = presets.applyPreset({ ledger: { important: ['x/'] } }, 'next');
116
+ merged.ledger.important.includes('app/') && merged.ledger.important.includes('x/')
117
+ ? ok('applyPreset merges a stack preset (array union)') : bad('applyPreset did not merge the preset');
118
+ // 013 — a partial/custom preset (omits l5 + qa) must merge, not crash.
119
+ presets.PRESETS.__sc_partial = { ledger: { important: ['z/'] } };
120
+ try {
121
+ const partial = presets.applyPreset({}, '__sc_partial');
122
+ partial.ledger.important.includes('z/') && Array.isArray(partial.l5.highRiskPaths) && Array.isArray(partial.qa.criticalPaths)
123
+ ? ok('applyPreset tolerates a partial preset (missing l5/qa keys)') : bad('applyPreset partial-preset result malformed');
124
+ } catch (err) {
125
+ bad(`applyPreset crashed on a partial preset — ${err?.message ?? err}`);
126
+ } finally {
127
+ delete presets.PRESETS.__sc_partial;
128
+ }
129
+ }
130
+
131
+ function checkPaths(paths) {
132
+ if (!paths?.pathsFor) {
133
+ bad('pathsFor not exported');
134
+ return;
135
+ }
136
+ const pf = paths.pathsFor('/tmp/proj');
137
+ pf.pipeline.replaceAll('\\', '/').endsWith('contextkit/pipeline') && pf.sessions.replaceAll('\\', '/').endsWith('contextkit/memory/sessions')
138
+ ? ok('pathsFor resolves canonical absolute paths') : bad(`pathsFor wrong: ${pf.pipeline}`);
139
+ }
140
+
141
+ async function checkTemplates() {
142
+ console.log('Checking template inventory...');
143
+ // Ticket 047 — commands live in domain subfolders + at root. Walk recursively
144
+ // and assert (a) every expected command resolves by basename, (b) no two
145
+ // commands collide on basename (Claude Code resolves by basename).
146
+ async function walkCmds(dir, acc = []) {
147
+ for (const ent of await readdir(dir, { withFileTypes: true }).catch(() => [])) {
148
+ const full = resolve(dir, ent.name);
149
+ if (ent.isDirectory()) await walkCmds(full, acc);
150
+ else if (ent.name.endsWith('.md') && ent.name !== 'README.md') acc.push(ent.name);
151
+ }
152
+ return acc;
153
+ }
154
+ const cmds = await walkCmds(resolve(KIT, 'templates/claude/commands'));
155
+ cmds.length >= 35 ? ok(`${cmds.length} slash commands present (across packs + root)`) : bad(`only ${cmds.length} slash commands`);
156
+ const seen = new Map();
157
+ for (const c of cmds) seen.set(c, (seen.get(c) || 0) + 1);
158
+ const collisions = [...seen.entries()].filter(([, n]) => n > 1);
159
+ collisions.length === 0 ? ok('no command basename collides across packs (ticket 047)') : bad(`basename collisions: ${collisions.map(([n]) => n).join(', ')}`);
160
+ for (const c of ['setupcontextdevkit.md', 'distill-sessions.md', 'distill-apply.md', 'context-doctor.md', 'context-config.md', 'test-plan.md', 'scaffold-tests.md', 'qa-signoff.md', 'audit.md', 'ship.md', 'retro.md', 'context-stats.md', 'contract-check.md', 'aidevtool-from0.md', 'analyze-code-ia-practices.md', 'pipeline.md', 'roadmap.md', 'claude-md.md', 'git.md', 'squad.md', 'deps-audit.md', 'deep-analysis.md', 'security-setup.md', 'fleet.md', 'tune-agents.md', 'playbook.md', 'token-report.md', 'visual-test.md', 'forge-new.md',
161
+ 'forge-list.md', 'forge-show.md', 'forge-doctor.md', 'forge-policy.md', 'forge-budget.md', 'forge-audit.md',
162
+ 'forge-eval.md', 'forge-redteam.md', 'forge-route.md', 'forge-fallback-test.md',
163
+ 'forge-refresh-matrix.md', 'forge-killswitch.md', 'forge-deprecate.md', 'runs.md']) {
164
+ cmds.includes(c) ? ok(`command ${c.replace('.md', '')} present`) : bad(`missing command ${c}`);
165
+ }
166
+ const agents = await readdir(resolve(KIT, 'templates/claude/agents')).catch(() => []);
167
+ agents.length >= 20 ? ok(`${agents.length} agent archetypes present`) : bad(`only ${agents.length} agents`);
168
+ for (const a of ['qa-orchestrator.md', 'qa-unit.md', 'qa-integration.md', 'qa-fuzzer.md', 'qa-perf.md', 'qa-e2e.md', 'privacy-lgpd.md', 'ux-designer.md', 'ui-designer.md', 'accessibility.md', 'product-owner.md', 'devops.md', 'infra-security.md', 'code-security.md',
169
+ 'forge-orchestrator.md', 'agent-architect.md', 'model-router.md', 'prompt-engineer.md', 'tool-designer.md', 'packager.md',
170
+ 'eval-designer.md', 'governance-officer.md', 'rag-designer.md']) {
171
+ agents.includes(a) ? ok(`agent ${a.replace('.md', '')} present`) : bad(`missing agent ${a}`);
172
+ }
173
+ existsSync(resolve(KIT, '.github/workflows/release.yml')) ? ok('release workflow present') : bad('missing release workflow');
174
+ const scripts = await readdir(resolve(KIT, 'templates/contextkit/tools/scripts')).catch(() => []);
175
+ for (const s of ['detect-stack.mjs', 'setup-complete.mjs', 'context-config.mjs', 'doctor.mjs', 'mark-simulation.mjs', 'predictions-review.mjs', 'tech-debt-scan.mjs', 'tech-debt-detectors.mjs', 'stats.mjs', 'contract-scan.mjs', 'pipeline.mjs', 'roadmap.mjs', 'claude-md.mjs', 'git.mjs', 'deps-audit.mjs', 'gh-alerts.mjs', 'pipeline-prioritize.mjs', 'pipeline-board.mjs', 'deep-analysis.mjs', 'squad.mjs', 'squad-meta.mjs', 'fleet.mjs', 'agent-tuning.mjs', 'playbook.mjs', 'token-report.mjs', 'visual-test.mjs', 'squad-pipeline.mjs', 'squad-pipeline-condition.mjs', 'pipeline-session.mjs', 'runs.mjs', 'pipeline-validate.mjs', 'resume.mjs', 'distill-detect.mjs', 'workflow.mjs']) {
176
+ scripts.includes(s) ? ok(`script ${s} present`) : bad(`missing script ${s}`);
177
+ }
178
+ const ghTpl = await readdir(resolve(KIT, 'templates/github')).catch(() => []);
179
+ ghTpl.includes('PULL_REQUEST_TEMPLATE.md') ? ok('GitHub PR template present') : bad('missing PR template');
180
+ ghTpl.includes('dependabot.yml') ? ok('Dependabot config template present') : bad('missing dependabot.yml');
181
+ existsSync(resolve(KIT, 'templates/github/workflows/security.yml')) ? ok('security workflow template present') : bad('missing security workflow template');
182
+ existsSync(resolve(KIT, 'templates/github/workflows/quality.yml')) ? ok('quality workflow template present') : bad('missing quality workflow template');
183
+ for (const f of [
184
+ 'templates/CLAUDE.md.tpl', 'templates/docs/CHANGELOG.md.tpl', 'templates/contextkit/config.json',
185
+ 'templates/contextkit/instrucoes.md', 'templates/gitattributes', 'install.mjs',
186
+ '.github/workflows/ci.yml', 'CHANGELOG.md', 'instrucoes.md', 'docs/ROADMAP.md',
187
+ 'templates/contextkit/runtime/hooks/concurrency-guard.mjs', 'templates/contextkit/runtime/git-hooks/pre-push.mjs',
188
+ 'templates/contextkit/runtime/hooks/safe-io.mjs', 'templates/contextkit/runtime/config/levels.mjs',
189
+ 'templates/contextkit/runtime/statusline.mjs', 'templates/contextkit/runtime/config/presets.mjs',
190
+ 'templates/contextkit/best-practices.md', 'templates/contextkit/pipeline/devpipeline.md',
191
+ 'templates/contextkit/pipeline/working/.gitkeep',
192
+ 'templates/contextkit/runtime/state/state-io.mjs',
193
+ 'templates/contextkit/detectors/README.md', 'templates/contextkit/detectors/example-detector.mjs.example',
194
+ 'templates/contextkit/memory/roadmap.md', 'templates/contextkit/CLAUDE.child.md.tpl',
195
+ 'templates/contextkit/squads/README.md', 'templates/contextkit/squads/_BRIEFING.md.tpl',
196
+ 'templates/contextkit/squads/agent-forge/README.md', 'templates/contextkit/squads/agent-forge/best-practices.md',
197
+ 'templates/contextkit/squads/agent-forge/ROADMAP.md',
198
+ 'templates/contextkit/squads/agent-forge/lib/yaml.mjs',
199
+ 'templates/contextkit/squads/agent-forge/lib/router.mjs',
200
+ 'templates/contextkit/squads/agent-forge/lib/architect.mjs',
201
+ 'templates/contextkit/squads/agent-forge/lib/prompt-gen.mjs',
202
+ 'templates/contextkit/squads/agent-forge/lib/tool-gen.mjs',
203
+ 'templates/contextkit/squads/agent-forge/lib/packager.mjs',
204
+ 'templates/contextkit/squads/agent-forge/router/capability-matrix.json',
205
+ 'templates/contextkit/squads/agent-forge/router/decision-rules.json',
206
+ 'templates/contextkit/squads/agent-forge/cli/forge-new.mjs',
207
+ 'templates/contextkit/squads/agent-forge/cli/forge-ops.mjs',
208
+ 'templates/contextkit/squads/agent-forge/cli/forge-eval-cli.mjs',
209
+ 'templates/contextkit/squads/agent-forge/cli/forge-admin.mjs',
210
+ 'templates/contextkit/squads/agent-forge/lib/package-ops.mjs',
211
+ 'templates/contextkit/squads/agent-forge/lib/eval-designer.mjs',
212
+ 'templates/contextkit/squads/agent-forge/lib/eval-runner.mjs',
213
+ 'templates/contextkit/squads/agent-forge/lib/governance-officer.mjs',
214
+ 'templates/contextkit/squads/agent-forge/lib/rag-designer.mjs',
215
+ 'templates/contextkit/squads/agent-forge/pipeline.yaml',
216
+ 'tools/selfcheck-agent-forge-ops.mjs',
217
+ 'templates/claude/commands/forge/forge-new.md',
218
+ 'templates/claude/commands/README.md',
219
+ 'docs/SQUADS/agent-forge.md', 'docs/AGENT-PACKAGE-FORMAT.md',
220
+ 'docs/SQUAD-PIPELINE-FORMAT.md',
221
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/manifest.yaml',
222
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/README.md',
223
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/.agentforgerc',
224
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/prompts/system.canonical.md',
225
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/tools/schemas.canonical.json',
226
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/evals/golden.jsonl',
227
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/evals/thresholds.yaml',
228
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/governance/cost.policy.yaml',
229
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/governance/compliance.policy.yaml',
230
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/governance/quality.policy.yaml',
231
+ 'templates/contextkit/squads/agent-forge/templates/agent-package/governance/audit.schema.json',
232
+ 'templates/contextkit/memory/business-rules/_TEMPLATE.md',
233
+ 'templates/contextkit/memory/predictions/.gitkeep',
234
+ 'templates/contextkit/memory/workflows/.gitkeep',
235
+ ]) {
236
+ existsSync(resolve(KIT, f)) ? ok(f) : bad(`missing ${f}`);
237
+ }
238
+ const wf = await readdir(resolve(KIT, 'templates/contextkit/workflows')).catch(() => []);
239
+ for (const f of ['README.md', 'L1-static-loading.md', 'L2-session-ledger.md', 'L3-multi-session.md', 'L4-squads.md', 'L5-proactive.md']) {
240
+ wf.includes(f) ? ok(`workflow ${f} present`) : bad(`missing workflow ${f}`);
241
+ }
242
+ const playbooks = await readdir(resolve(KIT, 'templates/contextkit/workflows/playbooks')).catch(() => []);
243
+ for (const f of ['tech-debt-sweep.md', 'simulate-impact.md', 'distillation-cycle.md', 'security-batch.md']) {
244
+ playbooks.includes(f) ? ok(`playbook ${f} present`) : bad(`missing playbook ${f}`);
245
+ }
246
+ }
247
+
248
+ async function main() {
249
+ console.log('\nšŸŒ€ ContextDevKit self-check\n');
250
+ const mods = await importLibs();
251
+ if (mods['config/settings-compose.mjs']?.composeSettings) checkCompose(mods['config/settings-compose.mjs'].composeSettings);
252
+ if (mods['config/load.mjs']?.loadConfigSync) checkConfig(mods['config/load.mjs']);
253
+ checkPaths(mods['config/paths.mjs']);
254
+ checkPresets(mods['config/presets.mjs']);
255
+ await runRuntimeChecks({ ok, bad }, { KIT, mods });
256
+ await runConfigChecks({ ok, bad }, { RT, mods });
257
+ await runSourceChecks({ ok, bad }, { KIT });
258
+ await runAgentForgeChecks({ ok, bad }, KIT);
259
+ await runAgentForgeOpsChecks({ ok, bad }, KIT);
260
+ await checkTemplates();
261
+ console.log(failures === 0 ? '\nāœ… All checks passed.\n' : `\nāŒ ${failures} check(s) failed.\n`);
262
+ process.exit(failures === 0 ? 0 : 1);
263
+ }
264
+
265
+ main().catch((err) => {
266
+ console.error('self-check crashed:', err);
267
+ process.exit(1);
268
+ });