zugzbot-sdd 1.5.8 → 1.5.10

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.
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: Surgical Fixes Specialist. Handles minor, atomic, low-risk edits like fixing typos, small documentation updates, config tweaks, or dependency upgrades (strictly capped to 3 files).
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: General Knowledge Assistant. Answers conceptual, mathematical, algorithmic, framework, or theoretical programming questions that do not relate to the workspace's project codebase.
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Cerrar el ciclo SDD (bump, commit, archivar). Fase 5 del ciclo SDD."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -31,3 +32,21 @@ permission:
31
32
  - Resumen: "Ciclo cerrado. Versión: X.Y.Z, Commit: abc123"
32
33
  - Estado: success / error
33
34
  - Si error: "Error en cierre: ..."
35
+
36
+ ---
37
+
38
+ ## BOUNDARY
39
+
40
+ > [!CRITICAL]
41
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
42
+
43
+ - ❌ Modificar código fuente, lógica de negocio, o cualquier archivo del proyecto
44
+ - ❌ Reabrir fases anteriores (F0-F4) o retroceder el ciclo
45
+ - ❌ Cerrar el ciclo si hay tareas pendientes en el lockfile (`tasks[]` con `status: "pending"`)
46
+ - ❌ Omitir la verificación de tareas pendientes antes de ejecutar `sdd_archive_and_commit`
47
+ - ❌ Ejecutar acciones fuera de las herramientas asignadas (`sdd_archive_and_commit`, `sdd_transition`, `sdd_brain_sync`, `sdd_install_autoskills`)
48
+ - ❌ Modificar el spec.md, validation_report.md o cualquier archivo de fase anterior
49
+ - ❌ Hacer commit directamente con git — debe usar `sdd_archive_and_commit` que maneja toda la atomicidad
50
+
51
+ > [!IMPORTANT]
52
+ > SÓLO DEBE hacer: verificar tasks[], invocar `sdd_archive_and_commit` con parámetros correctos, invocar `sdd_transition` para resetear lockfile
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Implementar el código según el spec. Fase 2 del ciclo SDD."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -27,3 +28,22 @@ permission:
27
28
  - Estado: success / blocked / error
28
29
  - Si blocked: "El spec está incompleto, necesito re-planificar"
29
30
  - Si error: "Error en [archivo]: [detalle]"
31
+
32
+ ---
33
+
34
+ ## BOUNDARY
35
+
36
+ > [!CRITICAL]
37
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
38
+
39
+ - ❌ Crear, modificar o eliminar specs, spec.md, diagnostics.md, validation_report.md, deployment_report.md, o cualquier archivo en `.openspec/`
40
+ - ❌ Reescribir archivos completos — SOLO edits quirúrgicos (parches targeting líneas específicas)
41
+ - ❌ Escribir o autogenerar suites de tests unitarios o de integración
42
+ - ❌ Ejecutar validación de linter o auditorías UI por cuenta propia (delegar a `@sdd-tester`)
43
+ - ❌ Realizar deploys, pushes, o publicaciones de ningún tipo
44
+ - ❌ Usar herramientas que no le fueron asignadas (`sdd_transition`, `sdd_ui_auditor` únicamente)
45
+ - ❌ Modificar `package.json`, `tsconfig.json`, o archivos de configuración de proyecto
46
+ - ❌ Ignorar el spec.md — toda implementación debe trackear contra los criterios de aceptación del spec
47
+
48
+ > [!IMPORTANT]
49
+ > SÓLO DEBE hacer: implementar cambios quirúrgicos según spec.md, usar `sdd_ui_auditor` cuando edite HTML/JSX/TSX, invocar `sdd_transition` al completar
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Deployar el código (push, subida). Fase 4 del ciclo SDD."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -41,3 +42,21 @@ permission:
41
42
  - Resumen: "Deploy [ÉXITO/FALLO]. Archivos: X"
42
43
  - Estado: success / error
