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
package/bin/cli.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
11
|
+
const serverDist = path.join(projectRoot, 'dist', 'index.js');
|
|
12
|
+
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const command = args[0] || 'start';
|
|
15
|
+
|
|
16
|
+
if (
|
|
17
|
+
command === 'start' ||
|
|
18
|
+
command === 'run' ||
|
|
19
|
+
(command && !['install', 'setup', '--help', '-h', 'help'].includes(command))
|
|
20
|
+
) {
|
|
21
|
+
// If invoked as standard MCP server (e.g. npx -y contradiction-mcp)
|
|
22
|
+
await import('../dist/index.js');
|
|
23
|
+
} else if (command === '--help' || command === '-h' || command === 'help') {
|
|
24
|
+
console.log(`
|
|
25
|
+
Contradiction MCP - Cross-Source Inconsistency & Contradiction Engine
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
npx contradiction-mcp Start MCP server (stdio default)
|
|
29
|
+
npx contradiction-mcp install [ide] Auto-configure MCP server in specified IDE/client
|
|
30
|
+
|
|
31
|
+
Supported IDEs:
|
|
32
|
+
antigravity Configure Google Antigravity (~/.gemini/config/mcp_config.json)
|
|
33
|
+
cursor Configure Cursor IDE (~/.cursor/mcp.json or workspace)
|
|
34
|
+
claude Configure Claude Desktop App
|
|
35
|
+
claude-code Configure Claude Code CLI (~/.claude.json or via claude mcp add)
|
|
36
|
+
windsurf Configure Windsurf IDE (~/.codeium/windsurf/mcp_config.json)
|
|
37
|
+
all Configure all detected environments (default)
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
npx contradiction-mcp install antigravity
|
|
41
|
+
npx contradiction-mcp install cursor
|
|
42
|
+
npx contradiction-mcp install claude
|
|
43
|
+
npx contradiction-mcp install claude-code
|
|
44
|
+
npx contradiction-mcp install all
|
|
45
|
+
`);
|
|
46
|
+
process.exit(0);
|
|
47
|
+
} else if (command === 'install' || command === 'setup') {
|
|
48
|
+
const requestedIde = (args[1] || 'all').toLowerCase();
|
|
49
|
+
const home = os.homedir();
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
|
|
52
|
+
const nodeExecutable = process.execPath;
|
|
53
|
+
const isGlobalNpx = !fs.existsSync(serverDist);
|
|
54
|
+
|
|
55
|
+
// If installed via npm global or npx, use npx contradiction-mcp as command, else point to local dist/index.js
|
|
56
|
+
const serverConfig = isGlobalNpx
|
|
57
|
+
? {
|
|
58
|
+
command: 'npx',
|
|
59
|
+
args: ['-y', 'contradiction-mcp'],
|
|
60
|
+
env: {
|
|
61
|
+
NODE_ENV: 'production',
|
|
62
|
+
MCP_TRANSPORT: 'stdio',
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
: {
|
|
66
|
+
command: nodeExecutable,
|
|
67
|
+
args: [serverDist],
|
|
68
|
+
env: {
|
|
69
|
+
NODE_ENV: 'production',
|
|
70
|
+
DATABASE_PATH: path.join(projectRoot, 'data', 'contradiction.db'),
|
|
71
|
+
MCP_TRANSPORT: 'stdio',
|
|
72
|
+
LOG_LEVEL: 'error',
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
console.log(
|
|
77
|
+
`\n=== Installing Contradiction MCP for target: [${requestedIde.toUpperCase()}] ===\n`,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
function updateJsonConfig(filePath, serverKey = 'contradiction', format = 'mcpServers') {
|
|
81
|
+
try {
|
|
82
|
+
const dir = path.dirname(filePath);
|
|
83
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
84
|
+
|
|
85
|
+
let data = {};
|
|
86
|
+
if (fs.existsSync(filePath)) {
|
|
87
|
+
try {
|
|
88
|
+
data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
89
|
+
} catch {
|
|
90
|
+
data = {};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (format === 'mcpServers') {
|
|
95
|
+
if (!data.mcpServers || typeof data.mcpServers !== 'object') {
|
|
96
|
+
data.mcpServers = {};
|
|
97
|
+
}
|
|
98
|
+
data.mcpServers[serverKey] = serverConfig;
|
|
99
|
+
} else if (format === 'claudeCode') {
|
|
100
|
+
// Claude Code CLI format in ~/.claude.json
|
|
101
|
+
if (!data.mcpServers || typeof data.mcpServers !== 'object') {
|
|
102
|
+
data.mcpServers = {};
|
|
103
|
+
}
|
|
104
|
+
data.mcpServers[serverKey] = serverConfig;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
108
|
+
console.log(`✔ Configured: ${filePath}`);
|
|
109
|
+
return true;
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.warn(`⚠ Failed configuring ${filePath}: ${err.message}`);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let count = 0;
|
|
117
|
+
|
|
118
|
+
// 1. Antigravity
|
|
119
|
+
if (['antigravity', 'all'].includes(requestedIde)) {
|
|
120
|
+
const globalGemini = path.join(home, '.gemini', 'config', 'mcp_config.json');
|
|
121
|
+
if (updateJsonConfig(globalGemini)) count++;
|
|
122
|
+
|
|
123
|
+
const workspaceAgents = path.join(cwd, '.agents', 'mcp_config.json');
|
|
124
|
+
if (updateJsonConfig(workspaceAgents)) count++;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 2. Cursor
|
|
128
|
+
if (['cursor', 'all'].includes(requestedIde)) {
|
|
129
|
+
const globalCursor = path.join(home, '.cursor', 'mcp.json');
|
|
130
|
+
if (updateJsonConfig(globalCursor)) count++;
|
|
131
|
+
|
|
132
|
+
const workspaceCursor = path.join(cwd, '.cursor', 'mcp.json');
|
|
133
|
+
if (updateJsonConfig(workspaceCursor)) count++;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 3. Claude Desktop
|
|
137
|
+
if (['claude', 'claude-desktop', 'all'].includes(requestedIde)) {
|
|
138
|
+
const claudePath =
|
|
139
|
+
process.platform === 'darwin'
|
|
140
|
+
? path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
|
|
141
|
+
: process.platform === 'win32'
|
|
142
|
+
? path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json')
|
|
143
|
+
: path.join(home, '.config', 'Claude', 'claude_desktop_config.json');
|
|
144
|
+
|
|
145
|
+
if (updateJsonConfig(claudePath)) count++;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 4. Claude Code CLI
|
|
149
|
+
if (['claude-code', 'claudecode', 'all'].includes(requestedIde)) {
|
|
150
|
+
const claudeCodeJson = path.join(home, '.claude.json');
|
|
151
|
+
if (updateJsonConfig(claudeCodeJson, 'contradiction', 'claudeCode')) count++;
|
|
152
|
+
|
|
153
|
+
// Also attempt native `claude mcp add` if claude cli is in PATH
|
|
154
|
+
try {
|
|
155
|
+
const checkClaude = execSync('which claude 2>/dev/null || true', {
|
|
156
|
+
encoding: 'utf-8',
|
|
157
|
+
}).trim();
|
|
158
|
+
if (checkClaude) {
|
|
159
|
+
try {
|
|
160
|
+
execSync(
|
|
161
|
+
`claude mcp add contradiction -- ${serverConfig.command} ${serverConfig.args.join(' ')}`,
|
|
162
|
+
{ stdio: 'ignore' },
|
|
163
|
+
);
|
|
164
|
+
console.log(`✔ Registered via Claude CLI: claude mcp add contradiction`);
|
|
165
|
+
} catch {
|
|
166
|
+
// ignore if already added
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
// ignore
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 5. Windsurf
|
|
175
|
+
if (['windsurf', 'all'].includes(requestedIde)) {
|
|
176
|
+
const windsurfPath = path.join(home, '.codeium', 'windsurf', 'mcp_config.json');
|
|
177
|
+
if (updateJsonConfig(windsurfPath)) count++;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(`\n🎉 Installation finished! Successfully configured in ${count} location(s).`);
|
|
181
|
+
console.log(`Restart your IDE / Agent (${requestedIde}) to begin using Contradiction MCP.\n`);
|
|
182
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface ClaimMatchResult {
|
|
2
|
+
matches: boolean;
|
|
3
|
+
subjectSimilarity: number;
|
|
4
|
+
predicateSimilarity: number;
|
|
5
|
+
normalizedSubjectA: string;
|
|
6
|
+
normalizedSubjectB: string;
|
|
7
|
+
normalizedPredicateA: string;
|
|
8
|
+
normalizedPredicateB: string;
|
|
9
|
+
reason: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ClaimMatcherOptions {
|
|
12
|
+
subjectThreshold?: number;
|
|
13
|
+
predicateThreshold?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Normalizes text for deterministic entity/property matching:
|
|
17
|
+
* - Lowercase & trim
|
|
18
|
+
* - Replaces separators (hyphens, underscores, slashes, dots) with spaces
|
|
19
|
+
* - Removes non-alphanumeric characters (except spaces)
|
|
20
|
+
* - Collapses consecutive whitespace
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeText(input: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Calculates Token Jaccard Similarity between two normalized strings.
|
|
25
|
+
* Returns a value between 0.0 and 1.0.
|
|
26
|
+
*/
|
|
27
|
+
export declare function calculateTokenSimilarity(a: string, b: string): number;
|
|
28
|
+
/**
|
|
29
|
+
* Levenshtein distance-based string similarity for single-token or exact variations.
|
|
30
|
+
*/
|
|
31
|
+
export declare function calculateLevenshteinSimilarity(s1: string, s2: string): number;
|
|
32
|
+
/**
|
|
33
|
+
* Combined similarity score leveraging token overlap and string distance.
|
|
34
|
+
*/
|
|
35
|
+
export declare function calculateCompositeSimilarity(strA: string, strB: string): number;
|
|
36
|
+
export declare class ClaimMatcher {
|
|
37
|
+
private readonly subjectThreshold;
|
|
38
|
+
private readonly predicateThreshold;
|
|
39
|
+
constructor(options?: ClaimMatcherOptions);
|
|
40
|
+
match(claimA: {
|
|
41
|
+
subject: string;
|
|
42
|
+
predicate: string;
|
|
43
|
+
}, claimB: {
|
|
44
|
+
subject: string;
|
|
45
|
+
predicate: string;
|
|
46
|
+
}): ClaimMatchResult;
|
|
47
|
+
}
|
|
48
|
+
export declare const claimMatcher: ClaimMatcher;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes text for deterministic entity/property matching:
|
|
3
|
+
* - Lowercase & trim
|
|
4
|
+
* - Replaces separators (hyphens, underscores, slashes, dots) with spaces
|
|
5
|
+
* - Removes non-alphanumeric characters (except spaces)
|
|
6
|
+
* - Collapses consecutive whitespace
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeText(input) {
|
|
9
|
+
if (!input)
|
|
10
|
+
return '';
|
|
11
|
+
return input
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[_\-./\\:]+/g, ' ')
|
|
14
|
+
.replace(/[^\p{L}\p{N}\s]/gu, '')
|
|
15
|
+
.replace(/\s+/g, ' ')
|
|
16
|
+
.trim();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calculates Token Jaccard Similarity between two normalized strings.
|
|
20
|
+
* Returns a value between 0.0 and 1.0.
|
|
21
|
+
*/
|
|
22
|
+
export function calculateTokenSimilarity(a, b) {
|
|
23
|
+
if (a === b)
|
|
24
|
+
return 1.0;
|
|
25
|
+
if (!a || !b)
|
|
26
|
+
return 0.0;
|
|
27
|
+
const tokensA = new Set(a.split(' ').filter(Boolean));
|
|
28
|
+
const tokensB = new Set(b.split(' ').filter(Boolean));
|
|
29
|
+
if (tokensA.size === 0 || tokensB.size === 0)
|
|
30
|
+
return 0.0;
|
|
31
|
+
let intersectionCount = 0;
|
|
32
|
+
for (const token of tokensA) {
|
|
33
|
+
if (tokensB.has(token)) {
|
|
34
|
+
intersectionCount++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const unionCount = tokensA.size + tokensB.size - intersectionCount;
|
|
38
|
+
return unionCount === 0 ? 0.0 : intersectionCount / unionCount;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Levenshtein distance-based string similarity for single-token or exact variations.
|
|
42
|
+
*/
|
|
43
|
+
export function calculateLevenshteinSimilarity(s1, s2) {
|
|
44
|
+
if (s1 === s2)
|
|
45
|
+
return 1.0;
|
|
46
|
+
if (!s1 || !s2)
|
|
47
|
+
return 0.0;
|
|
48
|
+
const l1 = s1.length;
|
|
49
|
+
const l2 = s2.length;
|
|
50
|
+
const maxLen = Math.max(l1, l2);
|
|
51
|
+
if (maxLen === 0)
|
|
52
|
+
return 1.0;
|
|
53
|
+
const dp = Array.from({ length: l1 + 1 }, () => Array(l2 + 1).fill(0));
|
|
54
|
+
for (let i = 0; i <= l1; i++)
|
|
55
|
+
dp[i][0] = i;
|
|
56
|
+
for (let j = 0; j <= l2; j++)
|
|
57
|
+
dp[0][j] = j;
|
|
58
|
+
for (let i = 1; i <= l1; i++) {
|
|
59
|
+
for (let j = 1; j <= l2; j++) {
|
|
60
|
+
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
|
61
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const distance = dp[l1][l2];
|
|
65
|
+
return 1 - distance / maxLen;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Combined similarity score leveraging token overlap and string distance.
|
|
69
|
+
*/
|
|
70
|
+
export function calculateCompositeSimilarity(strA, strB) {
|
|
71
|
+
const normA = normalizeText(strA);
|
|
72
|
+
const normB = normalizeText(strB);
|
|
73
|
+
if (normA === normB)
|
|
74
|
+
return 1.0;
|
|
75
|
+
if (!normA || !normB)
|
|
76
|
+
return 0.0;
|
|
77
|
+
const tokenSim = calculateTokenSimilarity(normA, normB);
|
|
78
|
+
const editSim = calculateLevenshteinSimilarity(normA, normB);
|
|
79
|
+
// If one contains the other as substring (e.g. "api server" and "api server cluster")
|
|
80
|
+
if (normA.includes(normB) || normB.includes(normA)) {
|
|
81
|
+
const minLen = Math.min(normA.length, normB.length);
|
|
82
|
+
const maxLen = Math.max(normA.length, normB.length);
|
|
83
|
+
const inclusionScore = minLen / maxLen;
|
|
84
|
+
return Math.max(tokenSim, editSim, inclusionScore * 0.9);
|
|
85
|
+
}
|
|
86
|
+
return Math.max(tokenSim, editSim);
|
|
87
|
+
}
|
|
88
|
+
export class ClaimMatcher {
|
|
89
|
+
subjectThreshold;
|
|
90
|
+
predicateThreshold;
|
|
91
|
+
constructor(options) {
|
|
92
|
+
this.subjectThreshold = options?.subjectThreshold ?? 0.75;
|
|
93
|
+
this.predicateThreshold = options?.predicateThreshold ?? 0.8;
|
|
94
|
+
}
|
|
95
|
+
match(claimA, claimB) {
|
|
96
|
+
const normSubA = normalizeText(claimA.subject);
|
|
97
|
+
const normSubB = normalizeText(claimB.subject);
|
|
98
|
+
const normPredA = normalizeText(claimA.predicate);
|
|
99
|
+
const normPredB = normalizeText(claimB.predicate);
|
|
100
|
+
const subjectSimilarity = calculateCompositeSimilarity(claimA.subject, claimB.subject);
|
|
101
|
+
const predicateSimilarity = calculateCompositeSimilarity(claimA.predicate, claimB.predicate);
|
|
102
|
+
const subjectMatches = subjectSimilarity >= this.subjectThreshold;
|
|
103
|
+
const predicateMatches = predicateSimilarity >= this.predicateThreshold;
|
|
104
|
+
const matches = subjectMatches && predicateMatches;
|
|
105
|
+
let reason;
|
|
106
|
+
if (!subjectMatches && !predicateMatches) {
|
|
107
|
+
reason = `Both subject ('${normSubA}' vs '${normSubB}') and predicate ('${normPredA}' vs '${normPredB}') refer to different concepts`;
|
|
108
|
+
}
|
|
109
|
+
else if (!subjectMatches) {
|
|
110
|
+
reason = `Subjects '${normSubA}' and '${normSubB}' do not match (similarity: ${subjectSimilarity.toFixed(2)})`;
|
|
111
|
+
}
|
|
112
|
+
else if (!predicateMatches) {
|
|
113
|
+
reason = `Predicates '${normPredA}' and '${normPredB}' do not match (similarity: ${predicateSimilarity.toFixed(2)})`;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
reason = `Matches same conceptual fact on subject '${normSubA}' and predicate '${normPredA}'`;
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
matches,
|
|
120
|
+
subjectSimilarity,
|
|
121
|
+
predicateSimilarity,
|
|
122
|
+
normalizedSubjectA: normSubA,
|
|
123
|
+
normalizedSubjectB: normSubB,
|
|
124
|
+
normalizedPredicateA: normPredA,
|
|
125
|
+
normalizedPredicateB: normPredB,
|
|
126
|
+
reason,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export const claimMatcher = new ClaimMatcher();
|
|
131
|
+
//# sourceMappingURL=claimMatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claimMatcher.js","sourceRoot":"","sources":["../../src/analysis/claimMatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const ClaimRelationshipTypes: readonly ["SAME_FACT", "COMPATIBLE_FACT", "DIFFERENT_SCOPE", "DIFFERENT_ENVIRONMENT", "HISTORICAL", "EXAMPLE", "SET_MEMBERSHIP", "INCOMPATIBLE_FACT", "UNKNOWN"];
|
|
2
|
+
export type ClaimRelationshipType = (typeof ClaimRelationshipTypes)[number];
|
|
3
|
+
export interface ClaimRelationship {
|
|
4
|
+
type: ClaimRelationshipType;
|
|
5
|
+
confidence: number;
|
|
6
|
+
explanation: string;
|
|
7
|
+
isContradictionEligible: boolean;
|
|
8
|
+
contextFactors: {
|
|
9
|
+
environmentMatch: boolean;
|
|
10
|
+
scopeMatch: boolean;
|
|
11
|
+
roleMatch: boolean;
|
|
12
|
+
temporalMatch: boolean;
|
|
13
|
+
setMembershipMatch: boolean;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const ClaimRelationshipTypes = [
|
|
2
|
+
'SAME_FACT',
|
|
3
|
+
'COMPATIBLE_FACT',
|
|
4
|
+
'DIFFERENT_SCOPE',
|
|
5
|
+
'DIFFERENT_ENVIRONMENT',
|
|
6
|
+
'HISTORICAL',
|
|
7
|
+
'EXAMPLE',
|
|
8
|
+
'SET_MEMBERSHIP',
|
|
9
|
+
'INCOMPATIBLE_FACT',
|
|
10
|
+
'UNKNOWN',
|
|
11
|
+
];
|
|
12
|
+
//# sourceMappingURL=claimRelationship.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claimRelationship.js","sourceRoot":"","sources":["../../src/analysis/claimRelationship.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,WAAW;IACX,iBAAiB;IACjB,iBAAiB;IACjB,uBAAuB;IACvB,YAAY;IACZ,SAAS;IACT,gBAAgB;IAChB,mBAAmB;IACnB,SAAS;CACD,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface ConfidenceScoreInputs {
|
|
2
|
+
subjectSimilarity: number;
|
|
3
|
+
predicateSimilarity: number;
|
|
4
|
+
valueComparable: boolean;
|
|
5
|
+
valueDifferenceStrength: number;
|
|
6
|
+
claimAConfidence?: number;
|
|
7
|
+
claimBConfidence?: number;
|
|
8
|
+
sourceATrust?: number;
|
|
9
|
+
sourceBTrust?: number;
|
|
10
|
+
isAmbiguous?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ConfidenceScoreResult {
|
|
13
|
+
confidence: number;
|
|
14
|
+
breakdown: {
|
|
15
|
+
subjectWeight: number;
|
|
16
|
+
predicateWeight: number;
|
|
17
|
+
valueDifferenceWeight: number;
|
|
18
|
+
claimConfidenceWeight: number;
|
|
19
|
+
sourceTrustWeight: number;
|
|
20
|
+
ambiguityPenalty: number;
|
|
21
|
+
rawScore: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Deterministic Heuristic Confidence Scorer
|
|
26
|
+
*
|
|
27
|
+
* Formula:
|
|
28
|
+
* rawConfidence = (subjectSimilarity * 0.30)
|
|
29
|
+
* + (predicateSimilarity * 0.30)
|
|
30
|
+
* + (valueDifferenceStrength * 0.20)
|
|
31
|
+
* + (avgClaimConfidence * 0.10)
|
|
32
|
+
* + (avgSourceTrust * 0.10)
|
|
33
|
+
* - ambiguityPenalty (0.25 if ambiguous or unparseable)
|
|
34
|
+
*
|
|
35
|
+
* Final score clamped to [0.0, 1.0] and rounded to 2 decimal places.
|
|
36
|
+
*/
|
|
37
|
+
export declare class ConfidenceScorer {
|
|
38
|
+
calculate(inputs: ConfidenceScoreInputs): ConfidenceScoreResult;
|
|
39
|
+
}
|
|
40
|
+
export declare const confidenceScorer: ConfidenceScorer;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic Heuristic Confidence Scorer
|
|
3
|
+
*
|
|
4
|
+
* Formula:
|
|
5
|
+
* rawConfidence = (subjectSimilarity * 0.30)
|
|
6
|
+
* + (predicateSimilarity * 0.30)
|
|
7
|
+
* + (valueDifferenceStrength * 0.20)
|
|
8
|
+
* + (avgClaimConfidence * 0.10)
|
|
9
|
+
* + (avgSourceTrust * 0.10)
|
|
10
|
+
* - ambiguityPenalty (0.25 if ambiguous or unparseable)
|
|
11
|
+
*
|
|
12
|
+
* Final score clamped to [0.0, 1.0] and rounded to 2 decimal places.
|
|
13
|
+
*/
|
|
14
|
+
export class ConfidenceScorer {
|
|
15
|
+
calculate(inputs) {
|
|
16
|
+
const subSim = Math.max(0, Math.min(1, inputs.subjectSimilarity));
|
|
17
|
+
const predSim = Math.max(0, Math.min(1, inputs.predicateSimilarity));
|
|
18
|
+
const diffStrength = inputs.valueComparable
|
|
19
|
+
? Math.max(0, Math.min(1, inputs.valueDifferenceStrength))
|
|
20
|
+
: 0.3;
|
|
21
|
+
const confA = inputs.claimAConfidence ?? 1.0;
|
|
22
|
+
const confB = inputs.claimBConfidence ?? 1.0;
|
|
23
|
+
const avgClaimConfidence = Math.max(0, Math.min(1, (confA + confB) / 2));
|
|
24
|
+
const trustA = inputs.sourceATrust ?? 1.0;
|
|
25
|
+
const trustB = inputs.sourceBTrust ?? 1.0;
|
|
26
|
+
const avgSourceTrust = Math.max(0, Math.min(1, (trustA + trustB) / 2));
|
|
27
|
+
const subjectWeight = subSim * 0.3;
|
|
28
|
+
const predicateWeight = predSim * 0.3;
|
|
29
|
+
const valueDifferenceWeight = diffStrength * 0.2;
|
|
30
|
+
const claimConfidenceWeight = avgClaimConfidence * 0.1;
|
|
31
|
+
const sourceTrustWeight = avgSourceTrust * 0.1;
|
|
32
|
+
let ambiguityPenalty = 0.0;
|
|
33
|
+
if (inputs.isAmbiguous || !inputs.valueComparable) {
|
|
34
|
+
ambiguityPenalty = 0.25;
|
|
35
|
+
}
|
|
36
|
+
const rawScore = subjectWeight +
|
|
37
|
+
predicateWeight +
|
|
38
|
+
valueDifferenceWeight +
|
|
39
|
+
claimConfidenceWeight +
|
|
40
|
+
sourceTrustWeight -
|
|
41
|
+
ambiguityPenalty;
|
|
42
|
+
const clampedConfidence = Math.max(0.0, Math.min(1.0, rawScore));
|
|
43
|
+
const roundedConfidence = Number(clampedConfidence.toFixed(2));
|
|
44
|
+
return {
|
|
45
|
+
confidence: roundedConfidence,
|
|
46
|
+
breakdown: {
|
|
47
|
+
subjectWeight: Number(subjectWeight.toFixed(3)),
|
|
48
|
+
predicateWeight: Number(predicateWeight.toFixed(3)),
|
|
49
|
+
valueDifferenceWeight: Number(valueDifferenceWeight.toFixed(3)),
|
|
50
|
+
claimConfidenceWeight: Number(claimConfidenceWeight.toFixed(3)),
|
|
51
|
+
sourceTrustWeight: Number(sourceTrustWeight.toFixed(3)),
|
|
52
|
+
ambiguityPenalty,
|
|
53
|
+
rawScore: Number(rawScore.toFixed(3)),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export const confidenceScorer = new ConfidenceScorer();
|
|
59
|
+
//# sourceMappingURL=confidenceScorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidenceScorer.js","sourceRoot":"","sources":["../../src/analysis/confidenceScorer.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,gBAAgB;IACpB,SAAS,CAAC,MAA6B;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe;YACzC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,uBAAuB,CAAC,CAAC;YAC1D,CAAC,CAAC,GAAG,CAAC;QAER,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,IAAI,GAAG,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,IAAI,GAAG,CAAC;QAC7C,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC;QAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAEvE,MAAM,aAAa,GAAG,MAAM,GAAG,GAAG,CAAC;QACnC,MAAM,eAAe,GAAG,OAAO,GAAG,GAAG,CAAC;QACtC,MAAM,qBAAqB,GAAG,YAAY,GAAG,GAAG,CAAC;QACjD,MAAM,qBAAqB,GAAG,kBAAkB,GAAG,GAAG,CAAC;QACvD,MAAM,iBAAiB,GAAG,cAAc,GAAG,GAAG,CAAC;QAE/C,IAAI,gBAAgB,GAAG,GAAG,CAAC;QAC3B,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YAClD,gBAAgB,GAAG,IAAI,CAAC;QAC1B,CAAC;QAED,MAAM,QAAQ,GACZ,aAAa;YACb,eAAe;YACf,qBAAqB;YACrB,qBAAqB;YACrB,iBAAiB;YACjB,gBAAgB,CAAC;QAEnB,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;QACjE,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/D,OAAO;YACL,UAAU,EAAE,iBAAiB;YAC7B,SAAS,EAAE;gBACT,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC/C,eAAe,EAAE,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACnD,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC/D,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC/D,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACvD,gBAAgB;gBAChB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;aACtC;SACF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Claim } from '../domain/entities/claim.js';
|
|
2
|
+
import { ClaimRelationship } from './claimRelationship.js';
|
|
3
|
+
export interface ContextAnalysisResult {
|
|
4
|
+
relationship: ClaimRelationship;
|
|
5
|
+
isContextCompatible: boolean;
|
|
6
|
+
compatibilityScore: number;
|
|
7
|
+
reason: string;
|
|
8
|
+
divergenceDimensions: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare class ContextAnalyzer {
|
|
11
|
+
analyze(claimA: Claim, claimB: Claim): ContextAnalysisResult;
|
|
12
|
+
}
|
|
13
|
+
export declare const contextAnalyzer: ContextAnalyzer;
|