From d1fdc2553c965d84644293980f2273d522a768ae Mon Sep 17 00:00:00 2001 From: Alberto Arroyo Raygada Date: Tue, 18 Aug 2026 20:09:54 -0500 Subject: [PATCH 1/5] fix(harness): the deep audit counted client schemas in a directory that moved (#621) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit auditClientIngestion read `rulesets/schema`, a path that has not existed since rulesets/ moved under src/ (ADR-0048). exists() turned the moved directory into a silent zero, so the audit reported ZERO client schemas over a directory holding 50. Measured before and after on the same tree: Schemas 0 -> 50, the dimension's verdict PARCIAL -> SÓLIDO, and the global score 8/9 -> 9/9 dimensiones SÓLIDO. The score was wrong in the pessimistic direction. Salvaged from a commit that lived only in a stale local main and was about to be discarded. The narrative rewrite that travelled with it is deliberately not included — that is a claim about the product, not a defect fix. --- .harness/playbooks/sdlc-deep-audit.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.harness/playbooks/sdlc-deep-audit.mjs b/.harness/playbooks/sdlc-deep-audit.mjs index 627f50c7..c74f6e27 100644 --- a/.harness/playbooks/sdlc-deep-audit.mjs +++ b/.harness/playbooks/sdlc-deep-audit.mjs @@ -233,7 +233,10 @@ function auditEvaluationEngine() { function auditClientIngestion() { // Check for client manifest / schema that external projects use - const schemaDir = "rulesets/schema"; + // GT-707-era layout: `rulesets/` moved under `src/` (ADR-0048). This path was left + // behind, so `exists()` is false and the audit reports ZERO client schemas over a + // directory that holds 50 of them. + const schemaDir = "src/rulesets/schema"; const schemas = exists(schemaDir) ? walk(schemaDir) : []; const clientSchemaFiles = schemas.filter(f => f.endsWith(".schema.json") && !f.includes("node_modules")); From 6f67ceb4c2765af401a11d9d2514dbee2e91f274 Mon Sep 17 00:00:00 2001 From: Alberto Arroyo Raygada Date: Tue, 18 Aug 2026 20:10:20 -0500 Subject: [PATCH 2/5] fix(harness): the SDLC dimension was scored over a directory with a doubled segment (#622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit auditSdlc read `reference/core/sdlc/sdlc` — a doubled segment. That path has never existed; the SDLC surface is at reference/core/sdlc. exists() turned it into a silent zero, so the dimension was scored over no files at all. Measured before and after: Archivos SDLC 0 -> 174, datos estructurados 5 -> 7, playbooks 0 -> 22. Unlike #621 this moves no verdict: the dimension was already SÓLIDO on Fases 5/5 and Gates 5/5, computed elsewhere. That is why it survived — the zero never hurt the score, so an evidence line reading 'Archivos SDLC: 0' sat next to a green verdict. A wrong number that costs nothing is the one nobody reports. Left out on purpose, same function: '0 markdown fases' is still 0, because the filter matches phase-0[1-5] while the files are phase-1, phase-1.1, phase-2, phase-3, phase-4. Whether phase-1.1 counts as a phase is a question about the model, not about a regex. --- .harness/playbooks/sdlc-deep-audit.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.harness/playbooks/sdlc-deep-audit.mjs b/.harness/playbooks/sdlc-deep-audit.mjs index c74f6e27..75a094e9 100644 --- a/.harness/playbooks/sdlc-deep-audit.mjs +++ b/.harness/playbooks/sdlc-deep-audit.mjs @@ -100,7 +100,10 @@ function auditCorpus() { // ── 2. MODELO SDLC EJECUTABLE ──────────────────────────────────────── function auditSdlc() { - const sdlcDir = "reference/core/sdlc/sdlc"; + // The segment was doubled: the SDLC surface lives at `reference/core/sdlc`, and + // `.../sdlc/sdlc` has never existed. `exists()` made that a silent zero rather than an + // error, so this dimension was scored over no files at all. + const sdlcDir = "reference/core/sdlc"; const files = exists(sdlcDir) ? walk(sdlcDir) : []; const phaseFiles = files.filter(f => f.match(/phase-0[1-5]/i) || f.match(/fase-0[1-5]/i)); From 144fce23386722df71e51a03ff25a8adf61b1812 Mon Sep 17 00:00:00 2001 From: Alberto Arroyo Raygada Date: Tue, 18 Aug 2026 20:59:57 -0500 Subject: [PATCH 3/5] docs(sdlc): retire Knowledge-First Discovery and the KDD concept from the Core (#623) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Advances GT-708 — the Tracker half is beyondnetcode/evolith_tracker#153. Two things travelled under three letters and neither was ever built: Phase 1.1 (an optional subphase with its own readiness gate and seven artifact templates) and KDD = Knowledge-Driven Development (an optional section INSIDE the PRD, per-tenant, from the 2026-07-04 owner session). Owner decision: neither survives, in either repo. Measured before deleting anything: five gates for phases 1..5; none of the seven KDD artifacts among the 33 registered; zero TypeScript files; 31 CLI commands with zero mentions (--phase discovery maps to phase 1 ENTIRE); zero in MCP; no Tracker screen or entity; no KDD section in prd.schema.json. The prose was load-bearing anyway: phase-1-business-signoff made 'Phase 1.1 adoption level has been declared' a PRECONDITION for opening Gate 1, with 'a FAIL result blocks this gate'. A gate nothing implements was blocking a gate everything implements. 16 files deleted, the Gate 1 precondition and its three KDD clauses removed, the Subphase 01.1 tables and index rows removed, D-004/L-009 rewritten to what survives them. ADR-0127 carries the retirement and AMENDS ADR-0103 rather than editing it. CHANGELOG.md and ADR-0103 keep their KDD text on purpose. Three pinned corpus counts move by one because the ADR itself owes a generated conformance ruleset — the corpus grows by one rule nothing can run, to record the removal of a concept nothing could run either. --- .harness/agents/discovery-agents.es.md | 2 +- .harness/agents/discovery-agents.md | 2 +- AGENTS.es.md | 2 +- AGENTS.md | 2 +- ...127-retire-knowledge-first-discovery.es.md | 97 ++++++ .../0127-retire-knowledge-first-discovery.md | 95 ++++++ .../gaps/gap-reference-catalog.es.md | 36 +++ .../gaps/gap-reference-catalog.md | 36 +++ .../control-center/gaps/gap-tracking.es.md | 3 +- .../core/control-center/gaps/gap-tracking.md | 3 +- .../maturity-reports/executive-summary.es.md | 16 +- .../maturity-reports/executive-summary.md | 16 +- .../maturity-reconciliation.json | 8 +- .../core/foundations/agent-skills/po.es.md | 2 +- reference/core/foundations/agent-skills/po.md | 2 +- .../agent-skills/tracker-discovery-flow.es.md | 10 +- .../agent-skills/tracker-discovery-flow.md | 10 +- .../agent-skills/tracker-intake-flow.es.md | 9 +- .../agent-skills/tracker-intake-flow.md | 9 +- .../foundations/agent-skills/winston.es.md | 4 +- .../core/foundations/agent-skills/winston.md | 4 +- ...oduct-initiative-governance-redesign.es.md | 2 + .../product-initiative-governance-redesign.md | 2 + ...00-architecture-planning-gate-intake.es.md | 2 - .../00-architecture-planning-gate-intake.md | 2 - reference/core/sdlc/01-playbooks/README.es.md | 1 - reference/core/sdlc/01-playbooks/README.md | 1 - .../phase-1-business-signoff.es.md | 7 +- .../01-playbooks/phase-1-business-signoff.md | 7 +- .../phase-1.1-knowledge-first-discovery.es.md | 158 ---------- .../phase-1.1-knowledge-first-discovery.md | 158 ---------- .../phase-2-design-baseline.es.md | 4 +- .../01-playbooks/phase-2-design-baseline.md | 4 +- .../sdlc/04-artifact-templates/README.es.md | 4 +- .../core/sdlc/04-artifact-templates/README.md | 2 +- .../assumptions-questions-log-template.es.md | 205 ------------- .../assumptions-questions-log-template.md | 205 ------------- .../capability-map-template.es.md | 225 -------------- .../capability-map-template.md | 225 -------------- .../discovery-context-pack-template.es.md | 239 --------------- .../discovery-context-pack-template.md | 239 --------------- .../discovery-knowledge-brief-template.es.md | 279 ----------------- .../discovery-knowledge-brief-template.md | 279 ----------------- .../discovery-readiness-gate-template.es.md | 285 ------------------ .../discovery-readiness-gate-template.md | 285 ------------------ .../epic-candidate-matrix-template.es.md | 227 -------------- .../epic-candidate-matrix-template.md | 227 -------------- .../story-seed-bank-template.es.md | 230 -------------- .../story-seed-bank-template.md | 230 -------------- .../sdlc/sdlc-evolith-artifact-mapping.es.md | 22 +- .../sdlc/sdlc-evolith-artifact-mapping.md | 22 +- .../validators/rule-corpus-triage.spec.ts | 17 +- ...retired-and-with-it-the-kdd-con.rules.json | 28 ++ src/rulesets/standards/iso-5055-mapping.csv | 1 + src/rulesets/standards/iso-5055-mapping.json | 37 ++- .../native-evaluability-snapshot.json | 11 +- 56 files changed, 416 insertions(+), 3824 deletions(-) create mode 100644 reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md create mode 100644 reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md delete mode 100644 reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.es.md delete mode 100644 reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.md delete mode 100644 reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.md delete mode 100644 reference/core/sdlc/04-artifact-templates/capability-map-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/capability-map-template.md delete mode 100644 reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.md delete mode 100644 reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.md delete mode 100644 reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.md delete mode 100644 reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.md delete mode 100644 reference/core/sdlc/04-artifact-templates/story-seed-bank-template.es.md delete mode 100644 reference/core/sdlc/04-artifact-templates/story-seed-bank-template.md create mode 100644 src/rulesets/adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json diff --git a/.harness/agents/discovery-agents.es.md b/.harness/agents/discovery-agents.es.md index 75f6364e..a7915121 100644 --- a/.harness/agents/discovery-agents.es.md +++ b/.harness/agents/discovery-agents.es.md @@ -2,7 +2,7 @@ > **Navegación Bilingüe:** [English Version](./discovery-agents.md) -Los siguientes agentes soportan el Architecture Planning Gate (Fase 00) y la subfase Knowledge-First Discovery (01.1). Cada agente sigue la regla de Calidad de Actualización de Agente: alcance, entradas, salidas, restricciones, handoff, checklist de validación y formato de auditoría. +Los siguientes agentes soportan el Architecture Planning Gate (Fase 00). Cada agente sigue la regla de Calidad de Actualización de Agente: alcance, entradas, salidas, restricciones, handoff, checklist de validación y formato de auditoría. | Agente | Alcance | Entradas | Salidas | Handoff A | |--------|---------|----------|---------|-----------| diff --git a/.harness/agents/discovery-agents.md b/.harness/agents/discovery-agents.md index a1dc96e9..07239334 100644 --- a/.harness/agents/discovery-agents.md +++ b/.harness/agents/discovery-agents.md @@ -2,7 +2,7 @@ > **Bilingual Navigation:** [Versión en Español](./discovery-agents.es.md) -The following agents support the Architecture Planning Gate (Phase 00) and the Knowledge-First Discovery subphase (01.1). Each agent follows the Agent Update Quality rule: scope, inputs, outputs, constraints, handoff, validation checklist, and audit output format. +The following agents support the Architecture Planning Gate (Phase 00). Each agent follows the Agent Update Quality rule: scope, inputs, outputs, constraints, handoff, validation checklist, and audit output format. | Agent | Scope | Inputs | Outputs | Handoff To | |-------|-------|--------|---------|------------| diff --git a/AGENTS.es.md b/AGENTS.es.md index 7f55b162..12d4a7f8 100644 --- a/AGENTS.es.md +++ b/AGENTS.es.md @@ -102,7 +102,7 @@ El enrutador frontal principal para el ecosistema BMAD de Evolith. Todas las int ## Agentes de Intake y Discovery (Fases 00 y 01.1) -Los agentes que soportan el Architecture Planning Gate (Fase 00) y la subfase Knowledge-First Discovery (01.1) han sido extraídos a un archivo dedicado para optimizar la carga de contexto. +Los agentes que soportan el Architecture Planning Gate (Fase 00) han sido extraídos a un archivo dedicado para optimizar la carga de contexto. > **Ver:** [`.harness/agents/discovery-agents.es.md`](./.harness/agents/discovery-agents.es.md) para la lista completa de agentes, alcances, entradas, salidas y handoffs. diff --git a/AGENTS.md b/AGENTS.md index e2a62ed5..e514ea81 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -114,7 +114,7 @@ The primary frontend router for the Evolith BMAD ecosystem. All raw user intents ## Intake and Discovery Agents (Phases 00 and 01.1) -The agents supporting the Architecture Planning Gate (Phase 00) and the Knowledge-First Discovery subphase (01.1) have been extracted to a dedicated file to optimize context loading. +The agents supporting the Architecture Planning Gate (Phase 00) have been extracted to a dedicated file to optimize context loading. > **See:** [`.harness/agents/discovery-agents.md`](./.harness/agents/discovery-agents.md) for the full list of agents, scopes, inputs, outputs, and handoffs. diff --git a/reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md b/reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md new file mode 100644 index 00000000..fd3da45a --- /dev/null +++ b/reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md @@ -0,0 +1,97 @@ +# ADR-0127: Se retira Knowledge-First Discovery y, con ella, el concepto KDD + +> **Navegación Bilingüe:** [English](./0127-retire-knowledge-first-discovery.md) · Español (este documento) + +| Campo | Valor | +|---|---| +| **Estado** | Aceptado | +| **Fecha** | 2026-08-18 | +| **Decisores** | Product Owner (decisión del dueño) · Architecture Board | +| **Historia técnica** | Una subfase-gate, siete plantillas de artefacto y un módulo opcional del PRD por tenant, descritos en prosa en dos repositorios e implementados en ninguno | + + +> **Estado de implementación en este repositorio: completo** (2026-08-18). +> No había código que quitar: el barrido es documental por construcción, que es justamente el +> hallazgo sobre el que se apoya este ADR. Verificado por búsqueda tras el cambio — `KDD` y +> `knowledge-first` solo sobreviven en `CHANGELOG.md` y en el `ADR-0103`, ambos a propósito, como +> registros de lo que era cierto cuando se escribieron. + +## Status + +Aceptado — 2026-08-18. En vigor. + +## Contexto + +Bajo las mismas tres letras viajaban dos cosas distintas, y ninguna llegó a construirse. + +**Fase 1.1 — Knowledge-First Discovery.** Una subfase opcional y progresiva dentro de la Fase 1, +escalando de Nivel 1 a Nivel 4, con su propia compuerta de preparación y siete plantillas de +artefacto: Discovery Knowledge Brief, Assumptions & Questions Log, Discovery Context Pack, +Capability Map, Epic Candidate Matrix, Story Seed Bank y Discovery Readiness Gate. + +**KDD — Knowledge-Driven Development.** Una lectura posterior y más estrecha, capturada en la +sesión guiada por el dueño del 2026-07-04 (`tracker-intake-flow` L-009, `tracker-discovery-flow` +D-004): no una subfase, sino una *sección opcional dentro del PRD*, activable por tenant vía +feature-override, con el PRD como piso canónico no-overrideable. + +**Ninguna existía en nada ejecutable, y esto se midió en vez de suponerse:** + +| superficie | ¿KDD presente? | +|---|---| +| Rulesets del Core (`phase-gates.rules.json`, `artifact-registry.json`) | **no** — cinco gates, fases 1..5; ninguno de los siete artefactos KDD está entre los 33 registrados | +| Código del Core (TypeScript) | **no** — cero ficheros con `KDD`, `knowledge-first`, `knowledgeBrief`, `discoveryReadiness`, `storySeed`, `epicCandidate` | +| CLI | **no** — 31 comandos, cero menciones. `--phase discovery` mapea a la **fase 1 entera** (`phase-id.ts`: `f1: 'discovery'`), no a la 1.1 | +| Servidor MCP | **no** — cero ficheros | +| Código y UI del Tracker | **no** — sin pantalla ni entidad; el menú «Discovery» cuelga Strategic intake, Opportunities e Initiatives | +| `prd.schema.json` | **sin sección KDD** — la decisión D-004 nunca llegó a schema | + +Lo que sí existía era prosa, y tenía dientes: el playbook de la Fase 1 convertía *«el nivel de +adopción de la Fase 1.1 ha sido declarado»* en **precondición para abrir el Gate 1**, y tres filas +de su tabla de evidencia llevaban cláusulas condicionadas a niveles de KDD. Una compuerta que nadie +implementa estaba bloqueando, sobre el papel, una compuerta que todo el mundo implementa. + +## Decisión + +**Ambas lecturas se retiran. Evolith Core y Evolith Tracker dejan de manejar el concepto KDD en +cualquier forma**, y la información relacionada se elimina en vez de archivarse en su sitio. + +1. El playbook de la Fase 1.1 y las siete plantillas de artefacto se **borran** (16 ficheros, EN y ES). +2. La precondición de la Fase 1 y toda cláusula condicionada a KDD en su tabla de evidencia se + **eliminan**; el Gate 1 enuncia ahora sus requisitos sin referirse a ninguna subfase. +3. La tabla `Subfase 01.1` del mapeo de artefactos, la fila del índice de playbooks y las + referencias a Story Seeds / Epic Candidates en el playbook de Fase 2 y en el índice de plantillas + se **eliminan**. +4. Las filas de decisión D-004 / L-009 se **reescriben** a lo que las sobrevive: el PRD es el piso + canónico y el Gate 1 lo exige siempre. La cláusula de la sección KDD opcional desaparece. +5. `CHANGELOG.md` y el `ADR-0103` se **dejan intactos**, a propósito. Son registros de lo que era + cierto cuando se escribieron; editarlos para ocultar un concepto retirado falsificaría la + historia que este repositorio conserva deliberadamente. + +**El `ADR-0103` queda enmendado por este ADR, no reabierto.** Aquella decisión situó el Architecture +Planning Gate *antes* de Knowledge-First Discovery y descartó embeber la lógica de planificación +*dentro* de la Fase 1.1. Su razonamiento se mantiene; lo que desapareció es su vecino. Leído hoy: el +Planning Gate precede directamente a la **Fase 1 (Business Sign-Off)**, y la opción que descartó +queda sin objeto, no equivocada. + +## Consecuencias + +**Bueno.** El modelo de cinco fases es ya el mismo en la prosa y en los datos — cinco fases, cinco +gates, y ninguna sexta cosa descrita en ningún otro sitio. El Gate 1 deja de depender de una subfase +que nadie puede ejecutar, así que un satélite que lea el playbook puede de verdad satisfacer sus +precondiciones. Unos cuarenta documentos dejan de describir una capacidad que el producto no tiene. + +**Costes, dichos con claridad.** Las siete plantillas eran trabajo real y algunas —el Assumptions & +Questions Log, el Capability Map— son útiles al margen de KDD. Son recuperables desde el historial; +nada aquí afirma que carecieran de valor, solo que Evolith no las gobernará. + +**El riesgo que este ADR acepta.** La captura de conocimiento en Discovery queda sin modelar. Si +vuelve, tiene que volver como schema y como regla antes que como playbook: el fallo que registra +esta fila es exactamente el de un concepto de gobierno que vivió meses solo en prosa, fue citado +como precondición por una compuerta real y no se ejecutó ni una vez. + +## ADRs Relacionados + +- [ADR-0103](./0103-architecture-planning-gate-intake.es.md) — enmendado por este ADR: el Planning + Gate precede ahora directamente a la Fase 1. +- [ADR-0101](./0101-core-stateless-evaluation-engine.es.md) — el Core es un motor de evaluación sin + estado; los artefactos que no puede evaluar no son asunto del Core. diff --git a/reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md b/reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md new file mode 100644 index 00000000..ec769e04 --- /dev/null +++ b/reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md @@ -0,0 +1,95 @@ +# ADR-0127: Knowledge-First Discovery Is Retired, and With It the KDD Concept + +> **Bilingual Navigation:** English (this document) · [Versión en Español](./0127-retire-knowledge-first-discovery.es.md) + +| Field | Value | +|---|---| +| **Status** | Accepted | +| **Date** | 2026-08-18 | +| **Deciders** | Product Owner (owner decision) · Architecture Board | +| **Technical story** | A subphase gate, seven artifact templates and a per-tenant PRD module, all described in prose across two repositories and implemented in none of them | + + +> **Implementation status in this repository: full** (2026-08-18). +> There was no code to remove: the sweep is documentary by construction, which is the finding +> this ADR is built on. Verified by search after the change — `KDD` and `knowledge-first` survive +> only in `CHANGELOG.md` and in `ADR-0103`, both deliberately, as records of what was true when +> they were written. + +## Status + +Accepted — 2026-08-18. In force. + +## Context + +Two different things travelled under the same three letters, and neither was ever built. + +**Phase 1.1 — Knowledge-First Discovery.** An optional, progressive subphase inside Phase 1, +scaling from Level 1 to Level 4, with its own readiness gate and seven artifact templates: +Discovery Knowledge Brief, Assumptions & Questions Log, Discovery Context Pack, Capability Map, +Epic Candidate Matrix, Story Seed Bank, Discovery Readiness Gate. + +**KDD — Knowledge-Driven Development.** A later and narrower reading, captured in the +owner-guided session of 2026-07-04 (`tracker-intake-flow` L-009, `tracker-discovery-flow` D-004): +not a subphase but an *optional section inside the PRD*, activated per tenant by feature-override, +with the PRD itself as the non-overrideable canonical floor. + +**Neither existed anywhere executable, and this was measured rather than assumed:** + +| surface | KDD present? | +|---|---| +| Core rulesets (`phase-gates.rules.json`, `artifact-registry.json`) | **no** — five gates, phases 1..5; none of the seven KDD artifacts is registered among the 33 | +| Core code (TypeScript) | **no** — zero files match `KDD`, `knowledge-first`, `knowledgeBrief`, `discoveryReadiness`, `storySeed`, `epicCandidate` | +| CLI | **no** — 31 commands, zero mentions. `--phase discovery` maps to **phase 1 entire** (`phase-id.ts`: `f1: 'discovery'`), not to 1.1 | +| MCP server | **no** — zero files | +| Tracker code and UI | **no** — no screen, no entity; the "Discovery" menu carries Strategic intake, Opportunities and Initiatives | +| `prd.schema.json` | **no KDD section** — the D-004 decision was never schema'd | + +What did exist was prose, and it had teeth: the Phase 1 playbook made *"Phase 1.1 adoption level +has been declared"* a **precondition for opening Gate 1**, and three rows of its evidence table +carried conditional clauses keyed to KDD levels. A gate nothing implements was blocking a gate +everything implements, on paper. + +## Decision + +**Both readings are retired. Evolith Core and Evolith Tracker no longer carry the KDD concept in +any form**, and the information related to it is removed rather than archived in place. + +1. The Phase 1.1 playbook and the seven artifact templates are **deleted** (16 files, EN and ES). +2. The Phase 1 precondition and every KDD-conditional clause in its evidence table are **removed**; + Gate 1 now states its own requirements without reference to a subphase. +3. The `Subphase 01.1` table in the artifact mapping, the playbook index row, and the + Story-Seed/Epic-Candidate references in the Phase 2 playbook and template index are **removed**. +4. The D-004 / L-009 decision rows are **rewritten** to what survives them: the PRD is the + canonical floor and Gate 1 always requires it. The optional-KDD-section clause is gone. +5. `CHANGELOG.md` and `ADR-0103` are **left untouched**, on purpose. They are records of what was + true when written; editing them to hide a retired concept would falsify the history this + repository keeps deliberately. + +**`ADR-0103` is amended by this ADR, not reopened.** That decision placed the Architecture Planning +Gate *before* Knowledge-First Discovery and rejected embedding planning logic *into* Phase 1.1. Its +reasoning stands; only its neighbour is gone. Read today: the Planning Gate precedes **Phase 1 +(Business Sign-Off)** directly, and the option it rejected is moot rather than wrong. + +## Consequences + +**Good.** The five-phase model is now the same in prose and in data — five phases, five gates, and +no sixth thing described nowhere else. Gate 1 stops depending on a subphase nobody can execute, so +a satellite reading the playbook can actually satisfy its preconditions. Roughly forty documents +stop describing a capability the product does not have. + +**Costs, stated plainly.** The seven templates were real work and some of them — the Assumptions & +Questions Log, the Capability Map — are useful independently of KDD. They are recoverable from +history; nothing here claims they were worthless, only that Evolith will not govern them. + +**The risk this ADR accepts.** Discovery-phase knowledge capture is now unmodelled. If it returns, +it must return as a schema and a rule before it returns as a playbook — the failure this row +records is precisely a governance concept that lived for months entirely in prose, was cited as a +precondition by a real gate, and was never once executed. + +## Related ADRs + +- [ADR-0103](./0103-architecture-planning-gate-intake.md) — amended by this ADR: the Planning Gate + now precedes Phase 1 directly. +- [ADR-0101](./0101-core-stateless-evaluation-engine.md) — the Core is a stateless evaluation + engine; artifacts it cannot evaluate are not Core concerns. diff --git a/reference/core/control-center/gaps/gap-reference-catalog.es.md b/reference/core/control-center/gaps/gap-reference-catalog.es.md index 5f8440fa..44747e72 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.es.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.es.md @@ -10012,3 +10012,39 @@ Los dos se arreglaron de forma estructural y no como correcciones: el rethrow no **Medido sobre un binario real:** `--help` código 0, `--version` `1.3.2`, `init --runtime nodejs --monorepo none --arch clean` código 0 escribiendo un satélite. `tsc -b` limpio; 106 suites / 1485 tests en verde. +#### GT-708 + +**Título:** KDD existía solo en prosa, en dos repositorios, y una compuerta real dependía de él + +- **Propósito:** Que el modelo de cinco fases se lea igual en los documentos que en los datos, y que el Gate 1 deje de depender de una subfase que nada puede ejecutar. +- **Evidencia, medida el 2026-08-18 en todas las superficies ejecutables:** + + | superficie | ¿KDD presente? | + |---|---| + | Rulesets del Core (`phase-gates.rules.json`, `artifact-registry.json`) | **no** — cinco gates para las fases 1..5; ninguno de los siete artefactos KDD entre los 33 registrados | + | Código del Core (TypeScript) | **no** — cero ficheros con `KDD`, `knowledge-first`, `knowledgeBrief`, `discoveryReadiness`, `storySeed`, `epicCandidate` | + | CLI | **no** — 31 comandos, cero menciones; `--phase discovery` mapea a la **fase 1 entera** (`phase-id.ts`: `f1: 'discovery'`) | + | Servidor MCP | **no** — cero ficheros | + | Código y UI del Tracker | **no** — sin pantalla ni entidad; el menú «Discovery» cuelga Strategic intake, Opportunities, Initiatives | + | `prd.schema.json` | **sin sección KDD** — la decisión `D-004` nunca llegó a schema | + +- **Dos cosas distintas bajo tres letras, y esta fila existe porque se confundieron con una.** La **Fase 1.1 — Knowledge-First Discovery** es una subfase opcional y progresiva con su propia compuerta de preparación y siete plantillas. **KDD — Knowledge-Driven Development** es una lectura posterior y más estrecha, de la sesión guiada por el dueño del 2026-07-04 (`tracker-intake-flow` L-009, `tracker-discovery-flow` D-004): una sección opcional *dentro del PRD*, activable por tenant vía feature-override. El primer análisis de esta fila trató 45 ficheros como un solo concepto; la respuesta del dueño —que KDD se retira de Core y Tracker en cualquier forma— lo resolvió, pero la distinción queda registrada porque el próximo lector chocará con la misma colisión. +- **Aun así, la prosa tenía dientes.** `phase-1-business-signoff.es.md` convertía *«el nivel de adopción de la Fase 1.1 ha sido declarado»* en **precondición para abrir el Gate 1**, con *«un resultado FAIL bloquea esta compuerta»*, y tres filas de su tabla de evidencia llevaban cláusulas condicionadas a Niveles 1+ y 2+ de KDD. El `ADR-0103` (Aceptado 2026-07-02) situaba el Architecture Planning Gate *antes* de Knowledge-First Discovery y descartaba embeber la planificación en la Fase 1.1 — una decisión aceptada apoyada en un vecino que no existe. +- **Casos de uso:** + - Un satélite lee el playbook de la Fase 1 y no puede satisfacer una precondición que nombra una subfase sin gate, sin schema y sin comando. + - Alguien implementa `REQ-DIS-13` (Tracker) o las siete plantillas, construyendo una capacidad que el dueño decidió no tener. + - Un auditor pregunta cuántas fases gobierna Evolith y obtiene cinco de los datos y seis de los documentos. +- **Impacto:** El modelo documentado y el ejecutable discrepaban en cuántas fases existen, y la discrepancia era estructural: vivía en las precondiciones de la única compuerta por la que pasa toda iniciativa. +- **Resultado esperado:** KDD ausente de todas las superficies de ambos repositorios, con la retirada registrada como decisión y no como borrado silencioso — y `CHANGELOG` y `ADR-0103` intactos a propósito, porque son registros de lo que era cierto cuando se escribieron. +- **Ficheros afectados:** `reference/core/sdlc/01-playbooks/`, `reference/core/sdlc/04-artifact-templates/`, `reference/core/foundations/agent-skills/`, `reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md` +- **Componente:** `Governance` · **Criticidad:** P2 · **Complejidad:** M +- **Principal:** `M` · **Interest:** `MED` · **Basis:** `estimate` +- **Procedencia:** Registrado el 2026-08-18. Encontrado tirando de un hilo: el playbook de auditoría profunda reportaba `0 markdown fases`, que resultó ser un desajuste de cero a la izquierda (`phase-0[1-5]` frente a `phase-1`, `phase-1.1`) — y preguntar si `phase-1.1` debía contar destapó que nada la cuenta porque nada la implementa. +- **Criterios de aceptación:** + - [x] `KDD` y `knowledge-first` devuelven cero coincidencias en ambos repositorios, salvo en `CHANGELOG.md` y el `ADR-0103`, que quedan como registros históricos a propósito. **CUMPLIDO para el Core.** Tras el barrido los tokens sobreviven en exactamente seis ficheros: `CHANGELOG.md`, el `ADR-0103` (EN/ES), el `ADR-0127` (EN/ES) —la propia retirada— más el tablero de gaps y el aviso de corrección del documento de rediseño. La mitad del Tracker es su propio pull request en `evolith_tracker`. + - [x] Las precondiciones y la tabla de evidencia del Gate 1 se sostienen solas, sin referencia a ninguna subfase ni a niveles de KDD. **CUMPLIDO** — desapareció la viñeta *«el nivel de adopción de la Fase 1.1 ha sido declarado… un resultado FAIL bloquea esta compuerta»*, y las tres filas de evidencia (Discovery Canvas, Ballpark Estimation, MoSCoW) ya no llevan sus cláusulas `Si se aplicó Fase 1.1 Nivel ≥ n`. + - [x] La retirada es un **ADR**, y el `ADR-0103` queda enmendado por él en vez de editado — una decisión aceptada se supersede, no se reescribe. **CUMPLIDO** — el `ADR-0127` lleva la decisión y enuncia la enmienda: el Planning Gate precede ahora directamente a la Fase 1, y la opción que el `ADR-0103` descartó queda sin objeto, no equivocada. El propio `ADR-0103` queda intacto. + - [ ] Los `REQ-DIS-12` y `REQ-DIS-13` del Tracker se van con él; un requisito numerado que queda en pie es una instrucción de construir la cosa. **ABIERTO — la mitad del Tracker es un pull request aparte en `evolith_tracker`**, donde los ficheros, el tablero y los guards son otros. Sin marcar a propósito: esta fila no está hecha hasta que lo estén los dos repositorios. + - [x] **FALSABILIDAD:** ningún enlace de ninguno de los dos repositorios resuelve a un fichero KDD borrado, comprobado tras el barrido y no supuesto desde la lista de borrados. **CUMPLIDO para el Core** — buscar los ocho nombres borrados en todos los markdown no devuelve nada fuera del `ADR-0127` y del aviso de corrección del documento de rediseño, que los nombran como retirados en vez de enlazarlos. +- **Estado:** `EN-PROGRESO` + diff --git a/reference/core/control-center/gaps/gap-reference-catalog.md b/reference/core/control-center/gaps/gap-reference-catalog.md index 98fd5a65..34c0ff3a 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.md @@ -10107,3 +10107,39 @@ Both were fixed structurally rather than corrected: the rethrow now names BOTH f **Measured on a real binary:** `--help` exit 0, `--version` `1.3.2`, `init --runtime nodejs --monorepo none --arch clean` exit 0 writing a satellite. `tsc -b` clean; 106 suites / 1485 tests green. +#### GT-708 + +**Title:** KDD existed only in prose, in two repositories, and a real gate depended on it + +- **Purpose:** Make the five-phase model read the same in the documents as in the data, and stop Gate 1 depending on a subphase nothing can execute. +- **Evidence, measured 2026-08-18 across every executable surface:** + + | surface | KDD present? | + |---|---| + | Core rulesets (`phase-gates.rules.json`, `artifact-registry.json`) | **no** — five gates for phases 1..5; none of the seven KDD artifacts among the 33 registered | + | Core code (TypeScript) | **no** — zero files matching `KDD`, `knowledge-first`, `knowledgeBrief`, `discoveryReadiness`, `storySeed`, `epicCandidate` | + | CLI | **no** — 31 commands, zero mentions; `--phase discovery` maps to **phase 1 entire** (`phase-id.ts`: `f1: 'discovery'`) | + | MCP server | **no** — zero files | + | Tracker code and UI | **no** — no screen, no entity; the "Discovery" menu carries Strategic intake, Opportunities, Initiatives | + | `prd.schema.json` | **no KDD section** — the `D-004` decision never reached a schema | + +- **Two different things under three letters, and the row exists because they were confused for one.** **Phase 1.1 — Knowledge-First Discovery** is an optional, progressive subphase with its own readiness gate and seven artifact templates. **KDD — Knowledge-Driven Development** is a later, narrower reading from the owner-guided session of 2026-07-04 (`tracker-intake-flow` L-009, `tracker-discovery-flow` D-004): an optional section *inside the PRD*, activated per tenant by feature-override. The first analysis of this row treated 45 files as one concept; the owner's answer — that KDD is retired in both Core and Tracker in any form — resolved it, but the distinction is recorded because a future reader will hit the same collision. +- **The prose had teeth.** `phase-1-business-signoff.md` made *"Phase 1.1 (Knowledge-First Discovery) adoption level has been declared"* a **precondition for opening Gate 1**, with *"a FAIL result blocks this gate"*, and three rows of its evidence table carried clauses keyed to KDD Levels 1+ and 2+. `ADR-0103` (Accepted 2026-07-02) positioned the Architecture Planning Gate *before* Knowledge-First Discovery and rejected embedding planning into Phase 1.1 — an accepted decision resting on a neighbour that does not exist. +- **Use cases:** + - A satellite reads the Phase 1 playbook and cannot satisfy a precondition that names a subphase with no gate, no schema and no command. + - Someone implements `REQ-DIS-13` (Tracker) or the seven templates, building a capability the owner decided not to have. + - An auditor asks which phases Evolith governs and gets five from the data and six from the documents. +- **Impact:** The documented model and the executable model disagreed about how many phases exist, and the disagreement was load-bearing: it sat in the preconditions of the one gate every initiative must pass. +- **Expected outcome:** KDD absent from every surface of both repositories, with the retirement recorded as a decision rather than as a silent deletion — and `CHANGELOG` and `ADR-0103` deliberately untouched, because they are records of what was true when written. +- **Affected files:** `reference/core/sdlc/01-playbooks/`, `reference/core/sdlc/04-artifact-templates/`, `reference/core/foundations/agent-skills/`, `reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md` +- **Component:** `Governance` · **Criticality:** P2 · **Complexity:** M +- **Principal:** `M` · **Interest:** `MED` · **Basis:** `estimate` +- **Provenance:** Registered 2026-08-18. Found by pulling a thread: the deep-audit playbook reported `0 markdown fases`, which turned out to be a zero-padding mismatch (`phase-0[1-5]` vs `phase-1`, `phase-1.1`) — and asking whether `phase-1.1` should count exposed that nothing counts it because nothing implements it. +- **Acceptance criteria:** + - [x] `KDD` and `knowledge-first` return zero matches across both repositories, except in `CHANGELOG.md` and `ADR-0103`, which are left as historical records on purpose. **MET for the Core.** After the sweep the tokens survive in exactly six files: `CHANGELOG.md`, `ADR-0103` (EN/ES), `ADR-0127` (EN/ES) — the retirement itself — plus the gap board and the redesign doc's correction notice. The Tracker half is its own pull request in `evolith_tracker`. + - [x] Gate 1's preconditions and evidence table stand on their own, with no reference to a subphase or to KDD levels. **MET** — the *"Phase 1.1 adoption level has been declared… a FAIL result blocks this gate"* bullet is gone, and the three evidence rows (Discovery Canvas, Ballpark Estimation, MoSCoW) no longer carry their `If Phase 1.1 Level ≥ n` clauses. + - [x] The retirement is an **ADR**, and `ADR-0103` is amended by it rather than edited — an accepted decision is superseded, not rewritten. **MET** — `ADR-0127` carries the decision and states the amendment: the Planning Gate now precedes Phase 1 directly, and the option `ADR-0103` rejected is moot rather than wrong. `ADR-0103` itself is untouched. + - [ ] The Tracker's `REQ-DIS-12` and `REQ-DIS-13` go with it; a numbered requirement left standing is an instruction to build the thing. **OPEN — the Tracker half is a separate pull request in `evolith_tracker`**, where the files, the board and the guards are different. Left unticked deliberately: this row is not done until both repositories are. + - [x] **FALSIFIABILITY:** no link in either repository resolves to a deleted KDD file, checked after the sweep rather than assumed from the delete list. **MET for the Core** — searching the eight deleted filenames across every markdown file returns nothing outside `ADR-0127` and the redesign doc's correction notice, both of which name them as retired rather than link to them. +- **Status:** `IN-PROGRESS` + diff --git a/reference/core/control-center/gaps/gap-tracking.es.md b/reference/core/control-center/gaps/gap-tracking.es.md index a46719f6..ade760fc 100644 --- a/reference/core/control-center/gaps/gap-tracking.es.md +++ b/reference/core/control-center/gaps/gap-tracking.es.md @@ -20,6 +20,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | ID | Gap | En simple | Qué resuelve | Componente | Fase | Criticidad | Complejidad | Estado | |---|---|---|---|:---:|:---:|:---:|:---:|:---:| +| [`GT-708`](./gap-reference-catalog.es.md#gt-708) | **Un concepto de gobierno que existía solo en prosa, en dos repositorios, y que una compuerta real citaba como precondición.** «KDD» nombraba dos cosas distintas y ninguna llegó a construirse: la **Fase 1.1 — Knowledge-First Discovery**, subfase opcional con su propia compuerta de preparación y siete plantillas de artefacto; y **KDD — Knowledge-Driven Development**, lectura posterior de la sesión con el dueño del 2026-07-04 (`L-009`, `D-004`) que lo convertía en sección opcional *dentro del PRD*, activable por tenant. **Medido en todas las superficies ejecutables, y ausente en todas:** `phase-gates.rules.json` tiene cinco gates para las fases 1..5; ninguno de los siete artefactos KDD está entre los 33 de `artifact-registry.json`; cero ficheros TypeScript con `KDD`/`knowledge-first`/`knowledgeBrief`/`discoveryReadiness`/`storySeed`/`epicCandidate`; el CLI tiene 31 comandos y cero menciones, y su `--phase discovery` mapea a la **fase 1 entera** (`phase-id.ts`: `f1: 'discovery'`), no a la 1.1; el servidor MCP, cero; el Tracker no tiene ni pantalla ni entidad; y `prd.schema.json` no lleva sección KDD, así que `D-004` tampoco llegó nunca a schema. **Aun así la prosa tenía dientes:** `phase-1-business-signoff.es.md` convertía *«el nivel de adopción de la Fase 1.1 ha sido declarado»* en **precondición para abrir el Gate 1**, y tres filas de su tabla de evidencia llevaban cláusulas condicionadas a niveles de KDD — una compuerta que nadie implementa bloqueando una que implementa todo el mundo. **CERRADA el 2026-08-18 por eliminación, por decisión del dueño de que Evolith Core y Tracker dejan de manejar el concepto en cualquier forma.** 16 ficheros borrados (el playbook de la Fase 1.1 y las siete plantillas, EN y ES); eliminadas la precondición del Gate 1 y sus tres cláusulas de evidencia condicionadas a KDD; eliminadas la tabla `Subfase 01.1`, la fila del índice de playbooks y las referencias a Story Seeds / Epic Candidates en el playbook de Fase 2 y en el índice de plantillas; `D-004`/`L-009` reescritas a lo que las sobrevive — el PRD es el piso canónico y el Gate 1 lo exige siempre. **La retirada es el [`ADR-0127`](../../architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md), y el `ADR-0103` queda ENMENDADO por él en vez de editado:** una decisión aceptada del Architecture Board se supersede, no se reescribe, así que su razonamiento se mantiene y lo único que desapareció es su vecino. `CHANGELOG.md` y el `ADR-0103` conservan su texto sobre KDD a propósito — registran lo que era cierto cuando se escribieron, y editarlos falsificaría la historia que este repositorio guarda deliberadamente. **Falsabilidad, comprobada tras el barrido y no inferida de la lista de borrados:** toda referencia a los ocho ficheros borrados no devuelve nada fuera del ADR y del aviso de corrección, y `KDD`/`knowledge-first` solo sobreviven en los seis ficheros citados. **Lo que deja esta fila es la lección, no el barrido:** un concepto puede ser citado como precondición dura por una compuerta que todo el mundo implementa mientras no lo implementa nadie, y seguir así meses, porque nadie contrasta la prosa contra los datos. | Un concepto que describimos por todas partes y no construimos en ninguna, del que depende una de nuestras compuertas reales. | Que el modelo de cinco fases se lea igual en los documentos que en los datos, y que el Gate 1 deje de depender de una subfase que nadie puede ejecutar. | `Governance` | Cross | P2 | M | `EN-PROGRESO` | | [`GT-707`](./gap-reference-catalog.es.md#gt-707) | **Todo binario autónomo que publica este repositorio falla en `--help`, y ninguna release ha llevado nunca uno.** Medido el 2026-08-18 en los cuatro pull requests abiertos y, antes de ellos, en el push del tag `v1.3.6` y en el pull request que hizo por primera vez que el release pipeline corriera en pull requests: `smoke-test` y `smoke-test-functional` fallan con `ERR_REQUIRE_ESM: require() of ES Module /snapshot/…/@clack/prompts/dist/index.mjs`, lanzado desde `prompt.service.js` — así que el binario muere antes de parsear un argumento, en las tres plataformas. `gh release view` sobre `v1.3.0` y `v1.1.0` devuelve **cero assets**: `upload-assets` depende de `smoke-test`, así que el canal nunca ha entregado nada, y la propia puerta del pipeline es lo que lo detuvo. **Medido además, para que el próximo intento arranque aquí:** `@clack/prompts@1.5.1` es la ÚNICA dependencia solo-ESM del CLI (`chalk` 4.1.2, `ora` 5.4.1, `inquirer` 8.2.7 y `cli-table3` son todas CommonJS); `esbuild` la empaqueta en un CJS de 107 kB que carga limpio; y empaquetar con el fork mantenido `@yao-pkg/pkg@6` ELIMINA el `ERR_REQUIRE_ESM` y falla distinto — `MODULE_NOT_FOUND` por el mismo `.mjs`, porque el fichero no está en el snapshot — lo que significa que el empaquetador y el conjunto de assets son dos defectos distintos, no uno. **El arreglo que parece barato no lo es:** redirigir el import toca 6 ficheros de producción y ~24 specs que hacen `jest.mock('@clack/prompts')` con ese especificador exacto. **Deliberadamente NO arreglado dentro de los cuatro pull requests que lo encontraron:** están verdes en los 8 checks requeridos y esto es un fallo previo en un workflow no requerido; meter un rediseño de empaquetado ahí sería el cambio-ajeno-dentro-de-una-promoción que este tablero no deja de rechazar. **CERRADA el 2026-08-18 vendorizando a CommonJS las dependencias solo-ESM — y la primera evidencia de esta misma fila estaba mal dos veces, que es la parte que merece conservarse.** El binario empaquetado ya arranca: construido desde este árbol, `--help` sale **0**, `--version` imprime `1.3.2`, e `init --runtime nodejs --monorepo none --arch clean` sale **0** y escribe un satélite. **MAL #1 — «la única dependencia solo-ESM».** Esta fila lo midió sondeando `require('/package.json')`, que ocho de las 25 dependencias directas rechazan con `ERR_PACKAGE_PATH_NOT_EXPORTED` — un error que se lee como «bien». Leyendo los manifiestos DESDE DISCO aparecen **tres**: `@clack/prompts@1.5.1`, `conf@15.1.0` y `@modelcontextprotocol/sdk@1.29.0`. Dos se cargan en runtime y ambas quedan vendorizadas; el sdk de MCP es solo un `.d.ts` en este paquete, así que nunca entra en el snapshot. `pkg` llevaba avisando de `conf` todo el tiempo —muere nombrando `conf/package.json` y `config.service.js`— y nadie leyó más allá del primer error. **MAL #2 — el fallback apuntaba a nada.** `clack.ts` compila a `dist/infrastructure/prompts/` mientras el bundle se escribe en `dist/vendor/`, así que `require('./vendor/clack.cjs')` resolvía a una ruta inexistente. Nada falló en build; falló el BINARIO en ejecución, con el error del propio paquete, porque el `MODULE_NOT_FOUND` del fallback quedaba tragado por un rethrow del original. Ambos son ahora arreglos estructurales y no correcciones: el rethrow nombra LOS DOS fallos, y `vendor-esm-deps.mjs` lee la ruta relativa del shim COMPILADO y la resuelve — observado en rojo contra la ruta rota, con la ubicación resuelta en el mensaje. **Lo que se entrega:** `scripts/vendor-esm-deps.mjs` empaqueta cada dependencia solo-ESM con esbuild (clack 107 kB, conf 410 kB) y luego la carga de vuelta en un proceso hijo con `--no-experimental-require-module` —lo más cerca que un proceso Node normal está del contrato sin-ESM del snapshot— y compara su superficie de exports con la del paquete real. Dos shims (`prompts/clack.ts`, `config/conf-module.ts`) prueban PRIMERO EL PAQUETE y caen al bundle ante CUALQUIER fallo de carga: el orden es lo que mantiene las ~24 specs que hacen `jest.mock('@clack/prompts')` interceptando el mismo especificador de siempre, y «cualquier fallo» es porque la misma causa aflora como `ERR_REQUIRE_ESM` con un empaquetador y como `MODULE_NOT_FOUND` con otro. 106 suites / 1485 tests en verde, `tsc -b` limpio. El release pipeline no cambia: el arreglo es agnóstico del empaquetador, y su `smoke-test` es la falsabilidad que esta fila pedía. | El programa descargable que publicamos se cae al instante y, de hecho, nunca hemos publicado ninguno. | O un binario autónomo que arranca, o una retirada honesta del canal — no un check rojo que todo el mundo aprende a ignorar. | `Infra` | Cross | P2 | M | `COMPLETADO` | | [`GT-688`](./gap-reference-catalog.es.md#gt-688) | **Una composición de topologías confirmada se trunca a un solo id antes de la compuerta, así que un sistema mixto obtiene un veredicto verde por la única topología que sobrevivió.** Medido en vivo el 2026-08-14 contra el dist compilado: `manifestFromWorkspace` con `design.topologyConfirmedRefs: [modular-monolith, agentic-ai, event-driven]` devuelve `{"topology":"modular-monolith","facts":{"context":{"topologyRef":"modular-monolith"}}}` — **las otras dos no aparecen por ninguna parte**. Causa: `evaluation-context.builder.ts:26` `topology: ctx.topologyRef`, y `grep -n "design"` sobre ese fichero entero devuelve un hit, un comentario en `:149`. **Peor sin el escalar:** el manifiesto sale sin clave `topology`, el kind SALTA (`kind-evaluators.ts:363`), y el pipeline se reinventa una **con un regex sobre el YAML en disco**, ganando la primera coincidencia (`satellite-evaluation-pipeline.service.ts:354`). El contrato de resultado tampoco puede llevar dos (`TopologyEvaluationResult.topologyRef`, escalar obligatorio). Así que el kind devuelve `PASS, conformant: true` por el id que conservó — **un veredicto verde sobre un sistema del que la mitad nunca se comprobó**. **La observación del dueño que originó esta fila quedó REFUTADA a medias, y la mitad refutada importa:** el modelo NO es singular — `ADR-0079:44` rechaza por escrito el diseño excluyente, la transversalidad es declaración formal (`maturityLevel: "cross"` en las cinco no progresivas), y el corpus, el contrato de satélite y el evaluador de diseño son plurales; `evolith topology phase-artifacts -t agentic-ai,event-driven` sí une ambas. Lo que sobrevivió es el cable de APLICACIÓN. No lo cubre `MT-A*`: sus 26 filas están DONE y todas son corpus, esquema o documentación. | — | — | `Core Domain` | Cross | P1 | L | `COMPLETADO` | | [`GT-689`](./gap-reference-catalog.es.md#gt-689) | **El modelo de compatibilidad de composiciones no tiene ningún lector en ejecución, y su marcador de transversalidad no tiene ninguno.** `grep -rn "composableWith" --include=*.ts src/` excluyendo dist devuelve dos hits, ambos declaraciones de tipo, **cero lecturas**; `metadata.dimension` —el campo que codifica la transversalidad— no tiene lector alguno en producción. El único consumidor es el guard `22-validate-topology-composition.mjs`, y `find . -name topology.composition.json` devuelve **exactamente un** fichero fuera de worktrees. Tres consecuencias medidas: el guard compara todo par ordenado, así que exige simetría mientras los manifiestos son asimétricos, y por eso `modular-monolith → data-mesh` y `edge-computing → serverless` **fallarían en CI el día que alguien los escriba**; `minItems: 2` impide expresar el estado documentado más común, un `modular-monolith` solo; y `edge-computing` y `serverless` son ambos `dimension: execution` y se declaran componibles, algo que la documentación prohíbe y que nadie caza, porque nadie lee `dimension`. Se registra ahora y no después de [`GT-688`](./gap-reference-catalog.es.md#gt-688) porque es esa fila la que vuelve portante esta validación. | Las reglas sobre qué arquitecturas pueden combinarse están escritas con cuidado y no las consulta nada que se ejecute. | Que la compatibilidad sea algo que el motor comprueba: una combinación ilegal se rechaza y una legal deja de fallar en CI. | `Governance` | Cross | P2 | M | `DIFERIDO` | @@ -727,7 +728,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | [`GT-706`](./gap-reference-catalog.es.md#gt-706) | **Nada asegura que los `exports` que un paquete declara resuelvan dentro de su propio tarball, así que un productor publica una subruta fantasma y solo la descubre un consumidor — una publicación demasiado tarde.** `contracts@1.1.0` declaró una subruta de export que no incluía; el fallo salió en el smoke de sala limpia de `infra-providers@1.2.1`, **después de que `core-domain@1.3.1` ya estuviera irreversiblemente en el registry**, dejando la release a medio entregar y sin despublicar posible pasadas 72 horas. La comprobación que existe es real y tiene la forma equivocada: `npm-release.yml:213` calcula «prometidos» como `[pkg.main, ...bin]`, y **`exports` no está en esa lista**. FALSABILIDAD DEMOSTRADA, OBSERVADA EN VERDE: un paquete de dos ficheros que declara `"./ingest"` con solo `dist/index.js` en disco pasa esa aserción corrida literal — `exit=0`, mientras `require pkg/ingest` responde `MODULE_NOT_FOUND`. El smoke de sala limpia tampoco lo cubre, y no es defecto suyo: resuelve lo que un paquete IMPORTA, así que el fantasma del productor es invisible hasta el turno de un consumidor, que es después del paso irreversible. Exposición: 3 de 8 paquetes publicables declaran **23 subrutas de export**, ninguna asegurada, y dos declaran además un `./*` sin cota. **ARREGLADO 2026-08-16 — `.harness/scripts/ci/67-validate-declared-exports.mjs`, corriendo en tiempo de PR sobre todos los workspaces publicables Y por paquete dentro del bucle de release, justo antes de `npm publish`.** Recoge cada hoja de texto del árbol de condiciones, así que `types` cuenta tanto como `default`, e incluye `main`/`bin`, siendo un superconjunto de la aserción que sustituye. **La propia afirmación de esta fila sobre el registry la refutó el guard en su primera corrida:** «22 de 22 resuelven, 0 fantasmas» excluía las claves con comodín por su propio filtro, y una está MUERTA — `core-domain` declara `./infrastructure/adapters/*` **sin ningún directorio `adapters`**, 0 coincidencias en un packlist de 796 ficheros, `MODULE_NOT_FOUND` en el 1.3.1 publicado, y **ningún commit de este repositorio llevó jamás ese path**. Borrada, no ampliada: nunca hubo nada detrás. Falsabilidad observada por los dos lados — rojo con la fixture `./ingest`, con `core-domain` de verdad, y con un fichero presente en disco pero excluido por `files`; verde con la misma fixture en cuanto se incluye y con el árbol entero, **68 destinos declarados en 9 paquetes**. | Un paquete puede prometer una ruta de import que nunca incluyó, y quien se entera es el siguiente paquete en publicarse. | La release se niega a publicar un manifiesto que miente, antes de que nada sea irreversible. | `Infra` | Cross | P1 | S | `COMPLETADO` | -**Progreso:** 676 / 705 completados · 2 en progreso · 0 pendientes · 27 diferidos +**Progreso:** 676 / 706 completados · 3 en progreso · 0 pendientes · 27 diferidos **Oleada 2026-06-23 (auditoría profunda de Winston III):** Añadidos 14 gaps nuevos `GT-212`…`GT-225` del Winston Audit Playbook que cubren: higiene de estado ADR (GT-212), metadata + presupuestos operativos + corpus de guías por topología (GT-213, GT-217, GT-219), observabilidad + OpenAPI en controladores REST (GT-214, GT-215), paridad de input-schemas OPA + densidad de tests por topología (GT-216, GT-222), plantillas de rollback + on-call de Fase 05 (GT-218), cobertura de ramas CLI + paridad de envelope --format + limpieza de skip-list (GT-220, GT-224, GT-225), audit logging HTTP de MCP (GT-221), y tests e2e de paridad cross-surface (GT-223). diff --git a/reference/core/control-center/gaps/gap-tracking.md b/reference/core/control-center/gaps/gap-tracking.md index 0a3e2af2..4bafba69 100644 --- a/reference/core/control-center/gaps/gap-tracking.md +++ b/reference/core/control-center/gaps/gap-tracking.md @@ -20,6 +20,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | ID | Gap | In plain terms | What it fixes | Component | Phase | Criticality | Complexity | Status | |---|---|---|---|:---:|:---:|:---:|:---:|:---:| +| [`GT-708`](./gap-reference-catalog.md#gt-708) | **A governance concept that existed only in prose, in two repositories, and was cited as a precondition by a gate that does exist.** «KDD» named two different things and neither was ever built: **Phase 1.1 — Knowledge-First Discovery**, an optional subphase with its own readiness gate and seven artifact templates; and **KDD — Knowledge-Driven Development**, a later reading from the 2026-07-04 owner session (`L-009`, `D-004`) that made it an optional section *inside the PRD*, activated per tenant. **Measured across every executable surface, and absent from all of them:** `phase-gates.rules.json` has five gates for phases 1..5; none of the seven KDD artifacts is among the 33 in `artifact-registry.json`; zero TypeScript files match `KDD`/`knowledge-first`/`knowledgeBrief`/`discoveryReadiness`/`storySeed`/`epicCandidate`; the CLI has 31 commands and zero mentions, and its `--phase discovery` maps to **phase 1 entire** (`phase-id.ts`: `f1: 'discovery'`), not to 1.1; the MCP server has zero; the Tracker has no screen and no entity; and `prd.schema.json` carries no KDD section, so `D-004` never reached a schema either. **The prose had teeth anyway:** `phase-1-business-signoff.md` made *"Phase 1.1 adoption level has been declared"* a **precondition for opening Gate 1**, and three rows of its evidence table carried clauses keyed to KDD levels — a gate nothing implements blocking a gate everything implements. **CLOSED 2026-08-18 by removal, on the owner's decision that Evolith Core and Tracker no longer carry the concept in any form.** 16 files deleted (the Phase 1.1 playbook and the seven artifact templates, EN and ES); Gate 1's precondition and its three KDD-keyed evidence clauses removed; the `Subphase 01.1` table, the playbook index row and the Story-Seed/Epic-Candidate references in the Phase 2 playbook and template index removed; `D-004`/`L-009` rewritten to what survives them — the PRD is the canonical floor and Gate 1 always requires it. **The retirement is [`ADR-0127`](../../architecture/adrs/core/0127-retire-knowledge-first-discovery.md), and `ADR-0103` is AMENDED by it rather than edited:** an accepted Architecture Board decision is superseded, not rewritten, so its reasoning stands and only its neighbour is gone. `CHANGELOG.md` and `ADR-0103` keep their KDD text on purpose — they record what was true when written, and editing them would falsify the history this repository keeps deliberately. **Falsifiability, checked after the sweep rather than inferred from the delete list:** every reference to the eight deleted filenames returns nothing outside the ADR and the correction notice, and `KDD`/`knowledge-first` survive only in the six files named above. **What this row leaves behind is the lesson, not the sweep:** a concept can be cited as a hard precondition by a gate that everything implements while being implemented by nothing, and stay that way for months, because nobody diffs the prose against the data. | A concept we describe everywhere and have built nowhere, which one of our real gates depends on. | The five-phase model reads the same in the docs as in the data, and Gate 1 stops depending on a subphase nobody can execute. | `Governance` | Cross | P2 | M | `IN-PROGRESS` | | [`GT-707`](./gap-reference-catalog.md#gt-707) | **Every standalone binary this repository publishes fails on `--help`, and no release has ever carried one.** Measured 2026-08-18 across all four open pull requests and, before them, on the `v1.3.6` tag push and on the pull request that first made the release pipeline run on pull requests: `smoke-test` and `smoke-test-functional` fail with `ERR_REQUIRE_ESM: require() of ES Module /snapshot/…/@clack/prompts/dist/index.mjs`, raised from `prompt.service.js` — so the binary dies before parsing an argument, on all three platforms. `gh release view` on `v1.3.0` and `v1.1.0` returns **zero assets**: `upload-assets` depends on `smoke-test`, so the channel has never delivered anything, and the pipeline's own gate is what stopped it. **Measured further, so the next attempt starts here:** `@clack/prompts@1.5.1` is the ONLY ESM-only dependency the CLI has (`chalk` 4.1.2, `ora` 5.4.1, `inquirer` 8.2.7 and `cli-table3` are all CommonJS); `esbuild` bundles it to a 107 kB CJS file that loads clean; and packaging with the maintained fork `@yao-pkg/pkg@6` REMOVES the `ERR_REQUIRE_ESM` and then fails differently — `MODULE_NOT_FOUND` for the same `.mjs`, because the file is not in the snapshot — which means the packager and the asset set are two separate defects, not one. **The cheap-looking fix is not cheap:** redirecting the import touches 6 production files and ~24 spec files that `jest.mock('@clack/prompts')` by that exact specifier. **Deliberately NOT fixed inside the four pull requests that found it:** they are green on all 8 required checks and this is a pre-existing failure in a non-required workflow; smuggling a packaging redesign into them would be the unrelated-change-inside-a-promotion this board keeps refusing. **CLOSED 2026-08-18 by vendoring the ESM-only dependencies to CommonJS — and this row's own first evidence was wrong twice, which is the part worth keeping.** The packaged binary now runs: built from this tree, `--help` exits **0**, `--version` prints `1.3.2`, and `init --runtime nodejs --monorepo none --arch clean` exits **0** and writes a satellite. **WRONG #1 — "the only ESM-only dependency".** This row measured that by probing `require('/package.json')`, which eight of the 25 direct dependencies refuse with `ERR_PACKAGE_PATH_NOT_EXPORTED` — an error that reads like "fine". Reading the manifests FROM DISK instead found **three**: `@clack/prompts@1.5.1`, `conf@15.1.0` and `@modelcontextprotocol/sdk@1.29.0`. Two of them are loaded at runtime and both are vendored; the MCP sdk is only a `.d.ts` in this package, so it never enters the snapshot. `pkg` had been telling us about `conf` all along — it dies naming `conf/package.json` and `config.service.js` — and nobody read past the first error. **WRONG #2 — the fallback pointed at nothing.** `clack.ts` compiles to `dist/infrastructure/prompts/` while the bundle is written to `dist/vendor/`, so `require('./vendor/clack.cjs')` resolved to a path that does not exist. Nothing failed at build time; the BINARY failed at run time with the package's own error, because the fallback's `MODULE_NOT_FOUND` was swallowed by a rethrow of the original. Both are now structural fixes rather than corrections: the rethrow names BOTH failures, and `vendor-esm-deps.mjs` reads the relative path out of each COMPILED shim and resolves it — observed red against the broken path, with the resolved location in the message. **What ships:** `scripts/vendor-esm-deps.mjs` bundles each ESM-only dependency with esbuild (clack 107 kB, conf 410 kB), then loads each one back in a child process with `--no-experimental-require-module` — the closest an ordinary Node process gets to the snapshot's no-ESM contract — and compares its export surface against the real package. Two shims (`prompts/clack.ts`, `config/conf-module.ts`) try the PACKAGE FIRST and fall back to the bundle on ANY load failure: the order is what keeps the ~24 specs that `jest.mock('@clack/prompts')` intercepting the same specifier they always did, and "any failure" is because the same cause surfaces as `ERR_REQUIRE_ESM` under one packager and `MODULE_NOT_FOUND` under another. 106 suites / 1485 tests green, `tsc -b` clean. The release pipeline is unchanged: the fix is packager-agnostic, and its `smoke-test` is the falsifiability this row asked for. | The downloadable program we publish crashes instantly, and in fact we have never published one. | Either a standalone binary that runs, or an honest retirement of the channel — not a red check everybody learns to ignore. | `Infra` | Cross | P2 | M | `DONE` | | [`GT-688`](./gap-reference-catalog.md#gt-688) | **A confirmed topology composition is truncated to one id before the gate, so a mixed system gets a green topology verdict for the one topology that survived.** Measured live 2026-08-14 against the built dist: `manifestFromWorkspace` with `design.topologyConfirmedRefs: [modular-monolith, agentic-ai, event-driven]` returns `{"topology":"modular-monolith","facts":{"context":{"topologyRef":"modular-monolith"}}}` — **the other two appear nowhere**. Cause: `evaluation-context.builder.ts:26` `topology: ctx.topologyRef`, and `grep -n "design"` over that whole file returns one hit, a comment at `:149`. **Worse without the scalar:** the manifest carries no `topology` key at all, the kind SKIPs (`kind-evaluators.ts:363`), and the pipeline re-derives one **by regex over the YAML on disk**, first match wins (`satellite-evaluation-pipeline.service.ts:354`). The result contract cannot carry two either (`TopologyEvaluationResult.topologyRef`, required scalar). So the kind returns `PASS, conformant: true` for the id it kept — **a green verdict over a system half of which was never checked**. **The owner observation that produced this row was half REFUTED, and the refuted half matters:** the model is NOT singular — `ADR-0079:44` rejects the exclusive design in writing, transversality is a formal declaration (`maturityLevel: "cross"` on all five non-progressive manifests), and the corpus, satellite contract and design evaluator are plural; `evolith topology phase-artifacts -t agentic-ai,event-driven` really does union both. What survived is the ENFORCEMENT wire. Not covered by `MT-A*`: all 26 rows are DONE and every one is corpus/schema/docs work. | — | — | `Core Domain` | Cross | P1 | L | `DONE` | | [`GT-689`](./gap-reference-catalog.md#gt-689) | **The composition compatibility model has zero runtime readers, and its transversality marker has none at all.** `grep -rn "composableWith" --include=*.ts src/` excluding dist returns two hits, both type declarations, **zero reads**; `metadata.dimension` — the field encoding transversality — has no production reader at all. The single consumer is guard `22-validate-topology-composition.mjs`, and `find . -name topology.composition.json` returns **exactly one** non-worktree file. Three measured consequences: the guard compares every ordered pair so it demands symmetry while the manifests are asymmetric, making `modular-monolith → data-mesh` and `edge-computing → serverless` **fail CI the day anyone writes them down**; `minItems: 2` means the most common documented state, a lone `modular-monolith`, cannot be expressed as a composition at all; and `edge-computing` + `serverless` are both `dimension: execution` yet declare each other composable, which the docs forbid and nothing catches, because nothing reads `dimension`. Registered now rather than after [`GT-688`](./gap-reference-catalog.md#gt-688) because that row is what makes this validation load-bearing. | The rules about which architectures may be combined are written down carefully and consulted by nothing that runs. | Compatibility becomes a property the engine checks, so an illegal combination is refused and a legal one stops failing CI. | `Governance` | Cross | P2 | M | `DEFERRED` | @@ -727,7 +728,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | [`GT-706`](./gap-reference-catalog.md#gt-706) | **Nothing asserts that a package's own declared `exports` resolve inside its own tarball, so a producer publishes a phantom subpath and only a consumer discovers it — one publish too late.** `contracts@1.1.0` declared an export subpath it did not ship; the failure surfaced at `infra-providers@1.2.1`'s clean-room smoke, **after `core-domain@1.3.1` was already irreversibly on the registry**, leaving the release half-shipped with no unpublish available after 72 hours. The check that exists is real and the wrong shape: `npm-release.yml:213` computes "promised" as `[pkg.main, ...bin]`, and **`exports` is not in that list**. PROVEN FALSIFIABLE, OBSERVED GREEN: a two-file package declaring `"./ingest"` with only `dist/index.js` on disk passes that assertion run verbatim — `exit=0`, while `require pkg/ingest` answers `MODULE_NOT_FOUND`. The clean-room smoke does not cover it either, and that is not its defect: it resolves what a package IMPORTS, so a producer's phantom is invisible until a consumer's turn, which is after the irreversible step. Exposure: 3 of 8 publishable packages declare **23 export subpaths**, none asserted, two of them also declaring an unbounded `./*`. **FIXED 2026-08-16 — `.harness/scripts/ci/67-validate-declared-exports.mjs`, run at PR time over every publishable workspace AND per package inside the release loop, immediately before `npm publish`.** It collects every string leaf of the condition tree, so `types` counts as much as `default`, and folds in `main`/`bin`, making it a superset of the assertion it replaces. **The row's own claim about the registry was refuted by the guard on its first run:** "22 of 22 resolve, 0 phantom" excluded wildcard keys by its own filter, and one is DEAD — `core-domain` declares `./infrastructure/adapters/*` with **no `adapters` directory at all**, 0 matches in a 796-file packlist, `MODULE_NOT_FOUND` on the published 1.3.1, and **no commit in this repository ever carried that path**. Deleted, not widened: there was never anything behind it. Falsifiability observed on both sides — red on the `./ingest` fixture, on `core-domain` for real, and on a file present on disk but excluded by `files`; green on the same fixture once it ships and on the whole tree, **68 declared targets across 9 packages**. | A package can promise an import path it never shipped, and the next package to publish is the one that finds out. | The release refuses to publish a manifest that lies, before anything becomes irreversible. | `Infra` | Cross | P1 | S | `DONE` | -**Progress:** 676 / 705 done · 2 in progress · 0 pending · 27 deferred +**Progress:** 676 / 706 done · 3 in progress · 0 pending · 27 deferred **Wave 2026-06-23 (Winston deep audit III):** Added 14 new gaps `GT-212`…`GT-225` from the Winston Audit Playbook covering: ADR status hygiene (GT-212), topology manifest metadata + operational budgets + guidance corpus (GT-213, GT-217, GT-219), REST controller observability + OpenAPI (GT-214, GT-215), OPA input-schema parity + per-topology test density (GT-216, GT-222), SDLC Phase 05 rollback + on-call templates (GT-218), CLI branch coverage + envelope format coverage + skip-list cleanup (GT-220, GT-224, GT-225), MCP HTTP audit logging (GT-221), and cross-surface parity e2e tests (GT-223). diff --git a/reference/core/control-center/maturity-reports/executive-summary.es.md b/reference/core/control-center/maturity-reports/executive-summary.es.md index a00fb75c..2c245fd5 100644 --- a/reference/core/control-center/maturity-reports/executive-summary.es.md +++ b/reference/core/control-center/maturity-reports/executive-summary.es.md @@ -11,7 +11,7 @@ Instantánea estratégica generada desde el tablero canónico de gaps y la recon **Decisión actual:** NO-GO para expansión productiva o release mayor: existen bloqueadores P0 activos. -**Mayor problema ahora:** `Governance` concentra el mayor riesgo abierto ponderado (8 pendientes, 0 P0). Ataca esa concentración antes de ampliar alcance. +**Mayor problema ahora:** `Governance` concentra el mayor riesgo abierto ponderado (9 pendientes, 0 P0). Ataca esa concentración antes de ampliar alcance. **Dónde atacar primero:** [GT-435](../gaps/gap-reference-catalog.es.md#gt-435). @@ -26,10 +26,10 @@ La forma correcta de usar este resumen es simple: si necesitas contexto, abre so | Orden | Foco | Motivo | IDs | |---:|---|---|---| | 1 | Bloqueadores P0 | Impiden afirmar readiness productivo o release mayor. | [GT-435](../gaps/gap-reference-catalog.es.md#gt-435) | -| 2 | Área de mayor riesgo | `Governance` tiene la mayor carga ponderada abierta. | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), [GT-689](../gaps/gap-reference-catalog.es.md#gt-689), [GT-588](../gaps/gap-reference-catalog.es.md#gt-588), +2 | +| 2 | Área de mayor riesgo | `Governance` tiene la mayor carga ponderada abierta. | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), [GT-689](../gaps/gap-reference-catalog.es.md#gt-689), [GT-708](../gaps/gap-reference-catalog.es.md#gt-708), +3 | | 3 | Ganancias rápidas | Alta criticidad con complejidad XS/S. | [GT-684](../gaps/gap-reference-catalog.es.md#gt-684) | | 4 | Ola P1 | Endurecimiento siguiente después de limpiar P0. | [GT-684](../gaps/gap-reference-catalog.es.md#gt-684), [GT-324](../gaps/gap-reference-catalog.es.md#gt-324), [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-680](../gaps/gap-reference-catalog.es.md#gt-680), [GT-681](../gaps/gap-reference-catalog.es.md#gt-681), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-448](../gaps/gap-reference-catalog.es.md#gt-448) | -| 5 | P2/P3 | Solo después de estabilizar seguridad, CI, reglas y contratos. | [GT-444](../gaps/gap-reference-catalog.es.md#gt-444), [GT-464](../gaps/gap-reference-catalog.es.md#gt-464), [GT-674](../gaps/gap-reference-catalog.es.md#gt-674), [GT-685](../gaps/gap-reference-catalog.es.md#gt-685), [GT-686](../gaps/gap-reference-catalog.es.md#gt-686), [GT-687](../gaps/gap-reference-catalog.es.md#gt-687), +10 | +| 5 | P2/P3 | Solo después de estabilizar seguridad, CI, reglas y contratos. | [GT-444](../gaps/gap-reference-catalog.es.md#gt-444), [GT-464](../gaps/gap-reference-catalog.es.md#gt-464), [GT-674](../gaps/gap-reference-catalog.es.md#gt-674), [GT-685](../gaps/gap-reference-catalog.es.md#gt-685), [GT-686](../gaps/gap-reference-catalog.es.md#gt-686), [GT-687](../gaps/gap-reference-catalog.es.md#gt-687), +11 | ## Bloqueadores Actuales @@ -42,19 +42,19 @@ La forma correcta de usar este resumen es simple: si necesitas contexto, abre so | Indicador | Valor | |---|---:| | Fecha canónica del tablero | 2026-08-18 | -| Gaps totales | 705 | +| Gaps totales | 706 | | Gaps cerrados | 676 | -| Gaps pendientes | 29 | +| Gaps pendientes | 30 | | P0 abiertos | 1 | | P1 abiertos | 8 | -| P2 abiertos | 16 | -| Cierre total | 95.9% | +| P2 abiertos | 17 | +| Cierre total | 95.8% | | Registros de evidencia de cierre | 658 | | Readiness registrado | 4 PASS | | Área | Pendientes | P0 | P1 | Primeros IDs | |---|---:|---:|---:|---| -| `Governance` | 8 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), +4 | +| `Governance` | 9 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), +5 | | `Cross` | 3 | 1 | 1 | [GT-435](../gaps/gap-reference-catalog.es.md#gt-435), [GT-448](../gaps/gap-reference-catalog.es.md#gt-448), [GT-651](../gaps/gap-reference-catalog.es.md#gt-651) | | `MCP Server` | 3 | 0 | 3 | [GT-684](../gaps/gap-reference-catalog.es.md#gt-684), [GT-680](../gaps/gap-reference-catalog.es.md#gt-680), [GT-681](../gaps/gap-reference-catalog.es.md#gt-681) | | `Infra` | 4 | 0 | 1 | [GT-324](../gaps/gap-reference-catalog.es.md#gt-324), [GT-464](../gaps/gap-reference-catalog.es.md#gt-464), [GT-685](../gaps/gap-reference-catalog.es.md#gt-685), [GT-692](../gaps/gap-reference-catalog.es.md#gt-692) | diff --git a/reference/core/control-center/maturity-reports/executive-summary.md b/reference/core/control-center/maturity-reports/executive-summary.md index 87dcdc9c..7d70eb28 100644 --- a/reference/core/control-center/maturity-reports/executive-summary.md +++ b/reference/core/control-center/maturity-reports/executive-summary.md @@ -11,7 +11,7 @@ Strategic snapshot generated from the canonical gap board and maturity reconcili **Current decision:** NO-GO for production expansion or a major release: active P0 blockers remain. -**Biggest problem now:** `Governance` carries the highest weighted open risk (8 open, 0 P0). Attack that concentration before expanding scope. +**Biggest problem now:** `Governance` carries the highest weighted open risk (9 open, 0 P0). Attack that concentration before expanding scope. **Where to attack first:** [GT-435](../gaps/gap-reference-catalog.md#gt-435). @@ -26,10 +26,10 @@ Use this summary with a simple rule: if you need context, open only the linked I | Order | Focus | Reason | IDs | |---:|---|---|---| | 1 | P0 blockers | They prevent production-readiness or major-release confidence. | [GT-435](../gaps/gap-reference-catalog.md#gt-435) | -| 2 | Highest-risk area | `Governance` has the largest weighted open load. | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), [GT-689](../gaps/gap-reference-catalog.md#gt-689), [GT-588](../gaps/gap-reference-catalog.md#gt-588), +2 | +| 2 | Highest-risk area | `Governance` has the largest weighted open load. | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), [GT-689](../gaps/gap-reference-catalog.md#gt-689), [GT-708](../gaps/gap-reference-catalog.md#gt-708), +3 | | 3 | Quick wins | High criticality with XS/S complexity. | [GT-684](../gaps/gap-reference-catalog.md#gt-684) | | 4 | P1 wave | Next hardening after P0 is cleared. | [GT-684](../gaps/gap-reference-catalog.md#gt-684), [GT-324](../gaps/gap-reference-catalog.md#gt-324), [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-680](../gaps/gap-reference-catalog.md#gt-680), [GT-681](../gaps/gap-reference-catalog.md#gt-681), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-448](../gaps/gap-reference-catalog.md#gt-448) | -| 5 | P2/P3 | Only after security, CI, rules, and contracts stabilize. | [GT-444](../gaps/gap-reference-catalog.md#gt-444), [GT-464](../gaps/gap-reference-catalog.md#gt-464), [GT-674](../gaps/gap-reference-catalog.md#gt-674), [GT-685](../gaps/gap-reference-catalog.md#gt-685), [GT-686](../gaps/gap-reference-catalog.md#gt-686), [GT-687](../gaps/gap-reference-catalog.md#gt-687), +10 | +| 5 | P2/P3 | Only after security, CI, rules, and contracts stabilize. | [GT-444](../gaps/gap-reference-catalog.md#gt-444), [GT-464](../gaps/gap-reference-catalog.md#gt-464), [GT-674](../gaps/gap-reference-catalog.md#gt-674), [GT-685](../gaps/gap-reference-catalog.md#gt-685), [GT-686](../gaps/gap-reference-catalog.md#gt-686), [GT-687](../gaps/gap-reference-catalog.md#gt-687), +11 | ## Current Blockers @@ -42,19 +42,19 @@ Use this summary with a simple rule: if you need context, open only the linked I | Indicator | Value | |---|---:| | Canonical board date | 2026-08-18 | -| Total gaps | 705 | +| Total gaps | 706 | | Closed gaps | 676 | -| Open gaps | 29 | +| Open gaps | 30 | | Open P0 | 1 | | Open P1 | 8 | -| Open P2 | 16 | -| Total closure | 95.9% | +| Open P2 | 17 | +| Total closure | 95.8% | | Closure evidence records | 658 | | Recorded readiness | 4 PASS | | Area | Open | P0 | P1 | First IDs | |---|---:|---:|---:|---| -| `Governance` | 8 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), +4 | +| `Governance` | 9 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), +5 | | `Cross` | 3 | 1 | 1 | [GT-435](../gaps/gap-reference-catalog.md#gt-435), [GT-448](../gaps/gap-reference-catalog.md#gt-448), [GT-651](../gaps/gap-reference-catalog.md#gt-651) | | `MCP Server` | 3 | 0 | 3 | [GT-684](../gaps/gap-reference-catalog.md#gt-684), [GT-680](../gaps/gap-reference-catalog.md#gt-680), [GT-681](../gaps/gap-reference-catalog.md#gt-681) | | `Infra` | 4 | 0 | 1 | [GT-324](../gaps/gap-reference-catalog.md#gt-324), [GT-464](../gaps/gap-reference-catalog.md#gt-464), [GT-685](../gaps/gap-reference-catalog.md#gt-685), [GT-692](../gaps/gap-reference-catalog.md#gt-692) | diff --git a/reference/core/control-center/maturity-reports/maturity-reconciliation.json b/reference/core/control-center/maturity-reports/maturity-reconciliation.json index 64d54b08..64e02f02 100644 --- a/reference/core/control-center/maturity-reports/maturity-reconciliation.json +++ b/reference/core/control-center/maturity-reports/maturity-reconciliation.json @@ -3,17 +3,17 @@ "scope": "evolith-core", "asOf": "2026-08-18", "gaps": { - "total": 705, + "total": 706, "done": 676, "pending": 0, - "inProgress": 2, + "inProgress": 3, "deferred": 27 }, "evidence": { "closureRecords": 658, "cliPackage": "@beyondnet/evolith-cli@1.3.2", - "adrCount": 141, - "rulesetCount": 181, + "adrCount": 142, + "rulesetCount": 182, "schemaCount": 50 }, "readiness": [ diff --git a/reference/core/foundations/agent-skills/po.es.md b/reference/core/foundations/agent-skills/po.es.md index 90a00be4..e38bd4d7 100644 --- a/reference/core/foundations/agent-skills/po.es.md +++ b/reference/core/foundations/agent-skills/po.es.md @@ -98,7 +98,7 @@ Archivar propuestas en `.bmad-core/proposals/` siguiendo el formato en [AGENTS.e Contexto de negocio durable capturado en sesiones de flujo de producto guiadas por el dueño. Carga el registro relevante al validar o priorizar el área afectada: * [Flujo de Ingesta y Oportunidad del Tracker](./tracker-intake-flow.es.md) — Modelo de entrada del Tracker (Fase 0). Notas de negocio: dos orígenes (Oportunidad interna / Intake externo) convergen en una sola Iniciativa; Gate 0 inteligente con criterios de aceptación configurables por tenant sobre un piso fijado por Core; el rechazo es un ciclo de mejora gobernado y versionado (no terminal); `PENDIENTE` desacopla "aprobada" de "activada" (activación agéntica/mixta hacia Discovery). -* [Flujo de Discovery del Tracker](./tracker-discovery-flow.es.md) — Discovery (Fase 1). Notas de negocio: el PRD es el artefacto obligatorio (no-overrideable), con KDD opcional dentro; los tenants pueden solicitar **asesoría de arquitectura** gobernada como apoyo opt-in para de-risquear el diseño de la feature; el borrador de blueprint es opcional y no bloquea el Business Sign-Off; todo se audita en el Tracker. +* [Flujo de Discovery del Tracker](./tracker-discovery-flow.es.md) — Discovery (Fase 1). Notas de negocio: el PRD es el artefacto obligatorio (no-overrideable); los tenants pueden solicitar **asesoría de arquitectura** gobernada como apoyo opt-in para de-risquear el diseño de la feature; el borrador de blueprint es opcional y no bloquea el Business Sign-Off; todo se audita en el Tracker. * [Flujo de Design del Tracker](./tracker-design-flow.es.md) — Design (Fase 2). Notas de negocio: el blueprint es una **guía de desarrollo** que el tenant arma desde un catálogo de bloques (Core canónico ∪ colección privada del tenant); Core es advisory — **mide madurez** y recomienda, el gate del tenant decide el bloqueo; los agentes proponen proactivamente templates/ideas de diseño (simple/medio/complejo); los tenants pueden construir templates reutilizables y promoverlos aguas arriba (UP-NNN). Las herramientas de autoring de diseño viven en el Tracker. * [Flujo Downstream del Tracker](./tracker-downstream-flow.es.md) — Construcción/Calidad/Despliegue (F3-F5). Notas de negocio: el arco SDLC cierra bajo la misma postura advisory — Core da señales continuas no vinculantes + evaluación de gate, el gate del tenant decide; lo que el blueprint planeó (F7) se vuelve lo que estos gates verifican; el Tracker posee toda la ejecución operativa (boards, tests, releases, DORA/SPACE). diff --git a/reference/core/foundations/agent-skills/po.md b/reference/core/foundations/agent-skills/po.md index d8868942..30903caa 100644 --- a/reference/core/foundations/agent-skills/po.md +++ b/reference/core/foundations/agent-skills/po.md @@ -98,7 +98,7 @@ File proposals in `.bmad-core/proposals/` following the format in [AGENTS.md sec Durable business context captured from owner-guided product-flow sessions. Load the relevant record when validating or prioritizing the affected area: * [Tracker Intake & Opportunity Flow](./tracker-intake-flow.md) — Tracker entry model (Fase 0). Business notes: two origins (Opportunity internal / Intake external) converge on one Initiative; intelligent Gate 0 with tenant-configurable acceptance criteria over a Core-set floor; rejection is a governed, versioned improvement cycle (not terminal); `PENDING` decouples "approved" from "activated" (agentic/mixed activation into Discovery). -* [Tracker Discovery Flow](./tracker-discovery-flow.md) — Discovery (Fase 1). Business notes: PRD is the mandatory (non-overrideable) artifact, KDD optional inside it; tenants can request governed **architecture advisory** as opt-in support to de-risk feature design; the blueprint draft is optional and does not block Business Sign-Off; everything is audited in the Tracker. +* [Tracker Discovery Flow](./tracker-discovery-flow.md) — Discovery (Fase 1). Business notes: PRD is the mandatory (non-overrideable) artifact; tenants can request governed **architecture advisory** as opt-in support to de-risk feature design; the blueprint draft is optional and does not block Business Sign-Off; everything is audited in the Tracker. * [Tracker Design Flow](./tracker-design-flow.md) — Design (Fase 2). Business notes: the blueprint is a **development guide** the tenant assembles from a catalog of blocks (Core canonical ∪ tenant's own private collection); Core is advisory — it **measures maturity** and recommends, the tenant's gate decides blocking; agents proactively propose design templates/ideas (simple/medium/complex); tenants can build reusable templates and promote them upstream (UP-NNN). Design authoring tools belong in the Tracker. * [Tracker Downstream Flow](./tracker-downstream-flow.md) — Construction/Quality/Deployment (F3-F5). Business notes: the SDLC arc closes under the same advisory posture — Core gives continuous non-binding signals + gate evaluation, the tenant's gate decides; what the blueprint planned (F7) becomes what these gates check; the Tracker owns all operational execution (boards, tests, releases, DORA/SPACE). diff --git a/reference/core/foundations/agent-skills/tracker-discovery-flow.es.md b/reference/core/foundations/agent-skills/tracker-discovery-flow.es.md index 6fb0f6e6..283210fa 100644 --- a/reference/core/foundations/agent-skills/tracker-discovery-flow.es.md +++ b/reference/core/foundations/agent-skills/tracker-discovery-flow.es.md @@ -12,7 +12,7 @@ ## 1. Propósito -Capturar las decisiones guiadas por el dueño sobre la **fase Discovery de Evolith Tracker**: sus artefactos y criterios, la nueva capability de **asesoría de arquitectura gobernada** (primer puente Tracker→Core-arquitectura), el blueprint progresivo, y el modelo PRD/KDD. Cinco decisiones (D-001…D-005) cerraron el bloque Discovery el 2026-07-04. +Capturar las decisiones guiadas por el dueño sobre la **fase Discovery de Evolith Tracker**: sus artefactos y criterios, la nueva capability de **asesoría de arquitectura gobernada** (primer puente Tracker→Core-arquitectura), el blueprint progresivo, y el modelo de PRD. Cinco decisiones (D-001…D-005) cerraron el bloque Discovery el 2026-07-04. ## 2. Modelo de Discovery Consolidado @@ -20,7 +20,7 @@ Capturar las decisiones guiadas por el dueño sobre la **fase Discovery de Evoli Iniciativa PENDIENTE ──(activación agéntica/mixta, L-012)──► DISCOVERY (Fase 1) │ Artefactos: Discovery Canvas · BusinessCase · TechnicalJustification - · PRD (obligatorio; KDD opcional dentro) ◄── D-004 + · PRD (obligatorio) ◄── D-004 │ ┌── Asesoría de Arquitectura (capability híbrida gobernada, A3) ◄── D-002 │ el tenant invoca con SU agente → corre sobre conocimiento canónico de Core @@ -43,20 +43,20 @@ Iniciativa PENDIENTE ──(activación agéntica/mixta, L-012)──► DISCOVE | D-001 | Discovery tiene **artefactos + criterios** (patrón de gate inteligente, L-006). Gate 1 = Business Sign-Off. | Los criterios de Discovery son configurables (Core default + tenant override). | Mismo motor de gate inteligente; el set de artefactos de Discovery incluye ahora el PRD — reconciliar con el agregado `Initiative` actual que lo omite. | | D-002 | **Asesoría de Arquitectura = capability híbrida gobernada (A3):** el tenant pide apoyo para diseñar su feature; invoca con su propio agente pero corre sobre el conocimiento canónico de Core (blueprints/topologies/ADRs). Primer puente Tracker→Core-arquitectura. | Nuevo valor self-service: expertise de arquitectura gobernada durante Discovery, de-risquea el diseño antes de construcción; eje de producto/monetización. | Encaja con el modelo de autoridad ([[agent-authority-model]]): Hermes gestiona, Core posee el conocimiento, el tenant consume vía puertos. La asesoría NO cede autoridad. Superficie: MCP/Core API sobre el Architecture Hub + `architect`/Winston detrás de `IAgentEnginePort`. Solo contexto gobernado. | | D-003 | **Blueprint progresivo:** la asesoría de-risquea en Discovery **y** un BORRADOR de blueprint empieza a gestarse ahí (apoyo opcional que el tenant puede pedir); Design (Fase 2) lo formaliza. El borrador **NO bloquea el Gate 1**. | El blueprint madura progresivamente desde Discovery — menos sorpresas en el gate de Design; la asesoría es apoyo opt-in, no un obstáculo. | `TechnicalBlueprint` gana un estado draft temprano originado en Discovery; Design lo promueve a formal (Arquitectura Progresiva). El borrador referencia la evidencia de asesoría que lo produjo. | -| D-004 | **PRD obligatorio** en Discovery; **KDD opcional dentro** del PRD. Solo el PRD es **no-overrideable** (piso canónico, L-010); KDD/Canvas/BusinessCase/asesoría son overrideables por tenant. | El PRD es el artefacto de Discovery no-negociable; el KDD lo enriquece cuando hay que garantizar entendimiento. | Schema del PRD en Core con sección KDD opcional; el Gate 1 exige PRD siempre, exige KDD solo si un tenant/criterio lo activa (feature-override). Refina L-009: KDD es sub-artefacto del PRD, no independiente. | +| D-004 | **PRD obligatorio** en Discovery. Solo el PRD es **no-overrideable** (piso canónico, L-010); Canvas/BusinessCase/asesoría son overrideables por tenant. | El PRD es el artefacto de Discovery no-negociable. | Schema del PRD en Core; el Gate 1 exige el PRD siempre. | | D-005 | **Todo deja rastro de evidencia/auditoría en el Tracker; Core es stateless** (ADR-0101). | Cada apoyo/consulta/decisión es auditable en el grafo de evidencias del Tracker — trazabilidad completa idea→producción. | **Frontera dura:** la asesoría *corre sobre* el conocimiento canónico de Core (stateless: contexto → recomendación), pero la **evidencia de la sesión se persiste en el Tracker** (dueño del estado de gobernanza). El "Architecture Advisory Record" es una entidad del Tracker que referencia el resultado stateless de Core. Core nunca guarda la sesión. Refuerza ADR-0101 / Core = Evaluation Engine. | ## 4. Implicaciones Cross-Repo y de Core - **Primer canal Tracker→Core-arquitectura (D-002):** requiere una superficie de asesoría gobernada sobre el Architecture Hub (MCP/Core API), con el razonamiento de `architect`/Winston detrás de `IAgentEnginePort`. Core sigue stateless; el Tracker persiste la evidencia de asesoría (D-005). -- **PRD como piso canónico (D-004):** el schema del PRD (con sección KDD opcional) es candidato al corpus de Core (`src/rulesets/schema/`), heredado por Tracker y satélites; no-overrideable por L-010. +- **PRD como piso canónico (D-004):** el schema del PRD es candidato al corpus de Core (`src/rulesets/schema/`), heredado por Tracker y satélites; no-overrideable por L-010. - **Blueprint progresivo (D-003):** `TechnicalBlueprint` gana un estado draft originado en Discovery que alimenta Design — refinamiento de Arquitectura Progresiva de EPIC-001. - **Reconciliación de agregado:** el agregado `Initiative` del Tracker debe listar el PRD explícitamente (hoy solo lista Canvas/BusinessCase/TechnicalJustification/Checklist). ## 5. Ítems Abiertos - Definir la entidad **Architecture Advisory Record** en el Tracker (campos, enlace al resultado stateless de Core, enlace al borrador de blueprint). -- Confirmar cuáles de KDD / Canvas / asesoría están habilitados por defecto vs. puramente opt-in por tenant. +- Confirmar cuáles de Canvas / asesoría están habilitados por defecto vs. puramente opt-in por tenant. - Ciclo de vida del borrador de blueprint: cómo Design promueve un borrador de Discovery a un `TechnicalBlueprint` formal. ## 6. Procedencia diff --git a/reference/core/foundations/agent-skills/tracker-discovery-flow.md b/reference/core/foundations/agent-skills/tracker-discovery-flow.md index 0f3c1535..22eb78a8 100644 --- a/reference/core/foundations/agent-skills/tracker-discovery-flow.md +++ b/reference/core/foundations/agent-skills/tracker-discovery-flow.md @@ -12,7 +12,7 @@ ## 1. Purpose -Capture the owner-guided decisions on **Evolith Tracker's Discovery phase**: its artifacts and criteria, the new **governed architecture-advisory** capability (first Tracker→Core-architecture bridge), the progressive blueprint, and the PRD/KDD model. Five decisions (D-001…D-005) closed the Discovery block on 2026-07-04. +Capture the owner-guided decisions on **Evolith Tracker's Discovery phase**: its artifacts and criteria, the new **governed architecture-advisory** capability (first Tracker→Core-architecture bridge), the progressive blueprint, and the PRD model. Five decisions (D-001…D-005) closed the Discovery block on 2026-07-04. ## 2. Consolidated Discovery Model @@ -20,7 +20,7 @@ Capture the owner-guided decisions on **Evolith Tracker's Discovery phase**: its PENDING Initiative ──(agentic/mixed activation, L-012)──► DISCOVERY (Fase 1) │ Artifacts: Discovery Canvas · BusinessCase · TechnicalJustification - · PRD (mandatory; KDD optional inside) ◄── D-004 + · PRD (mandatory) ◄── D-004 │ ┌── Architecture Advisory (governed hybrid capability, A3) ◄── D-002 │ tenant invokes with ITS agent → runs over Core's canonical knowledge @@ -43,20 +43,20 @@ PENDING Initiative ──(agentic/mixed activation, L-012)──► DISCOVERY (F | D-001 | Discovery has **artifacts + criteria** (intelligent-gate pattern, L-006). Gate 1 = Business Sign-Off. | Discovery criteria are configurable (Core default + tenant override). | Same intelligent-gate engine; the Discovery artifact set now includes the PRD — reconcile with the current `Initiative` aggregate that omits it. | | D-002 | **Architecture Advisory = governed hybrid capability (A3):** tenant requests support to design its feature; invokes with its own agent but runs over Core's canonical knowledge (blueprints/topologies/ADRs). First Tracker→Core-architecture bridge. | New self-service value: governed architecture expertise during Discovery, de-risks design before construction; product/monetization axis. | Fits the authority model ([[agent-authority-model]]): Hermes manages, Core owns the knowledge, tenant consumes via ports. Advisory cedes NO authority. Surface: MCP/Core API over the Architecture Hub + `architect`/Winston behind `IAgentEnginePort`. Governed context only. | | D-003 | **Progressive blueprint:** advisory de-risks in Discovery **and** a blueprint DRAFT begins gestating there (optional support the tenant may request); Design (Fase 2) formalizes it. The draft **does NOT block Gate 1**. | Blueprint matures progressively from Discovery — fewer surprises at the Design gate; the advisory is opt-in support, not a hurdle. | `TechnicalBlueprint` gains an early draft state originated in Discovery; Design promotes it to formal (Progressive Architecture). Draft references the advisory evidence that produced it. | -| D-004 | **PRD mandatory** in Discovery; **KDD optional inside** the PRD. Only the PRD is **non-overrideable** (canonical floor, L-010); KDD/Canvas/BusinessCase/advisory are tenant-overrideable. | PRD is the non-negotiable Discovery artifact; KDD enriches it when understanding must be guaranteed. | PRD schema in Core with an optional KDD section; Gate 1 always requires PRD, requires KDD only if a tenant/criterion activates it (feature-override). Refines L-009: KDD is a PRD sub-artifact, not standalone. | +| D-004 | **PRD mandatory** in Discovery. Only the PRD is **non-overrideable** (canonical floor, L-010); Canvas/BusinessCase/advisory are tenant-overrideable. | PRD is the non-negotiable Discovery artifact. | PRD schema in Core; Gate 1 always requires the PRD. | | D-005 | **Everything leaves an evidence/audit trail in the Tracker; Core is stateless** (ADR-0101). | Every support/consultation/decision is auditable in the Tracker's evidence graph — full idea→production traceability. | **Hard boundary:** the advisory *runs over* Core's canonical knowledge (stateless: context in → recommendation out), but the session **evidence is persisted in the Tracker** (owner of governance state). The "Architecture Advisory Record" is a Tracker entity referencing Core's stateless result. Core never stores the session. Reinforces ADR-0101 / Core = Evaluation Engine. | ## 4. Cross-Repo & Core Implications - **First Tracker→Core-architecture channel (D-002):** requires a governed advisory surface over the Architecture Hub (MCP/Core API), with the `architect`/Winston reasoning behind `IAgentEnginePort`. Core stays stateless; Tracker persists the advisory evidence (D-005). -- **PRD as canonical floor (D-004):** PRD schema (with optional KDD section) is a Core-corpus candidate (`src/rulesets/schema/`), inherited by Tracker and satellites; non-overrideable per L-010. +- **PRD as canonical floor (D-004):** the PRD schema is a Core-corpus candidate (`src/rulesets/schema/`), inherited by Tracker and satellites; non-overrideable per L-010. - **Progressive blueprint (D-003):** `TechnicalBlueprint` gains a Discovery-originated draft state feeding Design — a Progressive-Architecture refinement of EPIC-001. - **Aggregate reconciliation:** the Tracker `Initiative` aggregate must list the PRD explicitly (today it lists Canvas/BusinessCase/TechnicalJustification/Checklist only). ## 5. Open Items - Define the **Architecture Advisory Record** entity in the Tracker (fields, link to Core's stateless result, link to blueprint draft). -- Confirm which of KDD / Canvas / advisory are enabled by default vs. purely opt-in per tenant. +- Confirm which of Canvas / advisory are enabled by default vs. purely opt-in per tenant. - Blueprint draft lifecycle: how Design promotes a Discovery draft to a formal `TechnicalBlueprint`. ## 6. Provenance diff --git a/reference/core/foundations/agent-skills/tracker-intake-flow.es.md b/reference/core/foundations/agent-skills/tracker-intake-flow.es.md index 671cf876..759b2eaa 100644 --- a/reference/core/foundations/agent-skills/tracker-intake-flow.es.md +++ b/reference/core/foundations/agent-skills/tracker-intake-flow.es.md @@ -47,7 +47,6 @@ Capturar las decisiones guiadas por el dueño sobre **cómo entra el trabajo a E │ │ ▼ cerrada con historial DISCOVERY (formal) - (+ KDD opcional) ``` ## 3. Registros de Aprendizaje (L-001 … L-012) @@ -60,16 +59,15 @@ Capturar las decisiones guiadas por el dueño sobre **cómo entra el trabajo a E | L-004 | Feedback de rechazo **dual** (humano+agente), **evolutivo**, **versionado**; itera hasta lograrlo o hasta que el proponente acepta. | El rechazo no es terminal por defecto; ciclo de mejora gobernado con historial. | La propuesta de entrada es un artefacto versionado en el grafo de evidencias; Gate 0 es **re-entrante**. | | L-005 | `IIniciativa` es una **interface única**; Intake y Oportunidad tienen cada una su interface + ACL que adapta a ella. Aprobada → estado **PENDIENTE**. | Un solo concepto río abajo; la diversidad de origen se encapsula en la frontera. | **ACLs simétricos** (`OpportunityACL` interno, `IntakeACL` externo); ningún concepto de origen se filtra al dominio; nuevo estado `PENDIENTE`. | | L-006 | **Gate 0 inteligente**: Core define criterios mínimos de aceptación por defecto; el **tenant puede override** a su realidad. | El default protege el estándar; el override respeta la realidad tenant/producto (valor enterprise). | Extiende `TenantConfig`. **Responde directamente a los gaps GT-08…GT-11 de Core** (existencia → contenido/umbral + parametrización). | -| L-007 | Activar una iniciativa PENDIENTE **inicia Discovery formal** (flujo/artefactos KDD opcionales). | PENDIENTE → Discovery = "aceptada" → "en elaboración". | `PENDIENTE` precede a Discovery; realinear con el `Initiative (DRAFT)` actual; KDD es módulo de feature-override. | +| L-007 | Activar una iniciativa PENDIENTE **inicia Discovery formal**. | PENDIENTE → Discovery = "aceptada" → "en elaboración". | `PENDIENTE` precede a Discovery; realinear con el `Initiative (DRAFT)` actual. | | L-008 | **Todo lo canónico vive en Core** y se hereda (Tracker **y** satélites) como formato. | Un estándar sirve a todo el ecosistema; menor costo de gobernanza. | Confirma Hub-and-Spoke (Visión §4.1); los overrides locales nunca mutan el canon sin aprobación del Board. | -| L-009 | **KDD = Knowledge-Driven Development**: conjunto de artefactos que garantizan el entendimiento del producto/feature. | Entrega entendimiento verificable antes de avanzar. | Schema propio (candidato al corpus de Core); cuando está activo, sus artefactos son evidencia de gate en Discovery. | | L-010 | El **piso inmutable lo define CORE** (no el ADMIN ROOT del SaaS). El ADMIN ROOT solo opera la capa overrideable. | Los tenants no pueden vaciar el gate; nuevo actor de plataforma (ADMIN ROOT) acotado. | Preserva Visión §4.3 ("Core rule definition → Evolith Core"); resuelve la divergencia de satélites — el piso es de Core para todos. | | L-011 | La **terminación del ciclo de rechazo es configurable** (default en Core + override tenant). | Parametrizable (máx iteraciones / ventana de estancamiento). | Política `rejectionCycle` en el corpus de Core; el Gate 0 la lee para auto-archivo/escalamiento. | | L-012 | La activación PENDIENTE → Discovery es **agéntica/mixta** (agente de priorización + confirmación humana opcional). | Confirma "aprobada ≠ activada"; PENDIENTE es una cola de portafolio gobernada. | El agente de priorización = capability gobernada (capacidad/ROI/deps) + `IApprovalPort`; punto de transición auditable. | ## 4. Implicaciones Cross-Repo y de Core -- **Adiciones implícitas al corpus de Core:** schema del formato unificado de entrada (L-002/L-008), criterios default de aceptación del Gate 0 + designación del piso inmutable (L-006/L-010), política `rejectionCycle` (L-011), schema de artefactos KDD (L-009). Candidatos a `src/rulesets/schema/` + rulesets, heredados por Tracker y satélites. +- **Adiciones implícitas al corpus de Core:** schema del formato unificado de entrada (L-002/L-008), criterios default de aceptación del Gate 0 + designación del piso inmutable (L-006/L-010), política `rejectionCycle` (L-011). Candidatos a `src/rulesets/schema/` + rulesets, heredados por Tracker y satélites. - **Conexión estratégica:** L-006 aporta el requisito de producto para cerrar **GT-08…GT-11** (validación de contenido/umbral de gates) — la mayor brecha de credibilidad del maturity assessment actual. - **Nuevo actor:** ADMIN ROOT (super-admin del SaaS) — opera solo la capa overrideable; no tiene autoridad del piso (L-010). - **Cambio de máquina de estados:** el modelo one-shot `PROMOTED | REJECTED` del Intake se reemplaza por una máquina iterativa, versionada y re-entrante (L-004/L-011). @@ -77,12 +75,11 @@ Capturar las decisiones guiadas por el dueño sobre **cómo entra el trabajo a E ## 5. Ítems Abiertos - Realinear `PENDIENTE` con el `Initiative (DRAFT)` actual del Tracker (US-DIS-001): renombrar vs. preceder. -- Confirmar el conjunto de artefactos KDD y cuáles son obligatorios vs. opcionales por tenant. - Decidir el detalle de precedencia dentro de la capa overrideable (tenant vs producto). ## 6. Procedencia -Capturado durante una sesión de flujo de producto guiada por el dueño (2026-07-04). Notas de trabajo fuente rastreadas en la sesión. Próximo bloque: **Discovery (Fase 1)** con el módulo KDD. La promoción de cualquier ítem a reglas vinculantes de Core requiere un ADR. +Capturado durante una sesión de flujo de producto guiada por el dueño (2026-07-04). Notas de trabajo fuente rastreadas en la sesión. Próximo bloque: **Discovery (Fase 1)**. La promoción de cualquier ítem a reglas vinculantes de Core requiere un ADR. --- diff --git a/reference/core/foundations/agent-skills/tracker-intake-flow.md b/reference/core/foundations/agent-skills/tracker-intake-flow.md index cdc9b092..2b451035 100644 --- a/reference/core/foundations/agent-skills/tracker-intake-flow.md +++ b/reference/core/foundations/agent-skills/tracker-intake-flow.md @@ -47,7 +47,6 @@ Capture the owner-guided decisions about **how work enters Evolith Tracker**, so │ │ ▼ closed w/ full history DISCOVERY (formal) - (+ KDD optional) ``` ## 3. Learning Records (L-001 … L-012) @@ -60,16 +59,15 @@ Capture the owner-guided decisions about **how work enters Evolith Tracker**, so | L-004 | Rejection feedback is **dual** (human+agent), **evolutionary**, **versioned**; iterate until success or proposer accepts. | Rejection is not terminal by default; a governed improvement cycle with history. | Entry proposal is a versioned artifact in the evidence graph; Gate 0 is **re-entrant**. | | L-005 | `IInitiative` is a **single interface**; Intake and Opportunity each have their own interface + ACL adapting to it. Approved → status **PENDING**. | One downstream concept; origin diversity encapsulated at the boundary. | **Symmetric ACLs** (`OpportunityACL` internal, `IntakeACL` external); no origin concept leaks into the domain; new `PENDING` state. | | L-006 | **Intelligent Gate 0**: Core sets default minimum acceptance criteria; **tenant can override** to its reality. | Default protects the standard; override respects tenant/product reality (enterprise value). | Extends `TenantConfig`. **Directly answers Core gaps GT-08…GT-11** (existence-checks → content/threshold + parametrization). | -| L-007 | Activating a PENDING initiative **starts formal Discovery** (KDD flow/artifacts optional). | PENDING → Discovery = "accepted" → "in elaboration". | `PENDING` precedes Discovery; realign with current `Initiative (DRAFT)`; KDD is a feature-override module. | +| L-007 | Activating a PENDING initiative **starts formal Discovery**. | PENDING → Discovery = "accepted" → "in elaboration". | `PENDING` precedes Discovery; realign with current `Initiative (DRAFT)`. | | L-008 | **Everything canonical lives in Core** and is inherited (Tracker **and** satellites) as format. | One standard serves the whole ecosystem; lower governance cost. | Confirms Hub-and-Spoke (Vision §4.1); local overrides never mutate the canon without Board approval. | -| L-009 | **KDD = Knowledge-Driven Development**: a set of artifacts guaranteeing product/feature understanding. | Delivers verifiable understanding before advancing. | Own schema (Core corpus candidate); when active, its artifacts are Discovery gate evidence. | | L-010 | The immutable **floor is defined by CORE** (not the SaaS ADMIN ROOT). ADMIN ROOT only operates the overrideable layer. | Tenants cannot empty the gate; new platform actor (ADMIN ROOT) bounded. | Preserves Vision §4.3 ("Core rule definition → Evolith Core"); resolves satellite divergence — floor is Core's for all. | | L-011 | Rejection-cycle **termination is configurable** (Core default + tenant override). | Parametrizable (max iterations / staleness window). | `rejectionCycle` policy in Core corpus; Gate 0 reads it for auto-archive/escalation. | | L-012 | PENDING → Discovery activation is **agentic/mixed** (prioritization agent + optional human confirmation). | Confirms "approved ≠ activated"; PENDING is a governed portfolio queue. | Prioritization agent = governed capability (capacity/ROI/deps) + `IApprovalPort`; auditable transition point. | ## 4. Cross-Repo & Core Implications -- **Core corpus additions implied:** unified entry-format schema (L-002/L-008), Gate 0 default acceptance criteria + immutable-floor designation (L-006/L-010), `rejectionCycle` policy (L-011), KDD artifact schema (L-009). Candidates for `src/rulesets/schema/` + rulesets, inherited by Tracker and satellites. +- **Core corpus additions implied:** unified entry-format schema (L-002/L-008), Gate 0 default acceptance criteria + immutable-floor designation (L-006/L-010), `rejectionCycle` policy (L-011). Candidates for `src/rulesets/schema/` + rulesets, inherited by Tracker and satellites. - **Strategic connection:** L-006 supplies the product requirement to close **GT-08…GT-11** (gate content/threshold validation) — the single biggest credibility gap in the current maturity assessment. - **New actor:** ADMIN ROOT (SaaS super-admin) — operates the overrideable layer only; does not hold floor authority (L-010). - **State-machine change:** the one-shot `PROMOTED | REJECTED` Intake model is replaced by an iterative, versioned, re-entrant machine (L-004/L-011). @@ -77,12 +75,11 @@ Capture the owner-guided decisions about **how work enters Evolith Tracker**, so ## 5. Open Items - Realign `PENDING` with the Tracker's current `Initiative (DRAFT)` (US-DIS-001): rename vs. precede. -- Confirm KDD artifact set and which are mandatory vs. optional per tenant. - Decide precedence detail within the overrideable layer (tenant vs product). ## 6. Provenance -Captured during an owner-guided product-flow session (2026-07-04). Source working notes tracked in-session. Next block: **Discovery (Fase 1)** with the KDD module. Promotion of any item into binding Core rules requires an ADR. +Captured during an owner-guided product-flow session (2026-07-04). Source working notes tracked in-session. Next block: **Discovery (Fase 1)**. Promotion of any item into binding Core rules requires an ADR. --- diff --git a/reference/core/foundations/agent-skills/winston.es.md b/reference/core/foundations/agent-skills/winston.es.md index 8c39e37a..b749173f 100644 --- a/reference/core/foundations/agent-skills/winston.es.md +++ b/reference/core/foundations/agent-skills/winston.es.md @@ -162,8 +162,8 @@ Como Garante de Estándares, aplicas estrictamente los siguientes recursos de In Contexto de diseño durable capturado en sesiones de flujo de producto guiadas por el dueño. Carga el registro relevante antes de auditar la superficie afectada: -* [Flujo de Ingesta y Oportunidad del Tracker](./tracker-intake-flow.es.md) — Modelo de entrada del Tracker (Fase 0). Notas de arquitectura: ACLs simétricos por origen → única `IIniciativa`; Gate 0 inteligente (default de Core + override de tenant, piso inmutable fijado por Core) como el requisito de producto detrás de **GT-08…GT-11**; ciclo de rechazo re-entrante y versionado; los schemas canónicos de formato de entrada/KDD pertenecen al corpus de Core. -* [Flujo de Discovery del Tracker](./tracker-discovery-flow.es.md) — Discovery (Fase 1). Notas de arquitectura: la capability de **asesoría de arquitectura** gobernada (A3) es el primer puente Tracker→Core-arquitectura — corre sobre el conocimiento stateless de Core, evidencia persistida en Tracker (ADR-0101); borrador de blueprint progresivo (no bloquea el Gate 1); el PRD es el piso canónico con KDD como sub-artefacto opcional. +* [Flujo de Ingesta y Oportunidad del Tracker](./tracker-intake-flow.es.md) — Modelo de entrada del Tracker (Fase 0). Notas de arquitectura: ACLs simétricos por origen → única `IIniciativa`; Gate 0 inteligente (default de Core + override de tenant, piso inmutable fijado por Core) como el requisito de producto detrás de **GT-08…GT-11**; ciclo de rechazo re-entrante y versionado; el schema canónico de formato de entrada pertenece al corpus de Core. +* [Flujo de Discovery del Tracker](./tracker-discovery-flow.es.md) — Discovery (Fase 1). Notas de arquitectura: la capability de **asesoría de arquitectura** gobernada (A3) es el primer puente Tracker→Core-arquitectura — corre sobre el conocimiento stateless de Core, evidencia persistida en Tracker (ADR-0101); borrador de blueprint progresivo (no bloquea el Gate 1); el PRD es el piso canónico. * [Flujo de Design del Tracker](./tracker-design-flow.es.md) + **[ADR-0104](../../architecture/adrs/core/0104-topology-driven-advisory-design-governance.es.md)** — Design (Fase 2), postura advisory. Notas de arquitectura: **blueprint = guía de desarrollo detallada**, compuesto multi-concern (frontend/backend/services/mobile/data) bajo Convention over Configuration (block-type registry, extensibilidad perpetua); topología confirmada como composición (mixable) que dirige la unión de `designProfile`; Core recomienda/valida/**mide madurez** (no vinculante), deriva criterios downstream; catálogo efectivo = Core canónico ∪ colección privada del tenant (Core stateless). Implementación = épico **GT-425** (F1–F8). * [Flujo Downstream del Tracker](./tracker-downstream-flow.es.md) — Construcción/Calidad/Despliegue (F3-F5). Notas de arquitectura: Core es advisory en las tres (señales continuas de drift/calidad/readiness + evaluación de gate no vinculante); los `downstreamCriteria` derivados del blueprint (F7) configuran los gates; el Tracker posee toda la ejecución operativa (boards/tests/releases), Core sigue stateless. * [Modelo de Autoridad de Agentes](./agent-authority-model.es.md) — Hermes gestiona; los agentes de Core del dueño gobiernan la Constitución; los tenants traen sus propios modelos/agentes. Frontera aplicada vía `IAgentEnginePort`. diff --git a/reference/core/foundations/agent-skills/winston.md b/reference/core/foundations/agent-skills/winston.md index 7b177752..5b92f271 100644 --- a/reference/core/foundations/agent-skills/winston.md +++ b/reference/core/foundations/agent-skills/winston.md @@ -164,8 +164,8 @@ As the Standards Enforcer, you strictly apply the following BMAD Intelligence re Durable design context captured from owner-guided product-flow sessions. Load the relevant record before auditing the affected surface: -* [Tracker Intake & Opportunity Flow](./tracker-intake-flow.md) — Tracker entry model (Fase 0). Architecture notes: symmetric origin ACLs → single `IInitiative`; intelligent Gate 0 (Core default + tenant override, Core-set immutable floor) as the product requirement behind **GT-08…GT-11**; re-entrant versioned rejection cycle; canonical entry format/KDD schemas belong in Core corpus. -* [Tracker Discovery Flow](./tracker-discovery-flow.md) — Discovery (Fase 1). Architecture notes: governed **architecture-advisory** capability (A3) is the first Tracker→Core-architecture bridge — runs over Core's stateless knowledge, evidence persisted in Tracker (ADR-0101); progressive blueprint draft (does not block Gate 1); PRD is the canonical floor with KDD as an optional sub-artifact. +* [Tracker Intake & Opportunity Flow](./tracker-intake-flow.md) — Tracker entry model (Fase 0). Architecture notes: symmetric origin ACLs → single `IInitiative`; intelligent Gate 0 (Core default + tenant override, Core-set immutable floor) as the product requirement behind **GT-08…GT-11**; re-entrant versioned rejection cycle; the canonical entry-format schema belongs in Core corpus. +* [Tracker Discovery Flow](./tracker-discovery-flow.md) — Discovery (Fase 1). Architecture notes: governed **architecture-advisory** capability (A3) is the first Tracker→Core-architecture bridge — runs over Core's stateless knowledge, evidence persisted in Tracker (ADR-0101); progressive blueprint draft (does not block Gate 1); PRD is the canonical floor. * [Tracker Design Flow](./tracker-design-flow.md) + **[ADR-0104](../../architecture/adrs/core/0104-topology-driven-advisory-design-governance.md)** — Design (Fase 2), advisory posture. Architecture notes: **blueprint = detailed development guide**, composed multi-concern (frontend/backend/services/mobile/data) under Convention over Configuration (block-type registry, perpetual extensibility); topology confirmed as a composition (mixable) driving `designProfile` union; Core recommends/validates/**measures maturity** (non-binding), derives downstream criteria; effective catalog = Core canonical ∪ tenant private collection (Core stateless). Implementation = epic **GT-425** (F1–F8). * [Tracker Downstream Flow](./tracker-downstream-flow.md) — Construction/Quality/Deployment (F3-F5). Architecture notes: Core is advisory in all three (continuous drift/quality/readiness signals + non-binding gate evaluation); the blueprint-derived `downstreamCriteria` (F7) configure the gates; the Tracker owns all operational execution (boards/tests/releases), Core stays stateless. * [Agent Authority Model](./agent-authority-model.md) — Hermes manages; owner's Core agents govern the Constitution; tenants bring their own models/agents. Boundary enforced via `IAgentEnginePort`. diff --git a/reference/core/product-initiative-governance-redesign.es.md b/reference/core/product-initiative-governance-redesign.es.md index 7e84b575..50925842 100644 --- a/reference/core/product-initiative-governance-redesign.es.md +++ b/reference/core/product-initiative-governance-redesign.es.md @@ -21,6 +21,8 @@ **Owner:** Evolith Architecture Board **Origen:** Análisis multi-agente anclado en código real (9 agentes, verificación adversarial). Ver Apéndice B. +> **⚠ Segundo aviso de corrección (2026-08-18) — la mitad KDD de este análisis quedó sin objeto.** Varias filas de abajo prescriben *reetiquetar* las plantillas de Knowledge-First Discovery (`story-seed-bank`, `epic-candidate-matrix`, `capability-map`, `discovery-knowledge-brief`, `discovery-context-pack`, `discovery-readiness-gate`, `assumptions-questions-log`) y anotar la cadena `epicCandidateId → storySeedId → backlogItemId`. Esos ficheros ya no existen y esa cadena ya desapareció: **la Fase 1.1 y el concepto KDD fueron retirados por completo** — ver [ADR-0127](./architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md). El diagnóstico de esas filas era correcto; su remedio quedó superado por la eliminación, así que no ejecutes las instrucciones tal como están escritas. + --- ## Tesis central diff --git a/reference/core/product-initiative-governance-redesign.md b/reference/core/product-initiative-governance-redesign.md index f10277b0..961a5e8f 100644 --- a/reference/core/product-initiative-governance-redesign.md +++ b/reference/core/product-initiative-governance-redesign.md @@ -21,6 +21,8 @@ **Owner:** Evolith Architecture Board **Origin:** Multi-agent analysis anchored in real code (9 agents, adversarial verification). See Appendix B. +> **⚠ Second correction notice (2026-08-18) — the KDD half of this analysis is moot.** Several rows below prescribe *relabeling* the Knowledge-First Discovery templates (`story-seed-bank`, `epic-candidate-matrix`, `capability-map`, `discovery-knowledge-brief`, `discovery-context-pack`, `discovery-readiness-gate`, `assumptions-questions-log`) and annotating the `epicCandidateId → storySeedId → backlogItemId` chain. Those files no longer exist and that chain is already gone: **Phase 1.1 and the KDD concept were retired outright** — see [ADR-0127](./architecture/adrs/core/0127-retire-knowledge-first-discovery.md). The diagnosis in those rows was right; its remedy has been overtaken by removal, so do not act on the instructions as written. + --- ## Central thesis diff --git a/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.es.md b/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.es.md index fac102ed..461e8ca0 100644 --- a/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.es.md +++ b/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.es.md @@ -79,8 +79,6 @@ Después de que un plan es **APROBADO** y **EJECUTADO**, el sistema instancia el ``` Architecture Plan (Aprobado) ──→ Iniciativa Creada - │ - ├──→ Fase SDLC 01.1 (Knowledge-First Discovery) │ └──→ ADRs Obligatorios / Artefactos vinculados ``` diff --git a/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.md b/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.md index f4e60769..a5718169 100644 --- a/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.md +++ b/reference/core/sdlc/01-playbooks/00-architecture-planning-gate-intake.md @@ -79,8 +79,6 @@ After a plan is **APPROVED** and **EXECUTED**, the system instantiates the SDLC: ``` Architecture Plan (Approved) ──→ Initiative Created - │ - ├──→ SDLC Phase 01.1 (Knowledge-First Discovery) │ └──→ Mandatory ADRs / Artifacts linked ``` diff --git a/reference/core/sdlc/01-playbooks/README.es.md b/reference/core/sdlc/01-playbooks/README.es.md index bfe2a640..7bae1052 100644 --- a/reference/core/sdlc/01-playbooks/README.es.md +++ b/reference/core/sdlc/01-playbooks/README.es.md @@ -9,7 +9,6 @@ Este directorio contiene playbooks para cada compuerta de fase del SDLC. | Archivo | Propósito | | :--- | :--- | | [`phase-1-business-signoff.es.md`](./phase-1-business-signoff.es.md) | Compuerta Fase 1 — Lista de verificación de aprobación de negocio | -| [`phase-1.1-knowledge-first-discovery.es.md`](./phase-1.1-knowledge-first-discovery.es.md) | Subfase 1.1 — Compuerta Knowledge-First Discovery (opcional, progresiva) | | [`phase-2-design-baseline.es.md`](./phase-2-design-baseline.es.md) | Compuerta Fase 2 — Validación de línea base de arquitectura | | [`phase-3-construction-baseline.es.md`](./phase-3-construction-baseline.es.md) | Compuerta Fase 3 — Bucle interno de construcción y Build Exitoso | | [`phase-4-rc-stamp.es.md`](./phase-4-rc-stamp.es.md) | Compuerta Fase 4 — Sello de candidato a liberación | diff --git a/reference/core/sdlc/01-playbooks/README.md b/reference/core/sdlc/01-playbooks/README.md index 24f99c89..ae66a05a 100644 --- a/reference/core/sdlc/01-playbooks/README.md +++ b/reference/core/sdlc/01-playbooks/README.md @@ -9,7 +9,6 @@ This directory contains playbooks for each SDLC phase gate. | File | Purpose | | :--- | :--- | | [`phase-1-business-signoff.md`](./phase-1-business-signoff.md) | Phase 1 gate — Business sign-off checklist | -| [`phase-1.1-knowledge-first-discovery.md`](./phase-1.1-knowledge-first-discovery.md) | Phase 1.1 subphase — Knowledge-First Discovery gate (optional, progressive) | | [`phase-2-design-baseline.md`](./phase-2-design-baseline.md) | Phase 2 gate — Architecture baseline validation | | [`phase-3-construction-baseline.md`](./phase-3-construction-baseline.md) | Phase 3 gate — Construction inner loop and Successful Build | | [`phase-4-rc-stamp.md`](./phase-4-rc-stamp.md) | Phase 4 gate — Release candidate stamp | diff --git a/reference/core/sdlc/01-playbooks/phase-1-business-signoff.es.md b/reference/core/sdlc/01-playbooks/phase-1-business-signoff.es.md index cde9820d..ba1f95da 100644 --- a/reference/core/sdlc/01-playbooks/phase-1-business-signoff.es.md +++ b/reference/core/sdlc/01-playbooks/phase-1-business-signoff.es.md @@ -20,7 +20,6 @@ Antes de abrir la compuerta, confirmar: - La iniciativa está registrada en el backlog de portafolio con un identificador único. - Existen Patrocinador Ejecutivo y Product Owner nominados y reconocidos. - Se identificaron el Reference Blueprint de Evolith aplicable y la línea base topológica. -- El nivel de adopción de la Fase 1.1 (Knowledge-First Discovery) ha sido declarado. Si se seleccionó Nivel ≥ 1, el resultado del Gate de Preparación de Discovery (PASS o CONDITIONAL) debe estar archivado. Un resultado FAIL bloquea esta compuerta. Ver [Playbook Fase 1.1](./phase-1.1-knowledge-first-discovery.es.md). Si falta cualquier condición, **no iniciar la compuerta**. Volver más tarde evita retrabajo. @@ -33,10 +32,10 @@ Cada fila se corresponde con una entrada `mandatoryEvidence` de la compuerta de | # | Evidencia Obligatoria | Plantilla / Esquema | Criterio de Aceptación | |---|---|---|---| | 1 | PRD — Product Requirements Document | [`prd-template.es.md`](../04-artifact-templates/prd-template.es.md) · [`prd.schema.json`](../../../../src/rulesets/schema/prd.schema.json) | `status = Approved`, `approvalEvidence` poblado, `approvalDate` completada | -| 2 | Discovery Canvas | Registro de la iniciativa | Dolores del cliente, valor esperado y persona objetivo documentados. Si se aplicó Fase 1.1 Nivel ≥ 1, este artefacto debe reflejar el Discovery Knowledge Brief. | +| 2 | Discovery Canvas | Registro de la iniciativa | Dolores del cliente, valor esperado y persona objetivo documentados. | | 3 | Canvas de Factibilidad Técnica | [`technical-feasibility.schema.json`](../../../../src/rulesets/schema/technical-feasibility.schema.json) | Atributos de calidad y NFRs registrados con umbrales medibles | -| 4 | Estimación Ballpark | Bitácora T-Shirt sizing | Composición del equipo y supuestos de sizing declarados. Si se aplicó Fase 1.1 Nivel ≥ 2, el sizing del Story Seed Bank debe ser incorporado. | -| 5 | Matriz MoSCoW | Worksheet MoSCoW | Al menos un MUST y distribución Must/Should/Could/Won't válida. Si se aplicó Fase 1.1 Nivel ≥ 2, la Matriz de Candidatos a Épica sirve como este artefacto — no se requiere worksheet MoSCoW independiente. | +| 4 | Estimación Ballpark | Bitácora T-Shirt sizing | Composición del equipo y supuestos de sizing declarados. | +| 5 | Matriz MoSCoW | Worksheet MoSCoW | Al menos un MUST y distribución Must/Should/Could/Won't válida. | | 6 | Análisis Build-versus-Compose | [`build-vs-compose.schema.json`](../../../../src/rulesets/schema/build-vs-compose.schema.json) | Disposición Adoptar / Embeber / Integrar / Extender / Construir / Rechazar con costo a 3 años, licenciamiento, aislamiento por tenant, reemplazabilidad y requisitos de PoC (Product Vision §5.3) | --- diff --git a/reference/core/sdlc/01-playbooks/phase-1-business-signoff.md b/reference/core/sdlc/01-playbooks/phase-1-business-signoff.md index 6214687f..983d8219 100644 --- a/reference/core/sdlc/01-playbooks/phase-1-business-signoff.md +++ b/reference/core/sdlc/01-playbooks/phase-1-business-signoff.md @@ -20,7 +20,6 @@ Before opening the gate, confirm: - The initiative is registered in the portfolio backlog with a unique identifier. - An Executive Sponsor and a Product Owner are nominated and acknowledged. - The applicable Evolith Reference Blueprint and topology baseline are identified. -- Phase 1.1 (Knowledge-First Discovery) adoption level has been declared. If Level ≥ 1 was selected, the Discovery Readiness Gate outcome (PASS or CONDITIONAL) must be on file. A FAIL result blocks this gate. See [Phase 1.1 Playbook](./phase-1.1-knowledge-first-discovery.md). If any pre-condition is missing, **do not start the gate**. Returning later avoids re-work. @@ -33,10 +32,10 @@ Each row below maps to a `mandatoryEvidence` entry in the Phase 1 gate. Use the | # | Mandatory Evidence | Template / Schema | Acceptance Criterion | |---|---|---|---| | 1 | PRD — Product Requirements Document | [`prd-template.md`](../04-artifact-templates/prd-template.md) · [`prd.schema.json`](../../../../src/rulesets/schema/prd.schema.json) | `status = Approved`, `approvalEvidence` populated, `approvalDate` filled | -| 2 | Discovery Canvas | Initiative registry entry | Customer pains, expected value, and target persona documented. If Phase 1.1 Level ≥ 1 was applied, this artifact must reflect the Discovery Knowledge Brief. | +| 2 | Discovery Canvas | Initiative registry entry | Customer pains, expected value, and target persona documented. | | 3 | Technical Feasibility Canvas | [`technical-feasibility.schema.json`](../../../../src/rulesets/schema/technical-feasibility.schema.json) | Quality attributes and NFRs recorded with measurable thresholds | -| 4 | Ballpark Estimation | T-Shirt sizing log | Team composition and sizing assumptions stated. If Phase 1.1 Level ≥ 2 was applied, Story Seed Bank sizing must be incorporated. | -| 5 | MoSCoW Prioritization Matrix | MoSCoW worksheet | At least one MUST item, valid Must/Should/Could/Won't distribution. If Phase 1.1 Level ≥ 2 was applied, the Epic Candidate Matrix serves as this artifact — no standalone MoSCoW worksheet required. | +| 4 | Ballpark Estimation | T-Shirt sizing log | Team composition and sizing assumptions stated. | +| 5 | MoSCoW Prioritization Matrix | MoSCoW worksheet | At least one MUST item, valid Must/Should/Could/Won't distribution. | | 6 | Build-versus-Compose Analysis | [`build-vs-compose.schema.json`](../../../../src/rulesets/schema/build-vs-compose.schema.json) | Adopt / Embed / Integrate / Extend / Build / Reject disposition with three-year cost, licensing, tenant isolation, replaceability, and PoC requirements (Product Vision §5.3) | --- diff --git a/reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.es.md b/reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.es.md deleted file mode 100644 index d6594c18..00000000 --- a/reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.es.md +++ /dev/null @@ -1,158 +0,0 @@ -# Fase 1.1 — Gate de Knowledge-First Discovery / KDD Readiness - -> **Navegación Bilingüe:** [English Version](./phase-1.1-knowledge-first-discovery.md) - -**Fase:** 01 — Concepción y Descubrimiento -**Subfase:** 01.1 — Knowledge-First Discovery / KDD Readiness -**Tipo de Gate:** Opcional, progresivo -**Rol Responsable:** Business Discovery Agent / Product Owner -**Autoridad de Waiver:** Sponsor Ejecutivo - ---- - -## Propósito - -Este playbook operacionaliza el gate de Knowledge-First Discovery dentro de la Fase 01. Valida que se ha capturado el conocimiento mínimo suficiente antes de crear cualquier épica, historia o ítem de backlog. El gate es opcional y escala desde ligero (Nivel 1) hasta enterprise-regulado (Nivel 4). - ---- - -## Cuándo Aplicar - -| Escenario | Nivel Recomendado | -|-----------|------------------| -| Corrección pequeña o cambio trivial | Nivel 0 (omitir) | -| Dominio bien entendido, equipo experimentado | Nivel 1 (Ligero) | -| Producto nuevo o feature significativa | Nivel 2 (Estándar) | -| Modernización de legacy o integración compleja | Nivel 3 (Gobernado) | -| Industria regulada (finanzas, salud, gobierno) | Nivel 4 (Enterprise) | -| Onboarding de repositorio satélite | Nivel 2-3 | - ---- - -## Agentes de Discovery - -Cada paso en el procedimiento del gate es soportado por un agente de IA especializado definido en [`AGENTS.es.md §Agentes de Discovery`](../../../../AGENTS.es.md#agentes-de-intake-y-discovery-fases-00-y-011). Invoque a los agentes en esta secuencia; la salida de cada agente es la entrada del siguiente agente: - -| Agente | Artefacto Producido | Nivel | -|---|---|:---:| -| Business Discovery Agent | Discovery Knowledge Brief (borrador) | 1+ | -| Product Framing Agent | Knowledge Brief (validado), Context Pack | 1+ | -| Capability Modeling Agent | Mapa de Capacidades | 2+ | -| Epic Discovery Agent | Matriz de Candidatos a Épica (con MoSCoW) | 2+ | -| Story Slicing Agent + Acceptance Criteria Agent | Banco de Semillas de Historia | 2+ | -| Architecture Discovery Agent | Restricciones arquitectónicas, Candidatos a Decisión | 3+ | -| Discovery Gate Agent | Gate de Preparación de Discovery (PASS/CONDITIONAL/FAIL) | 3+ | - -La ejecución humana es válida en todos los niveles; los agentes son aceleradores opcionales. - ---- - -## Procedimiento del Gate - -### Paso 1: Determinar Nivel de Adopción - -Evaluar la iniciativa contra estos criterios: - -| Factor | Nivel 0-1 | Nivel 2 | Nivel 3 | Nivel 4 | -|--------|-----------|---------|---------|---------| -| Familiaridad con el dominio | Conocido | Parcialmente conocido | Nuevo | Regulado | -| Tamaño del equipo | 1-3 | 4-8 | 8+ | Cualquier + cumplimiento | -| Riesgo del cambio | Bajo | Medio | Alto | Crítico | -| Requisitos regulatorios | Ninguno | Ninguno | Algunos | Obligatorios | -| Involucramiento de agentes IA | Ninguno | Posible | Probable | Requerido | - -### Paso 2: Producir Artefactos Requeridos - -**Nivel 1 — Ligero:** -1. Discovery Knowledge Brief (problema, valor, actores, contexto) -2. Log de Supuestos y Preguntas (ítems abiertos) -3. Discovery Context Pack (exportable para agentes) - -**Nivel 2 — Estándar (agrega):** -4. Mapa de Capacidades (capacidades del dominio) -5. Matriz de Candidatos a Épica (trazabilidad capacidad → épica) -6. Banco de Semillas de Historia (semillas mínimas de historia) - -**Nivel 3 — Gobernado (agrega):** -7. Gate de Preparación de Discovery (validación formal) - -**Nivel 4 — Enterprise (agrega):** -8. Validación de ruleset OPA -9. Generación de evidencia CLI/MCP -10. Registro de auditoría - -### Paso 3: Validar Contra Checklist de Calidad - -- [ ] La declaración del problema es explícita y verificable -- [ ] La propuesta de valor está articulada -- [ ] Los stakeholders / actores están identificados -- [ ] Las capacidades están descritas a nivel de dominio -- [ ] Cada candidato a épica deriva de una capacidad -- [ ] Cada semilla de historia deriva de un candidato a épica -- [ ] Los supuestos son visibles y etiquetados (validados / no validados) -- [ ] Las preguntas abiertas tienen owners y fechas objetivo -- [ ] Las restricciones técnicas están identificadas -- [ ] Los riesgos tienen owners o estrategia de mitigación -- [ ] Los candidatos a ADR, spikes o enablers están marcados -- [ ] Existe Discovery Context Pack (Nivel 1+) -- [ ] El nivel de adopción es apropiado para el tipo de iniciativa -- [ ] La cadena de trazabilidad está completa (trigger → brief → capability → epic → story) - -### Paso 4: Decisión del Gate - -| Resultado | Acción | -|-----------|--------| -| **PASS** | Proceder a Mapa de Capacidades / Matriz de Candidatos a Épica / Estimación Ballpark | -| **CONDITIONAL** | Proceder con waivers documentados para gaps específicos | -| **FAIL** | Regresar a captura de conocimiento; re-ejecutar gate después de cerrar gaps | - ---- - -## Handoff - -Después de gate PASS: - -``` -Discovery Knowledge Brief ──→ Mapa de Capacidades ──→ Matriz de Candidatos a Épica - │ -Log de Supuestos y Preguntas ────────────────────────────────┤ - │ -Banco de Semillas de Historia ──→ Estimación Ballpark ──→ Agile Backlog - │ -Discovery Context Pack ──→ Diseño / Arquitectura ──→ Construcción -``` - ---- - -## Checklist de Calidad - -- [ ] Todos los artefactos requeridos para el nivel elegido existen -- [ ] Los IDs de trazabilidad están asignados y vinculados -- [ ] Ningún supuesto bloqueante queda sin validar (Nivel 3+) -- [ ] El conocimiento es suficiente para la siguiente fase (Ballpark o Backlog) -- [ ] El Discovery Context Pack está actualizado y es exportable - ---- - -## Handoff hacia Gate F1 - -Después de un resultado **PASS** o **CONDITIONAL**, los siguientes artefactos del gate F1 deben reflejar las salidas del KDD: - -| Artefacto Gate F1 | Fuente KDD | Condición | -|---|---|---| -| Discovery Canvas | Discovery Knowledge Brief | Nivel 1+ | -| Ballpark Estimation | Sizing del Story Seed Bank | Nivel 2+ | -| Matriz de Priorización MoSCoW | Matriz de Candidatos a Épica (columnas MoSCoW) | Nivel 2+ — la matriz ES el artefacto MoSCoW; no se requiere MoSCoW independiente | -| Technical Feasibility Canvas | Salida del Architecture Discovery Agent | Nivel 3+ | - -Un resultado **FAIL** en este gate **bloquea** la apertura del gate de Aprobación de Negocio de la Fase 1. Documentar el gap y re-ejecutar después de la resolución. - ---- - -## Referencias - -- [Plantilla Discovery Knowledge Brief](../04-artifact-templates/discovery-knowledge-brief-template.es.md) -- [Plantilla Mapa de Capacidades](../04-artifact-templates/capability-map-template.es.md) -- [Plantilla Matriz de Candidatos a Épica](../04-artifact-templates/epic-candidate-matrix-template.es.md) -- [Plantilla Gate de Preparación de Discovery](../04-artifact-templates/discovery-readiness-gate-template.es.md) -- [Principios KDD](https://github.com/Kaddo-kdd/kaddo) — referencia externa, no es una dependencia diff --git a/reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.md b/reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.md deleted file mode 100644 index bfa217a3..00000000 --- a/reference/core/sdlc/01-playbooks/phase-1.1-knowledge-first-discovery.md +++ /dev/null @@ -1,158 +0,0 @@ -# Phase 1.1 — Knowledge-First Discovery / KDD Readiness Gate - -> **Bilingual Navigation:** [Versión en Español](./phase-1.1-knowledge-first-discovery.es.md) - -**Phase:** 01 — Conception & Discovery -**Subphase:** 01.1 — Knowledge-First Discovery / KDD Readiness -**Gate Type:** Optional, progressive -**Accountable Role:** Business Discovery Agent / Product Owner -**Waiver Authority:** Executive Sponsor - ---- - -## Purpose - -This playbook operationalises the Knowledge-First Discovery gate within Phase 01. It validates that minimum sufficient knowledge has been captured before any epic, story, or backlog item is created. The gate is optional and scales from lightweight (Level 1) to enterprise-regulated (Level 4). - ---- - -## When to Apply - -| Scenario | Recommended Level | -|----------|------------------| -| Small fix or trivial change | Level 0 (skip) | -| Well-understood domain, experienced team | Level 1 (Light) | -| New product or significant feature | Level 2 (Standard) | -| Legacy modernization or complex integration | Level 3 (Governed) | -| Regulated industry (finance, health, government) | Level 4 (Enterprise) | -| Satellite repository onboarding | Level 2-3 | - ---- - -## Discovery Agents - -Each step in the gate procedure is supported by a specialized AI agent defined in [`AGENTS.md §Discovery Agents`](../../../../AGENTS.md#intake-and-discovery-agents-phases-00-and-011). Invoke agents in this sequence; each agent's output is the next agent's input: - -| Agent | Artifact Produced | Level | -|---|---|:---:| -| Business Discovery Agent | Discovery Knowledge Brief (draft) | 1+ | -| Product Framing Agent | Knowledge Brief (validated), Context Pack | 1+ | -| Capability Modeling Agent | Capability Map | 2+ | -| Epic Discovery Agent | Epic Candidate Matrix (with MoSCoW) | 2+ | -| Story Slicing Agent + Acceptance Criteria Agent | Story Seed Bank | 2+ | -| Architecture Discovery Agent | Architecture constraints, Decision Candidates | 3+ | -| Discovery Gate Agent | Discovery Readiness Gate (PASS/CONDITIONAL/FAIL) | 3+ | - -Human execution is valid at all levels; agents are optional accelerators. - ---- - -## Gate Procedure - -### Step 1: Determine Adoption Level - -Evaluate the initiative against these criteria: - -| Factor | Level 0-1 | Level 2 | Level 3 | Level 4 | -|--------|-----------|---------|---------|---------| -| Domain familiarity | Known | Partially known | New | Regulated | -| Team size | 1-3 | 4-8 | 8+ | Any + compliance | -| Change risk | Low | Medium | High | Critical | -| Regulatory requirements | None | None | Some | Mandatory | -| AI agent involvement | None | Possible | Likely | Required | - -### Step 2: Produce Required Artifacts - -**Level 1 — Light:** -1. Discovery Knowledge Brief (problem, value, actors, context) -2. Assumptions & Questions Log (open items) -3. Discovery Context Pack (exportable for agents) - -**Level 2 — Standard (adds):** -4. Capability Map (domain capabilities) -5. Epic Candidate Matrix (capability → epic traceability) -6. Story Seed Bank (minimal story seeds) - -**Level 3 — Governed (adds):** -7. Discovery Readiness Gate (formal validation) - -**Level 4 — Enterprise (adds):** -8. OPA ruleset validation -9. CLI/MCP evidence generation -10. Audit trail record - -### Step 3: Validate Against Quality Checklist - -- [ ] Problem statement is explicit and testable -- [ ] Value proposition is articulated -- [ ] Stakeholders / actors are identified -- [ ] Capabilities are described at domain level -- [ ] Each epic candidate derives from a capability -- [ ] Each story seed derives from an epic candidate -- [ ] Assumptions are visible and labeled (validated / unvalidated) -- [ ] Open questions have owners and target dates -- [ ] Technical constraints are identified -- [ ] Risks have owners or mitigation strategy -- [ ] ADR candidates, spikes, or enablers are flagged -- [ ] Discovery Context Pack exists (Level 1+) -- [ ] Adoption level is appropriate for initiative type -- [ ] Traceability chain is complete (trigger → brief → capability → epic → story) - -### Step 4: Gate Decision - -| Outcome | Action | -|---------|--------| -| **PASS** | Proceed to Capability Map / Epic Candidate Matrix / Ballpark Estimation | -| **CONDITIONAL** | Proceed with documented waivers for specific gaps | -| **FAIL** | Return to knowledge capture; re-run gate after gaps addressed | - ---- - -## Handoff - -After gate PASS: - -``` -Discovery Knowledge Brief ──→ Capability Map ──→ Epic Candidate Matrix - │ -Assumptions & Questions Log ─────────────────────────────┤ - │ -Story Seed Bank ──→ Ballpark Estimation ──→ Agile Backlog - │ -Discovery Context Pack ──→ Design / Architecture ──→ Construction -``` - ---- - -## Quality Checklist - -- [ ] All required artifacts for the chosen level exist -- [ ] Traceability IDs are assigned and linked -- [ ] No blocking assumptions remain unvalidated (Level 3+) -- [ ] Knowledge sufficient for the next phase (Ballpark or Backlog) -- [ ] Discovery Context Pack is current and exportable - ---- - -## Handoff to Gate F1 - -After a **PASS** or **CONDITIONAL** outcome, the following gate-F1 artifacts must reflect KDD outputs: - -| Gate F1 Artifact | KDD Source | Condition | -|---|---|---| -| Discovery Canvas | Discovery Knowledge Brief | Level 1+ | -| Ballpark Estimation | Story Seed Bank sizing | Level 2+ | -| MoSCoW Prioritization Matrix | Epic Candidate Matrix (MoSCoW columns) | Level 2+ — the matrix IS the MoSCoW artifact; no standalone required | -| Technical Feasibility Canvas | Architecture Discovery Agent output | Level 3+ | - -A **FAIL** outcome on this gate **blocks** the opening of the Phase 1 Business Sign-Off gate. Document the gap and re-run after resolution. - ---- - -## References - -- [Discovery Knowledge Brief Template](../04-artifact-templates/discovery-knowledge-brief-template.md) -- [Capability Map Template](../04-artifact-templates/capability-map-template.md) -- [Epic Candidate Matrix Template](../04-artifact-templates/epic-candidate-matrix-template.md) -- [Discovery Readiness Gate Template](../04-artifact-templates/discovery-readiness-gate-template.md) -- [KDD Principles](https://github.com/Kaddo-kdd/kaddo) — external reference, not a dependency diff --git a/reference/core/sdlc/01-playbooks/phase-2-design-baseline.es.md b/reference/core/sdlc/01-playbooks/phase-2-design-baseline.es.md index 55c86d90..31995622 100644 --- a/reference/core/sdlc/01-playbooks/phase-2-design-baseline.es.md +++ b/reference/core/sdlc/01-playbooks/phase-2-design-baseline.es.md @@ -22,7 +22,7 @@ Este playbook operacionaliza la compuerta Design Baseline Approved. Toda salida | 2 | Evaluar Extraction Readiness (ADR-0045 ≥70%); confirmar progresión ADR-0047 justificada | Score documentado | | 3 | Confirmar ADR-0002; ejecutar Checklist de Simplicidad Fase 1 | Baseline de arquitectura | | 4 | Producir Mapa de Bounded Contexts (Plantilla DDD); aplicar ADR-0031 + ADR-0032 | Mapa de Bounded Contexts | -| 5 | Refinar Story Seeds → Historias Funcionales (KDD L2+) o escribir desde cero; descomponer → Historias de Usuario; organizar Agile Backlog | Historias Funcionales, Backlog | +| 5 | Escribir Historias Funcionales desde el alcance aprobado; descomponer → Historias de Usuario; organizar Agile Backlog | Historias Funcionales, Backlog | | 6 | Documentar decisiones de límites como ADRs; completar Análisis de Impacto CLI; consultar ADR-0018; verificar Alineación con Blueprint | Registro ADR (completo) | | 7 | Ejecutar `evolith validate --topology distributed-modules` — las 8 reglas DM deben pasar | Validación de topología | | 8 | (Condicional) Validar DOMA si topología F3 en roadmap (ADR-0076) | Cumplimiento DOMA | @@ -47,7 +47,7 @@ Antes de abrir la compuerta, confirmar: | # | Evidencia Obligatoria | Plantilla / Esquema | Criterio de Aceptación | |---|---|---|---| | 1 | Registro de ADRs | [`adr-template.es.md`](../04-artifact-templates/adr-template.es.md) | Toda decisión que cruza fronteras tiene un ADR numerado y aceptado. No quedan decisiones "no documentadas". | -| 2 | Functional Stories | [`functional-story-template.es.md`](../04-artifact-templates/functional-story-template.es.md) · [`functional-story.schema.json`](../../../../src/rulesets/schema/functional-story.schema.json) | Todas las historias en `Ready` con criterios de aceptación BDD; estándar de redacción cumplido. Nota KDD: Si existen Story Seeds de Fase 1.1 KDD Nivel 2+, refinándolas aquí en Historias Funcionales. | +| 2 | Functional Stories | [`functional-story-template.es.md`](../04-artifact-templates/functional-story-template.es.md) · [`functional-story.schema.json`](../../../../src/rulesets/schema/functional-story.schema.json) | Todas las historias en `Ready` con criterios de aceptación BDD; estándar de redacción cumplido. | | 3 | Alineación con Reference Blueprint | Conjunto de diagramas de arquitectura | Diagramas trazables al Reference Blueprint; las desviaciones llevan ADR. El Blueprint de Referencia es un artefacto de consulta — no lo produces; el Gate F2 verifica trazabilidad. | | 4 | Checklist de Simplicidad Fase 1 | Checklist de simplicidad | Aprobado — sin señales de over-engineering (abstracción prematura, capas especulativas, frameworks sin uso). A pesar del nombre 'Fase 1', este checklist se ejecuta en Fase 2. El identificador del artefacto está registrado en el validador de máquina — no renombrar. | | 5 | Bounded Context Map | Artefacto de context map | Todos los contextos con propietario, estrategia de persistencia y estilo de integración | diff --git a/reference/core/sdlc/01-playbooks/phase-2-design-baseline.md b/reference/core/sdlc/01-playbooks/phase-2-design-baseline.md index d437e3f3..00cdbda3 100644 --- a/reference/core/sdlc/01-playbooks/phase-2-design-baseline.md +++ b/reference/core/sdlc/01-playbooks/phase-2-design-baseline.md @@ -21,7 +21,7 @@ This playbook operationalises the Design Baseline Approved gate. Every Phase 2 e | 2 | Consult ADR-0056 (ubiquitous language); initialize ADR Registry | All artifacts | | 3 | Confirm ADR-0002; run Simplicity Checklist | Evidence #4 | | 4 | Produce Bounded Context Map (DDD Model Template); apply ADR-0031 + ADR-0032 | Evidence #5 | -| 5 | Refine Story Seeds (if KDD L2+) or write Functional Stories from scratch | Evidence #2 | +| 5 | Write Functional Stories from the approved scope | Evidence #2 | | 6 | Document boundary decisions as ADRs; complete CLI Impact Analysis; verify Blueprint Alignment | Evidence #1, #3 | | 7 | Run `evolith validate --topology distributed-modules` — all 8 DM rules must pass | Gate readiness | | 8 | Conditional: validate DOMA if F3 topology in scope (ADR-0076) | Blocking criterion | @@ -44,7 +44,7 @@ This playbook operationalises the Design Baseline Approved gate. Every Phase 2 e | # | Mandatory Evidence | Template / Schema | Acceptance Criterion | |---|---|---|---| | 1 | ADR Registry | [`adr-template.md`](../04-artifact-templates/adr-template.md) | Every boundary-crossing decision has a numbered, accepted ADR. No "undocumented" decisions remain. | -| 2 | Functional Stories | [`functional-story-template.md`](../04-artifact-templates/functional-story-template.md) · [`functional-story.schema.json`](../../../../src/rulesets/schema/functional-story.schema.json) | All stories in `Ready` state with BDD acceptance criteria; story writing standard satisfied. If Phase 1.1 Story Seeds exist (KDD Level 2+), refine them into Functional Stories at this step. Story Seeds do not replace Functional Stories. | +| 2 | Functional Stories | [`functional-story-template.md`](../04-artifact-templates/functional-story-template.md) · [`functional-story.schema.json`](../../../../src/rulesets/schema/functional-story.schema.json) | All stories in `Ready` state with BDD acceptance criteria; story writing standard satisfied. | | 3 | Reference Blueprint Alignment | Architecture diagram set | Verification step — not a document you produce. Architecture diagrams are produced here and checked against the Reference Blueprint. | | 4 | Simplicity Checklist Phase 1 | Simplicity checklist | Named 'Phase 1' because it guards against Phase 1 over-engineering entering the design baseline. Executed in Phase 2. Do not rename — machine-registered. | | 5 | Bounded Context Map | Context map artefact | All contexts named with ownership, persistence strategy, and integration style | diff --git a/reference/core/sdlc/04-artifact-templates/README.es.md b/reference/core/sdlc/04-artifact-templates/README.es.md index ea934026..b4ce3e8b 100644 --- a/reference/core/sdlc/04-artifact-templates/README.es.md +++ b/reference/core/sdlc/04-artifact-templates/README.es.md @@ -66,7 +66,7 @@ Las plantillas garantizan consistencia en todos los repositorios satélite. Los | **Fase 1 — Concepción** | PRD — Documento de Requisitos de Producto | [Abrir](./prd-template.es.md) | [Fuente](./source/prd-template-source.es.md) | [Ejemplo](./examples/prd-example-ums.es.md) | Product Owner, Sponsor Ejecutivo | | **Fase 2 — Diseño** | DDD Model (Bounded Context Map) | [Abrir](./ddd-model-template.es.md) | Incluido | N/A | Arquitecto, Tech Lead | | **Fase 2 — Diseño** | ADR — Registro de Decisión Arquitectónica | [Abrir](./adr-template.es.md) | [Fuente](./source/adr-template-source.es.md) | [Ejemplo](./examples/adr-example-ums.es.md) | Arquitecto, Principal Engineer | -| **Fase 2 — Diseño** | Historia Funcional | [Abrir](./functional-story-template.es.md) | [Fuente](./source/functional-story-template-source.es.md) | [Ejemplo](./examples/functional-story-example-ums.es.md) | Product Owner, Business Analyst | Si existen Story Seeds de Fase 1.1 KDD Nivel 2+, refinarlas aquí en Historias Funcionales | +| **Fase 2 — Diseño** | Historia Funcional | [Abrir](./functional-story-template.es.md) | [Fuente](./source/functional-story-template-source.es.md) | [Ejemplo](./examples/functional-story-example-ums.es.md) | Product Owner, Business Analyst | | | **Fase 3 — Construcción** | Historia Técnica | [Abrir](./technical-story-template.es.md) | [Fuente](./source/technical-story-template-source.es.md) | [Ejemplo](./examples/technical-story-example-ums.es.md) | Desarrollador Backend/Frontend, Tech Lead | | **Fase 4 — Validación** | Test Summary Report | [Abrir](./test-summary-report-template.es.md) | [Fuente](./source/test-summary-report-template-source.es.md) | [Ejemplo](./examples/test-summary-report-example-ums.es.md) | QA / SDET, Tech Lead, Security Engineer | | **Fase 5 — Entrega** | Release Notes | [Abrir](./release-notes-template.es.md) | [Fuente](./source/release-notes-template-source.es.md) | [Ejemplo](./examples/release-notes-example-ums.es.md) | DevOps / SRE, Tech Lead | @@ -74,7 +74,7 @@ Las plantillas garantizan consistencia en todos los repositorios satélite. Los > **Notas Fase 2:** > - **DDD Model** — Produce el Mapa de Bounded Contexts requerido por el Gate F2. -> - **Historia Funcional** — Formato de autoría para "Historias Funcionales" (evidencia Gate F2). Refinar Story Seeds de Fase 1.1 KDD aquí. +> - **Historia Funcional** — Formato de autoría para "Historias Funcionales" (evidencia Gate F2). > > **Notas Fase 3:** > - **Historia Técnica** — Cada una debe llevar `functionalStoryRef` vinculando a una Historia Funcional de Fase 2. Sigue el Construction-Focused SDLC Framework DoD. diff --git a/reference/core/sdlc/04-artifact-templates/README.md b/reference/core/sdlc/04-artifact-templates/README.md index 61072826..1b36ffb3 100644 --- a/reference/core/sdlc/04-artifact-templates/README.md +++ b/reference/core/sdlc/04-artifact-templates/README.md @@ -74,7 +74,7 @@ Templates enforce consistency across all satellite repositories. Satellite teams > **Phase 2 Notes:** > - **DDD Model** — Produces the Bounded Context Map required by Gate F2. -> - **Functional Story** — Authoring format for "Functional Stories" (Gate F2 evidence). Refine Story Seeds from Phase 1.1 KDD here. +> - **Functional Story** — Authoring format for "Functional Stories" (Gate F2 evidence). > > **Phase 3 Notes:** > - **Technical Story** — Each must carry a `functionalStoryRef` linking to a Phase 2 Functional Story. Follows the Construction-Focused SDLC Framework DoD. diff --git a/reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.es.md b/reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.es.md deleted file mode 100644 index 0e15327e..00000000 --- a/reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.es.md +++ /dev/null @@ -1,205 +0,0 @@ -# Plantilla: Registro de Supuestos y Preguntas - -> **Navegación Bilingüe:** [English Version](./assumptions-questions-log-template.md) -> **Propósito:** Registro vivo que rastrea preguntas abiertas y supuestos no validados durante todo el Discovery. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Product Owner / Business Analyst -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Discovery Knowledge Brief aprobado. -* **Salidas Esperadas:** Registro de Supuestos y Preguntas mantenido que alimenta el Paquete de Contexto de Discovery. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Assumption, Question, Risk, Decision). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-09 (Readability). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Registro de Supuestos y Preguntas: [Nombre de la Iniciativa] - -## 1. Registro Vivo - -| ID | Tipo | Declaración | Estado | Responsable | Fecha Objetivo | Resolución | Artefacto Vinculado | -|---|---|---|---|---|---|---|---| -| AQ-001 | assumption | Las cuotas del proveedor de nube soportan 500 req/s | Abierto | Carlos Ruiz | 2024-02-15 | — | KB-2024-001 | -| AQ-002 | question | ¿Qué proveedor de identidad soporta OAuth2 con SLA >= 99.9%? | Abierto | María López | 2024-02-20 | — | KB-2024-001 | -| AQ-003 | assumption | Los requisitos KYC/AML son estables por 12 meses | Validado | Equipo de Compliance | 2024-01-30 | Confirmado por Legal el 2024-01-28 | KB-2024-001 | -| AQ-004 | question | ¿Cuál es la latencia máxima de onboarding aceptable por mercado? | Diferido | Product Owner | 2024-03-01 | — | CAP-2024-001 | - -## 2. Resumen - -| Métrica | Cantidad | -|---|---| -| Total de ítems | 4 | -| Abiertos | 2 | -| Validados | 1 | -| Invalidados | 0 | -| Diferidos | 1 | - -## 3. Notas de Uso - -- Actualiza este registro cada vez que surja un nuevo supuesto o se planteé una pregunta durante talleres de Discovery, refinamiento de backlog o entrevistas con stakeholders. -- Cada supuesto debe ser verificable de forma independiente. Si no puede verificarse, conviértelo en una pregunta. -- Las preguntas que bloqueen decisiones a nivel de épica deben resolverse antes de la aprobación del Design Baseline. -- Vincula cada ítem con el artefacto de origen (Knowledge Brief, Capability Map, etc.) para trazabilidad. -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith y herramientas automáticas de seguimiento. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Assumptions & Questions Log", - "type": "object", - "required": ["id", "items"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de esta instancia de registro." - }, - "items": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "type", "statement", "status", "owner", "targetDate", "resolution", "linkedArtifact"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único del ítem (ej., AQ-001)." - }, - "type": { - "type": "string", - "enum": ["assumption", "question"], - "description": "Si es un supuesto no validado o una pregunta abierta." - }, - "statement": { - "type": "string", - "description": "Texto del supuesto o la pregunta." - }, - "status": { - "type": "string", - "enum": ["open", "validated", "invalidated", "deferred"], - "description": "Estado actual del ciclo de vida." - }, - "owner": { - "type": "string", - "description": "Persona responsable de resolver este ítem." - }, - "targetDate": { - "type": "string", - "format": "date", - "description": "Fecha objetivo de resolución (ISO 8601)." - }, - "resolution": { - "type": "string", - "description": "Detalles de resolución una vez resuelto. Cadena vacía si aún está abierto." - }, - "linkedArtifact": { - "type": "string", - "description": "ID del artefacto de origen (ej., Knowledge Brief, Capability Map)." - } - } - }, - "description": "Array de supuestos y preguntas rastreados." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "AQ-LOG-2024-001", - "items": [ - { - "id": "AQ-001", - "type": "assumption", - "statement": "Las cuotas del proveedor de nube soportan 500 req/s de concurrencia para el dominio de onboarding.", - "status": "open", - "owner": "Carlos Ruiz", - "targetDate": "2024-02-15", - "resolution": "", - "linkedArtifact": "KB-2024-001" - }, - { - "id": "AQ-002", - "type": "question", - "statement": "¿Qué proveedor de identidad soporta OAuth2 con SLA >= 99.9% en todos los mercados objetivo?", - "status": "open", - "owner": "María López", - "targetDate": "2024-02-20", - "resolution": "", - "linkedArtifact": "KB-2024-001" - }, - { - "id": "AQ-003", - "type": "assumption", - "statement": "Los requisitos KYC/AML permanecen estables por los próximos 12 meses.", - "status": "validated", - "owner": "Equipo de Compliance", - "targetDate": "2024-01-30", - "resolution": "Confirmado por Legal el 2024-01-28.", - "linkedArtifact": "KB-2024-001" - } - ] -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -El **Registro de Supuestos y Preguntas** alimenta directamente: - -1. **Paquete de Contexto de Discovery** — los supuestos validados y preguntas resueltas poblan el campo `assumptionsStatus`. -2. **Mapa de Capacidades** — los supuestos abiertos se vinculan a capacidades específicas a través de `relatedAssumptions`. -3. **Factibilidad Técnica** — los supuestos validados informan los objetivos de NFR y la validación de restricciones. - -Los ítems que permanezcan **Abiertos** o **Invalidados** al momento del Design Baseline deben escalarse o aceptarse explícitamente. - ---- - -## Quality Checklist - -- [ ] Cada supuesto es verificable de forma independiente -- [ ] Cada pregunta tiene un responsable claro y una fecha objetivo de resolución -- [ ] Todos los ítems están vinculados a un artefacto de origen -- [ ] Las transiciones de estado están documentadas con fechas -- [ ] Ningún ítem ha estado abierto más allá de la fecha objetivo sin escalamiento -- [ ] Los supuestos validados tienen evidencia de resolución adjunta -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas que tengan un Knowledge Brief aprobado. El registro debe mantenerse durante todo el Discovery y actualizarse antes de cada revisión de compuerta. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| Nuevo supuesto surge durante taller o entrevista | Agregar como nuevo ítem con estado Abierto | -| Supuesto validado con evidencia | Actualizar estado a Validado, agregar resolución con fecha | -| Supuesto demostrado como falso | Actualizar estado a Invalidado, registrar impacto y acción correctiva | -| Pregunta respondida | Actualizar estado a Validado, registrar resolución | -| Pregunta diferida más allá de la fase actual | Actualizar estado a Diferido, establecer nueva fecha objetivo | -| Fecha objetivo vencida | Escalar al patrocinador, agregar nota en el campo de resolución | diff --git a/reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.md b/reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.md deleted file mode 100644 index acd3281d..00000000 --- a/reference/core/sdlc/04-artifact-templates/assumptions-questions-log-template.md +++ /dev/null @@ -1,205 +0,0 @@ -# Template: Assumptions & Questions Log - -> **Bilingual Navigation:** [Versión en Español](./assumptions-questions-log-template.es.md) -> **Purpose:** Living log tracking open questions and unvalidated assumptions throughout discovery. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Product Owner / Business Analyst -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Approved Discovery Knowledge Brief. -* **Expected outputs:** Maintained Assumptions & Questions Log that feeds the Discovery Context Pack. -* **Applied taxonomy:** Aligned with Evolith glossary (Assumption, Question, Risk, Decision). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-09 (Readability). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Assumptions & Questions Log: [Initiative Name] - -## 1. Living Log - -| ID | Type | Statement | Status | Owner | Target Date | Resolution | Linked Artifact | -|---|---|---|---|---|---|---|---| -| AQ-001 | assumption | Cloud provider quotas support 500 req/s concurrency | Open | Carlos Ruiz | 2024-02-15 | — | KB-2024-001 | -| AQ-002 | question | Which identity provider supports OAuth2 with SLA >= 99.9%? | Open | Maria Lopez | 2024-02-20 | — | KB-2024-001 | -| AQ-003 | assumption | KYC/AML requirements are stable for 12 months | Validated | Compliance Team | 2024-01-30 | Confirmed by Legal on 2024-01-28 | KB-2024-001 | -| AQ-004 | question | What is the maximum onboarding latency acceptable per market? | Deferred | Product Owner | 2024-03-01 | — | CAP-2024-001 | - -## 2. Summary - -| Metric | Count | -|---|---| -| Total items | 4 | -| Open | 2 | -| Validated | 1 | -| Invalidated | 0 | -| Deferred | 1 | - -## 3. Usage Notes - -- Update this log whenever a new assumption surfaces or a question is raised during discovery workshops, backlog refinement, or stakeholder interviews. -- Each assumption must be independently verifiable. If it cannot be verified, convert it to a question. -- Questions that block epic-level decisions must be resolved before Design Baseline approval. -- Link every item to its originating artifact (Knowledge Brief, Capability Map, etc.) for traceability. -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI and automated tracking tools. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Assumptions & Questions Log", - "type": "object", - "required": ["id", "items"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this log instance." - }, - "items": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "type", "statement", "status", "owner", "targetDate", "resolution", "linkedArtifact"], - "properties": { - "id": { - "type": "string", - "description": "Unique item identifier (e.g., AQ-001)." - }, - "type": { - "type": "string", - "enum": ["assumption", "question"], - "description": "Whether this is an unvalidated assumption or an open question." - }, - "statement": { - "type": "string", - "description": "The assumption or question text." - }, - "status": { - "type": "string", - "enum": ["open", "validated", "invalidated", "deferred"], - "description": "Current lifecycle status." - }, - "owner": { - "type": "string", - "description": "Person responsible for resolving this item." - }, - "targetDate": { - "type": "string", - "format": "date", - "description": "Target date for resolution (ISO 8601)." - }, - "resolution": { - "type": "string", - "description": "Resolution details once resolved. Empty string if still open." - }, - "linkedArtifact": { - "type": "string", - "description": "ID of the originating artifact (e.g., Knowledge Brief, Capability Map)." - } - } - }, - "description": "Array of tracked assumptions and questions." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "AQ-LOG-2024-001", - "items": [ - { - "id": "AQ-001", - "type": "assumption", - "statement": "Cloud provider quotas support 500 req/s concurrency for the onboarding domain.", - "status": "open", - "owner": "Carlos Ruiz", - "targetDate": "2024-02-15", - "resolution": "", - "linkedArtifact": "KB-2024-001" - }, - { - "id": "AQ-002", - "type": "question", - "statement": "Which identity provider supports OAuth2 with SLA >= 99.9% across all target markets?", - "status": "open", - "owner": "Maria Lopez", - "targetDate": "2024-02-20", - "resolution": "", - "linkedArtifact": "KB-2024-001" - }, - { - "id": "AQ-003", - "type": "assumption", - "statement": "KYC/AML requirements remain stable for the next 12 months.", - "status": "validated", - "owner": "Compliance Team", - "targetDate": "2024-01-30", - "resolution": "Confirmed by Legal on 2024-01-28.", - "linkedArtifact": "KB-2024-001" - } - ] -} -``` - ---- - -## 4. Handoff to Next Artifact - -The **Assumptions & Questions Log** feeds directly into: - -1. **Discovery Context Pack** — validated assumptions and resolved questions populate the `assumptionsStatus` field. -2. **Capability Map** — open assumptions link to specific capabilities via `relatedAssumptions`. -3. **Technical Feasibility** — validated assumptions inform NFR targets and constraint validation. - -Items that remain **Open** or **Invalidated** at Design Baseline must be escalated or explicitly accepted. - ---- - -## Quality Checklist - -- [ ] Every assumption is independently verifiable -- [ ] Every question has a clear owner and target resolution date -- [ ] All items link back to an originating artifact -- [ ] Status transitions are documented with dates -- [ ] No item has been open longer than the target date without escalation -- [ ] Validated assumptions have resolution evidence attached -- [ ] Language is consistent (no mixed EN/ES within the file) - ---- - -## Recommended Adoption Level - -**Mandatory** for all initiatives that have an approved Knowledge Brief. The log must be maintained throughout Discovery and updated before each gate review. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| New assumption surfaces during workshop or interview | Add as new item with status Open | -| Assumption validated by evidence | Update status to Validated, add resolution with date | -| Assumption proven wrong | Update status to Invalidated, record impact and corrective action | -| Question answered | Update status to Validated, record resolution | -| Question deferred beyond current phase | Update status to Deferred, set new target date | -| Target date missed | Escalate to sponsor, add note in resolution field | diff --git a/reference/core/sdlc/04-artifact-templates/capability-map-template.es.md b/reference/core/sdlc/04-artifact-templates/capability-map-template.es.md deleted file mode 100644 index 8d5af6f2..00000000 --- a/reference/core/sdlc/04-artifact-templates/capability-map-template.es.md +++ /dev/null @@ -1,225 +0,0 @@ -# Plantilla: Mapa de Capacidades - -> **Navegación Bilingüe:** [English Version](./capability-map-template.md) -> **Propósito:** Descomposición de capacidades a nivel de dominio antes del desglose de épicas. Cada capacidad es una unidad de comportamiento significativa para el negocio. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Product Owner / Business Analyst -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Discovery Knowledge Brief aprobado, Registro de Supuestos y Preguntas. -* **Salidas Esperadas:** Mapa de Capacidades que alimenta el Paquete de Contexto de Discovery e informa el desglose de épicas. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Capability, Domain, Priority, Dependency, Epic Candidate). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-06 (Split Stories), R-13 (Functional Structure). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Mapa de Capacidades: [Nombre de la Iniciativa] - -## 1. Descomposición de Capacidades - -| ID de Capacidad | Nombre | Descripción | Dominio | Prioridad | Dependencias | Supuestos Vinculados | Candidatos a Épica | -|---|---|---|---|---|---|---|---| -| CAP-001 | [Nombre de Capacidad] | [Qué entrega esta capacidad al negocio] | [Bounded context] | Must/Should/Could/Wont | [CAP-XXX o Ninguna] | [AQ-XXX] | [EPIC-XXX] | -| CAP-002 | [Nombre de Capacidad] | [Qué entrega esta capacidad al negocio] | [Bounded context] | Must/Should/Could/Wont | [CAP-XXX o Ninguna] | [AQ-XXX] | [EPIC-XXX] | - -## 2. Definiciones de Prioridad - -| Prioridad | Definición | -|---|---| -| **Must** | Requerido para MVP. La iniciativa no puede entregar valor sin esta capacidad. | -| **Should** | Importante para la entrega completa de valor pero puede diferirse a una iteración posterior. | -| **Could** | Deseable. Incluir solo si los recursos y el cronograma lo permiten. | -| **Wont** | Explícitamente fuera del alcance de esta iniciativa. Registrado para trazabilidad. | - -## 3. Grafo de Dependencias - -[Describe o diagrama las relaciones de dependencia entre capacidades. Las capacidades sin dependencias ascendentes deben entregarse primero.] - -``` -CAP-001 (Verificación de Identidad) - └── CAP-002 (Orquestación de Onboarding) depende de CAP-001 - └── CAP-003 (Escaneo de Documentos KYC) depende de CAP-002 -``` - -## 4. Trazabilidad - -| Capacidad | Knowledge Brief | Registro de Supuestos | Factibilidad Técnica | Épica | -|---|---|---|---|---| -| CAP-001 | KB-2024-001 | AQ-001, AQ-002 | TF-2024-001 | EPIC-001 | -| CAP-002 | KB-2024-001 | AQ-001 | TF-2024-001 | EPIC-002 | -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith, scaffolding automatizado e ingestión de agentes de IA. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Capability Map", - "type": "object", - "required": ["id", "capabilities"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de esta instancia de Mapa de Capacidades." - }, - "capabilities": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "description", "domain", "priority", "dependencies", "relatedAssumptions", "epicCandidates"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de la capacidad (ej., CAP-001)." - }, - "name": { - "type": "string", - "description": "Nombre corto y descriptivo de la capacidad." - }, - "description": { - "type": "string", - "description": "Qué entrega esta capacidad al negocio." - }, - "domain": { - "type": "string", - "description": "Bounded context o dominio de negocio al que pertenece esta capacidad." - }, - "priority": { - "type": "string", - "enum": ["Must", "Should", "Could", "Wont"], - "description": "Nivel de prioridad MoSCoW." - }, - "dependencies": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs de capacidades que deben entregarse antes que esta." - }, - "relatedAssumptions": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs del Registro de Supuestos y Preguntas que afectan esta capacidad." - }, - "epicCandidates": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs de épicas propuestas que implementarían esta capacidad." - } - } - }, - "description": "Unidades de comportamiento significativas para el negocio de la iniciativa." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "CM-2024-001", - "capabilities": [ - { - "id": "CAP-001", - "name": "Verificación de Identidad", - "description": "Verificar la identidad del cliente contra requisitos KYC/AML usando verificaciones automatizadas de documentos y coincidencia biométrica.", - "domain": "Ciclo de Vida del Cliente", - "priority": "Must", - "dependencies": [], - "relatedAssumptions": ["AQ-001", "AQ-002"], - "epicCandidates": ["EPIC-001"] - }, - { - "id": "CAP-002", - "name": "Orquestación de Onboarding", - "description": "Coordinar el flujo de trabajo de onboarding de múltiples pasos entre verificación de identidad, creación de cuenta y secuencia de bienvenida.", - "domain": "Ciclo de Vida del Cliente", - "priority": "Must", - "dependencies": ["CAP-001"], - "relatedAssumptions": ["AQ-001"], - "epicCandidates": ["EPIC-002"] - }, - { - "id": "CAP-003", - "name": "Escaneo de Documentos KYC", - "description": "Escanear y extraer datos de documentos de identidad usando OCR y validar contra requisitos regulatorios.", - "domain": "Compliance", - "priority": "Should", - "dependencies": ["CAP-002"], - "relatedAssumptions": ["AQ-003"], - "epicCandidates": ["EPIC-003"] - }, - { - "id": "CAP-004", - "name": "Onboarding por Canal de Socios", - "description": "Extender el flujo de onboarding para soportar integraciones de canales de socios con marca personalizada y mapeo de campos.", - "domain": "Ciclo de Vida del Cliente", - "priority": "Could", - "dependencies": ["CAP-002"], - "relatedAssumptions": ["AQ-004"], - "epicCandidates": [] - } - ] -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -El **Mapa de Capacidades** alimenta directamente: - -1. **Paquete de Contexto de Discovery** — las capacidades poblan el array `capabilities` del JSON del paquete de contexto. -2. **Factibilidad Técnica** — las capacidades `Must` informan el alcance de NFR y el análisis de restricciones. -3. **Desglose de épicas** — cada capacidad `Must` y `Should` se convierte en candidata a épica para el Design Baseline. -4. **Estimación Ballpark** — la cantidad de capacidades y la profundidad de dependencias informan el dimensionamiento del esfuerzo. -5. **Modelo DDD** — las capacidades se mapean a raíces de agregado y límites de bounded context. - -Las capacidades marcadas `Wont` se rastrean explícitamente para gobernanza de alcance y consideración de roadmap futuro. - ---- - -## Quality Checklist - -- [ ] Cada capacidad tiene una descripción clara y significativa para el negocio (sin detalle de implementación técnica) -- [ ] Cada capacidad `Must` tiene al menos un candidato a épica -- [ ] El grafo de dependencias no tiene ciclos -- [ ] Todos los `relatedAssumptions` referencian IDs válidos del Registro de Supuestos y Preguntas -- [ ] Ninguna capacidad está huérfana (cada ítem enlaza al Knowledge Brief) -- [ ] Los niveles de prioridad siguen las definiciones MoSCoW consistentemente -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas con un Knowledge Brief aprobado. El mapa de capacidades debe completarse antes de la aprobación del Design Baseline y usarse como base para el desglose de épicas. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| Nueva capacidad identificada durante discovery | Agregar al array de capacidades con dependencias y prioridad | -| Supuesto invalidado que afecta una capacidad | Revisar y actualizar prioridad o marcar como bloqueada | -| Capacidad diferida a iteración futura | Cambiar prioridad de Must/Should a Could/Wont | -| Épica aprobada para una capacidad | Actualizar epicCandidates con el ID de épica asignado | -| Dependencia resuelta | Eliminar del array de dependencias, actualizar orden de entrega | -| Cambio de alcance del Knowledge Brief | Revisión completa del mapa de capacidades; agregar/eliminar/repriorizar según sea necesario | diff --git a/reference/core/sdlc/04-artifact-templates/capability-map-template.md b/reference/core/sdlc/04-artifact-templates/capability-map-template.md deleted file mode 100644 index b25588da..00000000 --- a/reference/core/sdlc/04-artifact-templates/capability-map-template.md +++ /dev/null @@ -1,225 +0,0 @@ -# Template: Capability Map - -> **Bilingual Navigation:** [Versión en Español](./capability-map-template.es.md) -> **Purpose:** Domain-level capability decomposition before epic breakdown. Each capability is a business-meaningful unit of behavior. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Product Owner / Business Analyst -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Approved Discovery Knowledge Brief, Assumptions & Questions Log. -* **Expected outputs:** Capability Map that feeds the Discovery Context Pack and informs epic breakdown. -* **Applied taxonomy:** Aligned with Evolith glossary (Capability, Domain, Priority, Dependency, Epic Candidate). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-06 (Split Stories), R-13 (Functional Structure). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Capability Map: [Initiative Name] - -## 1. Capability Decomposition - -| Capability ID | Name | Description | Domain | Priority | Dependencies | Related Assumptions | Epic Candidates | -|---|---|---|---|---|---|---|---| -| CAP-001 | [Capability Name] | [What this capability delivers to the business] | [Bounded context] | Must/Should/Could/Wont | [CAP-XXX or None] | [AQ-XXX] | [EPIC-XXX] | -| CAP-002 | [Capability Name] | [What this capability delivers to the business] | [Bounded context] | Must/Should/Could/Wont | [CAP-XXX or None] | [AQ-XXX] | [EPIC-XXX] | - -## 2. Priority Definitions - -| Priority | Definition | -|---|---| -| **Must** | Required for MVP. The initiative cannot deliver value without this capability. | -| **Should** | Important for full value delivery but can be deferred to a subsequent iteration. | -| **Could** | Nice-to-have. Include only if resources and timeline permit. | -| **Wont** | Explicitly out of scope for this initiative. Recorded for traceability. | - -## 3. Dependency Graph - -[Describe or diagram the dependency relationships between capabilities. Capabilities with no upstream dependencies should be delivered first.] - -``` -CAP-001 (Identity Verification) - └── CAP-002 (Onboarding Orchestration) depends on CAP-001 - └── CAP-003 (KYC Document Scanning) depends on CAP-002 -``` - -## 4. Traceability - -| Capability | Knowledge Brief | Assumptions Log | Technical Feasibility | Epic | -|---|---|---|---|---| -| CAP-001 | KB-2024-001 | AQ-001, AQ-002 | TF-2024-001 | EPIC-001 | -| CAP-002 | KB-2024-001 | AQ-001 | TF-2024-001 | EPIC-002 | -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI, automated scaffolding, and AI agent ingestion. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Capability Map", - "type": "object", - "required": ["id", "capabilities"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this Capability Map instance." - }, - "capabilities": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "description", "domain", "priority", "dependencies", "relatedAssumptions", "epicCandidates"], - "properties": { - "id": { - "type": "string", - "description": "Unique capability identifier (e.g., CAP-001)." - }, - "name": { - "type": "string", - "description": "Short, descriptive name for the capability." - }, - "description": { - "type": "string", - "description": "What this capability delivers to the business." - }, - "domain": { - "type": "string", - "description": "Bounded context or business domain this capability belongs to." - }, - "priority": { - "type": "string", - "enum": ["Must", "Should", "Could", "Wont"], - "description": "MoSCoW priority level." - }, - "dependencies": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs of capabilities that must be delivered before this one." - }, - "relatedAssumptions": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs from the Assumptions & Questions Log that affect this capability." - }, - "epicCandidates": { - "type": "array", - "items": { "type": "string" }, - "description": "Proposed epic IDs that would implement this capability." - } - } - }, - "description": "Business-meaningful capability units for the initiative." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "CM-2024-001", - "capabilities": [ - { - "id": "CAP-001", - "name": "Identity Verification", - "description": "Verify customer identity against KYC/AML requirements using automated document checks and biometric matching.", - "domain": "Customer Lifecycle", - "priority": "Must", - "dependencies": [], - "relatedAssumptions": ["AQ-001", "AQ-002"], - "epicCandidates": ["EPIC-001"] - }, - { - "id": "CAP-002", - "name": "Onboarding Orchestration", - "description": "Coordinate the multi-step onboarding workflow across identity verification, account creation, and welcome sequence.", - "domain": "Customer Lifecycle", - "priority": "Must", - "dependencies": ["CAP-001"], - "relatedAssumptions": ["AQ-001"], - "epicCandidates": ["EPIC-002"] - }, - { - "id": "CAP-003", - "name": "KYC Document Scanning", - "description": "Scan and extract data from identity documents using OCR and validate against regulatory requirements.", - "domain": "Compliance", - "priority": "Should", - "dependencies": ["CAP-002"], - "relatedAssumptions": ["AQ-003"], - "epicCandidates": ["EPIC-003"] - }, - { - "id": "CAP-004", - "name": "Partner Channel Onboarding", - "description": "Extend onboarding flow to support partner-channel integrations with custom branding and field mapping.", - "domain": "Customer Lifecycle", - "priority": "Could", - "dependencies": ["CAP-002"], - "relatedAssumptions": ["AQ-004"], - "epicCandidates": [] - } - ] -} -``` - ---- - -## 4. Handoff to Next Artifact - -The **Capability Map** feeds directly into: - -1. **Discovery Context Pack** — capabilities populate the `capabilities` array in the context pack JSON. -2. **Technical Feasibility** — `Must` capabilities inform NFR scoping and constraint analysis. -3. **Epic breakdown** — each `Must` and `Should` capability becomes an epic candidate for Design Baseline. -4. **Ballpark Estimation** — capability count and dependency depth inform effort sizing. -5. **DDD Model** — capabilities map to aggregate roots and bounded context boundaries. - -Capabilities marked `Wont` are explicitly tracked for scope governance and future roadmap consideration. - ---- - -## Quality Checklist - -- [ ] Every capability has a clear, business-meaningful description (no technical implementation detail) -- [ ] Every `Must` capability has at least one epic candidate -- [ ] Dependency graph has no cycles -- [ ] All `relatedAssumptions` reference valid IDs from the Assumptions & Questions Log -- [ ] No capability is orphaned (every item links to the Knowledge Brief) -- [ ] Priority levels follow MoSCoW definitions consistently -- [ ] Language is consistent (no mixed EN/ES within the file) - ---- - -## Recommended Adoption Level - -**Mandatory** for all initiatives with an approved Knowledge Brief. The capability map must be completed before Design Baseline approval and used as the basis for epic breakdown. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| New capability identified during discovery | Add to capabilities array with dependencies and priority | -| Assumption invalidated that affects a capability | Review and update priority or mark as blocked | -| Capability descoped to future iteration | Change priority from Must/Should to Could/Wont | -| Epic approved for a capability | Update epicCandidates with assigned epic ID | -| Dependency resolved | Remove from dependencies array, update delivery order | -| Knowledge Brief scope change | Full capability map review; add/remove/reprioritize as needed | diff --git a/reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.es.md b/reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.es.md deleted file mode 100644 index cdef97cd..00000000 --- a/reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.es.md +++ /dev/null @@ -1,239 +0,0 @@ -# Plantilla: Paquete de Contexto de Discovery - -> **Navegación Bilingüe:** [English Version](./discovery-context-pack-template.md) -> **Propósito:** Paquete de conocimiento exportable y autocontenido para agentes de IA y repositorios satélite. Consumible por CLI, MCP o lectura directa. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Platform Architect / Pipeline de Agentes de IA -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Discovery Knowledge Brief aprobado, Registro de Supuestos y Preguntas, Mapa de Capacidades. -* **Salidas Esperadas:** Paquete de contexto autocontenido que agentes de IA, herramientas CLI y repositorios satélite pueden consumir para inicializar artefactos descendentes. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Initiative, Capability, Risk, Assumption, Adoption Level). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-20 (Satellite Upstream Promotion). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Paquete de Contexto de Discovery: [Nombre de la Iniciativa] - -## 1. Resumen Ejecutivo -[Resumen de 2-3 oraciones de la iniciativa, su valor y estado actual. Preámbulo legible por máquina.] - -## 2. ID de la Iniciativa -[Identificador único que referencia el Knowledge Brief de origen.] - -## 3. Nivel de Adopción -[Mandatory | Recommended | Optional — indica cómo este paquete de contexto debe ser consumido por procesos descendentes.] - -## 4. Resumen del Knowledge Brief -[Versión condensada del Knowledge Brief: problema, valor, actores clave y contexto de dominio.] - -| Campo | Valor | -|---|---| -| Problema | [Declaración del problema en una línea] | -| Valor | [Propuesta de valor en una línea] | -| Dominio | [Dominio principal / bounded context] | -| Patrocinador | [Nombre] | - -## 5. Lista de Capacidades -[Extraída del Mapa de Capacidades. Cada capacidad es una unidad de comportamiento significativa para el negocio.] - -| ID de Capacidad | Nombre | Dominio | Prioridad | -|---|---|---|---| -| CAP-001 | [Nombre de Capacidad] | [Dominio] | Must/Should/Could/Wont | - -## 6. Riesgos Abiertos -[Riesgos del Knowledge Brief que permanecen sin resolver.] - -| Riesgo | Probabilidad | Impacto | Mitigación | -|---|---|---|---| -| [Riesgo] | [Alta/Media/Baja] | [Alta/Media/Baja] | [Estrategia] | - -## 7. Estado de Supuestos -[Resumen del Registro de Supuestos y Preguntas.] - -| Estado | Cantidad | -|---|---| -| Abiertos | [N] | -| Validados | [N] | -| Invalidados | [N] | -| Diferidos | [N] | - -## 8. Siguientes Pasos Recomendados -[Lista ordenada de acciones inmediatas para consumidores descendentes.] - -1. [Siguiente paso 1] -2. [Siguiente paso 2] -3. [Siguiente paso 3] -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith, pipelines MCP e ingestión de agentes de IA. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Discovery Context Pack", - "type": "object", - "required": ["id", "version", "initiativeId", "adoptionLevel", "knowledgeBriefRef", "capabilities", "openRisks", "assumptionsStatus", "nextSteps", "generatedAt"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de esta instancia de paquete de contexto." - }, - "version": { - "type": "string", - "description": "Versión semántica de este paquete de contexto." - }, - "initiativeId": { - "type": "string", - "description": "Referencia al Knowledge Brief de origen." - }, - "adoptionLevel": { - "type": "string", - "enum": ["Mandatory", "Recommended", "Optional"], - "description": "Nivel de adopción para consumidores descendentes." - }, - "knowledgeBriefRef": { - "type": "string", - "description": "Ruta o URL al Knowledge Brief completo." - }, - "capabilities": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "domain", "priority"], - "properties": { - "id": { "type": "string" }, - "name": { "type": "string" }, - "domain": { "type": "string" }, - "priority": { "type": "string", "enum": ["Must", "Should", "Could", "Wont"] } - } - }, - "description": "Unidades de comportamiento significativas para el negocio extraídas del Mapa de Capacidades." - }, - "openRisks": { - "type": "array", - "items": { - "type": "object", - "required": ["description", "probability", "impact"], - "properties": { - "description": { "type": "string" }, - "probability": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "impact": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "mitigation": { "type": "string" } - } - }, - "description": "Riesgos no resueltos del Knowledge Brief." - }, - "assumptionsStatus": { - "type": "object", - "required": ["open", "validated", "invalidated", "deferred"], - "properties": { - "open": { "type": "integer" }, - "validated": { "type": "integer" }, - "invalidated": { "type": "integer" }, - "deferred": { "type": "integer" } - }, - "description": "Conteos resumidos del Registro de Supuestos y Preguntas." - }, - "nextSteps": { - "type": "array", - "items": { "type": "string" }, - "description": "Lista ordenada de acciones recomendadas." - }, - "generatedAt": { - "type": "string", - "format": "date-time", - "description": "Marca de tiempo ISO 8601 de cuándo se generó este paquete." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "CTX-2024-001", - "version": "1.0.0", - "initiativeId": "KB-2024-001", - "adoptionLevel": "Mandatory", - "knowledgeBriefRef": "./discovery-knowledge-briefs/KB-2024-001.md", - "capabilities": [ - { "id": "CAP-001", "name": "Verificación de Identidad", "domain": "Ciclo de Vida del Cliente", "priority": "Must" }, - { "id": "CAP-002", "name": "Orquestación de Onboarding", "domain": "Ciclo de Vida del Cliente", "priority": "Must" }, - { "id": "CAP-003", "name": "Escaneo de Documentos KYC", "domain": "Compliance", "priority": "Should" } - ], - "openRisks": [ - { "description": "El SLA del proveedor de identidad está por debajo del 99.9% en períodos de pico", "probability": "Medium", "impact": "High", "mitigation": "Negociar cláusula de SLA o evaluar proveedor alternativo" } - ], - "assumptionsStatus": { "open": 2, "validated": 1, "invalidated": 0, "deferred": 1 }, - "nextSteps": [ - "Resolver la decisión de selección del proveedor de identidad (AQ-002)", - "Completar el mapa de capacidades con análisis de dependencias", - "Enviar para aprobación de la compuerta del Knowledge Brief" - ], - "generatedAt": "2024-02-01T10:00:00Z" -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -El **Paquete de Contexto de Discovery** sirve como entrada para: - -1. **Factibilidad Técnica** — las capacidades y riesgos informan el alcance de NFR y la validación de restricciones. -2. **Refinamiento del Mapa de Capacidades** — el paquete proporciona la lista inicial de capacidades para la descomposición de dominio. -3. **Desglose de Épicas** — las capacidades con prioridad `Must` se convierten en candidatas a épicas para el Design Baseline. -4. **Inicialización de repositorios satélite** — los agentes de IA consumen este paquete para inicializar el contexto del proyecto en nuevos repositorios. - -El campo `generatedAt` permite la validación de vigencia por herramientas CLI y guards de pipeline. - ---- - -## Quality Checklist - -- [ ] El ID de la iniciativa enlaza a un Knowledge Brief aprobado -- [ ] La lista de capacidades no está vacía y cada ítem tiene una prioridad -- [ ] Los riesgos abiertos están extraídos del Knowledge Brief (no inventados) -- [ ] Los conteos de estado de supuestos coinciden con el Registro de Supuestos y Preguntas -- [ ] Los siguientes pasos son accionables y ordenados por prioridad -- [ ] La estructura JSON valida contra el esquema -- [ ] `generatedAt` es un timestamp ISO 8601 válido -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas que hayan completado la aprobación de la compuerta del Knowledge Brief. El paquete de contexto debe regenerarse cada vez que el Knowledge Brief, el Registro de Supuestos o el Mapa de Capacidades cambien materialmente. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| Knowledge Brief aprobado | Generar paquete de contexto inicial | -| Nueva capacidad agregada al Mapa de Capacidades | Regenerar paquete, incrementar versión | -| Riesgo resuelto o nuevo riesgo agregado | Actualizar openRisks, incrementar versión | -| Estado de supuestos cambia | Actualizar conteos de assumptionsStatus, incrementar versión | -| Cambio material en el Knowledge Brief | Regenerar paquete desde cero, incrementar versión mayor | -| Revisión trimestral de vigencia | Validar generatedAt < 90 días; regenerar si obsoleto | diff --git a/reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.md b/reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.md deleted file mode 100644 index 7469ad74..00000000 --- a/reference/core/sdlc/04-artifact-templates/discovery-context-pack-template.md +++ /dev/null @@ -1,239 +0,0 @@ -# Template: Discovery Context Pack - -> **Bilingual Navigation:** [Versión en Español](./discovery-context-pack-template.es.md) -> **Purpose:** Exportable, self-contained knowledge package for AI agents and satellite repositories. Consumable by CLI, MCP, or direct reading. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Platform Architect / AI Agent Pipeline -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Approved Discovery Knowledge Brief, Assumptions & Questions Log, Capability Map. -* **Expected outputs:** Self-contained context pack that AI agents, CLI tools, and satellite repos can consume to bootstrap downstream artifacts. -* **Applied taxonomy:** Aligned with Evolith glossary (Initiative, Capability, Risk, Assumption, Adoption Level). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-20 (Satellite Upstream Promotion). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Discovery Context Pack: [Initiative Name] - -## 1. Executive Summary -[2-3 sentence overview of the initiative, its value, and current status. Machine-readable preamble.] - -## 2. Initiative ID -[Unique identifier referencing the originating Knowledge Brief.] - -## 3. Adoption Level -[Mandatory | Recommended | Optional — indicates how this context pack should be consumed by downstream processes.] - -## 4. Knowledge Brief Summary -[Condensed version of the Knowledge Brief: problem, value, key actors, and domain context.] - -| Field | Value | -|---|---| -| Problem | [One-line problem statement] | -| Value | [One-line value proposition] | -| Domain | [Primary domain / bounded context] | -| Sponsor | [Name] | - -## 5. Capability List -[Extracted from the Capability Map. Each capability is a business-meaningful unit of behavior.] - -| Capability ID | Name | Domain | Priority | -|---|---|---|---| -| CAP-001 | [Capability Name] | [Domain] | Must/Should/Could/Wont | - -## 6. Open Risks -[Risks from the Knowledge Brief that remain unresolved.] - -| Risk | Probability | Impact | Mitigation | -|---|---|---|---| -| [Risk] | [High/Med/Low] | [High/Med/Low] | [Strategy] | - -## 7. Assumptions Status -[Summary from the Assumptions & Questions Log.] - -| Status | Count | -|---|---| -| Open | [N] | -| Validated | [N] | -| Invalidated | [N] | -| Deferred | [N] | - -## 8. Recommended Next Steps -[Ordered list of immediate next actions for downstream consumers.] - -1. [Next step 1] -2. [Next step 2] -3. [Next step 3] -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI, MCP pipelines, and AI agent ingestion. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Discovery Context Pack", - "type": "object", - "required": ["id", "version", "initiativeId", "adoptionLevel", "knowledgeBriefRef", "capabilities", "openRisks", "assumptionsStatus", "nextSteps", "generatedAt"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this context pack instance." - }, - "version": { - "type": "string", - "description": "Semantic version of this context pack." - }, - "initiativeId": { - "type": "string", - "description": "Reference to the originating Knowledge Brief." - }, - "adoptionLevel": { - "type": "string", - "enum": ["Mandatory", "Recommended", "Optional"], - "description": "Adoption level for downstream consumers." - }, - "knowledgeBriefRef": { - "type": "string", - "description": "Path or URL to the full Knowledge Brief." - }, - "capabilities": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "domain", "priority"], - "properties": { - "id": { "type": "string" }, - "name": { "type": "string" }, - "domain": { "type": "string" }, - "priority": { "type": "string", "enum": ["Must", "Should", "Could", "Wont"] } - } - }, - "description": "Business-meaningful capability units extracted from the Capability Map." - }, - "openRisks": { - "type": "array", - "items": { - "type": "object", - "required": ["description", "probability", "impact"], - "properties": { - "description": { "type": "string" }, - "probability": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "impact": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "mitigation": { "type": "string" } - } - }, - "description": "Unresolved risks from the Knowledge Brief." - }, - "assumptionsStatus": { - "type": "object", - "required": ["open", "validated", "invalidated", "deferred"], - "properties": { - "open": { "type": "integer" }, - "validated": { "type": "integer" }, - "invalidated": { "type": "integer" }, - "deferred": { "type": "integer" } - }, - "description": "Summary counts from the Assumptions & Questions Log." - }, - "nextSteps": { - "type": "array", - "items": { "type": "string" }, - "description": "Ordered list of recommended next actions." - }, - "generatedAt": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp of when this pack was generated." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "CTX-2024-001", - "version": "1.0.0", - "initiativeId": "KB-2024-001", - "adoptionLevel": "Mandatory", - "knowledgeBriefRef": "./discovery-knowledge-briefs/KB-2024-001.md", - "capabilities": [ - { "id": "CAP-001", "name": "Identity Verification", "domain": "Customer Lifecycle", "priority": "Must" }, - { "id": "CAP-002", "name": "Onboarding Orchestration", "domain": "Customer Lifecycle", "priority": "Must" }, - { "id": "CAP-003", "name": "KYC Document Scanning", "domain": "Compliance", "priority": "Should" } - ], - "openRisks": [ - { "description": "Identity provider SLA below 99.9% during peak periods", "probability": "Medium", "impact": "High", "mitigation": "Negotiate SLA clause or evaluate fallback provider" } - ], - "assumptionsStatus": { "open": 2, "validated": 1, "invalidated": 0, "deferred": 1 }, - "nextSteps": [ - "Resolve identity provider selection decision (AQ-002)", - "Complete capability map with dependency analysis", - "Submit for Knowledge Brief gate approval" - ], - "generatedAt": "2024-02-01T10:00:00Z" -} -``` - ---- - -## 4. Handoff to Next Artifact - -The **Discovery Context Pack** serves as the input for: - -1. **Technical Feasibility** — capabilities and risks inform NFR scoping and constraint validation. -2. **Capability Map refinement** — the pack provides the initial capability list for domain decomposition. -3. **Epic breakdown** — capabilities with `Must` priority become epic candidates for Design Baseline. -4. **Satellite repository bootstrap** — AI agents consume this pack to initialize project context in new repositories. - -The `generatedAt` field enables freshness validation by CLI tools and pipeline guards. - ---- - -## Quality Checklist - -- [ ] Initiative ID links to an approved Knowledge Brief -- [ ] Capability list is non-empty and each item has a priority -- [ ] Open risks are extracted from the Knowledge Brief (not invented) -- [ ] Assumptions status counts match the Assumptions & Questions Log -- [ ] Next steps are actionable and ordered by priority -- [ ] JSON structure validates against the schema -- [ ] `generatedAt` is a valid ISO 8601 timestamp -- [ ] Language is consistent (no mixed EN/ES within the file) - ---- - -## Recommended Adoption Level - -**Mandatory** for all initiatives that have completed the Knowledge Brief approval gate. The context pack must be regenerated whenever the Knowledge Brief, Assumptions Log, or Capability Map changes materially. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| Knowledge Brief approved | Generate initial context pack | -| New capability added to Capability Map | Regenerate pack, increment version | -| Risk resolved or new risk added | Update openRisks, increment version | -| Assumptions status changes | Update assumptionsStatus counts, increment version | -| Material change to Knowledge Brief | Regenerate pack from scratch, increment major version | -| Quarterly freshness review | Validate generatedAt < 90 days; regenerate if stale | diff --git a/reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.es.md b/reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.es.md deleted file mode 100644 index 98ecf1b0..00000000 --- a/reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.es.md +++ /dev/null @@ -1,279 +0,0 @@ -# Plantilla: Discovery Knowledge Brief - -> **Navegación Bilingüe:** [English Version](./discovery-knowledge-brief-template.md) -> **Propósito:** Documento base que captura el problema, el valor, los actores, el contexto, las restricciones y los riesgos. Esta es la semilla de conocimiento para toda la iniciativa. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Product Owner / Business Analyst -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Disparador de negocio o problema detectado, patrocinador identificado, mapa de stakeholders. -* **Salidas Esperadas:** Knowledge Brief aprobado que alimenta el Registro de Supuestos y Preguntas, el Paquete de Contexto de Discovery y el Mapa de Capacidades. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Bounded Context, Value Stream, Risk, Assumption). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Discovery Knowledge Brief: [Nombre de la Iniciativa] - -## 1. Declaración del Problema -[¿Qué problema u oportunidad específica se está abordando? Usa lenguaje de negocio claro (Rule R-09).] - -## 2. Propuesta de Valor -[¿Qué valor medible o cualitativo genera resolver este problema? Cuantifica cuando sea posible.] - -## 3. Stakeholders / Actores -[¿Quiénes son los actores clave? Incluye patrocinador, usuarios finales, equipos afectados y tomadores de decisiones.] - -| Rol | Nombre / Equipo | Responsabilidad | -|---|---|---| -| Patrocinador | [Nombre] | [Responsabilidad] | -| Product Owner | [Nombre] | [Responsabilidad] | -| Arquitecto | [Nombre] | [Responsabilidad] | -| Usuarios Afectados | [Equipo/Grupo] | [Descripción del impacto] | - -## 4. Contexto de Dominio -[Describe el dominio de negocio, los bounded contexts involucrados y cómo esta iniciativa se relaciona con sistemas existentes.] - -## 5. Restricciones -[¿Qué restricciones organizativas, técnicas, regulatorias o de recursos limitan el espacio de soluciones?] - -- [Restricción 1] -- [Restricción 2] - -## 6. Riesgos -[¿Qué podría impedir el éxito o reducir la entrega de valor? Incluye probabilidad e impacto.] - -| Riesgo | Probabilidad | Impacto | Mitigación | -|---|---|---|---| -| [Riesgo 1] | [Alta/Media/Baja] | [Alta/Media/Baja] | [Estrategia] | - -## 7. Supuestos -[¿Qué condiciones deben cumplirse para que esta iniciativa tenga éxito?] - -- [Supuesto 1] -- [Supuesto 2] - -## 8. Candidatos de Decisión -[¿Qué decisiones arquitectónicas o de producto deben tomarse antes de avanzar?] - -| Decisión | Opciones | Estado | -|---|---|---| -| [Decisión 1] | [Opción A vs Opción B] | Abierta | - -## 9. Enlaces de Evidencia -[Enlaces a documentos de soporte, fuentes de datos, investigación o artefactos previos.] - -| Evidencia | Tipo | Enlace | -|---|---|---| -| [Evidencia 1] | [Datos/Investigación/ADR] | [URL o ruta] | -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith y herramientas automáticas de scaffolding. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Discovery Knowledge Brief", - "type": "object", - "required": ["id", "businessTriggerId", "problem", "value", "actors", "context", "constraints", "risks", "assumptions", "decisionCandidates", "evidenceLinks", "adoptionLevel", "status"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de este Knowledge Brief." - }, - "businessTriggerId": { - "type": "string", - "description": "Referencia al disparador de negocio o ticket de problema." - }, - "problem": { - "type": "string", - "description": "Descripción en lenguaje claro del problema u oportunidad." - }, - "value": { - "type": "string", - "description": "Valor o beneficio esperado de resolver el problema." - }, - "actors": { - "type": "array", - "items": { - "type": "object", - "required": ["role", "name", "responsibility"], - "properties": { - "role": { "type": "string" }, - "name": { "type": "string" }, - "responsibility": { "type": "string" } - } - }, - "description": "Stakeholders clave y sus roles." - }, - "context": { - "type": "string", - "description": "Contexto del dominio de negocio y relaciones con bounded contexts." - }, - "constraints": { - "type": "array", - "items": { "type": "string" }, - "description": "Restricciones organizativas, técnicas o regulatorias." - }, - "risks": { - "type": "array", - "items": { - "type": "object", - "required": ["description", "probability", "impact"], - "properties": { - "description": { "type": "string" }, - "probability": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "impact": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "mitigation": { "type": "string" } - } - }, - "description": "Riesgos identificados con probabilidad e impacto." - }, - "assumptions": { - "type": "array", - "items": { "type": "string" }, - "description": "Condiciones que deben cumplirse para el éxito." - }, - "decisionCandidates": { - "type": "array", - "items": { - "type": "object", - "required": ["decision", "options", "status"], - "properties": { - "decision": { "type": "string" }, - "options": { "type": "string" }, - "status": { "type": "string", "enum": ["Open", "Decided", "Deferred"] } - } - }, - "description": "Decisiones pendientes que requieren resolución." - }, - "evidenceLinks": { - "type": "array", - "items": { - "type": "object", - "required": ["label", "type", "url"], - "properties": { - "label": { "type": "string" }, - "type": { "type": "string" }, - "url": { "type": "string" } - } - }, - "description": "Evidencia de soporte y referencias." - }, - "adoptionLevel": { - "type": "string", - "enum": ["Mandatory", "Recommended", "Optional"], - "description": "Nivel de adopción de este artefacto." - }, - "status": { - "type": "string", - "enum": ["Draft", "In Review", "Approved", "Superseded"], - "description": "Estado actual del ciclo de vida." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "KB-2024-001", - "businessTriggerId": "JIRA-PROJ-456", - "problem": "El onboarding de clientes tarda 48 horas debido a la verificación manual de identidad, causando un 40% de abandono en las primeras 24 horas.", - "value": "Reducir el tiempo de onboarding a menos de 5 minutos y disminuir la tasa de abandono en un 60% en dos cuatrimestres.", - "actors": [ - { "role": "Patrocinador", "name": "VP de Experiencia de Cliente", "responsibility": "Autoridad presupuestaria y alineación estratégica" }, - { "role": "Product Owner", "name": "María López", "responsibility": "Propiedad del backlog y comunicación con stakeholders" }, - { "role": "Arquitecto", "name": "Carlos Ruiz", "responsibility": "Factibilidad técnica y diseño de bounded context" } - ], - "context": "El onboarding digital abarca los bounded contexts de Verificación de Identidad y Ciclo de Vida del Cliente. Los sistemas existentes usan un módulo de autenticación monolítico que no puede escalar a integraciones de canales de socios.", - "constraints": [ - "Debe cumplir con regulaciones KYC/AML para todos los mercados objetivo", - "El contrato actual del proveedor de identidad vence en 6 meses", - "La capacidad del equipo se limita a 4 ingenieros en Q1" - ], - "risks": [ - { "description": "El SLA del proveedor de identidad está por debajo del 99.9% en períodos de pico", "probability": "Medium", "impact": "High", "mitigation": "Negociar cláusula de SLA o evaluar proveedor alternativo" }, - { "description": "Retrasos en aprobación regulatoria para el nuevo flujo de verificación", "probability": "Low", "impact": "High", "mitigation": "Compromiso temprano con el equipo de Compliance" } - ], - "assumptions": [ - "Los requisitos KYC/AML son estables para los próximos 12 meses", - "Las cuotas del proveedor de nube soportan la concurrencia proyectada de 500 req/s", - "El bus de eventos existente puede absorber los eventos del dominio de onboarding sin re-arquitectura" - ], - "decisionCandidates": [ - { "decision": "Selección del proveedor de identidad", "options": "Proveedor actual vs. alternativo con soporte OAuth2", "status": "Open" }, - { "decision": "Patrón de orquestación del onboarding", "options": "Saga vs. Corografía vs. Orquestación", "status": "Open" } - ], - "evidenceLinks": [ - { "label": "Informe de Abandono Q3", "type": "Data", "url": "./docs/reports/q3-abandonment.md" }, - { "label": "Resumen Regulatorio KYC", "type": "Research", "url": "./docs/compliance/kyc-regulatory-brief.md" } - ], - "adoptionLevel": "Mandatory", - "status": "In Review" -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -Una vez aprobado, el **Knowledge Brief** alimenta directamente: - -1. **Registro de Supuestos y Preguntas** — todos los supuestos y decisiones abiertas migran al registro vivo para seguimiento. -2. **Paquete de Contexto de Discovery** — los campos del Knowledge Brief poblan el paquete de contexto para agentes de IA y repositorios satélite. -3. **Mapa de Capacidades** — el contexto del dominio y la declaración del problema informan la descomposición de capacidades. - -Los campos `actors`, `risks` y `decisionCandidates` son consumidos por artefactos descendentes sin transformación. - ---- - -## Quality Checklist - -- [ ] La declaración del problema es específica, medible y escrita en lenguaje de negocio claro -- [ ] La propuesta de valor incluye al menos una métrica cuantificable -- [ ] Todos los stakeholders clave están identificados con responsabilidades claras -- [ ] Las restricciones están listadas explícitamente (no enterradas en prosa) -- [ ] Los riesgos incluyen evaluaciones de probabilidad e impacto -- [ ] Los supuestos son verificables de forma independiente -- [ ] Los candidatos de decisión listan opciones concretas (no áreas vagas) -- [ ] Los enlaces de evidencia resuelven a documentos o fuentes de datos reales -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) -- [ ] El documento está almacenado en control de versiones junto con el código o artefactos de diseño relevantes - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas nuevas que ingresan a Discovery. El Knowledge Brief es el prerrequisito para el Registro de Supuestos y Preguntas, el Paquete de Contexto de Discovery y el Mapa de Capacidades. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| Nuevo stakeholder identificado | Agregar a la tabla de actores y al array actors del JSON | -| Riesgo materializado o nuevo riesgo emergente | Actualizar la sección de riesgos con probabilidad/impacto actual | -| Supuesto validado o invalidado | Actualizar supuestos y sincronizar con el Registro de Supuestos y Preguntas | -| Candidato de decisión resuelto | Marcar como Decided, registrar resultado y enlazar al ADR | -| Cambio en el alcance del disparador de negocio | Revisar la declaración del problema y la propuesta de valor | -| Revisión trimestral | Revisión completa del artefacto; degradar o cerrar si la iniciativa está inactiva | diff --git a/reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.md b/reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.md deleted file mode 100644 index f58bb34b..00000000 --- a/reference/core/sdlc/04-artifact-templates/discovery-knowledge-brief-template.md +++ /dev/null @@ -1,279 +0,0 @@ -# Template: Discovery Knowledge Brief - -> **Bilingual Navigation:** [Versión en Español](./discovery-knowledge-brief-template.es.md) -> **Purpose:** Foundation document capturing the problem, value, actors, context, constraints, and risks. This is the knowledge seed for the entire initiative. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Product Owner / Business Analyst -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Business trigger or detected problem, sponsor identified, stakeholder map. -* **Expected outputs:** Approved Knowledge Brief that seeds the Assumptions & Questions Log, Discovery Context Pack, and Capability Map. -* **Applied taxonomy:** Aligned with Evolith glossary (Bounded Context, Value Stream, Risk, Assumption). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Discovery Knowledge Brief: [Initiative Name] - -## 1. Problem Statement -[What specific problem or opportunity is being addressed? Use plain business language (Rule R-09).] - -## 2. Value Proposition -[What measurable or qualitative value does solving this problem deliver? Quantify when possible.] - -## 3. Stakeholders / Actors -[Who are the key actors? Include sponsor, end-users, affected teams, and decision-makers.] - -| Role | Name / Team | Responsibility | -|---|---|---| -| Sponsor | [Name] | [Accountability] | -| Product Owner | [Name] | [Accountability] | -| Architect | [Name] | [Accountability] | -| Affected Users | [Team/Group] | [Impact description] | - -## 4. Domain Context -[Describe the business domain, bounded contexts involved, and how this initiative relates to existing systems.] - -## 5. Constraints -[What organizational, technical, regulatory, or resource constraints limit the solution space?] - -- [Constraint 1] -- [Constraint 2] - -## 6. Risks -[What could prevent success or reduce value delivery? Include probability and impact.] - -| Risk | Probability | Impact | Mitigation | -|---|---|---|---| -| [Risk 1] | [High/Med/Low] | [High/Med/Low] | [Strategy] | - -## 7. Assumptions -[What conditions must hold true for this initiative to succeed?] - -- [Assumption 1] -- [Assumption 2] - -## 8. Decision Candidates -[What architectural or product decisions need to be made before proceeding?] - -| Decision | Options | Status | -|---|---|---| -| [Decision 1] | [Option A vs Option B] | Open | - -## 9. Evidence Links -[Links to supporting documents, data sources, research, or prior artifacts.] - -| Evidence | Type | Link | -|---|---|---| -| [Evidence 1] | [Data/Research/ADR] | [URL or path] | -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI and automated scaffolding tools. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Discovery Knowledge Brief", - "type": "object", - "required": ["id", "businessTriggerId", "problem", "value", "actors", "context", "constraints", "risks", "assumptions", "decisionCandidates", "evidenceLinks", "adoptionLevel", "status"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this Knowledge Brief." - }, - "businessTriggerId": { - "type": "string", - "description": "Reference to the business trigger or problem ticket." - }, - "problem": { - "type": "string", - "description": "Plain-language description of the problem or opportunity." - }, - "value": { - "type": "string", - "description": "Expected value or benefit of solving the problem." - }, - "actors": { - "type": "array", - "items": { - "type": "object", - "required": ["role", "name", "responsibility"], - "properties": { - "role": { "type": "string" }, - "name": { "type": "string" }, - "responsibility": { "type": "string" } - } - }, - "description": "Key stakeholders and their roles." - }, - "context": { - "type": "string", - "description": "Business domain context and bounded context relationships." - }, - "constraints": { - "type": "array", - "items": { "type": "string" }, - "description": "Organizational, technical, or regulatory constraints." - }, - "risks": { - "type": "array", - "items": { - "type": "object", - "required": ["description", "probability", "impact"], - "properties": { - "description": { "type": "string" }, - "probability": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "impact": { "type": "string", "enum": ["High", "Medium", "Low"] }, - "mitigation": { "type": "string" } - } - }, - "description": "Identified risks with probability and impact." - }, - "assumptions": { - "type": "array", - "items": { "type": "string" }, - "description": "Conditions that must hold true for success." - }, - "decisionCandidates": { - "type": "array", - "items": { - "type": "object", - "required": ["decision", "options", "status"], - "properties": { - "decision": { "type": "string" }, - "options": { "type": "string" }, - "status": { "type": "string", "enum": ["Open", "Decided", "Deferred"] } - } - }, - "description": "Pending decisions requiring resolution." - }, - "evidenceLinks": { - "type": "array", - "items": { - "type": "object", - "required": ["label", "type", "url"], - "properties": { - "label": { "type": "string" }, - "type": { "type": "string" }, - "url": { "type": "string" } - } - }, - "description": "Supporting evidence and references." - }, - "adoptionLevel": { - "type": "string", - "enum": ["Mandatory", "Recommended", "Optional"], - "description": "Adoption level for this artifact." - }, - "status": { - "type": "string", - "enum": ["Draft", "In Review", "Approved", "Superseded"], - "description": "Current lifecycle status." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "KB-2024-001", - "businessTriggerId": "JIRA-PROJ-456", - "problem": "Customer onboarding takes 48 hours due to manual identity verification, causing 40% abandonment in the first 24 hours.", - "value": "Reduce onboarding time to under 5 minutes and cut abandonment rate by 60% within two quarters.", - "actors": [ - { "role": "Sponsor", "name": "VP of Customer Experience", "responsibility": "Budget authority and strategic alignment" }, - { "role": "Product Owner", "name": "Maria Lopez", "responsibility": "Backlog ownership and stakeholder communication" }, - { "role": "Architect", "name": "Carlos Ruiz", "responsibility": "Technical feasibility and bounded context design" } - ], - "context": "Digital onboarding spans the Identity Verification and Customer Lifecycle bounded contexts. Existing systems use a monolithic auth module that cannot scale to partner-channel integrations.", - "constraints": [ - "Must comply with KYC/AML regulations for all target markets", - "Current identity provider contract expires in 6 months", - "Team capacity limited to 4 engineers for Q1" - ], - "risks": [ - { "description": "Identity provider SLA below 99.9% during peak periods", "probability": "Medium", "impact": "High", "mitigation": "Negotiate SLA clause or evaluate fallback provider" }, - { "description": "Regulatory approval delays for new verification flow", "probability": "Low", "impact": "High", "mitigation": "Early engagement with Compliance team" } - ], - "assumptions": [ - "KYC/AML compliance requirements are stable for the next 12 months", - "Cloud provider quotas support projected concurrency of 500 req/s", - "Existing event bus can absorb onboarding domain events without re-architecture" - ], - "decisionCandidates": [ - { "decision": "Identity provider selection", "options": "Current vendor vs. alternative with OAuth2 support", "status": "Open" }, - { "decision": "Onboarding orchestration pattern", "options": "Saga vs. Choreography vs. Orchestration", "status": "Open" } - ], - "evidenceLinks": [ - { "label": "Q3 Abandonment Report", "type": "Data", "url": "./docs/reports/q3-abandonment.md" }, - { "label": "KYC Regulatory Brief", "type": "Research", "url": "./docs/compliance/kyc-regulatory-brief.md" } - ], - "adoptionLevel": "Mandatory", - "status": "In Review" -} -``` - ---- - -## 4. Handoff to Next Artifact - -Once approved, the **Knowledge Brief** feeds directly into: - -1. **Assumptions & Questions Log** — all assumptions and open decisions migrate to the living log for tracking. -2. **Discovery Context Pack** — the Knowledge Brief fields populate the context pack for AI agents and satellite repositories. -3. **Capability Map** — domain context and problem statement inform capability decomposition. - -The `actors`, `risks`, and `decisionCandidates` fields are consumed by downstream artifacts without transformation. - ---- - -## Quality Checklist - -- [ ] Problem statement is specific, measurable, and written in plain business language -- [ ] Value proposition includes at least one quantifiable metric -- [ ] All key stakeholders are identified with clear responsibilities -- [ ] Constraints are explicitly listed (not buried in prose) -- [ ] Risks include both probability and impact assessments -- [ ] Assumptions are independently verifiable -- [ ] Decision candidates list concrete options (not vague areas) -- [ ] Evidence links resolve to actual documents or data sources -- [ ] Language is consistent (no mixed EN/ES within the file) -- [ ] Document is stored in version control alongside relevant code or design artifacts - ---- - -## Recommended Adoption Level - -**Mandatory** for all new initiatives entering Discovery. The Knowledge Brief is the prerequisite for the Assumptions & Questions Log, Discovery Context Pack, and Capability Map. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| New stakeholder identified | Add to actors table and JSON actors array | -| Risk materializes or new risk emerges | Update risks section with current probability/impact | -| Assumption validated or invalidated | Update assumptions and sync to Assumptions & Questions Log | -| Decision candidate resolved | Mark as Decided, record outcome, and link to ADR | -| Business trigger scope changes | Revisit problem statement and value proposition | -| Quarterly review | Full artifact review; downgrade or close if initiative is dormant | diff --git a/reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.es.md b/reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.es.md deleted file mode 100644 index cf1187f1..00000000 --- a/reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.es.md +++ /dev/null @@ -1,285 +0,0 @@ -# Plantilla: Discovery Readiness Gate - -> **Navegación Bilingüe:** [English Version](./discovery-readiness-gate-template.md) -> **Propósito:** Gate formal que valida la suficiencia del conocimiento antes de proceder al backlog y diseño. Se usa en Nivel 3+. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Product Owner / Business Analyst -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Knowledge Brief aprobado, Registro de Supuestos y Preguntas validado, Epic Candidate Matrix, Story Seed Bank. -* **Salidas Esperadas:** Decisión del gate (PASS / CONDITIONAL / FAIL) con evidencia para cada verificación. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Gate, Check, Waiver, Decision, Traceability). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Discovery Readiness Gate: [Nombre de la Iniciativa] - -## 1. Información del Gate - -| Campo | Valor | -|---|---| -| ID del Gate | DRG-[YYYY]-[NNN] | -| ID de Iniciativa | [Identificador de la iniciativa] | -| Nivel de Adopción | Nivel 3+ | -| Fecha de Decisión | [YYYY-MM-DD] | -| Decidido Por | [Nombre / Rol] | - -## 2. Verificaciones del Gate - -### Problema y Valor - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 1 | La declaración del problema es específica y medible | [Pass/Fail/Waiver] | [Enlace a Knowledge Brief §1] | | -| 2 | La propuesta de valor incluye métricas cuantificables | [Pass/Fail/Waiver] | [Enlace a Knowledge Brief §2] | | -| 3 | El disparador de negocio y el patrocinador están identificados | [Pass/Fail/Waiver] | [Enlace a Knowledge Brief §3] | | - -### Stakeholders - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 4 | Todos los stakeholders clave identificados con responsabilidades | [Pass/Fail/Waiver] | [Enlace a Knowledge Brief §3] | | -| 5 | Los equipos afectados reconocidos y consultados | [Pass/Fail/Waiver] | [Notas de reunión o correo] | | - -### Capacidades - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 6 | El Mapa de Capacidades está completo para el alcance de la iniciativa | [Pass/Fail/Waiver] | [Enlace al Mapa de Capacidades] | | -| 7 | Al menos un candidato de épica tiene Prioridad = Must | [Pass/Fail/Waiver] | [Enlace al Epic Candidate Matrix] | | -| 8 | Los tamaños de épica están estimados (sin XL sin plan de división) | [Pass/Fail/Waiver] | [Enlace al Epic Candidate Matrix] | | - -### Trazabilidad - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 9 | Cada épica traza a un ID de Capacidad | [Pass/Fail/Waiver] | [Enlace al Epic Candidate Matrix] | | -| 10 | Cada semilla de historia traza a un ID de Candidato de Épica | [Pass/Fail/Waiver] | [Enlace al Story Seed Bank] | | -| 11 | Los supuestos están enlazados a artefactos de origen | [Pass/Fail/Waiver] | [Enlace al Registro de Supuestos y Preguntas] | | - -### Riesgos y Supuestos - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 12 | Todos los riesgos de alto impacto tienen planes de mitigación | [Pass/Fail/Waiver] | [Enlace a Knowledge Brief §6] | | -| 13 | Ningún supuesto crítico permanece sin validar | [Pass/Fail/Waiver] | [Enlace al Registro de Supuestos y Preguntas] | | -| 14 | Las preguntas abiertas tienen propietarios y fechas objetivo | [Pass/Fail/Waiver] | [Enlace al Registro de Supuestos y Preguntas] | | - -### Restricciones de Arquitectura - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 15 | Las restricciones técnicas están documentadas | [Pass/Fail/Waiver] | [Enlace a Knowledge Brief §5] | | -| 16 | Los límites de bounded context están definidos | [Pass/Fail/Waiver] | [Enlace al Modelo DDD o Documento de Arquitectura] | | - -### Paquete de Contexto - -| # | Criterio | Estado | Evidencia | Notas | -|---|---|---|---|---| -| 17 | El Paquete de Contexto de Discovery está poblado | [Pass/Fail/Waiver] | [Enlace al Context Pack] | | -| 18 | El Paquete de Contexto es accesible para agentes descendentes | [Pass/Fail/Waiver] | [Enlace o confirmación de acceso] | | - -## 3. Exenciones (Waivers) - -| Verificación # | Justificación | Aprobado Por | Fecha de Expiración | -|---|---|---|---| -| [N] | [Por qué se exime esta verificación] | [Nombre] | [YYYY-MM-DD] | - -## 4. Decisión - -| Campo | Valor | -|---|---| -| Decisión | [PASS / CONDITIONAL / FAIL] | -| Justificación | [Resumen de por qué se tomó esta decisión] | -| Condiciones (si CONDITIONAL) | [Qué debe resolverse antes de proceder] | -| Próximos Pasos | [Acciones a tomar basadas en la decisión] | -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith y herramientas de seguimiento de gates automáticas. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Discovery Readiness Gate", - "type": "object", - "required": ["id", "gateId", "initiativeId", "adoptionLevel", "checks", "decision", "decidedAt", "decidedBy"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de esta instancia de gate." - }, - "gateId": { - "type": "string", - "description": "Identificador formal del gate (ej., DRG-2024-001)." - }, - "initiativeId": { - "type": "string", - "description": "Referencia a la iniciativa sometida al gate." - }, - "adoptionLevel": { - "type": "string", - "description": "Nivel de adopción requerido para este gate (ej., Nivel 3+)." - }, - "checks": { - "type": "array", - "items": { - "type": "object", - "required": ["category", "criterion", "status", "evidence", "notes"], - "properties": { - "category": { - "type": "string", - "description": "Categoría de la verificación del gate (ej., Problema y Valor, Stakeholders)." - }, - "criterion": { - "type": "string", - "description": "El criterio específico que se está evaluando." - }, - "status": { - "type": "string", - "enum": ["Pass", "Fail", "Waiver"], - "description": "Resultado de la verificación." - }, - "evidence": { - "type": "string", - "description": "Enlace o referencia a evidencia de soporte." - }, - "notes": { - "type": "string", - "description": "Notas adicionales o contexto para esta verificación." - } - } - }, - "description": "Array de verificaciones del gate organizadas por categoría." - }, - "decision": { - "type": "string", - "enum": ["PASS", "CONDITIONAL", "FAIL"], - "description": "Decisión general del gate." - }, - "waivers": { - "type": "array", - "items": { - "type": "object", - "required": ["checkNumber", "rationale", "approvedBy", "expiryDate"], - "properties": { - "checkNumber": { - "type": "integer", - "description": "El número de verificación que se exime." - }, - "rationale": { - "type": "string", - "description": "Justificación de la exención." - }, - "approvedBy": { - "type": "string", - "description": "Persona que aprobó la exención." - }, - "expiryDate": { - "type": "string", - "format": "date", - "description": "Cuándo expira la exención (ISO 8601)." - } - } - }, - "description": "Exenciones para verificaciones fallidas que se aceptan con justificación." - }, - "decidedAt": { - "type": "string", - "format": "date-time", - "description": "Marca de tiempo de cuándo se tomó la decisión del gate (ISO 8601)." - }, - "decidedBy": { - "type": "string", - "description": "Persona o rol que tomó la decisión del gate." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "DRG-2024-001", - "gateId": "DRG-2024-001", - "initiativeId": "INIT-ONBOARD-2024", - "adoptionLevel": "Level 3+", - "checks": [ - { "category": "Problem & Value", "criterion": "Problem statement is specific and measurable", "status": "Pass", "evidence": "KB-2024-001 §1", "notes": "" }, - { "category": "Problem & Value", "criterion": "Value proposition includes quantifiable metrics", "status": "Pass", "evidence": "KB-2024-001 §2", "notes": "Se definió objetivo de reducción del 60%" }, - { "category": "Problem & Value", "criterion": "Business trigger and sponsor are identified", "status": "Pass", "evidence": "KB-2024-001 §3", "notes": "" }, - { "category": "Capabilities", "criterion": "At least one epic candidate has Priority = Must", "status": "Pass", "evidence": "ECM-2024-001", "notes": "EC-001 y EC-002 son Must" }, - { "category": "Capabilities", "criterion": "Epic sizes are estimated", "status": "Pass", "evidence": "ECM-2024-001", "notes": "Sin épicas XL" }, - { "category": "Traceability", "criterion": "Every epic traces to a Capability ID", "status": "Pass", "evidence": "ECM-2024-001", "notes": "" }, - { "category": "Risks & Assumptions", "criterion": "No critical assumptions remain unvalidated", "status": "Waiver", "evidence": "AQ-LOG-2024-001", "notes": "AQ-002 diferido a Q2 con aprobación del patrocinador" } - ], - "decision": "CONDITIONAL", - "waivers": [ - { "checkNumber": 13, "rationale": "La selección del proveedor de identidad se difiere a Q2; el patrocinador aprobó la exención", "approvedBy": "VP de Experiencia de Cliente", "expiryDate": "2024-06-30" } - ], - "decidedAt": "2024-01-25T14:00:00Z", - "decidedBy": "María López, Product Owner" -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -Una decisión **PASS** o **CONDITIONAL** en el **Discovery Readiness Gate** habilita: - -1. **Refinamiento del Backlog** — las semillas de historia K2+ entran a sesiones de refinamiento para planificación del sprint. -2. **Línea Base de Diseño** — el diseño de arquitectura y UX puede proceder con restricciones validadas. -3. **Factibilidad Técnica** — los supuestos validados informan los objetivos de NFR y la validación de restricciones. - -Una decisión **FAIL** devuelve la iniciativa a Discovery para investigación adicional o ajuste de alcance. - ---- - -## Quality Checklist - -- [ ] Las 18 verificaciones están evaluadas (sin verificación en blanco) -- [ ] Cada Fail tiene un plan de remediación o una exención documentada -- [ ] Las exenciones tienen aprobación del patrocinador y fechas de expiración -- [ ] Los enlaces de evidencia resuelven a artefactos reales -- [ ] La justificación de la decisión está documentada y es trazable -- [ ] El gate es revisado por al menos el Product Owner y un líder técnico -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) -- [ ] El documento está almacenado en control de versiones junto con el código o artefactos de diseño relevantes - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas en Nivel 3+ de adopción. El Discovery Readiness Gate es el punto de control formal antes de transitar de las fases de Discovery a Diseño y Backlog. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| La evidencia de una verificación queda desactualizada | Reevaluar la verificación con evidencia actualizada | -| Una exención expira | Reevaluar la verificación o renovar la exención con aprobación del patrocinador | -| Nuevo riesgo o supuesto surge | Agregar a la categoría de verificación relevante; reevaluar la decisión del gate | -| La decisión cambia (ej., CONDITIONAL a PASS) | Actualizar campo de decisión, registrar justificación, notificar a stakeholders | -| El alcance de la iniciativa cambia materialmente | Re-ejecutar la evaluación completa del gate | -| Revisión trimestral | Verificar que la decisión del gate siga siendo válida; cerrar si la iniciativa está inactiva | diff --git a/reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.md b/reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.md deleted file mode 100644 index b3a1ff37..00000000 --- a/reference/core/sdlc/04-artifact-templates/discovery-readiness-gate-template.md +++ /dev/null @@ -1,285 +0,0 @@ -# Template: Discovery Readiness Gate - -> **Bilingual Navigation:** [Versión en Español](./discovery-readiness-gate-template.es.md) -> **Purpose:** Formal gate validating knowledge sufficiency before proceeding to backlog and design. Used at Level 3+. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Product Owner / Business Analyst -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Approved Discovery Knowledge Brief, validated Assumptions & Questions Log, Epic Candidate Matrix, Story Seed Bank. -* **Expected outputs:** Gate decision (PASS / CONDITIONAL / FAIL) with evidence for each check. -* **Applied taxonomy:** Aligned with Evolith glossary (Gate, Check, Waiver, Decision, Traceability). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Discovery Readiness Gate: [Initiative Name] - -## 1. Gate Information - -| Field | Value | -|---|---| -| Gate ID | DRG-[YYYY]-[NNN] | -| Initiative ID | [Initiative identifier] | -| Adoption Level | Level 3+ | -| Decision Date | [YYYY-MM-DD] | -| Decided By | [Name / Role] | - -## 2. Gate Checks - -### Problem & Value - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 1 | Problem statement is specific and measurable | [Pass/Fail/Waiver] | [Link to Knowledge Brief §1] | | -| 2 | Value proposition includes quantifiable metrics | [Pass/Fail/Waiver] | [Link to Knowledge Brief §2] | | -| 3 | Business trigger and sponsor are identified | [Pass/Fail/Waiver] | [Link to Knowledge Brief §3] | | - -### Stakeholders - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 4 | All key stakeholders identified with responsibilities | [Pass/Fail/Waiver] | [Link to Knowledge Brief §3] | | -| 5 | Affected teams acknowledged and consulted | [Pass/Fail/Waiver] | [Meeting notes or email] | | - -### Capabilities - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 6 | Capability Map is complete for the initiative scope | [Pass/Fail/Waiver] | [Link to Capability Map] | | -| 7 | At least one epic candidate has Priority = Must | [Pass/Fail/Waiver] | [Link to Epic Candidate Matrix] | | -| 8 | Epic sizes are estimated (no XL without split plan) | [Pass/Fail/Waiver] | [Link to Epic Candidate Matrix] | | - -### Traceability - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 9 | Every epic traces to a Capability ID | [Pass/Fail/Waiver] | [Link to Epic Candidate Matrix] | | -| 10 | Every story seed traces to an Epic Candidate ID | [Pass/Fail/Waiver] | [Link to Story Seed Bank] | | -| 11 | Assumptions are linked to originating artifacts | [Pass/Fail/Waiver] | [Link to Assumptions & Questions Log] | | - -### Risks & Assumptions - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 12 | All high-impact risks have mitigation plans | [Pass/Fail/Waiver] | [Link to Knowledge Brief §6] | | -| 13 | No critical assumptions remain unvalidated | [Pass/Fail/Waiver] | [Link to Assumptions & Questions Log] | | -| 14 | Open questions have owners and target dates | [Pass/Fail/Waiver] | [Link to Assumptions & Questions Log] | | - -### Architecture Constraints - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 15 | Technical constraints are documented | [Pass/Fail/Waiver] | [Link to Knowledge Brief §5] | | -| 16 | Bounded context boundaries are defined | [Pass/Fail/Waiver] | [Link to DDD Model or Architecture Doc] | | - -### Context Pack - -| # | Criterion | Status | Evidence | Notes | -|---|---|---|---|---| -| 17 | Discovery Context Pack is populated | [Pass/Fail/Waiver] | [Link to Context Pack] | | -| 18 | Context Pack is accessible to downstream agents | [Pass/Fail/Waiver] | [Link or access confirmation] | | - -## 3. Waivers - -| Check # | Rationale | Approved By | Expiry Date | -|---|---|---|---| -| [N] | [Why this check is waived] | [Name] | [YYYY-MM-DD] | - -## 4. Decision - -| Field | Value | -|---|---| -| Decision | [PASS / CONDITIONAL / FAIL] | -| Rationale | [Summary of why this decision was made] | -| Conditions (if CONDITIONAL) | [What must be resolved before proceeding] | -| Next Steps | [Actions to take based on the decision] | -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI and automated gate tracking tools. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Discovery Readiness Gate", - "type": "object", - "required": ["id", "gateId", "initiativeId", "adoptionLevel", "checks", "decision", "decidedAt", "decidedBy"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this gate instance." - }, - "gateId": { - "type": "string", - "description": "Formal gate identifier (e.g., DRG-2024-001)." - }, - "initiativeId": { - "type": "string", - "description": "Reference to the initiative being gated." - }, - "adoptionLevel": { - "type": "string", - "description": "Required adoption level for this gate (e.g., Level 3+)." - }, - "checks": { - "type": "array", - "items": { - "type": "object", - "required": ["category", "criterion", "status", "evidence", "notes"], - "properties": { - "category": { - "type": "string", - "description": "Gate check category (e.g., Problem & Value, Stakeholders)." - }, - "criterion": { - "type": "string", - "description": "The specific criterion being evaluated." - }, - "status": { - "type": "string", - "enum": ["Pass", "Fail", "Waiver"], - "description": "Result of the check." - }, - "evidence": { - "type": "string", - "description": "Link or reference to supporting evidence." - }, - "notes": { - "type": "string", - "description": "Additional notes or context for this check." - } - } - }, - "description": "Array of gate checks organized by category." - }, - "decision": { - "type": "string", - "enum": ["PASS", "CONDITIONAL", "FAIL"], - "description": "Overall gate decision." - }, - "waivers": { - "type": "array", - "items": { - "type": "object", - "required": ["checkNumber", "rationale", "approvedBy", "expiryDate"], - "properties": { - "checkNumber": { - "type": "integer", - "description": "The check number being waived." - }, - "rationale": { - "type": "string", - "description": "Justification for the waiver." - }, - "approvedBy": { - "type": "string", - "description": "Person who approved the waiver." - }, - "expiryDate": { - "type": "string", - "format": "date", - "description": "When the waiver expires (ISO 8601)." - } - } - }, - "description": "Waivers for failed checks that are accepted with justification." - }, - "decidedAt": { - "type": "string", - "format": "date-time", - "description": "Timestamp when the gate decision was made (ISO 8601)." - }, - "decidedBy": { - "type": "string", - "description": "Person or role who made the gate decision." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "DRG-2024-001", - "gateId": "DRG-2024-001", - "initiativeId": "INIT-ONBOARD-2024", - "adoptionLevel": "Level 3+", - "checks": [ - { "category": "Problem & Value", "criterion": "Problem statement is specific and measurable", "status": "Pass", "evidence": "KB-2024-001 §1", "notes": "" }, - { "category": "Problem & Value", "criterion": "Value proposition includes quantifiable metrics", "status": "Pass", "evidence": "KB-2024-001 §2", "notes": "60% reduction target defined" }, - { "category": "Problem & Value", "criterion": "Business trigger and sponsor are identified", "status": "Pass", "evidence": "KB-2024-001 §3", "notes": "" }, - { "category": "Capabilities", "criterion": "At least one epic candidate has Priority = Must", "status": "Pass", "evidence": "ECM-2024-001", "notes": "EC-001 and EC-002 are Must" }, - { "category": "Capabilities", "criterion": "Epic sizes are estimated", "status": "Pass", "evidence": "ECM-2024-001", "notes": "No XL epics" }, - { "category": "Traceability", "criterion": "Every epic traces to a Capability ID", "status": "Pass", "evidence": "ECM-2024-001", "notes": "" }, - { "category": "Risks & Assumptions", "criterion": "No critical assumptions remain unvalidated", "status": "Waiver", "evidence": "AQ-LOG-2024-001", "notes": "AQ-002 deferred to Q2 with sponsor approval" } - ], - "decision": "CONDITIONAL", - "waivers": [ - { "checkNumber": 13, "rationale": "Identity provider selection deferred to Q2; sponsor approved waiver", "approvedBy": "VP of Customer Experience", "expiryDate": "2024-06-30" } - ], - "decidedAt": "2024-01-25T14:00:00Z", - "decidedBy": "Maria Lopez, Product Owner" -} -``` - ---- - -## 4. Handoff to Next Artifact - -A **PASS** or **CONDITIONAL** decision on the **Discovery Readiness Gate** enables: - -1. **Backlog Refinement** — story seeds at K2+ enter refinement sessions for sprint planning. -2. **Design Baseline** — architecture and UX design can proceed with validated constraints. -3. **Technical Feasibility** — validated assumptions inform NFR targets and constraint validation. - -A **FAIL** decision sends the initiative back to Discovery for additional research or scope adjustment. - ---- - -## Quality Checklist - -- [ ] All 18 checks are evaluated (no check left blank) -- [ ] Every Fail has either a remediation plan or a documented waiver -- [ ] Waivers have sponsor approval and expiry dates -- [ ] Evidence links resolve to actual artifacts -- [ ] Decision rationale is documented and traceable -- [ ] Gate is reviewed by at least Product Owner and one technical lead -- [ ] Language is consistent (no mixed EN/ES within the file) -- [ ] Document is stored in version control alongside relevant code or design artifacts - ---- - -## Recommended Adoption Level - -**Mandatory** for all initiatives at Level 3+ adoption. The Discovery Readiness Gate is the formal checkpoint before transitioning from Discovery to Design and Backlog phases. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| Check evidence becomes outdated | Re-evaluate the check with updated evidence | -| Waiver expires | Re-evaluate the check or renew the waiver with sponsor approval | -| New risk or assumption surfaces | Add to relevant check category; re-evaluate gate decision | -| Decision changes (e.g., CONDITIONAL to PASS) | Update decision field, record rationale, notify stakeholders | -| Initiative scope changes materially | Re-run full gate evaluation | -| Quarterly review | Verify gate decision remains valid; close if initiative is dormant | diff --git a/reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.es.md b/reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.es.md deleted file mode 100644 index b2f74f3e..00000000 --- a/reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.es.md +++ /dev/null @@ -1,227 +0,0 @@ -# Plantilla: Epic Candidate Matrix - -> **Navegación Bilingüe:** [English Version](./epic-candidate-matrix-template.md) -> **Propósito:** Mapea capacidades a candidatos de épica con prioridad, dependencias y trazabilidad. Puente entre conocimiento y planificación de entrega. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Product Owner / Business Analyst -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Knowledge Brief aprobado, Registro de Supuestos y Preguntas validado, Mapa de Capacidades. -* **Salidas Esperadas:** Epic Candidate Matrix que alimenta el Story Seed Bank y el Discovery Readiness Gate. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Epic Candidate, Capability, Priority, Dependency, Risk). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Epic Candidate Matrix: [Nombre de la Iniciativa] - -## 1. Candidatos de Épica - -| ID Candidato de Épica | Nombre | Derivado De (ID de Capacidad) | Descripción | Prioridad (MoSCoW) | Tamaño Estimado | Dependencias | Riesgos | Supuestos | Listo para Backlog | -|---|---|---|---|---|---|---|---|---|---| -| EC-001 | [Nombre de la Épica] | CAP-001 | [Descripción breve de lo que entrega esta épica] | Must | L | — | [Riesgo 1] | [Supuesto 1] | Sí | -| EC-002 | [Nombre de la Épica] | CAP-002 | [Descripción breve de lo que entrega esta épica] | Should | M | EC-001 | [Riesgo 2] | [Supuesto 2] | No | -| EC-003 | [Nombre de la Épica] | CAP-003 | [Descripción breve de lo que entrega esta épica] | Could | S | — | — | [Supuesto 3] | Sí | - -## 2. Resumen - -| Métrica | Cantidad | -|---|---| -| Total de candidatos de épica | 3 | -| Listos para Backlog | 2 | -| Bloqueados / No listos | 1 | -| Must | 1 | -| Should | 1 | -| Could | 1 | -| Won't (este ciclo) | 0 | - -## 3. Notas de Uso - -- Cada candidato de épica debe trazar a una capacidad del Mapa de Capacidades. -- Las dependencias con otras épicas deben ser explícitas; no se permiten dependencias circulares. -- La prioridad sigue MoSCoW: Must, Should, Could, Won't. Al menos una épica Must es requerida para que una iniciativa avance. -- El Tamaño Estimado usa tallas de camiseta: S (1-2 sprints), M (3-4 sprints), L (5-8 sprints), XL (8+ sprints, considerar dividir). -- "Listo para Backlog = Sí" requiere que todos los supuestos estén validados y no haya dependencias bloqueantes. -- Los riesgos y supuestos se copian del Knowledge Brief y el Registro de Supuestos y Preguntas cuando son relevantes. -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith y herramientas automáticas de scaffolding. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Epic Candidate Matrix", - "type": "object", - "required": ["id", "epicCandidates"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de este Epic Candidate Matrix." - }, - "epicCandidates": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "capabilityId", "description", "priority", "estimatedSize", "dependencies", "risks", "assumptions", "readyForBacklog"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único del candidato de épica (ej., EC-001)." - }, - "name": { - "type": "string", - "description": "Nombre descriptivo corto de la épica." - }, - "capabilityId": { - "type": "string", - "description": "Referencia a la capacidad del Mapa de Capacidades." - }, - "description": { - "type": "string", - "description": "Lo que esta épica entrega al producto." - }, - "priority": { - "type": "string", - "enum": ["Must", "Should", "Could", "Won't"], - "description": "Nivel de prioridad MoSCoW." - }, - "estimatedSize": { - "type": "string", - "enum": ["S", "M", "L", "XL"], - "description": "Estimación de tamaño en talla de camiseta." - }, - "dependencies": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs de otros candidatos de épica de los que depende esta épica." - }, - "risks": { - "type": "array", - "items": { "type": "string" }, - "description": "Riesgos heredados del Knowledge Brief o el Registro de Supuestos." - }, - "assumptions": { - "type": "array", - "items": { "type": "string" }, - "description": "Supuestos que deben cumplirse para que esta épica avance." - }, - "readyForBacklog": { - "type": "boolean", - "description": "Si este candidato de épica está listo para agregar al backlog del producto." - } - } - }, - "description": "Array de candidatos de épicas derivados de capacidades." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "ECM-2024-001", - "epicCandidates": [ - { - "id": "EC-001", - "name": "Motor de Verificación de Identidad", - "capabilityId": "CAP-001", - "description": "Implementar verificación de identidad automatizada con escaneo de documentos y detección de viveza.", - "priority": "Must", - "estimatedSize": "L", - "dependencies": [], - "risks": ["SLA del proveedor de identidad por debajo del 99.9%"], - "assumptions": ["Requisitos KYC/AML estables por 12 meses"], - "readyForBacklog": true - }, - { - "id": "EC-002", - "name": "Orquestación del Onboarding", - "capabilityId": "CAP-002", - "description": "Construir la capa de orquestación que secuencia los pasos de verificación y maneja reintentos.", - "priority": "Must", - "estimatedSize": "M", - "dependencies": ["EC-001"], - "risks": ["Retrasos en aprobación regulatoria para el nuevo flujo de verificación"], - "assumptions": ["El bus de eventos existente puede absorber los eventos del dominio de onboarding"], - "readyForBacklog": false - }, - { - "id": "EC-003", - "name": "Integración de Canal de Socios", - "capabilityId": "CAP-003", - "description": "Exponer la API de onboarding para integraciones de canal de socios con limitación de tasa y gestión de SLA.", - "priority": "Should", - "estimatedSize": "M", - "dependencies": ["EC-001", "EC-002"], - "risks": ["Cambios en contratos de API de socios"], - "assumptions": ["Requisitos de integración con socios finalizados para Q2"], - "readyForBacklog": false - } - ] -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -Una vez validado, el **Epic Candidate Matrix** alimenta directamente: - -1. **Story Seed Bank** — cada candidato de épica genera una o más semillas de historia para refinamiento del backlog. -2. **Discovery Readiness Gate** — el estado "Listo para Backlog" es un input de verificación del gate. -3. **Factibilidad Técnica** — épicas de tamaño XL pueden requerir evaluación de factibilidad antes de dividir. - -Los candidatos de épica marcados "Listo para Backlog = No" permanecen en la matriz hasta que se resuelvan las condiciones bloqueantes. - ---- - -## Quality Checklist - -- [ ] Cada candidato de épica traza a un ID de Capacidad del Mapa de Capacidades -- [ ] La prioridad sigue MoSCoW sin duplicados (cada épica tiene exactamente una prioridad) -- [ ] Las dependencias referencian IDs válidos de candidatos de épica (sin dependencias circulares) -- [ ] Al menos una épica tiene Prioridad = Must -- [ ] Ninguna épica está marcada Listo para Backlog si tiene dependencias no resueltas -- [ ] Las estimaciones de tamaño usan S/M/L/XL consistentemente (sin tama texto libre) -- [ ] Los riesgos y supuestos son trazables al Knowledge Brief o al Registro de Supuestos -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) -- [ ] El documento está almacenado en control de versiones junto con el código o artefactos de diseño relevantes - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas que ingresan a Discovery. El Epic Candidate Matrix es el puente entre la descomposición de capacidades y la planificación de entrega, y es el prerrequisito para el Story Seed Bank. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| Nueva capacidad identificada en el Mapa de Capacidades | Agregar como nuevo candidato de épica con prioridad por defecto Could | -| Dependencia resuelta o nueva dependencia descubierta | Actualizar columna de dependencias y reevaluar Listo para Backlog | -| Riesgo materializado o nuevo riesgo emergente | Actualizar columna de riesgos para épicas afectadas | -| Supuesto validado o invalidado | Actualizar columna de supuestos; recalcular Listo para Backlog | -| Cambio en la estimación de tamaño de la épica | Actualizar tamaño estimado; dividir épicas XL si es necesario | -| Repriorización de prioridad | Actualizar prioridad; asegurar que al menos una épica Must permanezca | -| Revisión trimestral | Revisión completa de la matriz; eliminar candidatos de épica inactivos o degradar a Won't | diff --git a/reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.md b/reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.md deleted file mode 100644 index 578ebafc..00000000 --- a/reference/core/sdlc/04-artifact-templates/epic-candidate-matrix-template.md +++ /dev/null @@ -1,227 +0,0 @@ -# Template: Epic Candidate Matrix - -> **Bilingual Navigation:** [Versión en Español](./epic-candidate-matrix-template.es.md) -> **Purpose:** Maps capabilities to epic candidates with priority, dependencies, and traceability. Bridges knowledge to delivery planning. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Product Owner / Business Analyst -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Approved Discovery Knowledge Brief, validated Assumptions & Questions Log, Capability Map. -* **Expected outputs:** Epic Candidate Matrix that feeds the Story Seed Bank and Discovery Readiness Gate. -* **Applied taxonomy:** Aligned with Evolith glossary (Epic Candidate, Capability, Priority, Dependency, Risk). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Epic Candidate Matrix: [Initiative Name] - -## 1. Epic Candidates - -| Epic Candidate ID | Name | Derived From (Capability ID) | Description | Priority (MoSCoW) | Estimated Size | Dependencies | Risks | Assumptions | Ready for Backlog | -|---|---|---|---|---|---|---|---|---|---| -| EC-001 | [Epic Name] | CAP-001 | [Brief description of what this epic delivers] | Must | L | — | [Risk 1] | [Assumption 1] | Yes | -| EC-002 | [Epic Name] | CAP-002 | [Brief description of what this epic delivers] | Should | M | EC-001 | [Risk 2] | [Assumption 2] | No | -| EC-003 | [Epic Name] | CAP-003 | [Brief description of what this epic delivers] | Could | S | — | — | [Assumption 3] | Yes | - -## 2. Summary - -| Metric | Count | -|---|---| -| Total epic candidates | 3 | -| Ready for Backlog | 2 | -| Blocked / Not Ready | 1 | -| Must | 1 | -| Should | 1 | -| Could | 1 | -| Won't (this cycle) | 0 | - -## 3. Usage Notes - -- Each epic candidate must trace back to a capability from the Capability Map. -- Dependencies on other epics must be explicit; circular dependencies are not allowed. -- Priority follows MoSCoW: Must, Should, Could, Won't. At least one Must epic is required for an initiative to proceed. -- Estimated Size uses T-shirt sizing: S (1-2 sprints), M (3-4 sprints), L (5-8 sprints), XL (8+ sprints, consider splitting). -- "Ready for Backlog = Yes" requires all assumptions validated and no blocking dependencies. -- Risks and assumptions are copied from the Knowledge Brief and Assumptions & Questions Log where relevant. -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI and automated scaffolding tools. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Epic Candidate Matrix", - "type": "object", - "required": ["id", "epicCandidates"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this Epic Candidate Matrix." - }, - "epicCandidates": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "capabilityId", "description", "priority", "estimatedSize", "dependencies", "risks", "assumptions", "readyForBacklog"], - "properties": { - "id": { - "type": "string", - "description": "Unique epic candidate identifier (e.g., EC-001)." - }, - "name": { - "type": "string", - "description": "Short descriptive name for the epic." - }, - "capabilityId": { - "type": "string", - "description": "Reference to the capability from the Capability Map." - }, - "description": { - "type": "string", - "description": "What this epic delivers to the product." - }, - "priority": { - "type": "string", - "enum": ["Must", "Should", "Could", "Won't"], - "description": "MoSCoW priority level." - }, - "estimatedSize": { - "type": "string", - "enum": ["S", "M", "L", "XL"], - "description": "T-shirt size estimate." - }, - "dependencies": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs of other epic candidates this epic depends on." - }, - "risks": { - "type": "array", - "items": { "type": "string" }, - "description": "Risks inherited from the Knowledge Brief or Assumptions Log." - }, - "assumptions": { - "type": "array", - "items": { "type": "string" }, - "description": "Assumptions that must hold for this epic to proceed." - }, - "readyForBacklog": { - "type": "boolean", - "description": "Whether this epic is ready to be added to the product backlog." - } - } - }, - "description": "Array of epic candidates derived from capabilities." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "ECM-2024-001", - "epicCandidates": [ - { - "id": "EC-001", - "name": "Identity Verification Engine", - "capabilityId": "CAP-001", - "description": "Implement automated identity verification with document scanning and liveness detection.", - "priority": "Must", - "estimatedSize": "L", - "dependencies": [], - "risks": ["Identity provider SLA below 99.9%"], - "assumptions": ["KYC/AML requirements stable for 12 months"], - "readyForBacklog": true - }, - { - "id": "EC-002", - "name": "Onboarding Orchestration", - "capabilityId": "CAP-002", - "description": "Build the orchestration layer that sequences verification steps and handles retries.", - "priority": "Must", - "estimatedSize": "M", - "dependencies": ["EC-001"], - "risks": ["Regulatory approval delays for new verification flow"], - "assumptions": ["Existing event bus can absorb onboarding domain events"], - "readyForBacklog": false - }, - { - "id": "EC-003", - "name": "Partner Channel Integration", - "capabilityId": "CAP-003", - "description": "Expose onboarding API for partner-channel integrations with rate limiting and SLA management.", - "priority": "Should", - "estimatedSize": "M", - "dependencies": ["EC-001", "EC-002"], - "risks": ["Partner API contract changes"], - "assumptions": ["Partner integration requirements finalized by Q2"], - "readyForBacklog": false - } - ] -} -``` - ---- - -## 4. Handoff to Next Artifact - -Once validated, the **Epic Candidate Matrix** feeds directly into: - -1. **Story Seed Bank** — each epic candidate generates one or more story seeds for backlog refinement. -2. **Discovery Readiness Gate** — "Ready for Backlog" status is a gate check input. -3. **Technical Feasibility** — XL-sized epics may require feasibility assessment before splitting. - -Epic candidates marked "Ready for Backlog = No" remain in the matrix until blocking conditions are resolved. - ---- - -## Quality Checklist - -- [ ] Every epic candidate traces to a Capability ID from the Capability Map -- [ ] Priority follows MoSCoW without duplicates (each epic has exactly one priority) -- [ ] Dependencies reference valid epic candidate IDs (no circular dependencies) -- [ ] At least one epic has Priority = Must -- [ ] No epic is marked Ready for Backlog if it has unresolved dependencies -- [ ] Size estimates use S/M/L/XL consistently (no free-text sizes) -- [ ] Risks and assumptions are traceable to the Knowledge Brief or Assumptions Log -- [ ] Language is consistent (no mixed EN/ES within the file) -- [ ] Document is stored in version control alongside relevant code or design artifacts - ---- - -## Recommended Adoption Level - -**Mandatory** for all initiatives entering Discovery. The Epic Candidate Matrix bridges capability decomposition to delivery planning and is the prerequisite for the Story Seed Bank. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| New capability identified in Capability Map | Add as new epic candidate with default priority Could | -| Dependency resolved or new dependency discovered | Update dependencies column and re-evaluate Ready for Backlog | -| Risk materializes or new risk emerges | Update risks column for affected epics | -| Assumption validated or invalidated | Update assumptions column; recalculate Ready for Backlog | -| Epic size estimate changes | Update estimated size; split XL epics if needed | -| Priority reprioritized | Update priority; ensure at least one Must epic remains | -| Quarterly review | Full matrix review; drop dormant epic candidates or demote to Won't | diff --git a/reference/core/sdlc/04-artifact-templates/story-seed-bank-template.es.md b/reference/core/sdlc/04-artifact-templates/story-seed-bank-template.es.md deleted file mode 100644 index 3d9ba8ff..00000000 --- a/reference/core/sdlc/04-artifact-templates/story-seed-bank-template.es.md +++ /dev/null @@ -1,230 +0,0 @@ -# Plantilla: Story Seed Bank - -> **Navegación Bilingüe:** [English Version](./story-seed-bank-template.md) -> **Propósito:** Semillas mínimas de historia antes del refinamiento completo del backlog. Cada semilla captura suficiente contexto para una futura historia sin ser una historia de usuario completa. -> -> **Fase SDLC:** 01 - Discovery / Ideación -> -> **Subfase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Responsable sugerido:** Product Owner / Business Analyst -> -> **Quality Gate:** Aprobación del Knowledge Brief - -## Metadatos del Artefacto - -* **URL Upstream Evolith:** `En construcción - Solicitar a Upstream` -* **Entradas Requeridas:** Epic Candidate Matrix aprobado, Registro de Supuestos y Preguntas validado. -* **Salidas Esperadas:** Story Seed Bank que alimenta el Discovery Readiness Gate y el futuro refinamiento del backlog. -* **Taxonomía Aplicada:** Alineado con el glosario Evolith (Story Seed, Epic Candidate, Knowledge Level, Acceptance Criteria). -* **Rules Evolith Aplicables:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Estructura Documental (Markdown) - -```markdown -# Story Seed Bank: [Nombre de la Iniciativa] - -## 1. Semillas de Historia - -| ID Semilla de Historia | Nombre | Derivado De (ID Candidato de Épica) | Rol de Usuario | Comportamiento Deseado | Criterios de Aceptación (Borrador) | Nivel de Conocimiento | Bloqueado Por | -|---|---|---|---|---|---|---|---| -| SS-001 | [Nombre de la Semilla] | EC-001 | [Rol] | [Lo que el usuario quiere hacer] | [CA 1] / [CA 2] | K2 | — | -| SS-002 | [Nombre de la Semilla] | EC-001 | [Rol] | [Lo que el usuario quiere hacer] | [CA 1] | K1 | SS-001 | -| SS-003 | [Nombre de la Semilla] | EC-002 | [Rol] | [Lo que el usuario quiere hacer] | [CA 1] / [CA 2] / [CA 3] | K3 | — | - -## 2. Resumen - -| Métrica | Cantidad | -|---|---| -| Total de semillas de historia | 3 | -| Listas para refinamiento | 2 | -| Bloqueadas | 1 | -| Nivel de Conocimiento K0-K1 | 1 | -| Nivel de Conocimiento K2-K3 | 2 | -| Nivel de Conocimiento K4 | 0 | - -## 3. Referencia de Niveles de Conocimiento - -| Nivel | Etiqueta | Descripción | -|---|---|---| -| K0 | Desconocido | El problema aún no se entiende; la semilla es una hipótesis | -| K1 | Conocido | El problema reconocido pero el enfoque de solución no está claro | -| K2 | Definido | El problema y el enfoque de solución definidos pero no validados | -| K3 | Validado | El enfoque de solución validado mediante investigación o prototipo | -| K4 | Comprobado | La solución implementada y validada en contexto de producción | - -## 4. Notas de Uso - -- Las semillas de historia NO son historias de usuario completas. Capturan contexto mínimo para refinamiento futuro. -- Cada semilla debe trazar a un ID de Candidato de Épica del Epic Candidate Matrix. -- El Nivel de Conocimiento indica la madurez del descubrimiento: semillas K0-K1 necesitan investigación antes del refinamiento; semillas K3-K4 están listas para refinamiento. -- "Bloqueado Por" referencia otros IDs de Semilla de Historia que deben completarse o refinarse primero. -- Los criterios de aceptación son borradores — se expandirán durante el refinamiento del backlog. -- Las semillas a nivel K4 pueden promoverse directamente a historias de usuario completas. -``` - ---- - -## 2. Estructura de Datos (JSON) - -Para integración con el CLI de Evolith y herramientas automáticas de scaffolding. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Story Seed Bank", - "type": "object", - "required": ["id", "storySeeds"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de este Story Seed Bank." - }, - "storySeeds": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "epicCandidateId", "userRole", "desiredBehavior", "acceptanceCriteria", "knowledgeLevel", "blockedBy"], - "properties": { - "id": { - "type": "string", - "description": "Identificador único de la semilla de historia (ej., SS-001)." - }, - "name": { - "type": "string", - "description": "Nombre descriptivo corto de la semilla." - }, - "epicCandidateId": { - "type": "string", - "description": "Referencia al candidato de épica del Epic Candidate Matrix." - }, - "userRole": { - "type": "string", - "description": "El rol de usuario que se beneficiaría de esta historia." - }, - "desiredBehavior": { - "type": "string", - "description": "Lo que el usuario quiere lograr (en lenguaje claro)." - }, - "acceptanceCriteria": { - "type": "array", - "items": { "type": "string" }, - "description": "Criterios de aceptación borrador para ser refinados durante el refinamiento del backlog." - }, - "knowledgeLevel": { - "type": "string", - "enum": ["K0", "K1", "K2", "K3", "K4"], - "description": "Nivel de madurez del descubrimiento de esta semilla." - }, - "blockedBy": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs de semillas de historia que bloquean esta semilla." - } - } - }, - "description": "Array de semillas mínimas de historia para refinamiento futuro." - } - } -} -``` - ---- - -## 3. Ejemplo Mínimo Aplicado - -```json -{ - "id": "SSB-2024-001", - "storySeeds": [ - { - "id": "SS-001", - "name": "Subir documento de identidad", - "epicCandidateId": "EC-001", - "userRole": "Cliente Nuevo", - "desiredBehavior": "Subir un documento de identidad gubernamental para verificación", - "acceptanceCriteria": [ - "El cliente puede subir JPG, PNG o PDF de hasta 10MB", - "El sistema valida que el documento no esté vencido", - "El sistema confirma la carga y muestra el estado de procesamiento" - ], - "knowledgeLevel": "K2", - "blockedBy": [] - }, - { - "id": "SS-002", - "name": "Verificación de viveza durante el onboarding", - "epicCandidateId": "EC-001", - "userRole": "Cliente Nuevo", - "desiredBehavior": "Completar una verificación de viveza para demostrar que es una persona real", - "acceptanceCriteria": [ - "El cliente es guiado a través de la captura de selfie con indicaciones en pantalla", - "El sistema detecta y rechaza fotos o reproducciones de video" - ], - "knowledgeLevel": "K1", - "blockedBy": ["SS-001"] - }, - { - "id": "SS-003", - "name": "Recibir notificación del resultado de verificación", - "epicCandidateId": "EC-002", - "userRole": "Cliente Nuevo", - "desiredBehavior": "Recibir una notificación cuando la verificación de identidad esté completa", - "acceptanceCriteria": [ - "El cliente recibe notificación por correo electrónico dentro de 5 minutos de la completación de la verificación", - "La notificación incluye el estado de verificación (aprobado / rechazado / revisión manual)", - "El cliente puede acceder al resultado detallado en la aplicación" - ], - "knowledgeLevel": "K3", - "blockedBy": [] - } - ] -} -``` - ---- - -## 4. Handoff hacia la Siguiente Fase - -El **Story Seed Bank** alimenta directamente: - -1. **Discovery Readiness Gate** — el conteo de semillas K0-K1 es un input de verificación del gate (un conteo alto puede indicar descubrimiento insuficiente). -2. **Refinamiento del Backlog** — las semillas K2-K4 se refinan en historias de usuario completas durante la planificación del sprint. -3. **Factibilidad Técnica** — las semillas K0-K1 con incertidumbre técnica pueden requerir evaluación de factibilidad antes del refinamiento. - -Las semillas a nivel **K4** pueden evitar el refinamiento y promoverse directamente al backlog del producto. - ---- - -## Quality Checklist - -- [ ] Cada semilla de historia traza a un ID de Candidato de Épica del Epic Candidate Matrix -- [ ] Cada semilla tiene un rol de usuario claro y comportamiento deseado -- [ ] Los criterios de aceptación están presentes (aunque en calidad de borrador) -- [ ] El Nivel de Conocimiento está asignado consistentemente (K0-K4) -- [ ] "Bloqueado Por" referencia IDs válidos de Semilla de Historia (sin bloques circulares) -- [ ] Al menos el 50% de las semillas son K2 o superiores (indica progreso suficiente del descubrimiento) -- [ ] Ninguna semilla está marcada K4 sin evidencia de validación en producción -- [ ] El lenguaje es consistente (sin mezcla de EN/ES dentro del archivo) -- [ ] El documento está almacenado en control de versiones junto con el código o artefactos de diseño relevantes - ---- - -## Nivel de Adopción Recomendado - -**Obligatorio** para todas las iniciativas que tienen un Epic Candidate Matrix aprobado. El Story Seed Bank captura la intención temprana de entrega y es el prerrequisito para el Discovery Readiness Gate. - ---- - -## Criterios de Actualización - -| Disparador | Acción | -|---|---| -| Nuevo candidato de épica agregado a la matriz | Generar semillas de historia para la nueva épica | -| Nivel de conocimiento avanza (ej., K1 a K2) | Actualizar nivel de conocimiento; refinar criterios de aceptación si es posible | -| Semilla de historia se bloquea | Actualizar Bloqueado Por; reevaluar si la semilla debe diferirse | -| Bloqueo resuelto | Eliminar de Bloqueado Por; reasignar nivel de conocimiento | -| Semilla validada en producción | Promover a K4; considerar promoción directa a historia de usuario | -| Revisión trimestral | Eliminar semillas de épicas inactivas; consolidar semillas superpuestas | diff --git a/reference/core/sdlc/04-artifact-templates/story-seed-bank-template.md b/reference/core/sdlc/04-artifact-templates/story-seed-bank-template.md deleted file mode 100644 index 2c545bd4..00000000 --- a/reference/core/sdlc/04-artifact-templates/story-seed-bank-template.md +++ /dev/null @@ -1,230 +0,0 @@ -# Template: Story Seed Bank - -> **Bilingual Navigation:** [Versión en Español](./story-seed-bank-template.es.md) -> **Purpose:** Minimal story seeds before full backlog refinement. Each seed captures enough context for a future story without being a complete user story. -> -> **SDLC Phase:** 01 - Discovery / Ideation -> -> **Subphase:** 01.1 - Knowledge-First Discovery / KDD Readiness -> -> **Suggested responsible:** Product Owner / Business Analyst -> -> **Quality Gate:** Knowledge Brief Approval - -## Metadata - -* **Upstream Evolith URL:** `Under construction - Request from Upstream` -* **Required inputs:** Approved Epic Candidate Matrix, validated Assumptions & Questions Log. -* **Expected outputs:** Story Seed Bank that feeds the Discovery Readiness Gate and future backlog refinement. -* **Applied taxonomy:** Aligned with Evolith glossary (Story Seed, Epic Candidate, Knowledge Level, Acceptance Criteria). -* **Applicable Evolith Rules:** R-03 (UTF-8 Clean), R-09 (Readability), R-13 (Functional Structure). - ---- - -## 1. Document Structure (Markdown) - -```markdown -# Story Seed Bank: [Initiative Name] - -## 1. Story Seeds - -| Story Seed ID | Name | Derived From (Epic Candidate ID) | User Role | Desired Behavior | Acceptance Criteria (Draft) | Knowledge Level | Blocked By | -|---|---|---|---|---|---|---|---| -| SS-001 | [Seed Name] | EC-001 | [Role] | [What the user wants to do] | [AC 1] / [AC 2] | K2 | — | -| SS-002 | [Seed Name] | EC-001 | [Role] | [What the user wants to do] | [AC 1] | K1 | SS-001 | -| SS-003 | [Seed Name] | EC-002 | [Role] | [What the user wants to do] | [AC 1] / [AC 2] / [AC 3] | K3 | — | - -## 2. Summary - -| Metric | Count | -|---|---| -| Total story seeds | 3 | -| Ready for refinement | 2 | -| Blocked | 1 | -| Knowledge Level K0-K1 | 1 | -| Knowledge Level K2-K3 | 2 | -| Knowledge Level K4 | 0 | - -## 3. Knowledge Levels Reference - -| Level | Label | Description | -|---|---|---| -| K0 | Unaware | Problem not yet understood; seed is a hypothesis | -| K1 | Aware | Problem acknowledged but solution approach unclear | -| K2 | Defined | Problem and solution approach defined but not validated | -| K3 | Validated | Solution approach validated through research or prototype | -| K4 | Proven | Solution implemented and validated in production context | - -## 4. Usage Notes - -- Story seeds are NOT complete user stories. They capture minimal context for future refinement. -- Each seed must trace to an Epic Candidate ID from the Epic Candidate Matrix. -- Knowledge Level indicates discovery maturity: K0-K1 seeds need research before refinement; K3-K4 seeds are refinement-ready. -- "Blocked By" references other Story Seed IDs that must be completed or refined first. -- Acceptance criteria are drafts — they will be expanded during backlog refinement. -- Seeds at K4 level may be promoted directly to complete user stories. -``` - ---- - -## 2. Data Structure (JSON) - -For integration with the Evolith CLI and automated scaffolding tools. - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Story Seed Bank", - "type": "object", - "required": ["id", "storySeeds"], - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for this Story Seed Bank." - }, - "storySeeds": { - "type": "array", - "items": { - "type": "object", - "required": ["id", "name", "epicCandidateId", "userRole", "desiredBehavior", "acceptanceCriteria", "knowledgeLevel", "blockedBy"], - "properties": { - "id": { - "type": "string", - "description": "Unique story seed identifier (e.g., SS-001)." - }, - "name": { - "type": "string", - "description": "Short descriptive name for the seed." - }, - "epicCandidateId": { - "type": "string", - "description": "Reference to the epic candidate from the Epic Candidate Matrix." - }, - "userRole": { - "type": "string", - "description": "The user role that would benefit from this story." - }, - "desiredBehavior": { - "type": "string", - "description": "What the user wants to achieve (in plain language)." - }, - "acceptanceCriteria": { - "type": "array", - "items": { "type": "string" }, - "description": "Draft acceptance criteria to be refined during backlog refinement." - }, - "knowledgeLevel": { - "type": "string", - "enum": ["K0", "K1", "K2", "K3", "K4"], - "description": "Discovery maturity level of this seed." - }, - "blockedBy": { - "type": "array", - "items": { "type": "string" }, - "description": "IDs of story seeds that block this seed." - } - } - }, - "description": "Array of minimal story seeds for future refinement." - } - } -} -``` - ---- - -## 3. Minimum Applied Example - -```json -{ - "id": "SSB-2024-001", - "storySeeds": [ - { - "id": "SS-001", - "name": "Upload identity document", - "epicCandidateId": "EC-001", - "userRole": "New Customer", - "desiredBehavior": "Upload a government-issued ID document for verification", - "acceptanceCriteria": [ - "Customer can upload JPG, PNG, or PDF up to 10MB", - "System validates document is not expired", - "System confirms upload and shows processing status" - ], - "knowledgeLevel": "K2", - "blockedBy": [] - }, - { - "id": "SS-002", - "name": "Liveness check during onboarding", - "epicCandidateId": "EC-001", - "userRole": "New Customer", - "desiredBehavior": "Complete a liveness check to prove they are a real person", - "acceptanceCriteria": [ - "Customer is guided through selfie capture with on-screen prompts", - "System detects and rejects photos or video replays" - ], - "knowledgeLevel": "K1", - "blockedBy": ["SS-001"] - }, - { - "id": "SS-003", - "name": "Receive verification result notification", - "epicCandidateId": "EC-002", - "userRole": "New Customer", - "desiredBehavior": "Receive a notification when identity verification is complete", - "acceptanceCriteria": [ - "Customer receives email notification within 5 minutes of verification completion", - "Notification includes verification status (approved / rejected / manual review)", - "Customer can access detailed result in the app" - ], - "knowledgeLevel": "K3", - "blockedBy": [] - } - ] -} -``` - ---- - -## 4. Handoff to Next Artifact - -The **Story Seed Bank** feeds directly into: - -1. **Discovery Readiness Gate** — count of K0-K1 seeds is a gate check input (high count may indicate insufficient discovery). -2. **Backlog Refinement** — K2-K4 seeds are refined into complete user stories during sprint planning. -3. **Technical Feasibility** — K0-K1 seeds with technical uncertainty may require feasibility assessment before refinement. - -Seeds at **K4** level may bypass refinement and be promoted directly to the product backlog. - ---- - -## Quality Checklist - -- [ ] Every story seed traces to an Epic Candidate ID from the Epic Candidate Matrix -- [ ] Each seed has a clear user role and desired behavior -- [ ] Acceptance criteria are present (even if draft quality) -- [ ] Knowledge Level is assigned consistently (K0-K4) -- [ ] "Blocked By" references valid Story Seed IDs (no circular blocks) -- [ ] At least 50% of seeds are K2 or above (indicates sufficient discovery progress) -- [ ] No seed is marked K4 without evidence of production validation -- [ ] Language is consistent (no mixed EN/ES within the file) -- [ ] Document is stored in version control alongside relevant code or design artifacts - ---- - -## Recommended Adoption Level - -**Mandatory** for all initiatives that have an approved Epic Candidate Matrix. The Story Seed Bank captures early delivery intent and is the prerequisite for the Discovery Readiness Gate. - ---- - -## Update Criteria - -| Trigger | Action | -|---|---| -| New epic candidate added to matrix | Generate story seeds for the new epic | -| Knowledge level advances (e.g., K1 to K2) | Update knowledge level; refine acceptance criteria if possible | -| Story seed becomes blocked | Update Blocked By; re-evaluate if the seed should be deferred | -| Block resolved | Remove from Blocked By; reassess knowledge level | -| Seed validated in production | Promote to K4; consider direct promotion to user story | -| Quarterly review | Drop seeds for dormant epics; consolidate overlapping seeds | diff --git a/reference/core/sdlc/sdlc-evolith-artifact-mapping.es.md b/reference/core/sdlc/sdlc-evolith-artifact-mapping.es.md index d7475b57..583b3212 100644 --- a/reference/core/sdlc/sdlc-evolith-artifact-mapping.es.md +++ b/reference/core/sdlc/sdlc-evolith-artifact-mapping.es.md @@ -88,11 +88,11 @@ flowchart LR | Artefacto | Ubicación | Por qué es requerido | |---|---|---| -| **Discovery Canvas** | [discovery-canvas-template.es.md](./04-artifact-templates/discovery-canvas-template.es.md) | Registro de iniciativa, dolor del cliente y valor esperado. En KDD Nivel 1+, informar este artefacto desde el Discovery Knowledge Brief. | +| **Discovery Canvas** | [discovery-canvas-template.es.md](./04-artifact-templates/discovery-canvas-template.es.md) | Registro de iniciativa, dolor del cliente y valor esperado. | | **Technical Feasibility Canvas** | [technical-feasibility-template.es.md](./04-artifact-templates/technical-feasibility-template.es.md) | Factibilidad técnica, cuotas de cloud y NFRs. | -| **Ballpark Estimation** | [ballpark-estimation-template.es.md](./04-artifact-templates/ballpark-estimation-template.es.md) | Estimación T-Shirt Sizing de esfuerzo y equipo. En KDD Nivel 2+, incorporar sizing del Story Seed Bank. | +| **Ballpark Estimation** | [ballpark-estimation-template.es.md](./04-artifact-templates/ballpark-estimation-template.es.md) | Estimación T-Shirt Sizing de esfuerzo y equipo. | | **PRD — Documento de Requisitos de Producto** | [prd-template.es.md](./04-artifact-templates/prd-template.es.md) | Captura alcance, personas, objetivos, restricciones, no-objetivos y evidencia de aprobación. | -| **Matriz de Priorización MoSCoW** | [plantilla MoSCoW](./04-artifact-templates/ballpark-estimation-template.es.md) | Análisis MoSCoW con al menos un ítem MUST. En KDD Nivel 2+, derivado de la Matriz de Candidatos a Épica. | +| **Matriz de Priorización MoSCoW** | [plantilla MoSCoW](./04-artifact-templates/ballpark-estimation-template.es.md) | Análisis MoSCoW con al menos un ítem MUST. | | **Análisis Build-versus-Compose** | [build-vs-compose.schema.json](../../../src/rulesets/schema/build-vs-compose.schema.json) | Disposición Adopt/Embed/Integrate/Extend/Build/Reject según Product Vision §5.3. | > **Baseline de Cumplimiento Evolith (§7):** Directivas Arquitectónicas, Taxonomía de Repositorio, Baseline Agnóstica, ADR-0047 y Manifiesto de Ingeniería son estándares transversales gobernados por la Compliance Baseline. Consúltese durante la Fase 1 pero no se producen aquí — ya están gobernados. @@ -106,18 +106,6 @@ flowchart LR | Estrategia de Comunicación Arquitectónica | [architecture-communication-strategy.md](../foundations/common-rules/communication/architecture-communication-strategy.md) | Al preparar briefings de arquitectura para stakeholders o ejecutivos. | | Modelo de Referencia UMS | [ums-reference-model.md](../../../product/research/demo/ums-reference-model.md) | Cuando el producto opera en identidad, access management o autorización multi-tenant. | -### Subfase 01.1 — Knowledge-First Discovery (Opcional) - -| Artefacto | Ubicación | Nivel | Cuándo usarlo | -|---|---|---|---| -| Discovery Knowledge Brief | [discovery-knowledge-brief-template.es.md](./04-artifact-templates/discovery-knowledge-brief-template.es.md) | 1+ | Cualquier iniciativa donde brechas de conocimiento puedan causar retrabajo | -| Log de Supuestos y Preguntas | [assumptions-questions-log-template.es.md](./04-artifact-templates/assumptions-questions-log-template.es.md) | 1+ | Cuando los supuestos necesitan seguimiento y validación | -| Discovery Context Pack | [discovery-context-pack-template.es.md](./04-artifact-templates/discovery-context-pack-template.es.md) | 1+ | Cuando agentes IA o repos satélite necesitan contexto exportable | -| Mapa de Capacidades | [capability-map-template.es.md](./04-artifact-templates/capability-map-template.es.md) | 2+ | Cuando se necesita descomposición del dominio antes de planificación de épicas | -| Matriz de Candidatos a Épica | [epic-candidate-matrix-template.es.md](./04-artifact-templates/epic-candidate-matrix-template.es.md) | 2+ | Cuando las capacidades deben rastrearse a candidatos de épica | -| Banco de Semillas de Historia | [story-seed-bank-template.es.md](./04-artifact-templates/story-seed-bank-template.es.md) | 2+ | Cuando se necesitan semillas mínimas de historia antes del refinamiento del backlog | -| Gate de Preparación de Discovery | [discovery-readiness-gate-template.es.md](./04-artifact-templates/discovery-readiness-gate-template.es.md) | 3+ | Cuando se requiere validación formal de suficiencia del conocimiento | - --- ## 3. Fase 2 — Diseño y Arquitectura @@ -137,7 +125,7 @@ flowchart LR | **ADR-0032 — Matriz de Selección de Protocolo** | [ADR-0032](../architecture/adrs/core/0032-api-protocol-decision-matrix-rest-grpc-graphql.es.md) | El uso de REST, gRPC y GraphQL debe resolverse antes de producir contratos API. | | **ADR-0056 — Convenciones de Naming y Diseño** | [ADR-0056](../architecture/adrs/core/0056-enterprise-naming-design-conventions.es.md) | El lenguaje ubicuo y las reglas de naming deben establecerse antes de nombrar entidades y endpoints. | | **ADR-0045 — Criterios de Readiness para Extracción** | [ADR-0045](../architecture/adrs/core/0045-microservice-extraction-readiness-criteria.es.md) | Requerido — los satélites que declaran F2 deben documentar su Extraction Readiness Score (≥70%). Enforcido por la regla de contrato satélite SVC-04. | -| **Historias Funcionales** | [functional-story-template.es.md](./04-artifact-templates/functional-story-template.es.md) | Historias listas para BDD en estado Ready, trazables al PRD. Usar Plantilla de Historia Funcional como formato y Estándar de Escritura como guía. Si existen Story Seeds de Fase 1.1 KDD Nivel 2+, refinarlas en Historias Funcionales aquí. | +| **Historias Funcionales** | [functional-story-template.es.md](./04-artifact-templates/functional-story-template.es.md) | Historias listas para BDD en estado Ready, trazables al PRD. Usar Plantilla de Historia Funcional como formato y Estándar de Escritura como guía. | | **Checklist de Simplicidad Fase 1** | [simplicity-checklist-phase-01.md](../architecture/blueprints/simplicity-checklist-phase-01.md) | A pesar del nombre 'Fase 1', este checklist se ejecuta en Fase 2. Su propósito: verificar que no entre sobre-ingeniería prematura en la baseline de diseño. El identificador del artefacto está registrado en el validador de máquina — no renombrar. | | **Análisis de Impacto CLI** | [cli-impact-analysis.es.md](./04-artifact-templates/cli-impact-analysis.es.md) | Capacidades CLI requeridas una vez que el diseño está baselined. | @@ -210,7 +198,7 @@ La Fase 2 implica una topología progresiva específica. Las siguientes acciones | 2 | Evaluar Extraction Readiness (ADR-0045 ≥70%); confirmar progresión ADR-0047 justificada | Score documentado | | 3 | Confirmar ADR-0002; ejecutar Checklist de Simplicidad Fase 1 | Baseline de arquitectura | | 4 | Producir Mapa de Bounded Contexts (Plantilla DDD); aplicar ADR-0031 + ADR-0032 | Mapa de Bounded Contexts | -| 5 | Refinar Story Seeds → Historias Funcionales (KDD L2+) o escribir desde cero | Historias Funcionales | +| 5 | Escribir Historias Funcionales a partir del alcance aprobado | Historias Funcionales | | 6 | Documentar decisiones de límites como ADRs; completar Análisis de Impacto CLI; consultar ADR-0018; verificar Alineación con Blueprint | Registro ADR (completo) | | 7 | Ejecutar `evolith validate --topology distributed-modules` — las 8 reglas DM deben pasar | Validación de topología | | 8 | (Condicional) Validar DOMA si topología F3 en roadmap (ADR-0076) | Cumplimiento DOMA | diff --git a/reference/core/sdlc/sdlc-evolith-artifact-mapping.md b/reference/core/sdlc/sdlc-evolith-artifact-mapping.md index 7b1b44e1..df8b9e8f 100644 --- a/reference/core/sdlc/sdlc-evolith-artifact-mapping.md +++ b/reference/core/sdlc/sdlc-evolith-artifact-mapping.md @@ -88,11 +88,11 @@ flowchart LR | Artifact | Location | Why it is required | |---|---|---| -| **Discovery Canvas** | [discovery-canvas-template.md](./04-artifact-templates/discovery-canvas-template.md) | Initiative registration, customer pain point, and expected value. At KDD Level 1+, inform this artifact from the Discovery Knowledge Brief. | +| **Discovery Canvas** | [discovery-canvas-template.md](./04-artifact-templates/discovery-canvas-template.md) | Initiative registration, customer pain point, and expected value. | | **Technical Feasibility Canvas** | [technical-feasibility-template.md](./04-artifact-templates/technical-feasibility-template.md) | Technical feasibility, cloud quotas, and NFRs. | -| **Ballpark Estimation** | [ballpark-estimation-template.md](./04-artifact-templates/ballpark-estimation-template.md) | T-Shirt Sizing estimation of effort and team size. At KDD Level 2+, incorporate Story Seed Bank sizing. | +| **Ballpark Estimation** | [ballpark-estimation-template.md](./04-artifact-templates/ballpark-estimation-template.md) | T-Shirt Sizing estimation of effort and team size. | | **PRD — Product Requirements Document** | [prd-template.md](./04-artifact-templates/prd-template.md) | Captures scope, personas, goals, constraints, non-goals, and approval evidence. | -| **MoSCoW Prioritization Matrix** | [moSCoW template](./04-artifact-templates/ballpark-estimation-template.md) | MoSCoW analysis with at least one MUST item. At KDD Level 2+, derived from Epic Candidate Matrix. | +| **MoSCoW Prioritization Matrix** | [moSCoW template](./04-artifact-templates/ballpark-estimation-template.md) | MoSCoW analysis with at least one MUST item. | | **Build-versus-Compose Analysis** | [build-vs-compose.schema.json](../../../src/rulesets/schema/build-vs-compose.schema.json) | Adopt/Embed/Integrate/Extend/Build/Reject disposition per Product Vision §5.3. | > **Evolith Compliance Baseline (§7):** Architectural Directives, Repository Taxonomy, Agnostic Baseline, ADR-0047, and Engineering Manifesto are cross-cutting standards governed by the Compliance Baseline. Consult them during Phase 1 but do not produce them here — they are already governed. @@ -106,18 +106,6 @@ flowchart LR | Architecture Communication Strategy | [architecture-communication-strategy.md](../foundations/common-rules/communication/architecture-communication-strategy.md) | When preparing stakeholder or executive architecture briefings. | | UMS Reference Model | [ums-reference-model.md](../../../product/research/demo/ums-reference-model.md) | When the product operates in identity, access management, or multi-tenant authorization. | -### Subphase 01.1 — Knowledge-First Discovery (Optional) - -| Artifact | Location | Level | When to Use | -|---|---|---|---| -| Discovery Knowledge Brief | [discovery-knowledge-brief-template.md](./04-artifact-templates/discovery-knowledge-brief-template.md) | 1+ | Any initiative where knowledge gaps could cause rework | -| Assumptions & Questions Log | [assumptions-questions-log-template.md](./04-artifact-templates/assumptions-questions-log-template.md) | 1+ | When assumptions need tracking and validation | -| Discovery Context Pack | [discovery-context-pack-template.md](./04-artifact-templates/discovery-context-pack-template.md) | 1+ | When AI agents or satellite repos need exportable context | -| Capability Map | [capability-map-template.md](./04-artifact-templates/capability-map-template.md) | 2+ | When domain decomposition is needed before epic planning | -| Epic Candidate Matrix | [epic-candidate-matrix-template.md](./04-artifact-templates/epic-candidate-matrix-template.md) | 2+ | When capabilities must be traced to epic candidates | -| Story Seed Bank | [story-seed-bank-template.md](./04-artifact-templates/story-seed-bank-template.md) | 2+ | When minimal story seeds are needed before backlog refinement | -| Discovery Readiness Gate | [discovery-readiness-gate-template.md](./04-artifact-templates/discovery-readiness-gate-template.md) | 3+ | When formal gate validation of knowledge sufficiency is required | - --- ## 3. Phase 2 — Design and Architecture @@ -137,7 +125,7 @@ flowchart LR | **ADR-0032 — Protocol Selection Matrix** | [ADR-0032](../architecture/adrs/core/0032-api-protocol-decision-matrix-rest-grpc-graphql.md) | REST, gRPC, and GraphQL use must be resolved before API contracts are produced. | | **ADR-0056 — Naming and Design Conventions** | [ADR-0056](../architecture/adrs/core/0056-enterprise-naming-design-conventions.md) | Ubiquitous language and naming rules must be established before entity and endpoint naming. | | **ADR-0045 — Extraction Readiness Criteria** | [ADR-0045](../architecture/adrs/core/0045-microservice-extraction-readiness-criteria.md) | Required — satellites declaring F2 must document their Extraction Readiness Score (≥70%). Enforced by satellite contract rule SVC-04. | -| **Functional Stories** | [functional-story-template.md](./04-artifact-templates/functional-story-template.md) | BDD-ready stories in Ready state, traceable to PRD. Use Functional Story Template as authoring format and Functional Story Writing Standard as quality guide. If Story Seeds exist from Phase 1.1 KDD Level 2+, refine them into Functional Stories here. | +| **Functional Stories** | [functional-story-template.md](./04-artifact-templates/functional-story-template.md) | BDD-ready stories in Ready state, traceable to PRD. Use Functional Story Template as authoring format and Functional Story Writing Standard as quality guide. | | **Simplicity Checklist Phase 1** | [simplicity-checklist-phase-01.md](../architecture/blueprints/simplicity-checklist-phase-01.md) | Despite the 'Phase 1' name, this checklist runs during Phase 2. Its purpose: verify no premature over-engineering enters the design baseline. The artifact identifier is registered in the machine validator — do not rename it. | | **CLI Impact Analysis** | [cli-impact-analysis.md](./04-artifact-templates/cli-impact-analysis.md) | Required CLI capabilities once design is baselined. | @@ -210,7 +198,7 @@ Phase 2 implies a specific progressive topology. The following actions are requi | 2 | Assess Extraction Readiness (ADR-0045 ≥70%); confirm ADR-0047 progression justified | Score documented | | 3 | Confirm ADR-0002; run Simplicity Checklist Phase 1 | Architecture baseline | | 4 | Produce Bounded Context Map (DDD Model Template); apply ADR-0031 + ADR-0032 | Bounded Context Map | -| 5 | Refine Story Seeds → Functional Stories (KDD L2+) or write from scratch | Functional Stories | +| 5 | Write Functional Stories from the approved scope | Functional Stories | | 6 | Document boundary decisions as ADRs; complete CLI Impact Analysis; consult ADR-0018; verify Blueprint Alignment | ADR Registry (complete) | | 7 | Run `evolith validate --topology distributed-modules` — all 8 DM rules must pass | Topology validation | | 8 | (Conditional) Validate DOMA if F3 topology in roadmap (ADR-0076) | DOMA compliance | diff --git a/src/packages/core-domain/src/application/validators/rule-corpus-triage.spec.ts b/src/packages/core-domain/src/application/validators/rule-corpus-triage.spec.ts index f6d1c64c..20d97bf4 100644 --- a/src/packages/core-domain/src/application/validators/rule-corpus-triage.spec.ts +++ b/src/packages/core-domain/src/application/validators/rule-corpus-triage.spec.ts @@ -112,7 +112,10 @@ const PINNED_CLASS_COUNTS: Readonly> = { // ADR owes one, `generate-adr-rulesets.mjs` wrote it, and it lands here for the same // reason every generated ADR ruleset does — its validationQuery says nothing a native // handler can execute. A decision written down, not a check that stopped working. - 'documentation-only': 138, + // 138 -> 139 on 2026-08-18: ADR-0127's, by the same mechanism. Worth noting what the + // count is measuring here — the ADR retires Knowledge-First Discovery, so the corpus + // grows by one rule in order to record the removal of a concept that never had one. + 'documentation-only': 139, 'unimplemented-native': 52, 'needs-external-system': 20, 'needs-runtime': 17, @@ -245,9 +248,12 @@ describe('GT-595 · the published breakdown, with its denominator', () => { // // 151 -> 152 on 2026-08-16: ADR-0126's generated conformance ruleset, the same +1 // recorded against `documentation-only` above. - expect(SUMMARY.nonExecutable).toBe(152); - expect(SUMMARY.executableTotal).toBe(SUMMARY.total - 152); - expect(SUMMARY.nonExecutableRuleIds).toHaveLength(152); + // 152 -> 153 on 2026-08-18: ADR-0127's, by the same mechanism — the ADR that retires + // Knowledge-First Discovery. The corpus grows by one rule nothing can run in order to + // record the removal of a concept nothing could run either. + expect(SUMMARY.nonExecutable).toBe(153); + expect(SUMMARY.executableTotal).toBe(SUMMARY.total - 153); + expect(SUMMARY.nonExecutableRuleIds).toHaveLength(153); }); it('names the blocking rules that can never produce a verdict', () => { @@ -307,8 +313,9 @@ describe('GT-595 · the handler slice that landed', () => { // 134 -> 135 on 2026-08-16: ADR-0126 (the bilingual mandate narrows to an entry // surface). Same shape as the ADR-0125 bump above — one accepted ADR, one generated // conformance placeholder, claimed by the conformance handler. + // 135 -> 136 on 2026-08-18: ADR-0127 (Knowledge-First Discovery is retired). Same shape. const adrConformance = CORPUS.filter(r => r.category === 'adr-conformance'); - expect(adrConformance).toHaveLength(135); + expect(adrConformance).toHaveLength(136); expect(adrConformance.every(claims)).toBe(true); }); diff --git a/src/rulesets/adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json b/src/rulesets/adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json new file mode 100644 index 00000000..6a5618f7 --- /dev/null +++ b/src/rulesets/adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json @@ -0,0 +1,28 @@ +{ + "$schema": "../../schema/ruleset-standard.schema.json", + "$id": "https://evolith.dev/rulesets/adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json", + "title": "ADR-0127 — Knowledge-First Discovery Is Retired, and With It the KDD Concept Rules (generated)", + "description": "Auto-generated ruleset encoding ADR-0127 (core track). Classification: advisory. Generated by .harness/scripts/generate-adr-rulesets.mjs — do not edit by hand.", + "version": "1.0.0", + "audience": "core", + "adrId": "ADR-0127", + "adrTitle": "Knowledge-First Discovery Is Retired, and With It the KDD Concept", + "status": "Accepted — 2026-08-18. In force.", + "date": "| 2026-08-18 |", + "rules": [ + { + "id": "CORE-0127-01", + "severity": "SHOULD", + "category": "adr-conformance", + "title": "Honor design decision in ADR-0127: Knowledge-First Discovery Is Retired, and With It the KDD Concept", + "description": "Design and implementation SHOULD honor the decision recorded in ADR-0127 (core track). ADR decision: Both readings are retired. Evolith Core and Evolith Tracker no longer carry the KDD concept in any form , and the information related to it is removed rather than archived in place. Manual attestation required — not machine-verifiable.", + "statement": "ADR decision: Both readings are retired. Evolith Core and Evolith Tracker no longer carry the KDD concept in any form , and the information related to it is removed rather than archived in place.", + "rationale": "Derived from ADR-0127 \"Decision\" section. No machine-verifiable signals detected; treated as an advisory design decision.", + "blocking": false, + "enforcement": "advisory" + } + ], + "references": [ + "reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md" + ] +} diff --git a/src/rulesets/standards/iso-5055-mapping.csv b/src/rulesets/standards/iso-5055-mapping.csv index 3eb9c217..74130f98 100644 --- a/src/rulesets/standards/iso-5055-mapping.csv +++ b/src/rulesets/standards/iso-5055-mapping.csv @@ -155,6 +155,7 @@ CORE-0123-01,adr/generated/adr-0123-timing-safe-comparison-standard.rules.json,a CORE-0124-01,adr/generated/adr-0124-credential-and-secret-management-standard.rules.json,architecture-decision,,,none,no,documentation-only CORE-0125-01,adr/generated/adr-0125-a-single-artifact-registry-keyed-by-slug.rules.json,architecture-decision,,,none,no,documentation-only CORE-0126-01,adr/generated/adr-0126-the-bilingual-mandate-narrows-to-an-entry-surface.rules.json,architecture-decision,,,none,no,documentation-only +CORE-0127-01,adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json,architecture-decision,,,none,no,documentation-only AI-0001-01,adr/generated/adr-ai-augmented-0001-harness-engineering-for-ai-augmented-development.rules.json,architecture-decision,,,none,no,documentation-only AI-0002-01,adr/generated/adr-ai-augmented-0002-mcp-integration-protocol-for-agent-tool-invocation.rules.json,architecture-decision,,,none,no,documentation-only AI-0003-01,adr/generated/adr-ai-augmented-0003-model-selection-governance-for-ai-augmented-workflows.rules.json,architecture-decision,,,none,no,documentation-only diff --git a/src/rulesets/standards/iso-5055-mapping.json b/src/rulesets/standards/iso-5055-mapping.json index ec57370c..e9c5e304 100644 --- a/src/rulesets/standards/iso-5055-mapping.json +++ b/src/rulesets/standards/iso-5055-mapping.json @@ -12,24 +12,24 @@ "weaknessCount": 138 }, "corpus": { - "rulesetFiles": 181, - "rules": 414, + "rulesetFiles": 182, + "rules": 415, "note": "Files that carry gate definitions or topology recommendations rather than conformance rules contribute no rows: architecture/topology-recommendation.rules.json and sdlc/phase-gates.rules.json." }, "summary": { - "rules": 414, + "rules": 415, "mappedToIso5055": 37, "mappedDirect": 8, "mappedPartial": 29, - "noInternationalEquivalent": 377, - "adoptedFraction": 0.0894, + "noInternationalEquivalent": 378, + "adoptedFraction": 0.0892, "analyserAdoptable": 46, "analyserAdoptablePartial": 23, - "analyserAdoptableFraction": 0.1111, - "analyserAdoptableFractionIncludingPartial": 0.1667, + "analyserAdoptableFraction": 0.1108, + "analyserAdoptableFractionIncludingPartial": 0.1663, "byClass": { "architecture-decision": { - "rules": 164, + "rules": 165, "mapped": 12, "adoptable": 6 }, @@ -146,7 +146,7 @@ "adoptablePartialRuleIds": [] }, "documentation-only": { - "rules": 138, + "rules": 139, "mappedToIso5055": 9, "analyserAdoptable": 6, "analyserAdoptablePartial": 7, @@ -3365,6 +3365,25 @@ "nativeEvaluability": "documentation-only", "note": "Conformance to a recorded architecture decision. ISO/IEC 5055 measures source structure, not whether a decision was honoured." }, + { + "ruleId": "CORE-0127-01", + "sourceFile": "adr/generated/adr-0127-knowledge-first-discovery-is-retired-and-with-it-the-kdd-con.rules.json", + "title": "Honor design decision in ADR-0127: Knowledge-First Discovery Is Retired, and With It the KDD Concept", + "severity": "SHOULD", + "ruleClass": "architecture-decision", + "iso5055": { + "cwes": [], + "weaknesses": [], + "measures": [], + "strength": "none" + }, + "analyser": { + "adoptable": "no", + "examples": [] + }, + "nativeEvaluability": "documentation-only", + "note": "Conformance to a recorded architecture decision. ISO/IEC 5055 measures source structure, not whether a decision was honoured." + }, { "ruleId": "AI-0001-01", "sourceFile": "adr/generated/adr-ai-augmented-0001-harness-engineering-for-ai-augmented-development.rules.json", diff --git a/src/rulesets/standards/native-evaluability-snapshot.json b/src/rulesets/standards/native-evaluability-snapshot.json index 9d9c1ad1..87c5c6b0 100644 --- a/src/rulesets/standards/native-evaluability-snapshot.json +++ b/src/rulesets/standards/native-evaluability-snapshot.json @@ -3,7 +3,7 @@ "title": "Native-engine evaluability class per rule (snapshot)", "description": "Per-rule evaluability class as computed by the Core native evaluator triage. This is a GENERATED CAPTURE, not the source of truth: the authority is src/packages/core-domain/src/application/validators/rule-evaluability.ts and the handler set registered in native-evaluator.ts. It is recorded here so the ISO/IEC 5055 mapping can be scoped to the real handler backlog without src/rulesets depending on a package it does not own. Do not hand-edit — regenerate.", "version": "1.1.0", - "capturedOn": "2026-08-18", + "capturedOn": "2026-08-19", "capturedFrom": [ "src/packages/core-domain/src/application/validators/rule-evaluability.ts (RULE_TRIAGE, classifyRule, ADR_CONFORMANCE_CATEGORY)", "src/packages/core-domain/src/application/validators/evaluators/native-evaluator.ts (registered handler set)", @@ -11,12 +11,12 @@ "src/packages/core-domain/test/rule-corpus-triage.ts (corpus loader, classification and this renderer)" ], "regenerateWith": "node src/rulesets/standards/capture-native-evaluability-snapshot.mjs", - "validation": "Rendered by test/rule-corpus-triage.ts from the live triage, written by capture-native-evaluability-snapshot.mjs and pinned byte-for-byte by rule-corpus-triage.spec.ts, so a divergence between this file and Core is a failing test rather than silent drift (corpus 412; native-handler 171, documentation-only 138, unimplemented-native 52, needs-external-system 20, needs-runtime 17, underspecified 14).", - "corpusSize": 412, - "distinctRuleIds": 412, + "validation": "Rendered by test/rule-corpus-triage.ts from the live triage, written by capture-native-evaluability-snapshot.mjs and pinned byte-for-byte by rule-corpus-triage.spec.ts, so a divergence between this file and Core is a failing test rather than silent drift (corpus 413; native-handler 171, documentation-only 139, unimplemented-native 52, needs-external-system 20, needs-runtime 17, underspecified 14).", + "corpusSize": 413, + "distinctRuleIds": 413, "counts": { "native-handler": 171, - "documentation-only": 138, + "documentation-only": 139, "unimplemented-native": 52, "needs-external-system": 20, "needs-runtime": 17, @@ -179,6 +179,7 @@ "CORE-0124-01": "documentation-only", "CORE-0125-01": "documentation-only", "CORE-0126-01": "documentation-only", + "CORE-0127-01": "documentation-only", "AI-0001-01": "documentation-only", "AI-0002-01": "documentation-only", "AI-0003-01": "documentation-only", From c2c09732dc602543a92a0c69647a18b4148b1296 Mon Sep 17 00:00:00 2001 From: Alberto Arroyo Raygada Date: Wed, 19 Aug 2026 08:38:21 -0500 Subject: [PATCH 4/5] =?UTF-8?q?docs(gaps):=20close=20GT-708=20=E2=80=94=20?= =?UTF-8?q?both=20halves=20of=20the=20KDD=20retirement=20landed=20(#624)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The row was left IN-PROGRESS when the Core half merged, because one of its criteria was the Tracker's REQ-DIS-12/REQ-DIS-13. That criterion is met by evolith_tracker#153 (97e1bc8e), so the row closes. Both repositories had the same shape of teeth in different words: the Core made 'Phase 1.1 adoption level has been declared' a precondition for opening Gate 1, and the Tracker gave REQ-DIS-13 the acceptance criterion 'a FAIL result blocks opening the Business Sign-Off gate'. One non-existent gate, described twice, blocking on paper the only gate every initiative must pass — while no ruleset, schema, CLI command, MCP tool, screen or entity implemented it anywhere. Board: 677 / 706 done, 0 pending. --- .../evidence/gap-closure-evidence.json | 21 +++++++++++++++++++ .../gaps/gap-reference-catalog.es.md | 4 ++-- .../gaps/gap-reference-catalog.md | 4 ++-- .../control-center/gaps/gap-tracking.es.md | 4 ++-- .../core/control-center/gaps/gap-tracking.md | 4 ++-- .../maturity-reports/executive-summary.es.md | 18 ++++++++-------- .../maturity-reports/executive-summary.md | 18 ++++++++-------- .../maturity-reconciliation.json | 6 +++--- 8 files changed, 50 insertions(+), 29 deletions(-) diff --git a/reference/core/control-center/evidence/gap-closure-evidence.json b/reference/core/control-center/evidence/gap-closure-evidence.json index 1716d719..f5068c7d 100644 --- a/reference/core/control-center/evidence/gap-closure-evidence.json +++ b/reference/core/control-center/evidence/gap-closure-evidence.json @@ -10614,6 +10614,27 @@ "npm run build --workspace src/sdk/cli && npm run build:policy && node .harness/scripts/ci/68-validate-engine-verdict-parity.mjs --verbose --json # the two builds are a real prerequisite, not decoration: the sweep spawns the CLI dist and loads policy.wasm", "node --test .harness/scripts/ci/68-validate-engine-verdict-parity.test.mjs" ] + }, + { + "id": "GT-708", + "closedAt": "2026-08-18", + "closureCommit": "144fce23", + "dependencyDisposition": "none", + "evidence": [ + "reference/core/architecture/adrs/core/0127-retire-knowledge-first-discovery.md", + "reference/core/sdlc/01-playbooks/phase-1-business-signoff.md", + "reference/core/sdlc/sdlc-evolith-artifact-mapping.md", + "reference/core/foundations/agent-skills/tracker-discovery-flow.md" + ], + "validationCommands": [ + "NOTHING TO DE-IMPLEMENT, MEASURED BEFORE DELETING: five gates for phases 1..5; none of the seven KDD artifacts among the 33 in artifact-registry.json; zero TypeScript files matching KDD/knowledge-first/knowledgeBrief/discoveryReadiness/storySeed/epicCandidate; 31 CLI commands with zero mentions and --phase discovery mapping to phase 1 ENTIRE; zero in the MCP server; no Tracker screen or entity; no KDD section in prd.schema.json.", + "THE PROSE HAD TEETH IN BOTH REPOSITORIES, IN DIFFERENT WORDS: the Core made 'Phase 1.1 adoption level has been declared' a precondition for opening Gate 1 ('a FAIL result blocks this gate'); the Tracker gave REQ-DIS-13 the acceptance criterion 'a FAIL result blocks opening the Business Sign-Off gate'. One non-existent gate, blocking on paper the only gate every initiative must pass.", + "TWO CONCEPTS UNDER THREE LETTERS, and the first analysis confused them: Phase 1.1 (subphase gate, seven templates) versus KDD = Knowledge-Driven Development (optional section INSIDE the PRD, per-tenant feature-override, owner session 2026-07-04, L-009/D-004). The owner retired both.", + "ADR-0103 IS AMENDED, NOT EDITED. ADR-0127 carries the retirement; ADR-0103 and CHANGELOG.md keep their KDD text because they record what was true when written, as do the Tracker's two audit-board rows.", + "THE ADR ITSELF GREW THE CORPUS BY ONE: generate-adr-rulesets.mjs owes every accepted ADR a conformance ruleset, so documentation-only went 138->139, nonExecutable 152->153 and adr-conformance 135->136. The corpus grows by one rule nothing can run, to record the removal of a concept nothing could run either.", + "BOTH HALVES: evolith_arch32#623 (144fce23) and evolith_tracker#153 (97e1bc8e).", + "node .harness/scripts/ci/08-validate-tracking.mjs && node --test src/rulesets/standards/iso-5055-mapping.test.mjs" + ] } ] } diff --git a/reference/core/control-center/gaps/gap-reference-catalog.es.md b/reference/core/control-center/gaps/gap-reference-catalog.es.md index 44747e72..c7b8e93a 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.es.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.es.md @@ -10044,7 +10044,7 @@ Los dos se arreglaron de forma estructural y no como correcciones: el rethrow no - [x] `KDD` y `knowledge-first` devuelven cero coincidencias en ambos repositorios, salvo en `CHANGELOG.md` y el `ADR-0103`, que quedan como registros históricos a propósito. **CUMPLIDO para el Core.** Tras el barrido los tokens sobreviven en exactamente seis ficheros: `CHANGELOG.md`, el `ADR-0103` (EN/ES), el `ADR-0127` (EN/ES) —la propia retirada— más el tablero de gaps y el aviso de corrección del documento de rediseño. La mitad del Tracker es su propio pull request en `evolith_tracker`. - [x] Las precondiciones y la tabla de evidencia del Gate 1 se sostienen solas, sin referencia a ninguna subfase ni a niveles de KDD. **CUMPLIDO** — desapareció la viñeta *«el nivel de adopción de la Fase 1.1 ha sido declarado… un resultado FAIL bloquea esta compuerta»*, y las tres filas de evidencia (Discovery Canvas, Ballpark Estimation, MoSCoW) ya no llevan sus cláusulas `Si se aplicó Fase 1.1 Nivel ≥ n`. - [x] La retirada es un **ADR**, y el `ADR-0103` queda enmendado por él en vez de editado — una decisión aceptada se supersede, no se reescribe. **CUMPLIDO** — el `ADR-0127` lleva la decisión y enuncia la enmienda: el Planning Gate precede ahora directamente a la Fase 1, y la opción que el `ADR-0103` descartó queda sin objeto, no equivocada. El propio `ADR-0103` queda intacto. - - [ ] Los `REQ-DIS-12` y `REQ-DIS-13` del Tracker se van con él; un requisito numerado que queda en pie es una instrucción de construir la cosa. **ABIERTO — la mitad del Tracker es un pull request aparte en `evolith_tracker`**, donde los ficheros, el tablero y los guards son otros. Sin marcar a propósito: esta fila no está hecha hasta que lo estén los dos repositorios. + - [x] Los `REQ-DIS-12` y `REQ-DIS-13` del Tracker se van con él; un requisito numerado que queda en pie es una instrucción de construir la cosa. **CUMPLIDO** — `evolith_tracker#153` (mergeado `97e1bc8e`) elimina ambos requisitos, la viñeta de gobierno de la subfase 01.1, la sección entera `Fase 1 · Subfase 01.1` del catálogo de artefactos, la viñeta de insumos de preparación del blueprint, las cláusulas KDD del índice del hub de Discovery (con el rango corregido de `REQ-DIS-01..13` a `..11`) y los bloques KDD de `.bmad-core`. El criterio de aceptación del `REQ-DIS-13` decía *«un resultado FAIL bloquea la apertura de la compuerta de Business Sign-Off»* — los mismos dientes que tenía la precondición de la Fase 1 en el Core, en el otro repositorio. - [x] **FALSABILIDAD:** ningún enlace de ninguno de los dos repositorios resuelve a un fichero KDD borrado, comprobado tras el barrido y no supuesto desde la lista de borrados. **CUMPLIDO para el Core** — buscar los ocho nombres borrados en todos los markdown no devuelve nada fuera del `ADR-0127` y del aviso de corrección del documento de rediseño, que los nombran como retirados en vez de enlazarlos. -- **Estado:** `EN-PROGRESO` +- **Estado:** `COMPLETADO` diff --git a/reference/core/control-center/gaps/gap-reference-catalog.md b/reference/core/control-center/gaps/gap-reference-catalog.md index 34c0ff3a..79e9288c 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.md @@ -10139,7 +10139,7 @@ Both were fixed structurally rather than corrected: the rethrow now names BOTH f - [x] `KDD` and `knowledge-first` return zero matches across both repositories, except in `CHANGELOG.md` and `ADR-0103`, which are left as historical records on purpose. **MET for the Core.** After the sweep the tokens survive in exactly six files: `CHANGELOG.md`, `ADR-0103` (EN/ES), `ADR-0127` (EN/ES) — the retirement itself — plus the gap board and the redesign doc's correction notice. The Tracker half is its own pull request in `evolith_tracker`. - [x] Gate 1's preconditions and evidence table stand on their own, with no reference to a subphase or to KDD levels. **MET** — the *"Phase 1.1 adoption level has been declared… a FAIL result blocks this gate"* bullet is gone, and the three evidence rows (Discovery Canvas, Ballpark Estimation, MoSCoW) no longer carry their `If Phase 1.1 Level ≥ n` clauses. - [x] The retirement is an **ADR**, and `ADR-0103` is amended by it rather than edited — an accepted decision is superseded, not rewritten. **MET** — `ADR-0127` carries the decision and states the amendment: the Planning Gate now precedes Phase 1 directly, and the option `ADR-0103` rejected is moot rather than wrong. `ADR-0103` itself is untouched. - - [ ] The Tracker's `REQ-DIS-12` and `REQ-DIS-13` go with it; a numbered requirement left standing is an instruction to build the thing. **OPEN — the Tracker half is a separate pull request in `evolith_tracker`**, where the files, the board and the guards are different. Left unticked deliberately: this row is not done until both repositories are. + - [x] The Tracker's `REQ-DIS-12` and `REQ-DIS-13` go with it; a numbered requirement left standing is an instruction to build the thing. **MET** — `evolith_tracker#153` (merged `97e1bc8e`) removes both requirements, the subphase-01.1 governance bullet, the whole `Phase 1 · Subphase 01.1` section of the artifact catalog, the blueprint's readiness-inputs bullet, the KDD clauses in the Discovery hub index (with the range corrected `REQ-DIS-01..13` → `..11`), and the KDD blocks in `.bmad-core`. `REQ-DIS-13`'s acceptance criterion was *"a FAIL result blocks opening the Business Sign-Off gate"* — the same teeth the Core's Phase 1 precondition had, in the other repository. - [x] **FALSIFIABILITY:** no link in either repository resolves to a deleted KDD file, checked after the sweep rather than assumed from the delete list. **MET for the Core** — searching the eight deleted filenames across every markdown file returns nothing outside `ADR-0127` and the redesign doc's correction notice, both of which name them as retired rather than link to them. -- **Status:** `IN-PROGRESS` +- **Status:** `DONE` diff --git a/reference/core/control-center/gaps/gap-tracking.es.md b/reference/core/control-center/gaps/gap-tracking.es.md index ade760fc..705cb89f 100644 --- a/reference/core/control-center/gaps/gap-tracking.es.md +++ b/reference/core/control-center/gaps/gap-tracking.es.md @@ -20,7 +20,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | ID | Gap | En simple | Qué resuelve | Componente | Fase | Criticidad | Complejidad | Estado | |---|---|---|---|:---:|:---:|:---:|:---:|:---:| -| [`GT-708`](./gap-reference-catalog.es.md#gt-708) | **Un concepto de gobierno que existía solo en prosa, en dos repositorios, y que una compuerta real citaba como precondición.** «KDD» nombraba dos cosas distintas y ninguna llegó a construirse: la **Fase 1.1 — Knowledge-First Discovery**, subfase opcional con su propia compuerta de preparación y siete plantillas de artefacto; y **KDD — Knowledge-Driven Development**, lectura posterior de la sesión con el dueño del 2026-07-04 (`L-009`, `D-004`) que lo convertía en sección opcional *dentro del PRD*, activable por tenant. **Medido en todas las superficies ejecutables, y ausente en todas:** `phase-gates.rules.json` tiene cinco gates para las fases 1..5; ninguno de los siete artefactos KDD está entre los 33 de `artifact-registry.json`; cero ficheros TypeScript con `KDD`/`knowledge-first`/`knowledgeBrief`/`discoveryReadiness`/`storySeed`/`epicCandidate`; el CLI tiene 31 comandos y cero menciones, y su `--phase discovery` mapea a la **fase 1 entera** (`phase-id.ts`: `f1: 'discovery'`), no a la 1.1; el servidor MCP, cero; el Tracker no tiene ni pantalla ni entidad; y `prd.schema.json` no lleva sección KDD, así que `D-004` tampoco llegó nunca a schema. **Aun así la prosa tenía dientes:** `phase-1-business-signoff.es.md` convertía *«el nivel de adopción de la Fase 1.1 ha sido declarado»* en **precondición para abrir el Gate 1**, y tres filas de su tabla de evidencia llevaban cláusulas condicionadas a niveles de KDD — una compuerta que nadie implementa bloqueando una que implementa todo el mundo. **CERRADA el 2026-08-18 por eliminación, por decisión del dueño de que Evolith Core y Tracker dejan de manejar el concepto en cualquier forma.** 16 ficheros borrados (el playbook de la Fase 1.1 y las siete plantillas, EN y ES); eliminadas la precondición del Gate 1 y sus tres cláusulas de evidencia condicionadas a KDD; eliminadas la tabla `Subfase 01.1`, la fila del índice de playbooks y las referencias a Story Seeds / Epic Candidates en el playbook de Fase 2 y en el índice de plantillas; `D-004`/`L-009` reescritas a lo que las sobrevive — el PRD es el piso canónico y el Gate 1 lo exige siempre. **La retirada es el [`ADR-0127`](../../architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md), y el `ADR-0103` queda ENMENDADO por él en vez de editado:** una decisión aceptada del Architecture Board se supersede, no se reescribe, así que su razonamiento se mantiene y lo único que desapareció es su vecino. `CHANGELOG.md` y el `ADR-0103` conservan su texto sobre KDD a propósito — registran lo que era cierto cuando se escribieron, y editarlos falsificaría la historia que este repositorio guarda deliberadamente. **Falsabilidad, comprobada tras el barrido y no inferida de la lista de borrados:** toda referencia a los ocho ficheros borrados no devuelve nada fuera del ADR y del aviso de corrección, y `KDD`/`knowledge-first` solo sobreviven en los seis ficheros citados. **Lo que deja esta fila es la lección, no el barrido:** un concepto puede ser citado como precondición dura por una compuerta que todo el mundo implementa mientras no lo implementa nadie, y seguir así meses, porque nadie contrasta la prosa contra los datos. | Un concepto que describimos por todas partes y no construimos en ninguna, del que depende una de nuestras compuertas reales. | Que el modelo de cinco fases se lea igual en los documentos que en los datos, y que el Gate 1 deje de depender de una subfase que nadie puede ejecutar. | `Governance` | Cross | P2 | M | `EN-PROGRESO` | +| [`GT-708`](./gap-reference-catalog.es.md#gt-708) | **Un concepto de gobierno que existía solo en prosa, en dos repositorios, y que una compuerta real citaba como precondición.** «KDD» nombraba dos cosas distintas y ninguna llegó a construirse: la **Fase 1.1 — Knowledge-First Discovery**, subfase opcional con su propia compuerta de preparación y siete plantillas de artefacto; y **KDD — Knowledge-Driven Development**, lectura posterior de la sesión con el dueño del 2026-07-04 (`L-009`, `D-004`) que lo convertía en sección opcional *dentro del PRD*, activable por tenant. **Medido en todas las superficies ejecutables, y ausente en todas:** `phase-gates.rules.json` tiene cinco gates para las fases 1..5; ninguno de los siete artefactos KDD está entre los 33 de `artifact-registry.json`; cero ficheros TypeScript con `KDD`/`knowledge-first`/`knowledgeBrief`/`discoveryReadiness`/`storySeed`/`epicCandidate`; el CLI tiene 31 comandos y cero menciones, y su `--phase discovery` mapea a la **fase 1 entera** (`phase-id.ts`: `f1: 'discovery'`), no a la 1.1; el servidor MCP, cero; el Tracker no tiene ni pantalla ni entidad; y `prd.schema.json` no lleva sección KDD, así que `D-004` tampoco llegó nunca a schema. **Aun así la prosa tenía dientes:** `phase-1-business-signoff.es.md` convertía *«el nivel de adopción de la Fase 1.1 ha sido declarado»* en **precondición para abrir el Gate 1**, y tres filas de su tabla de evidencia llevaban cláusulas condicionadas a niveles de KDD — una compuerta que nadie implementa bloqueando una que implementa todo el mundo. **CERRADA el 2026-08-18 por eliminación, por decisión del dueño de que Evolith Core y Tracker dejan de manejar el concepto en cualquier forma.** 16 ficheros borrados (el playbook de la Fase 1.1 y las siete plantillas, EN y ES); eliminadas la precondición del Gate 1 y sus tres cláusulas de evidencia condicionadas a KDD; eliminadas la tabla `Subfase 01.1`, la fila del índice de playbooks y las referencias a Story Seeds / Epic Candidates en el playbook de Fase 2 y en el índice de plantillas; `D-004`/`L-009` reescritas a lo que las sobrevive — el PRD es el piso canónico y el Gate 1 lo exige siempre. **La retirada es el [`ADR-0127`](../../architecture/adrs/core/0127-retire-knowledge-first-discovery.es.md), y el `ADR-0103` queda ENMENDADO por él en vez de editado:** una decisión aceptada del Architecture Board se supersede, no se reescribe, así que su razonamiento se mantiene y lo único que desapareció es su vecino. `CHANGELOG.md` y el `ADR-0103` conservan su texto sobre KDD a propósito — registran lo que era cierto cuando se escribieron, y editarlos falsificaría la historia que este repositorio guarda deliberadamente. **Falsabilidad, comprobada tras el barrido y no inferida de la lista de borrados:** toda referencia a los ocho ficheros borrados no devuelve nada fuera del ADR y del aviso de corrección, y `KDD`/`knowledge-first` solo sobreviven en los seis ficheros citados. **Lo que deja esta fila es la lección, no el barrido:** un concepto puede ser citado como precondición dura por una compuerta que todo el mundo implementa mientras no lo implementa nadie, y seguir así meses, porque nadie contrasta la prosa contra los datos. **CERRADA el 2026-08-18 — aterrizaron las dos mitades.** La del Tracker es `evolith_tracker#153` (`97e1bc8e`): `REQ-DIS-12` y `REQ-DIS-13` eliminados junto con la viñeta de gobierno de la subfase 01.1, la sección del catálogo de artefactos, la viñeta del blueprint, las cláusulas del índice de Discovery y los bloques de `.bmad-core`. **Los dos repositorios tenían la misma forma de dientes con distintas palabras:** el Core convertía *«el nivel de adopción de la Fase 1.1 ha sido declarado»* en precondición para abrir el Gate 1, y el Tracker daba al `REQ-DIS-13` el criterio de aceptación *«un resultado FAIL bloquea la apertura de la compuerta de Business Sign-Off»* — dos documentos, una compuerta inexistente, ambos bloqueando la única compuerta por la que pasa toda iniciativa. Lo que sobrevive es deliberado: `CHANGELOG.md` y el `ADR-0103` en el Core, y las dos filas del board de auditoría del Tracker, todos ellos registros de lo que era cierto cuando se escribieron. | Un concepto que describimos por todas partes y no construimos en ninguna, del que depende una de nuestras compuertas reales. | Que el modelo de cinco fases se lea igual en los documentos que en los datos, y que el Gate 1 deje de depender de una subfase que nadie puede ejecutar. | `Governance` | Cross | P2 | M | `COMPLETADO` | | [`GT-707`](./gap-reference-catalog.es.md#gt-707) | **Todo binario autónomo que publica este repositorio falla en `--help`, y ninguna release ha llevado nunca uno.** Medido el 2026-08-18 en los cuatro pull requests abiertos y, antes de ellos, en el push del tag `v1.3.6` y en el pull request que hizo por primera vez que el release pipeline corriera en pull requests: `smoke-test` y `smoke-test-functional` fallan con `ERR_REQUIRE_ESM: require() of ES Module /snapshot/…/@clack/prompts/dist/index.mjs`, lanzado desde `prompt.service.js` — así que el binario muere antes de parsear un argumento, en las tres plataformas. `gh release view` sobre `v1.3.0` y `v1.1.0` devuelve **cero assets**: `upload-assets` depende de `smoke-test`, así que el canal nunca ha entregado nada, y la propia puerta del pipeline es lo que lo detuvo. **Medido además, para que el próximo intento arranque aquí:** `@clack/prompts@1.5.1` es la ÚNICA dependencia solo-ESM del CLI (`chalk` 4.1.2, `ora` 5.4.1, `inquirer` 8.2.7 y `cli-table3` son todas CommonJS); `esbuild` la empaqueta en un CJS de 107 kB que carga limpio; y empaquetar con el fork mantenido `@yao-pkg/pkg@6` ELIMINA el `ERR_REQUIRE_ESM` y falla distinto — `MODULE_NOT_FOUND` por el mismo `.mjs`, porque el fichero no está en el snapshot — lo que significa que el empaquetador y el conjunto de assets son dos defectos distintos, no uno. **El arreglo que parece barato no lo es:** redirigir el import toca 6 ficheros de producción y ~24 specs que hacen `jest.mock('@clack/prompts')` con ese especificador exacto. **Deliberadamente NO arreglado dentro de los cuatro pull requests que lo encontraron:** están verdes en los 8 checks requeridos y esto es un fallo previo en un workflow no requerido; meter un rediseño de empaquetado ahí sería el cambio-ajeno-dentro-de-una-promoción que este tablero no deja de rechazar. **CERRADA el 2026-08-18 vendorizando a CommonJS las dependencias solo-ESM — y la primera evidencia de esta misma fila estaba mal dos veces, que es la parte que merece conservarse.** El binario empaquetado ya arranca: construido desde este árbol, `--help` sale **0**, `--version` imprime `1.3.2`, e `init --runtime nodejs --monorepo none --arch clean` sale **0** y escribe un satélite. **MAL #1 — «la única dependencia solo-ESM».** Esta fila lo midió sondeando `require('/package.json')`, que ocho de las 25 dependencias directas rechazan con `ERR_PACKAGE_PATH_NOT_EXPORTED` — un error que se lee como «bien». Leyendo los manifiestos DESDE DISCO aparecen **tres**: `@clack/prompts@1.5.1`, `conf@15.1.0` y `@modelcontextprotocol/sdk@1.29.0`. Dos se cargan en runtime y ambas quedan vendorizadas; el sdk de MCP es solo un `.d.ts` en este paquete, así que nunca entra en el snapshot. `pkg` llevaba avisando de `conf` todo el tiempo —muere nombrando `conf/package.json` y `config.service.js`— y nadie leyó más allá del primer error. **MAL #2 — el fallback apuntaba a nada.** `clack.ts` compila a `dist/infrastructure/prompts/` mientras el bundle se escribe en `dist/vendor/`, así que `require('./vendor/clack.cjs')` resolvía a una ruta inexistente. Nada falló en build; falló el BINARIO en ejecución, con el error del propio paquete, porque el `MODULE_NOT_FOUND` del fallback quedaba tragado por un rethrow del original. Ambos son ahora arreglos estructurales y no correcciones: el rethrow nombra LOS DOS fallos, y `vendor-esm-deps.mjs` lee la ruta relativa del shim COMPILADO y la resuelve — observado en rojo contra la ruta rota, con la ubicación resuelta en el mensaje. **Lo que se entrega:** `scripts/vendor-esm-deps.mjs` empaqueta cada dependencia solo-ESM con esbuild (clack 107 kB, conf 410 kB) y luego la carga de vuelta en un proceso hijo con `--no-experimental-require-module` —lo más cerca que un proceso Node normal está del contrato sin-ESM del snapshot— y compara su superficie de exports con la del paquete real. Dos shims (`prompts/clack.ts`, `config/conf-module.ts`) prueban PRIMERO EL PAQUETE y caen al bundle ante CUALQUIER fallo de carga: el orden es lo que mantiene las ~24 specs que hacen `jest.mock('@clack/prompts')` interceptando el mismo especificador de siempre, y «cualquier fallo» es porque la misma causa aflora como `ERR_REQUIRE_ESM` con un empaquetador y como `MODULE_NOT_FOUND` con otro. 106 suites / 1485 tests en verde, `tsc -b` limpio. El release pipeline no cambia: el arreglo es agnóstico del empaquetador, y su `smoke-test` es la falsabilidad que esta fila pedía. | El programa descargable que publicamos se cae al instante y, de hecho, nunca hemos publicado ninguno. | O un binario autónomo que arranca, o una retirada honesta del canal — no un check rojo que todo el mundo aprende a ignorar. | `Infra` | Cross | P2 | M | `COMPLETADO` | | [`GT-688`](./gap-reference-catalog.es.md#gt-688) | **Una composición de topologías confirmada se trunca a un solo id antes de la compuerta, así que un sistema mixto obtiene un veredicto verde por la única topología que sobrevivió.** Medido en vivo el 2026-08-14 contra el dist compilado: `manifestFromWorkspace` con `design.topologyConfirmedRefs: [modular-monolith, agentic-ai, event-driven]` devuelve `{"topology":"modular-monolith","facts":{"context":{"topologyRef":"modular-monolith"}}}` — **las otras dos no aparecen por ninguna parte**. Causa: `evaluation-context.builder.ts:26` `topology: ctx.topologyRef`, y `grep -n "design"` sobre ese fichero entero devuelve un hit, un comentario en `:149`. **Peor sin el escalar:** el manifiesto sale sin clave `topology`, el kind SALTA (`kind-evaluators.ts:363`), y el pipeline se reinventa una **con un regex sobre el YAML en disco**, ganando la primera coincidencia (`satellite-evaluation-pipeline.service.ts:354`). El contrato de resultado tampoco puede llevar dos (`TopologyEvaluationResult.topologyRef`, escalar obligatorio). Así que el kind devuelve `PASS, conformant: true` por el id que conservó — **un veredicto verde sobre un sistema del que la mitad nunca se comprobó**. **La observación del dueño que originó esta fila quedó REFUTADA a medias, y la mitad refutada importa:** el modelo NO es singular — `ADR-0079:44` rechaza por escrito el diseño excluyente, la transversalidad es declaración formal (`maturityLevel: "cross"` en las cinco no progresivas), y el corpus, el contrato de satélite y el evaluador de diseño son plurales; `evolith topology phase-artifacts -t agentic-ai,event-driven` sí une ambas. Lo que sobrevivió es el cable de APLICACIÓN. No lo cubre `MT-A*`: sus 26 filas están DONE y todas son corpus, esquema o documentación. | — | — | `Core Domain` | Cross | P1 | L | `COMPLETADO` | | [`GT-689`](./gap-reference-catalog.es.md#gt-689) | **El modelo de compatibilidad de composiciones no tiene ningún lector en ejecución, y su marcador de transversalidad no tiene ninguno.** `grep -rn "composableWith" --include=*.ts src/` excluyendo dist devuelve dos hits, ambos declaraciones de tipo, **cero lecturas**; `metadata.dimension` —el campo que codifica la transversalidad— no tiene lector alguno en producción. El único consumidor es el guard `22-validate-topology-composition.mjs`, y `find . -name topology.composition.json` devuelve **exactamente un** fichero fuera de worktrees. Tres consecuencias medidas: el guard compara todo par ordenado, así que exige simetría mientras los manifiestos son asimétricos, y por eso `modular-monolith → data-mesh` y `edge-computing → serverless` **fallarían en CI el día que alguien los escriba**; `minItems: 2` impide expresar el estado documentado más común, un `modular-monolith` solo; y `edge-computing` y `serverless` son ambos `dimension: execution` y se declaran componibles, algo que la documentación prohíbe y que nadie caza, porque nadie lee `dimension`. Se registra ahora y no después de [`GT-688`](./gap-reference-catalog.es.md#gt-688) porque es esa fila la que vuelve portante esta validación. | Las reglas sobre qué arquitecturas pueden combinarse están escritas con cuidado y no las consulta nada que se ejecute. | Que la compatibilidad sea algo que el motor comprueba: una combinación ilegal se rechaza y una legal deja de fallar en CI. | `Governance` | Cross | P2 | M | `DIFERIDO` | @@ -728,7 +728,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | [`GT-706`](./gap-reference-catalog.es.md#gt-706) | **Nada asegura que los `exports` que un paquete declara resuelvan dentro de su propio tarball, así que un productor publica una subruta fantasma y solo la descubre un consumidor — una publicación demasiado tarde.** `contracts@1.1.0` declaró una subruta de export que no incluía; el fallo salió en el smoke de sala limpia de `infra-providers@1.2.1`, **después de que `core-domain@1.3.1` ya estuviera irreversiblemente en el registry**, dejando la release a medio entregar y sin despublicar posible pasadas 72 horas. La comprobación que existe es real y tiene la forma equivocada: `npm-release.yml:213` calcula «prometidos» como `[pkg.main, ...bin]`, y **`exports` no está en esa lista**. FALSABILIDAD DEMOSTRADA, OBSERVADA EN VERDE: un paquete de dos ficheros que declara `"./ingest"` con solo `dist/index.js` en disco pasa esa aserción corrida literal — `exit=0`, mientras `require pkg/ingest` responde `MODULE_NOT_FOUND`. El smoke de sala limpia tampoco lo cubre, y no es defecto suyo: resuelve lo que un paquete IMPORTA, así que el fantasma del productor es invisible hasta el turno de un consumidor, que es después del paso irreversible. Exposición: 3 de 8 paquetes publicables declaran **23 subrutas de export**, ninguna asegurada, y dos declaran además un `./*` sin cota. **ARREGLADO 2026-08-16 — `.harness/scripts/ci/67-validate-declared-exports.mjs`, corriendo en tiempo de PR sobre todos los workspaces publicables Y por paquete dentro del bucle de release, justo antes de `npm publish`.** Recoge cada hoja de texto del árbol de condiciones, así que `types` cuenta tanto como `default`, e incluye `main`/`bin`, siendo un superconjunto de la aserción que sustituye. **La propia afirmación de esta fila sobre el registry la refutó el guard en su primera corrida:** «22 de 22 resuelven, 0 fantasmas» excluía las claves con comodín por su propio filtro, y una está MUERTA — `core-domain` declara `./infrastructure/adapters/*` **sin ningún directorio `adapters`**, 0 coincidencias en un packlist de 796 ficheros, `MODULE_NOT_FOUND` en el 1.3.1 publicado, y **ningún commit de este repositorio llevó jamás ese path**. Borrada, no ampliada: nunca hubo nada detrás. Falsabilidad observada por los dos lados — rojo con la fixture `./ingest`, con `core-domain` de verdad, y con un fichero presente en disco pero excluido por `files`; verde con la misma fixture en cuanto se incluye y con el árbol entero, **68 destinos declarados en 9 paquetes**. | Un paquete puede prometer una ruta de import que nunca incluyó, y quien se entera es el siguiente paquete en publicarse. | La release se niega a publicar un manifiesto que miente, antes de que nada sea irreversible. | `Infra` | Cross | P1 | S | `COMPLETADO` | -**Progreso:** 676 / 706 completados · 3 en progreso · 0 pendientes · 27 diferidos +**Progreso:** 677 / 706 completados · 2 en progreso · 0 pendientes · 27 diferidos **Oleada 2026-06-23 (auditoría profunda de Winston III):** Añadidos 14 gaps nuevos `GT-212`…`GT-225` del Winston Audit Playbook que cubren: higiene de estado ADR (GT-212), metadata + presupuestos operativos + corpus de guías por topología (GT-213, GT-217, GT-219), observabilidad + OpenAPI en controladores REST (GT-214, GT-215), paridad de input-schemas OPA + densidad de tests por topología (GT-216, GT-222), plantillas de rollback + on-call de Fase 05 (GT-218), cobertura de ramas CLI + paridad de envelope --format + limpieza de skip-list (GT-220, GT-224, GT-225), audit logging HTTP de MCP (GT-221), y tests e2e de paridad cross-surface (GT-223). diff --git a/reference/core/control-center/gaps/gap-tracking.md b/reference/core/control-center/gaps/gap-tracking.md index 4bafba69..4a5bf36b 100644 --- a/reference/core/control-center/gaps/gap-tracking.md +++ b/reference/core/control-center/gaps/gap-tracking.md @@ -20,7 +20,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | ID | Gap | In plain terms | What it fixes | Component | Phase | Criticality | Complexity | Status | |---|---|---|---|:---:|:---:|:---:|:---:|:---:| -| [`GT-708`](./gap-reference-catalog.md#gt-708) | **A governance concept that existed only in prose, in two repositories, and was cited as a precondition by a gate that does exist.** «KDD» named two different things and neither was ever built: **Phase 1.1 — Knowledge-First Discovery**, an optional subphase with its own readiness gate and seven artifact templates; and **KDD — Knowledge-Driven Development**, a later reading from the 2026-07-04 owner session (`L-009`, `D-004`) that made it an optional section *inside the PRD*, activated per tenant. **Measured across every executable surface, and absent from all of them:** `phase-gates.rules.json` has five gates for phases 1..5; none of the seven KDD artifacts is among the 33 in `artifact-registry.json`; zero TypeScript files match `KDD`/`knowledge-first`/`knowledgeBrief`/`discoveryReadiness`/`storySeed`/`epicCandidate`; the CLI has 31 commands and zero mentions, and its `--phase discovery` maps to **phase 1 entire** (`phase-id.ts`: `f1: 'discovery'`), not to 1.1; the MCP server has zero; the Tracker has no screen and no entity; and `prd.schema.json` carries no KDD section, so `D-004` never reached a schema either. **The prose had teeth anyway:** `phase-1-business-signoff.md` made *"Phase 1.1 adoption level has been declared"* a **precondition for opening Gate 1**, and three rows of its evidence table carried clauses keyed to KDD levels — a gate nothing implements blocking a gate everything implements. **CLOSED 2026-08-18 by removal, on the owner's decision that Evolith Core and Tracker no longer carry the concept in any form.** 16 files deleted (the Phase 1.1 playbook and the seven artifact templates, EN and ES); Gate 1's precondition and its three KDD-keyed evidence clauses removed; the `Subphase 01.1` table, the playbook index row and the Story-Seed/Epic-Candidate references in the Phase 2 playbook and template index removed; `D-004`/`L-009` rewritten to what survives them — the PRD is the canonical floor and Gate 1 always requires it. **The retirement is [`ADR-0127`](../../architecture/adrs/core/0127-retire-knowledge-first-discovery.md), and `ADR-0103` is AMENDED by it rather than edited:** an accepted Architecture Board decision is superseded, not rewritten, so its reasoning stands and only its neighbour is gone. `CHANGELOG.md` and `ADR-0103` keep their KDD text on purpose — they record what was true when written, and editing them would falsify the history this repository keeps deliberately. **Falsifiability, checked after the sweep rather than inferred from the delete list:** every reference to the eight deleted filenames returns nothing outside the ADR and the correction notice, and `KDD`/`knowledge-first` survive only in the six files named above. **What this row leaves behind is the lesson, not the sweep:** a concept can be cited as a hard precondition by a gate that everything implements while being implemented by nothing, and stay that way for months, because nobody diffs the prose against the data. | A concept we describe everywhere and have built nowhere, which one of our real gates depends on. | The five-phase model reads the same in the docs as in the data, and Gate 1 stops depending on a subphase nobody can execute. | `Governance` | Cross | P2 | M | `IN-PROGRESS` | +| [`GT-708`](./gap-reference-catalog.md#gt-708) | **A governance concept that existed only in prose, in two repositories, and was cited as a precondition by a gate that does exist.** «KDD» named two different things and neither was ever built: **Phase 1.1 — Knowledge-First Discovery**, an optional subphase with its own readiness gate and seven artifact templates; and **KDD — Knowledge-Driven Development**, a later reading from the 2026-07-04 owner session (`L-009`, `D-004`) that made it an optional section *inside the PRD*, activated per tenant. **Measured across every executable surface, and absent from all of them:** `phase-gates.rules.json` has five gates for phases 1..5; none of the seven KDD artifacts is among the 33 in `artifact-registry.json`; zero TypeScript files match `KDD`/`knowledge-first`/`knowledgeBrief`/`discoveryReadiness`/`storySeed`/`epicCandidate`; the CLI has 31 commands and zero mentions, and its `--phase discovery` maps to **phase 1 entire** (`phase-id.ts`: `f1: 'discovery'`), not to 1.1; the MCP server has zero; the Tracker has no screen and no entity; and `prd.schema.json` carries no KDD section, so `D-004` never reached a schema either. **The prose had teeth anyway:** `phase-1-business-signoff.md` made *"Phase 1.1 adoption level has been declared"* a **precondition for opening Gate 1**, and three rows of its evidence table carried clauses keyed to KDD levels — a gate nothing implements blocking a gate everything implements. **CLOSED 2026-08-18 by removal, on the owner's decision that Evolith Core and Tracker no longer carry the concept in any form.** 16 files deleted (the Phase 1.1 playbook and the seven artifact templates, EN and ES); Gate 1's precondition and its three KDD-keyed evidence clauses removed; the `Subphase 01.1` table, the playbook index row and the Story-Seed/Epic-Candidate references in the Phase 2 playbook and template index removed; `D-004`/`L-009` rewritten to what survives them — the PRD is the canonical floor and Gate 1 always requires it. **The retirement is [`ADR-0127`](../../architecture/adrs/core/0127-retire-knowledge-first-discovery.md), and `ADR-0103` is AMENDED by it rather than edited:** an accepted Architecture Board decision is superseded, not rewritten, so its reasoning stands and only its neighbour is gone. `CHANGELOG.md` and `ADR-0103` keep their KDD text on purpose — they record what was true when written, and editing them would falsify the history this repository keeps deliberately. **Falsifiability, checked after the sweep rather than inferred from the delete list:** every reference to the eight deleted filenames returns nothing outside the ADR and the correction notice, and `KDD`/`knowledge-first` survive only in the six files named above. **What this row leaves behind is the lesson, not the sweep:** a concept can be cited as a hard precondition by a gate that everything implements while being implemented by nothing, and stay that way for months, because nobody diffs the prose against the data. **CLOSED 2026-08-18 — both halves landed.** The Tracker half is `evolith_tracker#153` (`97e1bc8e`): `REQ-DIS-12` and `REQ-DIS-13` removed along with the subphase-01.1 governance bullet, the artifact-catalogue section, the blueprint bullet, the Discovery index clauses and the `.bmad-core` blocks. **Both repositories had the same shape of teeth in different words:** the Core made *"Phase 1.1 adoption level has been declared"* a precondition for opening Gate 1, and the Tracker gave `REQ-DIS-13` the acceptance criterion *"a FAIL result blocks opening the Business Sign-Off gate"* — two documents, one non-existent gate, both blocking the only gate every initiative must pass. What survives is deliberate: `CHANGELOG.md` and `ADR-0103` in the Core, and the Tracker's two audit-board rows, all of them records of what was true when written. | A concept we describe everywhere and have built nowhere, which one of our real gates depends on. | The five-phase model reads the same in the docs as in the data, and Gate 1 stops depending on a subphase nobody can execute. | `Governance` | Cross | P2 | M | `DONE` | | [`GT-707`](./gap-reference-catalog.md#gt-707) | **Every standalone binary this repository publishes fails on `--help`, and no release has ever carried one.** Measured 2026-08-18 across all four open pull requests and, before them, on the `v1.3.6` tag push and on the pull request that first made the release pipeline run on pull requests: `smoke-test` and `smoke-test-functional` fail with `ERR_REQUIRE_ESM: require() of ES Module /snapshot/…/@clack/prompts/dist/index.mjs`, raised from `prompt.service.js` — so the binary dies before parsing an argument, on all three platforms. `gh release view` on `v1.3.0` and `v1.1.0` returns **zero assets**: `upload-assets` depends on `smoke-test`, so the channel has never delivered anything, and the pipeline's own gate is what stopped it. **Measured further, so the next attempt starts here:** `@clack/prompts@1.5.1` is the ONLY ESM-only dependency the CLI has (`chalk` 4.1.2, `ora` 5.4.1, `inquirer` 8.2.7 and `cli-table3` are all CommonJS); `esbuild` bundles it to a 107 kB CJS file that loads clean; and packaging with the maintained fork `@yao-pkg/pkg@6` REMOVES the `ERR_REQUIRE_ESM` and then fails differently — `MODULE_NOT_FOUND` for the same `.mjs`, because the file is not in the snapshot — which means the packager and the asset set are two separate defects, not one. **The cheap-looking fix is not cheap:** redirecting the import touches 6 production files and ~24 spec files that `jest.mock('@clack/prompts')` by that exact specifier. **Deliberately NOT fixed inside the four pull requests that found it:** they are green on all 8 required checks and this is a pre-existing failure in a non-required workflow; smuggling a packaging redesign into them would be the unrelated-change-inside-a-promotion this board keeps refusing. **CLOSED 2026-08-18 by vendoring the ESM-only dependencies to CommonJS — and this row's own first evidence was wrong twice, which is the part worth keeping.** The packaged binary now runs: built from this tree, `--help` exits **0**, `--version` prints `1.3.2`, and `init --runtime nodejs --monorepo none --arch clean` exits **0** and writes a satellite. **WRONG #1 — "the only ESM-only dependency".** This row measured that by probing `require('/package.json')`, which eight of the 25 direct dependencies refuse with `ERR_PACKAGE_PATH_NOT_EXPORTED` — an error that reads like "fine". Reading the manifests FROM DISK instead found **three**: `@clack/prompts@1.5.1`, `conf@15.1.0` and `@modelcontextprotocol/sdk@1.29.0`. Two of them are loaded at runtime and both are vendored; the MCP sdk is only a `.d.ts` in this package, so it never enters the snapshot. `pkg` had been telling us about `conf` all along — it dies naming `conf/package.json` and `config.service.js` — and nobody read past the first error. **WRONG #2 — the fallback pointed at nothing.** `clack.ts` compiles to `dist/infrastructure/prompts/` while the bundle is written to `dist/vendor/`, so `require('./vendor/clack.cjs')` resolved to a path that does not exist. Nothing failed at build time; the BINARY failed at run time with the package's own error, because the fallback's `MODULE_NOT_FOUND` was swallowed by a rethrow of the original. Both are now structural fixes rather than corrections: the rethrow names BOTH failures, and `vendor-esm-deps.mjs` reads the relative path out of each COMPILED shim and resolves it — observed red against the broken path, with the resolved location in the message. **What ships:** `scripts/vendor-esm-deps.mjs` bundles each ESM-only dependency with esbuild (clack 107 kB, conf 410 kB), then loads each one back in a child process with `--no-experimental-require-module` — the closest an ordinary Node process gets to the snapshot's no-ESM contract — and compares its export surface against the real package. Two shims (`prompts/clack.ts`, `config/conf-module.ts`) try the PACKAGE FIRST and fall back to the bundle on ANY load failure: the order is what keeps the ~24 specs that `jest.mock('@clack/prompts')` intercepting the same specifier they always did, and "any failure" is because the same cause surfaces as `ERR_REQUIRE_ESM` under one packager and `MODULE_NOT_FOUND` under another. 106 suites / 1485 tests green, `tsc -b` clean. The release pipeline is unchanged: the fix is packager-agnostic, and its `smoke-test` is the falsifiability this row asked for. | The downloadable program we publish crashes instantly, and in fact we have never published one. | Either a standalone binary that runs, or an honest retirement of the channel — not a red check everybody learns to ignore. | `Infra` | Cross | P2 | M | `DONE` | | [`GT-688`](./gap-reference-catalog.md#gt-688) | **A confirmed topology composition is truncated to one id before the gate, so a mixed system gets a green topology verdict for the one topology that survived.** Measured live 2026-08-14 against the built dist: `manifestFromWorkspace` with `design.topologyConfirmedRefs: [modular-monolith, agentic-ai, event-driven]` returns `{"topology":"modular-monolith","facts":{"context":{"topologyRef":"modular-monolith"}}}` — **the other two appear nowhere**. Cause: `evaluation-context.builder.ts:26` `topology: ctx.topologyRef`, and `grep -n "design"` over that whole file returns one hit, a comment at `:149`. **Worse without the scalar:** the manifest carries no `topology` key at all, the kind SKIPs (`kind-evaluators.ts:363`), and the pipeline re-derives one **by regex over the YAML on disk**, first match wins (`satellite-evaluation-pipeline.service.ts:354`). The result contract cannot carry two either (`TopologyEvaluationResult.topologyRef`, required scalar). So the kind returns `PASS, conformant: true` for the id it kept — **a green verdict over a system half of which was never checked**. **The owner observation that produced this row was half REFUTED, and the refuted half matters:** the model is NOT singular — `ADR-0079:44` rejects the exclusive design in writing, transversality is a formal declaration (`maturityLevel: "cross"` on all five non-progressive manifests), and the corpus, satellite contract and design evaluator are plural; `evolith topology phase-artifacts -t agentic-ai,event-driven` really does union both. What survived is the ENFORCEMENT wire. Not covered by `MT-A*`: all 26 rows are DONE and every one is corpus/schema/docs work. | — | — | `Core Domain` | Cross | P1 | L | `DONE` | | [`GT-689`](./gap-reference-catalog.md#gt-689) | **The composition compatibility model has zero runtime readers, and its transversality marker has none at all.** `grep -rn "composableWith" --include=*.ts src/` excluding dist returns two hits, both type declarations, **zero reads**; `metadata.dimension` — the field encoding transversality — has no production reader at all. The single consumer is guard `22-validate-topology-composition.mjs`, and `find . -name topology.composition.json` returns **exactly one** non-worktree file. Three measured consequences: the guard compares every ordered pair so it demands symmetry while the manifests are asymmetric, making `modular-monolith → data-mesh` and `edge-computing → serverless` **fail CI the day anyone writes them down**; `minItems: 2` means the most common documented state, a lone `modular-monolith`, cannot be expressed as a composition at all; and `edge-computing` + `serverless` are both `dimension: execution` yet declare each other composable, which the docs forbid and nothing catches, because nothing reads `dimension`. Registered now rather than after [`GT-688`](./gap-reference-catalog.md#gt-688) because that row is what makes this validation load-bearing. | The rules about which architectures may be combined are written down carefully and consulted by nothing that runs. | Compatibility becomes a property the engine checks, so an illegal combination is refused and a legal one stops failing CI. | `Governance` | Cross | P2 | M | `DEFERRED` | @@ -728,7 +728,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | [`GT-706`](./gap-reference-catalog.md#gt-706) | **Nothing asserts that a package's own declared `exports` resolve inside its own tarball, so a producer publishes a phantom subpath and only a consumer discovers it — one publish too late.** `contracts@1.1.0` declared an export subpath it did not ship; the failure surfaced at `infra-providers@1.2.1`'s clean-room smoke, **after `core-domain@1.3.1` was already irreversibly on the registry**, leaving the release half-shipped with no unpublish available after 72 hours. The check that exists is real and the wrong shape: `npm-release.yml:213` computes "promised" as `[pkg.main, ...bin]`, and **`exports` is not in that list**. PROVEN FALSIFIABLE, OBSERVED GREEN: a two-file package declaring `"./ingest"` with only `dist/index.js` on disk passes that assertion run verbatim — `exit=0`, while `require pkg/ingest` answers `MODULE_NOT_FOUND`. The clean-room smoke does not cover it either, and that is not its defect: it resolves what a package IMPORTS, so a producer's phantom is invisible until a consumer's turn, which is after the irreversible step. Exposure: 3 of 8 publishable packages declare **23 export subpaths**, none asserted, two of them also declaring an unbounded `./*`. **FIXED 2026-08-16 — `.harness/scripts/ci/67-validate-declared-exports.mjs`, run at PR time over every publishable workspace AND per package inside the release loop, immediately before `npm publish`.** It collects every string leaf of the condition tree, so `types` counts as much as `default`, and folds in `main`/`bin`, making it a superset of the assertion it replaces. **The row's own claim about the registry was refuted by the guard on its first run:** "22 of 22 resolve, 0 phantom" excluded wildcard keys by its own filter, and one is DEAD — `core-domain` declares `./infrastructure/adapters/*` with **no `adapters` directory at all**, 0 matches in a 796-file packlist, `MODULE_NOT_FOUND` on the published 1.3.1, and **no commit in this repository ever carried that path**. Deleted, not widened: there was never anything behind it. Falsifiability observed on both sides — red on the `./ingest` fixture, on `core-domain` for real, and on a file present on disk but excluded by `files`; green on the same fixture once it ships and on the whole tree, **68 declared targets across 9 packages**. | A package can promise an import path it never shipped, and the next package to publish is the one that finds out. | The release refuses to publish a manifest that lies, before anything becomes irreversible. | `Infra` | Cross | P1 | S | `DONE` | -**Progress:** 676 / 706 done · 3 in progress · 0 pending · 27 deferred +**Progress:** 677 / 706 done · 2 in progress · 0 pending · 27 deferred **Wave 2026-06-23 (Winston deep audit III):** Added 14 new gaps `GT-212`…`GT-225` from the Winston Audit Playbook covering: ADR status hygiene (GT-212), topology manifest metadata + operational budgets + guidance corpus (GT-213, GT-217, GT-219), REST controller observability + OpenAPI (GT-214, GT-215), OPA input-schema parity + per-topology test density (GT-216, GT-222), SDLC Phase 05 rollback + on-call templates (GT-218), CLI branch coverage + envelope format coverage + skip-list cleanup (GT-220, GT-224, GT-225), MCP HTTP audit logging (GT-221), and cross-surface parity e2e tests (GT-223). diff --git a/reference/core/control-center/maturity-reports/executive-summary.es.md b/reference/core/control-center/maturity-reports/executive-summary.es.md index 2c245fd5..bca7817a 100644 --- a/reference/core/control-center/maturity-reports/executive-summary.es.md +++ b/reference/core/control-center/maturity-reports/executive-summary.es.md @@ -11,7 +11,7 @@ Instantánea estratégica generada desde el tablero canónico de gaps y la recon **Decisión actual:** NO-GO para expansión productiva o release mayor: existen bloqueadores P0 activos. -**Mayor problema ahora:** `Governance` concentra el mayor riesgo abierto ponderado (9 pendientes, 0 P0). Ataca esa concentración antes de ampliar alcance. +**Mayor problema ahora:** `Governance` concentra el mayor riesgo abierto ponderado (8 pendientes, 0 P0). Ataca esa concentración antes de ampliar alcance. **Dónde atacar primero:** [GT-435](../gaps/gap-reference-catalog.es.md#gt-435). @@ -26,10 +26,10 @@ La forma correcta de usar este resumen es simple: si necesitas contexto, abre so | Orden | Foco | Motivo | IDs | |---:|---|---|---| | 1 | Bloqueadores P0 | Impiden afirmar readiness productivo o release mayor. | [GT-435](../gaps/gap-reference-catalog.es.md#gt-435) | -| 2 | Área de mayor riesgo | `Governance` tiene la mayor carga ponderada abierta. | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), [GT-689](../gaps/gap-reference-catalog.es.md#gt-689), [GT-708](../gaps/gap-reference-catalog.es.md#gt-708), +3 | +| 2 | Área de mayor riesgo | `Governance` tiene la mayor carga ponderada abierta. | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), [GT-689](../gaps/gap-reference-catalog.es.md#gt-689), [GT-588](../gaps/gap-reference-catalog.es.md#gt-588), +2 | | 3 | Ganancias rápidas | Alta criticidad con complejidad XS/S. | [GT-684](../gaps/gap-reference-catalog.es.md#gt-684) | | 4 | Ola P1 | Endurecimiento siguiente después de limpiar P0. | [GT-684](../gaps/gap-reference-catalog.es.md#gt-684), [GT-324](../gaps/gap-reference-catalog.es.md#gt-324), [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-680](../gaps/gap-reference-catalog.es.md#gt-680), [GT-681](../gaps/gap-reference-catalog.es.md#gt-681), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-448](../gaps/gap-reference-catalog.es.md#gt-448) | -| 5 | P2/P3 | Solo después de estabilizar seguridad, CI, reglas y contratos. | [GT-444](../gaps/gap-reference-catalog.es.md#gt-444), [GT-464](../gaps/gap-reference-catalog.es.md#gt-464), [GT-674](../gaps/gap-reference-catalog.es.md#gt-674), [GT-685](../gaps/gap-reference-catalog.es.md#gt-685), [GT-686](../gaps/gap-reference-catalog.es.md#gt-686), [GT-687](../gaps/gap-reference-catalog.es.md#gt-687), +11 | +| 5 | P2/P3 | Solo después de estabilizar seguridad, CI, reglas y contratos. | [GT-444](../gaps/gap-reference-catalog.es.md#gt-444), [GT-464](../gaps/gap-reference-catalog.es.md#gt-464), [GT-674](../gaps/gap-reference-catalog.es.md#gt-674), [GT-685](../gaps/gap-reference-catalog.es.md#gt-685), [GT-686](../gaps/gap-reference-catalog.es.md#gt-686), [GT-687](../gaps/gap-reference-catalog.es.md#gt-687), +10 | ## Bloqueadores Actuales @@ -43,18 +43,18 @@ La forma correcta de usar este resumen es simple: si necesitas contexto, abre so |---|---:| | Fecha canónica del tablero | 2026-08-18 | | Gaps totales | 706 | -| Gaps cerrados | 676 | -| Gaps pendientes | 30 | +| Gaps cerrados | 677 | +| Gaps pendientes | 29 | | P0 abiertos | 1 | | P1 abiertos | 8 | -| P2 abiertos | 17 | -| Cierre total | 95.8% | -| Registros de evidencia de cierre | 658 | +| P2 abiertos | 16 | +| Cierre total | 95.9% | +| Registros de evidencia de cierre | 659 | | Readiness registrado | 4 PASS | | Área | Pendientes | P0 | P1 | Primeros IDs | |---|---:|---:|---:|---| -| `Governance` | 9 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), +5 | +| `Governance` | 8 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.es.md#gt-670), [GT-585](../gaps/gap-reference-catalog.es.md#gt-585), [GT-669](../gaps/gap-reference-catalog.es.md#gt-669), [GT-672](../gaps/gap-reference-catalog.es.md#gt-672), +4 | | `Cross` | 3 | 1 | 1 | [GT-435](../gaps/gap-reference-catalog.es.md#gt-435), [GT-448](../gaps/gap-reference-catalog.es.md#gt-448), [GT-651](../gaps/gap-reference-catalog.es.md#gt-651) | | `MCP Server` | 3 | 0 | 3 | [GT-684](../gaps/gap-reference-catalog.es.md#gt-684), [GT-680](../gaps/gap-reference-catalog.es.md#gt-680), [GT-681](../gaps/gap-reference-catalog.es.md#gt-681) | | `Infra` | 4 | 0 | 1 | [GT-324](../gaps/gap-reference-catalog.es.md#gt-324), [GT-464](../gaps/gap-reference-catalog.es.md#gt-464), [GT-685](../gaps/gap-reference-catalog.es.md#gt-685), [GT-692](../gaps/gap-reference-catalog.es.md#gt-692) | diff --git a/reference/core/control-center/maturity-reports/executive-summary.md b/reference/core/control-center/maturity-reports/executive-summary.md index 7d70eb28..9ec9256a 100644 --- a/reference/core/control-center/maturity-reports/executive-summary.md +++ b/reference/core/control-center/maturity-reports/executive-summary.md @@ -11,7 +11,7 @@ Strategic snapshot generated from the canonical gap board and maturity reconcili **Current decision:** NO-GO for production expansion or a major release: active P0 blockers remain. -**Biggest problem now:** `Governance` carries the highest weighted open risk (9 open, 0 P0). Attack that concentration before expanding scope. +**Biggest problem now:** `Governance` carries the highest weighted open risk (8 open, 0 P0). Attack that concentration before expanding scope. **Where to attack first:** [GT-435](../gaps/gap-reference-catalog.md#gt-435). @@ -26,10 +26,10 @@ Use this summary with a simple rule: if you need context, open only the linked I | Order | Focus | Reason | IDs | |---:|---|---|---| | 1 | P0 blockers | They prevent production-readiness or major-release confidence. | [GT-435](../gaps/gap-reference-catalog.md#gt-435) | -| 2 | Highest-risk area | `Governance` has the largest weighted open load. | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), [GT-689](../gaps/gap-reference-catalog.md#gt-689), [GT-708](../gaps/gap-reference-catalog.md#gt-708), +3 | +| 2 | Highest-risk area | `Governance` has the largest weighted open load. | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), [GT-689](../gaps/gap-reference-catalog.md#gt-689), [GT-588](../gaps/gap-reference-catalog.md#gt-588), +2 | | 3 | Quick wins | High criticality with XS/S complexity. | [GT-684](../gaps/gap-reference-catalog.md#gt-684) | | 4 | P1 wave | Next hardening after P0 is cleared. | [GT-684](../gaps/gap-reference-catalog.md#gt-684), [GT-324](../gaps/gap-reference-catalog.md#gt-324), [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-680](../gaps/gap-reference-catalog.md#gt-680), [GT-681](../gaps/gap-reference-catalog.md#gt-681), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-448](../gaps/gap-reference-catalog.md#gt-448) | -| 5 | P2/P3 | Only after security, CI, rules, and contracts stabilize. | [GT-444](../gaps/gap-reference-catalog.md#gt-444), [GT-464](../gaps/gap-reference-catalog.md#gt-464), [GT-674](../gaps/gap-reference-catalog.md#gt-674), [GT-685](../gaps/gap-reference-catalog.md#gt-685), [GT-686](../gaps/gap-reference-catalog.md#gt-686), [GT-687](../gaps/gap-reference-catalog.md#gt-687), +11 | +| 5 | P2/P3 | Only after security, CI, rules, and contracts stabilize. | [GT-444](../gaps/gap-reference-catalog.md#gt-444), [GT-464](../gaps/gap-reference-catalog.md#gt-464), [GT-674](../gaps/gap-reference-catalog.md#gt-674), [GT-685](../gaps/gap-reference-catalog.md#gt-685), [GT-686](../gaps/gap-reference-catalog.md#gt-686), [GT-687](../gaps/gap-reference-catalog.md#gt-687), +10 | ## Current Blockers @@ -43,18 +43,18 @@ Use this summary with a simple rule: if you need context, open only the linked I |---|---:| | Canonical board date | 2026-08-18 | | Total gaps | 706 | -| Closed gaps | 676 | -| Open gaps | 30 | +| Closed gaps | 677 | +| Open gaps | 29 | | Open P0 | 1 | | Open P1 | 8 | -| Open P2 | 17 | -| Total closure | 95.8% | -| Closure evidence records | 658 | +| Open P2 | 16 | +| Total closure | 95.9% | +| Closure evidence records | 659 | | Recorded readiness | 4 PASS | | Area | Open | P0 | P1 | First IDs | |---|---:|---:|---:|---| -| `Governance` | 9 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), +5 | +| `Governance` | 8 | 0 | 3 | [GT-670](../gaps/gap-reference-catalog.md#gt-670), [GT-585](../gaps/gap-reference-catalog.md#gt-585), [GT-669](../gaps/gap-reference-catalog.md#gt-669), [GT-672](../gaps/gap-reference-catalog.md#gt-672), +4 | | `Cross` | 3 | 1 | 1 | [GT-435](../gaps/gap-reference-catalog.md#gt-435), [GT-448](../gaps/gap-reference-catalog.md#gt-448), [GT-651](../gaps/gap-reference-catalog.md#gt-651) | | `MCP Server` | 3 | 0 | 3 | [GT-684](../gaps/gap-reference-catalog.md#gt-684), [GT-680](../gaps/gap-reference-catalog.md#gt-680), [GT-681](../gaps/gap-reference-catalog.md#gt-681) | | `Infra` | 4 | 0 | 1 | [GT-324](../gaps/gap-reference-catalog.md#gt-324), [GT-464](../gaps/gap-reference-catalog.md#gt-464), [GT-685](../gaps/gap-reference-catalog.md#gt-685), [GT-692](../gaps/gap-reference-catalog.md#gt-692) | diff --git a/reference/core/control-center/maturity-reports/maturity-reconciliation.json b/reference/core/control-center/maturity-reports/maturity-reconciliation.json index 64e02f02..9319ad43 100644 --- a/reference/core/control-center/maturity-reports/maturity-reconciliation.json +++ b/reference/core/control-center/maturity-reports/maturity-reconciliation.json @@ -4,13 +4,13 @@ "asOf": "2026-08-18", "gaps": { "total": 706, - "done": 676, + "done": 677, "pending": 0, - "inProgress": 3, + "inProgress": 2, "deferred": 27 }, "evidence": { - "closureRecords": 658, + "closureRecords": 659, "cliPackage": "@beyondnet/evolith-cli@1.3.2", "adrCount": 142, "rulesetCount": 182, From 8debf0137a50ccb6800377eb91feda9b228477ae Mon Sep 17 00:00:00 2001 From: Alberto Arroyo Raygada Date: Wed, 19 Aug 2026 11:09:13 -0500 Subject: [PATCH 5/5] fix(docker): the runtime images shipped their build tree, and duplicated it on the way out (#625) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Advances GT-692 (DEFERRED -> IN-PROGRESS). The Tracker's Deploy (kind + Helm + smoke) died importing evolith-core-api with 'no space left on device' on /repo/node_modules/get-intrinsic/CHANGELOG.md — the same shape this row registered in July, still biting in another repository. Two causes, and the second was not in the original evidence: 1. The runner received the build tree, compiler included. Fixed with 'npm prune --omit=dev' at the end of every builder stage. 2. Found by reading docker history rather than the Dockerfile: 'RUN … chown -R' is a 586 MB layer on core-api alone, a byte-for-byte duplicate of everything copied above it, because a recursive chown rewrites every file into a new layer. Ownership now travels on COPY --chown. Measured before and after, same tree and same day: core-api 1.96 GB -> 862 MB, agent-runtime-api 2.49 GB -> 1.13 GB, mcp-server 1.89 GB -> 825 MB, cli 2.00 GB -> 890 MB. Total 8.34 GB -> 3.71 GB. Every image was BOOTED, not merely built — and that is what earned the second finding: mcp-server first died with 'Cannot find module keyv', a runtime dependency of @nestjs/cache-manager it never declared, surviving only because eslint hoisted a copy. The prune exposed the defect; it did not create it. 70-validate-runtime-image-shape.mjs keeps both causes fixed and was observed red against the previous Dockerfile, naming line 87. Merged with the non-required 'Governance guards' job stuck ~26 min on an npm install step — the same flakiness seen twice today. All 8 required checks are green. --- .github/workflows/ci-cd.yml | 15 ++ .../ci/70-validate-runtime-image-shape.mjs | 184 ++++++++++++++++++ .../scripts/ci/runtime-image-budgets.json | 43 ++++ package-lock.json | 12 ++ .../gaps/gap-reference-catalog.es.md | 4 +- .../gaps/gap-reference-catalog.md | 8 +- .../control-center/gaps/gap-tracking.es.md | 4 +- .../core/control-center/gaps/gap-tracking.md | 4 +- .../maturity-reconciliation.json | 4 +- src/apps/agent-runtime-api/Dockerfile | 38 ++-- src/apps/core-api/Dockerfile | 60 ++++-- src/packages/mcp-server/Dockerfile | 56 +++--- src/packages/mcp-server/package.json | 1 + src/sdk/cli/Dockerfile | 54 ++--- 14 files changed, 400 insertions(+), 87 deletions(-) create mode 100644 .harness/scripts/ci/70-validate-runtime-image-shape.mjs create mode 100644 .harness/scripts/ci/runtime-image-budgets.json diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d0540df3..537023b6 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -125,6 +125,21 @@ jobs: run: node .harness/scripts/ci/69-validate-audit-transparency-gate.mjs --verbose + # GT-692 — a deployable image must not ship the tree its BUILD needed. + # + # All four images copied the whole workspace `node_modules` into their runtime + # stage and then ran `chown -R` over it, which in Docker rewrites every file + # into a new layer: 586 MB of pure duplicate on core-api alone. The cost was + # paid in ANOTHER repository — the Tracker's `Deploy (kind + Helm + smoke)` + # died importing this image with `no space left on device`. + # + # This checks the SHAPE, which is the cause, in seconds and without Docker. + # The measured sizes live in `runtime-image-budgets.json`; a real size budget + # needs a Docker-building job, and the baseline is written down for the day + # one exists. + - name: Deployable images ship no build tree (GT-692) + run: node .harness/scripts/ci/70-validate-runtime-image-shape.mjs --verbose + # CD gate = the evolith-cli unit suite (fast, deterministic). The full e2e # (env-sensitive: spawns servers, loads rulesets) is covered by the # dedicated sdk-cli-ci.yml e2e job + the per-flow E2E playbooks, not here. diff --git a/.harness/scripts/ci/70-validate-runtime-image-shape.mjs b/.harness/scripts/ci/70-validate-runtime-image-shape.mjs new file mode 100644 index 00000000..b304e21c --- /dev/null +++ b/.harness/scripts/ci/70-validate-runtime-image-shape.mjs @@ -0,0 +1,184 @@ +#!/usr/bin/env node + +/** + * GT-692 — a deployable image must not ship the tree its BUILD needed. + * + * ## What this exists to stop happening again + * + * Every one of this repository's four images copied the whole workspace + * `node_modules` — 659 MB, `typescript`, `eslint`, `jest` and `@types/*` included — + * into its runtime stage, and then ran a recursive `chown -R` over it, which in + * Docker rewrites every file into a NEW layer. Measured on `core-api`: that single + * `RUN` was **586 MB**, a byte-for-byte duplicate of everything above it. + * + * The cost was not hypothetical and it was not paid here. The Tracker's + * `Deploy (kind + Helm + smoke)` job died importing `evolith-core-api` into a kind + * node with `ctr: failed to extract layer … no space left on device`, on paths that + * name the cause outright — `@types/node/quic.d.ts`, `@sinonjs/commons/…` and + * `get-intrinsic/CHANGELOG.md`: two declaration trees and a test-double library + * being unpacked into a production image. + * + * ## What it checks, and what it deliberately does not + * + * It checks the SHAPE of every deployable Dockerfile, which is the cause: + * + * 1. the builder prunes development dependencies before the runner copies them; + * 2. no recursive `chown` over a copied tree — ownership is set by `COPY --chown`. + * + * It does NOT check image size, and that gap is deliberate rather than overlooked. + * A size budget requires building four images, which needs Docker and minutes; this + * guard runs in seconds anywhere. Shape is what regresses when someone adds an image + * by copying an existing Dockerfile — size is the symptom of exactly these two lines. + * The measured sizes are recorded in `runtime-image-budgets.json` so the day a + * Docker-building job wants a budget, the baseline is already written down and not + * re-derived from memory. + * + * ## Anti-vacuous pass + * + * The Dockerfile set is discovered, never listed, and asserted through + * `assertScannedPerSource`: zero Dockerfiles found is a hard failure, because a guard + * that scanned nothing has certified nothing. + * + * Usage: + * node .harness/scripts/ci/70-validate-runtime-image-shape.mjs + * node .harness/scripts/ci/70-validate-runtime-image-shape.mjs --verbose + * + * Exit codes: + * 0 - every deployable image prunes, and none rewrites a copied tree with chown -R + * 1 - an image ships development dependencies, duplicates a tree, or none was found + */ + +import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'; +import { join, relative, resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { REPO_ROOT } from '../lib/paths.mjs'; +import { assertScannedPerSource, ZeroCoverageError } from '../lib/coverage.mjs'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +export const BUDGETS_PATH = resolve(HERE, 'runtime-image-budgets.json'); + +const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.claude']); + +/** Every Dockerfile in the tree, discovered rather than listed. */ +export function findDockerfiles(root) { + const found = []; + (function walk(dir) { + let entries; + try { + entries = readdirSync(dir, { withFileTypes: true }); + } catch { + return; + } + for (const entry of entries) { + const full = join(dir, entry.name); + if (entry.isDirectory()) { + if (SKIP_DIRS.has(entry.name)) continue; + // A nested checkout is not part of this repository's tree (see guard 64). + if (existsSync(join(full, '.git'))) continue; + walk(full); + } else if (entry.name === 'Dockerfile') { + found.push(relative(root, full)); + } + } + })(root); + return found.sort(); +} + +/** + * The two shape rules, applied to one Dockerfile's text. + * + * Pure so the unit test can drive it with strings instead of scaffolding images. + */ +export function inspectShape(text) { + const lines = text.split('\n'); + const findings = []; + + const multiStage = /^FROM\s+\S+\s+AS\s+\w+/im.test(text); + if (!multiStage) { + // A single-stage image has no builder to prune; it is a different shape and this + // guard has nothing to say about it. Reported so the denominator stays honest. + return { findings, applicable: false, prunes: false }; + } + + const prunes = /npm\s+prune\s+--omit=dev|npm\s+ci\s+[^\n]*--omit=dev|npm\s+install\s+[^\n]*--omit=dev/.test(text); + if (!prunes) { + findings.push({ + rule: 'prune', + message: + 'the runner receives the build tree unpruned — add `RUN npm prune --omit=dev` at the end of the ' + + 'builder stage, or install with `--omit=dev`. Shipping `typescript`, `eslint` and `jest` into a ' + + 'runtime image is what exhausted a consumer\'s kind node.', + }); + } + + for (const [i, line] of lines.entries()) { + // `chown -R` inside a RUN duplicates every file it touches into a new layer. + // Ownership belongs on the COPY that writes the files. + if (/^\s*(RUN|&&)?\s*.*\bchown\s+-R\b/.test(line) && !/^\s*#/.test(line)) { + findings.push({ + rule: 'chown', + line: i + 1, + message: + `recursive chown at line ${i + 1} — it rewrites every file into a NEW layer (586 MB on core-api). ` + + 'Create the user before the copies and use `COPY --chown=:` instead.', + }); + } + } + + return { findings, applicable: true, prunes }; +} + +function main() { + const verbose = process.argv.includes('--verbose'); + const root = REPO_ROOT; + + console.log('🐳 Runtime image shape — a deployable image must not ship its build tree (GT-692)'); + + const dockerfiles = findDockerfiles(root); + const budgets = existsSync(BUDGETS_PATH) ? JSON.parse(readFileSync(BUDGETS_PATH, 'utf8')) : { images: [] }; + + try { + assertScannedPerSource( + { Dockerfiles: dockerfiles.length, 'recorded budgets': (budgets.images ?? []).length }, + { what: 'deployable image inputs' }, + ); + } catch (err) { + if (err instanceof ZeroCoverageError) { + console.error(`❌ ${err.message}`); + process.exit(1); + } + throw err; + } + + const problems = []; + let multiStage = 0; + + for (const rel of dockerfiles) { + const { findings, applicable } = inspectShape(readFileSync(resolve(root, rel), 'utf8')); + if (applicable) multiStage += 1; + for (const f of findings) problems.push({ file: rel, ...f }); + if (verbose) { + console.log(` · ${rel}: ${applicable ? (findings.length ? `${findings.length} finding(s)` : 'clean') : 'single-stage, not applicable'}`); + } + } + + console.log(` ${dockerfiles.length} Dockerfile(s) scanned, ${multiStage} multi-stage; ${problems.length} finding(s).`); + console.log( + ` recorded sizes (${budgets.measuredOn ?? 'undated'}): ` + + (budgets.images ?? []).map((i) => `${i.id} ${i.after}`).join(' · '), + ); + + if (problems.length > 0) { + console.error(`❌ ${problems.length} deployable image(s) ship or duplicate what they should not:`); + for (const p of problems) console.error(` - ${p.file}: ${p.message}`); + process.exit(1); + } + + console.log('✓ 70-validate-runtime-image-shape: every multi-stage image prunes, and none rewrites a copied tree.'); + process.exit(0); +} + +if (process.argv[1] && resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url))) { + main(); +} diff --git a/.harness/scripts/ci/runtime-image-budgets.json b/.harness/scripts/ci/runtime-image-budgets.json new file mode 100644 index 00000000..b24cde6b --- /dev/null +++ b/.harness/scripts/ci/runtime-image-budgets.json @@ -0,0 +1,43 @@ +{ + "$comment": [ + "GT-692 — the measured size of every deployable image, before and after the runtime-stage fix.", + "This file is a RECORD, not yet a gate: `70-validate-runtime-image-shape.mjs` checks the two lines", + "that cause the size (prune + no recursive chown) and prints these numbers, but does not build", + "images to compare against them. A real budget check needs a Docker-building job; when one exists,", + "the baseline is already written down here instead of being re-derived from memory.", + "Measured locally with `docker build` on the same tree, same day, same base image." + ], + "measuredOn": "2026-08-19", + "method": "docker build -f -t . ; docker images --format '{{.Size}}'", + "images": [ + { + "id": "core-api", + "dockerfile": "src/apps/core-api/Dockerfile", + "before": "1.96GB", + "after": "862MB", + "boot": "runs; GET /health -> HTTP 200; corpus loaded (413 rules); 0 restarts" + }, + { + "id": "agent-runtime-api", + "dockerfile": "src/apps/agent-runtime-api/Dockerfile", + "before": "2.49GB", + "after": "1.13GB", + "boot": "runs; GET /health -> HTTP 200" + }, + { + "id": "mcp-server", + "dockerfile": "src/packages/mcp-server/Dockerfile", + "before": "1.89GB", + "after": "825MB", + "boot": "runs; 'Evolith MCP HTTP server listening'. NOTE: the prune first exposed `Cannot find module 'keyv'` — a runtime dependency of `@nestjs/cache-manager` that mcp-server never declared. Declared as a production dependency; the prune found the defect, it did not create it." + }, + { + "id": "cli", + "dockerfile": "src/sdk/cli/Dockerfile", + "before": "2.00GB", + "after": "890MB", + "boot": "runs; `--version` -> 1.3.2" + } + ], + "total": { "before": "8.34GB", "after": "3.71GB", "saved": "4.63GB" } +} diff --git a/package-lock.json b/package-lock.json index 02aae385..37fb163d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13445,6 +13445,7 @@ }, "node_modules/json-buffer": { "version": "3.0.1", + "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { @@ -13492,6 +13493,7 @@ }, "node_modules/keyv": { "version": "4.5.4", + "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -17096,6 +17098,7 @@ "class-transformer": "0.5.1", "class-validator": "0.15.1", "fs-extra": "10.1.0", + "keyv": "5.6.0", "nestjs-pino": "4.6.1", "pino": "10.3.1", "pino-pretty": "13.1.3", @@ -17299,6 +17302,15 @@ "url": "https://opencollective.com/eslint" } }, + "src/packages/mcp-server/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "src/packages/mcp-server/node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", diff --git a/reference/core/control-center/gaps/gap-reference-catalog.es.md b/reference/core/control-center/gaps/gap-reference-catalog.es.md index c7b8e93a..13c836ac 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.es.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.es.md @@ -9535,7 +9535,9 @@ La declaración tiene un hueco — un pack que no declara — y el directorio lo - [ ] **FALSABILIDAD, y tiene que ser un ARRANQUE y no un build:** cada imagen afectada se levanta y sirve una petición real después, conforme a [`GT-647`](./gap-reference-catalog.es.md#gt-647), cuyo hallazgo entero fue que una lista de copiado mantenida a mano produce una imagen que compila en verde y muere en tiempo de `require`. - [ ] El job fallido del consumidor se vuelve a ejecutar contra la nueva imagen y la importación termina; se registran tanto el `no space left on device` literal como la ejecución que pasa. - [ ] Un check falla cuando una imagen desplegable crece por encima de un presupuesto declarado, para que la próxima regresión se cace aquí y no en el pipeline de otro. -- **Estado:** `DIFERIDO` +- **Estado:** `EN-PROGRESO` + +**AVANCE 2026-08-19.** Etapas de runtime arregladas en las cuatro imágenes y medidas antes y después sobre el mismo árbol: `core-api` 1,96 GB → **862 MB**, `agent-runtime-api` 2,49 GB → **1,13 GB**, `mcp-server` 1,89 GB → **825 MB**, `cli` 2,00 GB → **890 MB**; total **8,34 GB → 3,71 GB**. Dos causas, y la segunda no estaba en la evidencia original: además de la poda de dependencias de desarrollo, `RUN … chown -R` era una **capa de 586 MB** en `core-api` —un chown recursivo reescribe cada fichero en una capa nueva— y ahora la propiedad viaja en `COPY --chown`. Cada imagen se **arrancó**, no solo se construyó, y esa comprobación destapó `Cannot find module 'keyv'` en `mcp-server`: una dependencia de runtime de `@nestjs/cache-manager` que nunca se declaró y que sobrevivía porque `eslint` hoisteaba una copia. La poda encontró el defecto, no lo creó. `70-validate-runtime-image-shape.mjs` mantiene ambas causas arregladas y se observó en rojo contra el Dockerfile anterior. **Quedan dos criterios abiertos a propósito:** re-ejecutar el job del consumidor exige una imagen que este pull request aún no publica, y un presupuesto de tamaño real necesita un job que construya con Docker — las líneas base están en `runtime-image-budgets.json`. #### GT-693 diff --git a/reference/core/control-center/gaps/gap-reference-catalog.md b/reference/core/control-center/gaps/gap-reference-catalog.md index 79e9288c..ccb0c03e 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.md @@ -9624,12 +9624,12 @@ The declaration has one hole — a pack that does not declare — and the direct - **Principal:** `S` · **Interest:** `MED` · **Basis:** `estimate` - **Provenance:** Registered 2026-08-15 from three consecutive failures of a DIFFERENT repository's CI (`evolith_tracker` PRs #149 and #150) — the defect is ours and it was found by a consumer, which is the shape worth noting: nothing in this repository measures the size of what it publishes. **Deliberately not fixed in the promotion that found it:** pruning the runtime tree changes what every deployable image contains and needs its own verification — [`GT-647`](./gap-reference-catalog.md#gt-647) is the precedent for how a copy-list change breaks an image at startup, and that row's lesson was that the fix must be verified by BOOTING, not by reading the diff. - **Acceptance criteria:** - - [ ] The runtime stage of each deployable image carries production dependencies only, by an `--omit=dev` install or an equivalent, and the mechanism is the same in all of them. - - [ ] The image is measurably smaller, with the before and after sizes recorded — a claim of "smaller" without both numbers does not close this. - - [ ] **FALSIFIABILITY, and it must be a BOOT not a build:** each affected image is started and serves a real request afterwards, per [`GT-647`](./gap-reference-catalog.md#gt-647), whose whole finding was that a hand-maintained copy list produces an image that builds green and dies at `require` time. + - [x] The runtime stage of each deployable image carries production dependencies only, by an `--omit=dev` install or an equivalent, and the mechanism is the same in all of them. **MET, and the same mechanism in all four** — `RUN npm prune --omit=dev --legacy-peer-deps` at the end of every builder stage. Pruned there and not in the runner because the runner has no npm context: it receives `node_modules` by `COPY`. `--omit=dev` walks the whole workspace, so the non-hoisted trees under `src/*/*/node_modules` are pruned with it. + - [x] The image is measurably smaller, with the before and after sizes recorded — a claim of "smaller" without both numbers does not close this. **MET, both numbers for all four, same tree and same day:** `core-api` 1.96 GB → **862 MB**, `agent-runtime-api` 2.49 GB → **1.13 GB**, `mcp-server` 1.89 GB → **825 MB**, `cli` 2.00 GB → **890 MB**; total **8.34 GB → 3.71 GB**. Recorded in `.harness/scripts/ci/runtime-image-budgets.json` with the method. **Half of the saving was not the prune:** `RUN … chown -R` was a 586 MB layer on `core-api` alone — a recursive chown rewrites every file into a new layer — and that cause was not in this row's original evidence. + - [x] **FALSIFIABILITY, and it must be a BOOT not a build:** each affected image is started and serves a real request afterwards, per [`GT-647`](./gap-reference-catalog.md#gt-647), whose whole finding was that a hand-maintained copy list produces an image that builds green and dies at `require` time. **MET — every image was started, not merely built.** `core-api` and `agent-runtime-api` answer `GET /health` with **HTTP 200** (the former loading its full corpus, 413 rules, with 0 restarts); `mcp-server` reaches «Evolith MCP HTTP server listening»; the `cli` image prints `1.3.2`. **The boot is what earned this row its second finding:** `mcp-server` first died with `Cannot find module 'keyv'` — a runtime dependency of `@nestjs/cache-manager` that it never declared, surviving only because `eslint` hoisted a copy of it. Declared as a production dependency, which is what it always was. The prune exposed the defect; it did not create it. - [ ] The consumer's failing job is re-run against the new image and the import completes; the literal `no space left on device` failure and the passing run are both recorded. - [ ] A check fails when a deployable image grows past a declared budget, so the next regression is caught here rather than in someone else's pipeline. -- **Status:** `DEFERRED` +- **Status:** `IN-PROGRESS` #### GT-693 diff --git a/reference/core/control-center/gaps/gap-tracking.es.md b/reference/core/control-center/gaps/gap-tracking.es.md index 705cb89f..e59c34af 100644 --- a/reference/core/control-center/gaps/gap-tracking.es.md +++ b/reference/core/control-center/gaps/gap-tracking.es.md @@ -26,7 +26,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | [`GT-689`](./gap-reference-catalog.es.md#gt-689) | **El modelo de compatibilidad de composiciones no tiene ningún lector en ejecución, y su marcador de transversalidad no tiene ninguno.** `grep -rn "composableWith" --include=*.ts src/` excluyendo dist devuelve dos hits, ambos declaraciones de tipo, **cero lecturas**; `metadata.dimension` —el campo que codifica la transversalidad— no tiene lector alguno en producción. El único consumidor es el guard `22-validate-topology-composition.mjs`, y `find . -name topology.composition.json` devuelve **exactamente un** fichero fuera de worktrees. Tres consecuencias medidas: el guard compara todo par ordenado, así que exige simetría mientras los manifiestos son asimétricos, y por eso `modular-monolith → data-mesh` y `edge-computing → serverless` **fallarían en CI el día que alguien los escriba**; `minItems: 2` impide expresar el estado documentado más común, un `modular-monolith` solo; y `edge-computing` y `serverless` son ambos `dimension: execution` y se declaran componibles, algo que la documentación prohíbe y que nadie caza, porque nadie lee `dimension`. Se registra ahora y no después de [`GT-688`](./gap-reference-catalog.es.md#gt-688) porque es esa fila la que vuelve portante esta validación. | Las reglas sobre qué arquitecturas pueden combinarse están escritas con cuidado y no las consulta nada que se ejecute. | Que la compatibilidad sea algo que el motor comprueba: una combinación ilegal se rechaza y una legal deja de fallar en CI. | `Governance` | Cross | P2 | M | `DIFERIDO` | | [`GT-690`](./gap-reference-catalog.es.md#gt-690) | **Cada ruleset del eje progresivo existe dos veces con contenido distinto, y los manifiestos declaran la copia que el loader nunca lee.** Establecido con `ls` y `diff` —el método que [`GT-75`](./gap-reference-catalog.es.md#gt-75) hizo mal— los tres existen a la vez en `reference/core/architecture/topologies/progressive-axis/` y en `src/rulesets/topologies/progressive-axis/`, difiriendo exactamente en `$schema`, `$id` y el `"topologies": [""]` que añade la copia de `src`. El loader del corpus solo enraíza en `[rulesets]` y `[src,rulesets]` (`rulesets-location.ts:44-47`), así que `reference/` no se escanea jamás — mientras los tres manifiestos declaran la ruta de `reference/`. El `$schema` de esas copias ni resuelve: el directorio de esquemas no existe. **Contradice la afirmación de cierre de `GT-566`** de que «cada topología existe ahora en exactamente UN sitio», que queda anotada en vez de reabierta. | La misma regla vive en dos ficheros con contenidos distintos, y aquel al que apuntan los manifiestos es el que el motor ignora. | Una sola copia por ruleset, para que arreglar una regla una vez la arregle en todas partes. | `Governance` | Cross | P3 | XS | `DIFERIDO` | | [`GT-691`](./gap-reference-catalog.es.md#gt-691) | **Una CVE ALTA vive en una dependencia transitiva que ningún override desplaza, retenida ahí por una pin EXACTA aguas abajo y no por la ausencia de arreglo aguas arriba, y bloquea toda promoción a main.** `CVE-2026-73643` (`js-yaml` 5.2.1, corregida en 5.2.2) **-- y "sin arreglo aguas arriba" era el encuadre equivocado, corregido el 2026-08-16: js-yaml SÍ publicó el arreglo. Lo que no se ha movido es `@nestjs/swagger`, todavía `latest` en 11.4.6 y todavía declarando `"js-yaml": "5.2.1"` exacta; lo único más nuevo son `12.0.0-alpha.*`, y tomar una alpha de NestJS para cerrar una ALTA es peor trato que la propia CVE. Lo que hay que vigilar es por tanto la próxima ESTABLE de @nestjs/swagger, no js-yaml.** entra por UN camino: `@nestjs/swagger@11.4.6` declara `"js-yaml": "5.2.1"` **exacta**, y el lockfile registra esa pin en la entrada de swagger. **Se probaron cuatro formas de override el 2026-08-15, cada una borrando antes las entradas de `js-yaml` del lockfile —la trampa de `GT-636`— y ninguna la mueve:** la general `js-yaml: 4.3.1` ya presente en `package.json`, una clave por rango `js-yaml@^5`, una por especificador exacto `js-yaml@5.2.1`, y la anidada `@nestjs/swagger: { js-yaml: 5.2.2 }`. Las cuatro siguen resolviendo `@nestjs/swagger/node_modules/js-yaml → 5.2.1`. **No hay arreglo aguas arriba** —`11.4.6` es la última estable y el resto son `12.0.0-alpha.*`— y la única resolución que npm SÍ aplicó empuja a swagger a `4.3.1`, un downgrade mayor de una dependencia que pincha exacta. **La vía vulnerable no es alcanzable, medido y no supuesto:** el aviso exige `load()`/`loadAll()` sobre entrada no confiable, y un grep sobre `@nestjs/swagger/dist` devuelve **1 `yaml.dump` y cero `load`** — emite el documento OpenAPI y no parsea nada. `main` y `develop` son IDÉNTICOS en esta dependencia, así que ninguna promoción la introdujo. **Ni arreglada ni descartada aquí a propósito:** el downgrade colaría un riesgo de runtime en una promoción ajena, y un agente no descarta una alerta de seguridad. **CERRADA el 2026-08-18 por el disparador que esta misma fila nombró, dos días después de escribirlo — y el objetivo que nombró estaba equivocado de una forma que merece registrarse: el arreglo llegó como PARCHE sobre `11.4.x`, no como la estable 12 que esta fila decía esperar.** `@nestjs/swagger@11.4.7` (`dist-tags.latest`) declara `"js-yaml": "5.3.0"`. Sin override, sin downgrade y sin dismissal: `src/apps/core-api/package.json` pasó de `11.4.6` a `11.4.7` y el lockfile registra ahora `node_modules/@nestjs/swagger/node_modules/js-yaml` -> `5.3.0`, que es la prueba que esta fila pedía — una entrada de lockfile, no una intención en `package.json`. `npm audit` pasa de 1 alta a **0 altas / 0 críticas**; las 2 moderadas restantes (`hono`, `@hono/node-server`) no guardan relación y son anteriores a esta fila. **El criterio de falsabilidad se volvió a medir en vez de heredarlo:** `@nestjs/swagger/dist` sigue mostrando **1 `yaml.dump` y cero `load`**, y `js-yaml@5.x` sigue teniendo exactamente un consumidor. `tsc -b` limpio; core-api 31 suites / 163 tests en verde. La alerta Dependabot **#76** se cierra cuando el lockfile llegue a la rama por defecto. | Un fallo grave vive en una librería que no podemos actualizar, y la única vía por la que llegamos a ella no usa la parte rota. | Una decisión escrita con disparador, para que main deje de estar bloqueado por un argumento que si no vive en un chat. | `Infra` | Cross | P2 | S | `COMPLETADO` | -| [`GT-692`](./gap-reference-catalog.es.md#gt-692) | **Toda imagen desplegable embarca el árbol completo de dependencias de desarrollo, y es lo bastante grande como para agotar el disco de un runner de CI.** `src/apps/core-api/Dockerfile:20` ejecuta `npm ci --legacy-peer-deps` —el árbol entero, desarrollo incluido— y el stage de runtime lo copia tal cual (`COPY --from=builder /repo/node_modules ./node_modules`), sin `--omit=dev`, sin `prune` y sin una segunda instalación. **Medido en este árbol: `node_modules` ocupa 650 MB**, con `typescript` 24 MB, `eslint` 5,1 MB, `@types/node` 2,5 MB, `@sinonjs/commons` y `jest` — **ninguno dependencia de producción de `core-api`**. **Observado fallando tres veces en el CI de OTRO repositorio:** el `Deploy (kind + Helm + smoke)` del Tracker murió en el PR #149, en su rerun limpio y dos veces en el PR #150, siempre como `ctr: failed to extract layer … no space left on device` importando `evolith-core-api` en el nodo de kind — y las rutas donde murió nombran la causa: `/repo/node_modules/@types/node/quic.d.ts` y `/repo/node_modules/@sinonjs/commons/…`, un fichero de declaraciones y una librería de DOBLES DE TEST desempaquetándose en una imagen de producción. El job falla ANTES de ejercitar nada, así que no verifica nada en ninguna dirección. Lo encontró un consumidor, que es la forma que merece anotarse: aquí nada mide el tamaño de lo que se publica. No arreglado en la promoción que lo encontró — podar cambia lo que contiene cada imagen, y [`GT-647`](./gap-reference-catalog.es.md#gt-647) es el precedente de que eso se verifica ARRANCANDO y no leyendo el diff. | Nuestras imágenes publicadas llevan el compilador, el linter y el framework de tests, y son tan grandes que el CI de otro equipo se queda sin disco al cargar una. | Imágenes que llevan lo que ejecutan: cargan en un runner corriente, se transfieren antes, y dejan de ofrecer a un atacante herramientas que el proceso nunca usa. | `Infra` | Cross | P2 | S | `DIFERIDO` | +| [`GT-692`](./gap-reference-catalog.es.md#gt-692) | **Toda imagen desplegable embarca el árbol completo de dependencias de desarrollo, y es lo bastante grande como para agotar el disco de un runner de CI.** `src/apps/core-api/Dockerfile:20` ejecuta `npm ci --legacy-peer-deps` —el árbol entero, desarrollo incluido— y el stage de runtime lo copia tal cual (`COPY --from=builder /repo/node_modules ./node_modules`), sin `--omit=dev`, sin `prune` y sin una segunda instalación. **Medido en este árbol: `node_modules` ocupa 650 MB**, con `typescript` 24 MB, `eslint` 5,1 MB, `@types/node` 2,5 MB, `@sinonjs/commons` y `jest` — **ninguno dependencia de producción de `core-api`**. **Observado fallando tres veces en el CI de OTRO repositorio:** el `Deploy (kind + Helm + smoke)` del Tracker murió en el PR #149, en su rerun limpio y dos veces en el PR #150, siempre como `ctr: failed to extract layer … no space left on device` importando `evolith-core-api` en el nodo de kind — y las rutas donde murió nombran la causa: `/repo/node_modules/@types/node/quic.d.ts` y `/repo/node_modules/@sinonjs/commons/…`, un fichero de declaraciones y una librería de DOBLES DE TEST desempaquetándose en una imagen de producción. El job falla ANTES de ejercitar nada, así que no verifica nada en ninguna dirección. Lo encontró un consumidor, que es la forma que merece anotarse: aquí nada mide el tamaño de lo que se publica. No arreglado en la promoción que lo encontró — podar cambia lo que contiene cada imagen, y [`GT-647`](./gap-reference-catalog.es.md#gt-647) es el precedente de que eso se verifica ARRANCANDO y no leyendo el diff. **AVANCE 2026-08-19 — las etapas de runtime están arregladas, las cuatro imágenes medidas, y la fila pasa de DIFERIDO a EN-PROGRESO porque dos de sus cinco criterios solo pueden cumplirse cuando esto se publique.** El disparador fue que el job del consumidor volviera a ponerse rojo: el `Deploy (kind + Helm + smoke)` del Tracker murió con `ctr: failed to extract layer … no space left on device`, esta vez sobre `/repo/node_modules/get-intrinsic/CHANGELOG.md` — la misma forma que esta fila registró en julio, seguía mordiendo en otro repositorio. **Dos causas, y la segunda no estaba en la evidencia original.** La primera es la que nombraba la fila: el runner recibe el árbol de build, compilador incluido. La segunda apareció leyendo `docker history` en vez del Dockerfile — `RUN … chown -R evolith:evolith /repo /app` es una **capa de 586 MB** en `core-api`, duplicado byte a byte de todo lo copiado encima, porque un chown recursivo reescribe cada fichero en una capa nueva. La propiedad viaja ahora en `COPY --chown` y el usuario se crea antes de las copias. **Medido, antes y después, mismo árbol y mismo día:** `core-api` 1,96 GB → **862 MB**; `agent-runtime-api` 2,49 GB → **1,13 GB**; `mcp-server` 1,89 GB → **825 MB**; `cli` 2,00 GB → **890 MB**. Total **8,34 GB → 3,71 GB, 4,63 GB menos**. **Cada imagen se ARRANCÓ, no solo se construyó** — `core-api` y `agent-runtime-api` responden `GET /health` con 200, `mcp-server` llega a «MCP HTTP server listening», el CLI imprime `1.3.2`. **Y la poda encontró un defecto real en vez de causarlo:** `mcp-server` murió con `Cannot find module 'keyv'`, dependencia de runtime de `@nestjs/cache-manager` que nunca declaró y que sobrevivía solo porque `eslint` hoisteaba una copia. Declarada como dependencia de producción, que es lo que siempre fue. `70-validate-runtime-image-shape.mjs` mantiene arregladas ambas causas y se OBSERVÓ en rojo contra el Dockerfile anterior, nombrando la línea 87. **Dos criterios quedan abiertos a propósito:** el job del consumidor no se puede re-ejecutar contra una imagen que este pull request aún no ha publicado, y un presupuesto de tamaño de verdad necesita un job que construya con Docker — las líneas base medidas quedan en `runtime-image-budgets.json` para que ese check arranque desde números y no desde la memoria. | Nuestras imágenes publicadas llevan el compilador, el linter y el framework de tests, y son tan grandes que el CI de otro equipo se queda sin disco al cargar una. | Imágenes que llevan lo que ejecutan: cargan en un runner corriente, se transfieren antes, y dejan de ofrecer a un atacante herramientas que el proceso nunca usa. | `Infra` | Cross | P2 | S | `EN-PROGRESO` | | [`GT-693`](./gap-reference-catalog.es.md#gt-693) | **Una compuerta que referencia una política OPA se reporta `passed` mientras las violaciones de esa política se tiran, para 31 de las 39 políticas embarcadas.** `OpaEvaluator` atribuye violaciones por regla en `opa-evaluator.ts:174-185`: una regla en `CONTEXT_AWARE_VIOLATION_PREFIXES` reclama todo lo de su prefijo, y **cualquier otra regla reclama solo las violaciones cuyo id sea IGUAL al id de la regla** — pero el `rules: ["rulesets/opa/.rego"]` de una compuerta se vuelve `opa-` vía `deriveRuleId`, y ninguna política emite un id así. **Contado (2026-08-15, tras corregir un primer escaneo defectuoso): 35 de 39 ficheros `.rego` emiten ids con espacio de nombres y 4 están mapeados**, siendo el cuarto el que añadió `GT-688`. El filtro no casa con nada, la rama cae a `return { rule, result: 'passed' }`, y una política que sí disparó se reporta como conformidad. **Probado, no argumentado:** quitar la entrada `TPC-` de una línea devuelve el caso de atribución de GT-688 de `failed` a `passed` contra un resultado wasm idéntico. Dos restricciones que cualquier arreglo debe respetar, ambas medidas: los ids NO son únicos globalmente (`CLI-RR-01..05` y `TAX-05..11`, 10 de 196 colisionan — recontado el 2026-08-16; el 203 que había aquí nunca se volvió a medir) y cuatro políticas emiten más de un prefijo — así que ni un mapa de prefijos ni un mapa ingenuo de ids bastan. | — | — | `Core Domain` | Cross | P1 | M | `COMPLETADO` | | [`GT-694`](./gap-reference-catalog.es.md#gt-694) | **Doce categorías de política OPA no pueden producir veredicto nunca, porque nadie puebla las facetas de entrada que sus propios schemas exigen.** `OpaEvaluator.validateInput` compila `schemas/.input.schema.json` y rechaza la corrida cuando la entrada no lo satisface. Cruzado el 2026-08-15: **14 facetas requeridas no las emite nunca `opa-input-builder.ts`, en 13 categorías** (registrado como 15/12; remedido al cerrar) — `multiTenancy`, `runtime`, `openCore`, `protocol`, `layers`, `git`, `scorecards`, `coreParity`, `releaseReadiness`, `contracts`, `testing`, `findings`, `ci`, `files`. Confirmado de extremo a extremo sobre una en vez de dejarlo estático: una regla de compuerta `multi-tenancy` contra un satélite real con el bundle real devolvió `failed` con `OPA Input Schema Validation Failed: data/satellite must have required property 'multiTenancy'` — sin llegar nunca a la política. **No es un falso verde, y por eso es P2:** bajo `GT-595` una regla bloqueante que no puede correr se reporta, así que es un fallo PERMANENTE que no lleva información sobre el repositorio y a simple vista no se distingue de una violación real. Además infla lo que el producto aparenta aplicar. **No es `GT-693`:** aquello era un veredicto descartado a la salida; esto es una política a la que no se llega a la entrada. | — | — | `Core Domain` | Cross | P2 | L | `COMPLETADO` | | [`GT-695`](./gap-reference-catalog.es.md#gt-695) | **Once políticas OPA leen campos de entrada que sus propios schemas nunca declaran, así que el llamador no puede descubrir qué enviar y esas reglas disparan para siempre.** Cruzado el 2026-08-15: **21 campos en 10 categorías los lee un `.rego` y no los declara ningún schema** (registrado como 11; recontado al cerrar). Encontrado como lo encontraría un cliente: aportando todos los campos que declara `multi-tenancy.input.schema.json` y viendo que la corrida seguía fallando, porque la política lee `tenantAuditTrailEnabled` y `tenantMigrationPathDefined` para `MTN-06`/`MTN-07` y el schema no menciona ninguno. Una regla que nadie puede satisfacer es indistinguible de una regla que el repositorio viola, y el remedio no está nombrado en ningún sitio que el llamador lea. **P2, dicho en vez de asumido:** `additionalProperties` no está definido en estos schemas, así que los campos extra SÍ se aceptan — el defecto es de descubribilidad, no de rechazo. Nótese `cognitivLoadSurveyCompleted`, una errata que un schema declarado habría cazado el día en que se escribió. **No es `GT-694`:** aquello eran categorías a las que no se podía LLEGAR; esto son campos que no se pueden DESCUBRIR una vez se llega. | — | — | `Core Domain` | Cross | P2 | S | `COMPLETADO` | @@ -728,7 +728,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | [`GT-706`](./gap-reference-catalog.es.md#gt-706) | **Nada asegura que los `exports` que un paquete declara resuelvan dentro de su propio tarball, así que un productor publica una subruta fantasma y solo la descubre un consumidor — una publicación demasiado tarde.** `contracts@1.1.0` declaró una subruta de export que no incluía; el fallo salió en el smoke de sala limpia de `infra-providers@1.2.1`, **después de que `core-domain@1.3.1` ya estuviera irreversiblemente en el registry**, dejando la release a medio entregar y sin despublicar posible pasadas 72 horas. La comprobación que existe es real y tiene la forma equivocada: `npm-release.yml:213` calcula «prometidos» como `[pkg.main, ...bin]`, y **`exports` no está en esa lista**. FALSABILIDAD DEMOSTRADA, OBSERVADA EN VERDE: un paquete de dos ficheros que declara `"./ingest"` con solo `dist/index.js` en disco pasa esa aserción corrida literal — `exit=0`, mientras `require pkg/ingest` responde `MODULE_NOT_FOUND`. El smoke de sala limpia tampoco lo cubre, y no es defecto suyo: resuelve lo que un paquete IMPORTA, así que el fantasma del productor es invisible hasta el turno de un consumidor, que es después del paso irreversible. Exposición: 3 de 8 paquetes publicables declaran **23 subrutas de export**, ninguna asegurada, y dos declaran además un `./*` sin cota. **ARREGLADO 2026-08-16 — `.harness/scripts/ci/67-validate-declared-exports.mjs`, corriendo en tiempo de PR sobre todos los workspaces publicables Y por paquete dentro del bucle de release, justo antes de `npm publish`.** Recoge cada hoja de texto del árbol de condiciones, así que `types` cuenta tanto como `default`, e incluye `main`/`bin`, siendo un superconjunto de la aserción que sustituye. **La propia afirmación de esta fila sobre el registry la refutó el guard en su primera corrida:** «22 de 22 resuelven, 0 fantasmas» excluía las claves con comodín por su propio filtro, y una está MUERTA — `core-domain` declara `./infrastructure/adapters/*` **sin ningún directorio `adapters`**, 0 coincidencias en un packlist de 796 ficheros, `MODULE_NOT_FOUND` en el 1.3.1 publicado, y **ningún commit de este repositorio llevó jamás ese path**. Borrada, no ampliada: nunca hubo nada detrás. Falsabilidad observada por los dos lados — rojo con la fixture `./ingest`, con `core-domain` de verdad, y con un fichero presente en disco pero excluido por `files`; verde con la misma fixture en cuanto se incluye y con el árbol entero, **68 destinos declarados en 9 paquetes**. | Un paquete puede prometer una ruta de import que nunca incluyó, y quien se entera es el siguiente paquete en publicarse. | La release se niega a publicar un manifiesto que miente, antes de que nada sea irreversible. | `Infra` | Cross | P1 | S | `COMPLETADO` | -**Progreso:** 677 / 706 completados · 2 en progreso · 0 pendientes · 27 diferidos +**Progreso:** 677 / 706 completados · 3 en progreso · 0 pendientes · 26 diferidos **Oleada 2026-06-23 (auditoría profunda de Winston III):** Añadidos 14 gaps nuevos `GT-212`…`GT-225` del Winston Audit Playbook que cubren: higiene de estado ADR (GT-212), metadata + presupuestos operativos + corpus de guías por topología (GT-213, GT-217, GT-219), observabilidad + OpenAPI en controladores REST (GT-214, GT-215), paridad de input-schemas OPA + densidad de tests por topología (GT-216, GT-222), plantillas de rollback + on-call de Fase 05 (GT-218), cobertura de ramas CLI + paridad de envelope --format + limpieza de skip-list (GT-220, GT-224, GT-225), audit logging HTTP de MCP (GT-221), y tests e2e de paridad cross-surface (GT-223). diff --git a/reference/core/control-center/gaps/gap-tracking.md b/reference/core/control-center/gaps/gap-tracking.md index 4a5bf36b..82f94b7b 100644 --- a/reference/core/control-center/gaps/gap-tracking.md +++ b/reference/core/control-center/gaps/gap-tracking.md @@ -26,7 +26,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | [`GT-689`](./gap-reference-catalog.md#gt-689) | **The composition compatibility model has zero runtime readers, and its transversality marker has none at all.** `grep -rn "composableWith" --include=*.ts src/` excluding dist returns two hits, both type declarations, **zero reads**; `metadata.dimension` — the field encoding transversality — has no production reader at all. The single consumer is guard `22-validate-topology-composition.mjs`, and `find . -name topology.composition.json` returns **exactly one** non-worktree file. Three measured consequences: the guard compares every ordered pair so it demands symmetry while the manifests are asymmetric, making `modular-monolith → data-mesh` and `edge-computing → serverless` **fail CI the day anyone writes them down**; `minItems: 2` means the most common documented state, a lone `modular-monolith`, cannot be expressed as a composition at all; and `edge-computing` + `serverless` are both `dimension: execution` yet declare each other composable, which the docs forbid and nothing catches, because nothing reads `dimension`. Registered now rather than after [`GT-688`](./gap-reference-catalog.md#gt-688) because that row is what makes this validation load-bearing. | The rules about which architectures may be combined are written down carefully and consulted by nothing that runs. | Compatibility becomes a property the engine checks, so an illegal combination is refused and a legal one stops failing CI. | `Governance` | Cross | P2 | M | `DEFERRED` | | [`GT-690`](./gap-reference-catalog.md#gt-690) | **Each progressive-axis ruleset exists twice with different content, and the manifests declare the copy the loader never reads.** Established by `ls` and `diff` — the method [`GT-75`](./gap-reference-catalog.md#gt-75) got wrong — all three exist at both `reference/core/architecture/topologies/progressive-axis/` and `src/rulesets/topologies/progressive-axis/`, differing in exactly `$schema`, `$id` and the `src` copy adding `"topologies": [""]`. The corpus loader roots only at `[rulesets]` and `[src,rulesets]` (`rulesets-location.ts:44-47`), so `reference/` is never scanned — while all three manifests declare the `reference/` path. Those copies `$schema` does not resolve at all: the schema directory does not exist. **Contradicts `GT-566`s closure claim** that "every topology now exists in exactly ONE place", which is annotated rather than reopened. | The same rule lives in two files with different contents, and the one the manifests point at is the one the engine ignores. | One copy per ruleset, so fixing a rule once fixes it everywhere. | `Governance` | Cross | P3 | XS | `DEFERRED` | | [`GT-691`](./gap-reference-catalog.md#gt-691) | **A HIGH CVE sits in a transitive dependency that no override can move, held there by a downstream EXACT pin rather than by a missing upstream fix, and it blocks every promotion to main.** `CVE-2026-73643` (`js-yaml` 5.2.1, fixed in 5.2.2) **-- and "no upstream fix" was the wrong framing, corrected 2026-08-16: js-yaml SHIPPED the fix. What has not moved is `@nestjs/swagger`, still `latest` at 11.4.6 and still declaring `"js-yaml": "5.2.1"` exactly; the only newer releases are `12.0.0-alpha.*`, and taking a NestJS alpha to close a HIGH is a worse trade than the CVE. The thing to watch is therefore the next STABLE @nestjs/swagger, not js-yaml.** enters through ONE path: `@nestjs/swagger@11.4.6` declares `"js-yaml": "5.2.1"` **exactly**, and the lockfile records that pin on swagger's own entry. **Four override forms were tried on 2026-08-15, each with the `js-yaml` lockfile entries deleted first — the `GT-636` trap — and none moves it:** the blanket `js-yaml: 4.3.1` already in `package.json`, a range key `js-yaml@^5`, a spec key `js-yaml@5.2.1`, and the parent-scoped `@nestjs/swagger: { js-yaml: 5.2.2 }`. All four still resolve `@nestjs/swagger/node_modules/js-yaml → 5.2.1`. **No upstream fix exists** — `11.4.6` is the last stable, the rest are `12.0.0-alpha.*` — and the only resolution npm DID apply pushes swagger onto `4.3.1`, a major downgrade of a dependency it pins exactly. **The vulnerable path is not reachable, measured rather than assumed:** the advisory requires `load()`/`loadAll()` on untrusted input, and a grep over `@nestjs/swagger/dist` returns **1 `yaml.dump` and zero `load`** — it emits the OpenAPI document and parses nothing. `main` and `develop` are IDENTICAL on this dependency, so no promotion ever introduced it. **Deliberately not fixed and not dismissed here:** the downgrade would smuggle a runtime risk into an unrelated promotion, and an agent does not dismiss a security alert. **CLOSED 2026-08-18 by the trigger this row named, two days after it was written — and the target it named was wrong in a way worth recording: the fix arrived as a PATCH on `11.4.x`, not as the stable 12 this row said to wait for.** `@nestjs/swagger@11.4.7` (`dist-tags.latest`) declares `"js-yaml": "5.3.0"`. No override, no downgrade and no dismissal: `src/apps/core-api/package.json` moved `11.4.6` -> `11.4.7` and the lockfile now records `node_modules/@nestjs/swagger/node_modules/js-yaml` -> `5.3.0`, which is the proof this row asked for — a lockfile entry, not a `package.json` intention. `npm audit` goes from 1 high to **0 high / 0 critical**; the 2 remaining moderates (`hono`, `@hono/node-server`) are unrelated and predate this row. **The falsifiability criterion was re-measured rather than inherited:** `@nestjs/swagger/dist` still shows **1 `yaml.dump` and zero `load`**, and `js-yaml@5.x` still has exactly one consumer. `tsc -b` clean; core-api 31 suites / 163 tests green. Dependabot alert **#76** closes when the lockfile reaches the default branch. | A high-severity flaw sits in a library we cannot upgrade, and the only route we can reach it by does not use the broken part. | A written decision with a trigger, so main stops being blocked by an argument that otherwise lives in a chat log. | `Infra` | Cross | P2 | S | `DONE` | -| [`GT-692`](./gap-reference-catalog.md#gt-692) | **Every deployable image ships the full development dependency tree, and it is large enough to exhaust a CI runner's disk.** `src/apps/core-api/Dockerfile:20` runs `npm ci --legacy-peer-deps` — the whole tree, dev included — and the runner stage copies it verbatim (`COPY --from=builder /repo/node_modules ./node_modules`), with no `--omit=dev`, no `prune` and no second install. **Measured on this tree: `node_modules` is 650 MB**, carrying `typescript` 24 MB, `eslint` 5.1 MB, `@types/node` 2.5 MB, `@sinonjs/commons` and `jest` — **none of them a production dependency of `core-api`**. **Observed failing three times in ANOTHER repository's CI:** the Tracker's `Deploy (kind + Helm + smoke)` died on PR #149, on its clean rerun and twice on PR #150, always as `ctr: failed to extract layer … no space left on device` importing `evolith-core-api` into the kind node — and the paths it died on name the cause: `/repo/node_modules/@types/node/quic.d.ts` and `/repo/node_modules/@sinonjs/commons/…`, a declaration file and a TEST-DOUBLE library unpacking into a production image. The job fails BEFORE exercising anything, so it verifies nothing in either direction. Found by a consumer, which is the shape worth noting: nothing here measures the size of what it publishes. Not fixed in the promotion that found it — pruning changes what every image contains, and [`GT-647`](./gap-reference-catalog.md#gt-647) is the precedent that such a fix is verified by BOOTING, not by reading the diff. | Our published images carry the compiler, the linter and the test framework, and they are so big that another team CI runs out of disk trying to load one. | Images that carry what they run: they load on an ordinary runner, transfer faster, and stop offering an attacker tools the process never uses. | `Infra` | Cross | P2 | S | `DEFERRED` | +| [`GT-692`](./gap-reference-catalog.md#gt-692) | **Every deployable image ships the full development dependency tree, and it is large enough to exhaust a CI runner's disk.** `src/apps/core-api/Dockerfile:20` runs `npm ci --legacy-peer-deps` — the whole tree, dev included — and the runner stage copies it verbatim (`COPY --from=builder /repo/node_modules ./node_modules`), with no `--omit=dev`, no `prune` and no second install. **Measured on this tree: `node_modules` is 650 MB**, carrying `typescript` 24 MB, `eslint` 5.1 MB, `@types/node` 2.5 MB, `@sinonjs/commons` and `jest` — **none of them a production dependency of `core-api`**. **Observed failing three times in ANOTHER repository's CI:** the Tracker's `Deploy (kind + Helm + smoke)` died on PR #149, on its clean rerun and twice on PR #150, always as `ctr: failed to extract layer … no space left on device` importing `evolith-core-api` into the kind node — and the paths it died on name the cause: `/repo/node_modules/@types/node/quic.d.ts` and `/repo/node_modules/@sinonjs/commons/…`, a declaration file and a TEST-DOUBLE library unpacking into a production image. The job fails BEFORE exercising anything, so it verifies nothing in either direction. Found by a consumer, which is the shape worth noting: nothing here measures the size of what it publishes. Not fixed in the promotion that found it — pruning changes what every image contains, and [`GT-647`](./gap-reference-catalog.md#gt-647) is the precedent that such a fix is verified by BOOTING, not by reading the diff. **PROGRESS 2026-08-19 — the runtime stages are fixed, all four images measured, and the row moves from DEFERRED to IN-PROGRESS because two of its five criteria can only be met after this ships.** The trigger was the consumer's job going red again: the Tracker's `Deploy (kind + Helm + smoke)` died on `ctr: failed to extract layer … no space left on device`, this time on `/repo/node_modules/get-intrinsic/CHANGELOG.md` — the same shape this row registered in July, still biting in another repository. **Two causes, and the second was not in the original evidence.** The first is the one this row named: the runner receives the build tree, compiler included. The second was found by reading `docker history` instead of the Dockerfile — `RUN … chown -R evolith:evolith /repo /app` is a **586 MB layer** on `core-api`, a byte-for-byte duplicate of everything copied above it, because a recursive chown rewrites every file into a new layer. Ownership now travels on `COPY --chown` and the user is created before the copies. **Measured, before and after, same tree and same day:** `core-api` 1,96 GB → **862 MB**; `agent-runtime-api` 2,49 GB → **1,13 GB**; `mcp-server` 1,89 GB → **825 MB**; `cli` 2,00 GB → **890 MB**. Total **8,34 GB → 3,71 GB, 4,63 GB menos**. **Every image was BOOTED, not just built** — `core-api` and `agent-runtime-api` answer `GET /health` with 200, `mcp-server` reaches «MCP HTTP server listening», the CLI prints `1.3.2`. **And the prune found a real defect rather than causing one:** `mcp-server` died with `Cannot find module 'keyv'`, a runtime dependency of `@nestjs/cache-manager` that it never declared and that survived only because `eslint` happened to hoist a copy. Declared as a production dependency, which is what it always was. `70-validate-runtime-image-shape.mjs` keeps both causes fixed and was OBSERVED red against the previous Dockerfile, naming line 87. **Two criteria remain open on purpose:** the consumer's job cannot be re-run against an image this pull request has not published yet, and a real size budget needs a Docker-building job — the measured baselines are recorded in `runtime-image-budgets.json` so that check starts from numbers rather than from memory. | Our published images carry the compiler, the linter and the test framework, and they are so big that another team CI runs out of disk trying to load one. | Images that carry what they run: they load on an ordinary runner, transfer faster, and stop offering an attacker tools the process never uses. | `Infra` | Cross | P2 | S | `IN-PROGRESS` | | [`GT-693`](./gap-reference-catalog.md#gt-693) | **A gate that references an OPA policy is reported `passed` while the policy's violations are thrown away, for 31 of the 39 shipped policies.** `OpaEvaluator` attributes violations per rule at `opa-evaluator.ts:174-185`: a rule in `CONTEXT_AWARE_VIOLATION_PREFIXES` claims everything with its prefix, and **every other rule claims only violations whose id EQUALS the rule id** — but a gate's `rules: ["rulesets/opa/.rego"]` becomes `opa-` via `deriveRuleId`, and no policy emits an id like that. **Counted (2026-08-15, after correcting a faulty first scan): 35 of 39 `.rego` files emit namespaced ids and 4 are mapped**, the fourth being the one `GT-688` added. The filter matches nothing, the branch falls through to `return { rule, result: 'passed' }`, and a policy that fired is reported as conformance. **Proven, not argued:** removing the one-line `TPC-` entry turns the GT-688 attribution case from `failed` back to `passed` against an unchanged wasm result. Two constraints any fix must respect, both measured: ids are NOT globally unique (`CLI-RR-01..05` and `TAX-05..11`, 10 of 196 collide — recounted 2026-08-16, the 203 here was never re-measured) and four policies emit more than one prefix — so neither a prefix map nor a naive id map suffices. | — | — | `Core Domain` | Cross | P1 | M | `DONE` | | [`GT-694`](./gap-reference-catalog.md#gt-694) | **Twelve OPA policy categories can never produce a verdict, because nothing populates the input facets their own schemas require.** `OpaEvaluator.validateInput` compiles `schemas/.input.schema.json` and rejects the run when the input does not satisfy it. Cross-checked 2026-08-15: **14 required facets are never emitted by `opa-input-builder.ts`, across 13 categories** (registered as 15/12; re-measured on closure) — `multiTenancy`, `runtime`, `openCore`, `protocol`, `layers`, `git`, `scorecards`, `coreParity`, `releaseReadiness`, `contracts`, `testing`, `findings`, `ci`, `files`. Confirmed end to end on one rather than left static: a `multi-tenancy` gate rule against a real satellite through the real bundle returned `failed` with `OPA Input Schema Validation Failed: data/satellite must have required property 'multiTenancy'` — never reaching the policy. **Not a false pass, and P2 for that reason:** under `GT-595` a blocking rule that cannot run is reported, so this is a PERMANENT failure carrying no information about the repository, indistinguishable at a glance from a real violation. It also inflates what the product appears to enforce. **Not `GT-693`:** that was a verdict discarded on the way out; this is a policy never reached on the way in. | — | — | `Core Domain` | Cross | P2 | L | `DONE` | | [`GT-695`](./gap-reference-catalog.md#gt-695) | **Eleven OPA policies read input fields their own schemas never declare, so a caller cannot discover what to send and those rules fire forever.** Cross-checked 2026-08-15: **21 fields across 10 categories are read by a `.rego` and declared by no schema** (registered as 11; re-counted on closure). Found the way a customer would find it — supplying every field `multi-tenancy.input.schema.json` declares and watching the run still fail, because the policy reads `tenantAuditTrailEnabled` and `tenantMigrationPathDefined` for `MTN-06`/`MTN-07` and the schema mentions neither. A rule nobody can satisfy is indistinguishable from a rule the repository violates, and the remedy is named nowhere the caller reads. **P2, stated rather than assumed:** `additionalProperties` is undefined on these schemas so the extra fields ARE accepted — the defect is discoverability, not rejection. Note `cognitivLoadSurveyCompleted`, a typo a declared schema would have caught the day it was written. **Not `GT-694`:** that was categories that could not be REACHED; this is fields that cannot be DISCOVERED once they are. | — | — | `Core Domain` | Cross | P2 | S | `DONE` | @@ -728,7 +728,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | [`GT-706`](./gap-reference-catalog.md#gt-706) | **Nothing asserts that a package's own declared `exports` resolve inside its own tarball, so a producer publishes a phantom subpath and only a consumer discovers it — one publish too late.** `contracts@1.1.0` declared an export subpath it did not ship; the failure surfaced at `infra-providers@1.2.1`'s clean-room smoke, **after `core-domain@1.3.1` was already irreversibly on the registry**, leaving the release half-shipped with no unpublish available after 72 hours. The check that exists is real and the wrong shape: `npm-release.yml:213` computes "promised" as `[pkg.main, ...bin]`, and **`exports` is not in that list**. PROVEN FALSIFIABLE, OBSERVED GREEN: a two-file package declaring `"./ingest"` with only `dist/index.js` on disk passes that assertion run verbatim — `exit=0`, while `require pkg/ingest` answers `MODULE_NOT_FOUND`. The clean-room smoke does not cover it either, and that is not its defect: it resolves what a package IMPORTS, so a producer's phantom is invisible until a consumer's turn, which is after the irreversible step. Exposure: 3 of 8 publishable packages declare **23 export subpaths**, none asserted, two of them also declaring an unbounded `./*`. **FIXED 2026-08-16 — `.harness/scripts/ci/67-validate-declared-exports.mjs`, run at PR time over every publishable workspace AND per package inside the release loop, immediately before `npm publish`.** It collects every string leaf of the condition tree, so `types` counts as much as `default`, and folds in `main`/`bin`, making it a superset of the assertion it replaces. **The row's own claim about the registry was refuted by the guard on its first run:** "22 of 22 resolve, 0 phantom" excluded wildcard keys by its own filter, and one is DEAD — `core-domain` declares `./infrastructure/adapters/*` with **no `adapters` directory at all**, 0 matches in a 796-file packlist, `MODULE_NOT_FOUND` on the published 1.3.1, and **no commit in this repository ever carried that path**. Deleted, not widened: there was never anything behind it. Falsifiability observed on both sides — red on the `./ingest` fixture, on `core-domain` for real, and on a file present on disk but excluded by `files`; green on the same fixture once it ships and on the whole tree, **68 declared targets across 9 packages**. | A package can promise an import path it never shipped, and the next package to publish is the one that finds out. | The release refuses to publish a manifest that lies, before anything becomes irreversible. | `Infra` | Cross | P1 | S | `DONE` | -**Progress:** 677 / 706 done · 2 in progress · 0 pending · 27 deferred +**Progress:** 677 / 706 done · 3 in progress · 0 pending · 26 deferred **Wave 2026-06-23 (Winston deep audit III):** Added 14 new gaps `GT-212`…`GT-225` from the Winston Audit Playbook covering: ADR status hygiene (GT-212), topology manifest metadata + operational budgets + guidance corpus (GT-213, GT-217, GT-219), REST controller observability + OpenAPI (GT-214, GT-215), OPA input-schema parity + per-topology test density (GT-216, GT-222), SDLC Phase 05 rollback + on-call templates (GT-218), CLI branch coverage + envelope format coverage + skip-list cleanup (GT-220, GT-224, GT-225), MCP HTTP audit logging (GT-221), and cross-surface parity e2e tests (GT-223). diff --git a/reference/core/control-center/maturity-reports/maturity-reconciliation.json b/reference/core/control-center/maturity-reports/maturity-reconciliation.json index 9319ad43..5cf739dc 100644 --- a/reference/core/control-center/maturity-reports/maturity-reconciliation.json +++ b/reference/core/control-center/maturity-reports/maturity-reconciliation.json @@ -6,8 +6,8 @@ "total": 706, "done": 677, "pending": 0, - "inProgress": 2, - "deferred": 27 + "inProgress": 3, + "deferred": 26 }, "evidence": { "closureRecords": 659, diff --git a/src/apps/agent-runtime-api/Dockerfile b/src/apps/agent-runtime-api/Dockerfile index 3f4a508e..9d20a6d5 100644 --- a/src/apps/agent-runtime-api/Dockerfile +++ b/src/apps/agent-runtime-api/Dockerfile @@ -35,6 +35,13 @@ RUN test -f src/apps/agent-runtime-api/dist/main.js || { \ echo " Check that .dockerignore still excludes **/*.tsbuildinfo."; \ exit 1; } + +# GT-692 — the runner receives the tree the BUILD needed, compiler included. Pruned +# here because the runner has no npm context: it gets `node_modules` by COPY, and +# `--omit=dev` walks the whole workspace so the non-hoisted trees are pruned with it. +# Build artifacts are already emitted, so removing the compiler cannot affect them. +RUN npm prune --omit=dev --legacy-peer-deps + # ── Runner ────────────────────────────────────────────────────────────────── FROM node:20-alpine AS runner @@ -48,25 +55,28 @@ WORKDIR /repo # Workspace symlinks in node_modules/@beyondnet/evolith-* point at packages/*, so we ship # the compiled dist + package.json of each needed workspace plus the hoisted # third-party modules. -COPY --from=builder /repo/node_modules ./node_modules -COPY --from=builder /repo/package.json ./package.json -COPY --from=builder /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist -COPY --from=builder /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json -COPY --from=builder /repo/src/packages/agent-runtime/dist ./src/packages/agent-runtime/dist -COPY --from=builder /repo/src/packages/agent-runtime/package.json ./src/packages/agent-runtime/package.json -COPY --from=builder /repo/src/apps/agent-runtime-api/dist ./src/apps/agent-runtime-api/dist -COPY --from=builder /repo/src/apps/agent-runtime-api/package.json ./src/apps/agent-runtime-api/package.json +# GT-692 — the user is created BEFORE the copies so `COPY --chown` can name it. A +# recursive `chown -R` at the end rewrites every file into a NEW layer: measured on +# `core-api`, that single RUN was 586 MB, a byte-for-byte duplicate of everything +# above it. +RUN addgroup -g 1001 -S evolith && \ + adduser -S evolith -u 1001 -G evolith + +COPY --from=builder --chown=evolith:evolith /repo/node_modules ./node_modules +COPY --from=builder --chown=evolith:evolith /repo/package.json ./package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/agent-runtime/dist ./src/packages/agent-runtime/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/agent-runtime/package.json ./src/packages/agent-runtime/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/apps/agent-runtime-api/dist ./src/apps/agent-runtime-api/dist +COPY --from=builder --chown=evolith:evolith /repo/src/apps/agent-runtime-api/package.json ./src/apps/agent-runtime-api/package.json # Optional corpus so the real .harness / OPA adapters can be enabled by env # (AGENT_RUNTIME_HARNESS_ROOT / AGENT_RUNTIME_OPA_*) without rebuilding. Copied # from the builder stage so the bundled OPA binary and policy.wasm match the # container platform, not the developer host. -COPY --from=builder /repo/.harness ./corpus/.harness -COPY --from=builder /repo/src/rulesets ./corpus/rulesets - -RUN addgroup -g 1001 -S evolith && \ - adduser -S evolith -u 1001 -G evolith && \ - chown -R evolith:evolith /repo +COPY --from=builder --chown=evolith:evolith /repo/.harness ./corpus/.harness +COPY --from=builder --chown=evolith:evolith /repo/src/rulesets ./corpus/rulesets USER evolith diff --git a/src/apps/core-api/Dockerfile b/src/apps/core-api/Dockerfile index d1828ffc..7b65d60a 100644 --- a/src/apps/core-api/Dockerfile +++ b/src/apps/core-api/Dockerfile @@ -40,6 +40,28 @@ RUN test -f src/apps/core-api/dist/main.js || { \ echo " .dockerignore still excludes **/*.tsbuildinfo."; \ exit 1; } +# GT-692 — the runner receives the tree the BUILD needed, and the build needs a +# compiler. Measured on this repository: `node_modules` is 659 MB and the image it +# produced was 1.96 GB, carrying `typescript`, `eslint`, `jest` and `@types/*` — +# none of them a production dependency of `core-api`. That is not merely wasteful: +# it is what made a consumer's CI fail. The Tracker's `Deploy (kind + Helm + smoke)` +# job died importing this image into a kind node with +# `ctr: failed to extract layer … no space left on device`, on the paths that name +# the cause outright — `@types/node/quic.d.ts`, `@sinonjs/commons/…` and +# `get-intrinsic/CHANGELOG.md`, a test-double library and two declaration trees +# being unpacked into a production image. +# +# Pruned HERE and not in the runner because the runner has no npm context: it +# receives `node_modules` by COPY. `--omit=dev` walks the whole workspace, so the +# non-hoisted trees under `src/apps/*/node_modules` are pruned with it. +# +# The build artifacts are already emitted at this point, so removing the compiler +# cannot affect them. What it CAN affect is a runtime dependency mis-declared as a +# development one — which is a defect this prune exposes rather than causes, and +# `56-validate-docker-workspace-closure` plus the container's own boot are what +# catch it. +RUN npm prune --omit=dev --legacy-peer-deps + # ── Runner ────────────────────────────────────────────────────────────────── FROM node:20-alpine AS runner @@ -48,10 +70,18 @@ LABEL org.opencontainers.image.source="https://github.com/beyondnetcode/evolith_ RUN apk add --no-cache curl +# GT-692 — the user is created BEFORE the copies on purpose. The image used to end +# with `chown -R evolith:evolith /repo /app`, and in Docker a recursive chown rewrites +# every file it touches into a NEW layer: measured on this image, that single RUN was +# **586 MB**, a byte-for-byte duplicate of everything copied above it. `COPY --chown` +# sets the ownership as the layer is written, so the duplicate never exists. +RUN addgroup -g 1001 -S evolith && \ + adduser -S evolith -u 1001 -G evolith + WORKDIR /repo -COPY --from=builder /repo/node_modules ./node_modules -COPY --from=builder /repo/package.json ./package.json +COPY --from=builder --chown=evolith:evolith /repo/node_modules ./node_modules +COPY --from=builder --chown=evolith:evolith /repo/package.json ./package.json # The workspace closure the entrypoint requires, TRANSITIVELY. `contracts` is # here because infra-providers/dist/tracker/evaluation-ingest.client.js requires # `@beyondnet/evolith-contracts/ingest`, and that require is re-exported from @@ -59,16 +89,16 @@ COPY --from=builder /repo/package.json ./package.json # node_modules entry is a workspace SYMLINK into src/packages/contracts, so # shipping node_modules without the package's own dist yields a dangling link # and MODULE_NOT_FOUND at startup. Guard: 56-validate-docker-workspace-closure. -COPY --from=builder /repo/src/packages/contracts/dist ./src/packages/contracts/dist -COPY --from=builder /repo/src/packages/contracts/package.json ./src/packages/contracts/package.json -COPY --from=builder /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist -COPY --from=builder /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json -COPY --from=builder /repo/src/packages/infra-providers/dist ./src/packages/infra-providers/dist -COPY --from=builder /repo/src/packages/infra-providers/package.json ./src/packages/infra-providers/package.json -COPY --from=builder /repo/src/apps/core-api/dist ./src/apps/core-api/dist -COPY --from=builder /repo/src/apps/core-api/package.json ./src/apps/core-api/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/contracts/dist ./src/packages/contracts/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/contracts/package.json ./src/packages/contracts/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/infra-providers/dist ./src/packages/infra-providers/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/infra-providers/package.json ./src/packages/infra-providers/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/apps/core-api/dist ./src/apps/core-api/dist +COPY --from=builder --chown=evolith:evolith /repo/src/apps/core-api/package.json ./src/apps/core-api/package.json # Non-hoisted workspace deps (e.g. @nestjs/cache-manager) live here, not at root. -COPY --from=builder /repo/src/apps/core-api/node_modules ./src/apps/core-api/node_modules +COPY --from=builder --chown=evolith:evolith /repo/src/apps/core-api/node_modules ./src/apps/core-api/node_modules # Corpus (rulesets + generated OPA WASM + human reference) the Core reads at # runtime. rulesets comes from the builder stage so policy.wasm is present even @@ -79,12 +109,8 @@ COPY --from=builder /repo/src/apps/core-api/node_modules ./src/apps/core-api/nod # WorkspaceReferenceResolverService.corePath()). CORE_PATH=/app/corpus, so the # rulesets tree must live at /app/corpus/rulesets (NOT /app/corpus/src/rulesets) # or OPA fail-closes on a missing policy.wasm/schema in production. -COPY --from=builder /repo/src/rulesets /app/corpus/rulesets -COPY reference /app/corpus/reference - -RUN addgroup -g 1001 -S evolith && \ - adduser -S evolith -u 1001 -G evolith && \ - chown -R evolith:evolith /repo /app +COPY --from=builder --chown=evolith:evolith /repo/src/rulesets /app/corpus/rulesets +COPY --chown=evolith:evolith reference /app/corpus/reference USER evolith diff --git a/src/packages/mcp-server/Dockerfile b/src/packages/mcp-server/Dockerfile index 109684b2..d9649c03 100644 --- a/src/packages/mcp-server/Dockerfile +++ b/src/packages/mcp-server/Dockerfile @@ -40,6 +40,13 @@ RUN test -f src/packages/mcp-server/dist/main.js || { \ echo " Check that .dockerignore still excludes **/*.tsbuildinfo."; \ exit 1; } + +# GT-692 — the runner receives the tree the BUILD needed, compiler included. Pruned +# here because the runner has no npm context: it gets `node_modules` by COPY, and +# `--omit=dev` walks the whole workspace so the non-hoisted trees are pruned with it. +# Build artifacts are already emitted, so removing the compiler cannot affect them. +RUN npm prune --omit=dev --legacy-peer-deps + # ── Runner ────────────────────────────────────────────────────────────────── FROM node:20-alpine AS runner @@ -50,34 +57,41 @@ RUN apk add --no-cache curl WORKDIR /repo -COPY --from=builder /repo/node_modules ./node_modules -COPY --from=builder /repo/package.json ./package.json +# GT-692 — the user is created BEFORE the copies so `COPY --chown` can name it. A +# recursive `chown -R` at the end rewrites every file into a NEW layer: measured on +# `core-api`, that single RUN was 586 MB, a byte-for-byte duplicate of everything +# above it. +RUN addgroup -g 1001 -S evolith && \ + adduser -S evolith -u 1001 -G evolith + +COPY --from=builder --chown=evolith:evolith /repo/node_modules ./node_modules +COPY --from=builder --chown=evolith:evolith /repo/package.json ./package.json # `contracts` reaches this image through infra-providers, whose index re-exports # tracker/evaluation-ingest.client.js and its require of # `@beyondnet/evolith-contracts/ingest`. node_modules/@beyondnet/evolith-contracts # is a workspace SYMLINK into src/packages/contracts, so without the package's own # dist the link dangles and the server dies at startup with MODULE_NOT_FOUND. # Guard: 56-validate-docker-workspace-closure. -COPY --from=builder /repo/src/packages/contracts/dist ./src/packages/contracts/dist -COPY --from=builder /repo/src/packages/contracts/package.json ./src/packages/contracts/package.json -COPY --from=builder /repo/src/packages/sdk-client/dist ./src/packages/sdk-client/dist -COPY --from=builder /repo/src/packages/sdk-client/package.json ./src/packages/sdk-client/package.json -COPY --from=builder /repo/src/packages/agent-runtime/dist ./src/packages/agent-runtime/dist -COPY --from=builder /repo/src/packages/agent-runtime/package.json ./src/packages/agent-runtime/package.json -COPY --from=builder /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist -COPY --from=builder /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json -COPY --from=builder /repo/src/packages/infra-providers/dist ./src/packages/infra-providers/dist -COPY --from=builder /repo/src/packages/infra-providers/package.json ./src/packages/infra-providers/package.json -COPY --from=builder /repo/src/packages/core/dist ./src/packages/core/dist -COPY --from=builder /repo/src/packages/core/package.json ./src/packages/core/package.json -COPY --from=builder /repo/src/packages/mcp-server/dist ./src/packages/mcp-server/dist -COPY --from=builder /repo/src/packages/mcp-server/package.json ./src/packages/mcp-server/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/contracts/dist ./src/packages/contracts/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/contracts/package.json ./src/packages/contracts/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/sdk-client/dist ./src/packages/sdk-client/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/sdk-client/package.json ./src/packages/sdk-client/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/agent-runtime/dist ./src/packages/agent-runtime/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/agent-runtime/package.json ./src/packages/agent-runtime/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/infra-providers/dist ./src/packages/infra-providers/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/infra-providers/package.json ./src/packages/infra-providers/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core/dist ./src/packages/core/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core/package.json ./src/packages/core/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/mcp-server/dist ./src/packages/mcp-server/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/mcp-server/package.json ./src/packages/mcp-server/package.json # Non-hoisted workspace deps (e.g. @nestjs/cache-manager) live here, not at root. -COPY --from=builder /repo/src/packages/mcp-server/node_modules ./src/packages/mcp-server/node_modules +COPY --from=builder --chown=evolith:evolith /repo/src/packages/mcp-server/node_modules ./src/packages/mcp-server/node_modules # Ruleset corpus, copied from the BUILDER stage so the compiled policy.wasm # (a gitignored build artifact) is included — the host context does not have it. -COPY --from=builder /repo/src/rulesets /app/corpus/rulesets +COPY --from=builder --chown=evolith:evolith /repo/src/rulesets /app/corpus/rulesets # The MCP ABAC evaluator (abac-evaluator.ts) resolves the wasm at # `/sdk/cli/rulesets/opa/policy.wasm`, where corePath is derived in @@ -85,11 +99,7 @@ COPY --from=builder /repo/src/rulesets /app/corpus/rulesets # `packages/mcp-server`. The runtime WORKDIR is /repo/src/packages/mcp-server, so # corePath = /repo/src and the reader opens /repo/src/sdk/cli/rulesets/opa/policy.wasm. # Without this the OPA layer fail-closes in production and denies every tool call. -COPY --from=builder /repo/src/sdk/cli/rulesets/opa/policy.wasm ./src/sdk/cli/rulesets/opa/policy.wasm - -RUN addgroup -g 1001 -S evolith && \ - adduser -S evolith -u 1001 -G evolith && \ - chown -R evolith:evolith /repo /app +COPY --from=builder --chown=evolith:evolith /repo/src/sdk/cli/rulesets/opa/policy.wasm ./src/sdk/cli/rulesets/opa/policy.wasm USER evolith diff --git a/src/packages/mcp-server/package.json b/src/packages/mcp-server/package.json index b62f8fbd..134ee136 100644 --- a/src/packages/mcp-server/package.json +++ b/src/packages/mcp-server/package.json @@ -61,6 +61,7 @@ "class-transformer": "0.5.1", "class-validator": "0.15.1", "fs-extra": "10.1.0", + "keyv": "5.6.0", "nestjs-pino": "4.6.1", "pino": "10.3.1", "pino-pretty": "13.1.3", diff --git a/src/sdk/cli/Dockerfile b/src/sdk/cli/Dockerfile index 111a131e..e9e8976a 100644 --- a/src/sdk/cli/Dockerfile +++ b/src/sdk/cli/Dockerfile @@ -43,6 +43,13 @@ RUN npx tsc -b tsconfig.json && \ npm run copy-rulesets --workspace @beyondnet/evolith-cli && \ npm run copy-assets --workspace @beyondnet/evolith-cli + +# GT-692 — the runner receives the tree the BUILD needed, compiler included. Pruned +# here because the runner has no npm context: it gets `node_modules` by COPY, and +# `--omit=dev` walks the whole workspace so the non-hoisted trees are pruned with it. +# Build artifacts are already emitted, so removing the compiler cannot affect them. +RUN npm prune --omit=dev --legacy-peer-deps + # ── Runner ────────────────────────────────────────────────────────────────── FROM node:20-alpine AS runner @@ -54,42 +61,45 @@ RUN apk add --no-cache bash git WORKDIR /repo -COPY --from=builder /repo/node_modules ./node_modules -COPY --from=builder /repo/package.json ./package.json +# GT-692 — the user is created BEFORE the copies so `COPY --chown` can name it. A +# recursive `chown -R` at the end rewrites every file into a NEW layer: measured on +# `core-api`, that single RUN was 586 MB, a byte-for-byte duplicate of everything +# above it. +RUN addgroup -g 1001 -S evolith && \ + adduser -S evolith -u 1001 -G evolith + +COPY --from=builder --chown=evolith:evolith /repo/node_modules ./node_modules +COPY --from=builder --chown=evolith:evolith /repo/package.json ./package.json # `contracts` is a TRANSITIVE dependency, reached through infra-providers, whose # index re-exports tracker/evaluation-ingest.client.js and its require of # `@beyondnet/evolith-contracts/ingest`. node_modules/@beyondnet/evolith-contracts # is a workspace SYMLINK into src/packages/contracts, so omitting the package's own # dist leaves a dangling link and MODULE_NOT_FOUND on the first governance command. # Guard: 56-validate-docker-workspace-closure. -COPY --from=builder /repo/src/packages/contracts/dist ./src/packages/contracts/dist -COPY --from=builder /repo/src/packages/contracts/package.json ./src/packages/contracts/package.json -COPY --from=builder /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist -COPY --from=builder /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json -COPY --from=builder /repo/src/packages/infra-providers/dist ./src/packages/infra-providers/dist -COPY --from=builder /repo/src/packages/infra-providers/package.json ./src/packages/infra-providers/package.json -COPY --from=builder /repo/src/packages/agent-runtime/dist ./src/packages/agent-runtime/dist -COPY --from=builder /repo/src/packages/agent-runtime/package.json ./src/packages/agent-runtime/package.json -COPY --from=builder /repo/src/packages/sdk-client/dist ./src/packages/sdk-client/dist -COPY --from=builder /repo/src/packages/sdk-client/package.json ./src/packages/sdk-client/package.json -COPY --from=builder /repo/src/sdk/cli/dist ./src/sdk/cli/dist -COPY --from=builder /repo/src/sdk/cli/package.json ./src/sdk/cli/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/contracts/dist ./src/packages/contracts/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/contracts/package.json ./src/packages/contracts/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/dist ./src/packages/core-domain/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/core-domain/package.json ./src/packages/core-domain/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/infra-providers/dist ./src/packages/infra-providers/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/infra-providers/package.json ./src/packages/infra-providers/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/agent-runtime/dist ./src/packages/agent-runtime/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/agent-runtime/package.json ./src/packages/agent-runtime/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/packages/sdk-client/dist ./src/packages/sdk-client/dist +COPY --from=builder --chown=evolith:evolith /repo/src/packages/sdk-client/package.json ./src/packages/sdk-client/package.json +COPY --from=builder --chown=evolith:evolith /repo/src/sdk/cli/dist ./src/sdk/cli/dist +COPY --from=builder --chown=evolith:evolith /repo/src/sdk/cli/package.json ./src/sdk/cli/package.json # The asset trees the CLI reads at runtime, produced by copy-rulesets / # copy-assets above. `rulesets/` carries the compiled policy.wasm, which is a # gitignored build artifact and therefore absent from the host context. -COPY --from=builder /repo/src/sdk/cli/rulesets ./src/sdk/cli/rulesets -COPY --from=builder /repo/src/sdk/cli/shell ./src/sdk/cli/shell -COPY --from=builder /repo/src/sdk/cli/templates ./src/sdk/cli/templates +COPY --from=builder --chown=evolith:evolith /repo/src/sdk/cli/rulesets ./src/sdk/cli/rulesets +COPY --from=builder --chown=evolith:evolith /repo/src/sdk/cli/shell ./src/sdk/cli/shell +COPY --from=builder --chown=evolith:evolith /repo/src/sdk/cli/templates ./src/sdk/cli/templates # The corpus the governance commands read: rulesets from the BUILDER stage (so # the compiled policy.wasm is present) plus the human-readable reference tree. -COPY --from=builder /repo/src/rulesets /app/corpus/rulesets +COPY --from=builder --chown=evolith:evolith /repo/src/rulesets /app/corpus/rulesets COPY reference /app/corpus/reference -RUN addgroup -g 1001 -S evolith && \ - adduser -S evolith -u 1001 -G evolith && \ - chown -R evolith:evolith /repo /app - USER evolith ENV NODE_ENV=production