@triedotdev/mcp 1.0.167 → 1.0.169

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 (54) hide show
  1. package/README.md +64 -27
  2. package/dist/{chunk-YDHUCDHM.js → chunk-3XR6WVAW.js} +8 -8
  3. package/dist/{chunk-4MXH2ZPT.js → chunk-7IO4YUI3.js} +8 -8
  4. package/dist/{chunk-7WITSO22.js → chunk-AHD2CBQ7.js} +77 -55
  5. package/dist/chunk-AHD2CBQ7.js.map +1 -0
  6. package/dist/{chunk-575YT2SD.js → chunk-BUTOP5EB.js} +195 -1
  7. package/dist/chunk-BUTOP5EB.js.map +1 -0
  8. package/dist/{chunk-MRHKX5M5.js → chunk-FBNURWRY.js} +3 -3
  9. package/dist/{chunk-YZ6Y2H3P.js → chunk-FVRO5RN3.js} +66 -49
  10. package/dist/chunk-FVRO5RN3.js.map +1 -0
  11. package/dist/{chunk-5BRRRTN6.js → chunk-G3I7SZLW.js} +4 -4
  12. package/dist/{chunk-XTFWT2XM.js → chunk-I2O5OYQT.js} +2 -2
  13. package/dist/{chunk-XE6KQRKZ.js → chunk-KCUOWRPX.js} +2 -2
  14. package/dist/{chunk-LQIMKE3P.js → chunk-SASNMSB5.js} +106 -33
  15. package/dist/{chunk-LQIMKE3P.js.map → chunk-SASNMSB5.js.map} +1 -1
  16. package/dist/cli/main.js +7 -9
  17. package/dist/cli/main.js.map +1 -1
  18. package/dist/cli/yolo-daemon.js +10 -12
  19. package/dist/cli/yolo-daemon.js.map +1 -1
  20. package/dist/{fast-analyzer-XXYMOXRK.js → fast-analyzer-3GCCZMLK.js} +3 -3
  21. package/dist/{goal-manager-YOB7VWK7.js → goal-manager-QUKX2W6C.js} +3 -3
  22. package/dist/{goal-validator-ULKIBDPX.js → goal-validator-2SFSKKVU.js} +3 -3
  23. package/dist/{hypothesis-7BFFT5JY.js → hypothesis-KCPBR652.js} +3 -3
  24. package/dist/index.js +11 -13
  25. package/dist/index.js.map +1 -1
  26. package/dist/{issue-store-ZIRP23EP.js → issue-store-YAXTNRRY.js} +2 -2
  27. package/dist/server/mcp-server.js +11 -13
  28. package/dist/{tiered-storage-Z3YCR465.js → tiered-storage-DYNC5CQ6.js} +3 -2
  29. package/dist/{trie-agent-3YDPEGHJ.js → trie-agent-I3HAHY2G.js} +7 -9
  30. package/dist/{chunk-OMR4YCBS.js → vibe-code-signatures-5ZULYP3D.js} +4 -4
  31. package/dist/{chunk-OMR4YCBS.js.map → vibe-code-signatures-5ZULYP3D.js.map} +1 -1
  32. package/dist/{chunk-SY6KQG44.js → vulnerability-signatures-2URZSXAQ.js} +5 -5
  33. package/dist/{chunk-SY6KQG44.js.map → vulnerability-signatures-2URZSXAQ.js.map} +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-575YT2SD.js.map +0 -1
  36. package/dist/chunk-7WITSO22.js.map +0 -1
  37. package/dist/chunk-YZ6Y2H3P.js.map +0 -1
  38. package/dist/vibe-code-signatures-F6URTBW3.js +0 -16
  39. package/dist/vibe-code-signatures-F6URTBW3.js.map +0 -1
  40. package/dist/vulnerability-signatures-T7SKHORW.js +0 -18
  41. package/dist/vulnerability-signatures-T7SKHORW.js.map +0 -1
  42. /package/dist/{chunk-YDHUCDHM.js.map → chunk-3XR6WVAW.js.map} +0 -0
  43. /package/dist/{chunk-4MXH2ZPT.js.map → chunk-7IO4YUI3.js.map} +0 -0
  44. /package/dist/{chunk-MRHKX5M5.js.map → chunk-FBNURWRY.js.map} +0 -0
  45. /package/dist/{chunk-5BRRRTN6.js.map → chunk-G3I7SZLW.js.map} +0 -0
  46. /package/dist/{chunk-XTFWT2XM.js.map → chunk-I2O5OYQT.js.map} +0 -0
  47. /package/dist/{chunk-XE6KQRKZ.js.map → chunk-KCUOWRPX.js.map} +0 -0
  48. /package/dist/{fast-analyzer-XXYMOXRK.js.map → fast-analyzer-3GCCZMLK.js.map} +0 -0
  49. /package/dist/{goal-manager-YOB7VWK7.js.map → goal-manager-QUKX2W6C.js.map} +0 -0
  50. /package/dist/{goal-validator-ULKIBDPX.js.map → goal-validator-2SFSKKVU.js.map} +0 -0
  51. /package/dist/{hypothesis-7BFFT5JY.js.map → hypothesis-KCPBR652.js.map} +0 -0
  52. /package/dist/{issue-store-ZIRP23EP.js.map → issue-store-YAXTNRRY.js.map} +0 -0
  53. /package/dist/{tiered-storage-Z3YCR465.js.map → tiered-storage-DYNC5CQ6.js.map} +0 -0
  54. /package/dist/{trie-agent-3YDPEGHJ.js.map → trie-agent-I3HAHY2G.js.map} +0 -0
@@ -1,3 +1,6 @@
1
+ import {
2
+ Trie
3
+ } from "./chunk-6NLHFIYA.js";
1
4
  import {
2
5
  getTrieDirectory
3
6
  } from "./chunk-VVITXIHN.js";
@@ -7,6 +10,159 @@ import { writeFile, mkdir } from "fs/promises";
7
10
  import { join } from "path";
8
11
  import { createHash } from "crypto";
9
12
  import Database from "better-sqlite3";
