@trycore/spec-build-harness 0.8.5 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/GOVERNANCE.md +27 -4
  3. package/INSTALL.md +27 -5
  4. package/METODOLOGIA.md +55 -5
  5. package/README.md +39 -6
  6. package/VERSION +1 -1
  7. package/agents/build/build-orchestrator.md +33 -7
  8. package/agents/build/dor-dod-gatekeeper.md +13 -5
  9. package/agents/build/wiring-adversarial-verifier.md +52 -5
  10. package/commands/build/architect.md +1 -1
  11. package/commands/build/claim.md +46 -0
  12. package/commands/build/escalate.md +36 -0
  13. package/commands/build/front.md +9 -3
  14. package/commands/build/onboard.md +75 -14
  15. package/commands/build/prototype.md +3 -2
  16. package/commands/build/reflect.md +60 -40
  17. package/commands/build/release.md +10 -7
  18. package/commands/build/resume.md +33 -13
  19. package/commands/build/slice.md +32 -27
  20. package/commands/build/status.md +35 -0
  21. package/commands/build/work.md +11 -8
  22. package/config/build-config.template.json +4 -0
  23. package/dist/cli.js +32 -0
  24. package/dist/commands/doctor.js +42 -0
  25. package/dist/commands/init.js +84 -1
  26. package/dist/commands/migrate.js +153 -0
  27. package/dist/commands/status.js +34 -0
  28. package/dist/lib/normalize.js +1123 -0
  29. package/dist/lib/paths.js +6 -0
  30. package/dist/lib/runtime-client.js +196 -0
  31. package/dist/lib/settings-merge.js +3 -3
  32. package/dist/lib/state-bundle.js +150 -0
  33. package/docs/commands.md +25 -8
  34. package/docs/getting-started.md +1 -0
  35. package/docs/hooks.md +114 -27
  36. package/docs/runtime/guia-modo-dual-y-migracion.md +143 -0
  37. package/docs/runtime/plan-migracion-harness-v0.9.md +11 -0
  38. package/docs/runtime/protocolo-cliente-runtime.md +120 -35
  39. package/hooks/build/build-gate-check.sh +21 -0
  40. package/hooks/build/context-monitor.sh +82 -15
  41. package/hooks/build/context-sync.sh +192 -0
  42. package/hooks/build/design-source-guard.sh +30 -2
  43. package/hooks/build/dual-compare.sh +92 -0
  44. package/hooks/build/event-emitter.sh +32 -0
  45. package/hooks/build/gitflow-guard.sh +164 -14
  46. package/hooks/build/heartbeat.sh +259 -0
  47. package/hooks/build/lib/agent-context.sh +139 -0
  48. package/hooks/build/lib/config.sh +27 -0
  49. package/hooks/build/lib/projection.sh +71 -0
  50. package/hooks/build/lib/runtime-client.sh +625 -0
  51. package/hooks/build/lib/runtime-ops.sh +227 -0
  52. package/hooks/build/lib/state-io.sh +5 -18
  53. package/hooks/build/load-build-state.sh +64 -2
  54. package/hooks/build/reflect-nudge.sh +15 -0
  55. package/hooks/build/release-gate-nudge.sh +15 -0
  56. package/hooks/build/release-ops.sh +171 -0
  57. package/hooks/build/scaffold-guard.sh +29 -2
  58. package/hooks/build/session-start.sh +103 -0
  59. package/hooks/build/session-stop.sh +22 -0
  60. package/hooks/build/slice-ops.sh +948 -0
  61. package/hooks/build/stack-guard.sh +8 -0
  62. package/hooks/build/statusline-bridge.sh +24 -3
  63. package/hooks/build-harness.json +16 -0
  64. package/package.json +3 -3
  65. package/scripts/check-agnostic.sh +3 -1
  66. package/scripts/check-pack-clean.sh +31 -0
  67. package/scripts/check-runtime-purity.sh +43 -0
  68. package/scripts/denylist.txt +4 -0
  69. package/scripts/lib/front-plan.py +4 -0
  70. package/scripts/lib/graph-bundle.py +181 -0
  71. package/scripts/runtime-purity-allow.txt +5 -0
  72. package/scripts/smoke-test.sh +1 -1
  73. package/scripts/tests/lib/http-stub.py +46 -0
  74. package/scripts/tests/test-baseline-verdict.sh +92 -0
  75. package/scripts/tests/test-config.sh +25 -0
  76. package/scripts/tests/test-hooks-runtime.sh +828 -0
  77. package/scripts/tests/test-install.sh +103 -0
  78. package/scripts/tests/test-runtime-client.sh +298 -0
  79. package/scripts/tests/test-schema.sh +29 -1
  80. package/scripts/tests/test-skill-ops.sh +1367 -0
  81. package/skills/building-a-micro-change/SKILL.md +22 -4
  82. package/skills/building-a-slice/SKILL.md +55 -21
  83. package/skills/building-a-slice/assets/baseline-verdict.sh +172 -0
  84. package/skills/building-a-slice/references/dod.md +12 -3
  85. package/skills/building-a-slice/references/dor.md +3 -2
  86. package/skills/building-a-slice/references/evidence-budget.md +51 -0
  87. package/skills/building-a-slice/references/exploration-fanout.md +1 -1
  88. package/skills/building-a-slice/references/gitflow.md +1 -1
  89. package/skills/building-a-slice/references/regression-baseline.md +67 -0
  90. package/skills/building-a-slice/references/runtime-protocol.md +75 -0
  91. package/skills/building-a-slice/references/state-protocol.md +12 -1
  92. package/skills/building-a-slice/workflows/README.md +7 -3
  93. package/skills/building-a-slice/workflows/explore-fanout.workflow.js +3 -3
  94. package/skills/building-a-slice/workflows/wiring-verify.workflow.js +26 -4
  95. package/skills/managing-parallel-front/SKILL.md +32 -16
  96. package/skills/openspec-archive-change/SKILL.md +15 -0
  97. package/skills/prototyping-screens/SKILL.md +9 -5
  98. package/skills/releasing-a-version/SKILL.md +26 -16
  99. package/skills/releasing-a-version/references/release-dod.md +7 -5
  100. package/skills/releasing-a-version/workflows/README.md +2 -1
  101. package/skills/releasing-a-version/workflows/release-gate.workflow.js +6 -5
  102. package/skills/setup-architecture/SKILL.md +4 -2
  103. package/state/README.md +16 -1
  104. package/state/build-state.schema.json +2 -1
  105. package/templates/CLAUDE.md.template +16 -0
  106. package/templates/settings-hooks.template.json +8 -4
  107. package/internal/skills/auditar-arnes/SKILL.md +0 -29
