agentic-kdd 3.5.5 → 3.5.7
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/README.md +120 -35
- package/akdd-analyze.cjs +319 -0
- package/bin/akdd.js +5 -0
- package/mem-curator.cjs +290 -513
- package/package.json +1 -1
- package/src/init.js +1 -1
- package/src/onboard.js +312 -0
- package/src/update.js +154 -33
- package/tdd-gate.cjs +12 -0
- package/templates/.agentic/DESIGN_SYSTEM.fastapi.md +109 -0
- package/templates/.agentic/DESIGN_SYSTEM.nextjs.md +91 -0
- package/templates/.agentic/grafo/akdd-analyze.cjs +319 -0
- package/templates/.agentic/grafo/grafo.cjs +696 -2
- package/templates/.agentic/grafo/mem-curator.cjs +361 -0
|
@@ -212,6 +212,52 @@ function migrateDB(db) {
|
|
|
212
212
|
"CREATE UNIQUE INDEX IF NOT EXISTS idx_rel_unique ON relaciones(desde_id, tipo, hacia_id)",
|
|
213
213
|
];
|
|
214
214
|
indices.forEach(sql => { try { db.exec(sql); } catch(e) {} });
|
|
215
|
+
|
|
216
|
+
// v2.2 — nuevas tablas (seguro llamar múltiples veces)
|
|
217
|
+
const tablasV22 = [
|
|
218
|
+
`CREATE TABLE IF NOT EXISTS git_context_log (
|
|
219
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
220
|
+
sesion_id TEXT NOT NULL,
|
|
221
|
+
rama TEXT, commit_hash TEXT,
|
|
222
|
+
archivos_modificados TEXT DEFAULT '[]',
|
|
223
|
+
riesgos_detectados TEXT DEFAULT '[]',
|
|
224
|
+
predicciones TEXT DEFAULT '[]',
|
|
225
|
+
tiene_riesgos_altos INTEGER DEFAULT 0,
|
|
226
|
+
fecha TEXT DEFAULT (datetime('now'))
|
|
227
|
+
)`,
|
|
228
|
+
`CREATE TABLE IF NOT EXISTS cicd_reports (
|
|
229
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
230
|
+
episodio_id TEXT, plataforma TEXT DEFAULT 'github',
|
|
231
|
+
workflow TEXT, rama TEXT, commit_hash TEXT, actor TEXT, repo TEXT,
|
|
232
|
+
run_id TEXT, run_url TEXT,
|
|
233
|
+
tests_pasando INTEGER DEFAULT 0, tests_fallando INTEGER DEFAULT 0,
|
|
234
|
+
archivos_tocados TEXT DEFAULT '[]', errores_tests TEXT DEFAULT '[]',
|
|
235
|
+
es_exito INTEGER DEFAULT 0,
|
|
236
|
+
fecha TEXT DEFAULT (datetime('now'))
|
|
237
|
+
)`,
|
|
238
|
+
`CREATE TABLE IF NOT EXISTS prediction_log (
|
|
239
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
240
|
+
tarea TEXT, modulo TEXT, archivos TEXT DEFAULT '[]',
|
|
241
|
+
nivel_predicho TEXT, alertas TEXT DEFAULT '[]', precondiciones TEXT DEFAULT '[]',
|
|
242
|
+
fue_correcto INTEGER, ciclo_id TEXT,
|
|
243
|
+
fecha TEXT DEFAULT (datetime('now'))
|
|
244
|
+
)`,
|
|
245
|
+
];
|
|
246
|
+
tablasV22.forEach(sql => { try { db.exec(sql); } catch(e) {} });
|
|
247
|
+
|
|
248
|
+
// v2.2 — embedding en episodios
|
|
249
|
+
const migracionesV22 = [
|
|
250
|
+
"ALTER TABLE episodios ADD COLUMN embedding TEXT",
|
|
251
|
+
];
|
|
252
|
+
migracionesV22.forEach(sql => { try { db.exec(sql); } catch(e) {} });
|
|
253
|
+
|
|
254
|
+
// v2.2 — índices nuevas tablas
|
|
255
|
+
const indicesV22 = [
|
|
256
|
+
"CREATE INDEX IF NOT EXISTS idx_git_context_fecha ON git_context_log(fecha)",
|
|
257
|
+
"CREATE INDEX IF NOT EXISTS idx_cicd_rama ON cicd_reports(rama)",
|
|
258
|
+
"CREATE INDEX IF NOT EXISTS idx_prediction_fecha ON prediction_log(fecha)",
|
|
259
|
+
];
|
|
260
|
+
indicesV22.forEach(sql => { try { db.exec(sql); } catch(e) {} });
|
|
215
261
|
}
|
|
216
262
|
|
|
217
263
|
// ─── SNAPSHOT ─────────────────────────────────────────────────────────────────
|
|
@@ -1323,9 +1369,657 @@ if (_args[0] === 'decay') {
|
|
|
1323
1369
|
console.log(`Decay aplicado: ${r.procesados} nodos procesados`);
|
|
1324
1370
|
}
|
|
1325
1371
|
if (_args[0] === 'buscar') {
|
|
1326
|
-
|
|
1327
|
-
|
|
1372
|
+
// v2.2: búsqueda híbrida con embeddings si disponibles
|
|
1373
|
+
const embMod = getEmbeddingsModuleGrafo();
|
|
1374
|
+
if (embMod && embMod.isAvailable()) {
|
|
1375
|
+
buscarHibridoConEmbeddings(_args[1], _args[2], parseInt(_args[3]) || 10)
|
|
1376
|
+
.then(r => console.log(JSON.stringify({ resultados: r, trace: { metodo: 'vector_hybrid_rrf' } }, null, 2)));
|
|
1377
|
+
} else {
|
|
1378
|
+
const r = buscarHibrido(_args[1], _args[2], parseInt(_args[3]) || 10);
|
|
1379
|
+
console.log(JSON.stringify(r, null, 2));
|
|
1380
|
+
}
|
|
1328
1381
|
}
|
|
1329
1382
|
if (_args[0] === 'coala') {
|
|
1330
1383
|
statsCoala();
|
|
1331
1384
|
}
|
|
1385
|
+
|
|
1386
|
+
// ─── v2.2: Nuevos comandos CLI ────────────────────────────────────────────────
|
|
1387
|
+
|
|
1388
|
+
if (_args[0] === 'git-context') {
|
|
1389
|
+
const gitMod = getGitContextModuleGrafo();
|
|
1390
|
+
if (!gitMod) { console.log(' git-context module not available (akdd update)'); process.exit(0); }
|
|
1391
|
+
const db = initDB();
|
|
1392
|
+
const resultado = gitMod.analizarGitContext(ROOT, db);
|
|
1393
|
+
if (resultado.disponible) {
|
|
1394
|
+
const { contexto } = resultado;
|
|
1395
|
+
// Guardar en working_memory
|
|
1396
|
+
const sesionId = `git-${Date.now()}`;
|
|
1397
|
+
try {
|
|
1398
|
+
db.run('UPDATE working_memory SET expirado=1 WHERE expirado=0');
|
|
1399
|
+
db.run(
|
|
1400
|
+
`INSERT INTO working_memory (sesion_id, tipo, contenido, relevancia) VALUES (?,?,?,?)`,
|
|
1401
|
+
sesionId, 'observacion', JSON.stringify(contexto), 1.0
|
|
1402
|
+
);
|
|
1403
|
+
// Log en git_context_log si la tabla existe
|
|
1404
|
+
try {
|
|
1405
|
+
db.run(
|
|
1406
|
+
`INSERT INTO git_context_log (sesion_id, rama, commit_hash, archivos_modificados, riesgos_detectados, predicciones, tiene_riesgos_altos)
|
|
1407
|
+
VALUES (?,?,?,?,?,?,?)`,
|
|
1408
|
+
sesionId,
|
|
1409
|
+
contexto.rama || '',
|
|
1410
|
+
(contexto.commits_recientes?.[0]?.hash || ''),
|
|
1411
|
+
JSON.stringify(contexto.archivos_modificados || []),
|
|
1412
|
+
JSON.stringify(contexto.riesgos || []),
|
|
1413
|
+
JSON.stringify(contexto.predicciones || []),
|
|
1414
|
+
contexto.tiene_riesgos_altos ? 1 : 0
|
|
1415
|
+
);
|
|
1416
|
+
} catch(e) {}
|
|
1417
|
+
} catch(e) {}
|
|
1418
|
+
if (db.type === 'sqljs' && db.save) db.save();
|
|
1419
|
+
db.close();
|
|
1420
|
+
console.log(gitMod.formatearReporte(resultado));
|
|
1421
|
+
} else {
|
|
1422
|
+
db.close();
|
|
1423
|
+
console.log(` ${resultado.mensaje}`);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
if (_args[0] === 'predict') {
|
|
1428
|
+
const predMod = getPrediccionModuleGrafo();
|
|
1429
|
+
if (!predMod) { console.log(' prediccion module not available (akdd update)'); process.exit(0); }
|
|
1430
|
+
const db = initDB();
|
|
1431
|
+
predMod.mostrarEstadisticasPrediccion(db);
|
|
1432
|
+
db.close();
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
if (_args[0] === 'ci-install') {
|
|
1436
|
+
const ciMod = getCICDModuleGrafo();
|
|
1437
|
+
if (!ciMod) { console.log(' cicd module not available (akdd update)'); process.exit(0); }
|
|
1438
|
+
ciMod.instalarWorkflow(ROOT);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
if (_args[0] === 'ci-status') {
|
|
1442
|
+
const ciMod = getCICDModuleGrafo();
|
|
1443
|
+
if (!ciMod) { console.log(' cicd module not available (akdd update)'); process.exit(0); }
|
|
1444
|
+
const db = initDB();
|
|
1445
|
+
ciMod.mostrarEstadoCI(db);
|
|
1446
|
+
db.close();
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
if (_args[0] === 'ci-report') {
|
|
1450
|
+
const ciMod = getCICDModuleGrafo();
|
|
1451
|
+
if (!ciMod) { process.exit(0); } // No fallar CI
|
|
1452
|
+
const db = initDB();
|
|
1453
|
+
const esExito = _args.includes('--success');
|
|
1454
|
+
const outputIdx = _args.indexOf('--output');
|
|
1455
|
+
const outputFile = outputIdx >= 0 ? _args[outputIdx + 1] : null;
|
|
1456
|
+
ciMod.reportarCI(ROOT, db, { esExito, outputFile });
|
|
1457
|
+
if (db.type === 'sqljs' && db.save) db.save();
|
|
1458
|
+
db.close();
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
if (_args[0] === 'embed-status') {
|
|
1462
|
+
const embMod = getEmbeddingsModuleGrafo();
|
|
1463
|
+
console.log('\n Embeddings locales — Agentic KDD v2.2\n');
|
|
1464
|
+
if (!embMod) {
|
|
1465
|
+
console.log(' Estado: módulo embeddings.cjs no encontrado');
|
|
1466
|
+
console.log(' Solución: akdd update\n');
|
|
1467
|
+
} else if (!embMod.isAvailable()) {
|
|
1468
|
+
console.log(' Estado: @xenova/transformers no instalado');
|
|
1469
|
+
console.log(' Modelo: all-MiniLM-L6-v2 (23MB, 100% offline)');
|
|
1470
|
+
console.log(' Instalar: akdd embed-install\n');
|
|
1471
|
+
} else {
|
|
1472
|
+
console.log(' Estado: ✓ disponible');
|
|
1473
|
+
console.log(` Modelo: ${embMod.MODELO}`);
|
|
1474
|
+
console.log(` Dimensiones: ${embMod.DIM}`);
|
|
1475
|
+
console.log(' Búsqueda: vectorial híbrida (RRF)\n');
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
if (_args[0] === 'embed-install') {
|
|
1480
|
+
const embMod = getEmbeddingsModuleGrafo();
|
|
1481
|
+
if (!embMod) { console.log('\n akdd update primero\n'); process.exit(1); }
|
|
1482
|
+
embMod.instalar();
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// ─── v2.2: Lazy loaders de módulos (sin romper arranque si no existen) ────────
|
|
1486
|
+
function getEmbeddingsModuleGrafo() {
|
|
1487
|
+
try {
|
|
1488
|
+
const p = path.join(__dirname, 'embeddings.cjs');
|
|
1489
|
+
return fs.existsSync(p) ? require(p) : null;
|
|
1490
|
+
} catch(e) { return null; }
|
|
1491
|
+
}
|
|
1492
|
+
function getGitContextModuleGrafo() {
|
|
1493
|
+
try {
|
|
1494
|
+
const p = path.join(__dirname, 'git-context.cjs');
|
|
1495
|
+
return fs.existsSync(p) ? require(p) : null;
|
|
1496
|
+
} catch(e) { return null; }
|
|
1497
|
+
}
|
|
1498
|
+
function getPrediccionModuleGrafo() {
|
|
1499
|
+
try {
|
|
1500
|
+
const p = path.join(__dirname, 'prediccion.cjs');
|
|
1501
|
+
return fs.existsSync(p) ? require(p) : null;
|
|
1502
|
+
} catch(e) { return null; }
|
|
1503
|
+
}
|
|
1504
|
+
function getCICDModuleGrafo() {
|
|
1505
|
+
try {
|
|
1506
|
+
const p = path.join(__dirname, 'cicd.cjs');
|
|
1507
|
+
return fs.existsSync(p) ? require(p) : null;
|
|
1508
|
+
} catch(e) { return null; }
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
// ─── v2.2: buscar con embeddings (async) ────────────────────────────────────
|
|
1512
|
+
async function buscarHibridoConEmbeddings(query, area, topK) {
|
|
1513
|
+
const embMod = getEmbeddingsModuleGrafo();
|
|
1514
|
+
const db = initDB();
|
|
1515
|
+
|
|
1516
|
+
let sqlNodos = `SELECT *, 'procedural' as memoria_tipo FROM nodos WHERE estado='ACTIVO'`;
|
|
1517
|
+
if (area && area !== 'global') sqlNodos += ` AND (area=? OR area='global')`;
|
|
1518
|
+
const nodosAll = area ? db.all(sqlNodos, area) : db.all(sqlNodos);
|
|
1519
|
+
|
|
1520
|
+
let sqlEp = `SELECT *, 'episodica' as memoria_tipo FROM episodios WHERE relevancia > 0.3`;
|
|
1521
|
+
if (area && area !== 'global') sqlEp += ` AND (area=? OR area='global')`;
|
|
1522
|
+
sqlEp += ' ORDER BY fecha DESC LIMIT 50';
|
|
1523
|
+
const episodiosAll = area ? db.all(sqlEp, area) : db.all(sqlEp);
|
|
1524
|
+
|
|
1525
|
+
const entidadesAll = db.all("SELECT *, 'semantica' as memoria_tipo FROM entidades LIMIT 100");
|
|
1526
|
+
db.close();
|
|
1527
|
+
|
|
1528
|
+
const todos = [...nodosAll, ...episodiosAll, ...entidadesAll];
|
|
1529
|
+
if (embMod && embMod.isAvailable()) {
|
|
1530
|
+
return await embMod.buscarHibridoVectorial(todos, query, topK || 10);
|
|
1531
|
+
}
|
|
1532
|
+
return buscarHibrido(query, area, topK).resultados;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
// ─── v2.2: sync extendido (git-context + embeddings) ─────────────────────────
|
|
1536
|
+
// Se activa con: node grafo.cjs sync-v2
|
|
1537
|
+
if (_args[0] === 'sync-v2') {
|
|
1538
|
+
(async () => {
|
|
1539
|
+
// 1. Sync normal
|
|
1540
|
+
sincronizar();
|
|
1541
|
+
|
|
1542
|
+
const db = initDB();
|
|
1543
|
+
|
|
1544
|
+
// 2. Git context
|
|
1545
|
+
const gitMod = getGitContextModuleGrafo();
|
|
1546
|
+
if (gitMod && gitMod.gitDisponible(ROOT)) {
|
|
1547
|
+
const resultado = gitMod.analizarGitContext(ROOT, db);
|
|
1548
|
+
if (resultado.disponible && resultado.contexto) {
|
|
1549
|
+
const { riesgos, predicciones } = resultado.contexto;
|
|
1550
|
+
if (riesgos?.some(r => r.nivel === 'ALTO')) {
|
|
1551
|
+
console.log('\n ⚠️ ALERTAS:');
|
|
1552
|
+
riesgos.filter(r => r.nivel === 'ALTO').slice(0, 3).forEach(r =>
|
|
1553
|
+
console.log(` 🔴 [ALTO] ${r.archivo}: ${r.advertencia || ''}`));
|
|
1554
|
+
}
|
|
1555
|
+
if (predicciones?.length > 0) {
|
|
1556
|
+
console.log(' ⚡ Predicciones:');
|
|
1557
|
+
predicciones.slice(0, 3).forEach(p => console.log(` · ${p.mensaje}`));
|
|
1558
|
+
}
|
|
1559
|
+
// Guardar en working_memory
|
|
1560
|
+
const sesionId = `sync-v2-${Date.now()}`;
|
|
1561
|
+
try {
|
|
1562
|
+
db.run('UPDATE working_memory SET expirado=1 WHERE expirado=0');
|
|
1563
|
+
db.run(
|
|
1564
|
+
`INSERT INTO working_memory (sesion_id, tipo, contenido, relevancia) VALUES (?,?,?,?)`,
|
|
1565
|
+
sesionId, 'observacion', JSON.stringify(resultado.contexto), 1.0
|
|
1566
|
+
);
|
|
1567
|
+
} catch(e) {}
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
// 3. Embeddings — indexar pendientes
|
|
1572
|
+
const embMod = getEmbeddingsModuleGrafo();
|
|
1573
|
+
if (embMod && embMod.isAvailable()) {
|
|
1574
|
+
process.stdout.write(' Embeddings: indexando... ');
|
|
1575
|
+
try {
|
|
1576
|
+
const r = await embMod.indexarPendientes(db, 30);
|
|
1577
|
+
console.log(r.indexados > 0 ? `✓ (${r.indexados} nuevos)` : '✓ (al día)');
|
|
1578
|
+
} catch(e) { console.log(''); }
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
if (db.type === 'sqljs' && db.save) db.save();
|
|
1582
|
+
db.close();
|
|
1583
|
+
})();
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
// ─── v2.2: predicción para Context Guard ─────────────────────────────────────
|
|
1587
|
+
if (_args[0] === 'predecir') {
|
|
1588
|
+
const predMod = getPrediccionModuleGrafo();
|
|
1589
|
+
if (!predMod) { console.log(JSON.stringify({ nivel_riesgo: 'BAJO', alertas: [] })); process.exit(0); }
|
|
1590
|
+
try {
|
|
1591
|
+
const tarea = _args[1] || '';
|
|
1592
|
+
const archivos = _args[2] ? JSON.parse(_args[2]) : [];
|
|
1593
|
+
const modulo = _args[3] || 'global';
|
|
1594
|
+
const db = initDB();
|
|
1595
|
+
const resultado = predMod.evaluarRiesgoTarea(tarea, archivos, modulo, db);
|
|
1596
|
+
db.close();
|
|
1597
|
+
console.log(JSON.stringify(resultado, null, 2));
|
|
1598
|
+
} catch(e) { console.log(JSON.stringify({ nivel_riesgo: 'BAJO', alertas: [], error: e.message })); }
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
// ─── v2.2: schema migration ───────────────────────────────────────────────────
|
|
1602
|
+
// Las nuevas tablas se crean automáticamente en el próximo initDB()
|
|
1603
|
+
// grafo.cjs ya llama migrateDB() que tiene las ALTER TABLE
|
|
1604
|
+
// Solo hay que asegurar que las nuevas tablas de git_context_log, etc. se crean
|
|
1605
|
+
|
|
1606
|
+
// ─── v3.1: Migración para AST, Knowledge Base y Bi-temporal ─────────────────
|
|
1607
|
+
// Agentic KDD v3.1 — Nuevas tablas y columnas para Fases 1-3
|
|
1608
|
+
// Esta función se llama automáticamente en la siguiente ejecución.
|
|
1609
|
+
|
|
1610
|
+
function migrateV3_1(db) {
|
|
1611
|
+
// Columnas bi-temporales en relaciones_semanticas
|
|
1612
|
+
const biTemporalMigrations = [
|
|
1613
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN valid_at TEXT DEFAULT (datetime('now'))",
|
|
1614
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN invalid_at TEXT",
|
|
1615
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN expired_at TEXT",
|
|
1616
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN episode_id TEXT",
|
|
1617
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN confidence TEXT DEFAULT 'MEDIA'",
|
|
1618
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN context TEXT",
|
|
1619
|
+
"ALTER TABLE relaciones_semanticas ADD COLUMN source TEXT DEFAULT 'agent'",
|
|
1620
|
+
];
|
|
1621
|
+
biTemporalMigrations.forEach(sql => { try { db.exec(sql); } catch(e) {} });
|
|
1622
|
+
|
|
1623
|
+
// Índices bi-temporales
|
|
1624
|
+
const biTemporalIndices = [
|
|
1625
|
+
"CREATE INDEX IF NOT EXISTS idx_rel_sem_valid ON relaciones_semanticas(valid_at)",
|
|
1626
|
+
"CREATE INDEX IF NOT EXISTS idx_rel_sem_invalid ON relaciones_semanticas(invalid_at)",
|
|
1627
|
+
"CREATE INDEX IF NOT EXISTS idx_rel_sem_type ON relaciones_semanticas(tipo)",
|
|
1628
|
+
];
|
|
1629
|
+
biTemporalIndices.forEach(sql => { try { db.exec(sql); } catch(e) {} });
|
|
1630
|
+
|
|
1631
|
+
// Tabla AST Symbols
|
|
1632
|
+
const astSymbolsSQL = `
|
|
1633
|
+
CREATE TABLE IF NOT EXISTS ast_symbols (
|
|
1634
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1635
|
+
file TEXT NOT NULL,
|
|
1636
|
+
language TEXT NOT NULL,
|
|
1637
|
+
symbol_name TEXT NOT NULL,
|
|
1638
|
+
kind TEXT NOT NULL,
|
|
1639
|
+
line_start INTEGER DEFAULT 0,
|
|
1640
|
+
line_end INTEGER DEFAULT 0,
|
|
1641
|
+
exported INTEGER DEFAULT 0,
|
|
1642
|
+
signature TEXT,
|
|
1643
|
+
pagerank REAL DEFAULT 0.0,
|
|
1644
|
+
last_indexed TEXT DEFAULT (datetime('now')),
|
|
1645
|
+
content_hash TEXT
|
|
1646
|
+
)`;
|
|
1647
|
+
try { db.exec(astSymbolsSQL); } catch(e) {}
|
|
1648
|
+
try { db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_ast_sym_uniq ON ast_symbols(file, symbol_name, kind)"); } catch(e) {}
|
|
1649
|
+
try { db.exec("CREATE INDEX IF NOT EXISTS idx_ast_sym_file ON ast_symbols(file)"); } catch(e) {}
|
|
1650
|
+
|
|
1651
|
+
// Tabla AST Edges
|
|
1652
|
+
const astEdgesSQL = `
|
|
1653
|
+
CREATE TABLE IF NOT EXISTS ast_edges (
|
|
1654
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1655
|
+
from_file TEXT NOT NULL,
|
|
1656
|
+
to_file TEXT,
|
|
1657
|
+
from_symbol TEXT,
|
|
1658
|
+
to_symbol TEXT,
|
|
1659
|
+
kind TEXT NOT NULL,
|
|
1660
|
+
weight REAL DEFAULT 1.0,
|
|
1661
|
+
pagerank_src REAL DEFAULT 0.0,
|
|
1662
|
+
last_indexed TEXT DEFAULT (datetime('now'))
|
|
1663
|
+
)`;
|
|
1664
|
+
try { db.exec(astEdgesSQL); } catch(e) {}
|
|
1665
|
+
try { db.exec("CREATE INDEX IF NOT EXISTS idx_ast_edge_from ON ast_edges(from_file)"); } catch(e) {}
|
|
1666
|
+
try { db.exec("CREATE INDEX IF NOT EXISTS idx_ast_edge_to ON ast_edges(to_file)"); } catch(e) {}
|
|
1667
|
+
|
|
1668
|
+
// Tabla Knowledge Docs (ADRs, gotchas, convenciones)
|
|
1669
|
+
const knowledgeDocsSQL = `
|
|
1670
|
+
CREATE TABLE IF NOT EXISTS knowledge_docs (
|
|
1671
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1672
|
+
doc_id TEXT NOT NULL UNIQUE,
|
|
1673
|
+
tipo TEXT NOT NULL,
|
|
1674
|
+
titulo TEXT NOT NULL,
|
|
1675
|
+
status TEXT DEFAULT 'accepted',
|
|
1676
|
+
fecha TEXT,
|
|
1677
|
+
decision_makers TEXT DEFAULT '[]',
|
|
1678
|
+
afecta TEXT DEFAULT '[]',
|
|
1679
|
+
frontmatter TEXT DEFAULT '{}',
|
|
1680
|
+
contenido TEXT,
|
|
1681
|
+
context TEXT,
|
|
1682
|
+
decision TEXT,
|
|
1683
|
+
consequences TEXT,
|
|
1684
|
+
options TEXT DEFAULT '[]',
|
|
1685
|
+
file_path TEXT,
|
|
1686
|
+
last_indexed TEXT DEFAULT (datetime('now')),
|
|
1687
|
+
content_hash TEXT
|
|
1688
|
+
)`;
|
|
1689
|
+
try { db.exec(knowledgeDocsSQL); } catch(e) {}
|
|
1690
|
+
try { db.exec("CREATE INDEX IF NOT EXISTS idx_kdocs_tipo ON knowledge_docs(tipo)"); } catch(e) {}
|
|
1691
|
+
try { db.exec("CREATE INDEX IF NOT EXISTS idx_kdocs_status ON knowledge_docs(status)"); } catch(e) {}
|
|
1692
|
+
|
|
1693
|
+
// campo gate_result en fases (para harness tracking)
|
|
1694
|
+
try { db.exec("ALTER TABLE fases ADD COLUMN gate_result TEXT"); } catch(e) {}
|
|
1695
|
+
try { db.exec("ALTER TABLE fases ADD COLUMN harness_passed INTEGER DEFAULT 0"); } catch(e) {}
|
|
1696
|
+
|
|
1697
|
+
// campo ast_indexed en ciclos
|
|
1698
|
+
try { db.exec("ALTER TABLE ciclos ADD COLUMN ast_indexed INTEGER DEFAULT 0"); } catch(e) {}
|
|
1699
|
+
try { db.exec("ALTER TABLE ciclos ADD COLUMN knowledge_loaded INTEGER DEFAULT 0"); } catch(e) {}
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
// Auto-run migrateV3_1 when grafo.cjs is first loaded
|
|
1703
|
+
(function autoMigrateV3_1() {
|
|
1704
|
+
try {
|
|
1705
|
+
const _dbForMigration = initDB();
|
|
1706
|
+
migrateV3_1(_dbForMigration);
|
|
1707
|
+
if (_dbForMigration.save) _dbForMigration.save();
|
|
1708
|
+
_dbForMigration.close();
|
|
1709
|
+
} catch(e) {
|
|
1710
|
+
// Silent — migration runs opportunistically
|
|
1711
|
+
}
|
|
1712
|
+
})();
|
|
1713
|
+
|
|
1714
|
+
// Export migrateV3_1
|
|
1715
|
+
const _exportsV31 = module.exports || {};
|
|
1716
|
+
module.exports = { ..._exportsV31, migrateV3_1 };
|
|
1717
|
+
|
|
1718
|
+
|
|
1719
|
+
// ─── v3.2: Vigencia de Memoria + Verdad Vigente ────────────────────────────
|
|
1720
|
+
// Cierra el Gap #1: límite claro entre memoria vigente, histórica y evidencia
|
|
1721
|
+
|
|
1722
|
+
function migrateV3_2(db) {
|
|
1723
|
+
// Columna vigencia_tipo en nodos
|
|
1724
|
+
try { db.exec("ALTER TABLE nodos ADD COLUMN vigencia_tipo TEXT DEFAULT 'VIGENTE'"); } catch {}
|
|
1725
|
+
try { db.exec("CREATE INDEX IF NOT EXISTS idx_nodos_vigencia ON nodos(vigencia_tipo)"); } catch {}
|
|
1726
|
+
// Inferir vigencia_tipo para registros existentes
|
|
1727
|
+
try {
|
|
1728
|
+
db.exec("UPDATE nodos SET vigencia_tipo='OBSOLETO' WHERE estado='OBSOLETO' AND vigencia_tipo='VIGENTE'");
|
|
1729
|
+
db.exec("UPDATE nodos SET vigencia_tipo='HISTORICO' WHERE estado='CONSOLIDADO' AND vigencia_tipo='VIGENTE'");
|
|
1730
|
+
} catch {}
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
// Auto-run
|
|
1734
|
+
(function autoMigrateV3_2() {
|
|
1735
|
+
try {
|
|
1736
|
+
const _db = initDB();
|
|
1737
|
+
migrateV3_2(_db);
|
|
1738
|
+
if (_db.save) _db.save();
|
|
1739
|
+
_db.close();
|
|
1740
|
+
} catch {}
|
|
1741
|
+
})();
|
|
1742
|
+
|
|
1743
|
+
const _exportsV32 = module.exports || {};
|
|
1744
|
+
module.exports = { ..._exportsV32, migrateV3_2 };
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
// ─── v3.2: AUTO-INTEGRATION — MemCurator + llms-generator ─────────────────────
|
|
1748
|
+
// Se hookan automáticamente en el flujo de sync existente.
|
|
1749
|
+
|
|
1750
|
+
const _grafoPath = __dirname;
|
|
1751
|
+
|
|
1752
|
+
function _autoRunCurator() {
|
|
1753
|
+
try {
|
|
1754
|
+
const db = initDB();
|
|
1755
|
+
// Contar ciclos desde última curation
|
|
1756
|
+
let lastCuration = 0;
|
|
1757
|
+
try {
|
|
1758
|
+
const meta = db.prepare("SELECT valor FROM metadata WHERE clave='last_curator_cycle'").get();
|
|
1759
|
+
lastCuration = parseInt(meta?.valor || '0');
|
|
1760
|
+
} catch {}
|
|
1761
|
+
const totalCycles = db.prepare("SELECT COUNT(*) as n FROM ciclos").get()?.n || 0;
|
|
1762
|
+
if (totalCycles - lastCuration >= 10) {
|
|
1763
|
+
const { runCuration } = require(require('path').join(_grafoPath, 'mem-curator.cjs'));
|
|
1764
|
+
runCuration(process.cwd());
|
|
1765
|
+
try {
|
|
1766
|
+
db.prepare("INSERT OR REPLACE INTO metadata (clave, valor) VALUES ('last_curator_cycle', ?)").run(String(totalCycles));
|
|
1767
|
+
} catch {
|
|
1768
|
+
try { db.prepare("CREATE TABLE IF NOT EXISTS metadata (clave TEXT PRIMARY KEY, valor TEXT)").run(); } catch {}
|
|
1769
|
+
try { db.prepare("INSERT OR REPLACE INTO metadata (clave, valor) VALUES ('last_curator_cycle', ?)").run(String(totalCycles)); } catch {}
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
if (db.save) db.save(); db.close();
|
|
1773
|
+
} catch {}
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
function _autoGenerateLlms() {
|
|
1777
|
+
try {
|
|
1778
|
+
const { generateAll } = require(require('path').join(_grafoPath, 'llms-generator.cjs'));
|
|
1779
|
+
generateAll(process.cwd());
|
|
1780
|
+
} catch {}
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// Hookar en la función sincronizar existente
|
|
1784
|
+
const _origExports = module.exports || {};
|
|
1785
|
+
const _origSync = _origExports.sincronizar;
|
|
1786
|
+
if (_origSync && typeof _origSync === 'function') {
|
|
1787
|
+
_origExports.sincronizar = function(...args) {
|
|
1788
|
+
const result = _origSync.apply(this, args);
|
|
1789
|
+
try { _autoRunCurator(); } catch {}
|
|
1790
|
+
try { _autoGenerateLlms(); } catch {}
|
|
1791
|
+
return result;
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
module.exports = { ..._origExports };
|
|
1796
|
+
|
|
1797
|
+
// ─── v3.3: CONTRACT GUARD + CREATIVE ENGINE AUTO-INTEGRATION ─────────────────
|
|
1798
|
+
|
|
1799
|
+
function _autoRunContractGuard(cicloId, testOutput) {
|
|
1800
|
+
try {
|
|
1801
|
+
const db = initDB();
|
|
1802
|
+
const cg = require(require('path').join(__dirname, 'contract-guard.cjs'));
|
|
1803
|
+
cg.migrateSchema(db);
|
|
1804
|
+
if (testOutput) {
|
|
1805
|
+
cg.ingestFromCycle(db, process.cwd(), cicloId, testOutput);
|
|
1806
|
+
}
|
|
1807
|
+
if (db.save) db.save(); db.close();
|
|
1808
|
+
} catch {}
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
function _autoRunCreativeEngine(cicloId) {
|
|
1812
|
+
try {
|
|
1813
|
+
const db = initDB();
|
|
1814
|
+
const ce = require(require('path').join(__dirname, 'creative-engine.cjs'));
|
|
1815
|
+
ce.migrateSchema(db);
|
|
1816
|
+
const result = ce.runCreativePass(db, process.cwd(), cicloId);
|
|
1817
|
+
if (result.new_suggestions > 0 || result.auto_applied > 0) {
|
|
1818
|
+
console.error(`[CREATIVE] Level ${result.level}: ${result.new_suggestions} suggestions, ${result.auto_applied} auto-applied`);
|
|
1819
|
+
}
|
|
1820
|
+
if (db.save) db.save(); db.close();
|
|
1821
|
+
} catch {}
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
// Hook into existing exports
|
|
1825
|
+
const _contractCreativeExports = module.exports || {};
|
|
1826
|
+
const _origSyncCC = _contractCreativeExports.sincronizar;
|
|
1827
|
+
if (_origSyncCC && typeof _origSyncCC === 'function') {
|
|
1828
|
+
_contractCreativeExports.sincronizar = function(...args) {
|
|
1829
|
+
const result = _origSyncCC.apply(this, args);
|
|
1830
|
+
const cicloId = `sync-${Date.now()}`;
|
|
1831
|
+
try { _autoRunContractGuard(cicloId, null); } catch {}
|
|
1832
|
+
try { _autoRunCreativeEngine(cicloId); } catch {}
|
|
1833
|
+
return result;
|
|
1834
|
+
};
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
module.exports = { ..._contractCreativeExports };
|
|
1838
|
+
|
|
1839
|
+
// ─── v3.3: SESSION GUARD AUTO-CHECKPOINT ──────────────────────────────────────
|
|
1840
|
+
function _autoSessionGuard() {
|
|
1841
|
+
try {
|
|
1842
|
+
const db = initDB();
|
|
1843
|
+
const cycles = db.prepare("SELECT COUNT(*) as n FROM ciclos").get()?.n || 0;
|
|
1844
|
+
if (cycles > 0 && cycles % 5 === 0) {
|
|
1845
|
+
const { generateCheckpoint } = require(require('path').join(__dirname, 'session-guard.cjs'));
|
|
1846
|
+
generateCheckpoint(process.cwd());
|
|
1847
|
+
console.error('[SESSION] Checkpoint guardado (.agentic/checkpoint.md)');
|
|
1848
|
+
}
|
|
1849
|
+
if (db.save) db.save(); db.close();
|
|
1850
|
+
} catch {}
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
const _sgExports = module.exports || {};
|
|
1854
|
+
const _origSyncSG = _sgExports.sincronizar;
|
|
1855
|
+
if (_origSyncSG && typeof _origSyncSG === 'function') {
|
|
1856
|
+
_sgExports.sincronizar = function(...args) {
|
|
1857
|
+
const result = _origSyncSG.apply(this, args);
|
|
1858
|
+
try { _autoSessionGuard(); } catch {}
|
|
1859
|
+
return result;
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1862
|
+
module.exports = { ..._sgExports };
|
|
1863
|
+
|
|
1864
|
+
// ─── v3.3: AUTONOMOUS DECISION ENGINE AUTO-INTEGRATION ────────────────────────
|
|
1865
|
+
// Se hookea en el sync para correr la cola diferida al final de cada ciclo
|
|
1866
|
+
|
|
1867
|
+
function _autoFlushDeferred() {
|
|
1868
|
+
try {
|
|
1869
|
+
const { flushDeferredQueue } = require(require('path').join(__dirname, 'autonomous-decision.cjs'));
|
|
1870
|
+
const flushed = flushDeferredQueue(process.cwd());
|
|
1871
|
+
if (flushed.length > 0) {
|
|
1872
|
+
console.error(`[AUTONOMOUS] ${flushed.length} deferred item(s) from queue — review as suggestions`);
|
|
1873
|
+
// Add to creative engine suggestions
|
|
1874
|
+
try {
|
|
1875
|
+
const { addSuggestion } = require(require('path').join(__dirname, 'creative-engine.cjs'));
|
|
1876
|
+
const db = initDB();
|
|
1877
|
+
flushed.forEach(item => {
|
|
1878
|
+
addSuggestion(db, {
|
|
1879
|
+
type: 'OPPORTUNITY',
|
|
1880
|
+
title: item.task || 'Deferred task',
|
|
1881
|
+
description: item.reason || 'Deferred by Autonomous Decision Engine',
|
|
1882
|
+
module: (item.files || [])[0] || 'global',
|
|
1883
|
+
}, `deferred-${Date.now()}`);
|
|
1884
|
+
});
|
|
1885
|
+
if (db.save) db.save(); db.close();
|
|
1886
|
+
} catch {}
|
|
1887
|
+
}
|
|
1888
|
+
} catch {}
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
const _adExports = module.exports || {};
|
|
1892
|
+
const _origSyncAD = _adExports.sincronizar;
|
|
1893
|
+
if (_origSyncAD && typeof _origSyncAD === 'function') {
|
|
1894
|
+
_adExports.sincronizar = function(...args) {
|
|
1895
|
+
const result = _origSyncAD.apply(this, args);
|
|
1896
|
+
try { _autoFlushDeferred(); } catch {}
|
|
1897
|
+
return result;
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
module.exports = { ..._adExports };
|
|
1901
|
+
|
|
1902
|
+
// ─── v3.4: kdd-memory + knowledge-validator + telemetry INTEGRATION ─────────
|
|
1903
|
+
|
|
1904
|
+
function _autoKDDMemorySync() {
|
|
1905
|
+
try {
|
|
1906
|
+
const { syncFTS } = require(require('path').join(__dirname, 'kdd-memory.cjs'));
|
|
1907
|
+
const db = initDB();
|
|
1908
|
+
const nodeCount = db.prepare("SELECT COUNT(*) as n FROM nodos WHERE estado='ACTIVO'").get()?.n || 0;
|
|
1909
|
+
let ftsCount = 0;
|
|
1910
|
+
try { ftsCount = db.prepare("SELECT COUNT(*) as n FROM nodos_fts").get()?.n || 0; } catch {}
|
|
1911
|
+
if (ftsCount < nodeCount * 0.9) {
|
|
1912
|
+
syncFTS(db);
|
|
1913
|
+
console.error('[KDD-MEMORY] FTS index synced');
|
|
1914
|
+
}
|
|
1915
|
+
if (db.save) db.save(); db.close();
|
|
1916
|
+
} catch {}
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
function _autoKnowledgeValidation() {
|
|
1920
|
+
try {
|
|
1921
|
+
const { scanAll } = require(require('path').join(__dirname, 'knowledge-validator.cjs'));
|
|
1922
|
+
const result = scanAll(process.cwd());
|
|
1923
|
+
if (result.sospechoso > 0 || result.poison_candidates > 0) {
|
|
1924
|
+
console.error(`[VALIDATOR] ${result.sospechoso} suspicious + ${result.poison_candidates} poison candidates`);
|
|
1925
|
+
}
|
|
1926
|
+
} catch {}
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
const _kdmExports = module.exports || {};
|
|
1930
|
+
const _origSyncKDM = _kdmExports.sincronizar;
|
|
1931
|
+
if (_origSyncKDM && typeof _origSyncKDM === 'function') {
|
|
1932
|
+
_kdmExports.sincronizar = function(...args) {
|
|
1933
|
+
const result = _origSyncKDM.apply(this, args);
|
|
1934
|
+
try { _autoKDDMemorySync(); } catch {}
|
|
1935
|
+
return result;
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
module.exports = { ..._kdmExports };
|
|
1939
|
+
|
|
1940
|
+
// ─── v3.6: project_settings — config persistente en BD ──────────────────────
|
|
1941
|
+
// Guarda CONFIGURADO, nombre, stack y test command en memoria.db
|
|
1942
|
+
// Fuente de verdad secundaria cuando config.md falla o se pisa durante update
|
|
1943
|
+
|
|
1944
|
+
(function migrateProjectSettings() {
|
|
1945
|
+
try {
|
|
1946
|
+
const _db = initDB();
|
|
1947
|
+
|
|
1948
|
+
// Crear tabla project_settings si no existe
|
|
1949
|
+
_db.exec(`
|
|
1950
|
+
CREATE TABLE IF NOT EXISTS project_settings (
|
|
1951
|
+
key TEXT PRIMARY KEY,
|
|
1952
|
+
value TEXT NOT NULL,
|
|
1953
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
1954
|
+
)
|
|
1955
|
+
`);
|
|
1956
|
+
|
|
1957
|
+
// Leer config.md y sincronizar a BD si CONFIGURADO: SI
|
|
1958
|
+
const fs = require('fs');
|
|
1959
|
+
const path = require('path');
|
|
1960
|
+
const configPath = path.join(process.cwd(), '.agentic', 'config.md');
|
|
1961
|
+
|
|
1962
|
+
if (fs.existsSync(configPath)) {
|
|
1963
|
+
const config = fs.readFileSync(configPath, 'utf8');
|
|
1964
|
+
const configured = /^CONFIGURADO:\s*SI/m.test(config);
|
|
1965
|
+
|
|
1966
|
+
if (configured) {
|
|
1967
|
+
// Guardar estado en BD
|
|
1968
|
+
const upsert = _db.prepare(`
|
|
1969
|
+
INSERT INTO project_settings (key, value, updated_at)
|
|
1970
|
+
VALUES (?, ?, datetime('now'))
|
|
1971
|
+
ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at
|
|
1972
|
+
`);
|
|
1973
|
+
|
|
1974
|
+
upsert.run('configured', 'true');
|
|
1975
|
+
|
|
1976
|
+
const nameMatch = config.match(/^Nombre:\s*(.+)$/m);
|
|
1977
|
+
if (nameMatch) upsert.run('project_name', nameMatch[1].trim());
|
|
1978
|
+
|
|
1979
|
+
const testMatch = config.match(/^\s*test:\s*(.+)$/m);
|
|
1980
|
+
if (testMatch && testMatch[1].trim() !== '—') {
|
|
1981
|
+
upsert.run('test_command', testMatch[1].trim());
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
const stackBlock = config.match(/^## Stack\n([\s\S]+?)(?=\n##|$)/m);
|
|
1985
|
+
if (stackBlock) upsert.run('stack', stackBlock[1].trim());
|
|
1986
|
+
}
|
|
1987
|
+
} else {
|
|
1988
|
+
// config.md no existe — intentar restaurar desde BD
|
|
1989
|
+
const settings = {};
|
|
1990
|
+
try {
|
|
1991
|
+
const rows = _db.prepare('SELECT key, value FROM project_settings').all();
|
|
1992
|
+
for (const row of rows) settings[row.key] = row.value;
|
|
1993
|
+
} catch {}
|
|
1994
|
+
|
|
1995
|
+
if (settings.configured === 'true' && fs.existsSync(path.join(process.cwd(), '.agentic'))) {
|
|
1996
|
+
// Reconstruir config.md mínimo desde BD
|
|
1997
|
+
const lines = [
|
|
1998
|
+
'# Agentic KDD — Configuración del proyecto',
|
|
1999
|
+
'CONFIGURADO: SI',
|
|
2000
|
+
'VERSION: 2.0',
|
|
2001
|
+
'',
|
|
2002
|
+
'## Proyecto',
|
|
2003
|
+
`Nombre: ${settings.project_name || '(restaurado desde BD)'}`,
|
|
2004
|
+
'Descripción: —',
|
|
2005
|
+
'Tipo: EXISTENTE',
|
|
2006
|
+
'',
|
|
2007
|
+
settings.stack ? `## Stack\n${settings.stack}` : '## Stack\n—',
|
|
2008
|
+
'',
|
|
2009
|
+
'## Comando de tests',
|
|
2010
|
+
settings.test_command ? `test: ${settings.test_command}` : 'test: —',
|
|
2011
|
+
];
|
|
2012
|
+
fs.writeFileSync(configPath, lines.join('\n'), 'utf8');
|
|
2013
|
+
console.error('[AGENTIC] config.md restaurado desde memoria.db');
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
if (_db.save) _db.save();
|
|
2018
|
+
_db.close();
|
|
2019
|
+
} catch(e) {
|
|
2020
|
+
// Silent — best effort
|
|
2021
|
+
}
|
|
2022
|
+
})();
|
|
2023
|
+
|
|
2024
|
+
const _ps36Exports = module.exports || {};
|
|
2025
|
+
module.exports = { ..._ps36Exports };
|