agentic-kdd 3.0.4 → 3.2.1
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/bin/akdd.js +69 -0
- package/contract-guard.cjs +851 -0
- package/creative-engine.cjs +560 -0
- package/embeddings-v2.cjs +320 -0
- package/llms-generator.cjs +425 -0
- package/mem-curator.cjs +584 -0
- package/package.json +1 -1
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic KDD — llms.txt Generator v1.0
|
|
3
|
+
*
|
|
4
|
+
* Genera automáticamente:
|
|
5
|
+
* .agentic/llms.txt — mapa estructural mínimo para agentes externos
|
|
6
|
+
* .agentic/llms-full.txt — versión expandida con todas las reglas vigentes
|
|
7
|
+
* .agentic/knowledge-graph.json — grafo causal serializado para Git versioning
|
|
8
|
+
*
|
|
9
|
+
* ¿Qué resuelve?
|
|
10
|
+
* Gap: "Discoverability" — agentes externos no saben qué hay en Agentic KDD sin indexar todo
|
|
11
|
+
* Solución: llms.txt es el estándar emergente (equiv a robots.txt pero para LLMs)
|
|
12
|
+
*
|
|
13
|
+
* Gap: "Grafo descentralizado" — el reporte pide que el grafo viaje en el repo vía Git
|
|
14
|
+
* Solución: knowledge-graph.json en .agentic/ → versión del grafo junto al código
|
|
15
|
+
*
|
|
16
|
+
* Gap: "Progressive disclosure" — developer nuevo no sabe por dónde empezar
|
|
17
|
+
* Solución: llms.txt actúa como mapa de onboarding estructurado
|
|
18
|
+
*
|
|
19
|
+
* Se ejecuta automáticamente en: akdd sync, akdd update
|
|
20
|
+
* También se puede correr manualmente: node llms-generator.cjs
|
|
21
|
+
*
|
|
22
|
+
* Uso:
|
|
23
|
+
* node .agentic/grafo/llms-generator.cjs generate
|
|
24
|
+
* node .agentic/grafo/llms-generator.cjs graph
|
|
25
|
+
* node .agentic/grafo/llms-generator.cjs all
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
'use strict';
|
|
29
|
+
|
|
30
|
+
const path = require('path');
|
|
31
|
+
const fs = require('fs');
|
|
32
|
+
|
|
33
|
+
// ─── DB HELPER ────────────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
function openDB(projectRoot) {
|
|
36
|
+
const dbPath = path.join(projectRoot, '.agentic/memoria.db');
|
|
37
|
+
try { return new (require('better-sqlite3'))(dbPath); } catch {}
|
|
38
|
+
try { const { DatabaseSync } = require('node:sqlite'); return new DatabaseSync(dbPath); } catch {}
|
|
39
|
+
return null; // Si no hay DB, generar desde config.md
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ─── LEER CONFIG DEL PROYECTO ────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
function readProjectConfig(projectRoot) {
|
|
45
|
+
const configPath = path.join(projectRoot, '.agentic', 'config.md');
|
|
46
|
+
if (!fs.existsSync(configPath)) return {};
|
|
47
|
+
|
|
48
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
49
|
+
const config = {};
|
|
50
|
+
|
|
51
|
+
// Extraer campos clave del config.md
|
|
52
|
+
const extractField = (key) => {
|
|
53
|
+
const match = content.match(new RegExp(`${key}:\\s*(.+)`));
|
|
54
|
+
return match ? match[1].trim() : null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
config.proyecto = extractField('PROYECTO');
|
|
58
|
+
config.stack = extractField('STACK');
|
|
59
|
+
config.descripcion= extractField('DESCRIPCIÓN') || extractField('DESCRIPCION');
|
|
60
|
+
config.modulos = [];
|
|
61
|
+
|
|
62
|
+
// Extraer módulos listados
|
|
63
|
+
const modulosMatch = content.match(/MÓDULOS[^\n]*\n([\s\S]*?)(?=\n##|\n\*\*|$)/i);
|
|
64
|
+
if (modulosMatch) {
|
|
65
|
+
config.modulos = modulosMatch[1]
|
|
66
|
+
.split('\n')
|
|
67
|
+
.map(l => l.replace(/^[-*\s]+/, '').trim())
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.slice(0, 20);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return config;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ─── GENERAR llms.txt ─────────────────────────────────────────────────────────
|
|
76
|
+
/**
|
|
77
|
+
* llms.txt: formato estándar emergente para que LLMs se orienten en un proyecto.
|
|
78
|
+
* Minimalista. Agentes externos lo leen antes de explorar el codebase.
|
|
79
|
+
*/
|
|
80
|
+
function generateLlmsTxt(projectRoot, db) {
|
|
81
|
+
const config = readProjectConfig(projectRoot);
|
|
82
|
+
|
|
83
|
+
const lines = [];
|
|
84
|
+
const now = new Date().toISOString().split('T')[0];
|
|
85
|
+
|
|
86
|
+
lines.push(`# ${config.proyecto || path.basename(projectRoot)}`);
|
|
87
|
+
lines.push('');
|
|
88
|
+
if (config.descripcion) {
|
|
89
|
+
lines.push(`> ${config.descripcion}`);
|
|
90
|
+
lines.push('');
|
|
91
|
+
}
|
|
92
|
+
lines.push(`> Agentic KDD v3.2 — Knowledge-Driven Development`);
|
|
93
|
+
lines.push(`> Generated: ${now}`);
|
|
94
|
+
lines.push('');
|
|
95
|
+
|
|
96
|
+
// Stack
|
|
97
|
+
if (config.stack) {
|
|
98
|
+
lines.push('## Stack');
|
|
99
|
+
lines.push('');
|
|
100
|
+
config.stack.split(/[,/]/).map(s => s.trim()).filter(Boolean).forEach(s => {
|
|
101
|
+
lines.push(`- ${s}`);
|
|
102
|
+
});
|
|
103
|
+
lines.push('');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Módulos del proyecto
|
|
107
|
+
if (db) {
|
|
108
|
+
try {
|
|
109
|
+
const entities = db.prepare(`
|
|
110
|
+
SELECT nombre, tipo, descripcion, area
|
|
111
|
+
FROM entidades WHERE tipo IN ('modulo','archivo','api','tabla')
|
|
112
|
+
ORDER BY tipo, nombre LIMIT 30
|
|
113
|
+
`).all();
|
|
114
|
+
|
|
115
|
+
if (entities.length > 0) {
|
|
116
|
+
lines.push('## Architecture');
|
|
117
|
+
lines.push('');
|
|
118
|
+
const byType = {};
|
|
119
|
+
entities.forEach(e => {
|
|
120
|
+
if (!byType[e.tipo]) byType[e.tipo] = [];
|
|
121
|
+
byType[e.tipo].push(e);
|
|
122
|
+
});
|
|
123
|
+
Object.entries(byType).forEach(([tipo, ents]) => {
|
|
124
|
+
lines.push(`### ${tipo.charAt(0).toUpperCase() + tipo.slice(1)}s`);
|
|
125
|
+
ents.slice(0, 10).forEach(e => {
|
|
126
|
+
lines.push(`- **${e.nombre}**: ${e.descripcion || e.area || tipo}`);
|
|
127
|
+
});
|
|
128
|
+
lines.push('');
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
} catch {}
|
|
132
|
+
} else if (config.modulos?.length > 0) {
|
|
133
|
+
lines.push('## Modules');
|
|
134
|
+
lines.push('');
|
|
135
|
+
config.modulos.forEach(m => lines.push(`- ${m}`));
|
|
136
|
+
lines.push('');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Reglas vigentes HIGH
|
|
140
|
+
if (db) {
|
|
141
|
+
try {
|
|
142
|
+
const rules = db.prepare(`
|
|
143
|
+
SELECT titulo, area, tipo
|
|
144
|
+
FROM nodos
|
|
145
|
+
WHERE confianza = 'ALTA'
|
|
146
|
+
AND estado = 'ACTIVO'
|
|
147
|
+
AND (vigencia_tipo = 'VIGENTE' OR vigencia_tipo IS NULL)
|
|
148
|
+
ORDER BY aplicado DESC LIMIT 15
|
|
149
|
+
`).all();
|
|
150
|
+
|
|
151
|
+
if (rules.length > 0) {
|
|
152
|
+
lines.push('## Key Rules (HIGH confidence)');
|
|
153
|
+
lines.push('');
|
|
154
|
+
rules.forEach(r => {
|
|
155
|
+
lines.push(`- [${r.tipo}] ${r.titulo} (${r.area || 'global'})`);
|
|
156
|
+
});
|
|
157
|
+
lines.push('');
|
|
158
|
+
}
|
|
159
|
+
} catch {}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ADRs activos
|
|
163
|
+
if (db) {
|
|
164
|
+
try {
|
|
165
|
+
const adrs = db.prepare(`
|
|
166
|
+
SELECT titulo, decision, status FROM knowledge_docs
|
|
167
|
+
WHERE status = 'accepted' LIMIT 10
|
|
168
|
+
`).all();
|
|
169
|
+
|
|
170
|
+
if (adrs.length > 0) {
|
|
171
|
+
lines.push('## Architecture Decisions');
|
|
172
|
+
lines.push('');
|
|
173
|
+
adrs.forEach(a => {
|
|
174
|
+
lines.push(`- **${a.titulo}**: ${a.decision?.substring(0, 80) || ''}`);
|
|
175
|
+
});
|
|
176
|
+
lines.push('');
|
|
177
|
+
}
|
|
178
|
+
} catch {}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Errores frecuentes (memoria causal)
|
|
182
|
+
if (db) {
|
|
183
|
+
try {
|
|
184
|
+
const errors = db.prepare(`
|
|
185
|
+
SELECT titulo FROM nodos
|
|
186
|
+
WHERE tipo = 'error'
|
|
187
|
+
AND confianza IN ('ALTA','MEDIA')
|
|
188
|
+
AND estado = 'ACTIVO'
|
|
189
|
+
ORDER BY aplicado DESC LIMIT 10
|
|
190
|
+
`).all();
|
|
191
|
+
|
|
192
|
+
if (errors.length > 0) {
|
|
193
|
+
lines.push('## Known Pitfalls');
|
|
194
|
+
lines.push('');
|
|
195
|
+
errors.forEach(e => lines.push(`- ${e.titulo}`));
|
|
196
|
+
lines.push('');
|
|
197
|
+
}
|
|
198
|
+
} catch {}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Footer
|
|
202
|
+
lines.push('## Agentic KDD Tools');
|
|
203
|
+
lines.push('');
|
|
204
|
+
lines.push('This project uses Agentic KDD for persistent AI memory. Available MCP tools:');
|
|
205
|
+
lines.push('- `grafo_buscar` — hybrid search across 4 CoALA memory layers');
|
|
206
|
+
lines.push('- `ast_impact` — pre-change impact analysis');
|
|
207
|
+
lines.push('- `knowledge_query` — query ADRs and gotchas');
|
|
208
|
+
lines.push('- `verdad_vigente` — currently valid rules only');
|
|
209
|
+
lines.push('- `decision_trail` — decision observability');
|
|
210
|
+
lines.push('- `health_check` — full system diagnostic');
|
|
211
|
+
lines.push('');
|
|
212
|
+
lines.push('Run `akdd health` to verify system state before working.');
|
|
213
|
+
lines.push('');
|
|
214
|
+
|
|
215
|
+
return lines.join('\n');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ─── GENERAR llms-full.txt ────────────────────────────────────────────────────
|
|
219
|
+
/**
|
|
220
|
+
* Versión expandida con TODO el conocimiento vigente del proyecto.
|
|
221
|
+
* Para agentes que necesitan contexto completo antes de empezar.
|
|
222
|
+
*/
|
|
223
|
+
function generateLlmsFullTxt(projectRoot, db) {
|
|
224
|
+
if (!db) return null;
|
|
225
|
+
|
|
226
|
+
const lines = [];
|
|
227
|
+
const minimal = generateLlmsTxt(projectRoot, db);
|
|
228
|
+
lines.push(minimal);
|
|
229
|
+
|
|
230
|
+
lines.push('---');
|
|
231
|
+
lines.push('## Full Knowledge Base');
|
|
232
|
+
lines.push('');
|
|
233
|
+
|
|
234
|
+
// Todos los patrones ALTA y MEDIA vigentes
|
|
235
|
+
try {
|
|
236
|
+
const patterns = db.prepare(`
|
|
237
|
+
SELECT titulo, contenido, tipo, area, aplicado, util
|
|
238
|
+
FROM nodos
|
|
239
|
+
WHERE estado = 'ACTIVO'
|
|
240
|
+
AND confianza IN ('ALTA', 'MEDIA')
|
|
241
|
+
AND (vigencia_tipo = 'VIGENTE' OR vigencia_tipo IS NULL)
|
|
242
|
+
ORDER BY confianza DESC, aplicado DESC
|
|
243
|
+
LIMIT 50
|
|
244
|
+
`).all();
|
|
245
|
+
|
|
246
|
+
if (patterns.length > 0) {
|
|
247
|
+
lines.push('### All Active Patterns');
|
|
248
|
+
lines.push('');
|
|
249
|
+
patterns.forEach(p => {
|
|
250
|
+
lines.push(`#### [${p.tipo}] ${p.titulo} (${p.area || 'global'})`);
|
|
251
|
+
if (p.contenido) lines.push(p.contenido.substring(0, 300));
|
|
252
|
+
lines.push(`*Applied: ${p.aplicado || 0}× | Useful: ${p.util || 0}×*`);
|
|
253
|
+
lines.push('');
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
} catch {}
|
|
257
|
+
|
|
258
|
+
// Causal edges activos
|
|
259
|
+
try {
|
|
260
|
+
const edges = db.prepare(`
|
|
261
|
+
SELECT desde_entidad, tipo, hacia_entidad, descripcion
|
|
262
|
+
FROM relaciones_semanticas
|
|
263
|
+
WHERE tipo IN ('caused_failure','was_fixed_by','tested_by','regressed_by')
|
|
264
|
+
AND (invalid_at IS NULL OR invalid_at = '')
|
|
265
|
+
ORDER BY valid_at DESC LIMIT 30
|
|
266
|
+
`).all();
|
|
267
|
+
|
|
268
|
+
if (edges.length > 0) {
|
|
269
|
+
lines.push('### Causal Memory');
|
|
270
|
+
lines.push('');
|
|
271
|
+
edges.forEach(e => {
|
|
272
|
+
lines.push(`- ${e.desde_entidad} --${e.tipo}--> ${e.hacia_entidad}`);
|
|
273
|
+
if (e.descripcion) lines.push(` *${e.descripcion.substring(0, 100)}*`);
|
|
274
|
+
});
|
|
275
|
+
lines.push('');
|
|
276
|
+
}
|
|
277
|
+
} catch {}
|
|
278
|
+
|
|
279
|
+
return lines.join('\n');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ─── GENERAR knowledge-graph.json ────────────────────────────────────────────
|
|
283
|
+
/**
|
|
284
|
+
* Grafo causal serializado para Git versioning.
|
|
285
|
+
* Viaja con el repo → el equipo comparte el grafo sin infraestructura externa.
|
|
286
|
+
* Inspirado en Graphify y Understand Anything.
|
|
287
|
+
*/
|
|
288
|
+
function generateKnowledgeGraph(projectRoot, db) {
|
|
289
|
+
if (!db) return null;
|
|
290
|
+
|
|
291
|
+
const graph = {
|
|
292
|
+
version: '3.2',
|
|
293
|
+
generated: new Date().toISOString(),
|
|
294
|
+
project: path.basename(projectRoot),
|
|
295
|
+
nodes: [],
|
|
296
|
+
edges: [],
|
|
297
|
+
decisions: [],
|
|
298
|
+
stats: {},
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// Nodos procedurales vigentes
|
|
302
|
+
try {
|
|
303
|
+
graph.nodes = db.prepare(`
|
|
304
|
+
SELECT id, tipo, titulo, area, confianza, aplicado, util,
|
|
305
|
+
decay_score, vigencia_tipo, fecha_creacion
|
|
306
|
+
FROM nodos
|
|
307
|
+
WHERE estado = 'ACTIVO'
|
|
308
|
+
AND (vigencia_tipo = 'VIGENTE' OR vigencia_tipo IS NULL)
|
|
309
|
+
AND confianza IN ('ALTA', 'MEDIA')
|
|
310
|
+
ORDER BY confianza DESC, aplicado DESC
|
|
311
|
+
LIMIT 200
|
|
312
|
+
`).all();
|
|
313
|
+
} catch {}
|
|
314
|
+
|
|
315
|
+
// Edges causales activos
|
|
316
|
+
try {
|
|
317
|
+
graph.edges = db.prepare(`
|
|
318
|
+
SELECT desde_entidad, tipo, hacia_entidad, descripcion, confidence, valid_at
|
|
319
|
+
FROM relaciones_semanticas
|
|
320
|
+
WHERE tipo IN ('caused_failure','was_fixed_by','tested_by','regressed_by','depends_on_decision')
|
|
321
|
+
AND (invalid_at IS NULL OR invalid_at = '')
|
|
322
|
+
ORDER BY valid_at DESC LIMIT 300
|
|
323
|
+
`).all();
|
|
324
|
+
} catch {}
|
|
325
|
+
|
|
326
|
+
// ADRs
|
|
327
|
+
try {
|
|
328
|
+
graph.decisions = db.prepare(`
|
|
329
|
+
SELECT doc_id, titulo, decision, status, afecta, fecha_indexado
|
|
330
|
+
FROM knowledge_docs
|
|
331
|
+
WHERE status = 'accepted'
|
|
332
|
+
LIMIT 50
|
|
333
|
+
`).all();
|
|
334
|
+
} catch {}
|
|
335
|
+
|
|
336
|
+
// Stats
|
|
337
|
+
graph.stats = {
|
|
338
|
+
total_nodes: graph.nodes.length,
|
|
339
|
+
total_edges: graph.edges.length,
|
|
340
|
+
total_decisions: graph.decisions.length,
|
|
341
|
+
high_confidence: graph.nodes.filter(n => n.confianza === 'ALTA').length,
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
return graph;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// ─── GENERAR TODO ─────────────────────────────────────────────────────────────
|
|
348
|
+
|
|
349
|
+
function generateAll(projectRoot) {
|
|
350
|
+
projectRoot = projectRoot || process.cwd();
|
|
351
|
+
const db = openDB(projectRoot);
|
|
352
|
+
|
|
353
|
+
const results = { llms_txt: false, llms_full: false, knowledge_graph: false };
|
|
354
|
+
|
|
355
|
+
// 1. llms.txt
|
|
356
|
+
try {
|
|
357
|
+
const content = generateLlmsTxt(projectRoot, db);
|
|
358
|
+
fs.writeFileSync(path.join(projectRoot, '.agentic', 'llms.txt'), content);
|
|
359
|
+
results.llms_txt = true;
|
|
360
|
+
console.log('[LLMS] ✅ .agentic/llms.txt generado');
|
|
361
|
+
} catch (e) {
|
|
362
|
+
console.error('[LLMS] Error llms.txt:', e.message);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// 2. llms-full.txt
|
|
366
|
+
if (db) {
|
|
367
|
+
try {
|
|
368
|
+
const content = generateLlmsFullTxt(projectRoot, db);
|
|
369
|
+
if (content) {
|
|
370
|
+
fs.writeFileSync(path.join(projectRoot, '.agentic', 'llms-full.txt'), content);
|
|
371
|
+
results.llms_full = true;
|
|
372
|
+
console.log('[LLMS] ✅ .agentic/llms-full.txt generado');
|
|
373
|
+
}
|
|
374
|
+
} catch (e) {
|
|
375
|
+
console.error('[LLMS] Error llms-full.txt:', e.message);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// 3. knowledge-graph.json
|
|
380
|
+
if (db) {
|
|
381
|
+
try {
|
|
382
|
+
const graph = generateKnowledgeGraph(projectRoot, db);
|
|
383
|
+
if (graph) {
|
|
384
|
+
fs.writeFileSync(
|
|
385
|
+
path.join(projectRoot, '.agentic', 'knowledge-graph.json'),
|
|
386
|
+
JSON.stringify(graph, null, 2)
|
|
387
|
+
);
|
|
388
|
+
results.knowledge_graph = true;
|
|
389
|
+
console.log(`[LLMS] ✅ .agentic/knowledge-graph.json generado (${graph.stats.total_nodes} nodos, ${graph.stats.total_edges} edges)`);
|
|
390
|
+
}
|
|
391
|
+
} catch (e) {
|
|
392
|
+
console.error('[LLMS] Error knowledge-graph.json:', e.message);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return results;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ─── CLI ──────────────────────────────────────────────────────────────────────
|
|
400
|
+
|
|
401
|
+
if (require.main === module) {
|
|
402
|
+
const [,, cmd] = process.argv;
|
|
403
|
+
const projectRoot = process.cwd();
|
|
404
|
+
|
|
405
|
+
switch (cmd) {
|
|
406
|
+
case 'generate':
|
|
407
|
+
const db = openDB(projectRoot);
|
|
408
|
+
const content = generateLlmsTxt(projectRoot, db);
|
|
409
|
+
fs.writeFileSync(path.join(projectRoot, '.agentic', 'llms.txt'), content);
|
|
410
|
+
console.log('✅ .agentic/llms.txt generado');
|
|
411
|
+
break;
|
|
412
|
+
case 'graph':
|
|
413
|
+
const db2 = openDB(projectRoot);
|
|
414
|
+
if (!db2) { console.error('DB no disponible'); break; }
|
|
415
|
+
const graph = generateKnowledgeGraph(projectRoot, db2);
|
|
416
|
+
fs.writeFileSync(path.join(projectRoot, '.agentic', 'knowledge-graph.json'), JSON.stringify(graph, null, 2));
|
|
417
|
+
console.log(`✅ knowledge-graph.json: ${graph.stats.total_nodes} nodos, ${graph.stats.total_edges} edges`);
|
|
418
|
+
break;
|
|
419
|
+
case 'all':
|
|
420
|
+
default:
|
|
421
|
+
generateAll(projectRoot);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
module.exports = { generateLlmsTxt, generateLlmsFullTxt, generateKnowledgeGraph, generateAll };
|