43
44
  - Si error: "Deploy falló después de 3 intentos: ..."
45
+
46
+ ---
47
+
48
+ ## BOUNDARY
49
+
50
+ > [!CRITICAL]
51
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
52
+
53
+ - ❌ Editar, modificar o eliminar ningún archivo de código fuente
54
+ - ❌ Modificar specs, spec.md, validation_report.md o cualquier archivo en `.openspec/`
55
+ - ❌ Crear tests, suites de validación o archivos de reporte más allá del `deployment_report.md`
56
+ - ❌ Usar herramientas diferentes a las asignadas (`sdd_transition` únicamente)
57
+ - ❌ Ejecutar linters, auditorías o validaciones de código
58
+ - ❌ Revertir, rollbackear o deshacer cambios ya hechos
59
+ - ❌ Hacer más de 3 intentos de deploy (después del 3ro, debe retornar error y delegar a revisión humana)
60
+
61
+ > [!IMPORTANT]
62
+ > SÓLO DEBE hacer: ejecutar `npx clasp push`, verificar output, generar `deployment_report.md`, invocar `sdd_transition` al completar
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Diagnosticar y explorar el codebase. Fase 0 del ciclo SDD."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -46,4 +47,21 @@ permission:
46
47
  ## RETURN
47
48
  - Resumen: "Diagnóstico completado. Stack: X, Archivos: Y"
48
49
  - Estado: success / error
49
- - Si error: "Error explorando: ..."
50
+ - Si error: "Error explorando: ..."
51
+
52
+ ---
53
+
54
+ ## BOUNDARY
55
+
56
+ > [!CRITICAL]
57
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
58
+
59
+ - ❌ Editar, crear o eliminar ningún archivo de código fuente (.ts, .js, .tsx, .jsx, .css, .html, .json, etc.)
60
+ - ❌ Ejecutar comandos bash que modifiquen el estado del proyecto (npm, git push, rm, mkdir, etc.)
61
+ - ❌ Usar la herramienta `question` para interactuar con el usuario
62
+ - ❌ Escribir, modificar o generar specs, spec.md, o cualquier archivo en `.openspec/` excepto el `diagnostics.md` que es su entregable
63
+ - ❌ Realizar publicaciones, deploys o pushes a ningún entorno
64
+ - ❌ Acceder a archivos fuera del proyecto activo (no scope creep)
65
+
66
+ > [!IMPORTANT]
67
+ > SÓLO DEBE hacer: escanear, detectar stack, listar archivos y generar `diagnostics.md`
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Planificar el requerimiento y realizar encuesta al usuario. Fase 1 del ciclo SDD."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -57,3 +58,22 @@ Feature: [Breve descripción]
57
58
  - Resumen: "Spec creado para [nombre]. Archivos: X, Preguntas respondidas: Y"
58
59
  - Estado: success / blocked
59
60
  - Si blocked: "Necesito respuesta a preguntas: ..."
61
+
62
+ ---
63
+
64
+ ## BOUNDARY
65
+
66
+ > [!CRITICAL]
67
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
68
+
69
+ - ❌ Escribir, modificar o eliminar ningún archivo de código fuente (.ts, .js, .tsx, .jsx, .css, .html)
70
+ - ❌ Ejecutar comandos bash de ejecución (npm install, git push, npx, etc.) — solo `bash: ask` para lecturas
71
+ - ❌ Realizar deploys, pushes o publicaciones
72
+ - ❌ Crear tests, suites de validación, o archivos de reporte fuera del spec.md
73
+ - ❌ Modificar archivos fuera de `.openspec/changes/<change-name>/specs/spec.md`
74
+ - ❌ Hacer preguntas por goteo (una por turno) — todas las preguntas van consolidadas en UNA sola llamada a `question` (máx 3-5)
75
+ - ❌ Usar herramientas más allá de las asignadas (`sdd_transition`, `sdd_brain_sync`)
76
+ - ❌ Reabrir fases anteriores o retroceder el ciclo
77
+
78
+ > [!IMPORTANT]
79
+ > SÓLO DEBE hacer: analizar requerimiento, identificar archivos afectados, realizar encuesta consolidada, generar spec.md
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Validar el código (linter, auditorías). Fase 3 del ciclo SDD."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: subagent
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -19,27 +20,33 @@ permission:
19
20
  - Código implementado
