agentic-kdd 2.1.1 → 2.1.2

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/init.js +53 -412
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-kdd",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Autonomous development pipeline with KDD — aa: · ag: · audit: · Visual Dashboard. Works with Cursor and Claude Code.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/init.js CHANGED
@@ -5,228 +5,10 @@ const path = require('path');
5
5
  const { execSync } = require('child_process');
6
6
  const chalk = require('chalk');
7
7
  const ora = require('ora');
8
- const inquirer = require('inquirer');
9
8
 
10
9
  const GITHUB_REPO = 'Adrianlpz211/Agentic-KDD';
11
10
  const TEMP_DIR = path.join(require('os').tmpdir(), 'agentic-kdd-download');
12
11
 
13
- // ── Plantillas por stack ────────────────────────────────────────
14
- const TEMPLATES = {
15
- nextjs: {
16
- nombre: 'Next.js App',
17
- tipo: 'NUEVO',
18
- modulos_impl: [
19
- '| 1 | Auth y middleware | /login, /registro, middleware.ts |',
20
- '| 2 | Layout y navegación | app/layout.tsx, componentes nav |',
21
- ],
22
- modulos_pend: [
23
- '- [ ] Dashboard principal',
24
- '- [ ] Módulo de usuarios',
25
- '- [ ] API routes principales',
26
- ],
27
- reglas: [
28
- '- App Router (no Pages Router)',
29
- '- Server Components por defecto, Client Components solo cuando necesario',
30
- '- Queries de base de datos solo en lib/queries/',
31
- '- Tailwind CSS para estilos',
32
- '- TypeScript estricto',
33
- ],
34
- descripcion: 'Aplicación web con Next.js 14 App Router, TypeScript y Tailwind CSS.',
35
- },
36
- laravel: {
37
- nombre: 'Laravel App',
38
- tipo: 'NUEVO',
39
- modulos_impl: [
40
- '| 1 | Auth y roles | routes/auth.php, AuthController |',
41
- '| 2 | Modelos base | app/Models/, migraciones |',
42
- ],
43
- modulos_pend: [
44
- '- [ ] Panel de administración',
45
- '- [ ] API REST principal',
46
- '- [ ] Jobs y queues',
47
- ],
48
- reglas: [
49
- '- Lógica de negocio en Services, no en Controllers',
50
- '- Queries complejas en Repositories',
51
- '- Form Requests para validación',
52
- '- Resources para transformar respuestas API',
53
- '- Jobs para procesos en background',
54
- ],
55
- descripcion: 'Aplicación web con Laravel, MySQL y arquitectura MVC.',
56
- },
57
- node: {
58
- nombre: 'Node.js API',
59
- tipo: 'NUEVO',
60
- modulos_impl: [
61
- '| 1 | Servidor y configuración | index.js, config/, middleware |',
62
- '| 2 | Auth JWT | routes/auth.js, middleware/auth.js |',
63
- ],
64
- modulos_pend: [
65
- '- [ ] Endpoints principales',
66
- '- [ ] Base de datos y modelos',
67
- '- [ ] Tests de integración',
68
- ],
69
- reglas: [
70
- '- Express con middleware centralizado',
71
- '- Lógica en services/, no en routes',
72
- '- Variables de entorno en .env, nunca hardcoded',
73
- '- Manejo de errores centralizado',
74
- ],
75
- descripcion: 'API REST con Node.js, Express y base de datos.',
76
- },
77
- react: {
78
- nombre: 'React App',
79
- tipo: 'NUEVO',
80
- modulos_impl: [
81
- '| 1 | Estructura base | App.tsx, router, layout |',
82
- '| 2 | Estado global | context o zustand |',
83
- ],
84
- modulos_pend: [
85
- '- [ ] Componentes principales',
86
- '- [ ] Integración con API',
87
- '- [ ] Tests de componentes',
88
- ],
89
- reglas: [
90
- '- Componentes funcionales con hooks',
91
- '- Estado local con useState, global con Context/Zustand',
92
- '- Llamadas API centralizadas en services/',
93
- '- CSS Modules o Tailwind, no inline styles',
94
- ],
95
- descripcion: 'Aplicación React con TypeScript y gestión de estado.',
96
- },
97
- php: {
98
- nombre: 'PHP App',
99
- tipo: 'NUEVO',
100
- modulos_impl: [
101
- '| 1 | Configuración base | config.php, conexión DB |',
102
- '| 2 | Auth | login.php, session |',
103
- ],
104
- modulos_pend: [
105
- '- [ ] Módulo principal',
106
- '- [ ] Panel de administración',
107
- ],
108
- reglas: [
109
- '- Queries preparadas siempre (PDO)',
110
- '- Validación en el servidor',
111
- '- Sin lógica en las vistas',
112
- ],
113
- descripcion: 'Aplicación PHP con MySQL.',
114
- },
115
- python: {
116
- nombre: 'Python App',
117
- tipo: 'NUEVO',
118
- modulos_impl: [
119
- '| 1 | Estructura base | main.py, config.py |',
120
- '| 2 | Auth | auth/, middleware |',
121
- ],
122
- modulos_pend: [
123
- '- [ ] Endpoints principales',
124
- '- [ ] Base de datos',
125
- '- [ ] Tests',
126
- ],
127
- reglas: [
128
- '- FastAPI o Django según el proyecto',
129
- '- Pydantic para validación',
130
- '- SQLAlchemy para queries',
131
- '- pytest para tests',
132
- ],
133
- descripcion: 'Aplicación Python con FastAPI/Django.',
134
- },
135
- };
136
-
137
- // ── Detectar stack ──────────────────────────────────────────────
138
- function detectStack(projectPath) {
139
- const stack = {
140
- framework: '—', language: '—', runtime: '—',
141
- base_datos: '—', packageManager: 'npm',
142
- templateKey: null,
143
- commands: { install: 'npm install', dev: 'npm run dev', build: 'npm run build', test: 'npm test', lint: 'npm run lint' }
144
- };
145
-
146
- if (fs.existsSync(path.join(projectPath, 'package.json'))) {
147
- const pkg = fs.readJsonSync(path.join(projectPath, 'package.json'), { throws: false }) || {};
148
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
149
- stack.language = deps['typescript'] ? 'TypeScript' : 'JavaScript';
150
- stack.runtime = 'Node.js';
151
-
152
- if (fs.existsSync(path.join(projectPath, 'pnpm-lock.yaml'))) {
153
- stack.packageManager = 'pnpm';
154
- stack.commands = { install: 'pnpm install', dev: 'pnpm dev', build: 'pnpm build', test: 'pnpm test', lint: 'pnpm lint' };
155
- } else if (fs.existsSync(path.join(projectPath, 'yarn.lock'))) {
156
- stack.packageManager = 'yarn';
157
- stack.commands = { install: 'yarn', dev: 'yarn dev', build: 'yarn build', test: 'yarn test', lint: 'yarn lint' };
158
- }
159
-
160
- if (deps['next']) {
161
- stack.framework = `Next.js ${(deps['next']||'').replace(/[\^~]/,'')}`;
162
- stack.templateKey = 'nextjs';
163
- if (deps['@supabase/supabase-js']) stack.base_datos = 'Supabase PostgreSQL';
164
- else if (deps['prisma'] || deps['@prisma/client']) stack.base_datos = 'Prisma';
165
- else if (deps['mongoose']) stack.base_datos = 'MongoDB';
166
- } else if (deps['vue']) {
167
- stack.framework = `Vue ${(deps['vue']||'').replace(/[\^~]/,'')}`;
168
- } else if (deps['react'] && !deps['next']) {
169
- stack.framework = 'React';
170
- stack.templateKey = 'react';
171
- } else if (deps['express']) {
172
- stack.framework = 'Express';
173
- stack.templateKey = 'node';
174
- stack.commands.dev = pkg.scripts?.dev || 'node index.js';
175
- } else if (deps['fastify']) {
176
- stack.framework = 'Fastify';
177
- stack.templateKey = 'node';
178
- } else if (deps['@nestjs/core']) {
179
- stack.framework = 'NestJS';
180
- stack.templateKey = 'node';
181
- stack.commands.dev = 'npm run start:dev';
182
- }
183
- }
184
-
185
- if (fs.existsSync(path.join(projectPath, 'composer.json'))) {
186
- const composer = fs.readJsonSync(path.join(projectPath, 'composer.json'), { throws: false }) || {};
187
- stack.language = 'PHP'; stack.runtime = 'PHP';
188
- stack.packageManager = 'composer';
189
- stack.commands = { install: 'composer install', dev: 'php artisan serve', build: 'composer build', test: './vendor/bin/phpunit', lint: 'composer lint' };
190
- if ((composer.require || {})['laravel/framework']) {
191
- stack.framework = `Laravel ${((composer.require||{})['laravel/framework']||'').replace(/[\^~]/,'')}`;
192
- stack.templateKey = 'laravel';
193
- } else {
194
- stack.framework = 'PHP';
195
- stack.templateKey = 'php';
196
- }
197
- }
198
-
199
- if (fs.existsSync(path.join(projectPath, 'pyproject.toml')) ||
200
- fs.existsSync(path.join(projectPath, 'requirements.txt'))) {
201
- stack.language = 'Python'; stack.runtime = 'Python';
202
- stack.packageManager = 'pip';
203
- stack.templateKey = 'python';
204
- stack.commands = { install: 'pip install -r requirements.txt', dev: 'uvicorn main:app --reload', build: 'pip install -e .', test: 'pytest', lint: 'flake8' };
205
- if (fs.existsSync(path.join(projectPath, 'pyproject.toml'))) {
206
- const toml = fs.readFileSync(path.join(projectPath, 'pyproject.toml'), 'utf8');
207
- if (toml.includes('fastapi')) { stack.framework = 'FastAPI'; }
208
- else if (toml.includes('django')) { stack.framework = 'Django'; }
209
- else { stack.framework = 'Python'; }
210
- }
211
- }
212
-
213
- return stack;
214
- }
215
-
216
- // ── Detectar si el proyecto tiene contenido ─────────────────────
217
- function detectProjectState(projectPath) {
218
- const hasCode = fs.existsSync(path.join(projectPath, 'src')) ||
219
- fs.existsSync(path.join(projectPath, 'app')) ||
220
- fs.existsSync(path.join(projectPath, 'pages')) ||
221
- fs.existsSync(path.join(projectPath, 'api'));
222
- const hasKnowledge = fs.existsSync(path.join(projectPath, '.agentic', 'conocimiento')) &&
223
- fs.readdirSync(path.join(projectPath, '.agentic', 'conocimiento')).filter(f => f !== 'README.md').length > 0;
224
- const hasPackageFile = fs.existsSync(path.join(projectPath, 'package.json')) ||
225
- fs.existsSync(path.join(projectPath, 'composer.json')) ||
226
- fs.existsSync(path.join(projectPath, 'pyproject.toml'));
227
- return { hasCode, hasKnowledge, hasPackageFile };
228
- }
229
-
230
12
  // ── Descargar desde GitHub ──────────────────────────────────────
