@luanpdd/kit-mcp 1.26.0 → 1.28.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 (326) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +168 -914
  3. package/gates/agent-no-recursive-dispatch.md +45 -11
  4. package/kit/COMANDOS.md +138 -138
  5. package/kit/README.md +76 -76
  6. package/kit/agents/advisor-researcher.md +106 -106
  7. package/kit/agents/assumptions-analyzer.md +107 -107
  8. package/kit/agents/audit-log-implementer.md +1 -1
  9. package/kit/agents/auditor-consistencia-isolamento.md +1 -1
  10. package/kit/agents/b2b-saas-architect.md +1 -1
  11. package/kit/agents/cascading-failures-auditor.md +1 -1
  12. package/kit/agents/codebase-mapper.md +768 -768
  13. package/kit/agents/crm-pipeline-implementer.md +1 -1
  14. package/kit/agents/debugger.md +813 -813
  15. package/kit/agents/detector-tenant-quente.md +1 -1
  16. package/kit/agents/evolution-go-integrator.md +1 -1
  17. package/kit/agents/example-reviewer.md +21 -21
  18. package/kit/agents/executor.md +564 -564
  19. package/kit/agents/integration-checker.md +200 -200
  20. package/kit/agents/invite-flow-implementer.md +1 -1
  21. package/kit/agents/legacy-characterizer.md +1 -1
  22. package/kit/agents/lgpd-compliance-auditor.md +1 -1
  23. package/kit/agents/multi-tenant-isolation-auditor.md +1 -1
  24. package/kit/agents/multi-tenant-rls-writer.md +1 -1
  25. package/kit/agents/nyquist-auditor.md +178 -178
  26. package/kit/agents/observability-coverage-auditor.md +1 -1
  27. package/kit/agents/org-onboarding-implementer.md +1 -1
  28. package/kit/agents/payload-capture-instrumenter.md +1 -1
  29. package/kit/agents/phase-researcher.md +696 -696
  30. package/kit/agents/plan-checker.md +272 -272
  31. package/kit/agents/planner.md +922 -922
  32. package/kit/agents/project-researcher.md +652 -652
  33. package/kit/agents/refactor-safety-auditor.md +1 -1
  34. package/kit/agents/release-pipeline-auditor.md +11 -0
  35. package/kit/agents/research-synthesizer.md +245 -245
  36. package/kit/agents/roadmapper.md +677 -677
  37. package/kit/agents/seam-finder.md +1 -1
  38. package/kit/agents/shotgun-surgery-detector.md +1 -1
  39. package/kit/agents/supabase-architect.md +14 -0
  40. package/kit/agents/supabase-branching-architect.md +562 -0
  41. package/kit/agents/supabase-cicd-pipeline-implementer.md +777 -0
  42. package/kit/agents/supabase-column-privileges-writer.md +1 -1
  43. package/kit/agents/supabase-migration-writer.md +13 -1
  44. package/kit/agents/supabase-rbac-implementer.md +1 -1
  45. package/kit/agents/supabase-rls-hardener.md +1 -1
  46. package/kit/agents/supabase-rls-writer.md +1 -1
  47. package/kit/agents/supabase-roles-implementer.md +1 -1
  48. package/kit/agents/super-admin-implementer.md +1 -1
  49. package/kit/agents/ui-auditor.md +437 -437
  50. package/kit/agents/ui-checker.md +302 -302
  51. package/kit/agents/ui-researcher.md +355 -355
  52. package/kit/agents/user-profiler.md +175 -175
  53. package/kit/agents/validador-evolucao-schema.md +1 -1
  54. package/kit/agents/verifier.md +728 -728
  55. package/kit/commands/adicionar-backlog.md +75 -75
  56. package/kit/commands/adicionar-fase.md +42 -42
  57. package/kit/commands/adicionar-tarefa.md +45 -45
  58. package/kit/commands/adicionar-testes.md +41 -41
  59. package/kit/commands/ajuda.md +21 -21
  60. package/kit/commands/atualizar.md +37 -37
  61. package/kit/commands/auditar-cascading.md +1 -1
  62. package/kit/commands/auditar-marco.md +179 -179
  63. package/kit/commands/auditar-observabilidade-cobertura.md +1 -1
  64. package/kit/commands/auditar-refactor.md +1 -1
  65. package/kit/commands/auditar-release.md +1 -1
  66. package/kit/commands/auditar-uat.md +23 -23
  67. package/kit/commands/autonomo.md +40 -40
  68. package/kit/commands/branch-pr.md +24 -24
  69. package/kit/commands/burn-rate-status.md +1 -1
  70. package/kit/commands/capturar-payloads.md +1 -1
  71. package/kit/commands/caracterizar.md +1 -1
  72. package/kit/commands/concluir-marco.md +247 -247
  73. package/kit/commands/configuracoes.md +36 -36
  74. package/kit/commands/dados-distribuidos.md +1 -1
  75. package/kit/commands/definir-perfil.md +10 -10
  76. package/kit/commands/depurar.md +190 -190
  77. package/kit/commands/detectar-duplicacao.md +1 -1
  78. package/kit/commands/discutir-fase.md +131 -131
  79. package/kit/commands/encontrar-seams.md +1 -1
  80. package/kit/commands/entrar-discord.md +17 -17
  81. package/kit/commands/estatisticas.md +18 -18
  82. package/kit/commands/example-greeting.md +33 -33
  83. package/kit/commands/executar-fase.md +58 -58
  84. package/kit/commands/expresso.md +56 -56
  85. package/kit/commands/fase-ui.md +34 -34
  86. package/kit/commands/fazer.md +57 -57
  87. package/kit/commands/fio.md +125 -125
  88. package/kit/commands/fluxos-trabalho.md +64 -64
  89. package/kit/commands/forense.md +176 -176
  90. package/kit/commands/gerenciador.md +38 -38
  91. package/kit/commands/inserir-fase.md +31 -31
  92. package/kit/commands/legacy.md +1 -1
  93. package/kit/commands/limpeza.md +17 -17
  94. package/kit/commands/listar-hipoteses-fase.md +45 -45
  95. package/kit/commands/listar-workspaces.md +18 -18
  96. package/kit/commands/load-shedding.md +1 -1
  97. package/kit/commands/mapear-codebase.md +70 -70
  98. package/kit/commands/multi-tenant.md +1 -1
  99. package/kit/commands/nota.md +33 -33
  100. package/kit/commands/novo-marco.md +43 -43
  101. package/kit/commands/novo-projeto.md +41 -41
  102. package/kit/commands/novo-workspace.md +43 -43
  103. package/kit/commands/pausar-trabalho.md +37 -37
  104. package/kit/commands/perfil-usuario.md +45 -45
  105. package/kit/commands/pesquisar-fase.md +195 -195
  106. package/kit/commands/planejar-fase.md +67 -67
  107. package/kit/commands/planejar-lacunas.md +33 -33
  108. package/kit/commands/plantar-ideia.md +25 -25
  109. package/kit/commands/progresso.md +24 -24
  110. package/kit/commands/proximo.md +30 -30
  111. package/kit/commands/publicar.md +490 -490
  112. package/kit/commands/rapido.md +35 -35
  113. package/kit/commands/reaplicar-patches.md +124 -124
  114. package/kit/commands/refactor-seguro.md +1 -1
  115. package/kit/commands/relatorio-sessao.md +19 -19
  116. package/kit/commands/remover-fase.md +31 -31
  117. package/kit/commands/remover-workspace.md +26 -26
  118. package/kit/commands/resumo-marco.md +50 -50
  119. package/kit/commands/retomar-trabalho.md +40 -40
  120. package/kit/commands/revisar-backlog.md +60 -60
  121. package/kit/commands/revisar-ui.md +32 -32
  122. package/kit/commands/revisar.md +37 -37
  123. package/kit/commands/saude.md +21 -21
  124. package/kit/commands/setup-notion.md +93 -93
  125. package/kit/commands/storytelling.md +1 -1
  126. package/kit/commands/supabase.md +1 -1
  127. package/kit/commands/sync-main.md +68 -68
  128. package/kit/commands/validar-fase.md +35 -35
  129. package/kit/commands/verificar-tarefas.md +44 -44
  130. package/kit/commands/verificar-trabalho.md +64 -64
  131. package/kit/file-manifest.json +93 -86
  132. package/kit/framework/bin/lib/commands.cjs +959 -959
  133. package/kit/framework/bin/lib/config.cjs +442 -442
  134. package/kit/framework/bin/lib/core.cjs +1230 -1230
  135. package/kit/framework/bin/lib/frontmatter.cjs +336 -336
  136. package/kit/framework/bin/lib/init.cjs +1442 -1442
  137. package/kit/framework/bin/lib/milestone.cjs +252 -252
  138. package/kit/framework/bin/lib/model-profiles.cjs +68 -68
  139. package/kit/framework/bin/lib/phase.cjs +888 -888
  140. package/kit/framework/bin/lib/profile-output.cjs +952 -952
  141. package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
  142. package/kit/framework/bin/lib/roadmap.cjs +329 -329
  143. package/kit/framework/bin/lib/security.cjs +382 -382
  144. package/kit/framework/bin/lib/state.cjs +1031 -1031
  145. package/kit/framework/bin/lib/template.cjs +222 -222
  146. package/kit/framework/bin/lib/uat.cjs +282 -282
  147. package/kit/framework/bin/lib/verify.cjs +888 -888
  148. package/kit/framework/bin/lib/workstream.cjs +491 -491
  149. package/kit/framework/bin/tools.cjs +918 -918
  150. package/kit/framework/commands/workstreams.md +63 -63
  151. package/kit/framework/references/checkpoints.md +778 -778
  152. package/kit/framework/references/continuation-format.md +249 -249
  153. package/kit/framework/references/decimal-phase-calculation.md +64 -64
  154. package/kit/framework/references/git-integration.md +295 -295
  155. package/kit/framework/references/git-planning-commit.md +38 -38
  156. package/kit/framework/references/model-profile-resolution.md +36 -36
  157. package/kit/framework/references/model-profiles.md +139 -139
  158. package/kit/framework/references/phase-argument-parsing.md +61 -61
  159. package/kit/framework/references/planning-config.md +202 -202
  160. package/kit/framework/references/questioning.md +162 -162
  161. package/kit/framework/references/tdd.md +263 -263
  162. package/kit/framework/references/ui-brand.md +160 -160
  163. package/kit/framework/references/user-profiling.md +657 -657
  164. package/kit/framework/references/verification-patterns.md +612 -612
  165. package/kit/framework/references/workstream-flag.md +58 -58
  166. package/kit/framework/templates/DEBUG.md +164 -164
  167. package/kit/framework/templates/UAT.md +265 -265
  168. package/kit/framework/templates/UI-SPEC.md +100 -100
  169. package/kit/framework/templates/VALIDATION.md +76 -76
  170. package/kit/framework/templates/claude-md.md +122 -122
  171. package/kit/framework/templates/codebase/architecture.md +185 -185
  172. package/kit/framework/templates/codebase/concerns.md +205 -205
  173. package/kit/framework/templates/codebase/conventions.md +204 -204
  174. package/kit/framework/templates/codebase/integrations.md +192 -192
  175. package/kit/framework/templates/codebase/stack.md +158 -158
  176. package/kit/framework/templates/codebase/structure.md +199 -199
  177. package/kit/framework/templates/codebase/testing.md +301 -301
  178. package/kit/framework/templates/config.json +44 -44
  179. package/kit/framework/templates/context.md +352 -352
  180. package/kit/framework/templates/continue-here.md +78 -78
  181. package/kit/framework/templates/copilot-instructions.md +7 -7
  182. package/kit/framework/templates/debug-subagent-prompt.md +91 -91
  183. package/kit/framework/templates/dev-preferences.md +20 -20
  184. package/kit/framework/templates/discovery.md +146 -146
  185. package/kit/framework/templates/discussion-log.md +63 -63
  186. package/kit/framework/templates/milestone-archive.md +123 -123
  187. package/kit/framework/templates/milestone.md +115 -115
  188. package/kit/framework/templates/phase-prompt.md +610 -610
  189. package/kit/framework/templates/planner-subagent-prompt.md +117 -117
  190. package/kit/framework/templates/project.md +186 -186
  191. package/kit/framework/templates/requirements.md +231 -231
  192. package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
  193. package/kit/framework/templates/research-project/FEATURES.md +147 -147
  194. package/kit/framework/templates/research-project/PITFALLS.md +200 -200
  195. package/kit/framework/templates/research-project/STACK.md +120 -120
  196. package/kit/framework/templates/research-project/SUMMARY.md +170 -170
  197. package/kit/framework/templates/research.md +419 -419
  198. package/kit/framework/templates/retrospective.md +54 -54
  199. package/kit/framework/templates/roadmap.md +202 -202
  200. package/kit/framework/templates/state.md +176 -176
  201. package/kit/framework/templates/summary-complex.md +59 -59
  202. package/kit/framework/templates/summary-minimal.md +41 -41
  203. package/kit/framework/templates/summary-standard.md +48 -48
  204. package/kit/framework/templates/summary.md +209 -209
  205. package/kit/framework/templates/user-profile.md +146 -146
  206. package/kit/framework/templates/user-setup.md +256 -256
  207. package/kit/framework/templates/verification-report.md +258 -258
  208. package/kit/framework/workflows/add-phase.md +112 -112
  209. package/kit/framework/workflows/add-tests.md +351 -351
  210. package/kit/framework/workflows/add-todo.md +158 -158
  211. package/kit/framework/workflows/audit-milestone.md +340 -340
  212. package/kit/framework/workflows/audit-uat.md +109 -109
  213. package/kit/framework/workflows/autonomous.md +891 -891
  214. package/kit/framework/workflows/check-todos.md +177 -177
  215. package/kit/framework/workflows/cleanup.md +152 -152
  216. package/kit/framework/workflows/complete-milestone.md +696 -696
  217. package/kit/framework/workflows/diagnose-issues.md +231 -231
  218. package/kit/framework/workflows/discovery-phase.md +289 -289
  219. package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
  220. package/kit/framework/workflows/discuss-phase.md +784 -784
  221. package/kit/framework/workflows/do.md +104 -104
  222. package/kit/framework/workflows/execute-phase.md +838 -838
  223. package/kit/framework/workflows/execute-plan.md +510 -510
  224. package/kit/framework/workflows/fast.md +102 -102
  225. package/kit/framework/workflows/forensics.md +265 -265
  226. package/kit/framework/workflows/health.md +181 -181
  227. package/kit/framework/workflows/help.md +619 -619
  228. package/kit/framework/workflows/insert-phase.md +130 -130
  229. package/kit/framework/workflows/list-phase-assumptions.md +178 -178
  230. package/kit/framework/workflows/list-workspaces.md +56 -56
  231. package/kit/framework/workflows/manager.md +362 -362
  232. package/kit/framework/workflows/map-codebase.md +377 -377
  233. package/kit/framework/workflows/milestone-summary.md +223 -223
  234. package/kit/framework/workflows/new-milestone.md +486 -486
  235. package/kit/framework/workflows/new-project.md +1159 -1159
  236. package/kit/framework/workflows/new-workspace.md +237 -237
  237. package/kit/framework/workflows/next.md +97 -97
  238. package/kit/framework/workflows/node-repair.md +92 -92
  239. package/kit/framework/workflows/note.md +156 -156
  240. package/kit/framework/workflows/pause-work.md +176 -176
  241. package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
  242. package/kit/framework/workflows/plan-phase.md +765 -765
  243. package/kit/framework/workflows/plant-seed.md +169 -169
  244. package/kit/framework/workflows/pr-branch.md +129 -129
  245. package/kit/framework/workflows/profile-user.md +450 -450
  246. package/kit/framework/workflows/progress.md +507 -507
  247. package/kit/framework/workflows/quick.md +757 -757
  248. package/kit/framework/workflows/remove-phase.md +155 -155
  249. package/kit/framework/workflows/remove-workspace.md +90 -90
  250. package/kit/framework/workflows/research-phase.md +82 -82
  251. package/kit/framework/workflows/resume-project.md +326 -326
  252. package/kit/framework/workflows/review.md +228 -228
  253. package/kit/framework/workflows/session-report.md +146 -146
  254. package/kit/framework/workflows/settings.md +283 -283
  255. package/kit/framework/workflows/ship.md +228 -228
  256. package/kit/framework/workflows/stats.md +60 -60
  257. package/kit/framework/workflows/transition.md +671 -671
  258. package/kit/framework/workflows/ui-phase.md +302 -302
  259. package/kit/framework/workflows/ui-review.md +165 -165
  260. package/kit/framework/workflows/update.md +323 -323
  261. package/kit/framework/workflows/validate-phase.md +174 -174
  262. package/kit/framework/workflows/verify-phase.md +252 -252
  263. package/kit/framework/workflows/verify-work.md +637 -637
  264. package/kit/hooks/check-update.js +118 -118
  265. package/kit/hooks/context-monitor.js +163 -163
  266. package/kit/hooks/prompt-guard.js +103 -103
  267. package/kit/hooks/statusline.js +125 -125
  268. package/kit/hooks/workflow-guard.js +101 -101
  269. package/kit/settings.json +45 -45
  270. package/kit/skills/_shared-supabase/glossary.md +10 -0
  271. package/kit/skills/ai-prompt-characterization/SKILL.md +1 -1
  272. package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +1 -1
  273. package/kit/skills/audit-log-multi-tenant/SKILL.md +1 -1
  274. package/kit/skills/b2b-saas-architecture/SKILL.md +1 -1
  275. package/kit/skills/consistencia-leitura-replica/SKILL.md +1 -1
  276. package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +1 -1
  277. package/kit/skills/escolha-modelo-consistencia/SKILL.md +1 -1
  278. package/kit/skills/evolucao-schema-compativel/SKILL.md +1 -1
  279. package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +1 -1
  280. package/kit/skills/example-skill/SKILL.md +42 -42
  281. package/kit/skills/legacy-api-only-applications/SKILL.md +1 -1
  282. package/kit/skills/legacy-characterization-tests/SKILL.md +1 -1
  283. package/kit/skills/legacy-effect-analysis/SKILL.md +1 -1
  284. package/kit/skills/legacy-extract-class/SKILL.md +1 -1
  285. package/kit/skills/legacy-programming-by-difference/SKILL.md +1 -1
  286. package/kit/skills/legacy-seams-and-test-harness/SKILL.md +1 -1
  287. package/kit/skills/legacy-shotgun-surgery/SKILL.md +1 -1
  288. package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +1 -1
  289. package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +1 -1
  290. package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +1 -1
  291. package/kit/skills/member-invite-flow/SKILL.md +1 -1
  292. package/kit/skills/member-management-react-shadcn/SKILL.md +1 -1
  293. package/kit/skills/multi-tenant-performance-scaling/SKILL.md +1 -1
  294. package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +1 -1
  295. package/kit/skills/org-onboarding-flow/SKILL.md +1 -1
  296. package/kit/skills/org-switcher-react-pattern/SKILL.md +1 -1
  297. package/kit/skills/permission-gate-react-pattern/SKILL.md +1 -1
  298. package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +1 -1
  299. package/kit/skills/pre-refactor-characterization/SKILL.md +1 -1
  300. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +1 -1
  301. package/kit/skills/streams-eventos-cdc/SKILL.md +1 -1
  302. package/kit/skills/supabase-branching-workflow/SKILL.md +544 -0
  303. package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -0
  304. package/kit/skills/supabase-column-level-security/SKILL.md +1 -1
  305. package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -0
  306. package/kit/skills/supabase-custom-claims-rbac/SKILL.md +1 -1
  307. package/kit/skills/supabase-migration-repair/SKILL.md +823 -0
  308. package/kit/skills/supabase-migrations/SKILL.md +1 -1
  309. package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -0
  310. package/kit/skills/supabase-postgres-roles/SKILL.md +1 -1
  311. package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +1 -1
  312. package/kit/skills/supabase-rls-policies/SKILL.md +1 -1
  313. package/kit/skills/super-admin-platform-pattern/SKILL.md +1 -1
  314. package/kit/skills/tenant-quente-mitigacao/SKILL.md +1 -1
  315. package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +1 -1
  316. package/package.json +63 -63
  317. package/src/cli/index.js +345 -6
  318. package/src/cli/render.js +7 -0
  319. package/src/core/kit.js +216 -216
  320. package/src/core/logger.js +170 -0
  321. package/src/core/notify.js +60 -0
  322. package/src/core/reflect.js +247 -247
  323. package/src/core/reverse-sync.js +372 -372
  324. package/src/core/sync.js +418 -418
  325. package/src/core/watch.js +121 -121
  326. package/src/mcp-server/index.js +65 -2