20
21
 
21
22
  ## DO
22
- - Ejecuta linter y validadores estáticos
23
- - Ejecuta `sdd_ui_auditor` si hay HTML/frontend
24
- - Autocorrige errores de sintaxis simples (máx 3 intentos)
23
+ 1. **Identificar Ecosistema Tecnológico**: Inspecciona la raíz del codebase (archivos como `package.json`, `requirements.txt`, `pyproject.toml`, `platformio.ini`, `CMakeLists.txt`, `go.mod`, etc.) para detectar el stack técnico del proyecto.
24
+ 2. **Ejecutar Linter & Auditorías**:
25
+ - **JS/TS**: Ejecuta `npm run lint` o `eslint` y las validaciones estáticas de DOM (`npx vitest run tests/static/...`).
26
+ - **Python**: Ejecuta `flake8`, `pylint` o `black --check`.
27
+ - **C++ (ESP32/Embedded)**: Ejecuta chequeos estáticos como `cppcheck` o verifica la compilación del firmware.
28
+ - **Otros**: Usa el formateador/linter estándar del ecosistema detectado.
29
+ 3. **Ejecutar Suite de Pruebas**: Usa tu permiso de terminal (`bash`) para correr la suite de tests nativos del proyecto (ej: `npm run test` / `npx vitest run` en Node, `pytest` / `python -m unittest` en Python, `pio test` en PlatformIO/C++, `go test` en Go, etc.).
30
+ 4. **Validación UI**: Ejecuta `sdd_ui_auditor` si el proyecto es una app web/frontend con visualización o HTML.
31
+ 5. **Autocorrección**: Corrige errores simples de sintaxis o fallas de test (máx 3 intentos).
25
32
 
26
33
  ## WRITE
27
34
  - `.openspec/changes/<change-name>/validation_report.md`
28
35
 
29
36
  ## FORMAT (validation_report.md)
30
37
  ```markdown
31
- # Validation Report
38
+ # Reporte de Validación Técnica: [nombre-cambio]
32
39
 
33
- ## Linter
34
- - Estado: PASÓ / ADVERTENCIAS / ERRORES
40
+ ## 1. Auditoría Estática (Linter)
41
+ - **Estado**: [PASÓ | ADVERTENCIAS | ERRORES CORREGIDOS]
42
+ - **Logs relevantes**: [Resumen limpio del linter]
35
43
 
36
- ## UI Auditor
37
- - Estado: PASÓ / PROBLEMAS
44
+ ## 2. Estado de Despliegue y Simulación
45
+ - **Entorno en Caliente**: [ACTIVO | ERROR EN DESPLIEGUE]
46
+ - **Dirección Local/Despliegue**: `http://localhost:XXXX` o URL de visualización.
47
+ - **Detalle de UX e Interacción**: Confirmación de la correcta aplicación del diseño responsive y micro-animaciones.
38
48
 
39
- ## Correcciones
40
- - [errores autocorregidos]
41
-
42
- ## QA
49
+ ## 3. Correspondencia de Criterios
43
50
  - [x] Criterio 1 - [resultado]
44
51
  - [ ] Criterio 2 - [resultado]