231
13
  async function downloadFromGitHub(spinner) {
232
14
  const tmpFile = path.join(require('os').tmpdir(), 'agentic-kdd.tar.gz');
@@ -243,110 +25,45 @@ async function downloadFromGitHub(spinner) {
243
25
 
244
26
  // ── Copiar archivos al proyecto ─────────────────────────────────
245
27
  function copyAgenticFiles(sourcePath, projectPath) {
246
- const files = ['CLAUDE.md', '_LOCKS.md', '.cursorrules', 'dashboard.cjs', 'docs', '.cursor', '.audit'];
247
- for (const file of files) {
28
+ // Archivos raíz
29
+ const rootFiles = ['CLAUDE.md', '_LOCKS.md', '.cursorrules', 'dashboard.cjs', 'docs', '.cursor', '.audit'];
30
+ for (const file of rootFiles) {
248
31
  const src = path.join(sourcePath, file);
249
32
  const dest = path.join(projectPath, file);
250
33
  if (fs.existsSync(src)) fs.copySync(src, dest, { overwrite: true });
251
34
  }
252
35
 
253
- const agSrc = path.join(sourcePath, '.agentic');
36
+ const agSrc = path.join(sourcePath, '.agentic');
254
37
  const agDest = path.join(projectPath, '.agentic');
255
38
 
256
39
  if (fs.existsSync(agSrc)) {
40
+ // Agentes — siempre sobreescribir
257
41
  fs.copySync(path.join(agSrc, 'agentes'), path.join(agDest, 'agentes'), { overwrite: true });
42
+
43
+ // Grafo — siempre sobreescribir
258
44
  fs.copySync(path.join(agSrc, 'grafo'), path.join(agDest, 'grafo'), { overwrite: true });
259
- fs.ensureDirSync(path.join(agDest, 'specs'));
260
- fs.ensureDirSync(path.join(projectPath, '_output'));
261
45
 
262
- const memorySrc = path.join(agSrc, 'memoria');
263
- const memoryDest = path.join(agDest, 'memoria');
264
- if (!fs.existsSync(memoryDest)) fs.copySync(memorySrc, memoryDest);
46
+ // Carpetas que solo se crean si no existen (no sobreescribir memoria del usuario)
47
+ const onlyCreate = ['memoria', 'specs', 'conocimiento'];
48
+ for (const dir of onlyCreate) {
49
+ const src = path.join(agSrc, dir);
50
+ const dest = path.join(agDest, dir);
51
+ if (!fs.existsSync(dest)) {
52
+ if (fs.existsSync(src)) fs.copySync(src, dest);
53
+ else fs.ensureDirSync(dest);
54
+ }
55
+ }
265
56
 
57
+ // PLAN.md — solo si no existe
266
58
  const planDest = path.join(agDest, 'PLAN.md');
267
- if (!fs.existsSync(planDest)) fs.copySync(path.join(agSrc, 'PLAN.md'), planDest);
268
-
269
- const knSrc = path.join(agSrc, 'conocimiento', 'README.md');
270
- const knDest = path.join(agDest, 'conocimiento', 'README.md');
271
- fs.ensureDirSync(path.dirname(knDest));
272
- if (!fs.existsSync(knDest)) fs.copySync(knSrc, knDest);
59
+ if (!fs.existsSync(planDest)) {
60
+ const planSrc = path.join(agSrc, 'PLAN.md');
61
+ if (fs.existsSync(planSrc)) fs.copySync(planSrc, planDest);
62
+ }
273
63
  }
274
- }
275
-
276
- // ── Escribir config.md completo y listo ────────────────────────
277
- function writeConfig(projectPath, data) {
278
- const { name, description, isNew, stack, template } = data;
279
- const tpl = template || {};
280
-
281
- const modulosImpl = tpl.modulos_impl ? tpl.modulos_impl.join('\n') : '_El agente Setup los detecta al correr aa: configurar_';
282
- const modulosPend = tpl.modulos_pend ? tpl.modulos_pend.join('\n') : '_El agente Setup los detecta al correr aa: configurar_';
283
- const reglas = tpl.reglas ? tpl.reglas.join('\n') : '_Se definen durante el desarrollo._';
284
-
285
- const config = `# Agentic KDD — Configuración del proyecto
286
- CONFIGURADO: SI
287
- VERSION: 2.0
288
-
289
- ---
290
-
291
- ## Proyecto
292
- Nombre: ${name}
293
- Descripción: ${description}
294
- Tipo: ${isNew ? 'NUEVO' : 'EXISTENTE'}
295
-
296
- ## Stack
297
- \`\`\`yaml
298
- frontend:
299
- framework: ${stack.framework}
300
- language: ${stack.language}
301
-
302
- backend:
303
- runtime: ${stack.runtime || stack.language}
304
- framework: ${stack.framework}
305
- base_datos: ${stack.base_datos || '—'}
306
64
 
307
- devops:
308
- package_manager: ${stack.packageManager}
309
-
310
- commands:
311
- install: ${stack.commands.install}
312
- dev: ${stack.commands.dev}
313
- build: ${stack.commands.build}
314
- test: ${stack.commands.test}
315
- lint: ${stack.commands.lint}
316
- \`\`\`
317
-
318
- ## Módulos
319
-
320
- ### Implementados
321
- | Fase | Módulo | Rutas clave |
322
- |------|--------|-------------|
323
- ${modulosImpl}
324
-
325
- ### Pendientes
326
- ${modulosPend}
327
-
328
- ## Archivos compartidos críticos
329
- _El Setup los detecta al correr aa: configurar._
330
-
331
- ## Reglas del proyecto
332
-
333
- ### Agentic KDD
334
- - \`aa:\` → pipeline completo sin pausas ni confirmaciones entre agentes
335
- - \`audit:\` → solo auditar, no modificar código
336
- - Context Guard: validar instrucción contra config/conocimiento/código
337
-
338
- ### Desarrollo ${stack.framework !== '—' ? stack.framework : ''}
339
- ${reglas}
340
-
341
- ## Sinónimos del proyecto
342
- _Sin sinónimos registrados aún._
343
-
344
- ## Mapa BD → módulo
345
- _El agente Setup lo detecta._
346
- `;
347
-
348
- fs.ensureDirSync(path.join(projectPath, '.agentic'));
349
- fs.writeFileSync(path.join(projectPath, '.agentic', 'config.md'), config, 'utf8');
65
+ // Crear _output si no existe
66
+ fs.ensureDirSync(path.join(projectPath, '_output'));
350
67
  }
351
68
 
352
69
  // ── Comando principal: akdd init ────────────────────────────────
@@ -357,87 +74,14 @@ async function init() {
357
74
  console.log(chalk.gray(' github.com/Adrianlpz211/Agentic-KDD\n'));
358
75
 
359
76
  // Verificar si ya está instalado
360
- const alreadyInstalled = fs.existsSync(path.join(projectPath, '.agentic', 'config.md'));
77
+ const alreadyInstalled = fs.existsSync(path.join(projectPath, '.agentic', 'agentes'));
361
78
  if (alreadyInstalled) {
362
- const content = fs.readFileSync(path.join(projectPath, '.agentic', 'config.md'), 'utf8');
363
- if (content.includes('CONFIGURADO: SI')) {
364
- const { confirm } = await inquirer.prompt([{
365
- type: 'confirm', name: 'confirm',
366
- message: chalk.yellow('Agentic KDD ya está instalado. ¿Reinstalar?'),
367
- default: false
368
- }]);
369
- if (!confirm) {
370
- console.log(chalk.gray('\n Usa akdd update para actualizar los agentes sin perder tu memoria.\n'));
371
- return;
372
- }
373
- }
79
+ console.log(chalk.yellow(' Agentic KDD ya está instalado en este proyecto.'));
80
+ console.log(chalk.gray(' Para actualizar los agentes sin perder tu memoria: akdd update\n'));
81
+ return;
374
82
  }
375
83
 
376
- // Detectar estado y stack automáticamente
377
- const state = detectProjectState(projectPath);
378
- const stack = detectStack(projectPath);
379
-
380
- // Mostrar lo que detectó
381
- if (stack.framework !== '—') {
382
- console.log(chalk.green(` ✓ Stack detectado: ${stack.framework} · ${stack.language} · ${stack.packageManager}`));
383
- }
384
- if (state.hasCode) {
385
- console.log(chalk.green(' ✓ Código existente detectado'));
386
- }
387
- if (state.hasKnowledge) {
388
- console.log(chalk.green(' ✓ Documentación encontrada en conocimiento/'));
389
- }
390
- console.log('');
391
-
392
- // ── PREGUNTA 1 — Nombre ─────────────────────────────────────────
393
- const { name } = await inquirer.prompt([{
394
- type: 'input', name: 'name',
395
- message: 'Nombre del proyecto:',
396
- default: path.basename(projectPath)
397
- }]);
398
-
399
- // ── PREGUNTA 2 — Nuevo o existente ──────────────────────────────
400
- const { isNew } = await inquirer.prompt([{
401
- type: 'list', name: 'isNew',
402
- message: '¿El proyecto es nuevo o ya tiene código?',
403
- choices: [
404
- { name: 'Nuevo — empezando desde cero', value: true },
405
- { name: 'Existente — ya tiene código o avance', value: false }
406
- ],
407
- default: !state.hasCode
408
- }]);
409
-
410
- // ── PREGUNTA 3 — Descripción (solo proyectos nuevos sin docs) ──
411
- let description = '—';
412
- if (isNew && !state.hasKnowledge) {
413
- const { desc } = await inquirer.prompt([{
414
- type: 'input', name: 'desc',
415
- message: 'Describe brevemente qué hace el proyecto:',
416
- validate: (v) => v.trim().length > 5 || 'Al menos 5 caracteres'
417
- }]);
418
- description = desc;
419
- } else if (!isNew && state.hasCode) {
420
- description = 'Proyecto existente — el agente Setup detectará módulos y describirá el proyecto al correr aa: configurar';
421
- } else if (state.hasKnowledge) {
422
- description = 'El agente Setup leerá conocimiento/ y generará la descripción';
423
- }
424
-
425
- // ── DOCUMENTACIÓN ──────────────────────────────────────────────
426
- if (!state.hasKnowledge) {
427
- const { hasDocs } = await inquirer.prompt([{
428
- type: 'confirm', name: 'hasDocs',
429
- message: '¿Tienes specs, wireframes o documentación del proyecto?',
430
- default: false
431
- }]);
432
- if (hasDocs) {
433
- console.log('\n' + chalk.cyan(' Sube tus archivos a:'));
434
- console.log(chalk.bold(' .agentic/conocimiento/'));
435
- console.log(chalk.gray(' (PDFs, Markdown, specs, wireframes — cualquier formato)\n'));
436
- await inquirer.prompt([{ type: 'input', name: 'ready', message: 'Presiona Enter cuando hayas subido los archivos...' }]);
437
- }
438
- }
439
-
440
- // ── Instalar ────────────────────────────────────────────────────
84
+ // Instalar
441
85
  const spinner = ora({ text: 'Descargando Agentic KDD...', color: 'magenta' }).start();
442
86
 
443
87
  try {
@@ -446,37 +90,34 @@ async function init() {
446
90
  spinner.text = 'Instalando archivos...';
447
91
  copyAgenticFiles(sourcePath, projectPath);
448
92
 
449
- spinner.text = 'Generando configuración...';
450
- const template = stack.templateKey ? TEMPLATES[stack.templateKey] : null;
451
- writeConfig(projectPath, { name, description, isNew, stack, template });
452
-
453
93
  fs.removeSync(TEMP_DIR);
454
94
  spinner.succeed(chalk.green('¡Agentic KDD instalado!'));
455
95
 
456
- // Resumen de lo instalado
96
+ // Mostrar qué se instaló
457
97
  console.log('\n' + chalk.bold(' Instalado:'));
458
- console.log(chalk.gray(' .agentic/ — pipeline de agentes + memoria KDD'));
459
- console.log(chalk.gray(' .audit/ departamento QA (7 subagentes)'));
460
- console.log(chalk.gray(' dashboard.cjs dashboard visual'));
461
- console.log(chalk.gray(' CLAUDE.md activación aa: / ag: / audit:'));
462
- console.log(chalk.gray(' .cursorrules reglas para Cursor'));
463
- if (template) {
464
- console.log(chalk.green(`\n Plantilla aplicada: ${stack.framework}`));
465
- }
466
-
467
- console.log('\n' + chalk.bold(' Siguiente paso:\n'));
468
- if (!isNew && state.hasCode) {
469
- console.log(' ' + chalk.hex('#a78bfa')('aa: configurar') + chalk.gray(' ← el Setup leerá el código y configurará todo'));
470
- } else {
471
- console.log(' ' + chalk.hex('#a78bfa')('aa: configurar') + chalk.gray(' ← termina la configuración'));
472
- }
473
- console.log(' ' + chalk.hex('#10b981')('aa: [tu tarea]') + chalk.gray(' ← cuando esté listo, a construir'));
474
- console.log(' ' + chalk.hex('#06b6d4')('node dashboard.cjs') + chalk.gray(' ← abrir dashboard visual\n'));
475
-
476
- if (stack.templateKey === null) {
477
- console.log(chalk.yellow(' 💡 Stack no detectado automáticamente. Edita .agentic/config.md'));
478
- console.log(chalk.yellow(' con tu stack y luego corre aa: configurar\n'));
479
- }
98
+ console.log(chalk.gray(' .agentic/agentes/ — pipeline de 9 agentes'));
99
+ console.log(chalk.gray(' .agentic/grafo/ motor SQLite de conocimiento'));
100
+ console.log(chalk.gray(' .agentic/memoria/ errores, patrones, decisiones'));
101
+ console.log(chalk.gray(' .agentic/conocimiento/ documentación del proyecto'));
102
+ console.log(chalk.gray(' .agentic/specs/ specs auto-generadas'));
103
+ console.log(chalk.gray(' .audit/ — departamento QA (7 subagentes)'));
104
+ console.log(chalk.gray(' dashboard.cjs — dashboard visual'));
105
+ console.log(chalk.gray(' CLAUDE.md — activa aa: / ag: / audit:'));
106
+ console.log(chalk.gray(' .cursorrules — reglas para Cursor'));
107
+
108
+ // Instrucción final clara y directa
109
+ console.log('\n' + chalk.bold.hex('#2a3050')(' ─────────────────────────────────────────────'));
110
+ console.log(chalk.bold(' Último paso — abre este proyecto en'));
111
+ console.log(chalk.bold(' Cursor o Claude Code y ejecuta:'));
112
+ console.log('');
113
+ console.log(' ' + chalk.bold.hex('#a78bfa')('aa: configurar'));
114
+ console.log('');
115
+ console.log(chalk.gray(' Esto completa la configuración leyendo'));
116
+ console.log(chalk.gray(' tu código real. Solo se hace una vez.'));
117
+ console.log(chalk.bold.hex('#2a3050')(' ─────────────────────────────────────────────'));
118
+
119
+ console.log('\n' + chalk.gray(' Tip: si tienes specs, wireframes o docs del proyecto,'));
120
+ console.log(chalk.gray(' cópialos a .agentic/conocimiento/ antes de configurar.\n'));
480
121
 
481
122
  } catch (err) {
482
123
  spinner.fail(chalk.red('Error en la instalación'));