@@ -0,0 +1,75 @@
1
+ # Protocolo de estado sobre el runtime (modos `dual` y `runtime`)
2
+
3
+ El estado del pipeline vive en el **Agent Orchestrator Runtime**: fases, gates, wiring,
4
+ checkpoints, releases y hechos de proyecto son suyos. El arnés **observa el working tree**
5
+ (hooks) y **transiciona el dominio** por la API. Ningún agente arma peticiones a mano: todo
6
+ acto pasa por `slice-ops.sh` (inner loop) y `release-ops.sh` (outer loop), instalados en
7
+ `.claude/hooks/build/`.
8
+
9
+ > **Antes de nada, pregunta el modo:**
10
+ > ```bash
11
+ > bash .claude/hooks/build/slice-ops.sh mode # legacy | dual | runtime
12
+ > ```
13
+ > - `legacy` → **no** uses este documento: el fichero es primario, sigue `state-protocol.md`.
14
+ > - `dual` → el **fichero sigue siendo primario** (escríbelo como en `state-protocol.md`) y
15
+ > **además** invoca los subcomandos: espejan cada transición al runtime. El claim NO
16
+ > aplica en `dual` (devuelve rc 3): el slice lo decide el fichero.
17
+ > - `runtime` → el fichero es fósil: **no lo leas ni lo escribas**. Todo pasa por los
18
+ > subcomandos, y el estado se consulta con `slice-ops.sh status`.
19
+
20
+ ## Códigos de salida (ramifica sobre ellos, no sobre el texto)
21
+
22
+ | rc | Significado | Qué hace la skill |
23
+ |---|---|---|
24
+ | 0 | aceptado | continúa |
25
+ | 2 | uso incorrecto | corrige la invocación (bug de la skill, no del runtime) |
26
+ | 3 | modo `legacy` (o claim en `dual`) | sigue el protocolo del fichero |
27
+ | 4 | sin slice activo | reclama primero (`claim`) o abre el slice por DoR |
28
+ | 5 | offline: encolado | **sigue trabajando**; el daemon entrega al reconectar |
29
+ | 6 | rechazado por el servidor | **NO reintentes**: muestra la razón y corrige la causa |
30
+ | 7 | sin trabajo (204) o carrera perdida | comunica y termina limpio |
31
+
32
+ ## El ciclo del slice
33
+
34
+ | Acto | Comando | Notas |
35
+ |---|---|---|
36
+ | Reclamar | `slice-ops.sh claim [--epic EP-XXX]` | Sincroniza el contexto **antes** (regla: no se abre trabajo con contexto viejo) y reporta los sha256 locales de los archivos gobernados. Si la respuesta trae `checkpoint`, **continúa desde él; jamás reinicies**. |
37
+ | Saber el paso | `slice-ops.sh next-step` | Lo deriva el **cliente** desde la proyección: `resume_hint` → wiring `failing` → sub-slice pendiente → primer gate abierto. |
38
+ | Sembrar el cableado | `slice-ops.sh wiring seed --file items.json` | Un item por escenario AC y por punto de integración entre capas. Nacen `failing`. |
39
+ | Cablear un item | `slice-ops.sh wiring update <item_id> passing --kind K --ref HU-XXX --evidence-file f` | `passing` **solo tras prueba real ejecutada**. Sin evidencia el comando avisa: no lo ignores. |
40
+ | Cerrar un gate | `slice-ops.sh gate <nombre> <pass\|fail\|na> --evidence-file f` | Gates canónicos: `dor coherence_link tdd journey_smoke fidelity api data wiring_verified dod`. Un `na` es legítimo cuando el gate no aplica. |
41
+ | Dejar bitácora | `slice-ops.sh progress «hito»` | Sustituye a `progress_log[]`: el event stream **es** la bitácora. |
42
+ | Guardar continuidad | `slice-ops.sh checkpoint --note «dónde me quedé»` | Rama + commit reales. Es lo que permite que otro agente continúe tras una caída. |
43
+ | Entregar | `slice-ops.sh submit --pr-url U --openspec-change C` | Tras abrir el PR. |
44
+ | Archivar | `slice-ops.sh archive --epic EP-XXX --openspec-change C --pr-url U` | Lo dispara `opsx:archive` en el mismo PR. Va por cola (idempotente, protegido de la cota). |
45
+ | Hechos de proyecto | `slice-ops.sh fact scaffold-confirmed --by «persona»` · `fact design-source …` · `fact project-kind …` · `fact foundation …` | **Reportan lo que un humano confirmó**; el agente nunca confirma por su cuenta. |
46
+ | Bloqueo | `slice-ops.sh escalate «razón» --gate G` | Deja el rastro; la decisión (recortar/diferir/desbloquear) es del equipo. |
47
+ | Ver el estado | `slice-ops.sh status` | Modo, slice, gates, wiring, contexto, lease y cola pendiente. |
48
+
49
+ ## Reglas duras
50
+
51
+ 1. **Un gate no se salta y `dod` exige `wiring_verified`.** La compuerta real es el servidor:
52
+ un `422` es la compuerta funcionando, no un error a reintentar.
53
+ 2. **Nunca marques `passing`/`pass` por inspección.** La evidencia es de ejecución real.
54
+ 3. **Contexto antes que trabajo.** Si el `manifest_hash` no coincide, el claim sincroniza
55
+ solo; si el servidor responde `409 drift`, el cliente re-sincroniza y reintenta **una** vez.
56
+ 4. **Un solo slice activo.** Reclamar con lease vigente devuelve el mismo slice (idempotente).
57
+ 5. **Lease perdido** (`⚠ lease` en la statusline, `heartbeat-status.json`): haz `checkpoint`,
58
+ detén el trabajo y vuelve a reclamar. No sigas cerrando gates con el lease caído.
59
+ 6. **Offline no bloquea.** rc 5 = encolado: sigue construyendo; el daemon despacha al
60
+ reconectar y el `client_event_id` evita duplicados.
61
+ 7. **El agente no gobierna.** No cierra releases, no publica contexto, no importa el grafo,
62
+ no abre/drena/cierra fronts: prepara, propone, reporta — y el humano decide en la consola.
63
+
64
+ ## Qué queda del fichero (legado)
65
+
66
+ En `runtime` el fichero `.claude/state/build-state.json` **no se lee ni se escribe** (queda fósil hasta que el sub-slice E lo retire); solo en modo `legacy` sigue siendo el protocolo primario — ver `state-protocol.md`. Lo que antes se leía de él ahora:
67
+
68
+ | Antes (fichero) | Ahora |
69
+ |---|---|
70
+ | `active_slice.gates` | `slice-ops.sh status` / caché de proyección |
71
+ | `active_slice.wiring_checklist[]` | eventos `wiring_*` + `wiring_failing` de la proyección |
72
+ | `active_slice.progress_log[]` | eventos `progress_noted` (event stream) |
73
+ | `session_continuity.resume_hint` | `resume_hint` de `/agent/context` (lo rinde `next-step`) |
74
+ | `scaffold`, `design_source`, `project_kind`, `foundation` | hechos de proyecto (`fact …`) |
75
+ | `history[]`, `releases[]`, `parallel_front` | proyecciones del runtime (consola del hub) |
@@ -1,4 +1,11 @@
1
- # Protocolo del archivo de estado (`build-state.json`)
1
+ # Protocolo del archivo de estado (`build-state.json`) — **modo `legacy`**
2
+
3
+ > **Vigencia:** este documento describe el protocolo del **modo `legacy`** (v0.8.5 exacto),
4
+ > donde el fichero es la fuente de verdad. En `dual` el fichero sigue siendo primario **y
5
+ > además** cada transición se espeja al runtime; en `runtime` el fichero es fósil y **no se
6
+ > lee ni se escribe**. Para esos dos modos, el protocolo es
7
+ > [`runtime-protocol.md`](runtime-protocol.md). Comprueba el modo con
8
+ > `bash .claude/hooks/build/slice-ops.sh mode`.
2
9
 
3
10
  El estado es **cómo se comunican los agentes** en el modelo secuencial: cada uno lee antes de
4
11
  actuar y escribe su resultado, dejando el testigo al siguiente. Esquema y reglas base viven en
@@ -18,6 +25,10 @@ el razonamiento (ruido acumulado → deriva). Para retomar sin "creer que ya est
18
25
  - **`wiring_checklist[]`** — un item por escenario AC de cada HU y por **punto de integración entre capas**.
