@tacuchi/agent-workflow-cli 12.5.0 → 12.7.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 (68) hide show
  1. package/dist/adapters/git-cli.d.ts +1 -0
  2. package/dist/adapters/git-cli.d.ts.map +1 -1
  3. package/dist/adapters/git-cli.js +21 -0
  4. package/dist/adapters/git-cli.js.map +1 -1
  5. package/dist/application/merge-state-service.d.ts +37 -0
  6. package/dist/application/merge-state-service.d.ts.map +1 -0
  7. package/dist/application/merge-state-service.js +89 -0
  8. package/dist/application/merge-state-service.js.map +1 -0
  9. package/dist/cli/commands/merge-state.d.ts +3 -0
  10. package/dist/cli/commands/merge-state.d.ts.map +1 -0
  11. package/dist/cli/commands/merge-state.js +28 -0
  12. package/dist/cli/commands/merge-state.js.map +1 -0
  13. package/dist/cli/help-groups.d.ts.map +1 -1
  14. package/dist/cli/help-groups.js +1 -0
  15. package/dist/cli/help-groups.js.map +1 -1
  16. package/dist/cli/main.js +2 -0
  17. package/dist/cli/main.js.map +1 -1
  18. package/dist/cli/tui/components/detail-panel.d.ts +14 -1
  19. package/dist/cli/tui/components/detail-panel.d.ts.map +1 -1
  20. package/dist/cli/tui/components/detail-panel.js +13 -2
  21. package/dist/cli/tui/components/detail-panel.js.map +1 -1
  22. package/dist/cli/tui/row-width.d.ts +19 -0
  23. package/dist/cli/tui/row-width.d.ts.map +1 -0
  24. package/dist/cli/tui/row-width.js +25 -0
  25. package/dist/cli/tui/row-width.js.map +1 -0
  26. package/dist/cli/tui/tabs/mcp-tab.d.ts.map +1 -1
  27. package/dist/cli/tui/tabs/mcp-tab.js +6 -21
  28. package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
  29. package/dist/cli/tui/tabs/project-tab.d.ts.map +1 -1
  30. package/dist/cli/tui/tabs/project-tab.js +11 -12
  31. package/dist/cli/tui/tabs/project-tab.js.map +1 -1
  32. package/dist/cli/tui/tabs/skills-tab.d.ts.map +1 -1
  33. package/dist/cli/tui/tabs/skills-tab.js +10 -16
  34. package/dist/cli/tui/tabs/skills-tab.js.map +1 -1
  35. package/dist/cli/tui/theme.d.ts +2 -2
  36. package/dist/cli/tui/theme.d.ts.map +1 -1
  37. package/dist/cli/tui/theme.js +6 -2
  38. package/dist/cli/tui/theme.js.map +1 -1
  39. package/dist/ports/git.d.ts +5 -0
  40. package/dist/ports/git.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/skills/w/README.md +5 -2
  43. package/skills/w/SKILL.md +21 -6
  44. package/skills/w/artifacts/README.md +2 -2
  45. package/skills/w/artifacts/artifacts-core/TASKS.md +1 -1
  46. package/skills/w/artifacts/{artifacts-dev → artifacts-exec}/TECHNICAL-NOTE.md +1 -1
  47. package/skills/w/commands/README.md +9 -6
  48. package/skills/w/commands/fix-git.md +33 -0
  49. package/skills/w/commands/plan-new.md +1 -1
  50. package/skills/w/commands/quick.md +1 -1
  51. package/skills/w/commands/spec-new.md +11 -8
  52. package/skills/w/exports/README.md +2 -2
  53. package/skills/w/exports/export-diagrams/SKILL.md +1 -1
  54. package/skills/w/exports/export-manuals/SKILL.md +2 -2
  55. package/skills/w/exports/export-reports/SKILL.md +1 -1
  56. package/skills/w/exports/export-scripts/SKILL.md +1 -1
  57. package/skills/w/harness/SKILL.md +85 -0
  58. package/skills/w/loops/README.md +14 -14
  59. package/skills/w/loops/plan-exec-loop/SKILL.md +13 -11
  60. package/skills/w/loops/plan-new-loop/SKILL.md +24 -22
  61. package/skills/w/loops/quick-loop/SKILL.md +10 -8
  62. package/skills/w/loops/spec-refine-loop/SKILL.md +48 -30
  63. package/skills/w/roles/README.md +1 -1
  64. package/skills/w/roles/git/SKILL.md +28 -7
  65. package/skills/w/roles/research/SKILL.md +1 -1
  66. package/skills/w/roles/testing/SKILL.md +2 -2
  67. package/skills/w/roles/ui-spec/SKILL.md +58 -48
  68. /package/skills/w/artifacts/{artifacts-dev → artifacts-exec}/DECISION.md +0 -0
@@ -4,8 +4,8 @@ description: >-
4
4
  El atajo liviano de agent-workflow: resuelve una tarea acotada (un fix, un
5
5
  ajuste pequeño) directamente desde el prompt del usuario, editando código con
6
6
  ceremonia mínima. Heir del chasis spec-refine-loop (motor gap-driven mínimo,
7
- research INLINE con regla BD read-only, AskUserQuestion con ≤3 tabs de
8
- contenido + 1 tab flow Compactar/Cerrar siempre, compact/resume con artefactos
7
+ research INLINE con regla BD read-only, structured-choice con ≤3 preguntas de
8
+ contenido + 1 control flow Compactar/Cerrar siempre, compact/resume con artefactos
9
9
  como log vivo: CHECKPOINT siempre, BACKLOG solo si difiere) y de plan-exec-loop
