@rangerchaz/aimem 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -11
- package/dist/cli/commands/git.d.ts +0 -0
- package/dist/cli/commands/git.d.ts.map +0 -0
- package/dist/cli/commands/git.js +0 -0
- package/dist/cli/commands/git.js.map +0 -0
- package/dist/cli/commands/guardrails.d.ts.map +1 -1
- package/dist/cli/commands/guardrails.js +90 -1
- package/dist/cli/commands/guardrails.js.map +1 -1
- package/dist/cli/commands/import.d.ts +0 -0
- package/dist/cli/commands/import.d.ts.map +0 -0
- package/dist/cli/commands/import.js +0 -0
- package/dist/cli/commands/import.js.map +0 -0
- package/dist/cli/commands/init.d.ts +0 -0
- package/dist/cli/commands/init.d.ts.map +0 -0
- package/dist/cli/commands/init.js +0 -0
- package/dist/cli/commands/init.js.map +0 -0
- package/dist/cli/commands/mcp-serve.d.ts +0 -0
- package/dist/cli/commands/mcp-serve.d.ts.map +0 -0
- package/dist/cli/commands/mcp-serve.js +0 -0
- package/dist/cli/commands/mcp-serve.js.map +0 -0
- package/dist/cli/commands/query.d.ts +0 -0
- package/dist/cli/commands/query.d.ts.map +0 -0
- package/dist/cli/commands/query.js +0 -0
- package/dist/cli/commands/query.js.map +0 -0
- package/dist/cli/commands/reindex.js +4 -4
- package/dist/cli/commands/setup.d.ts +0 -0
- package/dist/cli/commands/setup.d.ts.map +0 -0
- package/dist/cli/commands/setup.js +0 -0
- package/dist/cli/commands/setup.js.map +0 -0
- package/dist/cli/commands/start.d.ts +0 -0
- package/dist/cli/commands/start.d.ts.map +0 -0
- package/dist/cli/commands/start.js +0 -0
- package/dist/cli/commands/start.js.map +0 -0
- package/dist/cli/commands/status.d.ts +0 -0
- package/dist/cli/commands/status.d.ts.map +0 -0
- package/dist/cli/commands/status.js +0 -0
- package/dist/cli/commands/status.js.map +0 -0
- package/dist/cli/commands/stop.d.ts +0 -0
- package/dist/cli/commands/stop.d.ts.map +0 -0
- package/dist/cli/commands/stop.js +0 -0
- package/dist/cli/commands/stop.js.map +0 -0
- package/dist/cli/commands/visualize.d.ts +0 -0
- package/dist/cli/commands/visualize.d.ts.map +0 -0
- package/dist/cli/commands/visualize.js +0 -0
- package/dist/cli/commands/visualize.js.map +0 -0
- package/dist/cli/index.d.ts +0 -0
- package/dist/cli/index.d.ts.map +0 -0
- package/dist/cli/index.js +0 -0
- package/dist/cli/index.js.map +0 -0
- package/dist/db/index.d.ts +16 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +325 -196
- package/dist/db/index.js.map +1 -1
- package/dist/db/schema.d.ts +0 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +247 -238
- package/dist/db/schema.js.map +1 -1
- package/dist/extractor/index.d.ts +0 -0
- package/dist/extractor/index.d.ts.map +0 -0
- package/dist/extractor/index.js +0 -0
- package/dist/extractor/index.js.map +0 -0
- package/dist/git/extractor.d.ts +0 -0
- package/dist/git/extractor.d.ts.map +0 -0
- package/dist/git/extractor.js +0 -0
- package/dist/git/extractor.js.map +0 -0
- package/dist/git/hooks.d.ts +0 -0
- package/dist/git/hooks.d.ts.map +0 -0
- package/dist/git/hooks.js +0 -0
- package/dist/git/hooks.js.map +0 -0
- package/dist/git/index.d.ts +0 -0
- package/dist/git/index.d.ts.map +0 -0
- package/dist/git/index.js +0 -0
- package/dist/git/index.js.map +0 -0
- package/dist/guardrails/enforcer.d.ts +3 -2
- package/dist/guardrails/enforcer.d.ts.map +1 -1
- package/dist/guardrails/enforcer.js +30 -3
- package/dist/guardrails/enforcer.js.map +1 -1
- package/dist/guardrails/index.d.ts +2 -0
- package/dist/guardrails/index.d.ts.map +1 -1
- package/dist/guardrails/index.js +4 -0
- package/dist/guardrails/index.js.map +1 -1
- package/dist/guardrails/vindication-checker.d.ts +24 -0
- package/dist/guardrails/vindication-checker.d.ts.map +1 -0
- package/dist/guardrails/vindication-checker.js +209 -0
- package/dist/guardrails/vindication-checker.js.map +1 -0
- package/dist/guardrails/vindication-queue.d.ts +63 -0
- package/dist/guardrails/vindication-queue.d.ts.map +1 -0
- package/dist/guardrails/vindication-queue.js +98 -0
- package/dist/guardrails/vindication-queue.js.map +1 -0
- package/dist/indexer/index.d.ts +0 -0
- package/dist/indexer/index.d.ts.map +0 -0
- package/dist/indexer/index.js +0 -0
- package/dist/indexer/index.js.map +0 -0
- package/dist/indexer/parsers/base.d.ts +0 -0
- package/dist/indexer/parsers/base.d.ts.map +0 -0
- package/dist/indexer/parsers/base.js +0 -0
- package/dist/indexer/parsers/base.js.map +0 -0
- package/dist/indexer/parsers/cpp.d.ts +0 -0
- package/dist/indexer/parsers/cpp.d.ts.map +0 -0
- package/dist/indexer/parsers/cpp.js +0 -0
- package/dist/indexer/parsers/cpp.js.map +0 -0
- package/dist/indexer/parsers/go.d.ts +0 -0
- package/dist/indexer/parsers/go.d.ts.map +0 -0
- package/dist/indexer/parsers/go.js +0 -0
- package/dist/indexer/parsers/go.js.map +0 -0
- package/dist/indexer/parsers/java.d.ts +0 -0
- package/dist/indexer/parsers/java.d.ts.map +0 -0
- package/dist/indexer/parsers/java.js +0 -0
- package/dist/indexer/parsers/java.js.map +0 -0
- package/dist/indexer/parsers/javascript.d.ts +0 -0
- package/dist/indexer/parsers/javascript.d.ts.map +0 -0
- package/dist/indexer/parsers/javascript.js +0 -0
- package/dist/indexer/parsers/javascript.js.map +0 -0
- package/dist/indexer/parsers/kotlin.d.ts +0 -0
- package/dist/indexer/parsers/kotlin.d.ts.map +0 -0
- package/dist/indexer/parsers/kotlin.js +0 -0
- package/dist/indexer/parsers/kotlin.js.map +0 -0
- package/dist/indexer/parsers/php.d.ts +0 -0
- package/dist/indexer/parsers/php.d.ts.map +0 -0
- package/dist/indexer/parsers/php.js +0 -0
- package/dist/indexer/parsers/php.js.map +0 -0
- package/dist/indexer/parsers/python.d.ts +0 -0
- package/dist/indexer/parsers/python.d.ts.map +0 -0
- package/dist/indexer/parsers/python.js +0 -0
- package/dist/indexer/parsers/python.js.map +0 -0
- package/dist/indexer/parsers/ruby.d.ts +0 -0
- package/dist/indexer/parsers/ruby.d.ts.map +0 -0
- package/dist/indexer/parsers/ruby.js +0 -0
- package/dist/indexer/parsers/ruby.js.map +0 -0
- package/dist/indexer/parsers/rust.d.ts +0 -0
- package/dist/indexer/parsers/rust.d.ts.map +0 -0
- package/dist/indexer/parsers/rust.js +0 -0
- package/dist/indexer/parsers/rust.js.map +0 -0
- package/dist/indexer/watcher-daemon.d.ts +0 -0
- package/dist/indexer/watcher-daemon.d.ts.map +0 -0
- package/dist/indexer/watcher-daemon.js +10 -0
- package/dist/indexer/watcher-daemon.js.map +1 -1
- package/dist/indexer/watcher.d.ts +2 -0
- package/dist/indexer/watcher.d.ts.map +1 -1
- package/dist/indexer/watcher.js +8 -0
- package/dist/indexer/watcher.js.map +1 -1
- package/dist/mcp/server.d.ts +0 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +176 -274
- package/dist/mcp/server.js.map +1 -1
- package/dist/proxy/interceptor-mockttp.d.ts +0 -0
- package/dist/proxy/interceptor-mockttp.d.ts.map +1 -1
- package/dist/proxy/interceptor-mockttp.js +4 -2
- package/dist/proxy/interceptor-mockttp.js.map +1 -1
- package/dist/proxy/proxy-daemon.d.ts +0 -0
- package/dist/proxy/proxy-daemon.d.ts.map +0 -0
- package/dist/proxy/proxy-daemon.js +0 -0
- package/dist/proxy/proxy-daemon.js.map +0 -0
- package/dist/query/index.d.ts +0 -0
- package/dist/query/index.d.ts.map +0 -0
- package/dist/query/index.js +0 -0
- package/dist/query/index.js.map +0 -0
- package/dist/types/index.d.ts +38 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -0
- package/dist/types/index.js.map +0 -0
- package/dist/visualize/index.d.ts +0 -0
- package/dist/visualize/index.d.ts.map +0 -0
- package/dist/visualize/index.js +0 -0
- package/dist/visualize/index.js.map +0 -0
- package/dist/visualize/server.d.ts +0 -0
- package/dist/visualize/server.d.ts.map +0 -0
- package/dist/visualize/server.js +0 -0
- package/dist/visualize/server.js.map +0 -0
- package/dist/visualize/template.d.ts +0 -0
- package/dist/visualize/template.d.ts.map +0 -0
- package/dist/visualize/template.js +0 -0
- package/dist/visualize/template.js.map +0 -0
- package/package.json +16 -5
- package/dist/cli/commands/hook-session-end.d.ts +0 -7
- package/dist/cli/commands/hook-session-end.d.ts.map +0 -1
- package/dist/cli/commands/hook-session-end.js +0 -109
- package/dist/cli/commands/hook-session-end.js.map +0 -1
- package/dist/cli/commands/hook-session-start.d.ts +0 -7
- package/dist/cli/commands/hook-session-start.d.ts.map +0 -1
- package/dist/cli/commands/hook-session-start.js +0 -116
- package/dist/cli/commands/hook-session-start.js.map +0 -1
package/dist/db/index.js
CHANGED
|
@@ -71,13 +71,13 @@ export function getAllProjects() {
|
|
|
71
71
|
// File operations
|
|
72
72
|
export function upsertFile(projectId, path, hash) {
|
|
73
73
|
const db = getDb();
|
|
74
|
-
const stmt = db.prepare(`
|
|
75
|
-
INSERT INTO files (project_id, path, hash, last_indexed)
|
|
76
|
-
VALUES (?, ?, ?, datetime('now'))
|
|
77
|
-
ON CONFLICT(project_id, path) DO UPDATE SET
|
|
78
|
-
hash = excluded.hash,
|
|
79
|
-
last_indexed = datetime('now')
|
|
80
|
-
RETURNING *
|
|
74
|
+
const stmt = db.prepare(`
|
|
75
|
+
INSERT INTO files (project_id, path, hash, last_indexed)
|
|
76
|
+
VALUES (?, ?, ?, datetime('now'))
|
|
77
|
+
ON CONFLICT(project_id, path) DO UPDATE SET
|
|
78
|
+
hash = excluded.hash,
|
|
79
|
+
last_indexed = datetime('now')
|
|
80
|
+
RETURNING *
|
|
81
81
|
`);
|
|
82
82
|
return stmt.get(projectId, path, hash);
|
|
83
83
|
}
|
|
@@ -100,10 +100,10 @@ export function getProjectFiles(projectId) {
|
|
|
100
100
|
// Structure operations
|
|
101
101
|
export function insertStructure(fileId, type, name, lineStart, lineEnd, signature, rawContent, metadata = {}) {
|
|
102
102
|
const db = getDb();
|
|
103
|
-
const stmt = db.prepare(`
|
|
104
|
-
INSERT INTO structures (file_id, type, name, line_start, line_end, signature, raw_content, metadata)
|
|
105
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
106
|
-
RETURNING *
|
|
103
|
+
const stmt = db.prepare(`
|
|
104
|
+
INSERT INTO structures (file_id, type, name, line_start, line_end, signature, raw_content, metadata)
|
|
105
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
106
|
+
RETURNING *
|
|
107
107
|
`);
|
|
108
108
|
return stmt.get(fileId, type, name, lineStart, lineEnd, signature, rawContent, JSON.stringify(metadata));
|
|
109
109
|
}
|
|
@@ -114,30 +114,30 @@ export function deleteFileStructures(fileId) {
|
|
|
114
114
|
export function searchStructures(query, limit = 20, projectId) {
|
|
115
115
|
const db = getDb();
|
|
116
116
|
if (projectId) {
|
|
117
|
-
return db.prepare(`
|
|
118
|
-
SELECT s.* FROM structures s
|
|
119
|
-
JOIN structures_fts fts ON s.id = fts.rowid
|
|
120
|
-
JOIN files f ON s.file_id = f.id
|
|
121
|
-
WHERE structures_fts MATCH ? AND f.project_id = ?
|
|
122
|
-
ORDER BY rank
|
|
123
|
-
LIMIT ?
|
|
117
|
+
return db.prepare(`
|
|
118
|
+
SELECT s.* FROM structures s
|
|
119
|
+
JOIN structures_fts fts ON s.id = fts.rowid
|
|
120
|
+
JOIN files f ON s.file_id = f.id
|
|
121
|
+
WHERE structures_fts MATCH ? AND f.project_id = ?
|
|
122
|
+
ORDER BY rank
|
|
123
|
+
LIMIT ?
|
|
124
124
|
`).all(query, projectId, limit);
|
|
125
125
|
}
|
|
126
|
-
return db.prepare(`
|
|
127
|
-
SELECT s.* FROM structures s
|
|
128
|
-
JOIN structures_fts fts ON s.id = fts.rowid
|
|
129
|
-
WHERE structures_fts MATCH ?
|
|
130
|
-
ORDER BY rank
|
|
131
|
-
LIMIT ?
|
|
126
|
+
return db.prepare(`
|
|
127
|
+
SELECT s.* FROM structures s
|
|
128
|
+
JOIN structures_fts fts ON s.id = fts.rowid
|
|
129
|
+
WHERE structures_fts MATCH ?
|
|
130
|
+
ORDER BY rank
|
|
131
|
+
LIMIT ?
|
|
132
132
|
`).all(query, limit);
|
|
133
133
|
}
|
|
134
134
|
export function getStructuresByName(name, projectId) {
|
|
135
135
|
const db = getDb();
|
|
136
136
|
if (projectId) {
|
|
137
|
-
return db.prepare(`
|
|
138
|
-
SELECT s.* FROM structures s
|
|
139
|
-
JOIN files f ON s.file_id = f.id
|
|
140
|
-
WHERE s.name = ? AND f.project_id = ?
|
|
137
|
+
return db.prepare(`
|
|
138
|
+
SELECT s.* FROM structures s
|
|
139
|
+
JOIN files f ON s.file_id = f.id
|
|
140
|
+
WHERE s.name = ? AND f.project_id = ?
|
|
141
141
|
`).all(name, projectId);
|
|
142
142
|
}
|
|
143
143
|
return db.prepare('SELECT * FROM structures WHERE name = ?').all(name);
|
|
@@ -157,39 +157,39 @@ export function findProjectForPath(targetPath) {
|
|
|
157
157
|
// Conversation operations
|
|
158
158
|
export function insertConversation(rawContent, projectId = null, model = null, tool = null, summary = null) {
|
|
159
159
|
const db = getDb();
|
|
160
|
-
const stmt = db.prepare(`
|
|
161
|
-
INSERT INTO conversations (project_id, model, tool, summary, raw_content)
|
|
162
|
-
VALUES (?, ?, ?, ?, ?)
|
|
163
|
-
RETURNING *
|
|
160
|
+
const stmt = db.prepare(`
|
|
161
|
+
INSERT INTO conversations (project_id, model, tool, summary, raw_content)
|
|
162
|
+
VALUES (?, ?, ?, ?, ?)
|
|
163
|
+
RETURNING *
|
|
164
164
|
`);
|
|
165
165
|
return stmt.get(projectId, model, tool, summary, rawContent);
|
|
166
166
|
}
|
|
167
167
|
export function searchConversations(query, limit = 20, projectId) {
|
|
168
168
|
const db = getDb();
|
|
169
169
|
if (projectId) {
|
|
170
|
-
return db.prepare(`
|
|
171
|
-
SELECT c.* FROM conversations c
|
|
172
|
-
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
173
|
-
WHERE conversations_fts MATCH ? AND c.project_id = ?
|
|
174
|
-
ORDER BY rank
|
|
175
|
-
LIMIT ?
|
|
170
|
+
return db.prepare(`
|
|
171
|
+
SELECT c.* FROM conversations c
|
|
172
|
+
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
173
|
+
WHERE conversations_fts MATCH ? AND c.project_id = ?
|
|
174
|
+
ORDER BY rank
|
|
175
|
+
LIMIT ?
|
|
176
176
|
`).all(query, projectId, limit);
|
|
177
177
|
}
|
|
178
|
-
return db.prepare(`
|
|
179
|
-
SELECT c.* FROM conversations c
|
|
180
|
-
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
181
|
-
WHERE conversations_fts MATCH ?
|
|
182
|
-
ORDER BY rank
|
|
183
|
-
LIMIT ?
|
|
178
|
+
return db.prepare(`
|
|
179
|
+
SELECT c.* FROM conversations c
|
|
180
|
+
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
181
|
+
WHERE conversations_fts MATCH ?
|
|
182
|
+
ORDER BY rank
|
|
183
|
+
LIMIT ?
|
|
184
184
|
`).all(query, limit);
|
|
185
185
|
}
|
|
186
186
|
// Link operations
|
|
187
187
|
export function createLink(sourceType, sourceId, targetType, targetId, linkType) {
|
|
188
188
|
const db = getDb();
|
|
189
|
-
const stmt = db.prepare(`
|
|
190
|
-
INSERT OR IGNORE INTO links (source_type, source_id, target_type, target_id, link_type)
|
|
191
|
-
VALUES (?, ?, ?, ?, ?)
|
|
192
|
-
RETURNING *
|
|
189
|
+
const stmt = db.prepare(`
|
|
190
|
+
INSERT OR IGNORE INTO links (source_type, source_id, target_type, target_id, link_type)
|
|
191
|
+
VALUES (?, ?, ?, ?, ?)
|
|
192
|
+
RETURNING *
|
|
193
193
|
`);
|
|
194
194
|
return stmt.get(sourceType, sourceId, targetType, targetId, linkType);
|
|
195
195
|
}
|
|
@@ -204,10 +204,10 @@ export function getLinksTo(targetType, targetId) {
|
|
|
204
204
|
// Extraction operations
|
|
205
205
|
export function insertExtraction(conversationId, type, content, metadata = {}) {
|
|
206
206
|
const db = getDb();
|
|
207
|
-
const stmt = db.prepare(`
|
|
208
|
-
INSERT INTO extractions (conversation_id, type, content, metadata)
|
|
209
|
-
VALUES (?, ?, ?, ?)
|
|
210
|
-
RETURNING *
|
|
207
|
+
const stmt = db.prepare(`
|
|
208
|
+
INSERT INTO extractions (conversation_id, type, content, metadata)
|
|
209
|
+
VALUES (?, ?, ?, ?)
|
|
210
|
+
RETURNING *
|
|
211
211
|
`);
|
|
212
212
|
return stmt.get(conversationId, type, content, JSON.stringify(metadata));
|
|
213
213
|
}
|
|
@@ -223,30 +223,30 @@ export function searchExtractions(query, limit = 20, projectId) {
|
|
|
223
223
|
const db = getDb();
|
|
224
224
|
const searchTerm = `%${query}%`;
|
|
225
225
|
if (projectId) {
|
|
226
|
-
return db.prepare(`
|
|
227
|
-
SELECT e.* FROM extractions e
|
|
228
|
-
JOIN conversations c ON e.conversation_id = c.id
|
|
229
|
-
WHERE e.content LIKE ? AND c.project_id = ?
|
|
230
|
-
ORDER BY e.id DESC
|
|
231
|
-
LIMIT ?
|
|
226
|
+
return db.prepare(`
|
|
227
|
+
SELECT e.* FROM extractions e
|
|
228
|
+
JOIN conversations c ON e.conversation_id = c.id
|
|
229
|
+
WHERE e.content LIKE ? AND c.project_id = ?
|
|
230
|
+
ORDER BY e.id DESC
|
|
231
|
+
LIMIT ?
|
|
232
232
|
`).all(searchTerm, projectId, limit);
|
|
233
233
|
}
|
|
234
|
-
return db.prepare(`
|
|
235
|
-
SELECT * FROM extractions
|
|
236
|
-
WHERE content LIKE ?
|
|
237
|
-
ORDER BY id DESC
|
|
238
|
-
LIMIT ?
|
|
234
|
+
return db.prepare(`
|
|
235
|
+
SELECT * FROM extractions
|
|
236
|
+
WHERE content LIKE ?
|
|
237
|
+
ORDER BY id DESC
|
|
238
|
+
LIMIT ?
|
|
239
239
|
`).all(searchTerm, limit);
|
|
240
240
|
}
|
|
241
241
|
export function isDuplicateExtraction(content, projectId, windowSeconds = 300) {
|
|
242
242
|
const db = getDb();
|
|
243
243
|
// Check for duplicate extraction content within the last N seconds
|
|
244
|
-
const stmt = db.prepare(`
|
|
245
|
-
SELECT COUNT(*) as count FROM extractions e
|
|
246
|
-
JOIN conversations c ON e.conversation_id = c.id
|
|
247
|
-
WHERE e.content = ?
|
|
248
|
-
AND (c.project_id = ? OR (c.project_id IS NULL AND ? IS NULL))
|
|
249
|
-
AND datetime(c.timestamp) > datetime('now', '-' || ? || ' seconds')
|
|
244
|
+
const stmt = db.prepare(`
|
|
245
|
+
SELECT COUNT(*) as count FROM extractions e
|
|
246
|
+
JOIN conversations c ON e.conversation_id = c.id
|
|
247
|
+
WHERE e.content = ?
|
|
248
|
+
AND (c.project_id = ? OR (c.project_id IS NULL AND ? IS NULL))
|
|
249
|
+
AND datetime(c.timestamp) > datetime('now', '-' || ? || ' seconds')
|
|
250
250
|
`);
|
|
251
251
|
const result = stmt.get(content.trim(), projectId, projectId, windowSeconds);
|
|
252
252
|
return result.count > 0;
|
|
@@ -280,97 +280,97 @@ export function getConversationById(id) {
|
|
|
280
280
|
// Get full conversations for a project (for long-term memory)
|
|
281
281
|
export function getFullConversations(projectId, limit = 50, offset = 0) {
|
|
282
282
|
const db = getDb();
|
|
283
|
-
return db.prepare(`
|
|
284
|
-
SELECT * FROM conversations
|
|
285
|
-
WHERE project_id = ?
|
|
286
|
-
ORDER BY timestamp DESC
|
|
287
|
-
LIMIT ? OFFSET ?
|
|
283
|
+
return db.prepare(`
|
|
284
|
+
SELECT * FROM conversations
|
|
285
|
+
WHERE project_id = ?
|
|
286
|
+
ORDER BY timestamp DESC
|
|
287
|
+
LIMIT ? OFFSET ?
|
|
288
288
|
`).all(projectId, limit, offset);
|
|
289
289
|
}
|
|
290
290
|
// Get recent conversations (optionally scoped to project)
|
|
291
291
|
export function getRecentConversations(limit = 10, projectId) {
|
|
292
292
|
const db = getDb();
|
|
293
293
|
if (projectId) {
|
|
294
|
-
return db.prepare(`
|
|
295
|
-
SELECT * FROM conversations
|
|
296
|
-
WHERE project_id = ?
|
|
297
|
-
ORDER BY timestamp DESC
|
|
298
|
-
LIMIT ?
|
|
294
|
+
return db.prepare(`
|
|
295
|
+
SELECT * FROM conversations
|
|
296
|
+
WHERE project_id = ?
|
|
297
|
+
ORDER BY timestamp DESC
|
|
298
|
+
LIMIT ?
|
|
299
299
|
`).all(projectId, limit);
|
|
300
300
|
}
|
|
301
|
-
return db.prepare(`
|
|
302
|
-
SELECT * FROM conversations
|
|
303
|
-
ORDER BY timestamp DESC
|
|
304
|
-
LIMIT ?
|
|
301
|
+
return db.prepare(`
|
|
302
|
+
SELECT * FROM conversations
|
|
303
|
+
ORDER BY timestamp DESC
|
|
304
|
+
LIMIT ?
|
|
305
305
|
`).all(limit);
|
|
306
306
|
}
|
|
307
307
|
// Search conversations and return full content
|
|
308
308
|
export function searchFullConversations(query, limit = 20, projectId) {
|
|
309
309
|
const db = getDb();
|
|
310
310
|
if (projectId) {
|
|
311
|
-
return db.prepare(`
|
|
312
|
-
SELECT c.* FROM conversations c
|
|
313
|
-
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
314
|
-
WHERE conversations_fts MATCH ? AND c.project_id = ?
|
|
315
|
-
ORDER BY rank
|
|
316
|
-
LIMIT ?
|
|
311
|
+
return db.prepare(`
|
|
312
|
+
SELECT c.* FROM conversations c
|
|
313
|
+
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
314
|
+
WHERE conversations_fts MATCH ? AND c.project_id = ?
|
|
315
|
+
ORDER BY rank
|
|
316
|
+
LIMIT ?
|
|
317
317
|
`).all(query, projectId, limit);
|
|
318
318
|
}
|
|
319
|
-
return db.prepare(`
|
|
320
|
-
SELECT c.* FROM conversations c
|
|
321
|
-
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
322
|
-
WHERE conversations_fts MATCH ?
|
|
323
|
-
ORDER BY rank
|
|
324
|
-
LIMIT ?
|
|
319
|
+
return db.prepare(`
|
|
320
|
+
SELECT c.* FROM conversations c
|
|
321
|
+
JOIN conversations_fts fts ON c.id = fts.rowid
|
|
322
|
+
WHERE conversations_fts MATCH ?
|
|
323
|
+
ORDER BY rank
|
|
324
|
+
LIMIT ?
|
|
325
325
|
`).all(query, limit);
|
|
326
326
|
}
|
|
327
327
|
// Get all structures for a project with file paths
|
|
328
328
|
export function getAllProjectStructures(projectId) {
|
|
329
329
|
const db = getDb();
|
|
330
|
-
return db.prepare(`
|
|
331
|
-
SELECT s.*, f.path as file_path
|
|
332
|
-
FROM structures s
|
|
333
|
-
JOIN files f ON s.file_id = f.id
|
|
334
|
-
WHERE f.project_id = ?
|
|
335
|
-
ORDER BY f.path, s.line_start
|
|
330
|
+
return db.prepare(`
|
|
331
|
+
SELECT s.*, f.path as file_path
|
|
332
|
+
FROM structures s
|
|
333
|
+
JOIN files f ON s.file_id = f.id
|
|
334
|
+
WHERE f.project_id = ?
|
|
335
|
+
ORDER BY f.path, s.line_start
|
|
336
336
|
`).all(projectId);
|
|
337
337
|
}
|
|
338
338
|
// Get all links for a project
|
|
339
339
|
export function getAllProjectLinks(projectId) {
|
|
340
340
|
const db = getDb();
|
|
341
|
-
return db.prepare(`
|
|
342
|
-
SELECT DISTINCT l.* FROM links l
|
|
343
|
-
LEFT JOIN structures s ON l.source_type = 'structure' AND l.source_id = s.id
|
|
344
|
-
LEFT JOIN files f ON s.file_id = f.id
|
|
345
|
-
LEFT JOIN conversations c ON l.source_type = 'conversation' AND l.source_id = c.id
|
|
346
|
-
WHERE f.project_id = ? OR c.project_id = ?
|
|
341
|
+
return db.prepare(`
|
|
342
|
+
SELECT DISTINCT l.* FROM links l
|
|
343
|
+
LEFT JOIN structures s ON l.source_type = 'structure' AND l.source_id = s.id
|
|
344
|
+
LEFT JOIN files f ON s.file_id = f.id
|
|
345
|
+
LEFT JOIN conversations c ON l.source_type = 'conversation' AND l.source_id = c.id
|
|
346
|
+
WHERE f.project_id = ? OR c.project_id = ?
|
|
347
347
|
`).all(projectId, projectId);
|
|
348
348
|
}
|
|
349
349
|
// Get all extractions for a project
|
|
350
350
|
export function getAllProjectExtractions(projectId) {
|
|
351
351
|
const db = getDb();
|
|
352
|
-
return db.prepare(`
|
|
353
|
-
SELECT e.* FROM extractions e
|
|
354
|
-
JOIN conversations c ON e.conversation_id = c.id
|
|
355
|
-
WHERE c.project_id = ?
|
|
356
|
-
ORDER BY c.timestamp DESC
|
|
352
|
+
return db.prepare(`
|
|
353
|
+
SELECT e.* FROM extractions e
|
|
354
|
+
JOIN conversations c ON e.conversation_id = c.id
|
|
355
|
+
WHERE c.project_id = ?
|
|
356
|
+
ORDER BY c.timestamp DESC
|
|
357
357
|
`).all(projectId);
|
|
358
358
|
}
|
|
359
359
|
// ============ Git Operations ============
|
|
360
360
|
// Commit operations
|
|
361
361
|
export function upsertCommit(projectId, hash, shortHash, authorName, authorEmail, timestamp, subject, body, parentHashes = []) {
|
|
362
362
|
const db = getDb();
|
|
363
|
-
const stmt = db.prepare(`
|
|
364
|
-
INSERT INTO commits (project_id, hash, short_hash, author_name, author_email, timestamp, subject, body, parent_hashes)
|
|
365
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
366
|
-
ON CONFLICT(project_id, hash) DO UPDATE SET
|
|
367
|
-
short_hash = excluded.short_hash,
|
|
368
|
-
author_name = excluded.author_name,
|
|
369
|
-
author_email = excluded.author_email,
|
|
370
|
-
subject = excluded.subject,
|
|
371
|
-
body = excluded.body,
|
|
372
|
-
parent_hashes = excluded.parent_hashes
|
|
373
|
-
RETURNING *
|
|
363
|
+
const stmt = db.prepare(`
|
|
364
|
+
INSERT INTO commits (project_id, hash, short_hash, author_name, author_email, timestamp, subject, body, parent_hashes)
|
|
365
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
366
|
+
ON CONFLICT(project_id, hash) DO UPDATE SET
|
|
367
|
+
short_hash = excluded.short_hash,
|
|
368
|
+
author_name = excluded.author_name,
|
|
369
|
+
author_email = excluded.author_email,
|
|
370
|
+
subject = excluded.subject,
|
|
371
|
+
body = excluded.body,
|
|
372
|
+
parent_hashes = excluded.parent_hashes
|
|
373
|
+
RETURNING *
|
|
374
374
|
`);
|
|
375
375
|
return stmt.get(projectId, hash, shortHash, authorName, authorEmail, timestamp, subject, body, JSON.stringify(parentHashes));
|
|
376
376
|
}
|
|
@@ -385,36 +385,36 @@ export function getCommitById(id) {
|
|
|
385
385
|
export function searchCommits(query, limit = 20, projectId) {
|
|
386
386
|
const db = getDb();
|
|
387
387
|
if (projectId) {
|
|
388
|
-
return db.prepare(`
|
|
389
|
-
SELECT c.* FROM commits c
|
|
390
|
-
JOIN commits_fts fts ON c.id = fts.rowid
|
|
391
|
-
WHERE commits_fts MATCH ? AND c.project_id = ?
|
|
392
|
-
ORDER BY rank
|
|
393
|
-
LIMIT ?
|
|
388
|
+
return db.prepare(`
|
|
389
|
+
SELECT c.* FROM commits c
|
|
390
|
+
JOIN commits_fts fts ON c.id = fts.rowid
|
|
391
|
+
WHERE commits_fts MATCH ? AND c.project_id = ?
|
|
392
|
+
ORDER BY rank
|
|
393
|
+
LIMIT ?
|
|
394
394
|
`).all(query, projectId, limit);
|
|
395
395
|
}
|
|
396
|
-
return db.prepare(`
|
|
397
|
-
SELECT c.* FROM commits c
|
|
398
|
-
JOIN commits_fts fts ON c.id = fts.rowid
|
|
399
|
-
WHERE commits_fts MATCH ?
|
|
400
|
-
ORDER BY rank
|
|
401
|
-
LIMIT ?
|
|
396
|
+
return db.prepare(`
|
|
397
|
+
SELECT c.* FROM commits c
|
|
398
|
+
JOIN commits_fts fts ON c.id = fts.rowid
|
|
399
|
+
WHERE commits_fts MATCH ?
|
|
400
|
+
ORDER BY rank
|
|
401
|
+
LIMIT ?
|
|
402
402
|
`).all(query, limit);
|
|
403
403
|
}
|
|
404
404
|
export function getRecentCommits(projectId, limit = 50) {
|
|
405
405
|
const db = getDb();
|
|
406
|
-
return db.prepare(`
|
|
407
|
-
SELECT * FROM commits WHERE project_id = ?
|
|
408
|
-
ORDER BY timestamp DESC LIMIT ?
|
|
406
|
+
return db.prepare(`
|
|
407
|
+
SELECT * FROM commits WHERE project_id = ?
|
|
408
|
+
ORDER BY timestamp DESC LIMIT ?
|
|
409
409
|
`).all(projectId, limit);
|
|
410
410
|
}
|
|
411
411
|
// Commit link operations
|
|
412
412
|
export function createCommitLink(commitId, targetType, targetId, linkType) {
|
|
413
413
|
const db = getDb();
|
|
414
|
-
const stmt = db.prepare(`
|
|
415
|
-
INSERT OR IGNORE INTO commit_links (commit_id, target_type, target_id, link_type)
|
|
416
|
-
VALUES (?, ?, ?, ?)
|
|
417
|
-
RETURNING *
|
|
414
|
+
const stmt = db.prepare(`
|
|
415
|
+
INSERT OR IGNORE INTO commit_links (commit_id, target_type, target_id, link_type)
|
|
416
|
+
VALUES (?, ?, ?, ?)
|
|
417
|
+
RETURNING *
|
|
418
418
|
`);
|
|
419
419
|
return stmt.get(commitId, targetType, targetId, linkType);
|
|
420
420
|
}
|
|
@@ -428,31 +428,31 @@ export function getLinksToCommit(targetType, targetId) {
|
|
|
428
428
|
}
|
|
429
429
|
export function getCommitsForStructure(structureId) {
|
|
430
430
|
const db = getDb();
|
|
431
|
-
return db.prepare(`
|
|
432
|
-
SELECT c.* FROM commits c
|
|
433
|
-
JOIN commit_links cl ON c.id = cl.commit_id
|
|
434
|
-
WHERE cl.target_type = 'structure' AND cl.target_id = ?
|
|
435
|
-
ORDER BY c.timestamp DESC
|
|
431
|
+
return db.prepare(`
|
|
432
|
+
SELECT c.* FROM commits c
|
|
433
|
+
JOIN commit_links cl ON c.id = cl.commit_id
|
|
434
|
+
WHERE cl.target_type = 'structure' AND cl.target_id = ?
|
|
435
|
+
ORDER BY c.timestamp DESC
|
|
436
436
|
`).all(structureId);
|
|
437
437
|
}
|
|
438
438
|
export function getCommitsForExtraction(extractionId) {
|
|
439
439
|
const db = getDb();
|
|
440
|
-
return db.prepare(`
|
|
441
|
-
SELECT c.* FROM commits c
|
|
442
|
-
JOIN commit_links cl ON c.id = cl.commit_id
|
|
443
|
-
WHERE cl.target_type = 'extraction' AND cl.target_id = ?
|
|
444
|
-
ORDER BY c.timestamp DESC
|
|
440
|
+
return db.prepare(`
|
|
441
|
+
SELECT c.* FROM commits c
|
|
442
|
+
JOIN commit_links cl ON c.id = cl.commit_id
|
|
443
|
+
WHERE cl.target_type = 'extraction' AND cl.target_id = ?
|
|
444
|
+
ORDER BY c.timestamp DESC
|
|
445
445
|
`).all(extractionId);
|
|
446
446
|
}
|
|
447
447
|
// Update structure authorship
|
|
448
448
|
export function updateStructureAuthorship(structureId, author, authorEmail, commitHash) {
|
|
449
449
|
const db = getDb();
|
|
450
|
-
db.prepare(`
|
|
451
|
-
UPDATE structures SET
|
|
452
|
-
last_author = ?,
|
|
453
|
-
last_author_email = ?,
|
|
454
|
-
last_commit_hash = ?
|
|
455
|
-
WHERE id = ?
|
|
450
|
+
db.prepare(`
|
|
451
|
+
UPDATE structures SET
|
|
452
|
+
last_author = ?,
|
|
453
|
+
last_author_email = ?,
|
|
454
|
+
last_commit_hash = ?
|
|
455
|
+
WHERE id = ?
|
|
456
456
|
`).run(author, authorEmail, commitHash, structureId);
|
|
457
457
|
}
|
|
458
458
|
// Get uncommitted decisions (extractions created since last commit)
|
|
@@ -460,38 +460,38 @@ export function getUncommittedExtractions(projectId, sinceCommitHash) {
|
|
|
460
460
|
const db = getDb();
|
|
461
461
|
if (sinceCommitHash) {
|
|
462
462
|
// Get extractions created after the specified commit's timestamp
|
|
463
|
-
return db.prepare(`
|
|
464
|
-
SELECT e.* FROM extractions e
|
|
465
|
-
JOIN conversations c ON e.conversation_id = c.id
|
|
466
|
-
WHERE c.project_id = ?
|
|
467
|
-
AND c.timestamp > (
|
|
468
|
-
SELECT timestamp FROM commits WHERE project_id = ? AND hash = ?
|
|
469
|
-
)
|
|
470
|
-
AND e.id NOT IN (
|
|
471
|
-
SELECT target_id FROM commit_links WHERE target_type = 'extraction'
|
|
472
|
-
)
|
|
473
|
-
ORDER BY c.timestamp DESC
|
|
463
|
+
return db.prepare(`
|
|
464
|
+
SELECT e.* FROM extractions e
|
|
465
|
+
JOIN conversations c ON e.conversation_id = c.id
|
|
466
|
+
WHERE c.project_id = ?
|
|
467
|
+
AND c.timestamp > (
|
|
468
|
+
SELECT timestamp FROM commits WHERE project_id = ? AND hash = ?
|
|
469
|
+
)
|
|
470
|
+
AND e.id NOT IN (
|
|
471
|
+
SELECT target_id FROM commit_links WHERE target_type = 'extraction'
|
|
472
|
+
)
|
|
473
|
+
ORDER BY c.timestamp DESC
|
|
474
474
|
`).all(projectId, projectId, sinceCommitHash);
|
|
475
475
|
}
|
|
476
476
|
// Get all extractions not linked to any commit
|
|
477
|
-
return db.prepare(`
|
|
478
|
-
SELECT e.* FROM extractions e
|
|
479
|
-
JOIN conversations c ON e.conversation_id = c.id
|
|
480
|
-
WHERE c.project_id = ?
|
|
481
|
-
AND e.id NOT IN (
|
|
482
|
-
SELECT target_id FROM commit_links WHERE target_type = 'extraction'
|
|
483
|
-
)
|
|
484
|
-
ORDER BY c.timestamp DESC
|
|
477
|
+
return db.prepare(`
|
|
478
|
+
SELECT e.* FROM extractions e
|
|
479
|
+
JOIN conversations c ON e.conversation_id = c.id
|
|
480
|
+
WHERE c.project_id = ?
|
|
481
|
+
AND e.id NOT IN (
|
|
482
|
+
SELECT target_id FROM commit_links WHERE target_type = 'extraction'
|
|
483
|
+
)
|
|
484
|
+
ORDER BY c.timestamp DESC
|
|
485
485
|
`).all(projectId);
|
|
486
486
|
}
|
|
487
487
|
// ============ Guardrails Operations (DIK) ============
|
|
488
488
|
// Guardrail CRUD
|
|
489
489
|
export function insertGuardrail(projectId, category, rule, rationale = null, severity = 'warn', source = 'explicit', sourceFile = null) {
|
|
490
490
|
const db = getDb();
|
|
491
|
-
const stmt = db.prepare(`
|
|
492
|
-
INSERT INTO guardrails (project_id, category, rule, rationale, severity, source, source_file)
|
|
493
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
494
|
-
RETURNING *
|
|
491
|
+
const stmt = db.prepare(`
|
|
492
|
+
INSERT INTO guardrails (project_id, category, rule, rationale, severity, source, source_file)
|
|
493
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
494
|
+
RETURNING *
|
|
495
495
|
`);
|
|
496
496
|
return stmt.get(projectId, category, rule, rationale, severity, source, sourceFile);
|
|
497
497
|
}
|
|
@@ -535,10 +535,10 @@ export function deleteGuardrail(id) {
|
|
|
535
535
|
// Guardrail events
|
|
536
536
|
export function insertGuardrailEvent(guardrailId, eventType, context = null, response = null, dikLevel = null) {
|
|
537
537
|
const db = getDb();
|
|
538
|
-
const stmt = db.prepare(`
|
|
539
|
-
INSERT INTO guardrail_events (guardrail_id, event_type, context, response, dik_level)
|
|
540
|
-
VALUES (?, ?, ?, ?, ?)
|
|
541
|
-
RETURNING *
|
|
538
|
+
const stmt = db.prepare(`
|
|
539
|
+
INSERT INTO guardrail_events (guardrail_id, event_type, context, response, dik_level)
|
|
540
|
+
VALUES (?, ?, ?, ?, ?)
|
|
541
|
+
RETURNING *
|
|
542
542
|
`);
|
|
543
543
|
return stmt.get(guardrailId, eventType, context, response, dikLevel);
|
|
544
544
|
}
|
|
@@ -552,11 +552,11 @@ export function getGuardrailEvent(id) {
|
|
|
552
552
|
}
|
|
553
553
|
export function getOverrideEvents(projectId) {
|
|
554
554
|
const db = getDb();
|
|
555
|
-
return db.prepare(`
|
|
556
|
-
SELECT e.* FROM guardrail_events e
|
|
557
|
-
JOIN guardrails g ON e.guardrail_id = g.id
|
|
558
|
-
WHERE g.project_id = ? AND e.event_type = 'overridden'
|
|
559
|
-
ORDER BY e.timestamp DESC
|
|
555
|
+
return db.prepare(`
|
|
556
|
+
SELECT e.* FROM guardrail_events e
|
|
557
|
+
JOIN guardrails g ON e.guardrail_id = g.id
|
|
558
|
+
WHERE g.project_id = ? AND e.event_type = 'overridden'
|
|
559
|
+
ORDER BY e.timestamp DESC
|
|
560
560
|
`).all(projectId);
|
|
561
561
|
}
|
|
562
562
|
// Project DIK
|
|
@@ -564,8 +564,8 @@ export function getOrCreateProjectDik(projectId) {
|
|
|
564
564
|
const db = getDb();
|
|
565
565
|
let dik = db.prepare('SELECT * FROM project_dik WHERE project_id = ?').get(projectId);
|
|
566
566
|
if (!dik) {
|
|
567
|
-
dik = db.prepare(`
|
|
568
|
-
INSERT INTO project_dik (project_id) VALUES (?) RETURNING *
|
|
567
|
+
dik = db.prepare(`
|
|
568
|
+
INSERT INTO project_dik (project_id) VALUES (?) RETURNING *
|
|
569
569
|
`).get(projectId);
|
|
570
570
|
}
|
|
571
571
|
return dik;
|
|
@@ -613,10 +613,10 @@ export function incrementDikCounter(projectId, counter) {
|
|
|
613
613
|
// Get guardrail history for a specific rule (for response generation)
|
|
614
614
|
export function getGuardrailHistory(guardrailId) {
|
|
615
615
|
const db = getDb();
|
|
616
|
-
const events = db.prepare(`
|
|
617
|
-
SELECT event_type, COUNT(*) as count FROM guardrail_events
|
|
618
|
-
WHERE guardrail_id = ?
|
|
619
|
-
GROUP BY event_type
|
|
616
|
+
const events = db.prepare(`
|
|
617
|
+
SELECT event_type, COUNT(*) as count FROM guardrail_events
|
|
618
|
+
WHERE guardrail_id = ?
|
|
619
|
+
GROUP BY event_type
|
|
620
620
|
`).all(guardrailId);
|
|
621
621
|
let overrides = 0;
|
|
622
622
|
let vindicated = false;
|
|
@@ -656,4 +656,133 @@ export function isDikManuallySet(projectId) {
|
|
|
656
656
|
// If level is non-default but stats are zero, it's manually set
|
|
657
657
|
return dik.level !== 2 && dik.rules_confirmed === 0 && dik.corrections_made === 0 && dik.overrides_regretted === 0 && dik.conversations === 0;
|
|
658
658
|
}
|
|
659
|
+
// ============ Vindication Operations ============
|
|
660
|
+
// Insert guardrail event with vindication context (enhanced version)
|
|
661
|
+
export function insertGuardrailEventWithContext(guardrailId, eventType, context = null, response = null, dikLevel = null, vindicationContext) {
|
|
662
|
+
const db = getDb();
|
|
663
|
+
if (vindicationContext && eventType === 'overridden') {
|
|
664
|
+
const stmt = db.prepare(`
|
|
665
|
+
INSERT INTO guardrail_events (
|
|
666
|
+
guardrail_id, event_type, context, response, dik_level,
|
|
667
|
+
suggestion, code_context, file_path, line_start, line_end, content_hash, vindication_pending
|
|
668
|
+
)
|
|
669
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
|
|
670
|
+
RETURNING *
|
|
671
|
+
`);
|
|
672
|
+
return stmt.get(guardrailId, eventType, context, response, dikLevel, vindicationContext.suggestion || null, vindicationContext.codeContext || null, vindicationContext.filePath || null, vindicationContext.lineStart || null, vindicationContext.lineEnd || null, vindicationContext.contentHash || null);
|
|
673
|
+
}
|
|
674
|
+
// Fall back to regular insert for non-override events
|
|
675
|
+
return insertGuardrailEvent(guardrailId, eventType, context, response, dikLevel);
|
|
676
|
+
}
|
|
677
|
+
// Get pending vindications for a project
|
|
678
|
+
export function getPendingVindications(projectId) {
|
|
679
|
+
const db = getDb();
|
|
680
|
+
const rows = db.prepare(`
|
|
681
|
+
SELECT
|
|
682
|
+
e.id as eventId,
|
|
683
|
+
e.guardrail_id as guardrailId,
|
|
684
|
+
g.project_id as projectId,
|
|
685
|
+
e.suggestion,
|
|
686
|
+
e.file_path as filePath,
|
|
687
|
+
e.line_start as lineStart,
|
|
688
|
+
e.line_end as lineEnd,
|
|
689
|
+
e.code_context as originalCode,
|
|
690
|
+
e.content_hash as contentHash,
|
|
691
|
+
e.context as reason,
|
|
692
|
+
e.timestamp
|
|
693
|
+
FROM guardrail_events e
|
|
694
|
+
JOIN guardrails g ON e.guardrail_id = g.id
|
|
695
|
+
WHERE g.project_id = ?
|
|
696
|
+
AND e.event_type = 'overridden'
|
|
697
|
+
AND e.vindication_pending = 1
|
|
698
|
+
AND e.suggestion IS NOT NULL
|
|
699
|
+
AND e.file_path IS NOT NULL
|
|
700
|
+
ORDER BY e.timestamp DESC
|
|
701
|
+
`).all(projectId);
|
|
702
|
+
return rows;
|
|
703
|
+
}
|
|
704
|
+
// Get pending vindications for specific files
|
|
705
|
+
export function getPendingVindicationsForFile(projectId, filePath) {
|
|
706
|
+
const db = getDb();
|
|
707
|
+
const rows = db.prepare(`
|
|
708
|
+
SELECT
|
|
709
|
+
e.id as eventId,
|
|
710
|
+
e.guardrail_id as guardrailId,
|
|
711
|
+
g.project_id as projectId,
|
|
712
|
+
e.suggestion,
|
|
713
|
+
e.file_path as filePath,
|
|
714
|
+
e.line_start as lineStart,
|
|
715
|
+
e.line_end as lineEnd,
|
|
716
|
+
e.code_context as originalCode,
|
|
717
|
+
e.content_hash as contentHash,
|
|
718
|
+
e.context as reason,
|
|
719
|
+
e.timestamp
|
|
720
|
+
FROM guardrail_events e
|
|
721
|
+
JOIN guardrails g ON e.guardrail_id = g.id
|
|
722
|
+
WHERE g.project_id = ?
|
|
723
|
+
AND e.file_path = ?
|
|
724
|
+
AND e.event_type = 'overridden'
|
|
725
|
+
AND e.vindication_pending = 1
|
|
726
|
+
AND e.suggestion IS NOT NULL
|
|
727
|
+
ORDER BY e.timestamp DESC
|
|
728
|
+
`).all(projectId, filePath);
|
|
729
|
+
return rows;
|
|
730
|
+
}
|
|
731
|
+
// Mark a vindication as checked (not vindicated)
|
|
732
|
+
export function markVindicationChecked(eventId) {
|
|
733
|
+
const db = getDb();
|
|
734
|
+
db.prepare(`
|
|
735
|
+
UPDATE guardrail_events
|
|
736
|
+
SET vindication_pending = 0, checked_at = datetime('now')
|
|
737
|
+
WHERE id = ?
|
|
738
|
+
`).run(eventId);
|
|
739
|
+
}
|
|
740
|
+
// Mark a vindication as complete (vindicated)
|
|
741
|
+
export function markVindicated(eventId) {
|
|
742
|
+
const db = getDb();
|
|
743
|
+
db.prepare(`
|
|
744
|
+
UPDATE guardrail_events
|
|
745
|
+
SET vindication_pending = 0, checked_at = datetime('now')
|
|
746
|
+
WHERE id = ?
|
|
747
|
+
`).run(eventId);
|
|
748
|
+
}
|
|
749
|
+
// Expire old pending vindications
|
|
750
|
+
export function expireOldVindications(projectId, maxAgeDays = 30) {
|
|
751
|
+
const db = getDb();
|
|
752
|
+
const result = db.prepare(`
|
|
753
|
+
UPDATE guardrail_events
|
|
754
|
+
SET vindication_pending = 0, checked_at = datetime('now')
|
|
755
|
+
WHERE id IN (
|
|
756
|
+
SELECT e.id FROM guardrail_events e
|
|
757
|
+
JOIN guardrails g ON e.guardrail_id = g.id
|
|
758
|
+
WHERE g.project_id = ?
|
|
759
|
+
AND e.vindication_pending = 1
|
|
760
|
+
AND datetime(e.timestamp) < datetime('now', '-' || ? || ' days')
|
|
761
|
+
)
|
|
762
|
+
`).run(projectId, maxAgeDays);
|
|
763
|
+
return result.changes;
|
|
764
|
+
}
|
|
765
|
+
// Get all vindicated events for a project (for CLI display)
|
|
766
|
+
export function getVindicatedEvents(projectId) {
|
|
767
|
+
const db = getDb();
|
|
768
|
+
return db.prepare(`
|
|
769
|
+
SELECT e.* FROM guardrail_events e
|
|
770
|
+
JOIN guardrails g ON e.guardrail_id = g.id
|
|
771
|
+
WHERE g.project_id = ? AND e.event_type = 'vindicated'
|
|
772
|
+
ORDER BY e.timestamp DESC
|
|
773
|
+
`).all(projectId);
|
|
774
|
+
}
|
|
775
|
+
export function getOverrideEventsWithRules(projectId, pendingOnly = false) {
|
|
776
|
+
const db = getDb();
|
|
777
|
+
let sql = `
|
|
778
|
+
SELECT e.*, g.rule, g.category FROM guardrail_events e
|
|
779
|
+
JOIN guardrails g ON e.guardrail_id = g.id
|
|
780
|
+
WHERE g.project_id = ? AND e.event_type = 'overridden'
|
|
781
|
+
`;
|
|
782
|
+
if (pendingOnly) {
|
|
783
|
+
sql += ' AND e.vindication_pending = 1';
|
|
784
|
+
}
|
|
785
|
+
sql += ' ORDER BY e.timestamp DESC';
|
|
786
|
+
return db.prepare(sql).all(projectId);
|
|
787
|
+
}
|
|
659
788
|
//# sourceMappingURL=index.js.map
|