@planu/cli 4.11.1 → 4.11.3
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/CHANGELOG.md +16 -0
- package/dist/config/elicitation-questions.json +5 -17
- package/dist/engine/cascade-hooks/registry.js +0 -2
- package/dist/engine/challenge-scenarios-loader.d.ts +3 -3
- package/dist/engine/compliance-injector.d.ts +3 -3
- package/dist/engine/dashboard/kanban-logic.d.ts +1 -1
- package/dist/engine/doc-generator/portal/risk-matrix-svg.d.ts +1 -1
- package/dist/engine/doc-generator/proposal/proposal-generator.d.ts +1 -1
- package/dist/engine/elicitation/answer-extractor.d.ts +1 -4
- package/dist/engine/elicitation/answer-extractor.js +197 -68
- package/dist/engine/elicitation/decision-gap-detector.js +59 -79
- package/dist/engine/elicitation/index.d.ts +0 -1
- package/dist/engine/elicitation/index.js +0 -1
- package/dist/engine/elicitation/question-generator.js +10 -3
- package/dist/engine/elicitation/question-grounding-gate.js +83 -34
- package/dist/engine/evidence-gates/lifecycle-gate.js +27 -14
- package/dist/engine/evidence-index/index-builder.js +7 -2
- package/dist/engine/frontmatter-sha/frozen-fields.d.ts +1 -1
- package/dist/engine/handoff-artifacts/schemas/red-tests-handoff.d.ts +2 -2
- package/dist/engine/handoff-artifacts/schemas.d.ts +22 -22
- package/dist/engine/human-summary.js +3 -3
- package/dist/engine/implementation-contract/common.d.ts +1 -1
- package/dist/engine/implementation-contract/renderer.js +17 -39
- package/dist/engine/keyword-matcher/stopwords.d.ts +2 -2
- package/dist/engine/lifecycle-hints.d.ts +1 -1
- package/dist/engine/lifecycle-hints.js +13 -29
- package/dist/engine/provider-adapters/adapters/claude.d.ts +1 -1
- package/dist/engine/provider-adapters/adapters/gemini.d.ts +1 -1
- package/dist/engine/provider-adapters/adapters/gpt4.d.ts +1 -1
- package/dist/engine/provider-adapters/adapters/markdown.d.ts +1 -1
- package/dist/engine/safety/atomic-write-file.d.ts +1 -1
- package/dist/engine/safety/cross-process-lock.d.ts +1 -1
- package/dist/engine/safety/path-sanitizer.d.ts +1 -1
- package/dist/engine/security-analyzer/profile-detector.js +48 -16
- package/dist/engine/spec-format/copula-blacklist.d.ts +2 -2
- package/dist/engine/spec-format/lean-spec-generator.d.ts +2 -2
- package/dist/engine/spec-format/lean-spec-generator.js +9 -10
- package/dist/engine/spec-format/metadata-value-policy.d.ts +20 -20
- package/dist/engine/spec-generator/fallback-generator.js +13 -20
- package/dist/engine/spec-grounding/contract.d.ts +5 -0
- package/dist/engine/spec-grounding/contract.js +10 -6
- package/dist/engine/spec-migrator/lean-migration.js +9 -16
- package/dist/engine/text-signal-boundaries.js +45 -12
- package/dist/engine/universal-rules/rules/planu-modes.js +0 -2
- package/dist/engine/web-fetcher/stack-advisor.d.ts +2 -2
- package/dist/engine/web-fetcher/stack-advisor.js +78 -17
- package/dist/engine/well-known/manifest-schema.d.ts +33 -33
- package/dist/engine/workers/schema.d.ts +3 -3
- package/dist/hosts/claude-code/ux/mcp-resources.d.ts +4 -4
- package/dist/hosts/codex/rest-shim.d.ts +1 -1
- package/dist/native/lightweight-command-catalog.d.ts +30 -30
- package/dist/server/openapi-spec.d.ts +132 -132
- package/dist/tools/challenge-spec/challenge-report.d.ts +13 -0
- package/dist/tools/challenge-spec/challenge-report.js +55 -0
- package/dist/tools/challenge-spec/event-challenge-scenarios.js +8 -27
- package/dist/tools/challenge-spec/resilience-challenge-scenarios-a.js +16 -32
- package/dist/tools/challenge-spec/resilience-challenge-scenarios-b.js +15 -20
- package/dist/tools/challenge-spec/scenario-collector.d.ts +13 -0
- package/dist/tools/challenge-spec/scenario-collector.js +86 -0
- package/dist/tools/challenge-spec/scenarios-data.js +10 -9
- package/dist/tools/challenge-spec/scenarios-failure.js +38 -54
- package/dist/tools/challenge-spec/scenarios-scale.js +14 -15
- package/dist/tools/challenge-spec/scenarios-security.d.ts +1 -1
- package/dist/tools/challenge-spec/scenarios-security.js +18 -11
- package/dist/tools/challenge-spec/scenarios-utils.d.ts +31 -5
- package/dist/tools/challenge-spec/scenarios-utils.js +102 -6
- package/dist/tools/challenge-spec/security-challenge-scenarios.d.ts +1 -1
- package/dist/tools/challenge-spec/security-challenge-scenarios.js +20 -25
- package/dist/tools/challenge-spec.js +46 -124
- package/dist/tools/clarify-requirements/multiple-choice.js +1 -1
- package/dist/tools/clarify-requirements/questions-context.js +11 -11
- package/dist/tools/clarify-requirements/questions.js +3 -23
- package/dist/tools/clarify-requirements.js +38 -0
- package/dist/tools/compliance-gate-handler.d.ts +1 -1
- package/dist/tools/create-spec/autopilot-analyzer.d.ts +1 -1
- package/dist/tools/create-spec/autopilot-analyzer.js +29 -54
- package/dist/tools/create-spec/post-creation.js +23 -4
- package/dist/tools/create-spec.js +51 -168
- package/dist/tools/delete-first/suggest-deletions.d.ts +1 -1
- package/dist/tools/elicit-requirements-handler.js +20 -12
- package/dist/tools/generate-batch-script.d.ts +2 -2
- package/dist/tools/init-project/rules-generator.js +0 -1
- package/dist/tools/oauth-handler.d.ts +1 -1
- package/dist/tools/register-sdd-tools.d.ts +1 -1
- package/dist/tools/register-spec-tools/core-spec-tools.js +11 -2
- package/dist/tools/render-spec-for-provider.d.ts +2 -2
- package/dist/tools/scan-orphan-spec-refs.d.ts +6 -6
- package/dist/tools/schemas/agents.d.ts +7 -7
- package/dist/tools/schemas/analysis.d.ts +11 -11
- package/dist/tools/schemas/delete.d.ts +5 -5
- package/dist/tools/schemas/github.d.ts +4 -4
- package/dist/tools/schemas/ide-config.d.ts +12 -12
- package/dist/tools/schemas/infra.d.ts +9 -9
- package/dist/tools/schemas/lifecycle.d.ts +50 -50
- package/dist/tools/schemas/llm-provider-schemas.d.ts +7 -7
- package/dist/tools/schemas/plugins-schemas.d.ts +12 -12
- package/dist/tools/schemas/project-graph.d.ts +6 -6
- package/dist/tools/schemas/rbac.d.ts +2 -2
- package/dist/tools/schemas/registry.d.ts +3 -3
- package/dist/tools/schemas/runtime-security.d.ts +2 -2
- package/dist/tools/schemas/session.d.ts +2 -2
- package/dist/tools/schemas/spec.d.ts +15 -15
- package/dist/tools/schemas/token-intelligence.d.ts +6 -6
- package/dist/tools/schemas/token-optimization.d.ts +2 -2
- package/dist/tools/schemas/workers-schema.d.ts +4 -4
- package/dist/tools/skill-bootstrap-handler.d.ts +7 -7
- package/dist/tools/suggest-stack.js +49 -13
- package/dist/tools/tool-registry/deprecated-stubs.d.ts +1 -1
- package/dist/tools/triage-request.d.ts +3 -3
- package/dist/tools/update-status/dod-gates.d.ts +8 -0
- package/dist/tools/update-status/dod-gates.js +68 -43
- package/dist/tools/update-status/file-sync.d.ts +1 -1
- package/dist/tools/update-status/file-sync.js +10 -45
- package/dist/tools/update-status/index.js +133 -97
- package/dist/tools/update-status/qa-gate.js +26 -0
- package/dist/tools/update-status/response-builder.d.ts +1 -1
- package/dist/tools/update-status/response-builder.js +11 -19
- package/dist/tools/update-status/transition-guard.d.ts +2 -2
- package/dist/tools/update-status/transition-guard.js +11 -8
- package/dist/tools/update-status-actions.d.ts +0 -1
- package/dist/tools/update-status-actions.js +10 -26
- package/dist/tools/update-status-convention-gate.d.ts +1 -6
- package/dist/tools/update-status-convention-gate.js +9 -33
- package/dist/tools/validate-lint.d.ts +1 -1
- package/dist/tools/validate-lint.js +39 -1
- package/dist/types/docs.d.ts +0 -4
- package/dist/types/env.d.ts +0 -4
- package/dist/types/estimation.d.ts +0 -2
- package/dist/types/multi-teammate-review.d.ts +4 -4
- package/dist/types/plugin-install.d.ts +7 -7
- package/dist/types/spec/core.d.ts +20 -0
- package/dist/types/spec/inputs.d.ts +1 -1
- package/dist/types/stack/index.d.ts +1 -1
- package/dist/types/stack/recommend.d.ts +10 -0
- package/package.json +21 -18
- package/planu-native.json +1 -1
- package/planu-plugin.json +1 -1
- package/src/i18n/messages/en.json +0 -72
- package/src/i18n/messages/es.json +0 -72
- package/src/i18n/messages/pt.json +0 -72
- package/dist/config/elicitation-dimensions.json +0 -51
- package/dist/engine/actuals-estimator.d.ts +0 -14
- package/dist/engine/actuals-estimator.js +0 -64
- package/dist/engine/cascade-hooks/hooks/living-specs.hook.d.ts +0 -3
- package/dist/engine/cascade-hooks/hooks/living-specs.hook.js +0 -19
- package/dist/engine/elicitation/non-interactive-defaults.d.ts +0 -9
- package/dist/engine/elicitation/non-interactive-defaults.js +0 -28
- package/dist/engine/elicitation/option-builder.d.ts +0 -9
- package/dist/engine/elicitation/option-builder.js +0 -85
- package/dist/engine/progress-writer.d.ts +0 -10
- package/dist/engine/progress-writer.js +0 -63
- package/dist/tools/clarify-requirements/interview-mode.d.ts +0 -42
- package/dist/tools/clarify-requirements/interview-mode.js +0 -342
- package/dist/tools/update-status/mode-hints.d.ts +0 -4
- package/dist/tools/update-status/mode-hints.js +0 -24
|
@@ -558,77 +558,5 @@
|
|
|
558
558
|
"description": "Obtener una vista completa del proyecto — specs, progreso y metricas de salud",
|
|
559
559
|
"message": "Dame una vista completa del estado del proyecto {projectId}.\n\nPor favor:\n1. Lista todas las specs agrupadas por estado (draft, review, approved, implementing, done)\n2. Muestra el progreso general (cuantas specs estan terminadas vs total)\n3. Resalta specs que podrian necesitar atencion:\n - Specs estancadas en 'implementing' por mucho tiempo\n - Specs en 'draft' que no han sido revisadas\n - Specs con drift detectado\n4. Resume la salud del proyecto en lenguaje simple"
|
|
560
560
|
}
|
|
561
|
-
},
|
|
562
|
-
"questions": {
|
|
563
|
-
"target": {
|
|
564
|
-
"question": "¿Qué área abarca esta funcionalidad?",
|
|
565
|
-
"header": "Área",
|
|
566
|
-
"frontend": "Frontend",
|
|
567
|
-
"frontendDesc": "Componentes UI, páginas, estilos",
|
|
568
|
-
"backend": "Backend",
|
|
569
|
-
"backendDesc": "API, lógica de servidor, base de datos",
|
|
570
|
-
"fullstack": "Fullstack (Recomendado)",
|
|
571
|
-
"fullstackDesc": "Cambios en frontend y backend",
|
|
572
|
-
"infra": "Infraestructura",
|
|
573
|
-
"infraDesc": "CI/CD, despliegue, configuración"
|
|
574
|
-
},
|
|
575
|
-
"payment": {
|
|
576
|
-
"providerQuestion": "¿Con qué proveedor de pagos se integrará?",
|
|
577
|
-
"providerHeader": "Proveedor de Pago",
|
|
578
|
-
"stripe": "Stripe (Recomendado)",
|
|
579
|
-
"stripeDesc": "Tarjetas, suscripciones, facturación",
|
|
580
|
-
"paypal": "PayPal",
|
|
581
|
-
"paypalDesc": "Checkout y suscripciones de PayPal",
|
|
582
|
-
"paddle": "Paddle",
|
|
583
|
-
"paddleDesc": "Enfocado en SaaS, maneja impuestos",
|
|
584
|
-
"other": "Otro / personalizado",
|
|
585
|
-
"otherDesc": "Especificar en la descripción",
|
|
586
|
-
"modelQuestion": "¿Qué modelo de suscripción / facturación necesita?",
|
|
587
|
-
"modelHeader": "Modelo de Facturación",
|
|
588
|
-
"oneTime": "Pago único",
|
|
589
|
-
"oneTimeDesc": "Un solo cargo por compra",
|
|
590
|
-
"recurring": "Suscripción recurrente (Recomendado)",
|
|
591
|
-
"recurringDesc": "Planes mensuales o anuales",
|
|
592
|
-
"usageBased": "Basado en uso",
|
|
593
|
-
"usageBasedDesc": "Cobro por unidad consumida",
|
|
594
|
-
"freemium": "Freemium + planes de pago",
|
|
595
|
-
"freemiumDesc": "Nivel gratuito con actualizaciones"
|
|
596
|
-
},
|
|
597
|
-
"scope": {
|
|
598
|
-
"question": "¿Cuál es el alcance de este cambio?",
|
|
599
|
-
"header": "Alcance",
|
|
600
|
-
"feature": "Funcionalidad (Recomendado)",
|
|
601
|
-
"featureDesc": "Nueva función en un solo módulo",
|
|
602
|
-
"crossModule": "Multi-módulo",
|
|
603
|
-
"crossModuleDesc": "Cambios que abarcan varios módulos",
|
|
604
|
-
"trivial": "Trivial",
|
|
605
|
-
"trivialDesc": "Pequeño fix o cambio de configuración",
|
|
606
|
-
"architectural": "Arquitectural",
|
|
607
|
-
"architecturalDesc": "Cambio estructural que afecta todo el sistema"
|
|
608
|
-
},
|
|
609
|
-
"database": {
|
|
610
|
-
"question": "¿Esta funcionalidad involucra cambios en la base de datos?",
|
|
611
|
-
"header": "Base de Datos",
|
|
612
|
-
"none": "Sin cambios en base de datos",
|
|
613
|
-
"noneDesc": "Cambio puramente en frontend o lógica",
|
|
614
|
-
"schema": "Nueva tabla/columnas (Recomendado)",
|
|
615
|
-
"schemaDesc": "Se necesita migración de esquema",
|
|
616
|
-
"rls": "Políticas RLS",
|
|
617
|
-
"rlsDesc": "Cambios en Row Level Security",
|
|
618
|
-
"rpc": "Funciones RPC",
|
|
619
|
-
"rpcDesc": "Funciones de base de datos nuevas o modificadas"
|
|
620
|
-
},
|
|
621
|
-
"uiType": {
|
|
622
|
-
"question": "¿Qué tipo de trabajo de UI implica?",
|
|
623
|
-
"header": "Tipo de UI",
|
|
624
|
-
"newComponent": "Nuevo componente (Recomendado)",
|
|
625
|
-
"newComponentDesc": "Construir desde cero",
|
|
626
|
-
"modify": "Modificar existente",
|
|
627
|
-
"modifyDesc": "Cambiar un componente existente",
|
|
628
|
-
"serverAction": "Server Action",
|
|
629
|
-
"serverActionDesc": "Lógica de backend invocada desde UI",
|
|
630
|
-
"noUi": "Sin cambios de UI",
|
|
631
|
-
"noUiDesc": "Solo backend"
|
|
632
|
-
}
|
|
633
561
|
}
|
|
634
562
|
}
|
|
@@ -558,77 +558,5 @@
|
|
|
558
558
|
"description": "Obter uma visao completa do projeto — specs, progresso e metricas de saude",
|
|
559
559
|
"message": "Me de uma visao completa do estado do projeto {projectId}.\n\nPor favor:\n1. Liste todas as specs agrupadas por estado (draft, review, approved, implementing, done)\n2. Mostre o progresso geral (quantas specs estao concluidas vs total)\n3. Destaque specs que podem precisar de atencao:\n - Specs paradas em 'implementing' por muito tempo\n - Specs em 'draft' que nao foram revisadas\n - Specs com drift detectado\n4. Resuma a saude do projeto em linguagem simples"
|
|
560
560
|
}
|
|
561
|
-
},
|
|
562
|
-
"questions": {
|
|
563
|
-
"target": {
|
|
564
|
-
"question": "Qual área esta funcionalidade abrange?",
|
|
565
|
-
"header": "Área",
|
|
566
|
-
"frontend": "Frontend",
|
|
567
|
-
"frontendDesc": "Componentes UI, páginas, estilos",
|
|
568
|
-
"backend": "Backend",
|
|
569
|
-
"backendDesc": "API, lógica do servidor, banco de dados",
|
|
570
|
-
"fullstack": "Fullstack (Recomendado)",
|
|
571
|
-
"fullstackDesc": "Mudanças em frontend e backend",
|
|
572
|
-
"infra": "Infraestrutura",
|
|
573
|
-
"infraDesc": "CI/CD, implantação, configuração"
|
|
574
|
-
},
|
|
575
|
-
"payment": {
|
|
576
|
-
"providerQuestion": "Com qual provedor de pagamentos será integrado?",
|
|
577
|
-
"providerHeader": "Provedor de Pagamento",
|
|
578
|
-
"stripe": "Stripe (Recomendado)",
|
|
579
|
-
"stripeDesc": "Cartões, assinaturas, faturamento",
|
|
580
|
-
"paypal": "PayPal",
|
|
581
|
-
"paypalDesc": "Checkout e assinaturas PayPal",
|
|
582
|
-
"paddle": "Paddle",
|
|
583
|
-
"paddleDesc": "Focado em SaaS, gerencia impostos",
|
|
584
|
-
"other": "Outro / personalizado",
|
|
585
|
-
"otherDesc": "Especificar na descrição",
|
|
586
|
-
"modelQuestion": "Qual modelo de assinatura / faturamento é necessário?",
|
|
587
|
-
"modelHeader": "Modelo de Faturamento",
|
|
588
|
-
"oneTime": "Pagamento único",
|
|
589
|
-
"oneTimeDesc": "Cobrança única por compra",
|
|
590
|
-
"recurring": "Assinatura recorrente (Recomendado)",
|
|
591
|
-
"recurringDesc": "Planos mensais ou anuais",
|
|
592
|
-
"usageBased": "Baseado em uso",
|
|
593
|
-
"usageBasedDesc": "Cobrado por unidade consumida",
|
|
594
|
-
"freemium": "Freemium + planos pagos",
|
|
595
|
-
"freemiumDesc": "Nível gratuito com upgrades"
|
|
596
|
-
},
|
|
597
|
-
"scope": {
|
|
598
|
-
"question": "Qual é o escopo desta mudança?",
|
|
599
|
-
"header": "Escopo",
|
|
600
|
-
"feature": "Funcionalidade (Recomendado)",
|
|
601
|
-
"featureDesc": "Nova função em um único módulo",
|
|
602
|
-
"crossModule": "Multi-módulo",
|
|
603
|
-
"crossModuleDesc": "Mudanças em vários módulos",
|
|
604
|
-
"trivial": "Trivial",
|
|
605
|
-
"trivialDesc": "Pequena correção ou mudança de configuração",
|
|
606
|
-
"architectural": "Arquitetural",
|
|
607
|
-
"architecturalDesc": "Mudança estrutural que afeta todo o sistema"
|
|
608
|
-
},
|
|
609
|
-
"database": {
|
|
610
|
-
"question": "Esta funcionalidade envolve mudanças no banco de dados?",
|
|
611
|
-
"header": "Banco de Dados",
|
|
612
|
-
"none": "Sem mudanças no banco de dados",
|
|
613
|
-
"noneDesc": "Mudança puramente em frontend ou lógica",
|
|
614
|
-
"schema": "Nova tabela/colunas (Recomendado)",
|
|
615
|
-
"schemaDesc": "Migração de esquema necessária",
|
|
616
|
-
"rls": "Políticas RLS",
|
|
617
|
-
"rlsDesc": "Mudanças em Row Level Security",
|
|
618
|
-
"rpc": "Funções RPC",
|
|
619
|
-
"rpcDesc": "Funções de banco de dados novas ou modificadas"
|
|
620
|
-
},
|
|
621
|
-
"uiType": {
|
|
622
|
-
"question": "Que tipo de trabalho de UI está envolvido?",
|
|
623
|
-
"header": "Tipo de UI",
|
|
624
|
-
"newComponent": "Novo componente (Recomendado)",
|
|
625
|
-
"newComponentDesc": "Construir do zero",
|
|
626
|
-
"modify": "Modificar existente",
|
|
627
|
-
"modifyDesc": "Alterar um componente existente",
|
|
628
|
-
"serverAction": "Server Action",
|
|
629
|
-
"serverActionDesc": "Lógica de backend acionada pela UI",
|
|
630
|
-
"noUi": "Sem mudanças de UI",
|
|
631
|
-
"noUiDesc": "Apenas backend"
|
|
632
|
-
}
|
|
633
561
|
}
|
|
634
562
|
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": "target",
|
|
4
|
-
"headerKey": "questions.target.header",
|
|
5
|
-
"questionKey": "questions.target.question",
|
|
6
|
-
"suppressWhen": "hasTarget",
|
|
7
|
-
"optionSet": "target",
|
|
8
|
-
"multiSelect": false
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"id": "payment_provider",
|
|
12
|
-
"headerKey": "questions.payment.providerHeader",
|
|
13
|
-
"questionKey": "questions.payment.providerQuestion",
|
|
14
|
-
"requiresSignal": "hasBilling",
|
|
15
|
-
"suppressWhen": "namedProvider",
|
|
16
|
-
"optionSet": "payment_provider",
|
|
17
|
-
"multiSelect": false
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"id": "billing_model",
|
|
21
|
-
"headerKey": "questions.payment.modelHeader",
|
|
22
|
-
"questionKey": "questions.payment.modelQuestion",
|
|
23
|
-
"requiresSignal": "hasBilling",
|
|
24
|
-
"optionSet": "billing_model",
|
|
25
|
-
"multiSelect": false
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"id": "scope",
|
|
29
|
-
"headerKey": "questions.scope.header",
|
|
30
|
-
"questionKey": "questions.scope.question",
|
|
31
|
-
"suppressWhen": "hasScope",
|
|
32
|
-
"optionSet": "scope",
|
|
33
|
-
"multiSelect": false
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"id": "database",
|
|
37
|
-
"headerKey": "questions.database.header",
|
|
38
|
-
"questionKey": "questions.database.question",
|
|
39
|
-
"requiresSignal": "hasDatabase",
|
|
40
|
-
"optionSet": "database",
|
|
41
|
-
"multiSelect": true
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"id": "uiType",
|
|
45
|
-
"headerKey": "questions.uiType.header",
|
|
46
|
-
"questionKey": "questions.uiType.question",
|
|
47
|
-
"requiresSignal": "hasUi",
|
|
48
|
-
"optionSet": "uiType",
|
|
49
|
-
"multiSelect": false
|
|
50
|
-
}
|
|
51
|
-
]
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Actuals, Estimation } from '../types/index.js';
|
|
2
|
-
/** Returns true when all token/cost actuals are zero (agent did not provide them). */
|
|
3
|
-
export declare function actualsAreMissing(actuals: Actuals): boolean;
|
|
4
|
-
/**
|
|
5
|
-
* Auto-fills zero token/cost fields in actuals using the spec's estimation data.
|
|
6
|
-
* Marks the result with `estimated: true` so reports can distinguish real vs auto values.
|
|
7
|
-
*/
|
|
8
|
-
export declare function autoFillActuals(actuals: Actuals, estimation: Estimation): Actuals;
|
|
9
|
-
/**
|
|
10
|
-
* Creates a default Actuals object from the spec's estimation when the agent
|
|
11
|
-
* did not provide actuals at all. Token/cost fields are auto-estimated.
|
|
12
|
-
*/
|
|
13
|
-
export declare function createDefaultActuals(estimation: Estimation): Actuals;
|
|
14
|
-
//# sourceMappingURL=actuals-estimator.d.ts.map
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// Rough tokens consumed per dev-hour of Claude Code work (empirical approximation)
|
|
2
|
-
const OPUS_TOKENS_PER_DEV_HOUR = 25_000;
|
|
3
|
-
const SONNET_TOKENS_PER_DEV_HOUR = 45_000;
|
|
4
|
-
// Blended input+output cost per token (Anthropic 2026 pricing)
|
|
5
|
-
const OPUS_COST_PER_TOKEN = 0.00004; // ~$40/1M blended
|
|
6
|
-
const SONNET_COST_PER_TOKEN = 0.000008; // ~$8/1M blended
|
|
7
|
-
/** Returns true when all token/cost actuals are zero (agent did not provide them). */
|
|
8
|
-
export function actualsAreMissing(actuals) {
|
|
9
|
-
return actuals.tokensOpus === 0 && actuals.tokensSonnet === 0 && actuals.apiCostUsd === 0;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Auto-fills zero token/cost fields in actuals using the spec's estimation data.
|
|
13
|
-
* Marks the result with `estimated: true` so reports can distinguish real vs auto values.
|
|
14
|
-
*/
|
|
15
|
-
export function autoFillActuals(actuals, estimation) {
|
|
16
|
-
if (!actualsAreMissing(actuals)) {
|
|
17
|
-
return actuals;
|
|
18
|
-
}
|
|
19
|
-
const hours = actuals.devHours > 0 ? actuals.devHours : estimation.devHours;
|
|
20
|
-
let tokensOpus = 0;
|
|
21
|
-
let tokensSonnet = 0;
|
|
22
|
-
if (estimation.recommendedModel === 'opus') {
|
|
23
|
-
tokensOpus = Math.round(hours * OPUS_TOKENS_PER_DEV_HOUR);
|
|
24
|
-
}
|
|
25
|
-
else if (estimation.recommendedModel === 'sonnet') {
|
|
26
|
-
tokensSonnet = Math.round(hours * SONNET_TOKENS_PER_DEV_HOUR);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
// mixed: 40% opus, 60% sonnet
|
|
30
|
-
tokensOpus = Math.round(hours * OPUS_TOKENS_PER_DEV_HOUR * 0.4);
|
|
31
|
-
tokensSonnet = Math.round(hours * SONNET_TOKENS_PER_DEV_HOUR * 0.6);
|
|
32
|
-
}
|
|
33
|
-
const apiCostUsd = tokensOpus * OPUS_COST_PER_TOKEN + tokensSonnet * SONNET_COST_PER_TOKEN;
|
|
34
|
-
const humanCostUsd = actuals.humanCostUsd > 0 ? actuals.humanCostUsd : hours * estimation.hourlyRate;
|
|
35
|
-
const totalCostUsd = apiCostUsd + humanCostUsd;
|
|
36
|
-
return {
|
|
37
|
-
...actuals,
|
|
38
|
-
tokensOpus,
|
|
39
|
-
tokensSonnet,
|
|
40
|
-
apiCostUsd: parseFloat(apiCostUsd.toFixed(4)),
|
|
41
|
-
humanCostUsd: parseFloat(humanCostUsd.toFixed(4)),
|
|
42
|
-
totalCostUsd: parseFloat(totalCostUsd.toFixed(4)),
|
|
43
|
-
estimated: true,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Creates a default Actuals object from the spec's estimation when the agent
|
|
48
|
-
* did not provide actuals at all. Token/cost fields are auto-estimated.
|
|
49
|
-
*/
|
|
50
|
-
export function createDefaultActuals(estimation) {
|
|
51
|
-
const base = {
|
|
52
|
-
devHours: estimation.devHours,
|
|
53
|
-
reviewHours: estimation.reviewHours,
|
|
54
|
-
tokensOpus: 0,
|
|
55
|
-
tokensSonnet: 0,
|
|
56
|
-
apiCostUsd: 0,
|
|
57
|
-
humanCostUsd: estimation.humanCostUsd,
|
|
58
|
-
totalCostUsd: 0,
|
|
59
|
-
completedAt: new Date().toISOString(),
|
|
60
|
-
notes: '',
|
|
61
|
-
};
|
|
62
|
-
return autoFillActuals(base, estimation);
|
|
63
|
-
}
|
|
64
|
-
//# sourceMappingURL=actuals-estimator.js.map
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
async function handler(ctx) {
|
|
2
|
-
const { specId, projectPath } = ctx;
|
|
3
|
-
if (!projectPath) {
|
|
4
|
-
return;
|
|
5
|
-
}
|
|
6
|
-
await import('../../living-specs/index.js')
|
|
7
|
-
.then(({ reconcileSpec }) => reconcileSpec(specId, projectPath))
|
|
8
|
-
.catch((err) => {
|
|
9
|
-
console.error('[planu] living-specs auto-reconcile failed:', err);
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
export const livingSpecsHook = {
|
|
13
|
-
id: 'living-specs',
|
|
14
|
-
triggers: ['implementing', 'done'],
|
|
15
|
-
requiresProjectPath: true,
|
|
16
|
-
label: 'Auto-reconcile living specs on implementing/done (SPEC-330)',
|
|
17
|
-
handler,
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=living-specs.hook.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ElicitRequirementsInput } from '../../types/spec-elicitation.js';
|
|
2
|
-
/** A flat map of question-id -> answer string, matching the shape of parseAnswers() output. */
|
|
3
|
-
export type ParsedAnswers = Record<string, string>;
|
|
4
|
-
/**
|
|
5
|
-
* Build default answers for an elicitation session without any user interaction.
|
|
6
|
-
* Called when mode === 'non-interactive' and answers is empty.
|
|
7
|
-
*/
|
|
8
|
-
export declare function buildDefaultAnswers(input: ElicitRequirementsInput): ParsedAnswers;
|
|
9
|
-
//# sourceMappingURL=non-interactive-defaults.d.ts.map
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// engine/elicitation/non-interactive-defaults.ts — SPEC-724: Default answers for non-interactive mode.
|
|
2
|
-
// Synthesises a complete ParsedAnswers deterministically from ElicitRequirementsInput,
|
|
3
|
-
// reusing the hasDatabase / isApi heuristics already present in elicit-requirements-handler.ts.
|
|
4
|
-
/**
|
|
5
|
-
* Build default answers for an elicitation session without any user interaction.
|
|
6
|
-
* Called when mode === 'non-interactive' and answers is empty.
|
|
7
|
-
*/
|
|
8
|
-
export function buildDefaultAnswers(input) {
|
|
9
|
-
const desc = input.description.toLowerCase();
|
|
10
|
-
const title = input.title;
|
|
11
|
-
const hasDatabase = desc.includes('data') || desc.includes('store') || desc.includes('database');
|
|
12
|
-
const isApi = desc.includes('api') || desc.includes('endpoint');
|
|
13
|
-
const answers = {
|
|
14
|
-
users: `End users of the ${title} feature`,
|
|
15
|
-
success: `The ${title} feature works correctly and meets the described requirements`,
|
|
16
|
-
scope: input.description,
|
|
17
|
-
edge_cases: 'Handle empty states, invalid input, and network errors gracefully',
|
|
18
|
-
performance: 'Response time under 2 seconds for typical operations',
|
|
19
|
-
};
|
|
20
|
-
if (hasDatabase) {
|
|
21
|
-
answers.data = `Data for ${title} is persisted reliably with proper validation and error handling`;
|
|
22
|
-
}
|
|
23
|
-
if (isApi) {
|
|
24
|
-
answers.api_contract = `API endpoints for ${title} follow RESTful conventions with proper status codes`;
|
|
25
|
-
}
|
|
26
|
-
return answers;
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=non-interactive-defaults.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ProjectKnowledge, InteractiveOption } from '../../types/index.js';
|
|
2
|
-
/** Payment provider options — puts DNA-detected provider first when found. */
|
|
3
|
-
export declare function buildPaymentProviderOptions(knowledge: ProjectKnowledge | null): InteractiveOption[];
|
|
4
|
-
export declare function buildBillingModelOptions(): InteractiveOption[];
|
|
5
|
-
export declare function buildTargetOptions(): InteractiveOption[];
|
|
6
|
-
export declare function buildScopeOptions(): InteractiveOption[];
|
|
7
|
-
export declare function buildDatabaseOptions(): InteractiveOption[];
|
|
8
|
-
export declare function buildUiTypeOptions(): InteractiveOption[];
|
|
9
|
-
//# sourceMappingURL=option-builder.d.ts.map
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// src/engine/elicitation/option-builder.ts
|
|
2
|
-
// SPEC-624: Builds InteractiveOption lists from project DNA instead of hardcoded arrays.
|
|
3
|
-
import { t } from '../../i18n/index.js';
|
|
4
|
-
const DNA_PROVIDERS = ['stripe', 'paypal', 'paddle', 'braintree', 'adyen'];
|
|
5
|
-
function capitalize(s) {
|
|
6
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
7
|
-
}
|
|
8
|
-
/** Payment provider options — puts DNA-detected provider first when found. */
|
|
9
|
-
export function buildPaymentProviderOptions(knowledge) {
|
|
10
|
-
const stack = knowledge?.stack ?? [];
|
|
11
|
-
const services = (knowledge?.externalServices ?? []).map((s) => s.toLowerCase());
|
|
12
|
-
const detected = DNA_PROVIDERS.filter((p) => stack.some((s) => s.toLowerCase().includes(p)) || services.some((s) => s.includes(p)));
|
|
13
|
-
const [firstProvider, ...restProviders] = detected;
|
|
14
|
-
if (firstProvider !== undefined) {
|
|
15
|
-
const firstLabel = `${capitalize(firstProvider)} (Recommended)`;
|
|
16
|
-
const rest = restProviders.slice(0, 2).map((p) => ({
|
|
17
|
-
label: capitalize(p),
|
|
18
|
-
description: t(`questions.payment.${p}Desc`),
|
|
19
|
-
}));
|
|
20
|
-
return [
|
|
21
|
-
{ label: firstLabel, description: t(`questions.payment.${firstProvider}Desc`) },
|
|
22
|
-
...rest,
|
|
23
|
-
{ label: t('questions.payment.other'), description: t('questions.payment.otherDesc') },
|
|
24
|
-
].slice(0, 4);
|
|
25
|
-
}
|
|
26
|
-
return [
|
|
27
|
-
{ label: t('questions.payment.stripe'), description: t('questions.payment.stripeDesc') },
|
|
28
|
-
{ label: t('questions.payment.paypal'), description: t('questions.payment.paypalDesc') },
|
|
29
|
-
{ label: t('questions.payment.paddle'), description: t('questions.payment.paddleDesc') },
|
|
30
|
-
{ label: t('questions.payment.other'), description: t('questions.payment.otherDesc') },
|
|
31
|
-
];
|
|
32
|
-
}
|
|
33
|
-
export function buildBillingModelOptions() {
|
|
34
|
-
return [
|
|
35
|
-
{ label: t('questions.payment.oneTime'), description: t('questions.payment.oneTimeDesc') },
|
|
36
|
-
{ label: t('questions.payment.recurring'), description: t('questions.payment.recurringDesc') },
|
|
37
|
-
{
|
|
38
|
-
label: t('questions.payment.usageBased'),
|
|
39
|
-
description: t('questions.payment.usageBasedDesc'),
|
|
40
|
-
},
|
|
41
|
-
{ label: t('questions.payment.freemium'), description: t('questions.payment.freemiumDesc') },
|
|
42
|
-
];
|
|
43
|
-
}
|
|
44
|
-
export function buildTargetOptions() {
|
|
45
|
-
return [
|
|
46
|
-
{ label: t('questions.target.frontend'), description: t('questions.target.frontendDesc') },
|
|
47
|
-
{ label: t('questions.target.backend'), description: t('questions.target.backendDesc') },
|
|
48
|
-
{ label: t('questions.target.fullstack'), description: t('questions.target.fullstackDesc') },
|
|
49
|
-
{ label: t('questions.target.infra'), description: t('questions.target.infraDesc') },
|
|
50
|
-
];
|
|
51
|
-
}
|
|
52
|
-
export function buildScopeOptions() {
|
|
53
|
-
return [
|
|
54
|
-
{ label: t('questions.scope.feature'), description: t('questions.scope.featureDesc') },
|
|
55
|
-
{ label: t('questions.scope.crossModule'), description: t('questions.scope.crossModuleDesc') },
|
|
56
|
-
{ label: t('questions.scope.trivial'), description: t('questions.scope.trivialDesc') },
|
|
57
|
-
{
|
|
58
|
-
label: t('questions.scope.architectural'),
|
|
59
|
-
description: t('questions.scope.architecturalDesc'),
|
|
60
|
-
},
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
|
-
export function buildDatabaseOptions() {
|
|
64
|
-
return [
|
|
65
|
-
{ label: t('questions.database.none'), description: t('questions.database.noneDesc') },
|
|
66
|
-
{ label: t('questions.database.schema'), description: t('questions.database.schemaDesc') },
|
|
67
|
-
{ label: t('questions.database.rls'), description: t('questions.database.rlsDesc') },
|
|
68
|
-
{ label: t('questions.database.rpc'), description: t('questions.database.rpcDesc') },
|
|
69
|
-
];
|
|
70
|
-
}
|
|
71
|
-
export function buildUiTypeOptions() {
|
|
72
|
-
return [
|
|
73
|
-
{
|
|
74
|
-
label: t('questions.uiType.newComponent'),
|
|
75
|
-
description: t('questions.uiType.newComponentDesc'),
|
|
76
|
-
},
|
|
77
|
-
{ label: t('questions.uiType.modify'), description: t('questions.uiType.modifyDesc') },
|
|
78
|
-
{
|
|
79
|
-
label: t('questions.uiType.serverAction'),
|
|
80
|
-
description: t('questions.uiType.serverActionDesc'),
|
|
81
|
-
},
|
|
82
|
-
{ label: t('questions.uiType.noUi'), description: t('questions.uiType.noUiDesc') },
|
|
83
|
-
];
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=option-builder.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Spec } from '../types/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Generate initial ## Progress content for a newly created spec.
|
|
4
|
-
*/
|
|
5
|
-
export declare function generateProgressContent(spec: Spec): string;
|
|
6
|
-
/**
|
|
7
|
-
* Generate updated ## Progress content reflecting a status change.
|
|
8
|
-
*/
|
|
9
|
-
export declare function generateProgressUpdate(spec: Spec, previousStatus: string, existingContent: string): string;
|
|
10
|
-
//# sourceMappingURL=progress-writer.d.ts.map
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate initial ## Progress content for a newly created spec.
|
|
3
|
-
*/
|
|
4
|
-
export function generateProgressContent(spec) {
|
|
5
|
-
const sections = [
|
|
6
|
-
{ title: 'Progress', content: buildHeader(spec) },
|
|
7
|
-
{ title: 'Status History', content: buildStatusHistory(spec) },
|
|
8
|
-
{ title: 'Metrics', content: buildMetrics(spec) },
|
|
9
|
-
];
|
|
10
|
-
return sections.map((s) => `## ${s.title}\n\n${s.content}`).join('\n\n---\n\n');
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Generate updated ## Progress content reflecting a status change.
|
|
14
|
-
*/
|
|
15
|
-
export function generateProgressUpdate(spec, previousStatus, existingContent) {
|
|
16
|
-
const timestamp = new Date().toISOString();
|
|
17
|
-
const entry = `| ${timestamp} | ${previousStatus} → ${spec.status} |`;
|
|
18
|
-
if (existingContent.includes('| Timestamp')) {
|
|
19
|
-
return existingContent.replace(/((?:\|[^\n]*\n)+)/, `$1${entry}\n`);
|
|
20
|
-
}
|
|
21
|
-
return generateProgressContent(spec);
|
|
22
|
-
}
|
|
23
|
-
function buildHeader(spec) {
|
|
24
|
-
const lines = [
|
|
25
|
-
`**Spec:** ${spec.id}`,
|
|
26
|
-
`**Title:** ${spec.title}`,
|
|
27
|
-
`**Status:** ${spec.status}`,
|
|
28
|
-
`**Created:** ${spec.createdAt}`,
|
|
29
|
-
`**Last Updated:** ${spec.updatedAt}`,
|
|
30
|
-
'',
|
|
31
|
-
`**Difficulty:** ${spec.difficulty} | **Risk:** ${spec.risk}`,
|
|
32
|
-
`**Target:** ${spec.target} | **Scope:** ${spec.scope}`,
|
|
33
|
-
];
|
|
34
|
-
if (spec.gitBranch) {
|
|
35
|
-
lines.push(`**Branch:** \`${spec.gitBranch}\``);
|
|
36
|
-
}
|
|
37
|
-
return lines.join('\n');
|
|
38
|
-
}
|
|
39
|
-
function buildStatusHistory(spec) {
|
|
40
|
-
return [
|
|
41
|
-
'| Timestamp | Transition |',
|
|
42
|
-
'|-----------|-----------|',
|
|
43
|
-
`| ${spec.createdAt} | → ${spec.status} |`,
|
|
44
|
-
].join('\n');
|
|
45
|
-
}
|
|
46
|
-
function buildMetrics(spec) {
|
|
47
|
-
const est = spec.estimation;
|
|
48
|
-
const lines = [
|
|
49
|
-
'| Metric | Estimated | Actual |',
|
|
50
|
-
'|--------|-----------|--------|',
|
|
51
|
-
`| Dev Hours | ${String(est.devHours)} | - |`,
|
|
52
|
-
`| Review Hours | ${String(est.reviewHours)} | - |`,
|
|
53
|
-
`| Total Cost (USD) | $${String(est.totalCostUsd)} | - |`,
|
|
54
|
-
];
|
|
55
|
-
if (spec.actuals) {
|
|
56
|
-
const act = spec.actuals;
|
|
57
|
-
lines[2] = `| Dev Hours | ${String(est.devHours)} | ${String(act.devHours)} |`;
|
|
58
|
-
lines[3] = `| Review Hours | ${String(est.reviewHours)} | ${String(act.reviewHours)} |`;
|
|
59
|
-
lines[4] = `| Total Cost (USD) | $${String(est.totalCostUsd)} | $${String(act.totalCostUsd)} |`;
|
|
60
|
-
}
|
|
61
|
-
return lines.join('\n');
|
|
62
|
-
}
|
|
63
|
-
//# sourceMappingURL=progress-writer.js.map
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export type InterviewDimension = 'technical' | 'ux' | 'edge-cases' | 'tradeoffs' | 'security' | 'performance' | 'integration';
|
|
2
|
-
export interface CoverageMap {
|
|
3
|
-
technical: boolean;
|
|
4
|
-
ux: boolean;
|
|
5
|
-
'edge-cases': boolean;
|
|
6
|
-
tradeoffs: boolean;
|
|
7
|
-
security: boolean;
|
|
8
|
-
performance: boolean;
|
|
9
|
-
integration: boolean;
|
|
10
|
-
}
|
|
11
|
-
export interface InterviewState {
|
|
12
|
-
sessionId: string;
|
|
13
|
-
coverageMap: CoverageMap;
|
|
14
|
-
completionPercent: number;
|
|
15
|
-
accumulatedAnswers: Record<string, string>;
|
|
16
|
-
nextDimension: InterviewDimension | null;
|
|
17
|
-
ready: boolean;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Analyzes answers to update which dimensions are covered.
|
|
21
|
-
* Merges with an existing coverage map if provided.
|
|
22
|
-
*/
|
|
23
|
-
export declare function updateCoverageFromAnswers(answers: Record<string, string>, existing?: CoverageMap): CoverageMap;
|
|
24
|
-
/**
|
|
25
|
-
* Returns the lowest-priority uncovered dimension, or null if all are covered.
|
|
26
|
-
*/
|
|
27
|
-
export declare function pickNextDimension(coverage: CoverageMap): InterviewDimension | null;
|
|
28
|
-
/**
|
|
29
|
-
* Generates a targeted follow-up question for a specific dimension.
|
|
30
|
-
* Takes existing answers into account to avoid repeating covered ground.
|
|
31
|
-
*/
|
|
32
|
-
export declare function generateDimensionQuestion(dimension: InterviewDimension, topic: string, answers: Record<string, string>): string;
|
|
33
|
-
/**
|
|
34
|
-
* Computes completion percentage based on how many dimensions are covered (0–100).
|
|
35
|
-
*/
|
|
36
|
-
export declare function computeCompletion(coverage: CoverageMap): number;
|
|
37
|
-
/**
|
|
38
|
-
* Returns true if the topic is too simple for interview mode.
|
|
39
|
-
* Delegates to isShortTopic from questions.ts.
|
|
40
|
-
*/
|
|
41
|
-
export declare function shouldSkipInterview(topic: string): boolean;
|
|
42
|
-
//# sourceMappingURL=interview-mode.d.ts.map
|