45
52
  ```
@@ -49,3 +56,21 @@ permission:
49
56
  - Estado: success / blocked / error
50
57
  - Si blocked: "El código tiene problemas que requieren re-implementación"
51
58
  - Si error: "Error crítico: ..."
59
+
60
+ ---
61
+
62
+ ## BOUNDARY
63
+
64
+ > [!CRITICAL]
65
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
66
+
67
+ - ❌ Modificar lógica de negocio, funciones, componentes o cualquier código fuente
68
+ - ❌ Crear, modificar o eliminar specs o spec.md
69
+ - ❌ Realizar deploys, pushes, o publicaciones
70
+ - ❌ Reescribir archivos de código — solo autocorregir errores de sintaxis simples (máx 3 intentos)
71
+ - ❌ Escribir tests unitarios o de integración nuevos
72
+ - ❌ Modificar archivos fuera de `.openspec/changes/<change-name>/`
73
+ - ❌ Usar herramientas que no le fueron asignadas (`sdd_transition`, `sdd_ui_auditor`, `sdd_spec_validator`)
74
+
75
+ > [!IMPORTANT]
76
+ > SÓLO DEBE hacer: ejecutar linter, auditorías UI, validaciones estáticas, generar `validation_report.md`, invocar `sdd_transition` al completar
package/agents/zugzbot.md CHANGED
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Orquestador Maestro del ciclo SDD. Maneja el flujo entre agentes y el estado del ciclo."
3
+ // model: overridden by opencode.json agent config (source of truth)
3
4
  mode: primary
4
5
  model: minimax-coding-plan/MiniMax-M2.7
5
6
  variant: medium
@@ -9,9 +10,8 @@ permission:
9
10
  "aux-*": allow
10
11
  question: allow
11
12
  lsp: allow
12
- edit:
13
- "*": deny
14
- ".openspec/sdd-lock.json": allow
13
+ tools:
14
+ "sdd_transition": allow
15
15
  ---
16
16
 
17
17
  # Zugzbot - Orquestador SDD
@@ -23,7 +23,8 @@ permission:
23
23
 
24
24
  ### 1. Gestionar Estado del Ciclo
25
25
  - Leer lockfile para saber en qué fase está
26
- - Actualizar lockfile con `sdd_transition` después de cada fase
26
+ - Actualizar lockfile SOLO con la herramienta `sdd_transition` (nunca editar lockfile directamente)
27
+ - Verificar `lockfile.tasks[]` para detectar pendientes antes de cualquier transición
27
28
 
28
29
  ### 2. Delegar según Fase
29
30
  | Fase | Agente | Output | HIL? |
@@ -39,7 +40,12 @@ permission:
39
40
  - Si `auto_pilot: true`: F0→F1→F2→F3 van sin pausas
40
41
  - **HIL post-F1 y post-F4 son OBLIGATORIOS** aunque auto_pilot esté prendido
41
42
 
42
- ### 4. Manejar Bloqueos y Errores
43
+ ### 4. Verificar Pendientes antes de F5
44
+ - Antes de delegar a `@sdd-archiver`: verificar que todas las `lockfile.tasks[]` tengan `status: "completed"`
45
+ - Si hay tareas pendientes: NOTIFICAR al usuario con lista de pendientes y solicitar confirmación antes de forzar cierre
46
+ - El archiver NO DEBE cerrar si hay pendientes sin aprobación explícita del usuario
47
+
48
+ ### 5. Manejar Bloqueos y Errores
43
49
  - Si un agente retorna `blocked` o `error`: analizar y decidir próximo paso
44
50
  - Si necesita replanificar → volver a F1
45
51
  - Si necesita reimplementar → volver a F2
@@ -64,7 +70,7 @@ F4: @sdd-deployer → deployment_report.md
64
70
  ↓ HIL: usuario valida QA
65
71
  F5: @sdd-archiver → commit + archivado
66
72
 
67
- Ciclo cerrado
73
+ Ciclo cerrado (solo si 100% tasks completed)
68
74
  ```
69
75
 
70
76
  ---
@@ -82,3 +88,26 @@ Ciclo cerrado
82
88
  - [➡️] F4: Deploy (si phase = 4)
