contradiction-mcp 0.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.
- package/LICENSE +21 -0
- package/README.md +536 -0
- package/bin/cli.js +182 -0
- package/dist/analysis/claimMatcher.d.ts +48 -0
- package/dist/analysis/claimMatcher.js +131 -0
- package/dist/analysis/claimMatcher.js.map +1 -0
- package/dist/analysis/claimRelationship.d.ts +15 -0
- package/dist/analysis/claimRelationship.js +12 -0
- package/dist/analysis/claimRelationship.js.map +1 -0
- package/dist/analysis/confidenceScorer.d.ts +40 -0
- package/dist/analysis/confidenceScorer.js +59 -0
- package/dist/analysis/confidenceScorer.js.map +1 -0
- package/dist/analysis/contextAnalyzer.d.ts +13 -0
- package/dist/analysis/contextAnalyzer.js +187 -0
- package/dist/analysis/contextAnalyzer.js.map +1 -0
- package/dist/analysis/contradictionClassifier.d.ts +16 -0
- package/dist/analysis/contradictionClassifier.js +141 -0
- package/dist/analysis/contradictionClassifier.js.map +1 -0
- package/dist/analysis/contradictionEngine.d.ts +29 -0
- package/dist/analysis/contradictionEngine.js +284 -0
- package/dist/analysis/contradictionEngine.js.map +1 -0
- package/dist/analysis/explanationBuilder.d.ts +36 -0
- package/dist/analysis/explanationBuilder.js +77 -0
- package/dist/analysis/explanationBuilder.js.map +1 -0
- package/dist/analysis/valueComparator.d.ts +38 -0
- package/dist/analysis/valueComparator.js +418 -0
- package/dist/analysis/valueComparator.js.map +1 -0
- package/dist/config/env.d.ts +46 -0
- package/dist/config/env.js +34 -0
- package/dist/config/env.js.map +1 -0
- package/dist/connectors/base/connectorUtils.d.ts +26 -0
- package/dist/connectors/base/connectorUtils.js +63 -0
- package/dist/connectors/base/connectorUtils.js.map +1 -0
- package/dist/connectors/base/security.d.ts +11 -0
- package/dist/connectors/base/security.js +9 -0
- package/dist/connectors/base/security.js.map +1 -0
- package/dist/connectors/connectorRegistry.d.ts +43 -0
- package/dist/connectors/connectorRegistry.js +91 -0
- package/dist/connectors/connectorRegistry.js.map +1 -0
- package/dist/connectors/document/documentConnector.d.ts +45 -0
- package/dist/connectors/document/documentConnector.js +410 -0
- package/dist/connectors/document/documentConnector.js.map +1 -0
- package/dist/connectors/github/githubClient.d.ts +52 -0
- package/dist/connectors/github/githubClient.js +207 -0
- package/dist/connectors/github/githubClient.js.map +1 -0
- package/dist/connectors/github/githubConnector.d.ts +26 -0
- package/dist/connectors/github/githubConnector.js +169 -0
- package/dist/connectors/github/githubConnector.js.map +1 -0
- package/dist/connectors/github/githubExtractor.d.ts +26 -0
- package/dist/connectors/github/githubExtractor.js +469 -0
- package/dist/connectors/github/githubExtractor.js.map +1 -0
- package/dist/connectors/github/githubNormalizer.d.ts +11 -0
- package/dist/connectors/github/githubNormalizer.js +24 -0
- package/dist/connectors/github/githubNormalizer.js.map +1 -0
- package/dist/connectors/github/githubTypes.d.ts +55 -0
- package/dist/connectors/github/githubTypes.js +2 -0
- package/dist/connectors/github/githubTypes.js.map +1 -0
- package/dist/connectors/syncService.d.ts +60 -0
- package/dist/connectors/syncService.js +176 -0
- package/dist/connectors/syncService.js.map +1 -0
- package/dist/connectors/types/connector.d.ts +34 -0
- package/dist/connectors/types/connector.js +2 -0
- package/dist/connectors/types/connector.js.map +1 -0
- package/dist/connectors/types/fetchResult.d.ts +39 -0
- package/dist/connectors/types/fetchResult.js +2 -0
- package/dist/connectors/types/fetchResult.js.map +1 -0
- package/dist/connectors/website/ssrfGuard.d.ts +11 -0
- package/dist/connectors/website/ssrfGuard.js +122 -0
- package/dist/connectors/website/ssrfGuard.js.map +1 -0
- package/dist/connectors/website/websiteConnector.d.ts +30 -0
- package/dist/connectors/website/websiteConnector.js +231 -0
- package/dist/connectors/website/websiteConnector.js.map +1 -0
- package/dist/discovery/candidateGenerator.d.ts +12 -0
- package/dist/discovery/candidateGenerator.js +110 -0
- package/dist/discovery/candidateGenerator.js.map +1 -0
- package/dist/discovery/contradictionScanner.d.ts +30 -0
- package/dist/discovery/contradictionScanner.js +47 -0
- package/dist/discovery/contradictionScanner.js.map +1 -0
- package/dist/discovery/discoveryService.d.ts +37 -0
- package/dist/discovery/discoveryService.js +131 -0
- package/dist/discovery/discoveryService.js.map +1 -0
- package/dist/discovery/rankingService.d.ts +34 -0
- package/dist/discovery/rankingService.js +52 -0
- package/dist/discovery/rankingService.js.map +1 -0
- package/dist/discovery/similarityIndex.d.ts +20 -0
- package/dist/discovery/similarityIndex.js +89 -0
- package/dist/discovery/similarityIndex.js.map +1 -0
- package/dist/domain/entities/claim.d.ts +99 -0
- package/dist/domain/entities/claim.js +92 -0
- package/dist/domain/entities/claim.js.map +1 -0
- package/dist/domain/entities/contradiction.d.ts +110 -0
- package/dist/domain/entities/contradiction.js +74 -0
- package/dist/domain/entities/contradiction.js.map +1 -0
- package/dist/domain/entities/source.d.ts +43 -0
- package/dist/domain/entities/source.js +35 -0
- package/dist/domain/entities/source.js.map +1 -0
- package/dist/domain/types/common.d.ts +46 -0
- package/dist/domain/types/common.js +74 -0
- package/dist/domain/types/common.js.map +1 -0
- package/dist/httpServer.d.ts +25 -0
- package/dist/httpServer.js +164 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/intelligence/authorityScorer.d.ts +20 -0
- package/dist/intelligence/authorityScorer.js +103 -0
- package/dist/intelligence/authorityScorer.js.map +1 -0
- package/dist/intelligence/entityResolver.d.ts +33 -0
- package/dist/intelligence/entityResolver.js +152 -0
- package/dist/intelligence/entityResolver.js.map +1 -0
- package/dist/intelligence/evidenceEvaluator.d.ts +15 -0
- package/dist/intelligence/evidenceEvaluator.js +63 -0
- package/dist/intelligence/evidenceEvaluator.js.map +1 -0
- package/dist/intelligence/freshnessScorer.d.ts +25 -0
- package/dist/intelligence/freshnessScorer.js +90 -0
- package/dist/intelligence/freshnessScorer.js.map +1 -0
- package/dist/intelligence/provenanceAnalyzer.d.ts +19 -0
- package/dist/intelligence/provenanceAnalyzer.js +33 -0
- package/dist/intelligence/provenanceAnalyzer.js.map +1 -0
- package/dist/intelligence/resolutionAdvisor.d.ts +40 -0
- package/dist/intelligence/resolutionAdvisor.js +118 -0
- package/dist/intelligence/resolutionAdvisor.js.map +1 -0
- package/dist/intelligence/semanticMatcher.d.ts +21 -0
- package/dist/intelligence/semanticMatcher.js +71 -0
- package/dist/intelligence/semanticMatcher.js.map +1 -0
- package/dist/scripts/comprehensiveVerification.d.ts +5 -0
- package/dist/scripts/comprehensiveVerification.js +961 -0
- package/dist/scripts/comprehensiveVerification.js.map +1 -0
- package/dist/scripts/finalLiveDemo.d.ts +5 -0
- package/dist/scripts/finalLiveDemo.js +226 -0
- package/dist/scripts/finalLiveDemo.js.map +1 -0
- package/dist/scripts/liveMcpSmoke.d.ts +1 -0
- package/dist/scripts/liveMcpSmoke.js +89 -0
- package/dist/scripts/liveMcpSmoke.js.map +1 -0
- package/dist/scripts/seedDemoData.d.ts +6 -0
- package/dist/scripts/seedDemoData.js +179 -0
- package/dist/scripts/seedDemoData.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.js +1264 -0
- package/dist/server.js.map +1 -0
- package/dist/services/analysisService.d.ts +40 -0
- package/dist/services/analysisService.js +65 -0
- package/dist/services/analysisService.js.map +1 -0
- package/dist/services/healthService.d.ts +42 -0
- package/dist/services/healthService.js +50 -0
- package/dist/services/healthService.js.map +1 -0
- package/dist/services/metricsService.d.ts +35 -0
- package/dist/services/metricsService.js +57 -0
- package/dist/services/metricsService.js.map +1 -0
- package/dist/services/rateLimiter.d.ts +23 -0
- package/dist/services/rateLimiter.js +45 -0
- package/dist/services/rateLimiter.js.map +1 -0
- package/dist/services/reviewService.d.ts +32 -0
- package/dist/services/reviewService.js +94 -0
- package/dist/services/reviewService.js.map +1 -0
- package/dist/services/schedulerService.d.ts +30 -0
- package/dist/services/schedulerService.js +89 -0
- package/dist/services/schedulerService.js.map +1 -0
- package/dist/storage/backupService.d.ts +14 -0
- package/dist/storage/backupService.js +90 -0
- package/dist/storage/backupService.js.map +1 -0
- package/dist/storage/database.d.ts +119 -0
- package/dist/storage/database.js +935 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/migrations/001_initial.sql +63 -0
- package/dist/storage/migrations/002_discovery_uniqueness.sql +8 -0
- package/dist/storage/migrations/003_connector_identity.sql +7 -0
- package/dist/storage/migrations/004_claim_context.sql +15 -0
- package/dist/storage/migrations/005_claim_history.sql +26 -0
- package/dist/storage/migrations/006_contradiction_resolution.sql +27 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.js +48 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
export class SchedulerService {
|
|
3
|
+
syncService;
|
|
4
|
+
discoveryService;
|
|
5
|
+
tasks = new Map();
|
|
6
|
+
taskCallbacks = new Map();
|
|
7
|
+
timerHandles = new Map();
|
|
8
|
+
isRunning = false;
|
|
9
|
+
constructor(syncService, discoveryService) {
|
|
10
|
+
this.syncService = syncService;
|
|
11
|
+
this.discoveryService = discoveryService;
|
|
12
|
+
}
|
|
13
|
+
registerTask(id, name, intervalMs, fn) {
|
|
14
|
+
if (this.tasks.has(id)) {
|
|
15
|
+
throw new Error(`Scheduled task with id '${id}' is already registered`);
|
|
16
|
+
}
|
|
17
|
+
const task = {
|
|
18
|
+
id,
|
|
19
|
+
name,
|
|
20
|
+
intervalMs,
|
|
21
|
+
nextRun: new Date(Date.now() + intervalMs),
|
|
22
|
+
runCount: 0,
|
|
23
|
+
isRunning: false,
|
|
24
|
+
};
|
|
25
|
+
this.tasks.set(id, task);
|
|
26
|
+
this.taskCallbacks.set(id, fn);
|
|
27
|
+
if (this.isRunning) {
|
|
28
|
+
this.scheduleTask(task, fn);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
start() {
|
|
32
|
+
if (this.isRunning)
|
|
33
|
+
return;
|
|
34
|
+
this.isRunning = true;
|
|
35
|
+
for (const [id, task] of this.tasks.entries()) {
|
|
36
|
+
const fn = this.taskCallbacks.get(id);
|
|
37
|
+
if (fn && !this.timerHandles.has(id)) {
|
|
38
|
+
this.scheduleTask(task, fn);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
logger.info('In-process task scheduler started', { activeTasks: this.tasks.size });
|
|
42
|
+
}
|
|
43
|
+
stop() {
|
|
44
|
+
this.isRunning = false;
|
|
45
|
+
for (const [, handle] of this.timerHandles.entries()) {
|
|
46
|
+
clearTimeout(handle);
|
|
47
|
+
}
|
|
48
|
+
this.timerHandles.clear();
|
|
49
|
+
logger.info('In-process task scheduler stopped');
|
|
50
|
+
}
|
|
51
|
+
scheduleTask(task, fn) {
|
|
52
|
+
if (!this.isRunning)
|
|
53
|
+
return;
|
|
54
|
+
const timer = setTimeout(async () => {
|
|
55
|
+
if (!this.isRunning || task.isRunning)
|
|
56
|
+
return;
|
|
57
|
+
task.isRunning = true;
|
|
58
|
+
task.lastRun = new Date();
|
|
59
|
+
try {
|
|
60
|
+
logger.info(`Executing scheduled task: ${task.name}`, { taskId: task.id });
|
|
61
|
+
await fn();
|
|
62
|
+
task.lastStatus = 'success';
|
|
63
|
+
task.lastError = undefined;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
67
|
+
task.lastStatus = 'failed';
|
|
68
|
+
task.lastError = msg;
|
|
69
|
+
logger.error(`Scheduled task '${task.name}' failed`, { taskId: task.id, error: msg });
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
task.isRunning = false;
|
|
73
|
+
task.runCount++;
|
|
74
|
+
task.nextRun = new Date(Date.now() + task.intervalMs);
|
|
75
|
+
if (this.isRunning) {
|
|
76
|
+
this.scheduleTask(task, fn);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}, task.intervalMs);
|
|
80
|
+
this.timerHandles.set(task.id, timer);
|
|
81
|
+
}
|
|
82
|
+
getStatus() {
|
|
83
|
+
return {
|
|
84
|
+
isRunning: this.isRunning,
|
|
85
|
+
tasks: Array.from(this.tasks.values()),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=schedulerService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedulerService.js","sourceRoot":"","sources":["../../src/services/schedulerService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DatabaseManager } from './database.js';
|
|
2
|
+
export interface BackupVerificationResult {
|
|
3
|
+
valid: boolean;
|
|
4
|
+
tablesCount: number;
|
|
5
|
+
integrity: string[];
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class BackupService {
|
|
9
|
+
private readonly dbManager;
|
|
10
|
+
constructor(dbManager: DatabaseManager);
|
|
11
|
+
createBackup(targetDirectory: string): Promise<string>;
|
|
12
|
+
verifyBackup(backupPath: string): BackupVerificationResult;
|
|
13
|
+
restoreBackup(backupPath: string, destinationDbPath: string): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { DatabaseError } from '../domain/types/common.js';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
export class BackupService {
|
|
7
|
+
dbManager;
|
|
8
|
+
constructor(dbManager) {
|
|
9
|
+
this.dbManager = dbManager;
|
|
10
|
+
}
|
|
11
|
+
async createBackup(targetDirectory) {
|
|
12
|
+
if (!fs.existsSync(targetDirectory)) {
|
|
13
|
+
fs.mkdirSync(targetDirectory, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
16
|
+
const backupFileName = `contradiction-backup-${timestamp}.db`;
|
|
17
|
+
const targetPath = path.resolve(targetDirectory, backupFileName);
|
|
18
|
+
logger.info('Initiating database backup', { targetPath });
|
|
19
|
+
try {
|
|
20
|
+
await this.dbManager.backup(targetPath);
|
|
21
|
+
logger.info('Database backup completed successfully', { targetPath });
|
|
22
|
+
return targetPath;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
26
|
+
logger.error('Failed to create database backup', { targetPath, error: msg });
|
|
27
|
+
throw new DatabaseError(`Backup failed: ${msg}`, error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
verifyBackup(backupPath) {
|
|
31
|
+
if (!fs.existsSync(backupPath)) {
|
|
32
|
+
return {
|
|
33
|
+
valid: false,
|
|
34
|
+
tablesCount: 0,
|
|
35
|
+
integrity: [],
|
|
36
|
+
error: `Backup file does not exist: ${backupPath}`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
let tempDb = null;
|
|
40
|
+
try {
|
|
41
|
+
tempDb = new Database(backupPath, { readonly: true });
|
|
42
|
+
const integrityRows = tempDb.pragma('integrity_check');
|
|
43
|
+
const integrity = integrityRows.map((r) => r.integrity_check);
|
|
44
|
+
const isIntegrityOk = integrity.length === 1 && integrity[0] === 'ok';
|
|
45
|
+
const tablesRow = tempDb
|
|
46
|
+
.prepare("SELECT count(*) as count FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'")
|
|
47
|
+
.get();
|
|
48
|
+
return {
|
|
49
|
+
valid: isIntegrityOk,
|
|
50
|
+
tablesCount: tablesRow.count,
|
|
51
|
+
integrity,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
56
|
+
return {
|
|
57
|
+
valid: false,
|
|
58
|
+
tablesCount: 0,
|
|
59
|
+
integrity: [],
|
|
60
|
+
error: msg,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
if (tempDb && tempDb.open) {
|
|
65
|
+
tempDb.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
restoreBackup(backupPath, destinationDbPath) {
|
|
70
|
+
const verification = this.verifyBackup(backupPath);
|
|
71
|
+
if (!verification.valid) {
|
|
72
|
+
throw new DatabaseError(`Cannot restore invalid backup at ${backupPath}: ${verification.error || 'Integrity check failed'}`);
|
|
73
|
+
}
|
|
74
|
+
logger.warn('Restoring database from verified backup', { backupPath, destinationDbPath });
|
|
75
|
+
try {
|
|
76
|
+
// Create destination folder if needed
|
|
77
|
+
const destDir = path.dirname(destinationDbPath);
|
|
78
|
+
if (!fs.existsSync(destDir)) {
|
|
79
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
80
|
+
}
|
|
81
|
+
fs.copyFileSync(backupPath, destinationDbPath);
|
|
82
|
+
logger.info('Database restored successfully', { backupPath, destinationDbPath });
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
86
|
+
throw new DatabaseError(`Failed to restore database from ${backupPath}: ${msg}`, error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=backupService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backupService.js","sourceRoot":"","sources":["../../src/storage/backupService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAS5C,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,SAA0B;QAA1B,cAAS,GAAT,SAAS,CAAiB;IAAG,CAAC;IAEpD,KAAK,CAAC,YAAY,CAAC,eAAuB;QAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACpC,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,cAAc,GAAG,wBAAwB,SAAS,KAAK,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;QAEjE,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,wCAAwC,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;YACtE,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnE,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC7E,MAAM,IAAI,aAAa,CAAC,kBAAkB,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAEM,YAAY,CAAC,UAAkB;QACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,CAAC;gBACd,SAAS,EAAE,EAAE;gBACb,KAAK,EAAE,+BAA+B,UAAU,EAAE;aACnD,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,GAA6B,IAAI,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAuC,CAAC;YAC7F,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YAC9D,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;YAEtE,MAAM,SAAS,GAAG,MAAM;iBACrB,OAAO,CACN,6FAA6F,CAC9F;iBACA,GAAG,EAAuB,CAAC;YAE9B,OAAO;gBACL,KAAK,EAAE,aAAa;gBACpB,WAAW,EAAE,SAAS,CAAC,KAAK;gBAC5B,SAAS;aACV,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnE,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,CAAC;gBACd,SAAS,EAAE,EAAE;gBACb,KAAK,EAAE,GAAG;aACX,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC1B,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IAEM,aAAa,CAAC,UAAkB,EAAE,iBAAyB;QAChE,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YACxB,MAAM,IAAI,aAAa,CACrB,oCAAoC,UAAU,KAAK,YAAY,CAAC,KAAK,IAAI,wBAAwB,EAAE,CACpG,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC1F,IAAI,CAAC;YACH,sCAAsC;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,CAAC;YAED,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,gCAAgC,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnE,MAAM,IAAI,aAAa,CAAC,mCAAmC,UAAU,KAAK,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { Source, CreateSourceInput, UpdateSourceInput } from '../domain/entities/source.js';
|
|
3
|
+
import { Claim, ClaimHistoryEntry, CreateClaimInput } from '../domain/entities/claim.js';
|
|
4
|
+
import { Contradiction, ContradictionHistoryEntry, CreateContradictionInput, ContradictionStatus, ContradictionSeverity } from '../domain/entities/contradiction.js';
|
|
5
|
+
export interface ListContradictionsOptions {
|
|
6
|
+
status?: ContradictionStatus;
|
|
7
|
+
severity?: ContradictionSeverity;
|
|
8
|
+
type?: string;
|
|
9
|
+
minConfidence?: number;
|
|
10
|
+
limit?: number;
|
|
11
|
+
offset?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface DatabaseHealth {
|
|
14
|
+
status: 'connected' | 'unreachable';
|
|
15
|
+
latencyMs: number;
|
|
16
|
+
tablesCount: number;
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class DatabaseManager {
|
|
20
|
+
private db;
|
|
21
|
+
private readonly dbPath;
|
|
22
|
+
constructor(dbPath?: string);
|
|
23
|
+
initialize(): void;
|
|
24
|
+
getRawDb(): Database.Database;
|
|
25
|
+
runMigrations(): void;
|
|
26
|
+
checkHealth(): DatabaseHealth;
|
|
27
|
+
close(): void;
|
|
28
|
+
createSource(input: CreateSourceInput): Source;
|
|
29
|
+
getSourceById(id: string): Source | null;
|
|
30
|
+
getSourceByExternalId(externalId: string): Source | null;
|
|
31
|
+
upsertSource(input: CreateSourceInput): {
|
|
32
|
+
source: Source;
|
|
33
|
+
isNew: boolean;
|
|
34
|
+
};
|
|
35
|
+
listSources(options?: {
|
|
36
|
+
type?: string;
|
|
37
|
+
limit?: number;
|
|
38
|
+
}): Source[];
|
|
39
|
+
updateSource(id: string, input: UpdateSourceInput): Source;
|
|
40
|
+
deleteSource(id: string): boolean;
|
|
41
|
+
createClaim(input: CreateClaimInput): Claim;
|
|
42
|
+
getClaimById(id: string): Claim | null;
|
|
43
|
+
getClaimByExternalId(externalId: string): Claim | null;
|
|
44
|
+
updateClaim(id: string, updates: Partial<{
|
|
45
|
+
value: string;
|
|
46
|
+
valueType: string;
|
|
47
|
+
normalizedValue: string | null;
|
|
48
|
+
confidence: number;
|
|
49
|
+
environment: string | null;
|
|
50
|
+
scope: string | null;
|
|
51
|
+
sourceRole: string | null;
|
|
52
|
+
isHistorical: boolean;
|
|
53
|
+
validFrom: Date | null;
|
|
54
|
+
validUntil: Date | null;
|
|
55
|
+
valueConstraint: string | null;
|
|
56
|
+
multiValueContext: string | null;
|
|
57
|
+
observedAt: Date;
|
|
58
|
+
firstSeenAt: Date | null;
|
|
59
|
+
lastSeenAt: Date | null;
|
|
60
|
+
supersededBy: string | null;
|
|
61
|
+
metadata: Record<string, unknown>;
|
|
62
|
+
}>): Claim;
|
|
63
|
+
upsertClaim(input: CreateClaimInput): {
|
|
64
|
+
claim: Claim;
|
|
65
|
+
isNew: boolean;
|
|
66
|
+
updated: boolean;
|
|
67
|
+
};
|
|
68
|
+
listClaims(options?: {
|
|
69
|
+
sourceId?: string;
|
|
70
|
+
subject?: string;
|
|
71
|
+
limit?: number;
|
|
72
|
+
}): Claim[];
|
|
73
|
+
deleteClaim(id: string): boolean;
|
|
74
|
+
recordClaimHistory(claimId: string, value: string, normalizedValue: string | null, sourceId: string, observedAt: Date, firstSeenAt: Date, lastSeenAt: Date, supersededAt?: Date | null, supersededBy?: string | null, metadata?: Record<string, unknown>): ClaimHistoryEntry;
|
|
75
|
+
getClaimHistory(claimId: string): ClaimHistoryEntry[];
|
|
76
|
+
createContradiction(input: CreateContradictionInput): Contradiction;
|
|
77
|
+
getContradictionById(id: string): Contradiction | null;
|
|
78
|
+
findContradictionByClaimPair(claimAId: string, claimBId: string): Contradiction | null;
|
|
79
|
+
saveDiscoveredContradiction(input: CreateContradictionInput): {
|
|
80
|
+
contradiction: Contradiction;
|
|
81
|
+
isNew: boolean;
|
|
82
|
+
};
|
|
83
|
+
listContradictions(options?: ListContradictionsOptions): Contradiction[];
|
|
84
|
+
getContradictionWithDetails(id: string): {
|
|
85
|
+
contradiction: Contradiction;
|
|
86
|
+
claimA: Claim;
|
|
87
|
+
claimB: Claim;
|
|
88
|
+
sourceA: Source | null;
|
|
89
|
+
sourceB: Source | null;
|
|
90
|
+
} | null;
|
|
91
|
+
updateContradictionStatus(id: string, status: ContradictionStatus, details?: {
|
|
92
|
+
reason?: string | null;
|
|
93
|
+
resolvedBy?: string | null;
|
|
94
|
+
resolutionSource?: string | null;
|
|
95
|
+
chosenClaimId?: string | null;
|
|
96
|
+
auditNotes?: string | null;
|
|
97
|
+
resolvedAt?: Date | null;
|
|
98
|
+
}): Contradiction;
|
|
99
|
+
recordContradictionAudit(input: {
|
|
100
|
+
contradictionId: string;
|
|
101
|
+
action: 'REVIEWED' | 'RESOLVED' | 'DISMISSED' | 'REOPENED';
|
|
102
|
+
previousStatus: ContradictionStatus;
|
|
103
|
+
newStatus: ContradictionStatus;
|
|
104
|
+
performedBy: string;
|
|
105
|
+
reason?: string | null;
|
|
106
|
+
chosenClaimId?: string | null;
|
|
107
|
+
notes?: string | null;
|
|
108
|
+
}): ContradictionHistoryEntry;
|
|
109
|
+
getContradictionHistory(contradictionId: string): ContradictionHistoryEntry[];
|
|
110
|
+
backup(targetPath: string): Promise<void>;
|
|
111
|
+
checkIntegrity(): {
|
|
112
|
+
ok: boolean;
|
|
113
|
+
details: string[];
|
|
114
|
+
};
|
|
115
|
+
deleteContradiction(id: string): boolean;
|
|
116
|
+
private mapRowToSource;
|
|
117
|
+
private mapRowToClaim;
|
|
118
|
+
private mapRowToContradiction;
|
|
119
|
+
}
|