@luanpdd/kit-mcp 1.30.2 → 1.32.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.
- package/LICENSE +21 -21
- package/README.md +168 -168
- package/gates/agent-no-recursive-dispatch.md +84 -82
- package/kit/COMANDOS.md +138 -138
- package/kit/COMPATIBILITY.md +5 -0
- package/kit/README.md +76 -76
- package/kit/agents/advisor-researcher.md +107 -106
- package/kit/agents/ai-mutation-tester.md +1 -0
- package/kit/agents/assumptions-analyzer.md +108 -107
- package/kit/agents/audit-log-implementer.md +314 -313
- package/kit/agents/auditor-consistencia-isolamento.md +414 -413
- package/kit/agents/b2b-saas-architect.md +157 -156
- package/kit/agents/burn-rate-forecaster.md +1 -0
- package/kit/agents/cascading-failures-auditor.md +299 -298
- package/kit/agents/codebase-mapper.md +769 -768
- package/kit/agents/crm-pipeline-implementer.md +257 -256
- package/kit/agents/debugger.md +814 -813
- package/kit/agents/detector-tenant-quente.md +338 -337
- package/kit/agents/evolution-go-integrator.md +201 -200
- package/kit/agents/example-reviewer.md +22 -21
- package/kit/agents/executor.md +565 -564
- package/kit/agents/golden-signals-instrumenter.md +1 -0
- package/kit/agents/incident-investigator.md +1 -0
- package/kit/agents/integration-checker.md +201 -200
- package/kit/agents/invite-flow-implementer.md +190 -189
- package/kit/agents/legacy-characterizer.md +369 -368
- package/kit/agents/lgpd-compliance-auditor.md +296 -295
- package/kit/agents/load-shedding-instrumenter.md +1 -0
- package/kit/agents/multi-tenant-isolation-auditor.md +254 -253
- package/kit/agents/multi-tenant-rls-writer.md +341 -340
- package/kit/agents/nyquist-auditor.md +179 -178
- package/kit/agents/observability-coverage-auditor.md +316 -315
- package/kit/agents/observability-instrumenter.md +1 -0
- package/kit/agents/omm-auditor.md +1 -0
- package/kit/agents/org-onboarding-implementer.md +224 -223
- package/kit/agents/payload-capture-instrumenter.md +274 -273
- package/kit/agents/phase-researcher.md +697 -696
- package/kit/agents/plan-checker.md +273 -272
- package/kit/agents/planner.md +923 -922
- package/kit/agents/postmortem-writer.md +1 -0
- package/kit/agents/project-researcher.md +653 -652
- package/kit/agents/prr-conductor.md +1 -0
- package/kit/agents/refactor-safety-auditor.md +405 -404
- package/kit/agents/release-pipeline-auditor.md +1 -0
- package/kit/agents/research-synthesizer.md +246 -245
- package/kit/agents/roadmapper.md +678 -677
- package/kit/agents/schema-checker.md +1 -0
- package/kit/agents/seam-finder.md +360 -359
- package/kit/agents/shotgun-surgery-detector.md +350 -349
- package/kit/agents/slo-engineer.md +1 -0
- package/kit/agents/storytelling-analyst.md +1 -0
- package/kit/agents/supabase-architect.md +1 -0
- package/kit/agents/supabase-auth-bootstrapper.md +16 -1
- package/kit/agents/supabase-auth-hook-writer.md +418 -0
- package/kit/agents/supabase-branching-architect.md +563 -562
- package/kit/agents/supabase-cicd-pipeline-implementer.md +778 -777
- package/kit/agents/supabase-column-privileges-writer.md +400 -399
- package/kit/agents/supabase-edge-fn-tester.md +2 -1
- package/kit/agents/supabase-edge-fn-writer.md +2 -1
- package/kit/agents/supabase-mfa-implementer.md +439 -0
- package/kit/agents/supabase-migration-writer.md +386 -385
- package/kit/agents/supabase-oauth-server-implementer.md +507 -0
- package/kit/agents/supabase-rbac-implementer.md +393 -392
- package/kit/agents/supabase-realtime-implementer.md +364 -363
- package/kit/agents/supabase-rls-hardener.md +522 -521
- package/kit/agents/supabase-rls-writer.md +324 -323
- package/kit/agents/supabase-roles-implementer.md +356 -355
- package/kit/agents/supabase-social-auth-implementer.md +451 -0
- package/kit/agents/supabase-sso-saml-architect.md +549 -0
- package/kit/agents/supabase-storage-implementer.md +1 -0
- package/kit/agents/super-admin-implementer.md +282 -281
- package/kit/agents/toil-auditor.md +1 -0
- package/kit/agents/ui-auditor.md +438 -437
- package/kit/agents/ui-checker.md +303 -302
- package/kit/agents/ui-researcher.md +356 -355
- package/kit/agents/user-profiler.md +176 -175
- package/kit/agents/validador-evolucao-schema.md +336 -335
- package/kit/agents/verifier.md +729 -728
- package/kit/commands/adicionar-backlog.md +75 -75
- package/kit/commands/adicionar-fase.md +42 -42
- package/kit/commands/adicionar-tarefa.md +45 -45
- package/kit/commands/adicionar-testes.md +41 -41
- package/kit/commands/ajuda.md +21 -21
- package/kit/commands/atualizar.md +37 -37
- package/kit/commands/auditar-cascading.md +111 -111
- package/kit/commands/auditar-marco.md +179 -179
- package/kit/commands/auditar-observabilidade-cobertura.md +183 -183
- package/kit/commands/auditar-refactor.md +219 -219
- package/kit/commands/auditar-release.md +109 -109
- package/kit/commands/auditar-uat.md +23 -23
- package/kit/commands/autonomo.md +40 -40
- package/kit/commands/branch-pr.md +24 -24
- package/kit/commands/burn-rate-status.md +408 -408
- package/kit/commands/capturar-payloads.md +193 -193
- package/kit/commands/caracterizar.md +212 -212
- package/kit/commands/concluir-marco.md +247 -247
- package/kit/commands/configuracoes.md +36 -36
- package/kit/commands/dados-distribuidos.md +188 -188
- package/kit/commands/definir-perfil.md +10 -10
- package/kit/commands/depurar.md +190 -190
- package/kit/commands/detectar-duplicacao.md +197 -197
- package/kit/commands/discutir-fase.md +131 -131
- package/kit/commands/encontrar-seams.md +136 -136
- package/kit/commands/entrar-discord.md +17 -17
- package/kit/commands/estatisticas.md +18 -18
- package/kit/commands/example-greeting.md +33 -33
- package/kit/commands/executar-fase.md +58 -58
- package/kit/commands/expresso.md +56 -56
- package/kit/commands/fase-ui.md +34 -34
- package/kit/commands/fazer.md +57 -57
- package/kit/commands/fio.md +125 -125
- package/kit/commands/fluxos-trabalho.md +64 -64
- package/kit/commands/forense.md +176 -176
- package/kit/commands/gerenciador.md +38 -38
- package/kit/commands/inserir-fase.md +31 -31
- package/kit/commands/legacy.md +263 -263
- package/kit/commands/limpeza.md +17 -17
- package/kit/commands/listar-hipoteses-fase.md +45 -45
- package/kit/commands/listar-workspaces.md +18 -18
- package/kit/commands/load-shedding.md +117 -117
- package/kit/commands/mapear-codebase.md +70 -70
- package/kit/commands/multi-tenant.md +163 -163
- package/kit/commands/nota.md +33 -33
- package/kit/commands/novo-marco.md +43 -43
- package/kit/commands/novo-projeto.md +41 -41
- package/kit/commands/novo-workspace.md +43 -43
- package/kit/commands/pausar-trabalho.md +37 -37
- package/kit/commands/perfil-usuario.md +45 -45
- package/kit/commands/pesquisar-fase.md +195 -195
- package/kit/commands/planejar-fase.md +67 -67
- package/kit/commands/planejar-lacunas.md +33 -33
- package/kit/commands/plantar-ideia.md +25 -25
- package/kit/commands/progresso.md +24 -24
- package/kit/commands/proximo.md +30 -30
- package/kit/commands/publicar.md +490 -490
- package/kit/commands/rapido.md +35 -35
- package/kit/commands/reaplicar-patches.md +124 -124
- package/kit/commands/refactor-seguro.md +321 -321
- package/kit/commands/relatorio-sessao.md +19 -19
- package/kit/commands/remover-fase.md +31 -31
- package/kit/commands/remover-workspace.md +26 -26
- package/kit/commands/resumo-marco.md +50 -50
- package/kit/commands/retomar-trabalho.md +40 -40
- package/kit/commands/revisar-backlog.md +60 -60
- package/kit/commands/revisar-ui.md +32 -32
- package/kit/commands/revisar.md +37 -37
- package/kit/commands/saude.md +21 -21
- package/kit/commands/setup-notion.md +93 -93
- package/kit/commands/storytelling.md +179 -179
- package/kit/commands/supabase.md +21 -1
- package/kit/commands/sync-main.md +68 -68
- package/kit/commands/validar-fase.md +35 -35
- package/kit/commands/verificar-tarefas.md +44 -44
- package/kit/commands/verificar-trabalho.md +64 -64
- package/kit/file-manifest.json +100 -84
- package/kit/framework/bin/lib/commands.cjs +959 -959
- package/kit/framework/bin/lib/config.cjs +442 -442
- package/kit/framework/bin/lib/core.cjs +1230 -1230
- package/kit/framework/bin/lib/frontmatter.cjs +336 -336
- package/kit/framework/bin/lib/init.cjs +1442 -1442
- package/kit/framework/bin/lib/milestone.cjs +252 -252
- package/kit/framework/bin/lib/model-profiles.cjs +68 -68
- package/kit/framework/bin/lib/phase.cjs +888 -888
- package/kit/framework/bin/lib/profile-output.cjs +952 -952
- package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
- package/kit/framework/bin/lib/roadmap.cjs +329 -329
- package/kit/framework/bin/lib/security.cjs +382 -382
- package/kit/framework/bin/lib/state.cjs +1031 -1031
- package/kit/framework/bin/lib/template.cjs +222 -222
- package/kit/framework/bin/lib/uat.cjs +282 -282
- package/kit/framework/bin/lib/verify.cjs +888 -888
- package/kit/framework/bin/lib/workstream.cjs +491 -491
- package/kit/framework/bin/tools.cjs +918 -918
- package/kit/framework/commands/workstreams.md +63 -63
- package/kit/framework/references/checkpoints.md +778 -778
- package/kit/framework/references/continuation-format.md +249 -249
- package/kit/framework/references/decimal-phase-calculation.md +64 -64
- package/kit/framework/references/git-integration.md +295 -295
- package/kit/framework/references/git-planning-commit.md +38 -38
- package/kit/framework/references/model-profile-resolution.md +36 -36
- package/kit/framework/references/model-profiles.md +139 -139
- package/kit/framework/references/phase-argument-parsing.md +61 -61
- package/kit/framework/references/planning-config.md +202 -202
- package/kit/framework/references/questioning.md +162 -162
- package/kit/framework/references/tdd.md +263 -263
- package/kit/framework/references/ui-brand.md +160 -160
- package/kit/framework/references/user-profiling.md +657 -657
- package/kit/framework/references/verification-patterns.md +612 -612
- package/kit/framework/references/workstream-flag.md +58 -58
- package/kit/framework/templates/DEBUG.md +164 -164
- package/kit/framework/templates/UAT.md +265 -265
- package/kit/framework/templates/UI-SPEC.md +100 -100
- package/kit/framework/templates/VALIDATION.md +76 -76
- package/kit/framework/templates/claude-md.md +122 -122
- package/kit/framework/templates/codebase/architecture.md +185 -185
- package/kit/framework/templates/codebase/concerns.md +205 -205
- package/kit/framework/templates/codebase/conventions.md +204 -204
- package/kit/framework/templates/codebase/integrations.md +192 -192
- package/kit/framework/templates/codebase/stack.md +158 -158
- package/kit/framework/templates/codebase/structure.md +199 -199
- package/kit/framework/templates/codebase/testing.md +301 -301
- package/kit/framework/templates/config.json +44 -44
- package/kit/framework/templates/context.md +352 -352
- package/kit/framework/templates/continue-here.md +78 -78
- package/kit/framework/templates/copilot-instructions.md +7 -7
- package/kit/framework/templates/debug-subagent-prompt.md +91 -91
- package/kit/framework/templates/dev-preferences.md +20 -20
- package/kit/framework/templates/discovery.md +146 -146
- package/kit/framework/templates/discussion-log.md +63 -63
- package/kit/framework/templates/milestone-archive.md +123 -123
- package/kit/framework/templates/milestone.md +115 -115
- package/kit/framework/templates/phase-prompt.md +610 -610
- package/kit/framework/templates/planner-subagent-prompt.md +117 -117
- package/kit/framework/templates/project.md +186 -186
- package/kit/framework/templates/requirements.md +231 -231
- package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
- package/kit/framework/templates/research-project/FEATURES.md +147 -147
- package/kit/framework/templates/research-project/PITFALLS.md +200 -200
- package/kit/framework/templates/research-project/STACK.md +120 -120
- package/kit/framework/templates/research-project/SUMMARY.md +170 -170
- package/kit/framework/templates/research.md +419 -419
- package/kit/framework/templates/retrospective.md +54 -54
- package/kit/framework/templates/roadmap.md +202 -202
- package/kit/framework/templates/state.md +176 -176
- package/kit/framework/templates/summary-complex.md +59 -59
- package/kit/framework/templates/summary-minimal.md +41 -41
- package/kit/framework/templates/summary-standard.md +48 -48
- package/kit/framework/templates/summary.md +209 -209
- package/kit/framework/templates/user-profile.md +146 -146
- package/kit/framework/templates/user-setup.md +256 -256
- package/kit/framework/templates/verification-report.md +258 -258
- package/kit/framework/workflows/add-phase.md +112 -112
- package/kit/framework/workflows/add-tests.md +351 -351
- package/kit/framework/workflows/add-todo.md +158 -158
- package/kit/framework/workflows/audit-milestone.md +340 -340
- package/kit/framework/workflows/audit-uat.md +109 -109
- package/kit/framework/workflows/autonomous.md +891 -891
- package/kit/framework/workflows/check-todos.md +177 -177
- package/kit/framework/workflows/cleanup.md +152 -152
- package/kit/framework/workflows/complete-milestone.md +696 -696
- package/kit/framework/workflows/diagnose-issues.md +231 -231
- package/kit/framework/workflows/discovery-phase.md +289 -289
- package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
- package/kit/framework/workflows/discuss-phase.md +784 -784
- package/kit/framework/workflows/do.md +104 -104
- package/kit/framework/workflows/execute-phase.md +838 -838
- package/kit/framework/workflows/execute-plan.md +510 -510
- package/kit/framework/workflows/fast.md +102 -102
- package/kit/framework/workflows/forensics.md +265 -265
- package/kit/framework/workflows/health.md +181 -181
- package/kit/framework/workflows/help.md +619 -619
- package/kit/framework/workflows/insert-phase.md +130 -130
- package/kit/framework/workflows/list-phase-assumptions.md +178 -178
- package/kit/framework/workflows/list-workspaces.md +56 -56
- package/kit/framework/workflows/manager.md +362 -362
- package/kit/framework/workflows/map-codebase.md +377 -377
- package/kit/framework/workflows/milestone-summary.md +223 -223
- package/kit/framework/workflows/new-milestone.md +486 -486
- package/kit/framework/workflows/new-project.md +1159 -1159
- package/kit/framework/workflows/new-workspace.md +237 -237
- package/kit/framework/workflows/next.md +97 -97
- package/kit/framework/workflows/node-repair.md +92 -92
- package/kit/framework/workflows/note.md +156 -156
- package/kit/framework/workflows/pause-work.md +176 -176
- package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
- package/kit/framework/workflows/plan-phase.md +765 -765
- package/kit/framework/workflows/plant-seed.md +169 -169
- package/kit/framework/workflows/pr-branch.md +129 -129
- package/kit/framework/workflows/profile-user.md +450 -450
- package/kit/framework/workflows/progress.md +507 -507
- package/kit/framework/workflows/quick.md +757 -757
- package/kit/framework/workflows/remove-phase.md +155 -155
- package/kit/framework/workflows/remove-workspace.md +90 -90
- package/kit/framework/workflows/research-phase.md +82 -82
- package/kit/framework/workflows/resume-project.md +326 -326
- package/kit/framework/workflows/review.md +228 -228
- package/kit/framework/workflows/session-report.md +146 -146
- package/kit/framework/workflows/settings.md +283 -283
- package/kit/framework/workflows/ship.md +228 -228
- package/kit/framework/workflows/stats.md +60 -60
- package/kit/framework/workflows/transition.md +671 -671
- package/kit/framework/workflows/ui-phase.md +302 -302
- package/kit/framework/workflows/ui-review.md +165 -165
- package/kit/framework/workflows/update.md +323 -323
- package/kit/framework/workflows/validate-phase.md +174 -174
- package/kit/framework/workflows/verify-phase.md +252 -252
- package/kit/framework/workflows/verify-work.md +637 -637
- package/kit/hooks/check-update.js +118 -118
- package/kit/hooks/context-monitor.js +163 -163
- package/kit/hooks/kit-attribution-reminder.cjs +29 -50
- package/kit/hooks/kit-router.cjs +137 -0
- package/kit/hooks/prompt-guard.js +103 -103
- package/kit/hooks/statusline.js +125 -125
- package/kit/hooks/workflow-guard.js +101 -101
- package/kit/settings.json +45 -45
- package/kit/skills/ai-prompt-characterization/SKILL.md +335 -335
- package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +447 -447
- package/kit/skills/audit-log-multi-tenant/SKILL.md +340 -340
- package/kit/skills/b2b-saas-architecture/SKILL.md +300 -300
- package/kit/skills/consistencia-leitura-replica/SKILL.md +385 -385
- package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +343 -343
- package/kit/skills/escolha-modelo-consistencia/SKILL.md +494 -494
- package/kit/skills/evolucao-schema-compativel/SKILL.md +448 -448
- package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -322
- package/kit/skills/example-skill/SKILL.md +42 -42
- package/kit/skills/legacy-api-only-applications/SKILL.md +358 -358
- package/kit/skills/legacy-characterization-tests/SKILL.md +330 -330
- package/kit/skills/legacy-effect-analysis/SKILL.md +331 -331
- package/kit/skills/legacy-extract-class/SKILL.md +203 -203
- package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -252
- package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -460
- package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -286
- package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -434
- package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -270
- package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -340
- package/kit/skills/member-invite-flow/SKILL.md +305 -305
- package/kit/skills/member-management-react-shadcn/SKILL.md +328 -328
- package/kit/skills/multi-tenant-performance-scaling/SKILL.md +316 -316
- package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +342 -342
- package/kit/skills/org-onboarding-flow/SKILL.md +257 -257
- package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -349
- package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -271
- package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +552 -552
- package/kit/skills/pre-refactor-characterization/SKILL.md +421 -421
- package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +338 -338
- package/kit/skills/streams-eventos-cdc/SKILL.md +711 -711
- package/kit/skills/supabase-auth-hardening/SKILL.md +674 -0
- package/kit/skills/supabase-auth-hooks/SKILL.md +875 -0
- package/kit/skills/supabase-auth-methods/SKILL.md +486 -0
- package/kit/skills/supabase-auth-sessions/SKILL.md +579 -0
- package/kit/skills/supabase-auth-ssr/SKILL.md +60 -14
- package/kit/skills/supabase-branching-workflow/SKILL.md +544 -544
- package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -880
- package/kit/skills/supabase-column-level-security/SKILL.md +426 -426
- package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -807
- package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -472
- package/kit/skills/supabase-edge-functions/SKILL.md +1 -1
- package/kit/skills/supabase-edge-functions-auth/SKILL.md +1 -1
- package/kit/skills/supabase-edge-functions-limits/SKILL.md +1 -1
- package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +1 -1
- package/kit/skills/supabase-edge-functions-testing/SKILL.md +1 -1
- package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +1 -1
- package/kit/skills/supabase-enterprise-sso-saml/SKILL.md +545 -0
- package/kit/skills/supabase-jwt-signing-keys/SKILL.md +399 -0
- package/kit/skills/supabase-mfa/SKILL.md +488 -0
- package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
- package/kit/skills/supabase-migrations/SKILL.md +297 -297
- package/kit/skills/supabase-oauth-server/SKILL.md +537 -0
- package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -1053
- package/kit/skills/supabase-postgres-roles/SKILL.md +392 -392
- package/kit/skills/supabase-realtime/SKILL.md +460 -460
- package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -418
- package/kit/skills/supabase-rls-policies/SKILL.md +635 -635
- package/kit/skills/supabase-social-oauth/SKILL.md +480 -0
- package/kit/skills/supabase-third-party-auth/SKILL.md +450 -0
- package/kit/skills/super-admin-platform-pattern/SKILL.md +326 -326
- package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
- package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
- package/package.json +1 -1
- package/src/core/kit.js +216 -216
- package/src/core/reflect.js +247 -247
- package/src/core/reverse-sync.js +372 -372
- package/src/core/sync.js +437 -418
- package/src/core/watch.js +121 -121
- package/src/mcp-server/index.js +794 -746
package/src/core/reflect.js
CHANGED
|
@@ -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
|
+
}
|