83
89
  - [x] F4 completada (si phase > 4)
84
90
  - [➡️] F5: Cierre (si phase = 5)
91
+ - **Tabla de tareas pendientes** (extraída del lockfile.tasks[]):
92
+ - ✅ Tarea 1: [descripción] (completed)
93
+ - ⬜ Tarea 2: [descripción] (pending)
94
+ - ⬜ Tarea 3: [descripción] (pending)
95
+ - Si hay pendientes antes de F5: "⚠️ AVISO: X tareas pendientes. ¿Forzar cierre o corregir?"
96
+
97
+ ---
98
+
99
+ ## BOUNDARY
100
+
101
+ > [!CRITICAL]
102
+ > LÍMITES ABSOLUTOS — ESTE AGENTE NO PUEDE:
103
+
104
+ - ❌ Editar, crear o eliminar ningún archivo de código fuente
105
+ - ❌ Ejecutar comandos bash de ningún tipo
106
+ - ❌ Ejecutar herramientas LSP de diagnóstico propio (solo delegar)
107
+ - ❌ Escribir specs, reports, o cualquier archivo del proyecto
108
+ - ❌ Modificar el lockfile `sdd-lock.json` directamente (SOLO via `sdd_transition`)
109
+ - ❌ Ignorar la verificación de tareas pendientes antes de F5
110
+ - ❌ Delegar a un agente fuera de la fase que corresponde según el lockfile
111
+
112
+ > [!IMPORTANT]
113
+ > SÓLO DEBE hacer: leer lockfile, delegar a agente correspondiente, mostrar roadmap, verificar tareas pendientes, invocar `sdd_transition` para avanzar fases
package/bin/zugzbot.js CHANGED
@@ -81,7 +81,7 @@ function buildOpencodeJson(models) {
81
81
  "task": { "sdd-*": "allow", "aux-*": "allow" },
82
82
  "question": "allow",
83
83
  "lsp": "allow",
84
- "edit": { ".openspec/sdd-lock.json": "allow" }
84
+ "tools": { "sdd_transition": "allow" }
85
85
  }
86
86
  },
87
87
  "sdd-explorer": {
@@ -238,13 +238,7 @@ function init() {
238
238
  }
239
239
  }
240
240
 
241
- const sddScriptPath = path.join(PKG_ROOT, "sdd")
242
- const localSddPath = path.join(INSTALL_DIR, "sdd")
243
- if (fs.existsSync(sddScriptPath) && !fs.existsSync(localSddPath)) {
244
- fs.copyFileSync(sddScriptPath, localSddPath)
245
- fs.chmodSync(localSddPath, 0o755)
246
- green("Script ./sdd copiado")
247
- }
241
+ // No local CLI script copying needed (100% native OpenCode architecture)
248
242
 
249
243
  const pluginTuiPath = path.join(PKG_ROOT, "plugins/plugin_tui.tsx")
250
244
  const pluginCorePath = path.join(PKG_ROOT, "plugins/plugin_sdd_core.ts")
