zugzbot 1.1.6 → 1.2.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.
- package/.opencode/agents/sdd-orchestrator.md +24 -3
- package/.opencode/scripts/lint-charts.js +194 -0
- package/.opencode/skills/sdd-quickstart/SKILL.md +35 -0
- package/.opencode/skills/shadcn-templates/SKILL.md +45 -11
- package/.opencode/tools/akash_catalog.ts +596 -0
- package/.opencode/tools/sdd_network.ts +206 -41
- package/.opencode/tools/sdd_testing.ts +129 -4
- package/.utils/export_opencode_session.py +1 -1
- package/opencode.json +9 -1
- package/package.json +2 -1
|
@@ -49,6 +49,13 @@ Eres el coordinador principal del arnés de desarrollo SDD (Spec-Driven Developm
|
|
|
49
49
|
<f0_detect>
|
|
50
50
|
1. **Inicialización Atómica**: Llama obligatoriamente a `sdd_get_initial_session_data` para obtener estado, memorias e Oh-My-Design en un solo turno.
|
|
51
51
|
2. **Brain Pre-carga (OBLIGATORIO)**: Inmediatamente después, invoca `brain_read_memory({ category: "learnings" })` y `brain_read_memory({ category: "errors" })` para extraer errores y lecciones históricas que prevengan repetir problemas conocidos. Guarda el resultado en una variable interna para inyectarlo en cada brief de subagente.
|
|
52
|
+
2.5 **Detección de intención de catálogo Akash (CRÍTICO — bugfix sesión 1176)**: Analiza la petición. Si contiene ALGUNA keyword de marketing/landing/auth/composite o un nombre propio del catálogo:
|
|
53
|
+
- Keywords: `hero`, `landing`, `pricing`, `features`, `faq`, `testimonials`, `footer`, `cta`, `navbar`, `stats`, `logo cloud`, `login page`, `signup page`, `forgot password`, `chart`, `sidebar`, `dashboard section`, `comparison`, `use cases`, `how it works`, `changelog`, `cookie banner`, `newsletter`, `bento`, `marquee`, `gallery`, `integration`
|
|
54
|
+
- Nombres propios: `akash`, `akash3444`, `shadcnui-blocks`, `shadcn-ui-blocks`, `basecn`, `shadcn blocks`
|
|
55
|
+
- **Acción obligatoria**: cargar la skill `shadcn-templates` (que ahora referencia las tools MCP `sdd_akash_catalog_list_blocks` y `sdd_akash_catalog_get_block` — NUNCA uses `webfetch` directo a GitHub API, está cacheado).
|
|
56
|
+
- En modo HIL: llama `sdd_akash_catalog_list_blocks({category, limit: 5})` y presenta las 2-3 mejores opciones con `preview_url` para que el usuario elija.
|
|
57
|
+
- En modo autopiloto (`/loop`): llama `sdd_akash_catalog_get_block({name})` sobre 2-3 candidatos y elige el que mejor encaje.
|
|
58
|
+
- Esto evita el ciclo "ping-pong" de 3+ turnos que vimos en sesión 1176 donde el usuario tuvo que guiar al orquestador hacia el catálogo correcto.
|
|
52
59
|
3. **Detección Fast-Track Dashboard (CRÍTICO — bugfix sesión 1186 y 1180)**: Analiza la petición del usuario. Si contiene ALGUNA de estas keywords: `dashboard`, `admin panel`, `panel de control`, `panel admin`, `crm`, `erp`, `panel`:
|
|
53
60
|
- **NO preguntes NADA**. Asume todos los defaults: Stack = Next.js 16 + Shadcn UI + Tailwind v4, Persistencia = localStorage/mock, Diseño = `default` (zinc nativo de Shadcn, NO inyectar marcas de Oh-My-Design), Verificación = `console`.
|
|
54
61
|
- Llama directamente a `sdd_set_phase({ phase: "F1_CONTRACT", spec_name: "dashboard-admin" })` con `coreStack: ["Next.js 16", "Shadcn UI", "Tailwind CSS v4"]` y `skip_lint_gate: true`.
|
|
@@ -85,13 +92,20 @@ Eres el coordinador principal del arnés de desarrollo SDD (Spec-Driven Developm
|
|
|
85
92
|
- Lista resumida de `files_affected` para ESTE sprint (si dividiste)
|
|
86
93
|
- Sección `brain_learnings` del brief
|
|
87
94
|
- *Instrucción clave:* Indica si requiere bootstrap. Prohíbe formalmente el uso de `brain_read_memory` (ya está inyectado). Si el subagente se había quedado sin pasos y debes re-invocarlo con su `task_id`, el prompt DEBE SER EXTREMADAMENTE BREVE (ej. "Te quedaste sin pasos. Tu contexto y tareas ya están en tu historial. Revisa lo que falta y continúa."). NO incluyas código ni listas largas para no contaminar el contexto.
|
|
88
|
-
3. **
|
|
95
|
+
3. **Micro-Fixes (Anti-Spec Spam)**: Si el usuario reporta un bug, un desajuste visual o pide una pequeña corrección sobre lo que acabas de entregar, **TIENES PROHIBIDO crear un nuevo spec en F1**. Debes mantener el estado actual en `activeContract`, transicionar/mantener a `F2_IMPLEMENTATION`, y delegar el arreglo al Coder. Solo crea nuevos specs en F1 si el usuario solicita una característica completamente nueva.
|
|
96
|
+
3.5 **Plantilla de prompt para chart/visual fixes (bugfix sesión 1176)**: Cuando corrijas colores de gráficos Recharts:
|
|
97
|
+
1. Cambia valores OKLCH en `globals.css` (`.dark` y `:root`).
|
|
98
|
+
2. Verifica que el `chartConfig` del componente use `'var(--color-chart-N)'` DIRECTAMENTE, NUNCA `'hsl(var(--chart-N))'` — `hsl(oklch(...))` es CSS inválido.
|
|
99
|
+
3. Si encuentras `'hsl(var(--chart-N))'` en cualquier chartConfig, reemplázalo por `'var(--color-chart-N)'` en el mismo turno.
|
|
100
|
+
4. El linter `scripts/lint-charts.js` corre automáticamente en shift-left y bloqueará la transición a F3 si quedan ocurrencias inválidas.
|
|
101
|
+
4. **Verificación de Servidor y HMR**:
|
|
89
102
|
- **Si la categoría es 'script' o 'tooling' (Track Agnóstico):** No hay un dev server web que correr. Salta directamente este paso y transiciona de forma inmediata a F3.
|
|
90
103
|
- **De lo contrario (Web Next/FastAPI):**
|
|
104
|
+
- Next.js y tu stack frontend usan **Hot Module Replacement (HMR)**. Queda ESTRICTAMENTE PROHIBIDO detener y reiniciar el servidor (`sdd_network_stop_server` / `start_server`) para comprobar cambios de interfaz, CSS o componentes. El servidor se actualiza solo en vivo. Únicamente reinicia el servidor si hubo cambios en `next.config.ts`, `tailwind.config`, o instalación de dependencias muy pesadas.
|
|
91
105
|
- En autopiloto: Aprueba directo si el server corre sin errores fatales. Transiciona a F3.
|
|
92
106
|
- En modo `console`: Dile al usuario que verifique localmente en `http://localhost:3000`. Prohibido usar Playwright.
|
|
93
107
|
- En modo `visual`: Toma screenshot en `.openspec/ts-f2-hil.png` y preséntalo para aprobación.
|
|
94
|
-
|
|
108
|
+
5. Transiciona a `F3_VERIFICATION` llamando a `sdd_set_phase`. **Bajo ninguna circunstancia te saltes la fase F3 después de que el Coder haya intervenido, incluso para micro-fixes visuales**.
|
|
95
109
|
</f2_implementation>
|
|
96
110
|
|
|
97
111
|
<f3_verification>
|
|
@@ -115,8 +129,9 @@ Eres el coordinador principal del arnés de desarrollo SDD (Spec-Driven Developm
|
|
|
115
129
|
</f4_deployment>
|
|
116
130
|
|
|
117
131
|
<rollbacks>
|
|
118
|
-
1. Si se reportan fallos,
|
|
132
|
+
1. Si se reportan fallos en tests o linter en F3, haz un rollback de la estructura y regresa a `F2_IMPLEMENTATION` usando `sdd_set_phase` y delega la corrección al subagente experto (`@sdd-coder`). Bajo ninguna circunstancia puedes usar la herramienta `edit` o `write` para arreglar código, ni siquiera en modo autopiloto.
|
|
119
133
|
2. Si una misma fase falla más de 2 veces consecutivas, presenta el error al usuario con el contexto completo en vez de seguir intentando.
|
|
134
|
+
3. **Estado Corrupto**: Si detectas que el estado actual es `F2_IMPLEMENTATION` o superior, pero la propiedad `activeContract` está vacía o el archivo del contrato ya no existe, asume que la sesión previa se corrompió. Limpia el estado transicionando automáticamente a `F0_DETECT` antes de procesar el requerimiento del usuario.
|
|
120
135
|
</rollbacks>
|
|
121
136
|
|
|
122
137
|
<completion>
|
|
@@ -126,6 +141,11 @@ Eres el coordinador principal del arnés de desarrollo SDD (Spec-Driven Developm
|
|
|
126
141
|
- Anúnciala en 1 línea y delega la siguiente iteración completa a un NUEVO hilo `sdd-orchestrator` con contexto de 0 tokens.
|
|
127
142
|
- Si `loopCurrentIteration >= loopTargetIterations` o modo normal: Concluye con `sdd_set_phase({ phase: "F0_DETECT", loopMode: false })`.
|
|
128
143
|
2. **Brain save OBLIGATORIO**: Sintetiza 1-3 lecciones y regístralas con `brain_save_memory` (categoría: `learnings`, `errors`, `design` o `routing`). BLOQUEANTE — no omitir.
|
|
144
|
+
2.5 **Memory Post-Sesión para Catálogos (CRÍTICO — bugfix sesión 1176)**: Si la sesión tocó el catálogo Akash (shadcn-ui-blocks, basecn) o cualquier catálogo externo de UI, registra OBLIGATORIAMENTE en `brain.routing`:
|
|
145
|
+
- URL canónica del catálogo
|
|
146
|
+
- Comando `npx shadcn@latest add <URL>` listo para usar
|
|
147
|
+
- Nombre del autor/repo (para evitar redescubrimiento en próximas sesiones)
|
|
148
|
+
- Tool MCP del arnés a usar (`sdd_akash_catalog_list_blocks`, etc.)
|
|
129
149
|
3. **Mensaje Final MÁXIMO 10 LÍNEAS**:
|
|
130
150
|
```
|
|
131
151
|
✅ Sesión SDD completada
|
|
@@ -143,6 +163,7 @@ Eres el coordinador principal del arnés de desarrollo SDD (Spec-Driven Developm
|
|
|
143
163
|
<mcp_guidelines>
|
|
144
164
|
- **MCPs**: `shadcn` (UI), `context7` (APIs Next.js/FastAPI), `playwright` (Visual tests), `lucide-icons` (Iconos).
|
|
145
165
|
- `next-devtools` deshabilitado por defecto. MCPs invocados exclusivamente por subagentes.
|
|
166
|
+
- **Catálogos externos (Tools internas)**: `sdd_akash_catalog_list_blocks`, `sdd_akash_catalog_get_block`, `sdd_akash_catalog_warm_index` — cachean el catálogo de Akash (shadcn-ui-blocks + basecn) en `.openspec/cache/` con TTL 7d. NUNCA uses `webfetch` directo a GitHub API para descubrir bloques Akash; usa siempre estas tools.
|
|
146
167
|
</mcp_guidelines>
|
|
147
168
|
|
|
148
169
|
<communication_rules>
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
/**
|
|
4
|
+
* lint-charts.js — Linter bloqueante para configuraciones de Recharts inválidas.
|
|
5
|
+
*
|
|
6
|
+
* Bugfix sesión 1176: el coder dejó `color: "hsl(var(--chart-1))"` en
|
|
7
|
+
* `chart-area-interactive.tsx`. Como `--chart-1` está definido en OKLCH en
|
|
8
|
+
* `globals.css`, `hsl(oklch(...))` produce CSS inválido y los colores no
|
|
9
|
+
* cambian al actualizar el token.
|
|
10
|
+
*
|
|
11
|
+
* REGLA: en chartConfig, los `color:` DEBEN usar `var(--color-chart-N)`
|
|
12
|
+
* directamente, NUNCA `hsl(var(--chart-N))`.
|
|
13
|
+
*
|
|
14
|
+
* Uso:
|
|
15
|
+
* node .opencode/scripts/lint-charts.js [paths...]
|
|
16
|
+
*
|
|
17
|
+
* Por defecto escanea `src/` y `app/`. Sale con código 1 si encuentra
|
|
18
|
+
* violaciones (BLOQUEANTE en shift-left).
|
|
19
|
+
*
|
|
20
|
+
* Salida JSON para integración programática:
|
|
21
|
+
* node .opencode/scripts/lint-charts.js --json
|
|
22
|
+
*/
|
|
23
|
+
"use strict"
|
|
24
|
+
|
|
25
|
+
const fs = require("fs")
|
|
26
|
+
const path = require("path")
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Config
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
const INCLUDE_EXT = new Set([".ts", ".tsx", ".js", ".jsx"])
|
|
33
|
+
const IGNORE_DIRS = new Set([
|
|
34
|
+
"node_modules",
|
|
35
|
+
".next",
|
|
36
|
+
"dist",
|
|
37
|
+
"build",
|
|
38
|
+
"out",
|
|
39
|
+
"coverage",
|
|
40
|
+
".openspec/cache",
|
|
41
|
+
".openspec/__tests__",
|
|
42
|
+
".opencode/templates",
|
|
43
|
+
".opencode/oh-my-design"
|
|
44
|
+
])
|
|
45
|
+
|
|
46
|
+
// Patrones prohibidos: cualquier chartConfig que envuelva una variable CSS
|
|
47
|
+
// --chart-N dentro de hsl(). Capturamos la ocurrencia exacta.
|
|
48
|
+
const FORBIDDEN_PATTERNS = [
|
|
49
|
+
{
|
|
50
|
+
name: "hsl(oklch) misuse",
|
|
51
|
+
regex: /hsl\(\s*var\(\s*--chart-\d+\s*\)\s*\)/g,
|
|
52
|
+
fix: "Usa 'var(--color-chart-N)' directamente en chartConfig.color"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "hsl(--chart) sin var()",
|
|
56
|
+
regex: /hsl\(\s*--chart-\d+\s*\)/g,
|
|
57
|
+
fix: "Envuelve en var(): 'hsl(var(--chart-N))' — pero si --chart-N es OKLCH, sigue siendo inválido. Usa 'var(--color-chart-N)'."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// Walk
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
function walk(dir, acc = []) {
|
|
66
|
+
let entries
|
|
67
|
+
try {
|
|
68
|
+
entries = fs.readdirSync(dir, { withFileTypes: true })
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return acc
|
|
71
|
+
}
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
if (entry.name.startsWith(".") && entry.name !== ".opencode") continue
|
|
74
|
+
const full = path.join(dir, entry.name)
|
|
75
|
+
if (entry.isDirectory()) {
|
|
76
|
+
if (IGNORE_DIRS.has(entry.name)) continue
|
|
77
|
+
walk(full, acc)
|
|
78
|
+
} else if (entry.isFile()) {
|
|
79
|
+
const ext = path.extname(entry.name)
|
|
80
|
+
if (INCLUDE_EXT.has(ext)) acc.push(full)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return acc
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function isInChartContext(filePath, lineContent) {
|
|
87
|
+
// Heurística: considerar chartConfig si el archivo contiene Recharts
|
|
88
|
+
// o si la línea está cerca de una mención a ChartConfig. Para mantener
|
|
89
|
+
// el linter simple y rápido, NO restringimos por contexto y reportamos
|
|
90
|
+
// cualquier coincidencia; el developer decide si aplica.
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Lint
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
function lintFile(filePath) {
|
|
99
|
+
const content = fs.readFileSync(filePath, "utf8")
|
|
100
|
+
const lines = content.split("\n")
|
|
101
|
+
const violations = []
|
|
102
|
+
|
|
103
|
+
lines.forEach((line, idx) => {
|
|
104
|
+
for (const pat of FORBIDDEN_PATTERNS) {
|
|
105
|
+
pat.regex.lastIndex = 0
|
|
106
|
+
let m
|
|
107
|
+
while ((m = pat.regex.exec(line)) !== null) {
|
|
108
|
+
if (!isInChartContext(filePath, line)) continue
|
|
109
|
+
violations.push({
|
|
110
|
+
file: filePath,
|
|
111
|
+
line: idx + 1,
|
|
112
|
+
column: m.index + 1,
|
|
113
|
+
match: m[0],
|
|
114
|
+
pattern: pat.name,
|
|
115
|
+
fix: pat.fix,
|
|
116
|
+
snippet: line.trim()
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
return violations
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ============================================================================
|
|
126
|
+
// Main
|
|
127
|
+
// ============================================================================
|
|
128
|
+
|
|
129
|
+
function main() {
|
|
130
|
+
const argv = process.argv.slice(2)
|
|
131
|
+
const jsonOut = argv.includes("--json")
|
|
132
|
+
const explicitPaths = argv.filter((a) => !a.startsWith("--"))
|
|
133
|
+
|
|
134
|
+
const roots =
|
|
135
|
+
explicitPaths.length > 0
|
|
136
|
+
? explicitPaths
|
|
137
|
+
: [path.join(process.cwd(), "src"), path.join(process.cwd(), "app")].filter((p) => {
|
|
138
|
+
try {
|
|
139
|
+
return fs.statSync(p).isDirectory()
|
|
140
|
+
} catch {
|
|
141
|
+
return false
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
if (roots.length === 0) {
|
|
146
|
+
const msg = "No se encontraron directorios src/ ni app/ para escanear."
|
|
147
|
+
if (jsonOut) {
|
|
148
|
+
console.log(JSON.stringify({ status: "SKIPPED", message: msg, violations: [] }, null, 2))
|
|
149
|
+
} else {
|
|
150
|
+
console.log(`[lint-charts] ${msg}`)
|
|
151
|
+
}
|
|
152
|
+
process.exit(0)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const files = roots.flatMap((r) => walk(r))
|
|
156
|
+
const allViolations = files.flatMap((f) => lintFile(f))
|
|
157
|
+
|
|
158
|
+
if (jsonOut) {
|
|
159
|
+
console.log(
|
|
160
|
+
JSON.stringify(
|
|
161
|
+
{
|
|
162
|
+
status: allViolations.length === 0 ? "PASS" : "FAIL",
|
|
163
|
+
filesScanned: files.length,
|
|
164
|
+
violations: allViolations,
|
|
165
|
+
summary: allViolations.length === 0
|
|
166
|
+
? "No se encontraron chartConfig con hsl()+oklch misuse."
|
|
167
|
+
: `${allViolations.length} violacion(es) detectada(s).`
|
|
168
|
+
},
|
|
169
|
+
null,
|
|
170
|
+
2
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
} else {
|
|
174
|
+
console.log(`[lint-charts] Escaneados ${files.length} archivos.`)
|
|
175
|
+
if (allViolations.length === 0) {
|
|
176
|
+
console.log("[lint-charts] PASS - sin violaciones.")
|
|
177
|
+
} else {
|
|
178
|
+
console.log(`[lint-charts] FAIL - ${allViolations.length} violacion(es):`)
|
|
179
|
+
for (const v of allViolations) {
|
|
180
|
+
const rel = path.relative(process.cwd(), v.file)
|
|
181
|
+
console.log(
|
|
182
|
+
` ${rel}:${v.line}:${v.column} ${v.pattern}\n` +
|
|
183
|
+
` match: ${v.match}\n` +
|
|
184
|
+
` fix: ${v.fix}\n` +
|
|
185
|
+
` line: ${v.snippet}`
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
process.exit(allViolations.length === 0 ? 0 : 1)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
main()
|
|
@@ -148,6 +148,41 @@ Copia y adapta los IDs y descripciones que apliquen. Borra los que no apliquen.
|
|
|
148
148
|
- `AUTH-02`: Login con credenciales inválidas muestra error genérico.
|
|
149
149
|
- `AUTH-03`: Logout limpia el token y redirige a `/login`.
|
|
150
150
|
|
|
151
|
+
### Charts / Recharts (CRÍTICO — bugfix sesión 1176)
|
|
152
|
+
|
|
153
|
+
Cuando el contrato declare un chart de Recharts (`chart-area-*`, `chart-bar-*`, `chart-pie-*`, etc.) o cualquier componente que lea `var(--chart-*)`, **debes incluir al menos UNO de los siguientes test_scenarios para forzar la validación de tema dark/light en F3**:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"id": "TS-CHART-01",
|
|
158
|
+
"name": "Chart visible con contraste WCAG AA en modo oscuro",
|
|
159
|
+
"type": "visual",
|
|
160
|
+
"feature_ref": "ChartAreaInteractive",
|
|
161
|
+
"given": "el dashboard se renderiza en modo oscuro",
|
|
162
|
+
"when": "el area chart muestra las series desktop y mobile",
|
|
163
|
+
"then": "las líneas y rellenos tienen contraste >= 4.5:1 con el fondo de la card",
|
|
164
|
+
"selector": "[data-testid='chart-area-interactive']",
|
|
165
|
+
"assertion": "color-contrast-pass AND not-invisible"
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"id": "TS-CHART-02",
|
|
172
|
+
"name": "ChartConfig usa variables CSS válidas (no hsl+oklch mix)",
|
|
173
|
+
"type": "unit",
|
|
174
|
+
"feature_ref": "ChartAreaInteractive",
|
|
175
|
+
"given": "el componente importa su chartConfig",
|
|
176
|
+
"when": "el linter `node .opencode/scripts/lint-charts.js` escanea el archivo",
|
|
177
|
+
"then": "ninguna entrada usa 'hsl(var(--chart-N))'; todas usan 'var(--color-chart-N)' directamente",
|
|
178
|
+
"assertion": "lint-charts --json status == PASS"
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Por qué importan**: en sesión 1176, el coder dejó `color: "hsl(var(--chart-1))"` que es CSS inválido porque `--chart-1` se define en OKLCH. El usuario tuvo que reportar el bug manualmente. Estos test_scenarios **activan el linter BLOQUEANTE** `sdd_testing_lint_charts` durante shift-left y fuerzan al tester a validar contraste visual con Playwright.
|
|
183
|
+
|
|
184
|
+
Si el chart es solo decorativo (no necesita tema oscuro), puedes omitir `TS-CHART-01`. Pero `TS-CHART-02` debería incluirse **siempre** que el chart use tokens `--chart-*`.
|
|
185
|
+
|
|
151
186
|
---
|
|
152
187
|
|
|
153
188
|
## 2.5. Plantilla MÍNIMA viable (Fast-Track Dashboard)
|
|
@@ -154,18 +154,33 @@ El `@sdd-coder` utiliza el template base `nextjs-shadcn`. Si el contrato no deta
|
|
|
154
154
|
|
|
155
155
|
## 5. Catálogo Externo Oficial: Shadcn UI Blocks (Akash)
|
|
156
156
|
|
|
157
|
-
Además del catálogo nativo de Shadcn UI, dispones de acceso autónomo a más de 200 bloques de alta calidad del repositorio **Shadcn UI Blocks (por Akash)**. Si
|
|
157
|
+
Además del catálogo nativo de Shadcn UI, dispones de acceso autónomo a más de 200 bloques de alta calidad del repositorio **Shadcn UI Blocks (por Akash)**. Si el usuario solicita una interfaz relacionada con landings, marketing, autenticación, footers o dashboards, **TIENES LA OBLIGACIÓN** de explorar este catálogo ANTES de proponer crear componentes desde cero.
|
|
158
|
+
|
|
159
|
+
### 5.0 Herramientas MCP Nativas del Arnés (PREFERENTE — bugfix sesión 1176)
|
|
160
|
+
|
|
161
|
+
**PROHIBIDO** usar `webfetch` directo a la API de GitHub para descubrir bloques. El arnés expone herramientas MCP dedicadas que **cachean el índice localmente** con TTL de 7 días, evitando redescubrimiento y latencia:
|
|
162
|
+
|
|
163
|
+
- `sdd_akash_catalog_list_blocks({ category?, query?, registry?, limit?, force_refresh? })`
|
|
164
|
+
- Devuelve el listado completo del catálogo (shadcn-ui-blocks + basecn) filtrado por categoría o substring.
|
|
165
|
+
- `registry`: `"shadcn"` (Radix), `"basecn"` (Base UI) o `"both"` (default).
|
|
166
|
+
- `force_refresh: true` re-descarga aunque el cache sea fresco.
|
|
167
|
+
- `sdd_akash_catalog_get_block({ name, registry?, force_refresh? })`
|
|
168
|
+
- Devuelve el código fuente, archivos y dependencias de un bloque específico.
|
|
169
|
+
- Incluye `install_command` listo: `npx shadcn@latest add https://shadcnui-blocks.com/r/radix/<name>.json --yes`.
|
|
170
|
+
- `sdd_akash_catalog_warm_index({ registry? })`
|
|
171
|
+
- Pre-calienta el caché para evitar la latencia del primer `list_blocks`. Llamar al bootstrap del proyecto.
|
|
172
|
+
|
|
173
|
+
Cache local en `.openspec/cache/` (`.gitignore` lo excluye automáticamente). Si el caché tiene más de 7 días, se re-descarga silenciosamente en el próximo `list_blocks`.
|
|
158
174
|
|
|
159
175
|
### 5.1 Flujo de Descubrimiento (Fase F1 - Spec-Writer)
|
|
160
|
-
Si el usuario solicita una interfaz
|
|
161
|
-
- **
|
|
162
|
-
|
|
163
|
-
- **Análisis de resultados:** El JSON devuelto listará todos los bloques (`hero-01.json`, `footer-05.json`, `pricing-02.json`, etc.). Filtra mentalmente los que coincidan con la necesidad.
|
|
176
|
+
Si el usuario solicita una interfaz (ej: "necesito un hero", "haz un footer"), **llama primero a `sdd_akash_catalog_list_blocks`**:
|
|
177
|
+
- **Asistido:** `sdd_akash_catalog_list_blocks({ category: "hero", limit: 5 })` → muestra las 5 mejores opciones con su `preview_url` (`https://shadcnui-blocks.com/blocks/<name>`).
|
|
178
|
+
- **Autopiloto:** `sdd_akash_catalog_get_block({ name: "hero-06" })` sobre 2-3 candidatos y elige el que mejor encaje.
|
|
164
179
|
|
|
165
|
-
### 5.2 Selección de Bloques
|
|
180
|
+
### 5.2 Selección de Bloques (Interactiva o Autónoma)
|
|
166
181
|
Cuando existan múltiples opciones para un mismo tipo de bloque (ej. 10 footers distintos):
|
|
167
|
-
- **Modo Asistido (Por defecto):** Utiliza la herramienta `question` o
|
|
168
|
-
- **Modo Autopiloto (`/loop`):** Si estás actuando de forma 100% autónoma
|
|
182
|
+
- **Modo Asistido (Por defecto):** Utiliza la herramienta `question` para preguntarle al usuario o dile explícitamente en el chat: *"Tengo acceso a la galería de Shadcn UI Blocks. He encontrado X opciones de [categoria]. ¿Quieres que revise algunas en particular o te dejo el enlace visual (`https://www.shadcnui-blocks.com/blocks/categories/[categoria]`) para que elijas la que más te guste?"*.
|
|
183
|
+
- **Modo Autopiloto (`/loop`):** Si estás actuando de forma 100% autónoma, lee el código fuente de 2 o 3 opciones con `sdd_akash_catalog_get_block` y elígelo autónomamente sin preguntar.
|
|
169
184
|
|
|
170
185
|
### 5.3 Inyección e Instalación (Contrato y Coder)
|
|
171
186
|
- **Spec-Writer (F1):** En el `contract.json`, dentro de `frontend.components`, anota el bloque utilizando la URL remota directa:
|
|
@@ -176,9 +191,28 @@ Cuando existan múltiples opciones para un mismo tipo de bloque (ej. 10 footers
|
|
|
176
191
|
]
|
|
177
192
|
}
|
|
178
193
|
```
|
|
179
|
-
- **Coder (F2):** Para instalar estos bloques externos,
|
|
194
|
+
- **Coder (F2):** Para instalar estos bloques externos, **obtén el `install_command` listo** vía `sdd_akash_catalog_get_block({ name })` (campo `install_command` del resultado) y ejecútalo. La CLI v3 de Shadcn se encarga automáticamente de descargar el código y resolver dependencias internas:
|
|
180
195
|
```bash
|
|
181
|
-
npx shadcn@latest add https://shadcnui-blocks.com/r/radix/footer-04.json
|
|
196
|
+
npx shadcn@latest add https://shadcnui-blocks.com/r/radix/footer-04.json --yes
|
|
182
197
|
```
|
|
183
|
-
|
|
198
|
+
|
|
199
|
+
### 5.4 Validación Post-Instalación (BLOQUEANTE — bugfix sesión 1176)
|
|
200
|
+
Tras instalar cualquier bloque Akash (`npx shadcn add [URL]`), ejecuta INMEDIATAMENTE:
|
|
201
|
+
1. `npx tsc --noEmit` para detectar imports rotos o packages faltantes.
|
|
202
|
+
2. Verifica que todos los archivos declarados en el JSON del bloque fueron creados (compara con el campo `source_files` devuelto por `sdd_akash_catalog_get_block`).
|
|
203
|
+
3. Si faltan archivos, reintenta la instalación con `--overwrite`.
|
|
204
|
+
4. Solo entonces reporta éxito al orquestador.
|
|
205
|
+
|
|
206
|
+
**Bug conocido**: `Can't resolve 'shadcn/tailwind.css'` en Tailwind v4 requiere `npm install shadcn` antes de continuar.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 6. Patrones Avanzados de Layout CSS
|
|
211
|
+
|
|
212
|
+
### 6.1 Patrón de Fullscreen Layouts y Centrado (CRÍTICO)
|
|
213
|
+
Cuando necesites crear un Hero, Landing, o Splash screen que deba ocupar el 100% de la pantalla visible y tener su contenido perfectamente centrado, evita mezclar clases CSS que peleen entre sí. Sigue **estrictamente** este patrón:
|
|
214
|
+
- **Contenedor Padre**: Usa `min-h-[100dvh] flex flex-col`.
|
|
215
|
+
- **Contenedor Interno (Wrapper)**: Usa `flex-1 flex items-center justify-center w-full`.
|
|
216
|
+
- **Contenido Central**: Usa `mx-auto max-w-[ancho-deseado] flex flex-col items-center text-center`.
|
|
217
|
+
- **PROHIBICIÓN ESTRICTA DE `w-full` EN FLEX HIJOS**: Si el contenedor padre usa `flex` con `items-center` para centrar, **NO** le pongas `w-full` al hijo interno si quieres que no se "pegue" a la izquierda en pantallas ultra anchas. El `w-full` forzará al elemento a ocupar el 100% del contenedor padre flex y anulará el centrado horizontal. Usa siempre `mx-auto` explícitamente en el elemento hijo para garantizar que quede centrado dentro de su propia columna.
|
|
184
218
|
|