wogiflow 2.4.1 → 2.4.3
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/.claude/docs/claude-code-compatibility.md +27 -0
- package/.claude/settings.json +1 -1
- package/.workflow/models/registry.json +1 -1
- package/package.json +4 -4
- package/scripts/MEMORY-ARCHITECTURE.md +1 -1
- package/scripts/base-workflow-step.js +136 -0
- package/scripts/flow-adaptive-learning.js +8 -9
- package/scripts/flow-aggregate.js +11 -6
- package/scripts/flow-api-index.js +4 -6
- package/scripts/flow-assumption-detector.js +0 -2
- package/scripts/flow-audit.js +15 -2
- package/scripts/flow-auto-context.js +8 -12
- package/scripts/flow-auto-learn.js +49 -49
- package/scripts/flow-background.js +5 -6
- package/scripts/flow-bridge-state.js +8 -10
- package/scripts/flow-bulk-loop.js +1 -3
- package/scripts/flow-bulk-orchestrator.js +1 -3
- package/scripts/flow-cascade-completion.js +0 -2
- package/scripts/flow-cascade.js +4 -4
- package/scripts/flow-checkpoint.js +10 -13
- package/scripts/flow-code-intelligence.js +10 -12
- package/scripts/flow-community-sync.js +4 -4
- package/scripts/flow-community.js +12 -20
- package/scripts/flow-config-defaults.js +0 -2
- package/scripts/flow-config-interactive.js +9 -5
- package/scripts/flow-config-loader.js +49 -92
- package/scripts/flow-config-substitution.js +0 -2
- package/scripts/flow-context-estimator.js +4 -4
- package/scripts/flow-context-init.js +10 -12
- package/scripts/flow-context-manager.js +0 -2
- package/scripts/flow-context-scoring.js +2 -2
- package/scripts/flow-contract-scan.js +6 -9
- package/scripts/flow-correct.js +29 -27
- package/scripts/flow-correction-detector.js +5 -1
- package/scripts/flow-damage-control.js +47 -54
- package/scripts/flow-decisions-merge.js +4 -14
- package/scripts/flow-diff.js +5 -8
- package/scripts/flow-done-gates.js +786 -0
- package/scripts/flow-done-report.js +123 -0
- package/scripts/flow-done.js +71 -717
- package/scripts/flow-entropy-monitor.js +1 -3
- package/scripts/flow-eval.js +5 -5
- package/scripts/flow-extraction-review.js +1 -0
- package/scripts/flow-failure-categories.js +0 -2
- package/scripts/flow-figma-confirm.js +5 -9
- package/scripts/flow-figma-generate.js +8 -10
- package/scripts/flow-figma-index.js +8 -10
- package/scripts/flow-figma-match.js +3 -5
- package/scripts/flow-figma-mcp-server.js +2 -4
- package/scripts/flow-figma-orchestrator.js +2 -3
- package/scripts/flow-figma-registry.js +2 -3
- package/scripts/flow-framework-resolver.js +0 -2
- package/scripts/flow-function-index.js +4 -6
- package/scripts/flow-gate-confidence.js +2 -2
- package/scripts/flow-gitignore.js +0 -2
- package/scripts/flow-guided-edit.js +5 -6
- package/scripts/flow-health.js +5 -6
- package/scripts/flow-hook-errors.js +6 -0
- package/scripts/flow-hook-status.js +263 -0
- package/scripts/flow-hooks.js +17 -29
- package/scripts/flow-http-client.js +9 -8
- package/scripts/flow-hybrid-interactive.js +7 -12
- package/scripts/flow-hybrid-test.js +12 -13
- package/scripts/flow-instruction-richness.js +1 -1
- package/scripts/flow-io.js +21 -4
- package/scripts/flow-knowledge-router.js +9 -3
- package/scripts/flow-learning-orchestrator.js +318 -13
- package/scripts/flow-links.js +5 -7
- package/scripts/flow-long-input-association.js +275 -0
- package/scripts/flow-long-input-chunking.js +1 -0
- package/scripts/flow-long-input-cli.js +0 -2
- package/scripts/flow-long-input-complexity.js +0 -2
- package/scripts/flow-long-input-constants.js +0 -2
- package/scripts/flow-long-input-contradictions.js +351 -0
- package/scripts/flow-long-input-detection.js +0 -2
- package/scripts/flow-long-input-passes.js +885 -0
- package/scripts/flow-long-input-stories.js +1 -1
- package/scripts/flow-long-input-voice.js +0 -2
- package/scripts/flow-long-input.js +425 -3005
- package/scripts/flow-loop-retry-learning.js +2 -3
- package/scripts/flow-lsp.js +3 -3
- package/scripts/flow-mcp-docs.js +3 -4
- package/scripts/flow-memory-db.js +6 -8
- package/scripts/flow-memory-sync.js +18 -11
- package/scripts/flow-metrics.js +1 -2
- package/scripts/flow-model-adapter.js +2 -3
- package/scripts/flow-model-config.js +72 -104
- package/scripts/flow-model-router.js +2 -2
- package/scripts/flow-model-types.js +0 -2
- package/scripts/flow-multi-approach.js +5 -6
- package/scripts/flow-orchestrate-context.js +3 -7
- package/scripts/flow-orchestrate-rollback.js +3 -8
- package/scripts/flow-orchestrate-state.js +8 -14
- package/scripts/flow-orchestrate-templates.js +2 -6
- package/scripts/flow-orchestrate-validator.js +5 -9
- package/scripts/flow-orchestrate.js +126 -103
- package/scripts/flow-output.js +0 -2
- package/scripts/flow-parallel.js +1 -1
- package/scripts/flow-paths.js +23 -2
- package/scripts/flow-pattern-enforcer.js +30 -28
- package/scripts/flow-pattern-extractor.js +3 -4
- package/scripts/flow-pending.js +0 -2
- package/scripts/flow-permissions.js +2 -3
- package/scripts/flow-plugin-registry.js +10 -12
- package/scripts/flow-prd-manager.js +1 -1
- package/scripts/flow-progress.js +7 -9
- package/scripts/flow-prompt-composer.js +3 -3
- package/scripts/flow-prompt-template.js +2 -2
- package/scripts/flow-providers.js +7 -4
- package/scripts/flow-registry-manager.js +7 -12
- package/scripts/flow-regression.js +9 -11
- package/scripts/flow-roadmap.js +2 -2
- package/scripts/flow-run-trace.js +16 -15
- package/scripts/flow-safety.js +2 -5
- package/scripts/flow-scanner-base.js +5 -7
- package/scripts/flow-scenario-engine.js +1 -5
- package/scripts/flow-security.js +29 -0
- package/scripts/flow-session-end.js +32 -41
- package/scripts/flow-session-learning.js +53 -49
- package/scripts/flow-setup-hooks.js +2 -3
- package/scripts/flow-skill-create.js +7 -12
- package/scripts/flow-skill-generator.js +12 -16
- package/scripts/flow-skill-learn.js +17 -8
- package/scripts/flow-skill-matcher.js +1 -2
- package/scripts/flow-spec-generator.js +2 -4
- package/scripts/flow-stack-wizard.js +5 -7
- package/scripts/flow-standards-learner.js +35 -16
- package/scripts/flow-start.js +2 -0
- package/scripts/flow-stats-collector.js +2 -2
- package/scripts/flow-status.js +10 -10
- package/scripts/flow-statusline-setup.js +2 -2
- package/scripts/flow-step-changelog.js +2 -3
- package/scripts/flow-step-comments.js +66 -81
- package/scripts/flow-step-complexity.js +50 -70
- package/scripts/flow-step-coverage.js +3 -5
- package/scripts/flow-step-knowledge.js +2 -3
- package/scripts/flow-step-pr-tests.js +64 -74
- package/scripts/flow-step-regression.js +3 -5
- package/scripts/flow-step-review.js +86 -103
- package/scripts/flow-step-security.js +111 -121
- package/scripts/flow-step-silent-failures.js +56 -83
- package/scripts/flow-step-simplifier.js +52 -70
- package/scripts/flow-story.js +4 -7
- package/scripts/flow-strict-adherence.js +3 -4
- package/scripts/flow-task-checkpoint.js +36 -5
- package/scripts/flow-task-enforcer.js +2 -24
- package/scripts/flow-tech-debt.js +1 -1
- package/scripts/flow-template-extractor.js +1 -0
- package/scripts/flow-templates.js +11 -13
- package/scripts/flow-test-api.js +9 -13
- package/scripts/flow-test-discovery.js +1 -1
- package/scripts/flow-test-generate.js +5 -9
- package/scripts/flow-test-integrity.js +3 -7
- package/scripts/flow-test-ui.js +5 -9
- package/scripts/flow-testing-deps.js +1 -3
- package/scripts/flow-tiered-learning.js +4 -4
- package/scripts/flow-todowrite-sync.js +1 -1
- package/scripts/flow-tokens.js +0 -2
- package/scripts/flow-verification-profile.js +6 -10
- package/scripts/flow-verify.js +12 -16
- package/scripts/flow-version-check.js +4 -12
- package/scripts/flow-webmcp-generator.js +3 -5
- package/scripts/flow-workflow-steps.js +0 -2
- package/scripts/flow-workflow.js +9 -11
- package/scripts/hooks/adapters/claude-code.js +2 -0
- package/scripts/hooks/core/commit-log-gate.js +21 -10
- package/scripts/hooks/core/config-change.js +1 -0
- package/scripts/hooks/core/extension-registry.js +0 -2
- package/scripts/hooks/core/instructions-loaded.js +1 -1
- package/scripts/hooks/core/observation-capture.js +5 -5
- package/scripts/hooks/core/phase-gate.js +5 -0
- package/scripts/hooks/core/post-compact.js +1 -12
- package/scripts/hooks/core/research-gate.js +2 -12
- package/scripts/hooks/core/routing-gate.js +6 -0
- package/scripts/hooks/core/task-completed.js +12 -0
- package/scripts/hooks/core/task-gate.js +27 -0
- package/scripts/hooks/core/worktree-lifecycle.js +1 -1
- package/scripts/hooks/entry/claude-code/config-change.js +6 -29
- package/scripts/hooks/entry/claude-code/instructions-loaded.js +5 -30
- package/scripts/hooks/entry/claude-code/post-compact.js +4 -31
- package/scripts/hooks/entry/claude-code/post-tool-use.js +121 -172
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +260 -361
- package/scripts/hooks/entry/claude-code/session-end.js +4 -28
- package/scripts/hooks/entry/claude-code/session-start.js +205 -243
- package/scripts/hooks/entry/claude-code/setup.js +8 -49
- package/scripts/hooks/entry/claude-code/stop.js +40 -72
- package/scripts/hooks/entry/claude-code/task-completed.js +4 -28
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +113 -195
- package/scripts/hooks/entry/claude-code/worktree-create.js +6 -25
- package/scripts/hooks/entry/claude-code/worktree-remove.js +6 -25
- package/scripts/hooks/entry/shared/hook-runner.js +99 -0
- package/scripts/hooks/entry/shared/read-stdin.js +0 -2
- package/scripts/registries/api-registry.js +0 -2
- package/scripts/registries/component-registry.js +5 -9
- package/scripts/registries/contract-scanner.js +2 -9
- package/scripts/registries/function-registry.js +0 -2
- package/scripts/registries/schema-registry.js +14 -18
- package/scripts/registries/service-registry.js +23 -27
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Long Input Processing - Contradiction Detection & Resolution
|
|
3
|
+
*
|
|
4
|
+
* Extracted from flow-long-input.js
|
|
5
|
+
* Handles contradiction detection between statements, orphan resolution via
|
|
6
|
+
* semantic expansion, correction phrase detection, and clarification persistence.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('node:fs');
|
|
10
|
+
const path = require('node:path');
|
|
11
|
+
const { safeJsonParse } = require('./flow-utils');
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
SEMANTIC_EXPANSIONS,
|
|
15
|
+
CORRECTION_PATTERNS,
|
|
16
|
+
ADDITIVE_PATTERNS
|
|
17
|
+
} = require('./flow-long-input-constants');
|
|
18
|
+
|
|
19
|
+
// These are injected via init()
|
|
20
|
+
let _loadActiveDigest = null;
|
|
21
|
+
let _calculateAssociationConfidence = null;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize with core functions from other modules.
|
|
25
|
+
* @param {Object} deps
|
|
26
|
+
*/
|
|
27
|
+
function init(deps) {
|
|
28
|
+
_loadActiveDigest = deps.loadActiveDigest;
|
|
29
|
+
_calculateAssociationConfidence = deps.calculateAssociationConfidence;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Detect contradictions between statements
|
|
34
|
+
*/
|
|
35
|
+
function detectContradictions(statements) {
|
|
36
|
+
const contradictions = [];
|
|
37
|
+
const meaningfulStatements = statements.filter(s => s.meaningful);
|
|
38
|
+
|
|
39
|
+
// Contradiction patterns
|
|
40
|
+
const opposites = [
|
|
41
|
+
['left', 'right'],
|
|
42
|
+
['top', 'bottom'],
|
|
43
|
+
['show', 'hide'],
|
|
44
|
+
['enable', 'disable'],
|
|
45
|
+
['add', 'remove'],
|
|
46
|
+
['include', 'exclude'],
|
|
47
|
+
['before', 'after'],
|
|
48
|
+
['above', 'below']
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < meaningfulStatements.length; i++) {
|
|
52
|
+
for (let j = i + 1; j < meaningfulStatements.length; j++) {
|
|
53
|
+
const stmt1 = meaningfulStatements[i];
|
|
54
|
+
const stmt2 = meaningfulStatements[j];
|
|
55
|
+
|
|
56
|
+
// Only check statements in same topic
|
|
57
|
+
if (stmt1.topic_id !== stmt2.topic_id) continue;
|
|
58
|
+
|
|
59
|
+
const text1 = stmt1.text.toLowerCase();
|
|
60
|
+
const text2 = stmt2.text.toLowerCase();
|
|
61
|
+
|
|
62
|
+
// Check for opposite words
|
|
63
|
+
for (const [word1, word2] of opposites) {
|
|
64
|
+
if ((text1.includes(word1) && text2.includes(word2)) ||
|
|
65
|
+
(text1.includes(word2) && text2.includes(word1))) {
|
|
66
|
+
contradictions.push({
|
|
67
|
+
statement1_id: stmt1.id,
|
|
68
|
+
statement2_id: stmt2.id,
|
|
69
|
+
type: 'opposite_values',
|
|
70
|
+
attribute: `${word1}/${word2}`,
|
|
71
|
+
resolution: 'pending'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check for number conflicts (same attribute, different values)
|
|
77
|
+
const numbers1 = text1.match(/\d+/g);
|
|
78
|
+
const numbers2 = text2.match(/\d+/g);
|
|
79
|
+
if (numbers1 && numbers2) {
|
|
80
|
+
// Simple heuristic: if both mention numbers in similar context
|
|
81
|
+
const commonWords = text1.split(/\s+/).filter(w => text2.includes(w) && w.length > 3);
|
|
82
|
+
if (commonWords.length > 2 && numbers1[0] !== numbers2[0]) {
|
|
83
|
+
contradictions.push({
|
|
84
|
+
statement1_id: stmt1.id,
|
|
85
|
+
statement2_id: stmt2.id,
|
|
86
|
+
type: 'quantity_conflict',
|
|
87
|
+
values: [numbers1[0], numbers2[0]],
|
|
88
|
+
resolution: 'pending'
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return contradictions;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Enhanced confidence calculation with semantic expansion
|
|
100
|
+
*/
|
|
101
|
+
function calculateExpandedConfidence(statement, topic) {
|
|
102
|
+
let confidence = 0.5;
|
|
103
|
+
const reasons = [];
|
|
104
|
+
const statementLower = statement.text.toLowerCase();
|
|
105
|
+
|
|
106
|
+
// Standard matching first
|
|
107
|
+
const { confidence: baseConf, reasons: baseReasons } = _calculateAssociationConfidence(statement, topic);
|
|
108
|
+
if (baseConf > confidence) {
|
|
109
|
+
confidence = baseConf;
|
|
110
|
+
reasons.push(...baseReasons);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Semantic expansion - check synonyms
|
|
114
|
+
for (const [term, synonyms] of Object.entries(SEMANTIC_EXPANSIONS)) {
|
|
115
|
+
const allTerms = [term, ...synonyms];
|
|
116
|
+
const topicTitle = topic.title.toLowerCase();
|
|
117
|
+
const topicKeywords = (topic.keywords || []).map(k => k.toLowerCase());
|
|
118
|
+
|
|
119
|
+
for (const syn of allTerms) {
|
|
120
|
+
// Statement contains synonym and topic contains related term
|
|
121
|
+
if (statementLower.includes(syn)) {
|
|
122
|
+
for (const related of allTerms) {
|
|
123
|
+
if (topicTitle.includes(related) || topicKeywords.includes(related)) {
|
|
124
|
+
confidence = Math.max(confidence, 0.7);
|
|
125
|
+
reasons.push(`semantic_expansion:${syn}->${related}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return { confidence, reasons };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Try to resolve a single orphan statement
|
|
137
|
+
*/
|
|
138
|
+
function resolveOrphan(orphan, topics) {
|
|
139
|
+
const candidates = [];
|
|
140
|
+
|
|
141
|
+
// Try enhanced matching against all topics
|
|
142
|
+
for (const topic of topics) {
|
|
143
|
+
const { confidence, reasons } = calculateExpandedConfidence(orphan, topic);
|
|
144
|
+
if (confidence >= 0.5) {
|
|
145
|
+
candidates.push({ topic, confidence, reasons });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Sort by confidence
|
|
150
|
+
candidates.sort((a, b) => b.confidence - a.confidence);
|
|
151
|
+
|
|
152
|
+
// Resolution decision
|
|
153
|
+
if (candidates.length === 0) {
|
|
154
|
+
return {
|
|
155
|
+
resolved: false,
|
|
156
|
+
method: 'no_match',
|
|
157
|
+
confidence: 0
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const best = candidates[0];
|
|
162
|
+
|
|
163
|
+
// Clear winner
|
|
164
|
+
if (best.confidence >= 0.6 && (candidates.length === 1 || best.confidence - candidates[1].confidence > 0.15)) {
|
|
165
|
+
return {
|
|
166
|
+
resolved: true,
|
|
167
|
+
method: 'semantic_expansion',
|
|
168
|
+
topic_id: best.topic.id,
|
|
169
|
+
confidence: best.confidence,
|
|
170
|
+
reasons: best.reasons
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Ambiguous - multiple close matches
|
|
175
|
+
if (candidates.length > 1 && candidates[0].confidence - candidates[1].confidence < 0.1) {
|
|
176
|
+
return {
|
|
177
|
+
resolved: false,
|
|
178
|
+
method: 'ambiguous',
|
|
179
|
+
possible_topics: candidates.slice(0, 3).map(c => c.topic.id),
|
|
180
|
+
confidence: best.confidence
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Low confidence winner
|
|
185
|
+
return {
|
|
186
|
+
resolved: best.confidence >= 0.5,
|
|
187
|
+
method: best.confidence >= 0.5 ? 'context_reanalysis' : 'low_confidence',
|
|
188
|
+
topic_id: best.confidence >= 0.5 ? best.topic.id : null,
|
|
189
|
+
confidence: best.confidence,
|
|
190
|
+
reasons: best.reasons
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check if statement contains a correction phrase
|
|
196
|
+
*/
|
|
197
|
+
function detectCorrectionPhrase(text) {
|
|
198
|
+
for (const { pattern, name, weight } of CORRECTION_PATTERNS) {
|
|
199
|
+
if (pattern.test(text)) {
|
|
200
|
+
return { detected: true, phrase: name, weight };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return { detected: false, phrase: null, weight: 0 };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Check if statement is additive (not a real contradiction)
|
|
208
|
+
*/
|
|
209
|
+
function isAdditive(text) {
|
|
210
|
+
return ADDITIVE_PATTERNS.some(pattern => pattern.test(text));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Calculate resolution confidence for a contradiction
|
|
215
|
+
*/
|
|
216
|
+
function calculateResolutionConfidence(stmt1, stmt2, contradiction) {
|
|
217
|
+
let confidence = 0.5;
|
|
218
|
+
let reasons = [];
|
|
219
|
+
|
|
220
|
+
// Check for correction phrase in stmt2 (later statement)
|
|
221
|
+
const correction = detectCorrectionPhrase(stmt2.text);
|
|
222
|
+
if (correction.detected) {
|
|
223
|
+
confidence += correction.weight;
|
|
224
|
+
reasons.push(`correction_phrase:${correction.phrase}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Same speaker increases confidence
|
|
228
|
+
if (stmt1.speaker && stmt2.speaker && stmt1.speaker === stmt2.speaker) {
|
|
229
|
+
confidence += 0.15;
|
|
230
|
+
reasons.push('same_speaker');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Position difference - later statements typically override
|
|
234
|
+
const positionDiff = stmt2.position - stmt1.position;
|
|
235
|
+
if (positionDiff > 500) { // Significant distance
|
|
236
|
+
confidence += 0.1;
|
|
237
|
+
reasons.push('later_position');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Check if stmt2 explicitly references the attribute
|
|
241
|
+
const attr = contradiction.attribute;
|
|
242
|
+
if (attr) {
|
|
243
|
+
const [word1, word2] = attr.split('/');
|
|
244
|
+
if (stmt2.text.toLowerCase().includes(word1) || stmt2.text.toLowerCase().includes(word2)) {
|
|
245
|
+
confidence += 0.1;
|
|
246
|
+
reasons.push('explicit_attribute_reference');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Check for additive pattern - might not be a real contradiction
|
|
251
|
+
if (isAdditive(stmt2.text)) {
|
|
252
|
+
confidence = 0.3; // Low confidence - likely not a contradiction
|
|
253
|
+
reasons = ['additive_pattern'];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
confidence: Math.min(confidence, 1.0),
|
|
258
|
+
reasons,
|
|
259
|
+
winner: confidence >= 0.5 ? stmt2.id : null,
|
|
260
|
+
isAdditive: isAdditive(stmt2.text)
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Generate clarification question for unresolved contradiction
|
|
266
|
+
*/
|
|
267
|
+
function generateContradictionQuestion(stmt1, stmt2, contradiction) {
|
|
268
|
+
const attr = contradiction.attribute || 'value';
|
|
269
|
+
const [val1, val2] = attr.split('/');
|
|
270
|
+
|
|
271
|
+
// Extract the actual values from statements if possible
|
|
272
|
+
const extractValue = (text, hints) => {
|
|
273
|
+
for (const hint of hints || []) {
|
|
274
|
+
if (text.toLowerCase().includes(hint.toLowerCase())) {
|
|
275
|
+
return hint;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return text.slice(0, 50);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const value1 = val1 || extractValue(stmt1.text, []);
|
|
282
|
+
const value2 = val2 || extractValue(stmt2.text, []);
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
question: `You mentioned "${stmt1.text.slice(0, 60)}" but later said "${stmt2.text.slice(0, 60)}". Which do you prefer?`,
|
|
286
|
+
options: [
|
|
287
|
+
{ id: 'opt-1', text: value1, statement_id: stmt1.id },
|
|
288
|
+
{ id: 'opt-2', text: value2, statement_id: stmt2.id },
|
|
289
|
+
{ id: 'opt-3', text: 'Both are needed', resolution: 'keep_both' }
|
|
290
|
+
],
|
|
291
|
+
attribute: attr
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Save clarifications to file
|
|
297
|
+
*/
|
|
298
|
+
function saveClarifications(clarifications) {
|
|
299
|
+
const activeDigest = _loadActiveDigest();
|
|
300
|
+
if (!activeDigest.session.digest_path) {
|
|
301
|
+
throw new Error('No active digest session');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const clarPath = path.join(activeDigest.session.digest_path, 'clarifications.json');
|
|
305
|
+
fs.writeFileSync(clarPath, JSON.stringify(clarifications, null, 2));
|
|
306
|
+
return clarifications;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Load clarifications from file
|
|
311
|
+
*/
|
|
312
|
+
function loadClarifications() {
|
|
313
|
+
const activeDigest = _loadActiveDigest();
|
|
314
|
+
if (!activeDigest.session.digest_path) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const clarPath = path.join(activeDigest.session.digest_path, 'clarifications.json');
|
|
319
|
+
const defaultClarifications = {
|
|
320
|
+
questions: [],
|
|
321
|
+
contradictions: [],
|
|
322
|
+
metadata: {
|
|
323
|
+
total_questions: 0,
|
|
324
|
+
answered_questions: 0,
|
|
325
|
+
pending_questions: 0,
|
|
326
|
+
total_contradictions: 0,
|
|
327
|
+
resolved_contradictions: 0,
|
|
328
|
+
auto_resolved_count: 0,
|
|
329
|
+
user_resolved_count: 0
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
const data = safeJsonParse(clarPath, null);
|
|
333
|
+
if (!data) return defaultClarifications;
|
|
334
|
+
if (!data.questions) data.questions = [];
|
|
335
|
+
if (!data.contradictions) data.contradictions = [];
|
|
336
|
+
if (!data.metadata) data.metadata = defaultClarifications.metadata;
|
|
337
|
+
return data;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
module.exports = {
|
|
341
|
+
init,
|
|
342
|
+
detectContradictions,
|
|
343
|
+
calculateExpandedConfidence,
|
|
344
|
+
resolveOrphan,
|
|
345
|
+
detectCorrectionPhrase,
|
|
346
|
+
isAdditive,
|
|
347
|
+
calculateResolutionConfidence,
|
|
348
|
+
generateContradictionQuestion,
|
|
349
|
+
saveClarifications,
|
|
350
|
+
loadClarifications
|
|
351
|
+
};
|