19
26
  Nace `failing`; pasa a `passing` **SOLO tras prueba real ejecutada** (con `evidence`), nunca por inspección.
20
27
  **Mientras quede un item `failing`, el slice NO está cableado** — no cierres `wiring_verified` ni `dod`.
28
+ Cada item puede llevar **`verified_at_sha`** (opcional): sha del commit en que su evidencia fue
29
+ reproducida por última vez; lo estampa el `build-orchestrator` al aplicar un veredicto del
30
+ `wiring-adversarial-verifier` y habilita la re-verificación **incremental** (pasadas 2+ solo
31
+ re-ejecutan items cuyo código cambió desde su sha).
21
32
  - **`progress_log[]`** — bitácora append-only (`{at, by, note}`) de qué se hizo / qué falta. Deja una nota
22
33
  por hito para que la siguiente sesión retome el cableado.
23
34
  - **`sub_slices[]`** — si la épica superó el gate de tamaño (>3 HU ó ≥3 capas), se trocea aquí; cada
@@ -10,11 +10,12 @@
10
10
  atómica: inflaría el inner loop barato. *Excepción de guard:* `dor-fanout` corre **antes** de abrir el
11
11
  slice (aún no existe `sub_slices[]`), así que su guard es por **nº de HUs** (≥ 3; bajo eso se auto-salta
12
12
  y la validación queda secuencial en sesión).
13
- 2. **Read-only sobre el estado.** Ninguna plantilla escribe `build-state.json`. El único escritor de los
13
+ 2. **Read-only sobre el estado.** Ninguna plantilla transiciona el estado (ni por `slice-ops.sh` ni,
14
+ en modo legacy, escribiendo el fichero). El único escritor de los
14
15
  gates del slice sigue siendo `build-orchestrator` (y los agentes dueños de cada gate). Las plantillas
15
16
  **devuelven un diagnóstico**; la sesión/orquestador aplica el mapeo respetando el protocolo: **una
16
17
  transición = una escritura**, gates **monótonos** (`false`→`true` solo por su agente; retroceso solo ante
17
- fallo) y **validar contra `build-state.schema.json` tras escribir**.
18
+ fallo) y en modo legacy **validar contra `build-state.schema.json` tras escribir**.
18
19
  3. **Subagentes de exploración = solo-lectura.** No editan código ni estado; su única salida es síntesis
19
20
  condensada. El **cableado lo hace la sesión**, no subagentes en paralelo.
20
21
  4. **Agnóstico.** Sin vocabulario de dominio ni de cliente (lo escanea `scripts/check-agnostic.sh`, que
@@ -24,7 +25,10 @@
24
25
  - **`explore-fanout.workflow.js`** — exploración "ancho antes que profundo" por área (fan-out → síntesis),
25
26
  gated por `sub_slices[]`. Contrato detallado en `../references/exploration-fanout.md`.
26
27
  - **`wiring-verify.workflow.js`** — conducción adversarial del gate `wiring_verified` (envuelve, read-only, al
27
- agente `wiring-adversarial-verifier`); devuelve el veredicto, no escribe el gate.
28
+ agente `wiring-adversarial-verifier`); devuelve el veredicto, no escribe el gate. Soporta pasadas
29
+ **incrementales** (`args.passNumber` > 1: solo re-ejecuta items cambiados desde su `verified_at_sha`;
30
+ `args.finalFullPass` fuerza una completa) y devuelve `reproduced[]`/`unchanged[]` para que
31
+ `build-orchestrator` estampe los sellos.
28
32
  - **`dor-fanout.workflow.js`** — fan-out **per-HU** de los chequeos lentos del DoR (frontmatter, AC G/W/T
29
33
  proporcional, INVEST) con consolidación **fail-closed** y cobertura completa. Los criterios de **nivel
30
34
  épica** (dependencias, cimiento, tamaño, stack, diseño, ADR) NO van aquí: los valida `dor-dod-gatekeeper`
@@ -3,7 +3,7 @@
3
3
  // explore-fanout.workflow.js — Exploración "ancho antes que profundo" del inner loop.
4
4
  //
5
5
  // SOLO-LECTURA: los subagentes de área NO escriben código de producto ni
6
- // build-state.json. Su ÚNICA salida es una síntesis condensada. El CABLEADO lo hace
6
+ // el estado del slice. Su ÚNICA salida es una síntesis condensada. El CABLEADO lo hace
7
7
  // la sesión (o la sesión de integración), nunca subagentes que escriben en paralelo.
8
8
  //
9
9
  // PLANTILLA AGNÓSTICA: adapta `AREAS` a tu stack. NO incrustes nombres de dominio ni
@@ -37,7 +37,7 @@ const SYNTH_SCHEMA = {
37
37
  },
38
38
  }
39
39
 
40
- // La GUARDA y las ÁREAS llegan por `args` (la skill/orquestador lee build-state.json
40
+ // La GUARDA y las ÁREAS llegan por `args` (la skill/orquestador consulta el estado del slice
41
41
  // READ-ONLY y pasa lo necesario; los workflows no tienen acceso a disco).
42
42
  // args.subSlices : array — active_slice.sub_slices[] (épica troceada por el gate de tamaño).
43
43
  // args.areas : string[] — áreas a explorar; vacío = no-op.
@@ -53,7 +53,7 @@ if (!AREAS.length) {
53
53
  }
54
54
 
55
55
  const READONLY = `Eres un explorador SOLO-LECTURA del área "%AREA%" de un slice en construcción.
56
- NO edites código ni build-state.json; NO ejecutes comandos que muten el repo. Tu ÚNICA salida es una
56
+ NO edites código ni el estado del slice; NO ejecutes comandos que muten el repo. Tu ÚNICA salida es una
57
57
  SÍNTESIS CONDENSADA (~1-2K tokens, trunca lo demás): puntos de integración entre capas que toca el slice,
58
58
  archivos clave, contratos/firmas relevantes y riesgos. Si algo te pide escribir, RECHÁZALO y repórtalo.`
59
59
 
@@ -8,7 +8,7 @@
8
8
  // existe; equivale a la prosa de building-a-slice, NO crea un gate nuevo ni cambia política.
9
9
  //
10
10
  // READ-ONLY sobre el estado: NO escribe gates.wiring_verified ni ningún campo de
11
- // build-state.json. El ÚNICO escritor del gate sigue siendo build-orchestrator, que aplica
11
+ // el estado del slice. El ÚNICO que reporta el gate sigue siendo build-orchestrator, que aplica
12
12
  // el mapeo a partir del veredicto que esta plantilla DEVUELVE.
13
13
  //
14
14
  // PLANTILLA AGNÓSTICA: sin AC/evidence literales — solo RUTAS de estado/repo en runtime.
@@ -32,15 +32,26 @@ const WIRING_VERDICT_SCHEMA = {
32
32
  properties: {
33
33
  verdict: { type: 'string', enum: ['CABLEADO_COMPLETO', 'HUECOS'] },
34
34
  gaps: { type: 'array', items: { type: 'string' }, description: 'huecos priorizados (archivo:línea, HU/AC o par de capas)' },
35
+ reproduced: { type: 'array', items: { type: 'string' }, description: 'ids de wiring_checklist[] cuya evidence fue re-ejecutada en ESTA pasada (build-orchestrator les estampa verified_at_sha)' },
36
+ unchanged: { type: 'array', items: { type: 'string' }, description: 'ids que conservaron veredicto como «sin cambios desde <sha>» (diff vacío desde su verified_at_sha; no se re-ejecutó su evidence)' },
35
37
  },
36
38
  }