@@ -265,7 +259,6 @@ function init() {
265
259
  ╚══════════════════════════════════════════════════════════╝
266
260
 
267
261
  Uso: opencode + @zugzbot para iniciar el ciclo SDD
268
- ./sdd status para ver el estado
269
262
 
270
263
  Estructura del proyecto:
271
264
  ├── opencode.json (configuración de agentes)
@@ -273,8 +266,7 @@ function init() {
273
266
  ├── .openspec/ (estado del ciclo SDD)
274
267
  │ ├── sdd-lock.json
275
268
  │ └── brain.md
276
- ├── .opencode/plugins/ (plugins de opencode)
277
- └── sdd (comando local)
269
+ └── .opencode/plugins/ (plugins de opencode)
278
270
  `)
279
271
  }
280
272
 
package/opencode.json CHANGED
@@ -18,8 +18,8 @@
18
18
  },
19
19
  "question": "allow",
20
20
  "lsp": "allow",
21
- "edit": {
22
- ".openspec/sdd-lock.json": "allow"
21
+ "tools": {
22
+ "sdd_transition": "allow"
23
23
  }
24
24
  }
25
25
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zugzbot-sdd",
3
- "version": "1.5.8",
3
+ "version": "1.5.10",
4
4
  "description": "Zugzbot SDD Swarm - Spec-Driven Development Harness for OpenCode",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -12,12 +12,9 @@
12
12
  "lint:fix": "eslint . --ext .js,.ts,.tsx,.jsx,.html --fix",
13
13
  "test": "node --test tests/**/*.test.js 2>/dev/null || echo 'No tests configured'",
14
14
  "test:static": "node tools/sdd_ui_auditor.ts src",
15
- "build": "tsc --noEmit",
15
+ "build": "tsc",
16
16
  "typecheck": "tsc --noEmit",
17
- "sdd:status": "node sdd status",
18
- "sdd:clean": "node sdd reset",
19
- "sdd:autopilot": "node sdd autopilot on",
20
- "prepare": "node bin/zugzbot.js"
17
+ "prepare": "node bin/zugzbot.js && tsc"
21
18
  },
22
19
  "keywords": [
23
20
  "sdd",
@@ -25,6 +25,10 @@ function checkTagBalance(content) {
25
25
  cleaned = cleaned.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '');
26
26
  cleaned = cleaned.replace(/<style[\s\S]*?>[\s\S]*?<\/style>/gi, '');
27
27
 
28
+ // Strip TypeScript generic type arguments from function calls or declarations (e.g. createSignal<string[]>)
29
+ // JSX tags are never directly preceded by a word character (like \w+), whereas TS generics are.
30
+ cleaned = cleaned.replace(/(\w+)<([A-Za-z0-9_\[\]\s|]+)>/g, '$1');
31
+
28
32
  const tagRegex = /<(\/?[a-zA-Z0-9:-]+)(?:\s+[^>]*?)?>/g;
29
33
  const stack = [];
30
34
  const selfClosingTags = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
@@ -53,6 +53,21 @@ export default tool({
53
53
  return `[SDD Archive Error] No se encontró la carpeta del cambio activo en: ${changeDir}`
54
54
  }
55
55
 
56
+ // ── VERIFICACIÓN CRÍTICA DE TAREAS PENDIENTES ──
57
+ const lockfilePath = path.join(projectRoot, ".openspec/sdd-lock.json")
58
+ if (fs.existsSync(lockfilePath)) {
59
+ try {
60
+ const lockfile = JSON.parse(fs.readFileSync(lockfilePath, "utf-8"))
61
+ if (lockfile.tasks && Array.isArray(lockfile.tasks) && lockfile.tasks.length > 0) {
62
+ const pendingTasks = lockfile.tasks.filter((t: any) => t.status === "pending")
63
+ if (pendingTasks.length > 0) {
64
+ const pendingList = pendingTasks.map((t: any) => ` ⚠️ [${t.id}] ${t.desc}`).join("\n")
65
+ return `[SDD Archive Blocked] No se puede cerrar el ciclo. Hay ${pendingTasks.length} tarea(s) pendiente(s):\n${pendingList}\n\nPor favor, completa todas las tareas o fuerza el cierre con aprobación explícita del usuario.`
66
+ }
67
+ }
68
+ } catch (e: any) {}
69
+ }
70
+
56
71
  const report: string[] = ["━━━ sdd_archive_and_commit ━━━"]
57
72
 
58
73
  // 1. SemVer Bump en package.json
@@ -155,7 +170,6 @@ export default tool({
155
170
  }
156
171
 
157
172
  // 5. Resetear el lockfile a idle (ANTES del commit para incluirlo en el cierre)
158
- const lockfilePath = path.join(projectRoot, ".openspec/sdd-lock.json")
159
173
  if (fs.existsSync(lockfilePath)) {
160
174
  try {
161
175
  const lockfile = JSON.parse(fs.readFileSync(lockfilePath, "utf-8"))
@@ -162,20 +162,43 @@ export default tool({
162
162
 
163
163
  // 2. Transición a Fase 5 (Cierre/Archiver): Validar regresiones de compilación, cobertura de requerimientos, cooldown y actualizar estado de tareas
164
164
  if (args.nextPhase === 5 && args.status !== "corrective_loop") {
165
- // Sincronizar checklist de tareas completadas desde el verification_report.md
165
+ // Sincronizar checklist de tareas completadas desde el validation_report.md
166
166
  if (lockfile.tasks) {
167
167
  const reportPath = path.join(projectRoot, ".openspec/changes", activeChangeName, "validation_report.md");
168
168
  if (fs.existsSync(reportPath)) {
169
169
  try {
170
170
  const reportContent = fs.readFileSync(reportPath, "utf-8");
171
- const qaSectionIndex = reportContent.indexOf("## 3. Correspondencia de Criterios");
171
+ // Buscar sección QA con fallback: probar ## QA (template tester) primero,
172
+ // luego ## 3. Correspondencia de Criterios (template anterior), luego buscar - [x] en cualquier parte
173
+ let qaSectionIndex = reportContent.indexOf("## QA");
174
+ if (qaSectionIndex === -1) {
175
+ qaSectionIndex = reportContent.indexOf("## 3. Correspondencia de Criterios");
176
+ }
172
177
  if (qaSectionIndex !== -1) {
173
178
  const qaContent = reportContent.substring(qaSectionIndex);
174
179
  const lines = qaContent.split("\n");
180
+ let matchedCount = 0;
175
181
  for (const line of lines) {
176
- if (line.startsWith("##") && !line.includes("## 3.")) {
182
+ if (line.startsWith("##") && line !== "## QA" && line.includes("## QA") === false && !line.includes("## 3.")) {
177
183
  break;
178
184
  }
185
+ const match = line.match(/^\s*-\s*\[(x|\s)\]\s*(.+)$/i);
186
+ if (match) {
187
+ const isCompleted = match[1].toLowerCase() === "x";
188
+ const descClean = match[2].replace(/\*/g, "").trim().toLowerCase();
189
+ for (const t of lockfile.tasks) {
190
+ const taskClean = t.desc.toLowerCase();
191
+ if (descClean.includes(taskClean) || taskClean.includes(descClean)) {
192
+ t.status = isCompleted ? "completed" : "pending";
193
+ matchedCount++;
194
+ }
195
+ }
196
+ }
197
+ }
198
+ } else {
199
+ // Fallback: buscar - [x] checkboxes en todo el documento
200
+ const lines = reportContent.split("\n");
201
+ for (const line of lines) {
179
202
  const match = line.match(/^\s*-\s*\[(x|\s)\]\s*(.+)$/i);
180
203
  if (match) {
181
204
  const isCompleted = match[1].toLowerCase() === "x";
package/tsconfig.json CHANGED
@@ -6,7 +6,9 @@
6
6
  "lib": ["ES2022"],
7
7
  "allowJs": true,
8
8
  "checkJs": false,
9
- "noEmit": true,
9
+ "noEmit": false,
10
+ "outDir": "./.opencode/tools",
11
+ "rootDir": "./tools",
10
12
  "strict": true,
11
13
  "skipLibCheck": true,
12
14
  "esModuleInterop": true,
package/zugz-models.json CHANGED
@@ -1,4 +1,5 @@
1
1
  {
2
+ "//": "Fuente de verdad: opencode.json. Este archivo existe para referencia rápida. Mantén sincronizado con opencode.json.",
2
3
  "agents": {
3
4
  "zugzbot": "deepseek/deepseek-v4-pro",
4
5
  "sdd-explorer": "deepseek/deepseek-v4-flash",