@rasensio/aidlc 0.7.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +25 -1
  2. package/dist/cli.js +13 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/discover.d.ts +6 -2
  5. package/dist/commands/discover.d.ts.map +1 -1
  6. package/dist/commands/discover.js +30 -4
  7. package/dist/commands/discover.js.map +1 -1
  8. package/dist/commands/gate.d.ts.map +1 -1
  9. package/dist/commands/gate.js +8 -0
  10. package/dist/commands/gate.js.map +1 -1
  11. package/dist/commands/init.d.ts.map +1 -1
  12. package/dist/commands/init.js +3 -0
  13. package/dist/commands/init.js.map +1 -1
  14. package/dist/commands/knowledge.d.ts +16 -0
  15. package/dist/commands/knowledge.d.ts.map +1 -0
  16. package/dist/commands/knowledge.js +454 -0
  17. package/dist/commands/knowledge.js.map +1 -0
  18. package/dist/commands/start.d.ts +2 -1
  19. package/dist/commands/start.d.ts.map +1 -1
  20. package/dist/commands/start.js +31 -1
  21. package/dist/commands/start.js.map +1 -1
  22. package/dist/commands/transition.d.ts.map +1 -1
  23. package/dist/commands/transition.js +14 -1
  24. package/dist/commands/transition.js.map +1 -1
  25. package/dist/commands/update.d.ts.map +1 -1
  26. package/dist/commands/update.js +8 -1
  27. package/dist/commands/update.js.map +1 -1
  28. package/dist/compile/adapters/claude-code.d.ts.map +1 -1
  29. package/dist/compile/adapters/claude-code.js +5 -0
  30. package/dist/compile/adapters/claude-code.js.map +1 -1
  31. package/dist/compile/adapters/codex.d.ts.map +1 -1
  32. package/dist/compile/adapters/codex.js +5 -0
  33. package/dist/compile/adapters/codex.js.map +1 -1
  34. package/dist/compile/adapters/cursor.d.ts.map +1 -1
  35. package/dist/compile/adapters/cursor.js +5 -0
  36. package/dist/compile/adapters/cursor.js.map +1 -1
  37. package/dist/compile/adapters/kiro.d.ts.map +1 -1
  38. package/dist/compile/adapters/kiro.js +5 -0
  39. package/dist/compile/adapters/kiro.js.map +1 -1
  40. package/dist/compile/adapters/windsurf.d.ts.map +1 -1
  41. package/dist/compile/adapters/windsurf.js +5 -0
  42. package/dist/compile/adapters/windsurf.js.map +1 -1
  43. package/dist/compile/knowledge-section.d.ts +19 -0
  44. package/dist/compile/knowledge-section.d.ts.map +1 -0
  45. package/dist/compile/knowledge-section.js +46 -0
  46. package/dist/compile/knowledge-section.js.map +1 -0
  47. package/dist/core/types.d.ts +3 -1
  48. package/dist/core/types.d.ts.map +1 -1
  49. package/dist/discover/scanner.d.ts.map +1 -1
  50. package/dist/discover/scanner.js +18 -12
  51. package/dist/discover/scanner.js.map +1 -1
  52. package/dist/discover/workspaces.d.ts +24 -0
  53. package/dist/discover/workspaces.d.ts.map +1 -0
  54. package/dist/discover/workspaces.js +116 -0
  55. package/dist/discover/workspaces.js.map +1 -0
  56. package/dist/knowledge/compact.d.ts +24 -0
  57. package/dist/knowledge/compact.d.ts.map +1 -0
  58. package/dist/knowledge/compact.js +70 -0
  59. package/dist/knowledge/compact.js.map +1 -0
  60. package/dist/knowledge/context-generator.d.ts +36 -0
  61. package/dist/knowledge/context-generator.d.ts.map +1 -0
  62. package/dist/knowledge/context-generator.js +150 -0
  63. package/dist/knowledge/context-generator.js.map +1 -0
  64. package/dist/knowledge/engine.d.ts +40 -0
  65. package/dist/knowledge/engine.d.ts.map +1 -0
  66. package/dist/knowledge/engine.js +79 -0
  67. package/dist/knowledge/engine.js.map +1 -0
  68. package/dist/knowledge/gate-criterion.d.ts +36 -0
  69. package/dist/knowledge/gate-criterion.d.ts.map +1 -0
  70. package/dist/knowledge/gate-criterion.js +60 -0
  71. package/dist/knowledge/gate-criterion.js.map +1 -0
  72. package/dist/knowledge/index/knowledge-index.d.ts +45 -0
  73. package/dist/knowledge/index/knowledge-index.d.ts.map +1 -0
  74. package/dist/knowledge/index/knowledge-index.js +20 -0
  75. package/dist/knowledge/index/knowledge-index.js.map +1 -0
  76. package/dist/knowledge/index/sqlite-index.d.ts +53 -0
  77. package/dist/knowledge/index/sqlite-index.d.ts.map +1 -0
  78. package/dist/knowledge/index/sqlite-index.js +354 -0
  79. package/dist/knowledge/index/sqlite-index.js.map +1 -0
  80. package/dist/knowledge/merge-driver.d.ts +36 -0
  81. package/dist/knowledge/merge-driver.d.ts.map +1 -0
  82. package/dist/knowledge/merge-driver.js +130 -0
  83. package/dist/knowledge/merge-driver.js.map +1 -0
  84. package/dist/knowledge/reader.d.ts +32 -0
  85. package/dist/knowledge/reader.d.ts.map +1 -0
  86. package/dist/knowledge/reader.js +74 -0
  87. package/dist/knowledge/reader.js.map +1 -0
  88. package/dist/knowledge/seed.d.ts +38 -0
  89. package/dist/knowledge/seed.d.ts.map +1 -0
  90. package/dist/knowledge/seed.js +254 -0
  91. package/dist/knowledge/seed.js.map +1 -0
  92. package/dist/knowledge/staleness.d.ts +41 -0
  93. package/dist/knowledge/staleness.d.ts.map +1 -0
  94. package/dist/knowledge/staleness.js +102 -0
  95. package/dist/knowledge/staleness.js.map +1 -0
  96. package/dist/knowledge/sync.d.ts +31 -0
  97. package/dist/knowledge/sync.d.ts.map +1 -0
  98. package/dist/knowledge/sync.js +103 -0
  99. package/dist/knowledge/sync.js.map +1 -0
  100. package/dist/knowledge/types.d.ts +87 -0
  101. package/dist/knowledge/types.d.ts.map +1 -0
  102. package/dist/knowledge/types.js +82 -0
  103. package/dist/knowledge/types.js.map +1 -0
  104. package/dist/knowledge/writer.d.ts +67 -0
  105. package/dist/knowledge/writer.d.ts.map +1 -0
  106. package/dist/knowledge/writer.js +189 -0
  107. package/dist/knowledge/writer.js.map +1 -0
  108. package/dist/knowledge/yaml-source.d.ts +48 -0
  109. package/dist/knowledge/yaml-source.d.ts.map +1 -0
  110. package/dist/knowledge/yaml-source.js +195 -0
  111. package/dist/knowledge/yaml-source.js.map +1 -0
  112. package/package.json +3 -3