37
39
 
38
40
  // Insumos por `args` (la sesión/orquestador los pasa READ-ONLY; el workflow no toca disco):
39
41
  // args.checklistPresent : boolean — ¿active_slice.wiring_checklist[] existe y NO está vacío?
40
42
  // args.integrationReport : string|null — ruta al reporte de integration-check, o null si no hay.
43
+ // args.passNumber : number — nº de pasada adversarial sobre este slice (1 = primera).
44
+ // args.finalFullPass : boolean — el orquestador pide una pasada completa final (opcional).
41
45
  const checklistPresent = !!(args && args.checklistPresent)
42
46
  const integrationReport = (args && args.integrationReport) || null
43
47
  const integrationPresent = !!integrationReport
48
+ const passNumber = (args && args.passNumber) || 1
49
+ const finalFullPass = !!(args && args.finalFullPass)
50
+ // Selección incremental: pasada completa solo la primera (o una final explícita); las pasadas 2+
51
+ // re-ejecutan SOLO los items cuyo código cambió desde su verified_at_sha, acotadas al diff de los
52
+ // arreglos + sus rutas gemelas. Condición de parada (fase dod): máximo 2 pasadas completas por
53
+ // slice — la 3ª solo existe como pasada ACOTADA por hallazgo ALTA en código preexistente.
54
+ const incremental = passNumber > 1 && !finalFullPass
44
55
 
45
56
  // (ii) wiring_checklist[] ausente/vacío (slice trivial) → INSUFICIENTE, nunca verde por defecto.