10
10
  (git seguro: rama esperada antes de editar + commit propuesto, nunca
11
11
  push/--amend/--no-verify; la IA nunca ejecuta DML, migraciones a SCRIPTS.sql;
@@ -43,7 +43,7 @@ QUICK
43
43
 
44
44
  ## Inherits
45
45
 
46
- - del **chasis** [`spec-refine-loop`](../spec-refine-loop/SKILL.md): gap-driven (mínimo), `AskUserQuestion` ≤3 + `flow` (`Compactar`/`Cerrar`), `research` **inline** + regla BD read-only (pregunta MCP si >1 sin default → `SCRIPTS.sql` → ejecuta read-only), compact/resume, **artefactos como log vivo (ciclo artifact-first)** (`CHECKPOINT` siempre; `BACKLOG` solo si difiere).
46
+ - del **chasis** [`spec-refine-loop`](../spec-refine-loop/SKILL.md): gap-driven (mínimo), *structured-choice* ≤3 preguntas de contenido + 1 control `flow` (`Compactar`/`Cerrar`) (capacidad del arnés — ver [`../../harness/SKILL.md`](../../harness/SKILL.md); en Claude Code es `AskUserQuestion`), `research` **inline** + regla BD read-only (pregunta MCP si >1 sin default → `SCRIPTS.sql` → ejecuta read-only), compact/resume, **artefactos como log vivo (ciclo artifact-first)** (`CHECKPOINT` siempre; `BACKLOG` solo si difiere).
47
47
  - de [`plan-exec-loop`](../plan-exec-loop/SKILL.md): **git** (rama segura antes de editar + commit propuesto; nunca `push`/`--amend`/`--no-verify`), **BD** (la IA nunca ejecuta DML; migraciones → `SCRIPTS.sql` de la session), **sin auto-export** (no toca otras carpetas `docs/`).
48
48
 
49
49
  ## Composes
@@ -72,19 +72,19 @@ quick-loop(prompt):
72
72
  si consulta BD read-only → SCRIPTS.sql + ejecutar read-only
73
73
  si cambio BD (DDL/DML) → SCRIPTS.sql (artefacto session, NO ejecutar)
74
74
  si decisión no obvia → DECISION
75
- si duda/gap → research inline ó AskUserQuestion # chasis
75
+ si duda/gap → research inline ó structured-choice # chasis
76
76
  si la tarea CRECE → proponer escalar a SPEC/PLAN
77
77
  si acepta → handoff (código queda; BACKLOG→spec/plan sembrado) → goto finalize
78
78
  validación puntual (test si aplica)
79
79
  proponer commit (aprobar antes) # nunca push/amend/--no-verify
80
- AskUserQuestion(contenido: [Cerrar tarea, Preguntar algo más], flow: [Compactar, Cerrar])
80
+ structured_choice(contenido: [Cerrar tarea, Preguntar algo más], flow: [Compactar, Cerrar])
81
81
  finalize: CHECKPOINT (DESPUÉS: Pending→Completed) + BACKLOG (solo si queda algo diferido) + cerrar session + reportar
82
82
  ```
83
83
 
84
84
  ```mermaid
85
85
  flowchart TD
86
86
  S["create_or_resume session NNN-<slug>-quick"] --> G["branch-check por fuente"]
87
- G -->|ok| DO["editar código · BD→SCRIPTS.sql · DECISION<br/>(duda→research inline/AskUserQuestion)"]
87
+ G -->|ok| DO["editar código · BD→SCRIPTS.sql · DECISION<br/>(duda→research inline/structured-choice)"]
88
88
  G -->|rama ≠| PA["pausar + resolver"]
89
89
  PA --> G
90
90
  DO --> GROW{"¿la tarea creció?"}
@@ -92,12 +92,14 @@ flowchart TD
92
92
  ESC --> FIN
93
93
  GROW -->|no| V["validación puntual"]
94
94
  V --> CM["proponer commit (aprobar)"]
95
- CM --> Q["AskUserQuestion[Cerrar · Preguntar más]<br/>flow[Compactar · Cerrar]"]
95
+ CM --> Q["structured-choice[Cerrar · Preguntar más]<br/>flow[Compactar · Cerrar]"]
96
96
  Q --> FIN["finalize: CHECKPOINT + BACKLOG + cerrar"]
97
97
  ```
98
98
 
99
99
  ## Convergence / exit
100
100
 
101
101
  - Tarea hecha + commit (o aprobado saltarlo) → `Cerrar`.
102
- - `Cerrar`/`Compactar` (tab flow) → persiste `CHECKPOINT` + `BACKLOG` (reanudable).
102
+ - `Cerrar`/`Compactar` (control `flow`) → persiste `CHECKPOINT` + `BACKLOG` (reanudable).
103
103
  - **Sin export**: nada va a `docs/`. Si algo amerita preservarse → se promueve aparte vía `export-*`, o se escala a SPEC/PLAN.
104
+
105
+ > La **validación puntual** es el *convergence gate* de QUICK: la **excepción deliberada lightweight** del chasis (sin checklist formal) — se reduce a "¿el cambio hace lo que pedía el prompt? (test si aplica)". Mínima ceremonia por diseño.
@@ -9,7 +9,7 @@ description: >-
9
9
  (lo que se responde leyendo el repo/datos), integra y repite hasta converger.
10
10
  Compone la capacidad ui-design (built-in ui-spec) cuando el requerimiento
11
11
  involucra UI. Lo arranca el comando /w:spec-refine y es reanudable vía
12
- CHECKPOINT. Usa AskUserQuestion con ≤3 tabs de contenido + 1 tab flow
12
+ CHECKPOINT. Usa structured-choice con ≤3 preguntas de contenido + 1 control flow
13
13
  (Compactar/Cerrar) siempre presente; mantiene sus artefactos como log vivo
14
14
  (CHECKPOINT siempre, BACKLOG solo si difiere). Es el patrón de referencia que
15
15
  heredan plan-new-loop, plan-exec-loop y quick-loop. Invocar cuando haya que
@@ -24,13 +24,13 @@ description: >-
24
24
  SPEC
25
25
 
26
26
  ## Layer
27
- 2 — la IA lo corre entero (gap-driven). El usuario no conduce el ciclo; solo responde tabs de contenido y dirige el ciclo de vida por el tab `flow`.
27
+ 2 — la IA lo corre entero (gap-driven). El usuario no conduce el ciclo; solo responde preguntas de contenido y dirige el ciclo de vida por el control `flow`.
28
28
 
29
29
  ## Started by
30
30
  `/w:spec-refine` — **reanudable**. Detecta el estado previo (vía CHECKPOINT) y arranca según corresponda (ver *Compact / resume*).
31
31
 
32
32
  ## Reads
33
- - `docs/specs/NNN-spec*.md` (glob — localiza el spec por número, también captura el legacy `NNN-spec.md`), **o** la ruta exacta pasada en `$ARGUMENTS`. **Siempre el spec mismo**: este loop lo edita in place, no hay un archivo "refined" aparte.
33
+ - `docs/specs/NNN-spec*.md` (glob — localiza el spec por número, también captura el legacy `NNN-spec.md`), **o** la ruta exacta pasada en el argumento del comando. **Siempre el spec mismo**: este loop lo edita in place, no hay un archivo "refined" aparte.
34
34
 
35
35
  ## Writes
36
36
  Actualiza `docs/specs/NNN-spec-<slug>.md` **in place** (cuando el usuario elige `Guardar especificación refinada`): completa secciones y **agrega** `## Refinement decisions` + `## Q&A traceability`, cerrando `Open questions` a medida que se resuelven. Como sobrescribe un doc existente, **con confirmación** del usuario.
@@ -65,7 +65,7 @@ El loop crea y maneja su session en `.workflow/sessions/`. El usuario nunca la c
65
65
 
66
66
  El **CLI es dueño del número**: `aw session-create` antepone un `NNN` **global y secuencial** escaneando **todas** las sessions de `.workflow/sessions/` (cualquier tipo). El caller pasa **solo el descriptor** vía `--name` — **nunca** un número. Así la numeración no se reinicia por tipo ni colisiona (ej.: `001-spec-refine`, `002-plan-new`, `003-plan-exec`, …).
67
67
 
68
- > `<run>` = el **descriptor** (sin número) de la session del run: `spec-refine`, `plan-new`, `plan-exec`, `quick`. Como la investigación es **inline** en esta misma session, ya no hay sessions hijas `*-research-*` que numerar (compat: las viejas son históricas).
68
+ > `<run>` = el **descriptor** (sin número) de la session del run: `spec-refine`, `plan-new`, `plan-exec`; QUICK usa `<slug>-quick` (slug del prompt). Como la investigación es **inline** en esta misma session, ya no hay sessions hijas `*-research-*` que numerar (compat: las viejas son históricas).
69
69
  >
70
70
  > **Resume**: localiza la session existente **escaneando** `.workflow/sessions/` por descriptor + `## Origin` (qué spec/plan), **no** reconstruyendo el número (que es global, no derivable del artefacto). `aw session-resume --code <NNN | folder>` resuelve ambas formas.
71
71
 
@@ -76,7 +76,7 @@ El **CLI es dueño del número**: `aw session-create` antepone un `NNN` **global
76
76
 
77
77
  ## Composes
78
78
 
79
- Cuando el requerimiento involucra **UI**, compone la capacidad **`ui-design`** (default built-in `ui-spec`; rebindeable vía `.workflow/skills.toml`): autora el UI spec nativamente (esquema `Screen`, vocabulario, formato). El loop aporta la iteración/Q&A que el viejo servicio no tenía (design-system, tema, variantes, desambiguación) y lo integra como sección `## UI spec` del spec.
79
+ El gap **UI sin especificar** (cuando el requerimiento involucra UI; ver *Gap taxonomy*) se resuelve **componiendo** la capacidad **`ui-design`** (default built-in `ui-spec`; rebindeable vía `.workflow/skills.toml`): autora el UI spec nativamente (estructura, vocabulario, formato Markdown). Es un tercer modo de resolución de gap (junto a *research* y *humano*): el loop aporta la iteración/Q&A que el viejo servicio no tenía (design-system, tema, variantes, desambiguación) **vía la misma structured-choice**, y lo integra como sección `## UI spec` del spec.
80
80
 
81
81
  Otras capacidades transversales que el chasis usa siempre: `research` (research **inline**, ver abajo), `sql` (regla BD en research), `writing` (redacción del spec). Todas se resuelven por config; `off` → el loop sigue sin la capacidad y, si era necesaria, lo dice o pregunta.
82
82
 
@@ -89,14 +89,15 @@ El spec se completa **in place**: mismas secciones del borrador **completadas**
89
89
 
90
90
  > Refinado in place por spec-refine-loop
91
91
 
92
+ ## Origin (opt. — se conserva del borrador)
92
93
  ## Requirement (afinado, sin ambigüedad)
93
94
  ## Context (completo)
94
95
  ## Scope (In / Out claros)
95
- ## Acceptance criteria (testables, - [ ])
96
+ ## Acceptance criteria (testables, - [ ]; estilo EARS / Given-When-Then recomendado)
96
97
  ## Assumptions (declarados)
97
98
 
98
99
  ## UI spec (opt. — si involucra UI; vía capacidad ui-design / skill ui-spec)
99
- Screen (JSON) + render Markdown.
100
+ Descripción estructurada en Markdown (pantallas → regiones/componentes). Ver [`ui-spec`](../../roles/ui-spec/SKILL.md).
100
101
 
101
102
  ## Refinement decisions ← NEW (se AGREGA)
102
103
  Qué se definió al refinar y por qué. Incluye lo resuelto vía research inline
@@ -108,6 +109,10 @@ Cada duda preguntada al humano + la respuesta elegida.
108
109
  ## Open questions (idealmente "None"; lo que quede se difiere)
109
110
  ```
110
111
 
112
+ > **Marca de refinado (contrato con PLAN):** la presencia de `## Refinement decisions` + `## Q&A traceability` distingue un spec refinado de un borrador — plan-new lo detecta así, NO por el nombre del archivo; sin esas 2 secciones plan-new hace soft-suggest de spec-refine.
113
+
114
+ > **Acceptance criteria = criterios testables estáticos** (el "qué"): plan-exec los valida pero el avance se trackea en el PLAN (sus Tasks), no marcando estos `- [ ]` en el spec; el spec no muta por ejecución, solo por re-refine.
115
+
111
116
  ## Gap taxonomy (= weak sections of the schema)
112
117
 
113
118
  `detect_gaps(work)` busca estas señales; cada una tiene un resolutor:
@@ -121,22 +126,23 @@ Cada duda preguntada al humano + la respuesta elegida.
121
126
  | Open questions abiertas | dudas explícitas | según naturaleza |
122
127
  | Supuestos ocultos | el spec asume cosas no dichas | **research** valida / **humano** confirma |
123
128
  | Contradicción interna | secciones que se contradicen | **humano** |
129
+ | UI sin especificar *(si aplica)* | el requerimiento involucra UI pero falta `## UI spec` | **capacidad `ui-design`** |
124
130
 
125
131
  ## Ask-vs-research rule (el discriminador)
126
132
 
127
133
  Para cada gap, una sola pregunta decide el resolutor:
128
134
 
129
135
  > *"¿Puedo responder esto leyendo el repo/datos?"* → **research** (autónomo).
130
- > *"¿Depende de lo que el usuario quiere?"* → **preguntar al humano** (AskUserQuestion).
136
+ > *"¿Depende de lo que el usuario quiere?"* → **preguntar al humano** (structured-choice).
131
137
 
132
138
  ## Research: autonomy, scope & failure
133
139
 
134
140
  La investigación es **inline**: una actividad **dentro de la session actual del run**, no una session aparte. Escribe sus artefactos (`ANALYSIS-FILE` → `CONCLUSIONS`, + `SCRIPTS.sql` read-only si consulta BD) en la **carpeta de la propia session**.
135
141
 
136
- - **Autónomo**: la IA investiga inline y reporta **sin pedir permiso**. El humano se entera al integrarse (en `Refinement decisions`) y mantiene control vía el tab `flow`.
142
+ - **Autónomo**: la IA investiga inline y reporta **sin pedir permiso**. El humano se entera al integrarse (en `Refinement decisions`) y mantiene control vía el control `flow`.
137
143
  - **Alcance**: workspace + repos asociados (fuentes) + MCPs de BD.
138
144
  - **Regla BD** (única excepción a la autonomía):
139
- 1. **Elección de MCP**: si el gap requiere BD y hay **>1 MCP candidato sin default configurado**, la IA pregunta cuál usar. Esa pregunta va por el **mismo `AskUserQuestion`** como un **tab de contenido** (cuenta dentro del límite ≤3 + `flow`), **antes** de ejecutar queries. Si hay un único MCP o un default, no pregunta.
145
+ 1. **Elección de MCP**: si el gap requiere BD y hay **>1 MCP candidato sin default configurado**, la IA pregunta cuál usar. Esa pregunta va por la **misma structured-choice** como una **pregunta de contenido** (cuenta dentro del límite ≤3 + `flow`), **antes** de ejecutar queries. Si hay un único MCP o un default, no pregunta.
140
146
  2. Escribe **primero** las queries en `SCRIPTS.sql` de la session.
141
147
  3. Las ejecuta **read-only** vía MCP (respeta `sql-mutation-guard`: nunca DML/DDL).
142
148
  - **Research inconclusa** (BD no disponible, evidencia insuficiente, gap factual irresoluble):
@@ -144,11 +150,13 @@ La investigación es **inline**: una actividad **dentro de la session actual del
144
150
  - El loop **degrada** el gap: lo pasa a **pregunta-al-humano** (próximo batch → `Q&A traceability`) o, si tampoco aplica, lo **difiere** a `## Open questions` del spec.
145
151
  - El gap se marca **"ya intentado vía research"** (`attempts[gap]++`, límite `MAX`) para que `detect_gaps` **no lo re-dispare en bucle** → garantiza convergencia.
146
152
 
147
- ## AskUserQuestion (design & batching)
153
+ ## Structured-choice (design & batching)
154
+
155
+ *structured-choice* (capacidad del arnés — ver `../../harness/SKILL.md`). En **Claude Code** es `AskUserQuestion` (máx 4 preguntas/llamada → **≤3 preguntas de contenido + 1 control `flow`**); en un arnés sin elección estructurada, degrada a **markdown numerado**.
148
156
 
149
- - Límite del host: **máx 4 preguntas/llamada**. Como el tab `flow` va **siempre** → **≤3 tabs de contenido + 1 tab `flow`**.
150
- - **tab `flow`** (ciclo de vida, siempre presente): `Compactar` | `Cerrar`. Responder solo los tabs de contenido (sin tocar `flow`) = seguir iterando.
151
- - **Tabs de contenido** posibles:
157
+ - Como el control `flow` va **siempre** → **≤3 preguntas de contenido + 1 control `flow`**.
158
+ - **control `flow`** (ciclo de vida, siempre presente): `Compactar` | `Cerrar`. Responder solo las preguntas de contenido (sin tocar `flow`) = seguir iterando.
159
+ - **Preguntas de contenido** posibles:
152
160
  - dudas-de-humano (gaps no factuales);
153
161
  - elección de MCP (regla BD) — antes de ejecutar queries;
154
162
  - en **convergencia**, acción: `Guardar especificación refinada` | `Preguntar algo más`.
@@ -158,7 +166,7 @@ La investigación es **inline**: una actividad **dentro de la session actual del
158
166
 
159
167
  ```
160
168
  spec-refine-loop(spec):
161
- input = glob(NNN-spec*.md) | $ARGUMENTS path # siempre el spec mismo (in place)
169
+ input = glob(NNN-spec*.md) | argumento (ruta) # siempre el spec mismo (in place)
162
170
  refine_session = create_or_resume("spec-refine") # CLI antepone NNN global; resume localiza por descriptor/origin
163
171
  work = read(input) (+ aplicar avance del checkpoint si reanuda)
164
172
  attempts = {} # anti-relanzamiento por gap
@@ -168,7 +176,10 @@ spec-refine-loop(spec):
168
176
  batch = top ≤3 gaps ; pending_human = []
169
177
  seed CHECKPOINT.Pending/Next = batch (refine_session) # ANTES: sembrar intención (artifact-first)
170
178
  para cada gap en batch:
171
- si factual(gap) y attempts[gap] < MAX:
179
+ si gap = UI (requerimiento con UI, falta ## UI spec):
180
+ componer ui-design → autora ## UI spec # design-system/tema vía structured-choice (cuenta en el batch)
181
+ work = integrate(work, ui) # → ## UI spec
182
+ si no, si factual(gap) y attempts[gap] < MAX:
172
183
  si requiere BD y >1 MCP sin default → encolar "elección MCP" en pending_human
173
184
  res = research_inline(gap) # en la session actual: ANALYSIS-FILE → CONCLUSIONS (+SCRIPTS.sql read-only)
174
185
  si res.concluyente: work = integrate(work, res) # → Refinement decisions
@@ -177,15 +188,17 @@ spec-refine-loop(spec):
177
188
  pending_human.push(gap)
178
189
  update CHECKPOINT (refine_session) # DESPUÉS: Pending→Completed, en cada límite de gap (ver ciclo artifact-first)
179
190
  si pending_human no vacío:
180
- ans = AskUserQuestion(contenido: pending_human (≤3), flow: [Compactar, Cerrar])
191
+ ans = structured_choice(contenido: pending_human (≤3), flow: [Compactar, Cerrar])
181
192
  switch(flow):
182
- Compactar → write CHECKPOINT (refine_session) ; /compact ; continue
193
+ Compactar → write CHECKPOINT (refine_session) ; compactar(arnés) ; continue
183
194
  Cerrar → goto finalize
184
195
  work = integrate(work, ans) # → Q&A traceability / Open questions
185
- # convergió:
186
- ans = AskUserQuestion(contenido: [Guardar refinada, Preguntar algo más],
196
+ # sin gaps materiales → analyze gate (read-only) antes de ofrecer Guardar:
197
+ issues = analyze(work) # criterios trazan al Requirement · sin contradicciones · Scope coherente · Open questions cerradas/diferidas
198
+ si issues: gaps += issues ; continue # los hallazgos vuelven al loop como gaps
199
+ ans = structured_choice(contenido: [Guardar refinada, Preguntar algo más],
187
200
  flow: [Compactar, Cerrar])
188
- Guardar → edit_in_place_with_confirm(spec) # completa secciones + agrega Refinement decisions/Q&A ; goto finalize
201
+ Guardar → edit_in_place_with_confirm(spec) # completa secciones + inserta UI spec/Refinement decisions/Q&A ; goto finalize
189
202
  Preguntar algo más → continue
190
203
  flow Compactar/Cerrar → manejar igual
191
204
  finalize:
@@ -197,20 +210,24 @@ finalize:
197
210
  ```mermaid
198
211
  flowchart TD
199
212
  S["input = glob NNN-spec*.md (el spec mismo)<br/>create_or_resume refine session"] --> D{"¿gaps<br/>(no agotados)?"}
200
- D -->|no| C["AskUserQuestion<br/>contenido[Guardar refinada · Preguntar más]<br/>flow[Compactar · Cerrar]"]
213
+ D -->|no| AN{"analyze gate<br/>criterios↔Requirement · sin contradicciones<br/>Scope · Open questions cerradas/diferidas"}
214
+ AN -->|falla| D
215
+ AN -->|ok| C["structured-choice<br/>contenido[Guardar refinada · Preguntar más]<br/>flow[Compactar · Cerrar]"]
201
216
  D -->|sí| B["tomar ≤3 gaps"]
202
- B --> F{"¿factual y<br/>attempts<MAX?"}
203
- F -->|sí| RS["research INLINE en la session<br/>ANALYSIS-FILE CONCLUSIONS (+SCRIPTS.sql)"]
217
+ B --> K{"tipo de gap"}
218
+ K -->|UI| UI["componer ui-design<br/>→ ## UI spec (design-system/tema vía structured-choice)"]
219
+ K -->|factual y attempts&lt;MAX| RS["research INLINE en la session<br/>ANALYSIS-FILE → CONCLUSIONS (+SCRIPTS.sql)"]
220
+ K -->|humano| Q["structured-choice<br/>contenido[dudas + elección MCP ≤3]<br/>flow[Compactar · Cerrar]"]
204
221
  RS --> CC{"¿concluyente?"}
205
222
  CC -->|sí| I1["integrar → Refinement decisions"]
206
223
  CC -->|no| DEG["attempts++ ; degradar a humano / Open questions"]
207
- F -->|no| Q["AskUserQuestion<br/>contenido[dudas + elección MCP ≤3]<br/>flow[Compactar · Cerrar]"]
208
224
  Q --> I2["integrar → Q&A traceability"]
209
- I1 --> CK["update CHECKPOINT (Pending→Completed)"]
225
+ UI --> CK["update CHECKPOINT (Pending→Completed)"]
226
+ I1 --> CK
210
227
  DEG --> CK
211
228
  I2 --> CK
212
229
  CK --> D
213
- C -->|Guardar| W["edit IN PLACE con confirmación<br/>completa + agrega Refinement decisions/Q&A"]
230
+ C -->|Guardar| W["edit IN PLACE con confirmación<br/>completa + inserta UI spec/Refinement decisions/Q&A"]
214
231
  C -->|Preguntar más| D
215
232
  W --> FIN["finalize: CHECKPOINT (+ BACKLOG si difiere)<br/>+ cerrar session + reportar"]
216
233
  ```
@@ -223,18 +240,19 @@ El resume **keya off el `CHECKPOINT`** de la refine session, no de la existencia
223
240
  2. **Sin avance** (no hay CHECKPOINT y el spec **no** tiene `Refinement decisions`/`Q&A traceability`) → arranca desde cero leyendo el spec (`NNN-spec*.md`).
224
241
  3. **Ya refinado** (no hay CHECKPOINT abierto pero el spec **ya tiene** `Refinement decisions`/`Q&A traceability`) → re-refinamiento incremental leyendo el **spec mismo**; al `Guardar`, edita in place con confirmación.
225
242
 
226
- > **`Compactar`** (tab flow, transversal a los 3 casos) → escribe `CHECKPOINT.md` en la refine session (spec en progreso, gaps restantes, Q&A, `attempts`) → dispara `/compact` del host → reanuda leyendo el checkpoint.
243
+ > **`Compactar`** (control `flow`, transversal a los 3 casos) → escribe `CHECKPOINT.md` en la refine session (spec en progreso, gaps restantes, Q&A, `attempts`) → dispara la **compactación** del arnés (en Claude Code: `/compact`; ver `../../harness/SKILL.md`) → reanuda leyendo el checkpoint.
227
244
 
228
245
  ## Convergence / exit
229
246
 
230
- - **Sin gaps materiales** → ofrece `Guardar especificación refinada`.
247
+ - **Sin gaps materiales** → **analyze gate** (read-only): cada acceptance criterion traza al `Requirement`, sin contradicciones internas, `Scope` In/Out coherente, `Open questions` cerradas o explícitamente diferidas. Lo que falle **vuelve como gap**; si pasa → ofrece `Guardar especificación refinada`. *(Es el "convergence gate" del chasis; heirs: plan-new = coherencia del plan, plan-exec = validación final, quick = validación puntual — excepción lightweight.)*
231
248
  - `Guardar` → `edit_in_place_with_confirm(spec)` y `finalize`.
232
- - `Cerrar` (tab flow, en cualquier momento) → `finalize`. **`finalize` persiste siempre el `CHECKPOINT.md`** (reanudable) y, **solo si hay algo diferido/followup**, escribe `BACKLOG.md` (motivo de cierre + `Open questions` diferidas); cierra la session y reporta. Así sobrevive el avance aunque no se haya `Compactar` antes.
249
+ - `Cerrar` (control `flow`, en cualquier momento) → `finalize`. **`finalize` persiste siempre el `CHECKPOINT.md`** (reanudable) y, **solo si hay algo diferido/followup**, escribe `BACKLOG.md` (motivo de cierre + `Open questions` diferidas); cierra la session y reporta. Así sobrevive el avance aunque no se haya `Compactar` antes.
233
250
 
234
251
  ## Integration (dónde aterriza cada resolución)
235
252
 
236
253
  - Resuelto vía **research inline** → `## Refinement decisions` del spec (+ ref a las `CONCLUSIONS` de la session).
237
254
  - Resuelto vía **humano** → `## Q&A traceability` del spec.
255
+ - Resuelto vía **capacidad `ui-design`** (gap UI) → sección `## UI spec` del spec.
238
256
  - **Research inconclusa o sin resolver** → `## Open questions` del spec (diferido) + `BACKLOG.md` de la refine session (solo si queda algo diferido).
239
257
 
240
258
  ## Heredan este chasis
@@ -12,7 +12,7 @@ All 10 roles, their built-in defaults, their tier, and which loops/exports compo
12
12
 
13
13
  | Role | Default built-in | Tier | Composed by |
14
14
  |---|---|---|---|
15
- | `ui-design` | [`ui-spec`](../ui-spec/SKILL.md) | must | `spec-refine-loop` (when requirement involves UI) |
15
+ | `ui-design` | [`ui-spec`](ui-spec/SKILL.md) | must | `spec-refine-loop` (when requirement involves UI) |
16
16
  | `sql` | `sql` | must | inline research · `plan-exec-loop` · `quick-loop` · `export-scripts` |
17
17
  | `git` | `git` | must | `plan-exec-loop` · `quick-loop` |
18
18
  | `coding-standards` | `coding-standards` | must | `plan-exec-loop` · `quick-loop` |
@@ -6,7 +6,8 @@ description: >-
6
6
  commits when the user approves, and NEVER runs push, --amend, --no-verify, force,
7
7
  merge/rebase/cherry-pick, tags, or destructive resets without explicit user request.
8
8
  Read-only git (status/log/diff/branch) is always allowed. Use when a loop is about
9
- to edit code or when the user asks to commit / save / push changes.
9
+ to edit code, when the user asks to commit / save / push changes, or to resolve an
10
+ in-progress merge conflict (via /w:fix-git).
10
11
  ---
11
12
 
12
13
  # git — git-safe capability
@@ -23,6 +24,7 @@ Operar git de forma **segura y controlada**: verificar la rama esperada antes de
23
24
 
24
25
  - **`plan-exec-loop`** — verifica rama antes de cada edit; propone commits al cerrar/checkpoint.
25
26
  - **`quick-loop`** — igual, en el atajo liviano.
27
+ - **`/w:fix-git`** (comando transversal) — compone la sección *Resolución de conflictos de merge* para resolver un merge en curso en cualquier repo.
26
28
 
27
29
  (Cualquier flujo que edite código o que el usuario quiera commitear lo usa.)
28
30
 
@@ -40,9 +42,11 @@ Lista cerrada. La IA **nunca** las ejecuta por iniciativa propia:
40
42
 
41
43
  Y **siempre** prohibido, aún cuando el usuario pida commit: `--no-verify` (respetar los hooks pre-commit), `--force`, trailers `Co-Authored-By`, firmas de modelo.
42
44
 
45
+ > **Excepción — merge en curso:** resolver los conflictos de un merge **ya iniciado** (MERGE_HEAD), o iniciado a pedido **explícito** del usuario vía `/w:fix-git`, **sí** está permitido (es solicitud explícita, no iniciativa propia) — ver *Resolución de conflictos de merge*.
46
+
43
47
  ### Operaciones read-only (siempre permitidas, sin preguntar)
44
48
 
45
- `status` · `log` · `diff` · `branch --show-current` · `rev-parse` · `show`. `git checkout` (cambio de rama) **no** es read-only: requiere `AskUserQuestion` aunque no sea destructivo (ver verificación de rama).
49
+ `status` · `log` · `diff` · `branch --show-current` · `rev-parse` · `show`. `git checkout` (cambio de rama) **no** es read-only: requiere *structured-choice* (capacidad del arnés — ver `../../harness/SKILL.md`; en **Claude Code** es `AskUserQuestion`, máx 4 preguntas/llamada → **≤3 preguntas de contenido + 1 control `flow`**; sin elección estructurada degrada a **markdown numerado**) aunque no sea destructivo (ver verificación de rama).
46
50
 
47
51
  ### Verificación de rama (antes de editar)
48
52
 
@@ -53,9 +57,9 @@ Campos por fuente: `alias`, `path`, `main_branch` (base, default `certificacion`
53
57
  Casos:
54
58
 
55
59
  - **`match=true`** → OK, editar.
56
- - **`match=false, dirty=false`** (Caso A — rama distinta, repo limpio) → `AskUserQuestion`: hacer `git checkout <expected>` / mantener current y actualizar la expectativa de la sesión / cancelar.
60
+ - **`match=false, dirty=false`** (Caso A — rama distinta, repo limpio) → *structured-choice*: hacer `git checkout <expected>` / mantener current y actualizar la expectativa de la sesión / cancelar.
57
61
  - **`match=false, dirty=true`** (Caso B — rama distinta + cambios sin commit) → **pausar y esperar resolución manual**. No proponer checkout (podría perder trabajo). Pedir al usuario commit/stash/discard y avisar cuando continuar.
58
- - **Cross-fuente (hub)**: si las fuentes tocadas apuntan a ramas distintas sin declararlo, **hard gate** — bloquear avance con `AskUserQuestion` (alinear todas / declarar divergencia explícita / cancelar).
62
+ - **Cross-fuente (hub)**: si las fuentes tocadas apuntan a ramas distintas sin declararlo, **hard gate** — bloquear avance con *structured-choice* (alinear todas / declarar divergencia explícita / cancelar).
59
63
  - **HEAD detached** → tratar como Caso A.
60
64
  - **Fuente fuera de git** (`is_repo=false`) → informar, no bloquear.
61
65
 
@@ -64,14 +68,14 @@ Casos:
64
68
  Ante cualquier pedido o disparo de commit (cierre de loop, "commitea esto", "guardá los cambios"):
65
69
 
66
70
  1. Resolver las fuentes y su estado dirty/rama.
67
- 2. Si hay 1+ fuentes `dirty=true`, invocar **una sola** `AskUserQuestion` con un tab por fuente dirty (máx 4 simultáneas; si N>4, en tandas):
68
- - Header del tab: el `alias` de la fuente.
71
+ 2. Si hay 1+ fuentes `dirty=true`, invocar **una sola** *structured-choice* con una pregunta de contenido por fuente dirty (máx 4 simultáneas → **≤3 preguntas de contenido + 1 control `flow`**; si N>3, en tandas):
72
+ - Header de la pregunta: el `alias` de la fuente.
69
73
  - Opciones: "Aprobar sugerido (Recomendado)" con el mensaje canónico / "Saltar esta fuente". `Other` = mensaje custom.
70
74
  3. Ejecutar `git -C <path> commit -m "<msg>"` solo en las fuentes aprobadas, **una a una**. Respetar hooks (sin `--no-verify`).
71
75
  4. Si una fuente tiene `match=false` (rama distinta a la esperada): **omitirla y abortar su commit**; avisar para alinear la rama primero.
72
76
  5. Si todas están `dirty=false` → skip silencioso, informar en chat que no hay nada que commitear.
73
77
 
74
- **Bypass** (Regla 5): si el usuario aporta el mensaje literal exacto (`-m "..."`, comillas), commitear directo sin `AskUserQuestion`, pero seguir validando rama, hooks y formato. Si el literal viola el formato, avisar antes de ejecutar.
78
+ **Bypass** (Regla 5): si el usuario aporta el mensaje literal exacto (`-m "..."`, comillas), commitear directo sin *structured-choice*, pero seguir validando rama, hooks y formato. Si el literal viola el formato, avisar antes de ejecutar.
75
79
 
76
80
  ### Formato canónico del mensaje
77
81
 
@@ -89,6 +93,23 @@ fix(session018): corrige drift en hooks.json
89
93
 
90
94
  Fuera de sesión activa: relajar a "1 línea + sin co-author"; el tag `session<NNN>` se omite. El propose-then-execute sigue activo.
91
95
 
96
+ ### Resolución de conflictos de merge
97
+
98
+ `git merge` autónomo está prohibido (arriba), **pero** resolver un merge **ya en curso** (MERGE_HEAD) o invocado por el usuario vía `/w:fix-git` **sí** es trabajo sancionado. **Agnóstico al workspace**: opera sobre cualquier repo (no requiere `.workflow/`, flows ni sesiones).
99
+
100
+ 1. **Detectar + identificar** con `aw merge-state [<path>|--source <alias>|--all]` (read-only): `is_merging`, `current_branch` (**destino / ours**), `merge_origin` (**origen / theirs**), `conflicted_files`. Si `merge_origin` viene vacío, mirar `.git/MERGE_MSG` o `git log --oneline -1 MERGE_HEAD`.
101
+ 2. **Analizar la intención** de cada conflicto **antes** de resolver — nunca elegir un lado a ciegas:
102
+ - Las tres versiones: `git show :1:<file>` (base) · `:2:<file>` (ours/destino) · `:3:<file>` (theirs/origen).
103
+ - El porqué de cada lado: `git log --merge -p -- <file>`; el historial del hunk en cada rama.
104
+ - El código alrededor del marcador (coherencia con el resto del archivo).
105
+ 3. **Resolver** editando el archivo (quitar `<<<<<<<` / `=======` / `>>>>>>>`): elegir **ours**, **theirs**, **combinar** ambas intenciones, o **reescribir** para satisfacer las dos. `git add <file>` lo resuelto.
106
+ 4. **Preguntar** (*structured-choice*) cuando la intención es **ambigua** o los dos lados son **incoherentes** entre sí (no combinables sin perder algo): una pregunta de contenido por archivo/hunk dudoso (≤3 + control `flow`), opciones "Ours (`<destino>`)" / "Theirs (`<origen>`)" / "Combinar" / "Editar manual". **No inventar** una resolución cuando hay duda real.
107
+ 5. **Commit propuesto**: completar el merge es un `git commit` (el merge commit) → **propose-then-execute** como cualquier commit (formato canónico de arriba; fuera de sesión → 1 línea sin tag `session<NNN>`; nunca `--no-verify`/`--amend`/`push`). El hook `git-commit-advisor` lo gatea.
108
+ 6. **Escape**: si el merge no debe completarse, `git merge --abort` **tras confirmación** del usuario (*structured-choice*) — deja el repo como antes del merge.
109
+
110
+ > **Resume por git**: el estado del merge en `.git` (MERGE_HEAD + índice) **es** el checkpoint; re-correr `/w:fix-git` reanuda desde los conflictos que queden. No hay session ni artefacto.
111
+ > **Rebase / cherry-pick**: fuera de v1 (misma resolución de markers; distinto `--continue` / `REBASE_HEAD`).
112
+
92
113
  ## Output
93
114
 
94
115
  Ninguno en `docs/`. Produce commits **solo** cuando el usuario aprueba, en los repos fuente. La verificación de rama puede actualizar la expectativa de rama de la sesión si el usuario lo elige.
@@ -24,7 +24,7 @@ El discriminador clave:
24
24
  | La pregunta... | Acción |
25
25
  |---|---|
26
26
  | puede responderse leyendo repo / datos (hechos objetivos del sistema) | **investigar** |
27
- | depende de preferencias, prioridades o decisiones del usuario | **preguntar al humano** vía `AskUserQuestion` |
27
+ | depende de preferencias, prioridades o decisiones del usuario | **preguntar al humano** vía *structured-choice* (capacidad del arnés — ver `../../harness/SKILL.md`). En **Claude Code** es `AskUserQuestion` (máx 4 preguntas/llamada → **≤3 preguntas de contenido + 1 control `flow`**); en un arnés sin elección estructurada, degrada a **markdown numerado**. |
28
28
  | está parcialmente en el repo y parcialmente en intención del usuario | investigar primero, luego preguntar solo por la parte incierta |
29
29
 
30
30
  ## Composed by
@@ -28,10 +28,10 @@ Dar a los loops la capacidad de razonar sobre tests: qué nivel aplicar, con qu
28
28
 
29
29
  ### Execution rule
30
30
 
31
- Por defecto, **no ejecutar pruebas automáticamente**. Antes de correr cualquier test runner:
31
+ Por defecto, **no ejecutar pruebas automáticamente**. Antes de correr cualquier test runner, preguntar al humano vía *structured-choice* (capacidad del arnés — ver `../../harness/SKILL.md`). En **Claude Code** es `AskUserQuestion` (máx 4 preguntas/llamada → **≤3 preguntas de contenido + 1 control `flow`**); en un arnés sin elección estructurada, degrada a **markdown numerado**.
32
32
 
33
33
  ```
34
- AskUserQuestion:
34
+ structured-choice:
35
35
  "¿Correr los tests?"
36
36
  [a] Sí, el loop los ejecuta
37
37
  [b] Los corro yo manualmente
@@ -2,12 +2,12 @@
2
2
  name: ui-spec
3
3
  description: >-
4
4
  UI spec authoring — built-in default for the `ui-design` capability. Given a UI
5
- requirement, author a structured, framework-agnostic screen specification (the
6
- universal `Screen` model in JSON) plus its readable Markdown render. Knows the
7
- `Screen` schema, the kind/region vocabulary, the authoring rules, design-system /
8
- theme / variant handling, and the exact Markdown render format. Use when a loop is
9
- refining a spec that involves screens, forms, dashboards, modals or any UI surface
10
- — primarily `spec-refine-loop`. Recycled from the `ui-spec-generator` service.
5
+ requirement, author a structured, framework-agnostic screen specification as
6
+ **Markdown** (single output format). Knows the conceptual screen structure, the
7
+ kind/region vocabulary, the authoring rules, design-system / theme / variant
8
+ handling, and the exact Markdown render format. Use when a loop is refining a spec
9
+ that involves screens, forms, dashboards, modals or any UI surface — primarily
10
+ `spec-refine-loop`. Recycled from the `ui-spec-generator` service.
11
11
  ---
12
12
 
13
13
  # ui-spec — UI spec authoring
@@ -18,37 +18,31 @@ description: >-
18
18
 
19
19
  ## Purpose
20
20
 
21
- Dado un requerimiento de UI, autorar una **especificación de pantalla estructurada** — un modelo universal, agnóstico de framework más su render Markdown legible. **Reemplaza** al servicio single-shot `ui-spec-generator`: ahora la IA la autora **nativamente**, guiada por esta skill. No hay endpoint que llamar; el saber del servicio vive aquí.
21
+ Dado un requerimiento de UI, autorar una **descripción estructurada en Markdown** de las pantallas y sus componentes descriptiva (qué hay y para qué) y estructurada (regiones componentes, con vocabulario consistente), agnóstica de framework. **Reemplaza** al servicio single-shot `ui-spec-generator`: ahora la IA la autora **nativamente**, guiada por esta skill. No hay endpoint que llamar; el saber del servicio vive aquí. **Salida en un solo formato: Markdown** (sin representación JSON paralela).
22
22
 
23
23
  ## Composed by
24
24
 
25
- La carga el **`spec-refine-loop`** (ver `../../loops/spec-refine-loop.md`) cuando el requerimiento involucra UI. El loop aporta lo que el servicio viejo no tenía:
25
+ La carga el **`spec-refine-loop`** (ver `../../loops/spec-refine-loop/SKILL.md`) al resolver el gap **UI sin especificar** (cuando el requerimiento involucra UI). El loop aporta lo que el servicio viejo no tenía:
26
26
 
27
- - **Pregunta al humano** (design-system, tema, ambigüedades de pantalla) vía `AskUserQuestion`.
27
+ - **Pregunta al humano** (design-system, tema, ambigüedades de pantalla) vía *structured-choice* (capacidad del arnés — ver `../../harness/SKILL.md`). En **Claude Code** es `AskUserQuestion` (máx 4 preguntas/llamada → **≤3 preguntas de contenido + 1 control `flow`**); en un arnés sin elección estructurada, degrada a **markdown numerado**.
28
28
  - **Itera** gap-driven hasta converger.
29
29
  - Ofrece **variantes** y **cura** el resultado.
30
30
 
31
- Cualquier loop podría componerla; el caso primario es SPEC. El `Screen` y su Markdown aterrizan como una sección dentro del documento spec (`docs/specs/NNN-spec.md`) — nunca como artefacto suelto (invariante 3: el spec es un documento).
31
+ Cualquier loop podría componerla; el caso primario es SPEC. La descripción Markdown aterriza como una sección dentro del documento spec (`docs/specs/NNN-spec-<slug>.md`) — nunca como artefacto suelto (invariante 3: el spec es un documento).
32
32
 
33
33
  ## Knowledge
34
34
 
35
- ### Schema (modelo `Screen` — universal, recursivo)
35
+ ### Estructura conceptual (universal, recursiva)
36
36
 
37
- ```
38
- Screen {
39
- name: string # nombre de la pantalla
40
- purpose: string # "tipo" semántico: auth, dashboard, form, list, detail, error, ...
41
- platform: string # web (default), mobile, ...
42
- description?: string
43
- regions?: Region[] # pantallas complejas
44
- components?: Component[] # pantallas simples
45
- } # usar regions O components, no ambos
46
- Region { type: string, components: Component[] }
47
- Component { kind: string, role?: string, label?: string, children?: Component[] } # recursive
48
- ```
37
+ Una **pantalla** tiene: `nombre`, `tipo` (propósito semántico: auth, dashboard, form, list, detail, error, …), `plataforma` (web por default, mobile, …), `descripción` opcional, y **o bien regiones** (pantalla compleja) **o bien componentes** directos (pantalla simple) — **no ambos**.
38
+
39
+ - Una **región** agrupa componentes y tiene un `type`.
40
+ - Un **componente** tiene un `kind`, y opcionalmente `role`, `label` y `children` (anidables, recursivos).
49
41
 
50
- - `type` (region) `header · main · footer · sidebar · filters · summary`
51
- - `kind` (component) por categoría:
42
+ Es un modelo conceptual para guiar la autoría; **no se serializa a JSON** la única salida es el render Markdown (ver Output).
43
+
44
+ - `type` (región) ∈ `header · main · footer · sidebar · filters · summary`
45
+ - `kind` (componente) por categoría:
52
46
  - **Contenedores**: `card · panel · modal`
53
47
  - **Datos**: `table · list · grid`
54
48
  - **Visualización**: `chart · metric · badge · image`
@@ -57,8 +51,6 @@ Component { kind: string, role?: string, label?: string, children?: Component[]
57
51
  - **Navegación**: `navBar · tabs · breadcrumb`
58
52
  - **Feedback**: `alert · progress`
59
53
 
60
- JSON serializado en **camelCase**, **claves null omitidas** (no emitir `"description": null`).
61
-
62
54
  ### Rules
63
55
 
64
56
  1. **Conciso** — solo lo esencial. Nada de relleno ni componentes especulativos.
@@ -66,11 +58,11 @@ JSON serializado en **camelCase**, **claves null omitidas** (no emitir `"descrip
66
58
  3. Pantalla compleja (dashboard, mantenimiento CRUD) → `regions` para organizar.
67
59
  4. `role` es **opcional** — solo si aporta claridad (`role:"logo"`, `role:"primary"`).
68
60
  5. Límites: **≤100 componentes**, **≤5 niveles** de anidación.
69
- 6. Un solo `Screen` por sección; si el requerimiento son varias pantallas, una sección por pantalla.
61
+ 6. Una sola pantalla por bloque `#`; si el requerimiento son varias pantallas, se listan una tras otra (cada una con su `#`).
70
62
 
71
63
  ### Design options (las pregunta el loop al humano)
72
64
 
73
- Estas opciones **guían contenido/labels**; el modelo `Screen` es **agnóstico** de design-system y NO las lleva como campos. Se **anotan en el spec** (encabezado de la sección), no en el JSON:
65
+ Estas opciones **guían contenido/labels**; la estructura de la pantalla es **agnóstica** de design-system y NO las lleva como parte del modelo. Se **anotan en el spec** (encabezado de la sección):
74
66
 
75
67
  - **Design system**: `material3 · bootstrap5 · tailwind3 · antDesign · chakraUI · custom`.
76
68
  - **Tema**: `light · dark · auto`.
@@ -80,11 +72,11 @@ Estas opciones **guían contenido/labels**; el modelo `Screen` es **agnóstico**
80
72
 
81
73
  ### Variants
82
74
 
83
- Cuando el requerimiento admite más de un layout razonable (ej. tabla vs. grid de cards; tabs vs. acordeón), ofrecer **2-3 variantes** como `Screen` alternativos y pedir al humano que elija. Una sola variante se cura y queda; las descartadas no se persisten.
75
+ Cuando el requerimiento admite más de un layout razonable (ej. tabla vs. grid de cards; tabs vs. acordeón), ofrecer **2-3 variantes** como pantallas Markdown alternativas y pedir al humano que elija. Una sola variante se cura y queda; las descartadas no se persisten.
84
76
 
85
77
  ### Disambiguation
86
78
 
87
- Antes de autorar, resolver ambigüedades con `AskUserQuestion` (lo dispara el loop):
79
+ Antes de autorar, resolver ambigüedades con *structured-choice* (lo dispara el loop; ver `../../harness/SKILL.md`):
88
80
 
89
81
  - Pantalla simple o compleja (¿necesita `regions`?).
90
82
  - Qué acciones primarias/secundarias existen.
@@ -95,27 +87,45 @@ Si el humano no responde, asumir el caso más simple coherente con la descripci
95
87
 
96
88
  ### Examples (few-shot)
97
89
 
98
- ```json
99
- // Simple (sin regions)
100
- {"name":"Recuperar Contraseña","purpose":"auth","platform":"web","components":[{"kind":"image","role":"logo"},{"kind":"textInput","label":"Correo electrónico"},{"kind":"button","label":"Enviar enlace"},{"kind":"link","label":"Volver al login"}]}
90
+ **Simple (sin regiones)** — "Recuperar Contraseña" (auth, web):
101
91
 
102
- // Complejo (con regions)
103
- {"name":"Dashboard","purpose":"dashboard","platform":"web","regions":[{"type":"summary","components":[{"kind":"metric","label":"Total"},{"kind":"metric","label":"Pendientes"}]},{"type":"main","components":[{"kind":"table","label":"Registros"}]}]}
92
+ ```markdown
93
+ # Recuperar Contraseña
94
+ **Tipo**: auth | **Plataforma**: web
95
+
96
+ ## Componentes
97
+ - **logo** (image)
98
+ - **Correo electrónico** (textInput)
99
+ - **Enviar enlace** (button)
100
+ - **Volver al login** (link)
101
+ ```
102
+
103
+ **Complejo (con regiones)** — "Dashboard" (web):
104
+
105
+ ```markdown
106
+ # Dashboard
107
+ **Tipo**: dashboard | **Plataforma**: web
108
+
109
+ ## Summary
110
+ - **Total** (metric)
111
+ - **Pendientes** (metric)
112
+
113
+ ## Main
114
+ - **Registros** (table)
104
115
  ```
105
116
 
106
- ## Output — sección `## UI spec` dentro del spec (`docs/specs/NNN-spec.md`)
117
+ ## Output — sección `## UI spec` dentro del spec (`docs/specs/NNN-spec-<slug>.md`)
107
118
 
108
- La escribe el loop (no esta skill por sí sola). Encabezar la sección con las opciones de diseño elegidas (design system, tema, idioma) en una línea. Luego dos representaciones:
119
+ **Salida en un solo formato: Markdown.** La escribe el loop (no esta skill por sí sola). Encabezar la sección con las opciones de diseño elegidas (design system, tema, idioma) en una línea. Luego el render Markdown, con estas reglas exactas (recicladas del `MarkdownFormatter`):
109
120
 
110
- 1. **`Screen` (JSON)** — camelCase, claves null omitidas, en bloque ```json.
111
- 2. **Markdown** render legible (reglas exactas, recicladas del `MarkdownFormatter`):
112
- - `# {name}`
113
- - `**Tipo**: {purpose} | **Plataforma**: {platform}`
114
- - `description` como párrafo aparte (solo si existe).
115
- - Con `regions`: un `## {Type capitalizado}` por región (capitalizar la primera letra del `type`).
116
- - Sin `regions`: un `## Componentes`.
117
- - Cada componente: `- **{label || role || kind}**`, seguido de ` ({kind})` **solo si** había `label` o `role`.
118
- - `children` indentados **2 espacios por nivel**.
121
+ - `# {nombre}`
122
+ - `**Tipo**: {tipo} | **Plataforma**: {plataforma}`
123
+ - `descripción` como párrafo aparte (solo si existe).
124
+ - Con regiones: un `## {Type capitalizado}` por región (capitalizar la primera letra del `type`).
125
+ - Sin regiones: un único `## Componentes`.
126
+ - Cada componente: `- **{label || role || kind}**`, seguido de ` ({kind})` **solo si** había `label` o `role`.
127
+ - `children` indentados **2 espacios por nivel**.
128
+ - Si hay varias pantallas, se listan una tras otra (cada una con su `#`).
119
129
 
120
130
  Ejemplo de render para el dashboard de arriba:
121
131
 
@@ -133,4 +143,4 @@ Ejemplo de render para el dashboard de arriba:
133
143
 
134
144
  ## Source
135
145
 
136
- Reciclada de `ui-spec-generator` (Spring Boot/Kotlin). Se **conservan**: el prompt de sistema (vocabulario, kinds, reglas), el esquema `Screen`/`Region`/`Component`, los pocos-shot, el enum de design systems, los constraints (theme/density/maxWidth) y las reglas exactas del `MarkdownFormatter`. Se **descarta**: el transporte HTTP, OpenRouter/Gemini y el modo single-shot — los reemplaza la iteración del `spec-refine-loop`. El endpoint del servicio deja de usarse. También absorbe los principios UX de la vieja skill `standards/frontend-design/` cuando el spec describe mantenimientos CRUD (formularios, listados, modales, navegación, feedback).
146
+ Reciclada de `ui-spec-generator` (Spring Boot/Kotlin). Se **conservan**: el prompt de sistema (vocabulario, kinds, reglas), la estructura conceptual pantalla/región/componente, los pocos-shot (ahora en Markdown), el enum de design systems, los constraints (theme/density/maxWidth) y las reglas exactas del `MarkdownFormatter` (su render era exactamente este). Se **descarta**: la **serialización JSON `Screen`** (segunda representación, ahora innecesaria), el transporte HTTP, OpenRouter/Gemini y el modo single-shot — los reemplaza la iteración del `spec-refine-loop`. El endpoint del servicio deja de usarse. También absorbe los principios UX de la vieja skill `standards/frontend-design/` cuando el spec describe mantenimientos CRUD (formularios, listados, modales, navegación, feedback).