@@ -0,0 +1,354 @@
1
+ /**
2
+ * SQLite implementation of KnowledgeIndex using the Node standard library
3
+ * (`node:sqlite`, Node >= 22) — zero npm dependencies (design DD1).
4
+ *
5
+ * FTS5 powers full-text search; if the runtime's SQLite build lacks FTS5 the
6
+ * index falls back to LIKE matching with a one-time stderr warning. The
7
+ * database is a disposable cache at `.aidlc/knowledge/index.db`, gitignored
8
+ * and rebuildable from YAML at any time (KG Req 3.1–3.3).
9
+ *
10
+ * Requirements: KG 3.1–3.8, 10.1–10.3, 11.4
11
+ *
12
+ * @module
13
+ */
14
+ import { DatabaseSync } from 'node:sqlite';
15
+ import { join } from 'node:path';
16
+ import { mkdirSync } from 'node:fs';
17
+ import { KNOWLEDGE_SCHEMA_VERSION } from '../types.js';
18
+ import { IndexOutdatedError } from './knowledge-index.js';
19
+ /** Filename of the index database inside the knowledge directory. */
20
+ export const INDEX_DB_FILE = 'index.db';
21
+ export class SqliteIndex {
22
+ db;
23
+ ftsAvailable = true;
24
+ ftsWarned = false;
25
+ /**
26
+ * @param knowledgeDir - Directory holding YAML sources; index.db is created here.
27
+ * @param dbPathOverride - Test hook: use ':memory:' for an ephemeral index.
28
+ */
29
+ constructor(knowledgeDir, dbPathOverride) {
30
+ const dbPath = dbPathOverride ?? join(knowledgeDir, INDEX_DB_FILE);
31
+ if (!dbPathOverride)
32
+ mkdirSync(knowledgeDir, { recursive: true });
33
+ this.db = new DatabaseSync(dbPath);
34
+ this.db.exec('PRAGMA journal_mode = WAL');
35
+ this.ensureSchema();
36
+ }
37
+ // -------------------------------------------------------------------------
38
+ // Schema
39
+ // -------------------------------------------------------------------------
40
+ ensureSchema() {
41
+ const version = this.readSchemaVersion();
42
+ if (version === 0) {
43
+ this.createSchema();
44
+ }
45
+ else if (version < KNOWLEDGE_SCHEMA_VERSION) {
46
+ // Refuse to serve; migration is rebuild-from-YAML (KG Req 11.4)
47
+ throw new IndexOutdatedError(version, KNOWLEDGE_SCHEMA_VERSION);
48
+ }
49
+ }
50
+ readSchemaVersion() {
51
+ try {
52
+ const row = this.db
53
+ .prepare('SELECT version FROM _schema_version ORDER BY rowid DESC LIMIT 1')
54
+ .get();
55
+ return row?.version ?? 0;
56
+ }
57
+ catch {
58
+ return 0;
59
+ }
60
+ }
61
+ createSchema() {
62
+ this.db.exec(`
63
+ CREATE TABLE IF NOT EXISTS _schema_version (
64
+ version INTEGER NOT NULL,
65
+ created_at TEXT NOT NULL
66
+ );
67
+
68
+ CREATE TABLE IF NOT EXISTS entities (
69
+ id TEXT PRIMARY KEY,
70
+ type TEXT NOT NULL,
71
+ name TEXT NOT NULL,
72
+ description TEXT NOT NULL,
73
+ confidence REAL NOT NULL DEFAULT 0.5,
74
+ source TEXT NOT NULL DEFAULT 'agent-inferred',
75
+ author TEXT NOT NULL DEFAULT 'unknown',
76
+ tags TEXT NOT NULL DEFAULT '[]',
77
+ last_verified TEXT NOT NULL,
78
+ metadata TEXT DEFAULT '{}',
79
+ source_file TEXT NOT NULL DEFAULT ''
80
+ );
81
+
82
+ CREATE TABLE IF NOT EXISTS relationships (
83
+ from_entity TEXT NOT NULL,
84
+ to_entity TEXT NOT NULL,
85
+ type TEXT NOT NULL,
86
+ metadata TEXT DEFAULT '{}',
87
+ last_verified TEXT NOT NULL,
88
+ UNIQUE(from_entity, to_entity, type)
89
+ );
90
+
91
+ CREATE TABLE IF NOT EXISTS file_mappings (
92
+ file_path TEXT NOT NULL,
93
+ entity_id TEXT NOT NULL,
94
+ PRIMARY KEY (file_path, entity_id)
95
+ );
96
+
97
+ CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
98
+ CREATE INDEX IF NOT EXISTS idx_entities_confidence ON entities(confidence);
99
+ CREATE INDEX IF NOT EXISTS idx_relationships_from ON relationships(from_entity);
100
+ CREATE INDEX IF NOT EXISTS idx_relationships_to ON relationships(to_entity);
101
+ CREATE INDEX IF NOT EXISTS idx_relationships_type ON relationships(type);
102
+ `);
103
+ try {
104
+ // search_text carries a tokenizer-friendly normalization of name+tags
105
+ // (camelCase/kebab-case split) so code identifiers match (design risk 3).
106
+ this.db.exec(`
107
+ CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
108
+ id UNINDEXED, name, description, tags, search_text
109
+ );
110
+ `);
111
+ }
112
+ catch {
113
+ this.ftsAvailable = false;
114
+ }
115
+ this.db
116
+ .prepare('INSERT INTO _schema_version (version, created_at) VALUES (?, ?)')
117
+ .run(KNOWLEDGE_SCHEMA_VERSION, new Date().toISOString());
118
+ }
119
+ // -------------------------------------------------------------------------
120
+ // Entities
121
+ // -------------------------------------------------------------------------
122
+ getEntity(id) {
123
+ const row = this.db.prepare('SELECT * FROM entities WHERE id = ?').get(id);
124
+ return row ? rowToEntity(row) : undefined;
125
+ }
126
+ upsertEntity(entity) {
127
+ this.db
128
+ .prepare(`INSERT OR REPLACE INTO entities
129
+ (id, type, name, description, confidence, source, author, tags, last_verified, metadata, source_file)
130
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
131
+ .run(entity.id, entity.type, entity.name, entity.description, entity.confidence, entity.source, entity.author, JSON.stringify(entity.tags), entity.lastVerified, JSON.stringify(entity.metadata ?? {}), entity.source);
132
+ this.syncFts(entity);
133
+ this.syncFileMapping(entity);
134
+ }
135
+ deleteEntity(id) {
136
+ if (this.ftsAvailable) {
137
+ this.db.prepare('DELETE FROM entities_fts WHERE id = ?').run(id);
138
+ }
139
+ this.db.prepare('DELETE FROM file_mappings WHERE entity_id = ?').run(id);
140
+ this.db.prepare('DELETE FROM entities WHERE id = ?').run(id);
141
+ }
142
+ fullTextSearch(term, options = {}) {
143
+ const limit = options.limit ?? 20;
144
+ const minConfidence = options.minConfidence ?? 0;
145
+ if (this.ftsAvailable) {
146
+ try {
147
+ return this.ftsSearch(term, options.type, minConfidence, limit);
148
+ }
149
+ catch {
150
+ // FTS5 query syntax error on user input — fall back to LIKE.
151
+ }
152
+ }
153
+ this.warnNoFts();
154
+ return this.likeSearch(term, options.type, minConfidence, limit);
155
+ }
156
+ ftsSearch(term, type, minConfidence, limit) {
157
+ // Tokenize the query the same way FTS5's default tokenizer splits text —
158
+ // on non-alphanumeric boundaries — so punctuation in the term can't glue
159
+ // tokens together and miss the indexed words.
160
+ const tokens = term.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
161
+ if (tokens.length === 0) {
162
+ return this.likeSearch(term, type, minConfidence, limit);
163
+ }
164
+ const ftsQuery = tokens.map((t) => `"${t}"`).join(' OR ');
165
+ let sql = `
166
+ SELECT e.* FROM entities e
167
+ JOIN entities_fts f ON e.id = f.id
168
+ WHERE entities_fts MATCH ?
169
+ AND e.confidence >= ?`;
170
+ const params = [ftsQuery, minConfidence];
171
+ if (type) {
172
+ sql += ' AND e.type = ?';
173
+ params.push(type);
174
+ }
175
+ sql += ' ORDER BY f.rank, e.confidence DESC LIMIT ?';
176
+ params.push(limit);
177
+ const rows = this.db.prepare(sql).all(...params);
178
+ return rows.map(rowToEntity);
179
+ }
180
+ likeSearch(term, type, minConfidence, limit) {
181
+ const like = `%${term.toLowerCase()}%`;
182
+ let sql = `
183
+ SELECT * FROM entities
184
+ WHERE (lower(name) LIKE ? OR lower(description) LIKE ? OR lower(tags) LIKE ?)
185
+ AND confidence >= ?`;
186
+ const params = [like, like, like, minConfidence];
187
+ if (type) {
188
+ sql += ' AND type = ?';
189
+ params.push(type);
190
+ }
191
+ sql += ' ORDER BY confidence DESC LIMIT ?';
192
+ params.push(limit);
193
+ const rows = this.db.prepare(sql).all(...params);
194
+ return rows.map(rowToEntity);
195
+ }
196
+ getAllEntities(filter = {}) {
197
+ let sql = 'SELECT * FROM entities';
198
+ const params = [];
199
+ if (filter.minConfidence !== undefined) {
200
+ sql += ' WHERE confidence >= ?';
201
+ params.push(filter.minConfidence);
202
+ }
203
+ sql += ' ORDER BY confidence DESC, last_verified DESC';
204
+ const rows = this.db.prepare(sql).all(...params);
205
+ return rows.map(rowToEntity);
206
+ }
207
+ getEntitiesByTypes(types, filter = {}) {
208
+ if (types.length === 0)
209
+ return [];
210
+ const placeholders = types.map(() => '?').join(',');
211
+ let sql = `SELECT * FROM entities WHERE type IN (${placeholders})`;
212
+ const params = [...types];
213
+ if (filter.minConfidence !== undefined) {
214
+ sql += ' AND confidence >= ?';
215
+ params.push(filter.minConfidence);
216
+ }
217
+ sql += ' ORDER BY confidence DESC';
218
+ const rows = this.db.prepare(sql).all(...params);
219
+ return rows.map(rowToEntity);
220
+ }
221
+ getEntitiesByFilePath(path) {
222
+ const rows = this.db
223
+ .prepare(`SELECT e.* FROM entities e
224
+ JOIN file_mappings m ON e.id = m.entity_id
225
+ WHERE m.file_path = ?`)
226
+ .all(path);
227
+ return rows.map(rowToEntity);
228
+ }
229
+ countEntitiesByType(type) {
230
+ const row = this.db
231
+ .prepare('SELECT COUNT(*) AS n FROM entities WHERE type = ?')
232
+ .get(type);
233
+ return row.n;
234
+ }
235
+ // -------------------------------------------------------------------------
236
+ // Relationships
237
+ // -------------------------------------------------------------------------
238
+ upsertRelationship(rel) {
239
+ this.db
240
+ .prepare(`INSERT OR REPLACE INTO relationships
241
+ (from_entity, to_entity, type, metadata, last_verified)
242
+ VALUES (?, ?, ?, ?, ?)`)
243
+ .run(rel.from, rel.to, rel.type, JSON.stringify(rel.metadata ?? {}), rel.lastVerified);
244
+ }
245
+ relationshipsFrom(id) {
246
+ const rows = this.db
247
+ .prepare('SELECT * FROM relationships WHERE from_entity = ?')
248
+ .all(id);
249
+ return rows.map(rowToRelationship);
250
+ }
251
+ relationshipsTo(id) {
252
+ const rows = this.db
253
+ .prepare('SELECT * FROM relationships WHERE to_entity = ?')
254
+ .all(id);
255
+ return rows.map(rowToRelationship);
256
+ }
257
+ relationshipsFor(ids) {
258
+ if (ids.length === 0)
259
+ return [];
260
+ const placeholders = ids.map(() => '?').join(',');
261
+ const rows = this.db
262
+ .prepare(`SELECT * FROM relationships
263
+ WHERE from_entity IN (${placeholders}) OR to_entity IN (${placeholders})`)
264
+ .all(...ids, ...ids);
265
+ return rows.map(rowToRelationship);
266
+ }
267
+ countRelationshipsByType(type) {
268
+ const row = this.db
269
+ .prepare('SELECT COUNT(*) AS n FROM relationships WHERE type = ?')
270
+ .get(type);
271
+ return row.n;
272
+ }
273
+ // -------------------------------------------------------------------------
274
+ // Rebuild
275
+ // -------------------------------------------------------------------------
276
+ rebuild(entities, relationships) {
277
+ this.db.exec('BEGIN');
278
+ try {
279
+ this.db.exec('DELETE FROM relationships');
280
+ this.db.exec('DELETE FROM file_mappings');
281
+ this.db.exec('DELETE FROM entities');
282
+ if (this.ftsAvailable)
283
+ this.db.exec('DELETE FROM entities_fts');
284
+ for (const entity of entities)
285
+ this.upsertEntity(entity);
286
+ for (const rel of relationships)
287
+ this.upsertRelationship(rel);
288
+ this.db.exec('COMMIT');
289
+ }
290
+ catch (err) {
291
+ this.db.exec('ROLLBACK');
292
+ throw err;
293
+ }
294
+ }
295
+ close() {
296
+ this.db.close();
297
+ }
298
+ // -------------------------------------------------------------------------
299
+ // Internals
300
+ // -------------------------------------------------------------------------
301
+ syncFts(entity) {
302
+ if (!this.ftsAvailable)
303
+ return;
304
+ this.db.prepare('DELETE FROM entities_fts WHERE id = ?').run(entity.id);
305
+ this.db
306
+ .prepare('INSERT INTO entities_fts (id, name, description, tags, search_text) VALUES (?, ?, ?, ?, ?)')
307
+ .run(entity.id, entity.name, entity.description, entity.tags.join(' '), normalizeSearchText(`${entity.id} ${entity.name} ${entity.tags.join(' ')}`));
308
+ }
309
+ syncFileMapping(entity) {
310
+ this.db.prepare('DELETE FROM file_mappings WHERE entity_id = ?').run(entity.id);
311
+ if (entity.source && entity.source !== 'agent-inferred') {
312
+ this.db
313
+ .prepare('INSERT OR REPLACE INTO file_mappings (file_path, entity_id) VALUES (?, ?)')
314
+ .run(entity.source, entity.id);
315
+ }
316
+ }
317
+ warnNoFts() {
318
+ if (this.ftsAvailable || this.ftsWarned)
319
+ return;
320
+ this.ftsWarned = true;
321
+ process.stderr.write('Warning: SQLite FTS5 unavailable in this Node build; using slower LIKE search.\n');
322
+ }
323
+ }
324
+ /** Split camelCase and kebab/snake-case identifiers into searchable words. */
325
+ export function normalizeSearchText(text) {
326
+ return text
327
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
328
+ .replace(/[-_./]/g, ' ')
329
+ .toLowerCase();
330
+ }
331
+ function rowToEntity(row) {
332
+ return {
333
+ id: row.id,
334
+ type: row.type,
335
+ name: row.name,
336
+ description: row.description,
337
+ confidence: row.confidence,
338
+ source: row.source,
339
+ author: row.author,
340
+ tags: JSON.parse(row.tags),
341
+ lastVerified: row.last_verified,
342
+ metadata: JSON.parse(row.metadata || '{}'),
343
+ };
344
+ }
345
+ function rowToRelationship(row) {
346
+ return {
347
+ from: row.from_entity,
348
+ to: row.to_entity,
349
+ type: row.type,
350
+ metadata: JSON.parse(row.metadata || '{}'),
351
+ lastVerified: row.last_verified,
352
+ };
353
+ }
354
+ //# sourceMappingURL=sqlite-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-index.js","sourceRoot":"","sources":["../../../src/knowledge/index/sqlite-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Custom git merge driver for `.aidlc/knowledge/*.yaml` — a pure 3-way merge
3
+ * over entity/relationship documents (design DD5).
4
+ *
5
+ * Resolution for same-id conflicts (KG Req 12.3): higher confidence wins,
6
+ * newer lastVerified supplies description and author, tags union-merge,
7
+ * metadata merges with the newer side taking precedence. No entity present
8
+ * in ours or theirs is ever lost (correctness property 10); deletions are
9
+ * handled by `compact`, not by merges.
10
+ *
11
+ * Requirements: KG 12.2, 12.3
12
+ *
13
+ * @module
14
+ */
15
+ import type { Entity } from './types.js';
16
+ export interface MergeConflict {
17
+ id: string;
18
+ ours: Entity;
19
+ theirs: Entity;
20
+ resolution: Entity;
21
+ }
22
+ export interface MergeResult {
23
+ /** Serialized merged YAML file content. */
24
+ content: string;
25
+ /** Same-id conflicts that were auto-resolved. */
26
+ conflicts: MergeConflict[];
27
+ warnings: string[];
28
+ }
29
+ /** Resolve a same-id conflict per KG Req 12.3. */
30
+ export declare function resolveEntityConflict(ours: Entity, theirs: Entity): Entity;
31
+ /**
32
+ * 3-way merge of one knowledge YAML file. Pure function of the three
33
+ * contents; git integration is handled by the CLI command wrapper.
34
+ */
35
+ export declare function mergeKnowledgeFiles(base: string, ours: string, theirs: string): MergeResult;
36
+ //# sourceMappingURL=merge-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-driver.d.ts","sourceRoot":"","sources":["../../src/knowledge/merge-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAgC,MAAM,YAAY,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAkDD,kDAAkD;AAClD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAgB1E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAiD3F"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Custom git merge driver for `.aidlc/knowledge/*.yaml` — a pure 3-way merge
3
+ * over entity/relationship documents (design DD5).
4
+ *
5
+ * Resolution for same-id conflicts (KG Req 12.3): higher confidence wins,
6
+ * newer lastVerified supplies description and author, tags union-merge,
7
+ * metadata merges with the newer side taking precedence. No entity present
8
+ * in ours or theirs is ever lost (correctness property 10); deletions are
9
+ * handled by `compact`, not by merges.
10
+ *
11
+ * Requirements: KG 12.2, 12.3
12
+ *
13
+ * @module
14
+ */
15
+ import { parseAllDocuments, stringify } from 'yaml';
16
+ /** Key uniquely identifying a relationship document. */
17
+ function relationshipKey(rel) {
18
+ return `${rel.from}|${rel.type}|${rel.to}`;
19
+ }
20
+ function parseFile(content, label) {
21
+ const result = {
22
+ meta: null,
23
+ entities: new Map(),
24
+ relationships: new Map(),
25
+ warnings: [],
26
+ };
27
+ let docs;
28
+ try {
29
+ docs = parseAllDocuments(content);
30
+ }
31
+ catch (err) {
32
+ result.warnings.push(`${label}: unparseable YAML (${err.message})`);
33
+ return result;
34
+ }
35
+ for (const doc of docs) {
36
+ if (doc.errors.length > 0) {
37
+ result.warnings.push(`${label}: skipped corrupt document`);
38
+ continue;
39
+ }
40
+ const obj = doc.toJSON();
41
+ if (!obj || typeof obj !== 'object')
42
+ continue;
43
+ if ('_meta' in obj) {
44
+ result.meta = obj._meta;
45
+ }
46
+ else if (typeof obj.from === 'string' && typeof obj.to === 'string') {
47
+ const rel = obj;
48
+ result.relationships.set(relationshipKey(rel), rel);
49
+ }
50
+ else if (typeof obj.id === 'string') {
51
+ result.entities.set(obj.id, obj);
52
+ }
53
+ }
54
+ return result;
55
+ }
56
+ /** Resolve a same-id conflict per KG Req 12.3. */
57
+ export function resolveEntityConflict(ours, theirs) {
58
+ const ourTime = ours.lastVerified ?? '';
59
+ const theirTime = theirs.lastVerified ?? '';
60
+ const newer = ourTime >= theirTime ? ours : theirs;
61
+ const older = ourTime >= theirTime ? theirs : ours;
62
+ return {
63
+ ...older,
64
+ ...newer,
65
+ confidence: Math.max(ours.confidence ?? 0, theirs.confidence ?? 0),
66
+ lastVerified: newer.lastVerified,
67
+ description: newer.description || older.description,
68
+ author: newer.author ?? older.author,
69
+ tags: [...new Set([...(ours.tags ?? []), ...(theirs.tags ?? [])])],
70
+ metadata: { ...older.metadata, ...newer.metadata },
71
+ };
72
+ }
73
+ /**
74
+ * 3-way merge of one knowledge YAML file. Pure function of the three
75
+ * contents; git integration is handled by the CLI command wrapper.
76
+ */
77
+ export function mergeKnowledgeFiles(base, ours, theirs) {
78
+ const baseFile = parseFile(base, 'base');
79
+ const ourFile = parseFile(ours, 'ours');
80
+ const theirFile = parseFile(theirs, 'theirs');
81
+ const warnings = [...baseFile.warnings, ...ourFile.warnings, ...theirFile.warnings];
82
+ const conflicts = [];
83
+ // Entities: union of ours ∪ theirs (property 10: nothing is lost).
84
+ const merged = [];
85
+ const allIds = new Set([...ourFile.entities.keys(), ...theirFile.entities.keys()]);
86
+ for (const id of allIds) {
87
+ const ourEntity = ourFile.entities.get(id);
88
+ const theirEntity = theirFile.entities.get(id);
89
+ if (ourEntity && !theirEntity) {
90
+ merged.push(ourEntity);
91
+ }
92
+ else if (!ourEntity && theirEntity) {
93
+ merged.push(theirEntity);
94
+ }
95
+ else if (ourEntity && theirEntity) {
96
+ if (deepEqual(ourEntity, theirEntity)) {
97
+ merged.push(ourEntity);
98
+ }
99
+ else {
100
+ const resolution = resolveEntityConflict(ourEntity, theirEntity);
101
+ conflicts.push({ id, ours: ourEntity, theirs: theirEntity, resolution });
102
+ merged.push(resolution);
103
+ }
104
+ }
105
+ }
106
+ // Relationships: union by (from, type, to); newer lastVerified wins on clash.
107
+ const relationships = new Map();
108
+ for (const [key, rel] of theirFile.relationships)
109
+ relationships.set(key, rel);
110
+ for (const [key, rel] of ourFile.relationships) {
111
+ const existing = relationships.get(key);
112
+ if (!existing || (rel.lastVerified ?? '') >= (existing.lastVerified ?? '')) {
113
+ relationships.set(key, rel);
114
+ }
115
+ }
116
+ // Serialize: meta header (ours wins, else theirs/base), entities, relationships.
117
+ const meta = ourFile.meta ?? theirFile.meta ?? baseFile.meta;
118
+ const parts = [];
119
+ if (meta)
120
+ parts.push(stringify({ _meta: meta }));
121
+ for (const entity of merged)
122
+ parts.push(stringify(entity, { lineWidth: 100 }));
123
+ for (const rel of relationships.values())
124
+ parts.push(stringify(rel, { lineWidth: 100 }));
125
+ return { content: parts.join('---\n'), conflicts, warnings };
126
+ }
127
+ function deepEqual(a, b) {
128
+ return JSON.stringify(a) === JSON.stringify(b);
129
+ }
130
+ //# sourceMappingURL=merge-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-driver.js","sourceRoot":"","sources":["../../src/knowledge/merge-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * KnowledgeReader — query interface over the index (KG Req 5.1–5.7).
3
+ *
4
+ * Reads never touch the YAML sources; everything is served from the
5
+ * KnowledgeIndex. Subgraph traversal is breadth-first in application code —
6
+ * adequate for the target scale of ≤1000 entities (design DD1).
7
+ *
8
+ * @module
9
+ */
10
+ import type { Entity, Relationship, GraphQueryResult } from './types.js';
11
+ import type { KnowledgeIndex } from './index/knowledge-index.js';
12
+ export interface QueryOptions {
13
+ type?: string;
14
+ minConfidence?: number;
15
+ limit?: number;
16
+ }
17
+ export interface EntityDetail {
18
+ entity: Entity;
19
+ inbound: Relationship[];
20
+ outbound: Relationship[];
21
+ }
22
+ export declare class KnowledgeReader {
23
+ private readonly index;
24
+ constructor(index: KnowledgeIndex);
25
+ /** Full-text search with relationships for the matched set (KG Req 5.1). */
26
+ search(term: string, options?: QueryOptions): GraphQueryResult;
27
+ /** Single entity with inbound and outbound relationships (KG Req 5.2). */
28
+ get(entityId: string): EntityDetail | undefined;
29
+ /** Subgraph of all entities within `depth` hops (KG Req 5.3). */
30
+ subgraph(entityId: string, depth: number): GraphQueryResult;
31
+ }
32
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/knowledge/reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,cAAc;IAElD,4EAA4E;IAC5E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,gBAAgB;IAWlE,0EAA0E;IAC1E,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAU/C,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB;CAqC5D"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * KnowledgeReader — query interface over the index (KG Req 5.1–5.7).
3
+ *
4
+ * Reads never touch the YAML sources; everything is served from the
5
+ * KnowledgeIndex. Subgraph traversal is breadth-first in application code —
6
+ * adequate for the target scale of ≤1000 entities (design DD1).
7
+ *
8
+ * @module
9
+ */
10
+ export class KnowledgeReader {
11
+ index;
12
+ constructor(index) {
13
+ this.index = index;
14
+ }
15
+ /** Full-text search with relationships for the matched set (KG Req 5.1). */
16
+ search(term, options = {}) {
17
+ const searchOptions = {};
18
+ if (options.type !== undefined)
19
+ searchOptions.type = options.type;
20
+ if (options.minConfidence !== undefined)
21
+ searchOptions.minConfidence = options.minConfidence;
22
+ if (options.limit !== undefined)
23
+ searchOptions.limit = options.limit;
24
+ const entities = this.index.fullTextSearch(term, searchOptions);
25
+ const relationships = this.index.relationshipsFor(entities.map((e) => e.id));
26
+ return { entities, relationships, totalCount: entities.length };
27
+ }
28
+ /** Single entity with inbound and outbound relationships (KG Req 5.2). */
29
+ get(entityId) {
30
+ const entity = this.index.getEntity(entityId);
31
+ if (!entity)
32
+ return undefined;
33
+ return {
34
+ entity,
35
+ inbound: this.index.relationshipsTo(entityId),
36
+ outbound: this.index.relationshipsFrom(entityId),
37
+ };
38
+ }
39
+ /** Subgraph of all entities within `depth` hops (KG Req 5.3). */
40
+ subgraph(entityId, depth) {
41
+ const visited = new Set();
42
+ const entities = [];
43
+ const relationshipKeys = new Set();
44
+ const relationships = [];
45
+ const queue = [{ id: entityId, depth: 0 }];
46
+ while (queue.length > 0) {
47
+ const item = queue.shift();
48
+ if (visited.has(item.id) || item.depth > depth)
49
+ continue;
50
+ const entity = this.index.getEntity(item.id);
51
+ if (!entity)
52
+ continue;
53
+ visited.add(item.id);
54
+ entities.push(entity);
55
+ for (const rel of [...this.index.relationshipsFrom(item.id), ...this.index.relationshipsTo(item.id)]) {
56
+ const key = `${rel.from}|${rel.type}|${rel.to}`;
57
+ if (!relationshipKeys.has(key)) {
58
+ relationshipKeys.add(key);
59
+ relationships.push(rel);
60
+ }
61
+ const neighbor = rel.from === item.id ? rel.to : rel.from;
62
+ if (!visited.has(neighbor)) {
63
+ queue.push({ id: neighbor, depth: item.depth + 1 });
64
+ }
65
+ }
66
+ }
67
+ // Keep only relationships whose endpoints are both in the subgraph, so the
68
+ // result is self-contained at every depth (subgraph monotonicity property).
69
+ const inGraph = new Set(entities.map((e) => e.id));
70
+ const contained = relationships.filter((r) => inGraph.has(r.from) && inGraph.has(r.to));
71
+ return { entities, relationships: contained, totalCount: entities.length };
72
+ }
73
+ }
74
+ //# sourceMappingURL=reader.js.map