agentic-qe 3.7.21 → 3.8.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/.claude/helpers/brain-checkpoint.cjs +4 -1
- package/.claude/helpers/statusline-v3.cjs +3 -1
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +45 -0
- package/README.md +2 -14
- package/assets/helpers/statusline-v3.cjs +3 -1
- package/dist/cli/brain-commands.js +6 -10
- package/dist/cli/bundle.js +7441 -4327
- package/dist/cli/commands/audit.d.ts +43 -0
- package/dist/cli/commands/audit.js +125 -0
- package/dist/cli/commands/hooks.js +29 -6
- package/dist/cli/commands/init.js +1 -73
- package/dist/cli/commands/learning.js +270 -13
- package/dist/cli/commands/ruvector-commands.d.ts +15 -0
- package/dist/cli/commands/ruvector-commands.js +271 -0
- package/dist/cli/handlers/init-handler.d.ts +0 -1
- package/dist/cli/handlers/init-handler.js +0 -6
- package/dist/cli/index.js +4 -2
- package/dist/context/sources/defect-source.js +2 -2
- package/dist/context/sources/memory-source.js +2 -2
- package/dist/context/sources/requirements-source.js +2 -2
- package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
- package/dist/coordination/behavior-tree/decorators.js +251 -0
- package/dist/coordination/behavior-tree/index.d.ts +12 -0
- package/dist/coordination/behavior-tree/index.js +15 -0
- package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
- package/dist/coordination/behavior-tree/nodes.js +338 -0
- package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
- package/dist/coordination/behavior-tree/qe-trees.js +181 -0
- package/dist/coordination/coherence-action-gate.d.ts +284 -0
- package/dist/coordination/coherence-action-gate.js +512 -0
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +8 -0
- package/dist/coordination/reasoning-qec.d.ts +315 -0
- package/dist/coordination/reasoning-qec.js +585 -0
- package/dist/coordination/task-executor.d.ts +16 -0
- package/dist/coordination/task-executor.js +99 -0
- package/dist/coordination/workflow-orchestrator.d.ts +29 -0
- package/dist/coordination/workflow-orchestrator.js +42 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
- package/dist/domains/visual-accessibility/index.d.ts +1 -0
- package/dist/domains/visual-accessibility/index.js +4 -0
- package/dist/governance/coherence-validator.d.ts +112 -0
- package/dist/governance/coherence-validator.js +180 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/witness-chain.d.ts +311 -0
- package/dist/governance/witness-chain.js +509 -0
- package/dist/init/index.d.ts +0 -2
- package/dist/init/index.js +0 -1
- package/dist/init/init-wizard-steps.d.ts +10 -0
- package/dist/init/init-wizard-steps.js +87 -1
- package/dist/init/init-wizard.d.ts +1 -9
- package/dist/init/init-wizard.js +3 -69
- package/dist/init/orchestrator.js +0 -1
- package/dist/init/phases/01-detection.js +0 -27
- package/dist/init/phases/07-hooks.js +6 -4
- package/dist/init/phases/phase-interface.d.ts +0 -1
- package/dist/init/settings-merge.js +1 -1
- package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
- package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
- package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
- package/dist/integrations/browser/qe-dashboard/index.js +15 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
- package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
- package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
- package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
- package/dist/integrations/ruvector/cognitive-container.js +306 -0
- package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
- package/dist/integrations/ruvector/coherence-gate.js +631 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
- package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
- package/dist/integrations/ruvector/dither-adapter.js +295 -0
- package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
- package/dist/integrations/ruvector/domain-transfer.js +220 -0
- package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
- package/dist/integrations/ruvector/feature-flags.js +167 -2
- package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
- package/dist/integrations/ruvector/filter-adapter.js +285 -0
- package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
- package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
- package/dist/integrations/ruvector/index.d.ts +8 -2
- package/dist/integrations/ruvector/index.js +18 -2
- package/dist/integrations/ruvector/interfaces.d.ts +40 -0
- package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
- package/dist/integrations/ruvector/sona-persistence.js +162 -0
- package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
- package/dist/integrations/ruvector/sona-three-loop.js +814 -0
- package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
- package/dist/integrations/ruvector/sona-wrapper.js +147 -3
- package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
- package/dist/integrations/ruvector/spectral-math.js +254 -0
- package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
- package/dist/integrations/ruvector/temporal-compression.js +318 -0
- package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
- package/dist/integrations/ruvector/thompson-sampler.js +118 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
- package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
- package/dist/integrations/ruvector/transfer-verification.js +115 -0
- package/dist/kernel/hnsw-adapter.d.ts +52 -1
- package/dist/kernel/hnsw-adapter.js +139 -4
- package/dist/kernel/hnsw-index-provider.d.ts +5 -0
- package/dist/kernel/native-hnsw-backend.d.ts +110 -0
- package/dist/kernel/native-hnsw-backend.js +408 -0
- package/dist/kernel/unified-memory.js +5 -6
- package/dist/learning/aqe-learning-engine.d.ts +2 -0
- package/dist/learning/aqe-learning-engine.js +65 -0
- package/dist/learning/experience-capture-middleware.js +20 -0
- package/dist/learning/experience-capture.d.ts +10 -0
- package/dist/learning/experience-capture.js +34 -0
- package/dist/learning/index.d.ts +2 -2
- package/dist/learning/index.js +4 -4
- package/dist/learning/metrics-tracker.d.ts +11 -0
- package/dist/learning/metrics-tracker.js +29 -13
- package/dist/learning/pattern-lifecycle.d.ts +30 -1
- package/dist/learning/pattern-lifecycle.js +92 -20
- package/dist/learning/pattern-store.d.ts +8 -0
- package/dist/learning/pattern-store.js +8 -2
- package/dist/learning/qe-unified-memory.js +1 -28
- package/dist/learning/regret-tracker.d.ts +201 -0
- package/dist/learning/regret-tracker.js +361 -0
- package/dist/mcp/bundle.js +5915 -474
- package/dist/routing/index.d.ts +4 -2
- package/dist/routing/index.js +3 -1
- package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
- package/dist/routing/neural-tiny-dancer-router.js +514 -0
- package/dist/routing/queen-integration.js +5 -5
- package/dist/routing/routing-config.d.ts +6 -0
- package/dist/routing/routing-config.js +1 -0
- package/dist/routing/simple-neural-router.d.ts +76 -0
- package/dist/routing/simple-neural-router.js +202 -0
- package/dist/routing/tiny-dancer-router.d.ts +20 -1
- package/dist/routing/tiny-dancer-router.js +21 -2
- package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
- package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-types.js +10 -0
- package/dist/test-scheduling/index.d.ts +1 -0
- package/dist/test-scheduling/index.js +4 -0
- package/dist/test-scheduling/pipeline.d.ts +8 -0
- package/dist/test-scheduling/pipeline.js +28 -0
- package/package.json +6 -2
- package/dist/cli/commands/migrate.d.ts +0 -9
- package/dist/cli/commands/migrate.js +0 -566
- package/dist/init/init-wizard-migration.d.ts +0 -52
- package/dist/init/init-wizard-migration.js +0 -345
- package/dist/init/migration/config-migrator.d.ts +0 -31
- package/dist/init/migration/config-migrator.js +0 -149
- package/dist/init/migration/data-migrator.d.ts +0 -72
- package/dist/init/migration/data-migrator.js +0 -232
- package/dist/init/migration/detector.d.ts +0 -44
- package/dist/init/migration/detector.js +0 -105
- package/dist/init/migration/index.d.ts +0 -8
- package/dist/init/migration/index.js +0 -8
- package/dist/learning/v2-to-v3-migration.d.ts +0 -86
- package/dist/learning/v2-to-v3-migration.js +0 -529
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Path Consensus Reasoning Validator - Task 4.5
|
|
3
|
+
*
|
|
4
|
+
* Applies error correction to AI reasoning using three independent paths.
|
|
5
|
+
* Generates multiple independent reasoning chains for critical decisions,
|
|
6
|
+
* extracts syndrome locations (disagreements between paths), and applies
|
|
7
|
+
* confidence-weighted voting to produce a high-confidence result.
|
|
8
|
+
*
|
|
9
|
+
* Use cases:
|
|
10
|
+
* - Test generation validation
|
|
11
|
+
* - Security audit consensus
|
|
12
|
+
* - Defect triage decisions
|
|
13
|
+
*
|
|
14
|
+
* TypeScript implementation (no native package exists for reasoning QEC —
|
|
15
|
+
* consensus logic doesn't benefit from native computation).
|
|
16
|
+
*
|
|
17
|
+
* @module coordination/reasoning-qec
|
|
18
|
+
* @see docs/research/ruvector-quantum-solvers.md
|
|
19
|
+
*/
|
|
20
|
+
import { createLogger } from '../logging/logger-factory.js';
|
|
21
|
+
import { getRuVectorFeatureFlags } from '../integrations/ruvector/feature-flags.js';
|
|
22
|
+
const logger = createLogger('ReasoningQEC');
|
|
23
|
+
/**
|
|
24
|
+
* Default configuration values.
|
|
25
|
+
*/
|
|
26
|
+
export const DEFAULT_QEC_CONFIG = {
|
|
27
|
+
minPaths: 3,
|
|
28
|
+
confidenceThreshold: 0.5,
|
|
29
|
+
majorityThreshold: 0.5,
|
|
30
|
+
useNativeBackend: true,
|
|
31
|
+
votingMethod: 'weighted',
|
|
32
|
+
};
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Strategy Generators
|
|
35
|
+
// ============================================================================
|
|
36
|
+
/**
|
|
37
|
+
* Strategy registry: maps problem types to path generation approaches.
|
|
38
|
+
* Each strategy produces slightly different reasoning perspectives.
|
|
39
|
+
*/
|
|
40
|
+
const STRATEGY_PERSPECTIVES = {
|
|
41
|
+
'test-generation': [
|
|
42
|
+
'specification-driven',
|
|
43
|
+
'boundary-analysis',
|
|
44
|
+
'mutation-testing',
|
|
45
|
+
],
|
|
46
|
+
'security-audit': [
|
|
47
|
+
'threat-modeling',
|
|
48
|
+
'attack-surface',
|
|
49
|
+
'defense-in-depth',
|
|
50
|
+
],
|
|
51
|
+
'defect-triage': [
|
|
52
|
+
'root-cause-analysis',
|
|
53
|
+
'impact-assessment',
|
|
54
|
+
'risk-prioritization',
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
const DEFAULT_PERSPECTIVES = [
|
|
58
|
+
'analytical',
|
|
59
|
+
'empirical',
|
|
60
|
+
'heuristic',
|
|
61
|
+
];
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Native Backend Probe
|
|
64
|
+
// ============================================================================
|
|
65
|
+
/**
|
|
66
|
+
* Attempt to load the ruqu-exotic native backend.
|
|
67
|
+
* Returns null if unavailable (TypeScript fallback is used).
|
|
68
|
+
*/
|
|
69
|
+
let nativeBackend = null;
|
|
70
|
+
let nativeProbeComplete = false;
|
|
71
|
+
/**
|
|
72
|
+
* Check for native QEC backend.
|
|
73
|
+
* No native package exists — always returns false.
|
|
74
|
+
* The TypeScript majority-vote implementation is used.
|
|
75
|
+
*/
|
|
76
|
+
async function probeNativeBackend() {
|
|
77
|
+
if (nativeProbeComplete) {
|
|
78
|
+
return nativeBackend !== null;
|
|
79
|
+
}
|
|
80
|
+
nativeBackend = null;
|
|
81
|
+
nativeProbeComplete = true;
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// ============================================================================
|
|
85
|
+
// ReasoningQEC Class
|
|
86
|
+
// ============================================================================
|
|
87
|
+
/**
|
|
88
|
+
* Multi-Path Consensus Reasoning Validator.
|
|
89
|
+
*
|
|
90
|
+
* Named QEC by analogy with quantum error correction; implements consensus
|
|
91
|
+
* voting across multiple reasoning paths, not quantum algorithms.
|
|
92
|
+
*
|
|
93
|
+
* Generates multiple independent reasoning paths for a given problem,
|
|
94
|
+
* extracts syndrome locations where paths disagree, and applies
|
|
95
|
+
* confidence-weighted (or simple majority) voting to produce a
|
|
96
|
+
* high-confidence result.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const qec = new ReasoningQEC();
|
|
101
|
+
*
|
|
102
|
+
* const problem: ReasoningProblem = {
|
|
103
|
+
* type: 'security-audit',
|
|
104
|
+
* context: { file: 'auth.ts', finding: 'potential XSS' },
|
|
105
|
+
* steps: ['Analyze input handling', 'Check sanitization', 'Evaluate risk'],
|
|
106
|
+
* };
|
|
107
|
+
*
|
|
108
|
+
* const paths = qec.generatePaths(problem);
|
|
109
|
+
* const syndromes = qec.extractSyndromes(paths);
|
|
110
|
+
* const corrected = qec.correctErrors(paths, syndromes);
|
|
111
|
+
* const validation = qec.validate(corrected);
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export class ReasoningQEC {
|
|
115
|
+
config;
|
|
116
|
+
nativeAvailable = false;
|
|
117
|
+
constructor(config = {}) {
|
|
118
|
+
this.config = { ...DEFAULT_QEC_CONFIG, ...config };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Initialize the engine, probing for the native backend if configured.
|
|
122
|
+
* Call this once before using generate/extract/correct methods.
|
|
123
|
+
* If not called, the engine works in pure TypeScript mode.
|
|
124
|
+
*/
|
|
125
|
+
async initialize() {
|
|
126
|
+
if (this.config.useNativeBackend) {
|
|
127
|
+
const flags = getRuVectorFeatureFlags();
|
|
128
|
+
if (flags.useQEFlashAttention || flags.useQEGNNIndex) {
|
|
129
|
+
this.nativeAvailable = await probeNativeBackend();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Generate independent reasoning paths for a problem.
|
|
135
|
+
*
|
|
136
|
+
* Each path represents a different analytical perspective on the problem,
|
|
137
|
+
* producing its own step-by-step reasoning chain and conclusion.
|
|
138
|
+
*
|
|
139
|
+
* @param problem - The reasoning problem to analyze
|
|
140
|
+
* @returns Array of independent reasoning paths (minimum 3)
|
|
141
|
+
*/
|
|
142
|
+
generatePaths(problem) {
|
|
143
|
+
const numPaths = Math.max(this.config.minPaths, 3);
|
|
144
|
+
const perspectives = STRATEGY_PERSPECTIVES[problem.type] ?? DEFAULT_PERSPECTIVES;
|
|
145
|
+
const paths = [];
|
|
146
|
+
for (let pathId = 0; pathId < numPaths; pathId++) {
|
|
147
|
+
const perspective = perspectives[pathId % perspectives.length];
|
|
148
|
+
const steps = this.generatePathSteps(problem, pathId, perspective);
|
|
149
|
+
const conclusion = this.deriveConclusion(steps, perspective);
|
|
150
|
+
const confidence = this.calculatePathConfidence(steps);
|
|
151
|
+
paths.push({
|
|
152
|
+
id: pathId,
|
|
153
|
+
steps,
|
|
154
|
+
conclusion,
|
|
155
|
+
confidence,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
logger.debug(`Generated ${paths.length} reasoning paths for problem type: ${problem.type}`);
|
|
159
|
+
return paths;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Extract syndromes (disagreement locations) from reasoning paths.
|
|
163
|
+
*
|
|
164
|
+
* Compares all paths step-by-step and identifies indices where
|
|
165
|
+
* paths reach different conclusions. Severity is classified as:
|
|
166
|
+
* - minor: only one path disagrees (easily correctable)
|
|
167
|
+
* - major: paths are split (no clear majority)
|
|
168
|
+
* - critical: all paths disagree (low confidence in any correction)
|
|
169
|
+
*
|
|
170
|
+
* @param paths - Array of reasoning paths to compare
|
|
171
|
+
* @returns Array of syndromes identifying disagreement locations
|
|
172
|
+
*/
|
|
173
|
+
extractSyndromes(paths) {
|
|
174
|
+
if (paths.length < 2) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
const syndromes = [];
|
|
178
|
+
const maxSteps = Math.max(...paths.map(p => p.steps.length));
|
|
179
|
+
for (let stepIdx = 0; stepIdx < maxSteps; stepIdx++) {
|
|
180
|
+
const conclusions = new Map();
|
|
181
|
+
for (const path of paths) {
|
|
182
|
+
const step = path.steps[stepIdx];
|
|
183
|
+
if (!step)
|
|
184
|
+
continue;
|
|
185
|
+
const existing = conclusions.get(step.conclusion) ?? [];
|
|
186
|
+
existing.push(path.id);
|
|
187
|
+
conclusions.set(step.conclusion, existing);
|
|
188
|
+
}
|
|
189
|
+
// If all conclusions are the same, no syndrome at this step
|
|
190
|
+
if (conclusions.size <= 1) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const disagreements = [...conclusions.entries()].map(([conclusion, pathIds]) => pathIds.map(pathId => ({ pathId, conclusion }))).flat();
|
|
194
|
+
const severity = this.classifySyndromeSeverity(conclusions, paths.length);
|
|
195
|
+
syndromes.push({
|
|
196
|
+
stepIndex: stepIdx,
|
|
197
|
+
disagreements,
|
|
198
|
+
severity,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
// Also check for conclusion-level disagreement
|
|
202
|
+
const conclusionMap = new Map();
|
|
203
|
+
for (const path of paths) {
|
|
204
|
+
const existing = conclusionMap.get(path.conclusion) ?? [];
|
|
205
|
+
existing.push(path.id);
|
|
206
|
+
conclusionMap.set(path.conclusion, existing);
|
|
207
|
+
}
|
|
208
|
+
if (conclusionMap.size > 1) {
|
|
209
|
+
const disagreements = [...conclusionMap.entries()].map(([conclusion, pathIds]) => pathIds.map(pathId => ({ pathId, conclusion }))).flat();
|
|
210
|
+
const severity = this.classifySyndromeSeverity(conclusionMap, paths.length);
|
|
211
|
+
syndromes.push({
|
|
212
|
+
stepIndex: -1, // Conclusion-level syndrome
|
|
213
|
+
disagreements,
|
|
214
|
+
severity,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
logger.debug(`Extracted ${syndromes.length} syndromes: ` +
|
|
218
|
+
`${syndromes.filter(s => s.severity === 'critical').length} critical, ` +
|
|
219
|
+
`${syndromes.filter(s => s.severity === 'major').length} major, ` +
|
|
220
|
+
`${syndromes.filter(s => s.severity === 'minor').length} minor`);
|
|
221
|
+
return syndromes;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Correct errors using voting across paths.
|
|
225
|
+
*
|
|
226
|
+
* For each step, the conclusion with the highest vote weight among paths
|
|
227
|
+
* is selected. When votingMethod is 'weighted', path confidence is used
|
|
228
|
+
* as vote weight. When 'majority', simple count-based voting is used.
|
|
229
|
+
* If no clear majority exists, the highest-weighted conclusion is used
|
|
230
|
+
* but confidence is reduced.
|
|
231
|
+
*
|
|
232
|
+
* @param paths - Array of reasoning paths
|
|
233
|
+
* @param syndromes - Array of extracted syndromes
|
|
234
|
+
* @returns Corrected reasoning with applied corrections
|
|
235
|
+
*/
|
|
236
|
+
correctErrors(paths, syndromes) {
|
|
237
|
+
if (paths.length === 0) {
|
|
238
|
+
return {
|
|
239
|
+
steps: [],
|
|
240
|
+
conclusion: '',
|
|
241
|
+
confidence: 0,
|
|
242
|
+
corrections: [],
|
|
243
|
+
syndromeCount: syndromes.length,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const syndromeStepIndices = new Set(syndromes.filter(s => s.stepIndex >= 0).map(s => s.stepIndex));
|
|
247
|
+
const maxSteps = Math.max(...paths.map(p => p.steps.length));
|
|
248
|
+
const correctedSteps = [];
|
|
249
|
+
const corrections = [];
|
|
250
|
+
for (let stepIdx = 0; stepIdx < maxSteps; stepIdx++) {
|
|
251
|
+
if (syndromeStepIndices.has(stepIdx)) {
|
|
252
|
+
const { step, correction } = this.correctStep(paths, stepIdx);
|
|
253
|
+
correctedSteps.push(step);
|
|
254
|
+
if (correction) {
|
|
255
|
+
corrections.push(correction);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
// No disagreement at this step — use the first path's step
|
|
260
|
+
const baseStep = paths[0].steps[stepIdx];
|
|
261
|
+
if (baseStep) {
|
|
262
|
+
correctedSteps.push({ ...baseStep });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Correct the final conclusion using majority vote
|
|
267
|
+
const conclusion = this.correctConclusion(paths);
|
|
268
|
+
const confidence = this.calculateCorrectedConfidence(paths, syndromes);
|
|
269
|
+
const result = {
|
|
270
|
+
steps: correctedSteps,
|
|
271
|
+
conclusion,
|
|
272
|
+
confidence,
|
|
273
|
+
corrections,
|
|
274
|
+
syndromeCount: syndromes.length,
|
|
275
|
+
};
|
|
276
|
+
logger.debug(`Error correction applied: ${corrections.length} corrections, ` +
|
|
277
|
+
`confidence: ${confidence.toFixed(3)}`);
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Validate a corrected reasoning chain.
|
|
282
|
+
*
|
|
283
|
+
* Checks for low confidence, missing majority, inconsistent evidence,
|
|
284
|
+
* and all-divergent conditions. Returns a validation result indicating
|
|
285
|
+
* whether the corrected reasoning is trustworthy.
|
|
286
|
+
*
|
|
287
|
+
* @param corrected - The corrected reasoning to validate
|
|
288
|
+
* @returns Validation result with confidence and any issues found
|
|
289
|
+
*/
|
|
290
|
+
validate(corrected) {
|
|
291
|
+
const issues = [];
|
|
292
|
+
// Check overall confidence
|
|
293
|
+
if (corrected.confidence < this.config.confidenceThreshold) {
|
|
294
|
+
issues.push({
|
|
295
|
+
stepIndex: -1,
|
|
296
|
+
type: 'low-confidence',
|
|
297
|
+
description: `Overall confidence ${corrected.confidence.toFixed(3)} is below ` +
|
|
298
|
+
`threshold ${this.config.confidenceThreshold}`,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
// Check for steps with low confidence
|
|
302
|
+
for (const step of corrected.steps) {
|
|
303
|
+
if (step.evidence.length === 0) {
|
|
304
|
+
issues.push({
|
|
305
|
+
stepIndex: step.index,
|
|
306
|
+
type: 'inconsistent-evidence',
|
|
307
|
+
description: `Step ${step.index} has no supporting evidence`,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Check if too many corrections were needed (signal of unreliable reasoning)
|
|
312
|
+
if (corrected.syndromeCount > 0 && corrected.confidence < 0.3) {
|
|
313
|
+
issues.push({
|
|
314
|
+
stepIndex: -1,
|
|
315
|
+
type: 'all-divergent',
|
|
316
|
+
description: `${corrected.syndromeCount} syndromes with confidence ${corrected.confidence.toFixed(3)} ` +
|
|
317
|
+
`suggests all paths diverged significantly`,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
// Check individual corrections for no-majority situations
|
|
321
|
+
for (const correction of corrected.corrections) {
|
|
322
|
+
if (correction.reason.includes('no clear majority')) {
|
|
323
|
+
issues.push({
|
|
324
|
+
stepIndex: correction.stepIndex,
|
|
325
|
+
type: 'no-majority',
|
|
326
|
+
description: `Step ${correction.stepIndex}: ${correction.reason}`,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const valid = issues.length === 0;
|
|
331
|
+
const confidence = valid
|
|
332
|
+
? corrected.confidence
|
|
333
|
+
: corrected.confidence * (1 - issues.length * 0.1);
|
|
334
|
+
return {
|
|
335
|
+
valid,
|
|
336
|
+
confidence: Math.max(0, confidence),
|
|
337
|
+
issues,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Convenience method: run the full QEC pipeline on a problem.
|
|
342
|
+
*
|
|
343
|
+
* @param problem - The reasoning problem
|
|
344
|
+
* @returns Object containing paths, syndromes, corrected reasoning, and validation
|
|
345
|
+
*/
|
|
346
|
+
process(problem) {
|
|
347
|
+
const paths = this.generatePaths(problem);
|
|
348
|
+
const syndromes = this.extractSyndromes(paths);
|
|
349
|
+
const corrected = this.correctErrors(paths, syndromes);
|
|
350
|
+
const validation = this.validate(corrected);
|
|
351
|
+
return { paths, syndromes, corrected, validation };
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Get current configuration.
|
|
355
|
+
*/
|
|
356
|
+
getConfig() {
|
|
357
|
+
return { ...this.config };
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Check if native backend is available.
|
|
361
|
+
*/
|
|
362
|
+
isNativeAvailable() {
|
|
363
|
+
return this.nativeAvailable;
|
|
364
|
+
}
|
|
365
|
+
// ============================================================================
|
|
366
|
+
// Private Methods
|
|
367
|
+
// ============================================================================
|
|
368
|
+
/**
|
|
369
|
+
* Generate steps for a single reasoning path from a given perspective.
|
|
370
|
+
*/
|
|
371
|
+
generatePathSteps(problem, pathId, perspective) {
|
|
372
|
+
return problem.steps.map((stepDescription, index) => {
|
|
373
|
+
const conclusion = this.generateStepConclusion(stepDescription, perspective, problem.context, pathId);
|
|
374
|
+
const evidence = this.gatherEvidence(stepDescription, perspective, problem.context);
|
|
375
|
+
return {
|
|
376
|
+
index,
|
|
377
|
+
description: `[${perspective}] ${stepDescription}`,
|
|
378
|
+
conclusion,
|
|
379
|
+
evidence,
|
|
380
|
+
};
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Generate a conclusion for a step based on perspective and context.
|
|
385
|
+
*
|
|
386
|
+
* Each perspective prioritizes different aspects of the context, producing
|
|
387
|
+
* genuinely diverse conclusions rather than identical text with a path suffix.
|
|
388
|
+
*
|
|
389
|
+
* In production this would call an LLM or apply domain-specific heuristics.
|
|
390
|
+
* The TypeScript fallback uses deterministic derivation from inputs.
|
|
391
|
+
*/
|
|
392
|
+
generateStepConclusion(description, perspective, context, pathId) {
|
|
393
|
+
const contextKeys = Object.keys(context).sort();
|
|
394
|
+
// Weight context keys differently per perspective to generate diverse conclusions.
|
|
395
|
+
// Each perspective prioritizes different aspects of the context.
|
|
396
|
+
const perspectiveWeights = {
|
|
397
|
+
0: (keys) => keys.length > 0 ? `Focused on ${keys[0]}` : 'Primary analysis',
|
|
398
|
+
1: (keys) => keys.length > 1 ? `Focused on ${keys[keys.length - 1]}` : 'Secondary analysis',
|
|
399
|
+
2: (keys) => keys.length > 0 ? `Cross-referencing ${keys.join(' and ')}` : 'Holistic analysis',
|
|
400
|
+
};
|
|
401
|
+
const focusGenerator = perspectiveWeights[pathId % 3] ?? perspectiveWeights[0];
|
|
402
|
+
const focus = focusGenerator(contextKeys);
|
|
403
|
+
return `[${perspective}] ${description}: ${focus}`;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Gather evidence for a step from the given perspective.
|
|
407
|
+
*/
|
|
408
|
+
gatherEvidence(description, perspective, context) {
|
|
409
|
+
const evidence = [];
|
|
410
|
+
evidence.push(`Analysis via ${perspective}: ${description}`);
|
|
411
|
+
for (const [key, value] of Object.entries(context)) {
|
|
412
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
413
|
+
evidence.push(`Context[${key}]: ${String(value)}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return evidence;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Derive a final conclusion from a set of completed steps.
|
|
420
|
+
*/
|
|
421
|
+
deriveConclusion(steps, perspective) {
|
|
422
|
+
if (steps.length === 0) {
|
|
423
|
+
return `No conclusion (${perspective})`;
|
|
424
|
+
}
|
|
425
|
+
const lastStep = steps[steps.length - 1];
|
|
426
|
+
return `${perspective}: ${lastStep.conclusion}`;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Calculate confidence for a single path based on its steps.
|
|
430
|
+
*/
|
|
431
|
+
calculatePathConfidence(steps) {
|
|
432
|
+
if (steps.length === 0)
|
|
433
|
+
return 0;
|
|
434
|
+
// Base confidence from step count and evidence
|
|
435
|
+
const avgEvidence = steps.reduce((sum, s) => sum + s.evidence.length, 0) / steps.length;
|
|
436
|
+
// More evidence = higher confidence, capped at 1
|
|
437
|
+
return Math.min(1, 0.5 + (avgEvidence * 0.1));
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Classify syndrome severity based on how many distinct conclusions exist.
|
|
441
|
+
*/
|
|
442
|
+
classifySyndromeSeverity(conclusions, totalPaths) {
|
|
443
|
+
const maxGroupSize = Math.max(...[...conclusions.values()].map(ids => ids.length));
|
|
444
|
+
if (maxGroupSize >= Math.ceil(totalPaths * 2 / 3)) {
|
|
445
|
+
// Clear majority — disagreement is minor
|
|
446
|
+
return 'minor';
|
|
447
|
+
}
|
|
448
|
+
if (maxGroupSize >= Math.ceil(totalPaths / 2)) {
|
|
449
|
+
// Slim majority — disagreement is major
|
|
450
|
+
return 'major';
|
|
451
|
+
}
|
|
452
|
+
// No majority — all paths diverge
|
|
453
|
+
return 'critical';
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Correct a single step by voting among paths.
|
|
457
|
+
*
|
|
458
|
+
* When votingMethod is 'weighted', each path's vote is weighted by its
|
|
459
|
+
* confidence score. When 'majority', simple count-based voting is used.
|
|
460
|
+
*/
|
|
461
|
+
correctStep(paths, stepIndex) {
|
|
462
|
+
const weightedCounts = new Map();
|
|
463
|
+
const stepsByConclusion = new Map();
|
|
464
|
+
const useWeighted = this.config.votingMethod === 'weighted';
|
|
465
|
+
for (const path of paths) {
|
|
466
|
+
const step = path.steps[stepIndex];
|
|
467
|
+
if (!step)
|
|
468
|
+
continue;
|
|
469
|
+
const currentWeight = weightedCounts.get(step.conclusion) ?? 0;
|
|
470
|
+
const increment = useWeighted ? path.confidence : 1;
|
|
471
|
+
weightedCounts.set(step.conclusion, currentWeight + increment);
|
|
472
|
+
stepsByConclusion.set(step.conclusion, step);
|
|
473
|
+
}
|
|
474
|
+
if (weightedCounts.size === 0) {
|
|
475
|
+
// No steps available at this index
|
|
476
|
+
return {
|
|
477
|
+
step: {
|
|
478
|
+
index: stepIndex,
|
|
479
|
+
description: `Step ${stepIndex} (no data)`,
|
|
480
|
+
conclusion: '',
|
|
481
|
+
evidence: [],
|
|
482
|
+
},
|
|
483
|
+
correction: null,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
// Sort by weighted count descending, then by conclusion alphabetically for stability
|
|
487
|
+
const sorted = [...weightedCounts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
488
|
+
const [majorityConclusion, majorityWeight] = sorted[0];
|
|
489
|
+
const majorityStep = stepsByConclusion.get(majorityConclusion);
|
|
490
|
+
// Merge evidence from all paths for this step
|
|
491
|
+
const mergedEvidence = new Set();
|
|
492
|
+
for (const path of paths) {
|
|
493
|
+
const step = path.steps[stepIndex];
|
|
494
|
+
if (step) {
|
|
495
|
+
for (const e of step.evidence) {
|
|
496
|
+
mergedEvidence.add(e);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const correctedStep = {
|
|
501
|
+
index: stepIndex,
|
|
502
|
+
description: majorityStep.description,
|
|
503
|
+
conclusion: majorityConclusion,
|
|
504
|
+
evidence: [...mergedEvidence],
|
|
505
|
+
};
|
|
506
|
+
// Determine if a correction was applied
|
|
507
|
+
const firstPathConclusion = paths[0].steps[stepIndex]?.conclusion;
|
|
508
|
+
let correction = null;
|
|
509
|
+
if (firstPathConclusion && firstPathConclusion !== majorityConclusion) {
|
|
510
|
+
const totalPaths = paths.filter(p => p.steps[stepIndex]).length;
|
|
511
|
+
const totalWeight = [...weightedCounts.values()].reduce((a, b) => a + b, 0);
|
|
512
|
+
const ratio = majorityWeight / totalWeight;
|
|
513
|
+
const hasMajority = ratio > this.config.majorityThreshold;
|
|
514
|
+
const voteLabel = useWeighted ? 'Weighted vote' : 'Majority vote';
|
|
515
|
+
correction = {
|
|
516
|
+
stepIndex,
|
|
517
|
+
original: firstPathConclusion,
|
|
518
|
+
corrected: majorityConclusion,
|
|
519
|
+
reason: hasMajority
|
|
520
|
+
? `${voteLabel} (${majorityWeight.toFixed(2)}/${totalWeight.toFixed(2)} weight from ${totalPaths} paths)`
|
|
521
|
+
: `Selected highest ${useWeighted ? 'weight' : 'count'} (${majorityWeight.toFixed(2)}/${totalWeight.toFixed(2)}), no clear majority`,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
return { step: correctedStep, correction };
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Correct the final conclusion using voting among paths.
|
|
528
|
+
*
|
|
529
|
+
* When votingMethod is 'weighted', each path's vote is weighted by its
|
|
530
|
+
* confidence score. When 'majority', simple count-based voting is used.
|
|
531
|
+
*/
|
|
532
|
+
correctConclusion(paths) {
|
|
533
|
+
const weightedCounts = new Map();
|
|
534
|
+
const useWeighted = this.config.votingMethod === 'weighted';
|
|
535
|
+
for (const path of paths) {
|
|
536
|
+
const currentWeight = weightedCounts.get(path.conclusion) ?? 0;
|
|
537
|
+
const increment = useWeighted ? path.confidence : 1;
|
|
538
|
+
weightedCounts.set(path.conclusion, currentWeight + increment);
|
|
539
|
+
}
|
|
540
|
+
const sorted = [...weightedCounts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
|
|
541
|
+
return sorted[0]?.[0] ?? '';
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Calculate confidence for the corrected reasoning based on path agreement
|
|
545
|
+
* and syndrome severity.
|
|
546
|
+
*/
|
|
547
|
+
calculateCorrectedConfidence(paths, syndromes) {
|
|
548
|
+
// Start with average path confidence
|
|
549
|
+
const avgPathConfidence = paths.reduce((sum, p) => sum + p.confidence, 0) / paths.length;
|
|
550
|
+
// Penalize for syndromes
|
|
551
|
+
const criticalCount = syndromes.filter(s => s.severity === 'critical').length;
|
|
552
|
+
const majorCount = syndromes.filter(s => s.severity === 'major').length;
|
|
553
|
+
const minorCount = syndromes.filter(s => s.severity === 'minor').length;
|
|
554
|
+
const penalty = criticalCount * 0.2 +
|
|
555
|
+
majorCount * 0.1 +
|
|
556
|
+
minorCount * 0.03;
|
|
557
|
+
// Boost for agreement (no syndromes = high agreement)
|
|
558
|
+
const agreementBoost = syndromes.length === 0 ? 0.1 : 0;
|
|
559
|
+
return Math.max(0, Math.min(1, avgPathConfidence - penalty + agreementBoost));
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
// ============================================================================
|
|
563
|
+
// Factory Functions
|
|
564
|
+
// ============================================================================
|
|
565
|
+
/**
|
|
566
|
+
* Create a new ReasoningQEC engine with optional configuration.
|
|
567
|
+
*
|
|
568
|
+
* @param config - Partial configuration overrides
|
|
569
|
+
* @returns Configured ReasoningQEC instance
|
|
570
|
+
*/
|
|
571
|
+
export function createReasoningQEC(config) {
|
|
572
|
+
return new ReasoningQEC(config);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Run the full QEC pipeline on a problem in one call.
|
|
576
|
+
*
|
|
577
|
+
* @param problem - The reasoning problem to process
|
|
578
|
+
* @param config - Optional configuration overrides
|
|
579
|
+
* @returns Pipeline result with paths, syndromes, corrected reasoning, and validation
|
|
580
|
+
*/
|
|
581
|
+
export function processReasoning(problem, config) {
|
|
582
|
+
const qec = createReasoningQEC(config);
|
|
583
|
+
return qec.process(problem);
|
|
584
|
+
}
|
|
585
|
+
//# sourceMappingURL=reasoning-qec.js.map
|
|
@@ -58,6 +58,7 @@ export declare class DomainTaskExecutor implements TaskHandlerContext {
|
|
|
58
58
|
private agentBooster;
|
|
59
59
|
private taskRouter;
|
|
60
60
|
private qualityFeedbackLoop;
|
|
61
|
+
private coherenceActionGate;
|
|
61
62
|
private readonly taskHandlers;
|
|
62
63
|
constructor(kernel: QEKernel, eventBus: EventBus, config?: Partial<TaskExecutorConfig>);
|
|
63
64
|
/** Expose config to handler modules */
|
|
@@ -108,6 +109,21 @@ export declare class DomainTaskExecutor implements TaskHandlerContext {
|
|
|
108
109
|
* Sync version for backwards compatibility
|
|
109
110
|
*/
|
|
110
111
|
resetServiceCachesSync(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Evaluate task action through the coherence gate.
|
|
114
|
+
* Returns null when the feature flag is off, otherwise returns the evaluation.
|
|
115
|
+
* Advisory mode by default: logs decision but never blocks execution.
|
|
116
|
+
*/
|
|
117
|
+
private evaluateCoherenceGate;
|
|
118
|
+
/**
|
|
119
|
+
* Validate task reasoning through multi-path consensus (ReasoningQEC).
|
|
120
|
+
* Only runs when useReasoningQEC flag is on and task has reasoning steps.
|
|
121
|
+
* Advisory mode: logs validation result but never blocks execution.
|
|
122
|
+
*/
|
|
123
|
+
/** Lazily cached ReasoningQEC instance */
|
|
124
|
+
private _reasoningQEC;
|
|
125
|
+
private _reasoningQECLoaded;
|
|
126
|
+
private validateWithReasoningQEC;
|
|
111
127
|
private getTaskDomain;
|
|
112
128
|
private timeout;
|
|
113
129
|
private publishTaskCompleted;
|