13
+
14
+ // src/trie/ledger-trie.ts
15
+ var LedgerTrie = class {
16
+ tagTrie;
17
+ fileTrie;
18
+ agentTrie;
19
+ constructor() {
20
+ this.tagTrie = new Trie();
21
+ this.fileTrie = new Trie();
22
+ this.agentTrie = new Trie();
23
+ }
24
+ /**
25
+ * Index a tag from governance/blocker/fact
26
+ */
27
+ indexTag(tag) {
28
+ const normalized = tag.toLowerCase().trim();
29
+ if (!normalized) return;
30
+ const existing = this.tagTrie.search(normalized);
31
+ if (existing.found && existing.value) {
32
+ existing.value.occurrences++;
33
+ existing.value.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
34
+ this.tagTrie.insert(normalized, existing.value);
35
+ } else {
36
+ this.tagTrie.insert(normalized, {
37
+ type: "tag",
38
+ value: normalized,
39
+ occurrences: 1,
40
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString()
41
+ });
42
+ }
43
+ }
44
+ /**
45
+ * Index a file path from governance
46
+ */
47
+ indexFile(filePath) {
48
+ const normalized = filePath.trim();
49
+ if (!normalized) return;
50
+ const existing = this.fileTrie.search(normalized);
51
+ if (existing.found && existing.value) {
52
+ existing.value.occurrences++;
53
+ existing.value.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
54
+ this.fileTrie.insert(normalized, existing.value);
55
+ } else {
56
+ this.fileTrie.insert(normalized, {
57
+ type: "file",
58
+ value: normalized,
59
+ occurrences: 1,
60
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString()
61
+ });
62
+ }
63
+ }
64
+ /**
65
+ * Index an agent name from ledger entries
66
+ */
67
+ indexAgent(agentName) {
68
+ const normalized = agentName.toLowerCase().trim();
69
+ if (!normalized) return;
70
+ const existing = this.agentTrie.search(normalized);
71
+ if (existing.found && existing.value) {
72
+ existing.value.occurrences++;
73
+ existing.value.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
74
+ this.agentTrie.insert(normalized, existing.value);
75
+ } else {
76
+ this.agentTrie.insert(normalized, {
77
+ type: "agent",
78
+ value: normalized,
79
+ occurrences: 1,
80
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString()
81
+ });
82
+ }
83
+ }
84
+ /**
85
+ * Get all tags starting with prefix
86
+ */
87
+ searchTags(prefix) {
88
+ const normalized = prefix.toLowerCase().trim();
89
+ const results = this.tagTrie.getWithPrefix(normalized);
90
+ return results.map((r) => r.value).filter(Boolean).sort((a, b) => b.occurrences - a.occurrences);
91
+ }
92
+ /**
93
+ * Get all files starting with path prefix
94
+ */
95
+ searchFiles(pathPrefix) {
96
+ const normalized = pathPrefix.trim();
97
+ const results = this.fileTrie.getWithPrefix(normalized);
98
+ return results.map((r) => r.value).filter(Boolean).sort((a, b) => b.occurrences - a.occurrences);
99
+ }
100
+ /**
101
+ * Get all agents starting with prefix
102
+ */
103
+ searchAgents(prefix) {
104
+ const normalized = prefix.toLowerCase().trim();
105
+ const results = this.agentTrie.getWithPrefix(normalized);
106
+ return results.map((r) => r.value).filter(Boolean).sort((a, b) => b.occurrences - a.occurrences);
107
+ }
108
+ /**
109
+ * Get autocomplete suggestions for tags
110
+ */
111
+ autocomplete(type, prefix, limit = 10) {
112
+ let results;
113
+ switch (type) {
114
+ case "tag":
115
+ results = this.searchTags(prefix);
116
+ break;
117
+ case "file":
118
+ results = this.searchFiles(prefix);
119
+ break;
120
+ case "agent":
121
+ results = this.searchAgents(prefix);
122
+ break;
123
+ }
124
+ return results.slice(0, limit).map((r) => r.value);
125
+ }
126
+ /**
127
+ * Check if a tag exists
128
+ */
129
+ hasTag(tag) {
130
+ return this.tagTrie.search(tag.toLowerCase().trim()).found;
131
+ }
132
+ /**
133
+ * Check if a file path exists
134
+ */
135
+ hasFile(filePath) {
136
+ return this.fileTrie.search(filePath.trim()).found;
137
+ }
138
+ /**
139
+ * Get stats
140
+ */
141
+ getStats() {
142
+ return {
143
+ tags: this.tagTrie.getSize(),
144
+ files: this.fileTrie.getSize(),
145
+ agents: this.agentTrie.getSize()
146
+ };
147
+ }
148
+ /**
149
+ * Clear all indices
150
+ */
151
+ clear() {
152
+ this.tagTrie.clear();
153
+ this.fileTrie.clear();
154
+ this.agentTrie.clear();
155
+ }
156
+ };
157
+ var ledgerTrieInstance = null;
158
+ function getLedgerTrie() {
159
+ if (!ledgerTrieInstance) {
160
+ ledgerTrieInstance = new LedgerTrie();
161
+ }
162
+ return ledgerTrieInstance;
163
+ }
164
+
165
+ // src/storage/tiered-storage.ts
10
166
  var TieredStorage = class {
11
167
  workDir;
12
168
  hotCache = /* @__PURE__ */ new Map();
@@ -160,6 +316,7 @@ var TieredStorage = class {
160
316
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)
161
317
  `);
162
318
  const governanceRecords = signal.governance;
319
+ const ledgerTrie = getLedgerTrie();
163
320
  for (const gov of governanceRecords) {
164
321
  const hash = gov.hash || createHash("sha256").update(`${gov.decision}|${gov.context}|${gov.when}`).digest("hex").slice(0, 16);
165
322
  governanceStmt.run(
@@ -182,6 +339,12 @@ var TieredStorage = class {
182
339
  JSON.stringify(metadata?.domain || []),
183
340
  now
184
341
  );
342
+ for (const tag of gov.tags) {
343
+ ledgerTrie.indexTag(tag);
344
+ }
345
+ for (const file of gov.files) {
346
+ ledgerTrie.indexFile(file);
347
+ }
185
348
  }
186
349
  const factStmt = this.warmDb.prepare(`
187
350
  INSERT OR REPLACE INTO facts
@@ -219,6 +382,9 @@ var TieredStorage = class {
219
382
  JSON.stringify(metadata?.expandedTags || []),
220
383
  now
221
384
  );
385
+ for (const tag of blocker.tags) {
386
+ ledgerTrie.indexTag(tag);
387
+ }
222
388
  }