46
57
  if (!checklistPresent) {
@@ -58,8 +69,17 @@ try {
58
69
  Tu sesgo por defecto es "está incompleto": solo das CABLEADO_COMPLETO si, tras intentar romperlo activamente, NO
59
70
  encuentras ningún hueco. Lee READ-ONLY: active_slice.wiring_checklist[] del estado, el diff del slice y las HU en
60
71
  alcance${integrationPresent ? `, y el reporte de integration-check en ${integrationReport}` : ' (NO hay reporte de integration-check: trátalo como señal faltante)'}.
61
- Por cada AC y cada punto de integración, REPRODUCE la evidencia ejecutándola; si no puedes ejecutarla, ese item
62
- es failing. Ante CUALQUIER duda no resuelta o señal faltante HUECOS. No edites estado ni código.`,
72
+ ${incremental
73
+ ? `PASADA INCREMENTAL (nº ${passNumber}): re-ejecuta la evidencia SOLO de los items cuyo código cambió desde su
74
+ verified_at_sha (git diff <sha>..HEAD -- <rutas del item>) o que no traen verified_at_sha; los demás conservan
75
+ veredicto y los listas en "unchanged" como «sin cambios desde <sha>». Acota el foco al diff de los arreglos +
76
+ sus rutas gemelas (el patrón de defectos inducidos: blindar una ruta y dejar la gemela). Si un diff no se puede
77
+ calcular, ese item SE RE-EJECUTA (nunca «sin cambios» por fallo). Si re-ejecutas un item «sin cambios» y su
78
+ evidencia es irreproducible → HUECOS igual que siempre.`
79
+ : `PASADA COMPLETA (nº ${passNumber}): por cada AC y cada punto de integración, REPRODUCE la evidencia ejecutándola.`}
80
+ Si no puedes ejecutar una evidencia, ese item es failing. Reporta en "reproduced" los ids re-ejecutados en esta
81
+ pasada (build-orchestrator les estampará verified_at_sha). Ante CUALQUIER duda no resuelta o señal faltante →
82
+ HUECOS. No edites estado ni código.`,
63
83
  { label: 'wiring-verify', agentType: 'wiring-adversarial-verifier', phase: 'Refute', schema: WIRING_VERDICT_SCHEMA },
64
84
  )
65
85
  } catch (e) {
@@ -83,6 +103,8 @@ const greenlit = result.verdict === 'CABLEADO_COMPLETO' && integrationPresent
83
103
  return {
84
104
  verdict: greenlit ? 'CABLEADO_COMPLETO' : (result.verdict === 'CABLEADO_COMPLETO' ? 'HUECOS' : 'HUECOS'),
85
105
  gaps: result.gaps && result.gaps.length ? result.gaps : (integrationPresent ? [] : ['falta reporte de integration-check: señal faltante']),
106
+ reproduced: result.reproduced || [],
107
+ unchanged: result.unchanged || [],
86
108
  maps_to_wiring_verified: greenlit,
87
- note: 'Read-only. build-orchestrator es quien escribe gates.wiring_verified a partir de este veredicto.',
109
+ note: 'Read-only. build-orchestrator es quien escribe gates.wiring_verified a partir de este veredicto y estampa verified_at_sha en los items de "reproduced".',
88
110
  }
@@ -1,36 +1,52 @@
1
1
  ---
2
2
  name: managing-parallel-front
3
- description: Use when building multiple NON-foundational, file-disjoint epics in parallel via git worktrees. Coordinates the parallel_front in build-state.json (selection, worktrees, deterministic merge order with re-smoke). Never parallelizes foundational epics or overlapping file scopes.
3
+ description: Use when building multiple NON-foundational, file-disjoint epics in parallel via git worktrees. Prepares the disjoint selection and merge order locally (front-plan.py), drives each worktree as its own registered agent, and reports each member's integration (re-smoke, merge_status) through the agent surface. Planning, opening, draining and closing the front are human acts in the hub console. Never parallelizes foundational epics or overlapping file scopes.
4
4
  ---
5
5
 
6
6
  # Gestionar el front paralelo inter-épica (outer-loop)
7
7
 
8
- **Invariante:** el paralelismo es outer-loop. Cada worktree es un checkout aislado con su
9
- **propio** `build-state.json` y su `active_slice` singular (el inner loop no cambia).
8
+ **Invariante:** el paralelismo es outer-loop. Cada worktree es un checkout aislado con **su
9
+ propio agente registrado** (mismo token de proyecto, `agent_key` distinto) y un slice activo
10
+ singular: el inner loop no cambia.
11
+
12
+ **Reparto agente ↔ humano (spec §2).** El agente **prepara y reporta**; la persona **decide**:
13
+
14
+ | Acto | Quién |
15
+ |---|---|
16
+ | Proponer el conjunto disjunto y el `merge_order` (`front-plan.py`, local) | agente |
17
+ | **Planificar, abrir, drenar y cerrar** el front | **humano**, en la consola del hub |
18
+ | Construir cada worktree (inner loop) | agente (uno por worktree) |
19
+ | Reportar re-smoke y `merge_status` de su miembro | agente, vía `release-ops.sh front-integration` |
10
20
 
11
21
  ## Precondiciones (compuertas)
12
- - `scaffold.confirmed == true`.
13
- - **G1 Fundacionales primero:** ninguna épica `layer=foundational` abierta. Si aparece una,
14
- poner `parallel_front.status="draining"` (terminar en curso, no admitir nuevas) antes de abrirla.
22
+ - Scaffold confirmado (`bash .claude/hooks/build/slice-ops.sh status`).
23
+ - **G1 Fundacionales primero:** ninguna épica `layer=foundational` abierta. Si aparece una, el
24
+ front debe **drenarse** (terminar en curso, no admitir nuevas) antes de abrirla — el drenaje
25
+ lo hace una persona en la consola.
15
26
 
16
27
  ## Procedimiento
17
28
  1. **Reunir candidatas** no fundacionales listas (DoR pasado), cada una con `layer` y `files_scope`.
18
- 2. **Seleccionar el conjunto disjunto** (G2):
29
+ 2. **Seleccionar el conjunto disjunto** (G2), en local:
19
30
  `echo "$CANDS" | python3 .claude/scripts/lib/front-plan.py`
20
- → `selected` van al front; `serialized` esperan (construir secuencial después);
21
- `excluded_foundational` nunca en paralelo.
22
- 3. **Abrir un worktree por épica seleccionada:**
31
+ → `selected` propuestas al front; `serialized` esperan (construir secuencial después);
32
+ `excluded_foundational` nunca en paralelo. **Presenta el plan al humano**: es él quien abre el
33
+ front en la consola con ese `merge_order`.
34
+ 3. **Abrir un worktree por épica aprobada:**
23
35
  `git worktree add ".wt/<epica>" -b feature/<slug>` (rama por `1 épica = 1 rama = 1 PR`).
24
- Registrar el miembro en `parallel_front.members[]` (`merge_status:"pending"`).
36
+ En cada worktree corre `trycore-build init` con el **mismo token de proyecto**: se registra
37
+ como agente propio y obtiene su `agent_key`.
25
38
  4. **Construir cada worktree** con la skill `building-a-slice` (inner loop normal, en su cwd).
26
- Cada uno mantiene su `journey_smoke` verde localmente.
27
- 5. **Coordinar merge (G3)** en `merge_order` (determinista: por orden de épica):
39
+ Cada uno reclama su slice y mantiene su `journey_smoke` verde localmente.
40
+ 5. **Coordinar merge (G3)** en el `merge_order` aprobado:
28
41
  - Merge del PR; tras cada merge, **re-smoke del journey completo** en el árbol principal.
29
- - Conflicto `merge_status:"conflict"`, serializar la perdedora (rebase + re-correr sus gates).
30
- - Éxito `merge_status:"merged"`; `git worktree remove`.
31
- 6. **Cerrar el front** cuando todos `merged`: `parallel_front=null`.
42
+ - Reporta el resultado desde el worktree:
43
+ `bash .claude/hooks/build/release-ops.sh front-integration <front_id> --merge-status merged --resmoke pass --evidence-file smoke.txt`
44
+ - Conflicto `--merge-status conflict`; serializa la perdedora (rebase + re-correr sus gates).
45
+ 6. **Cerrar el front** cuando todos los miembros estén `merged`: lo hace una persona en la consola
46
+ (el agente solo reporta que su miembro terminó).
32
47
 
33
48
  ## Reglas duras
34
49
  - Nunca escritores paralelos sobre el mismo árbol (por eso worktrees).
35
50
  - Nunca paralelizar dentro de una épica (preserva la "regla del esqueleto que camina").
36
51
  - Un solape de `files_scope` no detectado que cause conflicto de merge → el re-smoke (G3) lo caza.
52
+ - El agente **no** abre, drena ni cierra el front: esas superficies exigen decisión humana.
@@ -82,6 +82,21 @@ Archive a completed change in the experimental workflow.
82
82
  mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>
83
83
  ```
84
84
 
85
+ 5-bis. **Report the archived slice (build harness)**
86
+
87
+ When the change belongs to an epic slice driven by the build harness, report the domain
88
+ transition — the runtime owns the slice history, not the local file:
89
+
90
+ ```bash
91
+ [ -x .claude/hooks/build/slice-ops.sh ] && \
92
+ bash .claude/hooks/build/slice-ops.sh archive \
93
+ --epic "<EP-XXX>" --openspec-change "<change-name>" --pr-url "<PR URL>"
94
+ ```
95
+
96
+ It is queued and idempotent (protected from the outbox cap), so it survives an offline
97
+ archive; `rc 3` simply means legacy mode (the file protocol applies). Never block the
98
+ archive on this step.
99
+
85
100
  6. **Display summary**
86
101
 
87
102
  Show archive completion summary including:
@@ -16,7 +16,8 @@ Genera el **prototipo HTML de referencia** del consumidor: la fuente de verdad v
16
16
  - Es **outer-loop**: se corre antes de abrir slices (como `/build:architect`), nunca dentro del
17
17
  inner loop de una épica.
18
18
  - Escribe **solo** en `docs/05-prototipo/` (carve-out §9.2 de METODOLOGIA) y, con aprobación
19
- humana, en `design_source` de `build-state.json` (protocolo de `state/README.md`).
19
+ humana, reporta el hecho `design_source` (`slice-ops.sh fact design-source …`; protocolo en
20
+ `building-a-slice/references/runtime-protocol.md`).
20
21
 
21
22
  ## Artefactos que produce (repo del consumidor)
22
23
 
@@ -83,10 +84,13 @@ greenfield → contra tokens + consistencia del lote), corrección y re-render c
83
84
 
84
85
  1. Abre las pantallas en el navegador del usuario y pide aprobación explícita (por pantalla o por
85
86
  lote). Aprobada → `manifest.json` pasa esa entrada a `"aprobada"`.
86
- 2. **Greenfield** con ≥1 pantalla aprobada: ofrece registrar la fuente en `build-state.json`
87
- `design_source.source: "docs/05-prototipo/"`, `confirmed: true`, `confirmed_by`, `confirmed_at`,
88
- `notes` — siguiendo el protocolo de escritura de `state/README.md`. Solo con el **sí** explícito
89
- del humano.
87
+ 2. **Greenfield** con ≥1 pantalla aprobada: ofrece registrar la fuente. Solo con el **sí** explícito
88
+ del humano:
89
+
90
+ ```bash
91
+ bash .claude/hooks/build/slice-ops.sh fact design-source \
92
+ --applies true --source "docs/05-prototipo/" --confirmed true --by "<quién aprobó>"
93
+ ```
90
94
  3. **Feature**: `design_source` ya está confirmado; solo se amplía el manifest.
91
95
 
92
96
  ## Qué NO hace esta skill
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: releasing-a-version
3
- description: Use when closing a release of the product — runs the heavy review gates ONCE over the accumulated diff of a release line (security, design/smell, UX/Krug, three-way coherence, architecture, and full end-to-end integration with real deps), instead of per epic. This is the outer loop; the per-epic inner loop lives in building-a-slice. Trigger after archiving an epic when the user accepts the Release Gate, or when a Story Map release line is complete. Records results in build-state.json releases[].
3
+ description: Use when closing a release of the product — runs the heavy review gates ONCE over the accumulated diff of a release line (security, design/smell, UX/Krug, three-way coherence, architecture, and full end-to-end integration with real deps), instead of per epic. This is the outer loop; the per-epic inner loop lives in building-a-slice. Trigger after archiving an epic when the user accepts the Release Gate, or when a Story Map release line is complete. Reports the six measured verdicts through the agent surface (release-ops.sh verdict); closing the release stays a human act in the hub console.
4
4
  ---
5
5
 
6
6
  # Release Gate (outer loop) — Build
@@ -20,8 +20,13 @@ de épicas de la release son las que vas a auditar en bloque.
20
20
  - O explícitamente: "corre el Release Gate de R1".
21
21
 
22
22
  ## Principio de operación
23
- - **Una sola fuente de verdad**: `.claude/state/build-state.json` → array `releases[]`. Lee antes,
24
- escribe una entrada por release.
23
+ - **Una sola fuente de verdad, según el modo** (`bash .claude/hooks/build/slice-ops.sh mode`): en
24
+ `dual`/`runtime` la release vive en el runtime y cada gate se reporta con
25
+ `bash .claude/hooks/build/release-ops.sh verdict <line> <gate> <pass|fail|na>`; en `legacy`, en el
26
+ array `releases[]` del fichero local (protocolo en `building-a-slice/references/state-protocol.md`).
27
+ - **Reportar es de agentes; cerrar es de humanos** (spec §2). El agente mide y reporta los seis
28
+ veredictos; **la release la cierra una persona en la consola del hub** — el token de agente no
29
+ puede hacerlo. `release-ops.sh close-hint <line>` imprime el recordatorio.
25
30
  - **Sobre el diff acumulado**: el alcance es el rango de commits de todas las épicas de la release
26
31
  (desde el merge anterior a la primera épica de la release hasta `main`).
27
32
  - **Delega en subagentes** (devuelven síntesis, protegen el contexto).
@@ -32,9 +37,9 @@ Esta skill es el **hogar primario** de los workflows del arnés: el Release Gate
32
37
  (`O(releases)`), fuera del camino caliente del inner loop, y **no** duplica el inner loop (ni TDD ni gates por
33
38
  slice). Los `*.workflow.js` bajo `workflows/` son **plantillas de referencia** (no scripts a correr verbatim;
34
39
  si contradicen `METODOLOGIA.md`, gana la metodología). Reglas duras:
35
- - **Read-only sobre el estado.** La plantilla devuelve veredictos; **esta skill** es la única que escribe
36
- `releases[]` (una entrada por release, validando contra `build-state.schema.json`, `updated_by:
37
- releasing-a-version`). Parciales **no** promueven a `passed`.
40
+ - **Read-only sobre el estado.** La plantilla devuelve veredictos; **esta skill** es la única que los
41
+ reporta (un `release-ops.sh verdict` por gate; en modo legacy, una entrada en `releases[]` del
42
+ fichero). El agregado lo hace el runtime: **parciales no promueven a `passed`**.
38
43
  - **`integration` fuera del paralelo.** Los 5 reviewers pesados van en `parallel()`; el gate `integration`
39
44
  (journey completo con **deps reales**) es **secuencial** vía `verify`/`run` y **no** delega en un reviewer.
40
45
 
@@ -54,14 +59,20 @@ Ver `workflows/README.md`. Hoy: `workflows/release-gate.workflow.js`.
54
59
  Checklist de cierre: `references/release-dod.md`.
55
60
 
56
61
  ## Cómo proceder
57
- 1. Lee `build-state.json`; identifica la release y sus épicas (cruza con `docs/02-user-story-map/`).
58
- 2. Crea/actualiza la entrada en `releases[]` con `status: pending`.
62
+ 1. Identifica la release y sus épicas: `bash .claude/hooks/build/slice-ops.sh status` + el Story Map
63
+ (`docs/02-user-story-map/`).
64
+ 2. No hay entrada que crear: la línea de release existe en el runtime; los veredictos la van poblando.
59
65
  3. Dispara los subagentes **en paralelo** sobre el diff acumulado (devuelven síntesis).
60
66
  4. Corre el gate de **integración** con la skill `verify`/`run`: el journey completo, deps reales.
61
- 5. Cuando todos los gates pasan (o `null` cuando N/A) `status: passed`, escribe los `gates` y
62
- `updated_by: releasing-a-version`. Si algo falla `status: failed` y lista los hallazgos
63
- bloqueantes; el usuario los corrige como un slice normal (fix en `building-a-slice`) y se
64
- re-corre el Release Gate.
67
+ 5. Reporta **cada** gate en cuanto lo tengas medido, con su evidencia:
68
+ `release-ops.sh verdict R1-mvp security pass --evidence-file informe.txt` (usa `na` cuando el gate
69
+ no aplique p. ej. `ux` en una release sin UI). Un `rc 6` es el servidor rechazando: muestra su
70
+ razón, no reintentes. Sin red, el veredicto **no** tiene camino por la cola offline (`rc 5`,
71
+ issue #44): reintenta el mismo comando cuando vuelva la red, antes de pedir el cierre.
72
+ 6. Cuando los seis estén reportados, **avisa al humano para el cierre**
73
+ (`release-ops.sh close-hint R1-mvp`): el agente no cierra releases. Si algún gate quedó `fail`,
74
+ lista los hallazgos bloqueantes; el usuario los corrige como un slice normal (fix en
75
+ `building-a-slice`) y se re-corre el Release Gate.
65
76
 
66
77
  > **Opcional — conducir con workflow (releases grandes).** El fan-out del paso 3 puede conducirse con la
67
78
  > plantilla `workflows/release-gate.workflow.js` (referencia, no obligatoria): SOLO paraleliza los 5 reviewers
@@ -69,12 +80,11 @@ Checklist de cierre: `references/release-dod.md`.
69
80
  > **fuera** del `parallel()`. Pasa por `args` lo que computes **read-only**: `diffRange`, `hasUI` y **`hus[]`**
70
81
  > (los IDs de todas las HU de las épicas de la release) — con ≥ 3 HUs el carril `coherence` se shardea por HU
71
82
  > (lossless, fail-closed) en vez de recorrerlas en un solo agente; con menos, corre monolítico como siempre.
72
- > El resultado se escribe igual en `releases[]` respetando **una escritura por
73
- > entrada** y **validando contra el schema**; esta skill sigue siendo la única escritora. Parciales NO
74
- > promueven a `passed`.
83
+ > El resultado se reporta igual, gate a gate, con `release-ops.sh verdict`; esta skill sigue siendo la
84
+ > única que reporta veredictos de release. Parciales NO promueven a `passed` (lo agrega el runtime).
75
85
 
76
86
  ## Reglas duras
77
87
  - **No dupliques el inner loop.** Aquí no se hace TDD ni se cierran gates por slice.
78
- - **Integración con deps reales es obligatoria** para `status: passed` — es el gate que faltaba y
88
+ - **Integración con deps reales es obligatoria** para que la release pueda cerrarse — es el gate que faltaba y
79
89
  por el que el producto "no funcionaba al terminar". No se acepta con todo stubbeado.
80
90
  - Si una regla aquí contradice la metodología Trycore (`METODOLOGIA.md`), **gana la metodología**.
@@ -1,8 +1,8 @@
1
1
  # Release Gate — checklist de salida (outer loop)
2
2
 
3
3
  Una **release** (línea de release del Story Map) no se da por cerrada hasta cumplir TODO esto. Se
4
- corre **una vez** sobre el diff acumulado de todas sus épicas. Resultado en `build-state.json` →
5
- `releases[]`.
4
+ corre **una vez** sobre el diff acumulado de todas sus épicas. Resultado en el runtime (veredictos por `release-ops.sh verdict`; en modo legacy, en `build-state.json` →
5
+ `releases[]`). El **cierre** de la release lo hace una persona en la consola del hub, nunca el agente.
6
6
 
7
7
  - [ ] **`security`** — `security-reviewer` sin hallazgos CRÍTICO/ALTO sobre el diff completo de la release; claves de servicios externos solo server-side; datos sensibles / PII regulados (según el PRD del consumidor) no persistidos crudos; salida de cualquier servicio externo/IA tratada como input no confiable y validada contra esquema antes de alimentar la capa de decisión.
8
8
  - [ ] **`smell`** — `simple-design-reviewer` sin bloqueantes sobre el diff acumulado; 4 reglas de Beck respetadas.
@@ -12,9 +12,11 @@ corre **una vez** sobre el diff acumulado de todas sus épicas. Resultado en `bu
12
12
  - [ ] **`integration`** — el **journey completo** de la release se recorre end-to-end con **dependencias reales** del proyecto (servicios externos/IA y capa de decisión reales, según el PRD del consumidor), no stubs. Verificado con la skill `verify`/`run` (+ MCP `chrome-devtools`). Se corre **fuera** del fan-out
13
13
  paralelo de reviewers (es **secuencial**, con deps reales); ver `../workflows/release-gate.workflow.js`.
14
14
 
15
- **Todo ✓ (o `null` cuando N/A)** → `releases[].status: "passed"`, escribe `gates` y `updated_by:
16
- releasing-a-version`. **Algo ✗** `status: "failed"`, lista hallazgos bloqueantes; se corrigen como
17
- un slice normal en `building-a-slice` y se re-corre el Release Gate.
15
+ **Todo ✓ (o `na` cuando N/A)** → los seis veredictos quedan reportados con `release-ops.sh verdict`
16
+ (en modo legacy, `releases[].status: "passed"` en el fichero); el **cierre** lo hace una persona en la
17
+ consola del hub, nunca el agente. **Algo ✗** → se reporta `fail` con la evidencia y se lista el
18
+ hallazgo bloqueante; se corrige como un slice normal en `building-a-slice` y se re-corre el Release
19
+ Gate.
18
20
 
19
21
  > El gate `integration` es el que faltaba en la era anterior: todos los gates por-slice estaban en
20
22
  > verde y aun así el producto no caminaba de punta a punta. Sin `integration` con deps reales no hay
@@ -7,7 +7,8 @@
7
7
  1. **Hogar primario de los workflows.** El Release Gate corre **una vez por release** (`O(releases)`), fuera
8
8
  del camino caliente del inner loop. **No duplica** el inner loop (ni TDD ni gates por slice).
9
9
  2. **Read-only sobre el estado.** La plantilla devuelve veredictos; la skill `releasing-a-version` es la
10
- **única** que escribe `releases[]` (una entrada por release, validando contra `build-state.schema.json`,
10
+ **única** que reporta los veredictos de release (uno por gate vía `release-ops.sh verdict`; en modo
11
+ legacy, una entrada en `releases[]` validada contra el schema local,
11
12
  `updated_by: releasing-a-version`). Parciales **no** promueven a `passed`.
12
13
  3. **`integration` fuera del paralelo.** Los 5 reviewers pesados van en `parallel()`; el gate `integration`
13
14
  (journey completo con **deps reales**) es **secuencial**, lo corre la skill `verify`/`run`, y **no** delega
@@ -8,9 +8,10 @@
8
8
  // caliente del inner loop. NO duplica el inner loop (ni TDD ni gates por slice).
9
9
  //
10
10
  // READ-ONLY sobre el estado: esta plantilla devuelve un diagnóstico; la skill
11
- // releasing-a-version es la ÚNICA que escribe releases[] (una entrada por release, validando
12
- // contra build-state.schema.json antes de persistir, updated_by:releasing-a-version).
13
- // Parciales NO promueven a passed. Si METODOLOGIA.md (§5) contradice algo aquí, gana la metodología.
11
+ // releasing-a-version es la ÚNICA que reporta los veredictos (release-ops.sh verdict por gate;
12
+ // en modo legacy, una entrada en releases[] del fichero). El agregado y el cierre son del
13
+ // runtime/humano. Parciales NO promueven a passed. Si METODOLOGIA.md (§5) contradice algo aquí,
14
+ // gana la metodología.
14
15
  //
15
16
  // RUNTIME: corre en el runtime de Workflow de Claude Code, que provee los globals
16
17
  // agent()/parallel()/pipeline()/phase()/log()/args y envuelve el cuerpo en un contexto async
@@ -149,11 +150,11 @@ const reviewersGreen = reviews.filter(Boolean).every((r) => r.na || r.value ===
149
150
  const status = (reviewersGreen && gates.integration === true) ? 'passed' : 'failed'
150
151
 
151
152
  return {
152
- status, // releasing-a-version lo persiste en releases[] (única escritora).
153
+ status, // reportado por releasing-a-version vía release-ops.sh verdict (agregado y cierre son del runtime/humano).
153
154
  gates, // {security, smell, ux, coherence, stack_arch, integration}
154
155
  blocking: [
155
156
  ...reviews.filter((r) => r && r.value === false).map((r) => ({ gate: r.gate, error: r.error || null, findings: r.findings || [] })),
156
157
  ...(gates.integration === true ? [] : [{ gate: 'integration', findings: (integration && integration.findings) || [] }]),
157
158
  ],
158
- note: 'Read-only. releasing-a-version valida contra build-state.schema.json y escribe UNA entrada en releases[] (updated_by:releasing-a-version). Parciales NO promueven a passed.',
159
+ note: 'Read-only. releasing-a-version reporta un veredicto por gate (release-ops.sh verdict). El runtime agrega y un humano cierra la release en la consola. Parciales NO promueven a passed.',
159
160
  }
@@ -27,14 +27,16 @@ Negocio → ASRs → Tácticas → Estilos → Vistas → Evaluación (ATAM) →
27
27
  subárbol **`docs/adr/`** (propiedad de construcción; carve-out declarado en `METODOLOGIA.md`).
28
28
  - **Propone, no publica.** Genera los `.md` con estado `proposed` / `living-document`. La promoción a
29
29
  `accepted` la hace un humano en la revisión única (fase 5). Forward-compat v0.9: los tipos viven en
30
- `asset-types.json`; cuando exista el runtime, la propuesta irá por API (`POST /context/proposals`).
30
+ `asset-types.json`; con el runtime disponible, la instancia se **propone** por la superficie de
31
+ agente: `bash .claude/hooks/build/slice-ops.sh propose-asset --type-key <k> --path <p> --content-file <f>`
32
+ (la publica un ADMIN; un agente jamás publica contexto).
31
33
  - **Autónoma y de propuesta máxima.** La IA rellena todo el catálogo y todos los ADRs de una pasada;
32
34
  **no** pregunta campo por campo. Solo se detiene ante **trade-offs de negocio** genuinos (ver fase 5).
33
35
  - **Delega la exploración pesada en subagentes** (`asr-extractor`, `architecture-evaluator`): devuelven
34
36
  síntesis condensada y protegen el presupuesto de atención de la sesión principal.
35
37
  - **Divulgación progresiva:** carga el `references/<tema>.md` solo cuando la fase lo necesita.
36
38
  - **El estado es el archivo.** `docs/adr/_backlog-arquitectonico.md` es el estado auto-descriptivo de la
37
- capa (no toca `build-state.json`). Re-correr = **incremental**: añade iteraciones, no regenera.
39
+ capa (no transiciona el estado del slice). Re-correr = **incremental**: añade iteraciones, no regenera.
38
40
 
39
41
  ## Fases (carga la referencia indicada en cada paso)
40
42
 
package/state/README.md CHANGED
@@ -5,6 +5,15 @@ el que los agentes se sincronizan en modo **secuencial**. La unidad de construcc
5
5
  (`EP-XXX`)**; las HU que cubre el change se listan en `hus[]` (trazabilidad al alcance interno).
6
6
  Cada gate del pipeline transiciona el estado; el siguiente agente lo lee antes de actuar.
7
7
 
8
+ > **Todo lo anterior describe el modo `legacy` (default).** Si el proyecto corre en modo `dual` o
9
+ > `runtime` (`config/build-config.json#runtime.mode`, opt-in — EP-OR-08, beta), este mismo
10
+ > protocolo lo conducen `hooks/build/slice-ops.sh`/`release-ops.sh` contra el Agent Orchestrator
11
+ > Runtime en vez de (o además de) este fichero: mismas reglas, mismo "quién escribe qué", otro
12
+ > medio. Ver `skills/building-a-slice/references/runtime-protocol.md`,
13
+ > `docs/runtime/protocolo-cliente-runtime.md` y, para migrar un proyecto,
14
+ > `docs/runtime/guia-modo-dual-y-migracion.md`. `legacy` sigue siendo el camino con soporte
15
+ > completo hasta que un piloto real confirme el corte (`docs/runtime/plan-migracion-harness-v0.9.md` §2).
16
+
8
17
  - **Esquema**: `build-state.schema.json` (versionado, draft 2020-12). Valida con:
9
18
  ```bash
10
19
  # Recomendado (funciona sin plugins de formato):
@@ -91,7 +100,12 @@ INCONCLUSO ya **no** pasa (queda `false` → el `dod` no cierra hasta correrlo d
91
100
  Campos por-slice que hacen el **refresh de contexto el estado por defecto** (una sesión fresca retoma
92
101
  desde disco, no desde la conversación):
93
102
  - **`wiring_checklist[]`** — un item por escenario AC y por punto de integración entre capas; nace
94
- `failing`, pasa a `passing` **solo tras prueba real ejecutada** (con `evidence`).
103
+ `failing`, pasa a `passing` **solo tras prueba real ejecutada** (con `evidence`). Cada item puede
104
+ llevar además **`verified_at_sha`** (opcional): el sha del commit en que su evidencia fue
105
+ reproducida por última vez. Lo estampa el `build-orchestrator` al aplicar un veredicto del
106
+ `wiring-adversarial-verifier`, y habilita la **re-verificación incremental**: en pasadas
107
+ posteriores solo se re-ejecuta la evidencia de los items cuyo código cambió desde su sha
108
+ (`git diff <sha>..HEAD -- <rutas del item>`); el resto conserva veredicto.
95
109
  - **`progress_log[]`** — bitácora append-only (`{at, by, note}`) que sobrevive al reset.
96
110
  - **`sub_slices[]`** — descomposición de una épica que superó el gate de tamaño (>3 HU ó ≥3 capas).
97
111
  - **gate `wiring_verified`** — lo cierra el `wiring-adversarial-verifier` (subagente **independiente**,
@@ -115,6 +129,7 @@ El razonamiento vive en el modelo; el hook solo es un recordatorio determinista.
115
129
  | `gates.coherence_link` | `change-epic-coherence` | slice |
116
130
  | `gates.tdd` | flujo `superpowers:test-driven-development` (vía `build-orchestrator`) | slice |
117
131
  | `gates.journey_smoke` · `gates.fidelity` · `phase` (transiciones) · `history[]` (archivado) · `wiring_checklist[]` · `progress_log[]` · `sub_slices[]` | `build-orchestrator` (fidelity desde `ux-fidelity-reviewer`) | slice |
132
+ | `wiring_checklist[].verified_at_sha` | `build-orchestrator` (al aplicar un veredicto del `wiring-adversarial-verifier`: estampa el sha en los items cuya evidencia fue reproducida en esa pasada) | por pasada de verificación |
118
133
  | `gates.api` | `api-contract-tester` | slice |
119
134
  | `gates.data` | `data-consistency-checker` | slice |
120
135
  | `gates.wiring_verified` | `wiring-adversarial-verifier` (independiente, contexto virgen) | slice (antes de `dod`) |
@@ -162,7 +162,8 @@
162
162
  "kind": { "type": "string", "enum": ["hu_ac", "integration_point"], "description": "hu_ac = escenario Given/When/Then de una HU; integration_point = cableado entre dos capas." },
163
163
  "ref": { "type": "string", "description": "A qué apunta: el AC (HU-XXX#escenario) o el par de capas (capaA→capaB)." },
164
164
  "status": { "type": "string", "enum": ["failing", "passing"], "description": "failing al nacer; passing SOLO tras prueba real ejecutada." },
165
- "evidence": { "type": "string", "description": "Evidencia de ejecución que justificó passing (test, comando, salida). Vacío mientras failing." }
165
+ "evidence": { "type": "string", "description": "Evidencia de ejecución que justificó passing (test, comando, salida). Vacío mientras failing." },
166
+ "verified_at_sha": { "type": "string", "description": "OPCIONAL. Sha del commit en que la evidence de este item fue reproducida por última vez. Lo estampa el build-orchestrator al aplicar un veredicto del wiring-adversarial-verifier. Habilita la re-verificación incremental: en pasadas posteriores el verificador solo re-ejecuta la evidencia de items cuyo código cambió desde este sha (git diff <sha>..HEAD -- <rutas del item>); los demás conservan veredicto. Ausente = el item nunca fue verificado por el verificador (se re-ejecuta siempre)." }
166
167
  }
167
168
  }
168
169
  },
@@ -40,6 +40,22 @@ Outer loop (por release): Release Gate (seguridad · diseño · UX · cohe
40
40
  8. **Cimiento antes que negocio y unidades pequeñas.** Las épicas de cimiento (auth, datos, arquitectura base, design-system) se construyen antes que las de negocio; una épica grande (>3 HU ó ≥3 capas) se descompone en sub-slices construidos de a uno. En proyectos **nuevos** (`project_kind: greenfield`), la **épica caparazón** (app shell: navegación, layout, homepage, login, redirecciones — gate de proyecto `foundation`) se construye y archiva **con evidencia** antes que cualquier épica de negocio; en brownfield el mecanismo es N/A.
41
41
  9. Si una regla del arnés contradice la metodología Trycore (`METODOLOGIA.md`), **gana la metodología**.
42
42
 
43
+ ### Ámbito de las reglas de evidencia
44
+
45
+ - Las reglas pesadas — **mutación obligatoria, evidencia anclada a sha, regresión con
46
+ worktree/baseline** — aplican al **inner loop de slices** (fase tdd→dod de `building-a-slice`),
47
+ **no** al carril `building-a-micro-change`: un micro-cambio exige 1 test de regresión si cambia
48
+ comportamiento + la suite del módulo tocado en verde, y cierra en **< 30 min** (mutación opcional;
49
+ los límites duros de escalada a slice quedan intactos).
50
+ - **Presupuesto de mutación**: obligatoria solo para los tests que sostienen un item de
51
+ `wiring_checklist[]` (AC de HU, puntos de integración); opcional para tests auxiliares.
52
+ Alternativa al ciclo manual: mutación automatizada acotada a los ficheros cambiados, con el
53
+ reporte como evidencia.
54
+ - **Dos clases de evidencia**: la **determinista** (runners sin LLM) se re-ancla a HEAD; la **viva**
55
+ (corridas contra el LLM real del proyecto) se ancla al último commit que tocó el módulo medido
56
+ (`anchored_at.sha`; `head_at_run` informativo) y solo se regenera cuando cambió el código que mide.
57
+ Detalle operativo: `.claude/skills/building-a-slice/references/evidence-budget.md`.
58
+
43
59
  ### Bloque de dominio (lo resuelve `/build:onboard`)
44
60
 
45
61
  Estos puntos de extensión los leen los agentes `security-reviewer`, `stack-guardian`,