@@ -1,247 +1,247 @@
1
- // reflect — feed an agent's recent failures back to an LLM and ask for
2
- // minimal prompt edits. Closes the learning loop opened by `forensics`.
3
- //
4
- // Inputs:
5
- // - kit/agents/{agent}.md (current agent prompt)
6
- // - .planning/learnings/{agent}.md (failure samples written by `forensics write-learnings`)
7
- //
8
- // Output:
9
- // - .planning/learnings/{agent}.proposal.md (proposed new full content)
10
- // - kit/agents/{agent}.md is overwritten only when `apply: true` (or user confirms in interactive mode)
11
- //
12
- // LLM:
13
- // - Uses Anthropic API via fetch (no new dependency)
14
- // - Requires ANTHROPIC_API_KEY env var to actually call the API
15
- // - With --dry-run, prints the assembled prompt and exits without calling
16
-
17
- import path from 'node:path';
18
- import fs from 'node:fs/promises';
19
- import { createInterface } from 'node:readline/promises';
20
- import { stdin as input, stdout as output, stderr } from 'node:process';
21
- import { resolveKitRoot } from './kit.js';
22
- import { redactSecrets } from './error-redaction.js';
23
-
24
- const DEFAULT_MODEL = process.env.KIT_REFLECT_MODEL ?? 'claude-sonnet-4-5-20250929';
25
- const DEFAULT_MAX_TOKENS = parseInt(process.env.KIT_REFLECT_MAX_TOKENS ?? '8000', 10);
26
-
27
- export async function reflect(opts = {}) {
28
- const agent = opts.agent;
29
- if (!agent) return { error: 'reflect: agent required' };
30
-
31
- const projectRoot = path.resolve(opts.projectRoot ?? process.cwd());
32
- const kitRoot = resolveKitRoot(opts.kitRoot);
33
- const dryRun = !!opts.dryRun;
34
- const apply = !!opts.apply;
35
- const interactive = opts.interactive !== false && !apply;
36
- const onLog = opts.onLog ?? ((s) => stderr.write(s + '\n'));
37
-
38
- const learningsPath = path.join(projectRoot, '.planning', 'learnings', `${agent}.md`);
39
- const agentPath = path.join(kitRoot, 'agents', `${agent}.md`);
40
-
41
- let learnings;
42
- try { learnings = await fs.readFile(learningsPath, 'utf8'); }
43
- catch {
44
- return { error: `No learnings found at ${learningsPath}. Run \`kit forensics write-learnings --project-root ${projectRoot}\` first.` };
45
- }
46
-
47
- let currentAgent;
48
- try { currentAgent = await fs.readFile(agentPath, 'utf8'); }
49
- catch { return { error: `Agent not found at ${agentPath}` }; }
50
-
51
- const prompt = buildReflectPrompt(agent, currentAgent, learnings);
52
-
53
- if (dryRun) {
54
- const promptPath = await savePrompt(prompt, projectRoot, agent);
55
- onLog(`prompt saved → ${promptPath} (dry-run, no API call)`);
56
- return {
57
- agent, dryRun: true, promptPath,
58
- promptBytes: prompt.length,
59
- model: DEFAULT_MODEL,
60
- learningsPath, agentPath,
61
- };
62
- }
63
-
64
- if (!process.env.ANTHROPIC_API_KEY) {
65
- const promptPath = await savePrompt(prompt, projectRoot, agent);
66
- return {
67
- error: 'ANTHROPIC_API_KEY not set. Either set it, or run with --dry-run to inspect the prompt.',
68
- promptPath,
69
- };
70
- }
71
-
72
- onLog(`calling Anthropic (${DEFAULT_MODEL})...`);
73
- const { text, usage } = await callClaude(prompt);
74
-
75
- const proposed = extractProposal(text);
76
- if (!proposed) {
77
- const rawPath = await saveRaw(text, projectRoot, agent);
78
- return { error: 'LLM response did not contain a parseable proposal. See raw output.', rawPath, usage };
79
- }
80
-
81
- const proposalPath = path.join(projectRoot, '.planning', 'learnings', `${agent}.proposal.md`);
82
- await fs.mkdir(path.dirname(proposalPath), { recursive: true });
83
- await fs.writeFile(proposalPath, proposed, 'utf8');
84
- onLog(`proposal saved → ${proposalPath}`);
85
-
86
- const summary = summarizeChange(currentAgent, proposed);
87
- onLog(`change: ${summary}`);
88
-
89
- // Apply decision
90
- let applied = false;
91
- if (apply) {
92
- await fs.writeFile(agentPath, proposed, 'utf8');
93
- applied = true;
94
- onLog(`✓ applied → ${agentPath}`);
95
- } else if (interactive) {
96
- const ok = await ask('apply this proposal to the agent? [y/N] ');
97
- if (ok) {
98
- await fs.writeFile(agentPath, proposed, 'utf8');
99
- applied = true;
100
- onLog(`✓ applied → ${agentPath}`);
101
- } else {
102
- onLog('not applied. Review the proposal and re-run with --apply when ready.');
103
- }
104
- } else {
105
- onLog('not applied (non-interactive without --apply).');
106
- }
107
-
108
- return { agent, proposalPath, summary, applied, model: DEFAULT_MODEL, usage };
109
- }
110
-
111
- // --- prompt building ---
112
-
113
- function buildReflectPrompt(agent, currentAgent, learnings) {
114
- return `You are reviewing the system prompt of an agent named "${agent}".
115
-
116
- ## Current agent prompt
117
-
118
- \`\`\`markdown
119
- ${currentAgent}
120
- \`\`\`
121
-
122
- ## Recent failures attributed to this agent
123
-
124
- ${learnings}
125
-
126
- ---
127
-
128
- ## Your task
129
-
130
- Propose **minimal, surgical edits** to the agent prompt that would reduce these failure patterns.
131
-
132
- Constraints:
133
- - Preserve YAML frontmatter (name, description, tools, color, hooks) exactly.
134
- - Do not rewrite the agent — just adjust phrasing, add a clarifying note, or insert specific guidance for the recurring failure modes you see.
135
- - Be conservative: a smaller diff is better. If the failures don't suggest a clear prompt-level fix, say so honestly and propose no change.
136
- - Output format below is mandatory — anything else will fail to parse.
137
-
138
- ## Output format
139
-
140
- ### Analysis
141
- 3-5 sentences on what patterns you see and why a prompt edit could help (or not).
142
-
143
- ### Proposed agent
144
-
145
- \`\`\`markdown
146
- {full new content of the agent .md file, including frontmatter}
147
- \`\`\`
148
-
149
- ### Summary of changes
150
- - {bullet 1}
151
- - {bullet 2}
152
- `;
153
- }
154
-
155
- // --- LLM call ---
156
-
157
- async function callClaude(prompt) {
158
- const res = await fetch('https://api.anthropic.com/v1/messages', {
159
- method: 'POST',
160
- headers: {
161
- 'content-type': 'application/json',
162
- 'x-api-key': process.env.ANTHROPIC_API_KEY,
163
- 'anthropic-version': '2023-06-01',
164
- },
165
- body: JSON.stringify({
166
- model: DEFAULT_MODEL,
167
- max_tokens: DEFAULT_MAX_TOKENS,
168
- messages: [{ role: 'user', content: prompt }],
169
- }),
170
- });
171
- if (!res.ok) {
172
- const errBody = await res.text();
173
- // SEC-14-06: Anthropic error responses can echo the supplied API key
174
- // (rare but observed in 401s). Strip secrets/paths before propagating
175
- // to caller — the central MCP catch will sanitize again, but doing it
176
- // here means CLI callers (which bypass the MCP catch) are also protected.
177
- throw new Error(`Anthropic API ${res.status}: ${redactSecrets(errBody)}`);
178
- }
179
- const j = await res.json();
180
- return {
181
- text: (j.content ?? []).map(c => c.text ?? '').join(''),
182
- usage: j.usage,
183
- };
184
- }
185
-
186
- // --- parsing ---
187
-
188
- function extractProposal(text) {
189
- // Find "Proposed agent" heading then the next ```markdown / ```md / ``` block.
190
- const lines = text.split(/\r?\n/);
191
- let headingIdx = -1;
192
- for (let i = 0; i < lines.length; i++) {
193
- if (/^#{1,4}\s+Proposed agent\s*$/i.test(lines[i])) { headingIdx = i; break; }
194
- }
195
- if (headingIdx === -1) return null;
196
-
197
- // Find opening fence after the heading
198
- let openIdx = -1;
199
- for (let i = headingIdx + 1; i < lines.length; i++) {
200
- if (/^```/.test(lines[i])) { openIdx = i; break; }
201
- }
202
- if (openIdx === -1) return null;
203
-
204
- // Find closing fence
205
- let closeIdx = -1;
206
- for (let i = openIdx + 1; i < lines.length; i++) {
207
- if (/^```\s*$/.test(lines[i])) { closeIdx = i; break; }
208
- }
209
- if (closeIdx === -1) return null;
210
-
211
- const block = lines.slice(openIdx + 1, closeIdx).join('\n').trim();
212
- return block ? block + '\n' : null;
213
- }
214
-
215
- function summarizeChange(before, after) {
216
- const bL = before.split(/\r?\n/).length;
217
- const aL = after.split(/\r?\n/).length;
218
- const dL = aL - bL;
219
- const dB = after.length - before.length;
220
- return `${aL} lines (${dL >= 0 ? '+' : ''}${dL}); ${before.length}→${after.length} bytes (${dB >= 0 ? '+' : ''}${dB})`;
221
- }
222
-
223
- // --- helpers ---
224
-
225
- async function savePrompt(prompt, projectRoot, agent) {
226
- const out = path.join(projectRoot, '.planning', 'learnings', `${agent}.reflect-prompt.md`);
227
- await fs.mkdir(path.dirname(out), { recursive: true });
228
- await fs.writeFile(out, prompt, 'utf8');
229
- return out;
230
- }
231
-
232
- async function saveRaw(text, projectRoot, agent) {
233
- const out = path.join(projectRoot, '.planning', 'learnings', `${agent}.reflect-raw.md`);
234
- await fs.mkdir(path.dirname(out), { recursive: true });
235
- await fs.writeFile(out, text, 'utf8');
236
- return out;
237
- }
238
-
239
- async function ask(q) {
240
- const rl = createInterface({ input, output });
241
- try {
242
- const a = (await rl.question(q)).trim().toLowerCase();
243
- return a === 'y' || a === 'yes';
244
- } finally {
245
- rl.close();
246
- }
247
- }
1
+ // reflect — feed an agent's recent failures back to an LLM and ask for
2
+ // minimal prompt edits. Closes the learning loop opened by `forensics`.
3
+ //
4
+ // Inputs:
5
+ // - kit/agents/{agent}.md (current agent prompt)
6
+ // - .planning/learnings/{agent}.md (failure samples written by `forensics write-learnings`)
7
+ //
8
+ // Output:
9
+ // - .planning/learnings/{agent}.proposal.md (proposed new full content)
10
+ // - kit/agents/{agent}.md is overwritten only when `apply: true` (or user confirms in interactive mode)
11
+ //
12
+ // LLM:
13
+ // - Uses Anthropic API via fetch (no new dependency)
14
+ // - Requires ANTHROPIC_API_KEY env var to actually call the API
15
+ // - With --dry-run, prints the assembled prompt and exits without calling
16
+
17
+ import path from 'node:path';
18
+ import fs from 'node:fs/promises';
19
+ import { createInterface } from 'node:readline/promises';
20
+ import { stdin as input, stdout as output, stderr } from 'node:process';
21
+ import { resolveKitRoot } from './kit.js';
22
+ import { redactSecrets } from './error-redaction.js';
23
+
24
+ const DEFAULT_MODEL = process.env.KIT_REFLECT_MODEL ?? 'claude-sonnet-4-5-20250929';
25
+ const DEFAULT_MAX_TOKENS = parseInt(process.env.KIT_REFLECT_MAX_TOKENS ?? '8000', 10);
26
+
27
+ export async function reflect(opts = {}) {
28
+ const agent = opts.agent;
29
+ if (!agent) return { error: 'reflect: agent required' };
30
+
31
+ const projectRoot = path.resolve(opts.projectRoot ?? process.cwd());
32
+ const kitRoot = resolveKitRoot(opts.kitRoot);
33
+ const dryRun = !!opts.dryRun;
34
+ const apply = !!opts.apply;
35
+ const interactive = opts.interactive !== false && !apply;
36
+ const onLog = opts.onLog ?? ((s) => stderr.write(s + '\n'));
37
+
38
+ const learningsPath = path.join(projectRoot, '.planning', 'learnings', `${agent}.md`);
39
+ const agentPath = path.join(kitRoot, 'agents', `${agent}.md`);
40
+
41
+ let learnings;
42
+ try { learnings = await fs.readFile(learningsPath, 'utf8'); }
43
+ catch {
44
+ return { error: `No learnings found at ${learningsPath}. Run \`kit forensics write-learnings --project-root ${projectRoot}\` first.` };
45
+ }
46
+
47
+ let currentAgent;
48
+ try { currentAgent = await fs.readFile(agentPath, 'utf8'); }
49
+ catch { return { error: `Agent not found at ${agentPath}` }; }
50
+
51
+ const prompt = buildReflectPrompt(agent, currentAgent, learnings);
52
+
53
+ if (dryRun) {
54
+ const promptPath = await savePrompt(prompt, projectRoot, agent);
55
+ onLog(`prompt saved → ${promptPath} (dry-run, no API call)`);
56
+ return {
57
+ agent, dryRun: true, promptPath,
58
+ promptBytes: prompt.length,
59
+ model: DEFAULT_MODEL,
60
+ learningsPath, agentPath,
61
+ };
62
+ }
63
+
64
+ if (!process.env.ANTHROPIC_API_KEY) {
65
+ const promptPath = await savePrompt(prompt, projectRoot, agent);
66
+ return {
67
+ error: 'ANTHROPIC_API_KEY not set. Either set it, or run with --dry-run to inspect the prompt.',
68
+ promptPath,
69
+ };
70
+ }
71
+
72
+ onLog(`calling Anthropic (${DEFAULT_MODEL})...`);
73
+ const { text, usage } = await callClaude(prompt);
74
+
75
+ const proposed = extractProposal(text);
76
+ if (!proposed) {
77
+ const rawPath = await saveRaw(text, projectRoot, agent);
78
+ return { error: 'LLM response did not contain a parseable proposal. See raw output.', rawPath, usage };
79
+ }
80
+
81
+ const proposalPath = path.join(projectRoot, '.planning', 'learnings', `${agent}.proposal.md`);
82
+ await fs.mkdir(path.dirname(proposalPath), { recursive: true });
83
+ await fs.writeFile(proposalPath, proposed, 'utf8');
84
+ onLog(`proposal saved → ${proposalPath}`);
85
+
86
+ const summary = summarizeChange(currentAgent, proposed);
87
+ onLog(`change: ${summary}`);
88
+
89
+ // Apply decision
90
+ let applied = false;
91
+ if (apply) {
92
+ await fs.writeFile(agentPath, proposed, 'utf8');
93
+ applied = true;
94
+ onLog(`✓ applied → ${agentPath}`);
95
+ } else if (interactive) {
96
+ const ok = await ask('apply this proposal to the agent? [y/N] ');
97
+ if (ok) {
98
+ await fs.writeFile(agentPath, proposed, 'utf8');
99
+ applied = true;
100
+ onLog(`✓ applied → ${agentPath}`);
101
+ } else {
102
+ onLog('not applied. Review the proposal and re-run with --apply when ready.');
103
+ }
104
+ } else {
105
+ onLog('not applied (non-interactive without --apply).');
106
+ }
107
+
108
+ return { agent, proposalPath, summary, applied, model: DEFAULT_MODEL, usage };
109
+ }
110
+
111
+ // --- prompt building ---
112
+
113
+ function buildReflectPrompt(agent, currentAgent, learnings) {
114
+ return `You are reviewing the system prompt of an agent named "${agent}".
115
+
116
+ ## Current agent prompt
117
+
118
+ \`\`\`markdown
119
+ ${currentAgent}
120
+ \`\`\`
121
+
122
+ ## Recent failures attributed to this agent
123
+
124
+ ${learnings}
125
+
126
+ ---
127
+
128
+ ## Your task
129
+
130
+ Propose **minimal, surgical edits** to the agent prompt that would reduce these failure patterns.
131
+
132
+ Constraints:
133
+ - Preserve YAML frontmatter (name, description, tools, color, hooks) exactly.
134
+ - Do not rewrite the agent — just adjust phrasing, add a clarifying note, or insert specific guidance for the recurring failure modes you see.
135
+ - Be conservative: a smaller diff is better. If the failures don't suggest a clear prompt-level fix, say so honestly and propose no change.
136
+ - Output format below is mandatory — anything else will fail to parse.
137
+
138
+ ## Output format
139
+
140
+ ### Analysis
141
+ 3-5 sentences on what patterns you see and why a prompt edit could help (or not).
142
+
143
+ ### Proposed agent
144
+
145
+ \`\`\`markdown
146
+ {full new content of the agent .md file, including frontmatter}
147
+ \`\`\`
148
+
149
+ ### Summary of changes
150
+ - {bullet 1}
151
+ - {bullet 2}
152
+ `;
153
+ }
154
+
155
+ // --- LLM call ---
156
+
157
+ async function callClaude(prompt) {
158
+ const res = await fetch('https://api.anthropic.com/v1/messages', {
159
+ method: 'POST',
160
+ headers: {
161
+ 'content-type': 'application/json',
162
+ 'x-api-key': process.env.ANTHROPIC_API_KEY,
163
+ 'anthropic-version': '2023-06-01',
164
+ },
165
+ body: JSON.stringify({
166
+ model: DEFAULT_MODEL,
167
+ max_tokens: DEFAULT_MAX_TOKENS,
168
+ messages: [{ role: 'user', content: prompt }],
169
+ }),
170
+ });
171
+ if (!res.ok) {
172
+ const errBody = await res.text();
173
+ // SEC-14-06: Anthropic error responses can echo the supplied API key
174
+ // (rare but observed in 401s). Strip secrets/paths before propagating
175
+ // to caller — the central MCP catch will sanitize again, but doing it
176
+ // here means CLI callers (which bypass the MCP catch) are also protected.
177
+ throw new Error(`Anthropic API ${res.status}: ${redactSecrets(errBody)}`);
178
+ }
179
+ const j = await res.json();
180
+ return {
181
+ text: (j.content ?? []).map(c => c.text ?? '').join(''),
182
+ usage: j.usage,
183
+ };
184
+ }
185
+
186
+ // --- parsing ---
187
+
188
+ function extractProposal(text) {
189
+ // Find "Proposed agent" heading then the next ```markdown / ```md / ``` block.
190
+ const lines = text.split(/\r?\n/);
191
+ let headingIdx = -1;
192
+ for (let i = 0; i < lines.length; i++) {
193
+ if (/^#{1,4}\s+Proposed agent\s*$/i.test(lines[i])) { headingIdx = i; break; }
194
+ }
195
+ if (headingIdx === -1) return null;
196
+
197
+ // Find opening fence after the heading
198
+ let openIdx = -1;
199
+ for (let i = headingIdx + 1; i < lines.length; i++) {
200
+ if (/^```/.test(lines[i])) { openIdx = i; break; }
201
+ }
202
+ if (openIdx === -1) return null;
203
+
204
+ // Find closing fence
205
+ let closeIdx = -1;
206
+ for (let i = openIdx + 1; i < lines.length; i++) {
207
+ if (/^```\s*$/.test(lines[i])) { closeIdx = i; break; }
208
+ }
209
+ if (closeIdx === -1) return null;
210
+
211
+ const block = lines.slice(openIdx + 1, closeIdx).join('\n').trim();
212
+ return block ? block + '\n' : null;
213
+ }
214
+
215
+ function summarizeChange(before, after) {
216
+ const bL = before.split(/\r?\n/).length;
217
+ const aL = after.split(/\r?\n/).length;
218
+ const dL = aL - bL;
219
+ const dB = after.length - before.length;
220
+ return `${aL} lines (${dL >= 0 ? '+' : ''}${dL}); ${before.length}→${after.length} bytes (${dB >= 0 ? '+' : ''}${dB})`;
221
+ }
222
+
223
+ // --- helpers ---
224
+
225
+ async function savePrompt(prompt, projectRoot, agent) {
226
+ const out = path.join(projectRoot, '.planning', 'learnings', `${agent}.reflect-prompt.md`);
227
+ await fs.mkdir(path.dirname(out), { recursive: true });
228
+ await fs.writeFile(out, prompt, 'utf8');
229
+ return out;
230
+ }
231
+
232
+ async function saveRaw(text, projectRoot, agent) {
233
+ const out = path.join(projectRoot, '.planning', 'learnings', `${agent}.reflect-raw.md`);
234
+ await fs.mkdir(path.dirname(out), { recursive: true });
235
+ await fs.writeFile(out, text, 'utf8');
236
+ return out;
237
+ }
238
+
239
+ async function ask(q) {
240
+ const rl = createInterface({ input, output });
241
+ try {
242
+ const a = (await rl.question(q)).trim().toLowerCase();
243
+ return a === 'y' || a === 'yes';
244
+ } finally {
245
+ rl.close();
246
+ }
247
+ }