223
389
  const questionStmt = this.warmDb.prepare(`
224
390
  INSERT OR REPLACE INTO questions
@@ -721,6 +887,34 @@ var TieredStorage = class {
721
887
  this.warmDb = null;
722
888
  }
723
889
  }
890
+ /**
891
+ * Autocomplete tags from ledger trie
892
+ */
893
+ autocompleteTag(prefix, limit = 10) {
894
+ const ledgerTrie = getLedgerTrie();
895
+ return ledgerTrie.autocomplete("tag", prefix, limit);
896
+ }
897
+ /**
898
+ * Autocomplete file paths from ledger trie
899
+ */
900
+ autocompleteFile(pathPrefix, limit = 10) {
901
+ const ledgerTrie = getLedgerTrie();
902
+ return ledgerTrie.autocomplete("file", pathPrefix, limit);
903
+ }
904
+ /**
905
+ * Autocomplete agent names from ledger trie
906
+ */
907
+ autocompleteAgent(prefix, limit = 10) {
908
+ const ledgerTrie = getLedgerTrie();
909
+ return ledgerTrie.autocomplete("agent", prefix, limit);
910
+ }
911
+ /**
912
+ * Get ledger trie statistics
913
+ */
914
+ getTrieStats() {
915
+ const ledgerTrie = getLedgerTrie();
916
+ return ledgerTrie.getStats();
917
+ }
724
918
  };
725
919
  var storageInstances = /* @__PURE__ */ new Map();
726
920
  function getStorage(workDir) {
@@ -734,4 +928,4 @@ export {
734
928
  TieredStorage,
735
929
  getStorage
736
930
  };
737
- //# sourceMappingURL=chunk-575YT2SD.js.map
931
+ //# sourceMappingURL=chunk-BUTOP5EB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/tiered-storage.ts","../src/trie/ledger-trie.ts"],"sourcesContent":["/**\n * Tiered Storage System\n * \n * Three-tier architecture for context management:\n * - HOT: In-memory, current session data\n * - WARM: SQLite DB, queryable governance/facts/blockers\n * - COLD: Full history, indexed but not actively queried\n * \n * This prevents context pollution by keeping agents focused on\n * relevant signal rather than dumping everything into context.\n */\n\nimport { writeFile, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { createHash } from 'node:crypto';\nimport Database, { type Database as DatabaseType } from 'better-sqlite3';\nimport type {\n Governance,\n Blocker,\n ExtractedSignal,\n ContextQuery,\n Nudge,\n Gotcha,\n} from '../types/signal.js';\nimport { getTrieDirectory } from '../utils/workspace.js';\nimport { getLedgerTrie } from '../trie/ledger-trie.js';\n\nexport class TieredStorage {\n private workDir: string;\n private hotCache: Map<string, any> = new Map();\n private warmDb: DatabaseType | null = null;\n\n constructor(workDir: string) {\n this.workDir = workDir;\n }\n\n /**\n * Initialize storage directories and database\n */\n async initialize(): Promise<void> {\n const trieDir = getTrieDirectory(this.workDir);\n \n // Create directories\n await mkdir(join(trieDir, 'hot'), { recursive: true });\n await mkdir(join(trieDir, 'warm'), { recursive: true });\n await mkdir(join(trieDir, 'cold'), { recursive: true });\n\n // Initialize warm database\n const dbPath = join(trieDir, 'warm', 'governance.db');\n this.warmDb = new Database(dbPath);\n\n // Create tables\n this.warmDb!.exec(`\n CREATE TABLE IF NOT EXISTS governance (\n id TEXT PRIMARY KEY,\n decision TEXT NOT NULL,\n context TEXT NOT NULL,\n reasoning TEXT,\n timestamp TEXT NOT NULL,\n who TEXT,\n files TEXT NOT NULL, -- JSON array\n tags TEXT NOT NULL, -- JSON array\n expandedTags TEXT, -- JSON array (with synonyms)\n relatedTo TEXT, -- JSON array\n tradeoffs TEXT, -- JSON array\n status TEXT NOT NULL,\n supersededBy TEXT,\n hash TEXT, -- SHA-256 fingerprint (first 16 hex chars)\n dependencies TEXT, -- JSON array (npm packages, services)\n codebaseArea TEXT, -- JSON array (frontend, backend, auth, etc.)\n domain TEXT, -- JSON array (payments, compliance, etc.)\n lastAccessed TEXT NOT NULL,\n accessCount INTEGER DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS facts (\n id TEXT PRIMARY KEY,\n fact TEXT NOT NULL,\n source TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n tags TEXT NOT NULL, -- JSON array\n expandedTags TEXT, -- JSON array (with synonyms)\n relatedGovernance TEXT, -- JSON array\n confidence REAL NOT NULL,\n lastAccessed TEXT NOT NULL,\n accessCount INTEGER DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS blockers (\n id TEXT PRIMARY KEY,\n blocker TEXT NOT NULL,\n impact TEXT NOT NULL,\n affectedAreas TEXT NOT NULL, -- JSON array\n timestamp TEXT NOT NULL,\n resolvedAt TEXT,\n resolution TEXT,\n tags TEXT NOT NULL, -- JSON array\n expandedTags TEXT, -- JSON array (with synonyms)\n lastAccessed TEXT NOT NULL,\n accessCount INTEGER DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS questions (\n id TEXT PRIMARY KEY,\n question TEXT NOT NULL,\n context TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n answeredAt TEXT,\n answer TEXT,\n relatedGovernance TEXT, -- JSON array\n tags TEXT NOT NULL, -- JSON array\n expandedTags TEXT, -- JSON array (with synonyms)\n lastAccessed TEXT NOT NULL,\n accessCount INTEGER DEFAULT 0\n );\n\n CREATE TABLE IF NOT EXISTS nudges (\n id TEXT PRIMARY KEY,\n message TEXT NOT NULL,\n severity TEXT NOT NULL, -- 'critical', 'high', 'warning', 'info'\n file TEXT,\n category TEXT, -- 'quality', 'security', 'performance', etc.\n goalId TEXT, -- Related goal ID if this is a goal violation\n timestamp TEXT NOT NULL,\n resolved BOOLEAN NOT NULL DEFAULT 0,\n resolvedAt TEXT,\n resolution TEXT, -- How it was resolved: 'dismissed', 'fixed', 'auto-fixed'\n dismissed BOOLEAN NOT NULL DEFAULT 0,\n priority INTEGER DEFAULT 5, -- 1-10 priority score\n suggestedAction TEXT,\n relatedIssues TEXT, -- JSON array\n metadata TEXT -- JSON object for additional data\n );\n\n CREATE TABLE IF NOT EXISTS gotchas (\n id TEXT PRIMARY KEY,\n message TEXT NOT NULL,\n confidence REAL NOT NULL, -- 0-1 confidence score\n riskLevel TEXT NOT NULL, -- 'low', 'medium', 'high', 'critical'\n recommendation TEXT NOT NULL,\n file TEXT,\n timestamp TEXT NOT NULL,\n precedentId TEXT, -- ID of related historical incident/governance record\n tags TEXT NOT NULL, -- JSON array\n evidence TEXT NOT NULL, -- JSON object with pastIncidents, matchingPatterns, relatedTickets\n resolved BOOLEAN NOT NULL DEFAULT 0,\n resolvedAt TEXT,\n resolution TEXT -- 'confirmed', 'false-positive', 'dismissed'\n );\n\n CREATE INDEX IF NOT EXISTS idx_governance_tags ON governance(tags);\n CREATE INDEX IF NOT EXISTS idx_governance_expanded ON governance(expandedTags);\n CREATE INDEX IF NOT EXISTS idx_governance_timestamp ON governance(timestamp);\n CREATE INDEX IF NOT EXISTS idx_governance_status ON governance(status);\n CREATE INDEX IF NOT EXISTS idx_governance_area ON governance(codebaseArea);\n CREATE INDEX IF NOT EXISTS idx_governance_domain ON governance(domain);\n CREATE INDEX IF NOT EXISTS idx_facts_tags ON facts(tags);\n CREATE INDEX IF NOT EXISTS idx_facts_expanded ON facts(expandedTags);\n CREATE INDEX IF NOT EXISTS idx_blockers_impact ON blockers(impact);\n CREATE INDEX IF NOT EXISTS idx_blockers_resolved ON blockers(resolvedAt);\n CREATE INDEX IF NOT EXISTS idx_nudges_timestamp ON nudges(timestamp);\n CREATE INDEX IF NOT EXISTS idx_nudges_resolved ON nudges(resolved);\n CREATE INDEX IF NOT EXISTS idx_nudges_severity ON nudges(severity);\n CREATE INDEX IF NOT EXISTS idx_nudges_file ON nudges(file);\n CREATE INDEX IF NOT EXISTS idx_gotchas_timestamp ON gotchas(timestamp);\n CREATE INDEX IF NOT EXISTS idx_gotchas_resolved ON gotchas(resolved);\n CREATE INDEX IF NOT EXISTS idx_gotchas_riskLevel ON gotchas(riskLevel);\n CREATE INDEX IF NOT EXISTS idx_gotchas_file ON gotchas(file);\n CREATE INDEX IF NOT EXISTS idx_gotchas_tags ON gotchas(tags);\n `);\n }\n\n /**\n * Store extracted signal with enriched metadata in warm storage\n */\n async storeSignal(signal: ExtractedSignal, metadata?: {\n expandedTags?: string[];\n dependencies?: string[];\n codebaseArea?: string[];\n domain?: string[];\n }): Promise<void> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const now = new Date().toISOString();\n \n // Log what we're storing for debugging\n const totalSignals = signal.governance.length + signal.facts.length + \n signal.blockers.length + signal.questions.length;\n if (totalSignals > 0) {\n console.debug(`[Storage] Storing ${totalSignals} signals: ${signal.governance.length}g, ${signal.facts.length}f, ${signal.blockers.length}b, ${signal.questions.length}q`);\n }\n\n // Store governance records\n const governanceStmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO governance \n (id, decision, context, reasoning, timestamp, who, files, tags, expandedTags, relatedTo, tradeoffs, status, supersededBy, hash, dependencies, codebaseArea, domain, lastAccessed, accessCount)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)\n `);\n\n const governanceRecords = signal.governance;\n const ledgerTrie = getLedgerTrie();\n \n for (const gov of governanceRecords) {\n const hash = gov.hash || createHash('sha256')\n .update(`${gov.decision}|${gov.context}|${gov.when}`)\n .digest('hex')\n .slice(0, 16);\n governanceStmt.run(\n gov.id,\n gov.decision,\n gov.context,\n gov.reasoning || null,\n gov.when,\n gov.who || null,\n JSON.stringify(gov.files),\n JSON.stringify(gov.tags),\n JSON.stringify(metadata?.expandedTags || []),\n JSON.stringify(gov.relatedTo || []),\n JSON.stringify(gov.tradeoffs || []),\n gov.status,\n gov.supersededBy || null,\n hash,\n JSON.stringify(metadata?.dependencies || []),\n JSON.stringify(metadata?.codebaseArea || []),\n JSON.stringify(metadata?.domain || []),\n now\n );\n \n // Index tags and files in ledger trie for autocomplete\n for (const tag of gov.tags) {\n ledgerTrie.indexTag(tag);\n }\n for (const file of gov.files) {\n ledgerTrie.indexFile(file);\n }\n }\n\n // Store facts\n const factStmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO facts\n (id, fact, source, timestamp, tags, expandedTags, relatedGovernance, confidence, lastAccessed, accessCount)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0)\n `);\n\n for (const fact of signal.facts) {\n factStmt.run(\n fact.id,\n fact.fact,\n fact.source,\n fact.when,\n JSON.stringify(fact.tags),\n JSON.stringify(metadata?.expandedTags || []),\n JSON.stringify(fact.relatedGovernance || []),\n fact.confidence,\n now\n );\n }\n\n // Store blockers\n const blockerStmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO blockers\n (id, blocker, impact, affectedAreas, timestamp, resolvedAt, resolution, tags, expandedTags, lastAccessed, accessCount)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)\n `);\n\n for (const blocker of signal.blockers) {\n blockerStmt.run(\n blocker.id,\n blocker.blocker,\n blocker.impact,\n JSON.stringify(blocker.affectedAreas),\n blocker.when,\n blocker.resolvedAt || null,\n blocker.resolution || null,\n JSON.stringify(blocker.tags),\n JSON.stringify(metadata?.expandedTags || []),\n now\n );\n \n // Index blocker tags in ledger trie\n for (const tag of blocker.tags) {\n ledgerTrie.indexTag(tag);\n }\n }\n\n // Store questions\n const questionStmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO questions\n (id, question, context, timestamp, answeredAt, answer, relatedGovernance, tags, expandedTags, lastAccessed, accessCount)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)\n `);\n\n for (const q of signal.questions) {\n questionStmt.run(\n q.id,\n q.question,\n q.context,\n q.when,\n q.answeredAt || null,\n q.answer || null,\n JSON.stringify(q.relatedGovernance || []),\n JSON.stringify(q.tags),\n JSON.stringify(metadata?.expandedTags || []),\n now\n );\n }\n\n // Store gotchas if present\n if (signal.gotchas && signal.gotchas.length > 0) {\n const gotchaStmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO gotchas\n (id, message, confidence, riskLevel, recommendation, file, timestamp, precedentId, tags, evidence, resolved, resolvedAt, resolution)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n for (const g of signal.gotchas) {\n gotchaStmt.run(\n g.id,\n g.message,\n g.confidence,\n g.riskLevel,\n g.recommendation,\n g.file || null,\n g.timestamp,\n g.precedentId || null,\n JSON.stringify(g.tags || []),\n JSON.stringify(g.evidence || { pastIncidents: [], matchingPatterns: [], relatedTickets: [] }),\n g.resolved ? 1 : 0,\n g.resolvedAt || null,\n g.resolution || null\n );\n }\n }\n \n // Log successful storage\n const storedCount = signal.governance.length + signal.facts.length + \n signal.blockers.length + signal.questions.length +\n (signal.gotchas?.length || 0);\n if (storedCount > 0) {\n console.debug(`[Storage] ✓ Successfully stored ${storedCount} signals to governance.db`);\n }\n }\n\n /**\n * Query governance records from warm storage with expanded tag matching\n */\n async queryGovernance(query: ContextQuery): Promise<Governance[]> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n let sql = 'SELECT * FROM governance WHERE status = ?';\n const params: any[] = ['active'];\n\n // Add filters - search both tags and expandedTags for broader matching\n if (query.tags && query.tags.length > 0) {\n sql += ' AND (' + query.tags.map(() => '(tags LIKE ? OR expandedTags LIKE ?)').join(' OR ') + ')';\n for (const tag of query.tags) {\n params.push(`%\"${tag}\"%`, `%\"${tag}\"%`);\n }\n }\n\n // Filter by codebase area if specified\n if (query.filters?.codebaseArea) {\n sql += ' AND codebaseArea LIKE ?';\n params.push(`%\"${query.filters.codebaseArea}\"%`);\n }\n\n // Filter by domain if specified\n if (query.filters?.domain) {\n sql += ' AND domain LIKE ?';\n params.push(`%\"${query.filters.domain}\"%`);\n }\n\n if (query.timeWindow) {\n if (query.timeWindow.start) {\n sql += ' AND timestamp >= ?';\n params.push(query.timeWindow.start);\n }\n if (query.timeWindow.end) {\n sql += ' AND timestamp <= ?';\n params.push(query.timeWindow.end);\n }\n }\n\n sql += ' ORDER BY timestamp DESC';\n\n if (query.limit) {\n sql += ' LIMIT ?';\n params.push(query.limit);\n }\n\n const rows = this.warmDb.prepare(sql).all(...params) as any[];\n\n return rows.map(row => ({\n id: row.id,\n decision: row.decision,\n context: row.context,\n reasoning: row.reasoning,\n when: row.timestamp || row.when,\n who: row.who,\n files: JSON.parse(row.files),\n tags: JSON.parse(row.tags),\n relatedTo: JSON.parse(row.relatedTo || '[]'),\n tradeoffs: JSON.parse(row.tradeoffs || '[]'),\n status: row.status,\n supersededBy: row.supersededBy,\n hash: row.hash || undefined,\n }));\n }\n\n /**\n * Query facts from warm storage (for Learned Signals display)\n */\n async queryFacts(query: { limit?: number } = {}): Promise<Array<{ id: string; fact: string; source: string; when: string; tags: string[]; confidence: number }>> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const limit = query.limit ?? 20;\n const rows = this.warmDb.prepare('SELECT * FROM facts ORDER BY timestamp DESC LIMIT ?').all(limit) as any[];\n\n return rows.map(row => ({\n id: row.id,\n fact: row.fact,\n source: row.source,\n when: row.timestamp || row.when,\n tags: JSON.parse(row.tags || '[]'),\n confidence: row.confidence ?? 0.8,\n }));\n }\n\n /**\n * Query blockers from warm storage with expanded tag matching\n */\n async queryBlockers(query: ContextQuery): Promise<Blocker[]> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n let sql = 'SELECT * FROM blockers WHERE resolvedAt IS NULL';\n const params: any[] = [];\n\n if (query.tags && query.tags.length > 0) {\n sql += ' AND (' + query.tags.map(() => '(tags LIKE ? OR expandedTags LIKE ?)').join(' OR ') + ')';\n for (const tag of query.tags) {\n params.push(`%\"${tag}\"%`, `%\"${tag}\"%`);\n }\n }\n\n sql += \" ORDER BY CASE impact WHEN 'critical' THEN 1 WHEN 'high' THEN 2 WHEN 'medium' THEN 3 ELSE 4 END, timestamp DESC\";\n\n if (query.limit) {\n sql += ' LIMIT ?';\n params.push(query.limit);\n }\n\n const rows = this.warmDb.prepare(sql).all(...params) as any[];\n\n return rows.map(row => ({\n id: row.id,\n blocker: row.blocker,\n impact: row.impact,\n affectedAreas: JSON.parse(row.affectedAreas),\n when: row.when,\n resolvedAt: row.resolvedAt,\n resolution: row.resolution,\n tags: JSON.parse(row.tags)\n }));\n }\n\n /**\n * Get hot cache item\n */\n getHot<T>(key: string): T | undefined {\n return this.hotCache.get(key);\n }\n\n /**\n * Set hot cache item\n */\n setHot<T>(key: string, value: T): void {\n this.hotCache.set(key, value);\n }\n\n /**\n * Clear hot cache\n */\n clearHot(): void {\n this.hotCache.clear();\n }\n\n /**\n * Store a nudge in warm storage\n */\n async storeNudge(nudge: Nudge): Promise<void> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const stmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO nudges\n (id, message, severity, file, category, goalId, timestamp, resolved, resolvedAt, resolution, dismissed, priority, suggestedAction, relatedIssues, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n stmt.run(\n nudge.id,\n nudge.message,\n nudge.severity,\n nudge.file || null,\n nudge.category || null,\n nudge.goalId || null,\n nudge.timestamp,\n nudge.resolved ? 1 : 0,\n nudge.resolvedAt || null,\n nudge.resolution || null,\n nudge.dismissed ? 1 : 0,\n nudge.priority,\n nudge.suggestedAction || null,\n JSON.stringify(nudge.relatedIssues || []),\n JSON.stringify(nudge.metadata || {})\n );\n }\n\n /**\n * Query nudges from warm storage\n */\n async queryNudges(filters?: {\n resolved?: boolean;\n severity?: string;\n file?: string;\n category?: string;\n goalId?: string;\n limit?: number;\n }): Promise<Nudge[]> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n let sql = 'SELECT * FROM nudges WHERE 1=1';\n const params: any[] = [];\n\n if (filters?.resolved !== undefined) {\n sql += ' AND resolved = ?';\n params.push(filters.resolved ? 1 : 0);\n }\n\n if (filters?.severity) {\n sql += ' AND severity = ?';\n params.push(filters.severity);\n }\n\n if (filters?.file) {\n sql += ' AND file = ?';\n params.push(filters.file);\n }\n\n if (filters?.category) {\n sql += ' AND category = ?';\n params.push(filters.category);\n }\n\n if (filters?.goalId) {\n sql += ' AND goalId = ?';\n params.push(filters.goalId);\n }\n\n sql += ' ORDER BY timestamp DESC';\n\n if (filters?.limit) {\n sql += ' LIMIT ?';\n params.push(filters.limit);\n }\n\n const rows = this.warmDb.prepare(sql).all(...params) as any[];\n\n return rows.map(row => ({\n id: row.id,\n message: row.message,\n severity: row.severity,\n file: row.file || undefined,\n category: row.category || undefined,\n goalId: row.goalId || undefined,\n timestamp: row.timestamp,\n resolved: Boolean(row.resolved),\n resolvedAt: row.resolvedAt || undefined,\n resolution: row.resolution || undefined,\n dismissed: Boolean(row.dismissed),\n priority: row.priority,\n suggestedAction: row.suggestedAction || undefined,\n relatedIssues: JSON.parse(row.relatedIssues || '[]'),\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n }\n\n /**\n * Mark a nudge as resolved\n */\n async resolveNudge(nudgeId: string, resolution: 'dismissed' | 'fixed' | 'auto-fixed'): Promise<void> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const now = new Date().toISOString();\n \n this.warmDb.prepare(`\n UPDATE nudges \n SET resolved = 1, resolvedAt = ?, resolution = ?, dismissed = ?\n WHERE id = ?\n `).run(now, resolution, resolution === 'dismissed' ? 1 : 0, nudgeId);\n }\n\n /**\n * Mark a nudge as dismissed\n */\n async dismissNudge(nudgeId: string): Promise<void> {\n await this.resolveNudge(nudgeId, 'dismissed');\n }\n\n /**\n * Mark a nudge as fixed (automatically called when issues are resolved)\n */\n async markNudgeFixed(nudgeId: string): Promise<void> {\n await this.resolveNudge(nudgeId, 'fixed');\n }\n\n /**\n * Clear all nudges (mark all as resolved)\n */\n async clearAllNudges(): Promise<void> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const now = new Date().toISOString();\n \n this.warmDb.prepare(`\n UPDATE nudges \n SET resolved = 1, resolvedAt = ?, resolution = 'dismissed'\n WHERE resolved = 0\n `).run(now);\n }\n\n /**\n * Resolve nudges for a goal violation that was fixed in a specific file.\n * Called when a file is rescanned and no longer has violations for that goal.\n */\n async resolveNudgesForGoalViolation(file: string, goalDescription: string, _workDir?: string): Promise<number> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const goalPattern = `%Goal \"${goalDescription.replace(/\"/g, '\"\"')}\"%`;\n const fileAlt = file.replace(/\\\\/g, '/');\n const rows = this.warmDb.prepare(`\n SELECT id FROM nudges \n WHERE resolved = 0 \n AND (file = ? OR file = ?)\n AND message LIKE ?\n `).all(file, fileAlt, goalPattern) as { id: string }[];\n\n const now = new Date().toISOString();\n let resolved = 0;\n for (const row of rows) {\n this.warmDb.prepare(`\n UPDATE nudges SET resolved = 1, resolvedAt = ?, resolution = 'auto-fixed'\n WHERE id = ?\n `).run(now, row.id);\n resolved++;\n }\n return resolved;\n }\n\n /**\n * Resolve all nudges for a specific goal (used when goal is achieved or deleted)\n */\n async resolveNudgesForGoal(goalDescription: string): Promise<number> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const goalPattern = `%Goal \"${goalDescription.replace(/\"/g, '\"\"')}\"%`;\n const now = new Date().toISOString();\n \n const result = this.warmDb.prepare(`\n UPDATE nudges \n SET resolved = 1, resolvedAt = ?, resolution = 'goal-achieved'\n WHERE resolved = 0 AND message LIKE ?\n `).run(now, goalPattern);\n\n return result.changes;\n }\n\n /**\n * Resolve nudges for files that no longer exist\n */\n async resolveNudgesForMissingFiles(): Promise<number> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const { existsSync } = await import('fs');\n const rows = this.warmDb.prepare(`\n SELECT id, file FROM nudges WHERE resolved = 0 AND file IS NOT NULL\n `).all() as { id: string; file: string }[];\n\n const now = new Date().toISOString();\n let resolved = 0;\n for (const row of rows) {\n if (row.file && !existsSync(row.file)) {\n this.warmDb.prepare(`\n UPDATE nudges SET resolved = 1, resolvedAt = ?, resolution = 'file-deleted'\n WHERE id = ?\n `).run(now, row.id);\n resolved++;\n }\n }\n return resolved;\n }\n\n /**\n * Resolve nudges matching a pattern in the message (for type error clearing, etc.)\n */\n async resolveNudgesByPattern(messagePattern: string, resolution: string = 'auto-fixed'): Promise<number> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const now = new Date().toISOString();\n const result = this.warmDb.prepare(`\n UPDATE nudges \n SET resolved = 1, resolvedAt = ?, resolution = ?\n WHERE resolved = 0 AND message LIKE ?\n `).run(now, resolution, `%${messagePattern}%`);\n\n return result.changes;\n }\n\n /**\n * Auto-resolve nudges that match fixed issues\n * Called after a scan to mark nudges as fixed if their related issues are resolved\n */\n async autoResolveFixedNudges(resolvedIssueIds: string[]): Promise<number> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n if (resolvedIssueIds.length === 0) return 0;\n\n const now = new Date().toISOString();\n let resolved = 0;\n\n // Mark nudges as fixed if their related issues are in the resolved list\n for (const issueId of resolvedIssueIds) {\n const result = this.warmDb.prepare(`\n UPDATE nudges \n SET resolved = 1, resolvedAt = ?, resolution = 'auto-fixed'\n WHERE resolved = 0 \n AND (\n relatedIssues LIKE ? \n OR id = ?\n )\n `).run(now, `%\"${issueId}\"%`, issueId);\n \n resolved += result.changes;\n }\n\n return resolved;\n }\n\n /**\n * Store a gotcha in warm storage\n */\n async storeGotcha(gotcha: Gotcha): Promise<void> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const stmt = this.warmDb.prepare(`\n INSERT OR REPLACE INTO gotchas\n (id, message, confidence, riskLevel, recommendation, file, timestamp, precedentId, tags, evidence, resolved, resolvedAt, resolution)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n stmt.run(\n gotcha.id,\n gotcha.message,\n gotcha.confidence,\n gotcha.riskLevel,\n gotcha.recommendation,\n gotcha.file || null,\n gotcha.timestamp,\n gotcha.precedentId || null,\n JSON.stringify(gotcha.tags || []),\n JSON.stringify(gotcha.evidence || { pastIncidents: [], matchingPatterns: [], relatedTickets: [] }),\n gotcha.resolved ? 1 : 0,\n gotcha.resolvedAt || null,\n gotcha.resolution || null\n );\n }\n\n /**\n * Query gotchas from warm storage\n */\n async queryGotchas(filters?: {\n resolved?: boolean;\n riskLevel?: string;\n file?: string;\n limit?: number;\n }): Promise<Gotcha[]> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n let sql = 'SELECT * FROM gotchas WHERE 1=1';\n const params: any[] = [];\n\n if (filters?.resolved !== undefined) {\n sql += ' AND resolved = ?';\n params.push(filters.resolved ? 1 : 0);\n }\n\n if (filters?.riskLevel) {\n sql += ' AND riskLevel = ?';\n params.push(filters.riskLevel);\n }\n\n if (filters?.file) {\n sql += ' AND file = ?';\n params.push(filters.file);\n }\n\n sql += ' ORDER BY timestamp DESC';\n\n if (filters?.limit) {\n sql += ' LIMIT ?';\n params.push(filters.limit);\n }\n\n const rows = this.warmDb.prepare(sql).all(...params) as any[];\n\n return rows.map(row => ({\n id: row.id,\n message: row.message,\n confidence: row.confidence,\n riskLevel: row.riskLevel,\n recommendation: row.recommendation,\n file: row.file || undefined,\n timestamp: row.timestamp,\n precedentId: row.precedentId || undefined,\n tags: JSON.parse(row.tags || '[]'),\n evidence: JSON.parse(row.evidence || '{\"pastIncidents\":[],\"matchingPatterns\":[],\"relatedTickets\":[]}'),\n resolved: Boolean(row.resolved),\n resolvedAt: row.resolvedAt || undefined,\n resolution: row.resolution || undefined,\n }));\n }\n\n /**\n * Get unresolved nudges count\n */\n async getUnresolvedNudgesCount(): Promise<number> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const result = this.warmDb.prepare('SELECT COUNT(*) as count FROM nudges WHERE resolved = 0').get() as { count: number };\n return result.count;\n }\n\n /**\n * Archive old data to cold storage\n */\n async archiveToCold(olderThanDays: number = 90): Promise<void> {\n if (!this.warmDb) await this.initialize();\n if (!this.warmDb) throw new Error('Database not initialized');\n\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);\n const cutoff = cutoffDate.toISOString();\n\n // Export to cold storage\n const coldDir = join(getTrieDirectory(this.workDir), 'cold');\n const archivePath = join(coldDir, `archive-${Date.now()}.json`);\n\n const governance = this.warmDb.prepare('SELECT * FROM governance WHERE timestamp < ? AND accessCount < 3').all(cutoff);\n const facts = this.warmDb.prepare('SELECT * FROM facts WHERE timestamp < ? AND accessCount < 3').all(cutoff);\n const blockers = this.warmDb.prepare('SELECT * FROM blockers WHERE timestamp < ? AND resolvedAt IS NOT NULL').all(cutoff);\n const questions = this.warmDb.prepare('SELECT * FROM questions WHERE timestamp < ? AND answeredAt IS NOT NULL').all(cutoff);\n const nudges = this.warmDb.prepare('SELECT * FROM nudges WHERE timestamp < ? AND resolved = 1').all(cutoff);\n const gotchas = this.warmDb.prepare('SELECT * FROM gotchas WHERE timestamp < ? AND resolved = 1').all(cutoff);\n\n await writeFile(archivePath, JSON.stringify({ governance, facts, blockers, questions, nudges, gotchas }, null, 2));\n\n // Delete from warm storage\n this.warmDb.prepare('DELETE FROM governance WHERE timestamp < ? AND accessCount < 3').run(cutoff);\n this.warmDb.prepare('DELETE FROM facts WHERE timestamp < ? AND accessCount < 3').run(cutoff);\n this.warmDb.prepare('DELETE FROM blockers WHERE timestamp < ? AND resolvedAt IS NOT NULL').run(cutoff);\n this.warmDb.prepare('DELETE FROM questions WHERE timestamp < ? AND answeredAt IS NOT NULL').run(cutoff);\n this.warmDb.prepare('DELETE FROM nudges WHERE timestamp < ? AND resolved = 1').run(cutoff);\n this.warmDb.prepare('DELETE FROM gotchas WHERE timestamp < ? AND resolved = 1').run(cutoff);\n }\n\n /**\n * Close database connection\n */\n close(): void {\n if (this.warmDb) {\n this.warmDb.close();\n this.warmDb = null;\n }\n }\n\n /**\n * Autocomplete tags from ledger trie\n */\n autocompleteTag(prefix: string, limit = 10): string[] {\n const ledgerTrie = getLedgerTrie();\n return ledgerTrie.autocomplete('tag', prefix, limit);\n }\n\n /**\n * Autocomplete file paths from ledger trie\n */\n autocompleteFile(pathPrefix: string, limit = 10): string[] {\n const ledgerTrie = getLedgerTrie();\n return ledgerTrie.autocomplete('file', pathPrefix, limit);\n }\n\n /**\n * Autocomplete agent names from ledger trie\n */\n autocompleteAgent(prefix: string, limit = 10): string[] {\n const ledgerTrie = getLedgerTrie();\n return ledgerTrie.autocomplete('agent', prefix, limit);\n }\n\n /**\n * Get ledger trie statistics\n */\n getTrieStats(): { tags: number; files: number; agents: number } {\n const ledgerTrie = getLedgerTrie();\n return ledgerTrie.getStats();\n }\n}\n\n/**\n * Get storage instance for working directory\n */\nconst storageInstances = new Map<string, TieredStorage>();\n\nexport function getStorage(workDir: string): TieredStorage {\n if (!storageInstances.has(workDir)) {\n storageInstances.set(workDir, new TieredStorage(workDir));\n }\n return storageInstances.get(workDir)!;\n}\n","/**\n * Ledger Trie - Prefix search for governance ledger\n * \n * Fast O(m) prefix lookups for:\n * - Tags (e.g., \"auth\" -> \"auth\", \"authentication\", \"authorization\")\n * - File paths (e.g., \"src/auth\" -> all files under that path)\n * - Agent names\n * \n * Supports autocomplete and discovery of what's in the ledger.\n */\n\nimport { Trie } from './trie.js';\n\nexport interface LedgerTrieEntry {\n type: 'tag' | 'file' | 'agent';\n value: string;\n occurrences: number; // How many times this appears in ledger\n lastSeen: string; // ISO timestamp\n}\n\nexport class LedgerTrie {\n private tagTrie: Trie<LedgerTrieEntry>;\n private fileTrie: Trie<LedgerTrieEntry>;\n private agentTrie: Trie<LedgerTrieEntry>;\n\n constructor() {\n this.tagTrie = new Trie();\n this.fileTrie = new Trie();\n this.agentTrie = new Trie();\n }\n\n /**\n * Index a tag from governance/blocker/fact\n */\n indexTag(tag: string): void {\n const normalized = tag.toLowerCase().trim();\n if (!normalized) return;\n\n const existing = this.tagTrie.search(normalized);\n if (existing.found && existing.value) {\n // Update existing\n existing.value.occurrences++;\n existing.value.lastSeen = new Date().toISOString();\n this.tagTrie.insert(normalized, existing.value);\n } else {\n // Insert new\n this.tagTrie.insert(normalized, {\n type: 'tag',\n value: normalized,\n occurrences: 1,\n lastSeen: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Index a file path from governance\n */\n indexFile(filePath: string): void {\n const normalized = filePath.trim();\n if (!normalized) return;\n\n const existing = this.fileTrie.search(normalized);\n if (existing.found && existing.value) {\n existing.value.occurrences++;\n existing.value.lastSeen = new Date().toISOString();\n this.fileTrie.insert(normalized, existing.value);\n } else {\n this.fileTrie.insert(normalized, {\n type: 'file',\n value: normalized,\n occurrences: 1,\n lastSeen: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Index an agent name from ledger entries\n */\n indexAgent(agentName: string): void {\n const normalized = agentName.toLowerCase().trim();\n if (!normalized) return;\n\n const existing = this.agentTrie.search(normalized);\n if (existing.found && existing.value) {\n existing.value.occurrences++;\n existing.value.lastSeen = new Date().toISOString();\n this.agentTrie.insert(normalized, existing.value);\n } else {\n this.agentTrie.insert(normalized, {\n type: 'agent',\n value: normalized,\n occurrences: 1,\n lastSeen: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Get all tags starting with prefix\n */\n searchTags(prefix: string): LedgerTrieEntry[] {\n const normalized = prefix.toLowerCase().trim();\n const results = this.tagTrie.getWithPrefix(normalized);\n return results\n .map(r => r.value!)\n .filter(Boolean)\n .sort((a, b) => b.occurrences - a.occurrences); // Most frequent first\n }\n\n /**\n * Get all files starting with path prefix\n */\n searchFiles(pathPrefix: string): LedgerTrieEntry[] {\n const normalized = pathPrefix.trim();\n const results = this.fileTrie.getWithPrefix(normalized);\n return results\n .map(r => r.value!)\n .filter(Boolean)\n .sort((a, b) => b.occurrences - a.occurrences);\n }\n\n /**\n * Get all agents starting with prefix\n */\n searchAgents(prefix: string): LedgerTrieEntry[] {\n const normalized = prefix.toLowerCase().trim();\n const results = this.agentTrie.getWithPrefix(normalized);\n return results\n .map(r => r.value!)\n .filter(Boolean)\n .sort((a, b) => b.occurrences - a.occurrences);\n }\n\n /**\n * Get autocomplete suggestions for tags\n */\n autocomplete(type: 'tag' | 'file' | 'agent', prefix: string, limit = 10): string[] {\n let results: LedgerTrieEntry[];\n \n switch (type) {\n case 'tag':\n results = this.searchTags(prefix);\n break;\n case 'file':\n results = this.searchFiles(prefix);\n break;\n case 'agent':\n results = this.searchAgents(prefix);\n break;\n }\n\n return results.slice(0, limit).map(r => r.value);\n }\n\n /**\n * Check if a tag exists\n */\n hasTag(tag: string): boolean {\n return this.tagTrie.search(tag.toLowerCase().trim()).found;\n }\n\n /**\n * Check if a file path exists\n */\n hasFile(filePath: string): boolean {\n return this.fileTrie.search(filePath.trim()).found;\n }\n\n /**\n * Get stats\n */\n getStats(): { tags: number; files: number; agents: number } {\n return {\n tags: this.tagTrie.getSize(),\n files: this.fileTrie.getSize(),\n agents: this.agentTrie.getSize(),\n };\n }\n\n /**\n * Clear all indices\n */\n clear(): void {\n this.tagTrie.clear();\n this.fileTrie.clear();\n this.agentTrie.clear();\n }\n}\n\n// Singleton instance\nlet ledgerTrieInstance: LedgerTrie | null = null;\n\nexport function getLedgerTrie(): LedgerTrie {\n if (!ledgerTrieInstance) {\n ledgerTrieInstance = new LedgerTrie();\n }\n return ledgerTrieInstance;\n}\n\nexport function resetLedgerTrie(): void {\n ledgerTrieInstance = null;\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  getMemoryStats,
6
6
  searchIssues
7
- } from "./chunk-XE6KQRKZ.js";
7
+ } from "./chunk-KCUOWRPX.js";
8
8
  import {
9
9
  getProjectState
10
10
  } from "./chunk-GTKYBOXL.js";
@@ -290,7 +290,7 @@ var GoalManager = class {
290
290
  currentValue
291
291
  });
292
292
  try {
293
- const { getStorage } = await import("./tiered-storage-Z3YCR465.js");
293
+ const { getStorage } = await import("./tiered-storage-DYNC5CQ6.js");
294
294
  const storage = getStorage(this.projectPath);
295
295
  await storage.initialize();
296
296
  const resolved = await storage.resolveNudgesForGoal(goal.description);
@@ -659,4 +659,4 @@ export {
659
659
  getGoalManager,
660
660
  clearGoalManagers
661
661
  };
662
- //# sourceMappingURL=chunk-MRHKX5M5.js.map
662
+ //# sourceMappingURL=chunk-FBNURWRY.js.map
@@ -4,18 +4,15 @@ import {
4
4
  import {
5
5
  TriePatternDiscovery
6
6
  } from "./chunk-ZV2K6M7T.js";
7
- import {
8
- scanForVulnerabilities
9
- } from "./chunk-SY6KQG44.js";
10
- import {
11
- scanForVibeCodeIssues
12
- } from "./chunk-OMR4YCBS.js";
13
7
  import {
14
8
  ContextGraph
15
9
  } from "./chunk-VUL52BQL.js";
10
+ import {
11
+ tryGetClient
12
+ } from "./chunk-FQ45QP5A.js";
16
13
  import {
17
14
  storeIssues
18
- } from "./chunk-XE6KQRKZ.js";
15
+ } from "./chunk-KCUOWRPX.js";
19
16
  import {
20
17
  getTrieDirectory,
21
18
  getWorkingDirectory
@@ -223,57 +220,77 @@ var LearningEngine = class {
223
220
  }
224
221
  async extractIssuesFromDiff(diff, file, type, message) {
225
222
  const issues = [];
226
- const badLines = this.getBadLinesFromDiff(diff, file, type);
227
- const content = badLines.join("\n");
228
- if (!content) return [];
229
- const vulnerabilities = await scanForVulnerabilities(content, file);
230
- const vibeIssues = await scanForVibeCodeIssues(content, file);
231
- const allMatches = [...vulnerabilities, ...vibeIssues];
232
- for (const match of allMatches) {
233
- issues.push({
234
- id: `implicit-${type}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
235
- severity: "serious",
236
- issue: `Implicit failure detected via ${type}: ${message}. Linked to pattern: ${match.category}`,
237
- fix: `Review the ${type} commit and avoid this pattern in ${file}.`,
238
- file,
239
- confidence: 0.7,
240
- autoFixable: false,
241
- agent: "implicit-learning",
242
- category: match.category
243
- });
223
+ const client = tryGetClient();
224
+ if (client) {
225
+ try {
226
+ const systemPrompt = `You are analyzing a git ${type} commit to understand what went wrong.
227
+
228
+ A ${type} commit means:
229
+ - If "fix": The removed lines (starting with -) were BUGGY and the added lines (starting with +) are the FIX
230
+ - If "revert": The commit is undoing changes, so the removed lines were PROBLEMATIC
231
+
232
+ Your job: Identify what patterns or issues led to this ${type}. Return a JSON array of issues:
233
+ [{
234
+ "issue": "Brief description of what was wrong",
235
+ "category": "bug category (e.g., logic-error, null-check, race-condition)",
236
+ "severity": "critical" | "serious" | "moderate",
237
+ "fix": "What the fix does / how to avoid this"
238
+ }]
239
+
240
+ IMPORTANT: Only return JSON, no other text. Focus on the ROOT CAUSE, not just symptoms.`;
241
+ const userPrompt = `File: ${file}
242
+ Commit message: ${message}
243
+ Type: ${type}
244
+
245
+ Diff:
246
+ \`\`\`diff
247
+ ${diff.slice(0, 3e3)}
248
+ \`\`\`
249
+
250
+ Analyze what went wrong and return JSON array of issues.`;
251
+ const response = await client.messages.create({
252
+ model: "claude-sonnet-4-20250514",
253
+ max_tokens: 2048,
254
+ temperature: 0.2,
255
+ system: systemPrompt,
256
+ messages: [{ role: "user", content: userPrompt }]
257
+ });
258
+ const textContent = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
259
+ const jsonMatch = textContent.match(/\[[\s\S]*\]/);
260
+ if (jsonMatch) {
261
+ const aiIssues = JSON.parse(jsonMatch[0]);
262
+ for (const aiIssue of aiIssues) {
263
+ issues.push({
264
+ id: `implicit-${type}-ai-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
265
+ severity: aiIssue.severity || "moderate",
266
+ issue: `[AI] ${aiIssue.issue} (from ${type} commit: ${message})`,
267
+ fix: aiIssue.fix || `Review the ${type} commit and learn from this pattern.`,
268
+ file,
269
+ confidence: 0.8,
270
+ autoFixable: false,
271
+ agent: "implicit-learning-ai",
272
+ category: aiIssue.category || type
273
+ });
274
+ }
275
+ }
276
+ } catch (error) {
277
+ }
244
278
  }
245
279
  if (issues.length === 0) {
246
280
  issues.push({
247
- id: `implicit-${type}-${Date.now()}`,
281
+ id: `implicit-${type}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
248
282
  severity: "moderate",
249
- issue: `Historical ${type} detected: ${message}`,
250
- fix: `Review the changes in ${file} from this commit to avoid regression.`,
283
+ issue: `Implicit failure detected via ${type}: ${message}`,
284
+ fix: `Review the ${type} commit and learn from this pattern in ${file}.`,
251
285
  file,
252
- confidence: 0.5,
286
+ confidence: 0.7,
253
287
  autoFixable: false,
254
- agent: "implicit-learning"
288
+ agent: "implicit-learning",
289
+ category: type
255
290
  });
256
291
  }
257
292
  return issues;
258
293
  }
259
- getBadLinesFromDiff(diff, file, type) {
260
- const badLines = [];
261
- const lines = diff.split("\n");
262
- let inTargetFile = false;
263
- for (const line of lines) {
264
- if (line.startsWith("+++ b/") || line.startsWith("--- a/")) {
265
- inTargetFile = line.includes(file);
266
- continue;
267
- }
268
- if (!inTargetFile) continue;
269
- if (type === "fix" && line.startsWith("-") && !line.startsWith("---")) {
270
- badLines.push(line.slice(1));
271
- } else if (type === "revert" && line.startsWith("+") && !line.startsWith("+++")) {
272
- badLines.push(line.slice(1));
273
- }
274
- }
275
- return badLines;
276
- }
277
294
  };
278
295
 
279
296
  // src/agent/perceive.ts
@@ -1286,4 +1303,4 @@ export {
1286
1303
  reasonAboutChangesHumanReadable,
1287
1304
  isTrieInitialized
1288
1305
  };
1289
- //# sourceMappingURL=chunk-YZ6Y2H3P.js.map
1306
+ //# sourceMappingURL=chunk-FVRO5RN3.js.map