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.
Files changed (164) hide show
  1. package/.claude/helpers/brain-checkpoint.cjs +4 -1
  2. package/.claude/helpers/statusline-v3.cjs +3 -1
  3. package/.claude/skills/skills-manifest.json +1 -1
  4. package/CHANGELOG.md +45 -0
  5. package/README.md +2 -14
  6. package/assets/helpers/statusline-v3.cjs +3 -1
  7. package/dist/cli/brain-commands.js +6 -10
  8. package/dist/cli/bundle.js +7441 -4327
  9. package/dist/cli/commands/audit.d.ts +43 -0
  10. package/dist/cli/commands/audit.js +125 -0
  11. package/dist/cli/commands/hooks.js +29 -6
  12. package/dist/cli/commands/init.js +1 -73
  13. package/dist/cli/commands/learning.js +270 -13
  14. package/dist/cli/commands/ruvector-commands.d.ts +15 -0
  15. package/dist/cli/commands/ruvector-commands.js +271 -0
  16. package/dist/cli/handlers/init-handler.d.ts +0 -1
  17. package/dist/cli/handlers/init-handler.js +0 -6
  18. package/dist/cli/index.js +4 -2
  19. package/dist/context/sources/defect-source.js +2 -2
  20. package/dist/context/sources/memory-source.js +2 -2
  21. package/dist/context/sources/requirements-source.js +2 -2
  22. package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
  23. package/dist/coordination/behavior-tree/decorators.js +251 -0
  24. package/dist/coordination/behavior-tree/index.d.ts +12 -0
  25. package/dist/coordination/behavior-tree/index.js +15 -0
  26. package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
  27. package/dist/coordination/behavior-tree/nodes.js +338 -0
  28. package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
  29. package/dist/coordination/behavior-tree/qe-trees.js +181 -0
  30. package/dist/coordination/coherence-action-gate.d.ts +284 -0
  31. package/dist/coordination/coherence-action-gate.js +512 -0
  32. package/dist/coordination/index.d.ts +4 -0
  33. package/dist/coordination/index.js +8 -0
  34. package/dist/coordination/reasoning-qec.d.ts +315 -0
  35. package/dist/coordination/reasoning-qec.js +585 -0
  36. package/dist/coordination/task-executor.d.ts +16 -0
  37. package/dist/coordination/task-executor.js +99 -0
  38. package/dist/coordination/workflow-orchestrator.d.ts +29 -0
  39. package/dist/coordination/workflow-orchestrator.js +42 -0
  40. package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
  41. package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
  42. package/dist/domains/visual-accessibility/index.d.ts +1 -0
  43. package/dist/domains/visual-accessibility/index.js +4 -0
  44. package/dist/governance/coherence-validator.d.ts +112 -0
  45. package/dist/governance/coherence-validator.js +180 -0
  46. package/dist/governance/index.d.ts +1 -0
  47. package/dist/governance/index.js +2 -0
  48. package/dist/governance/witness-chain.d.ts +311 -0
  49. package/dist/governance/witness-chain.js +509 -0
  50. package/dist/init/index.d.ts +0 -2
  51. package/dist/init/index.js +0 -1
  52. package/dist/init/init-wizard-steps.d.ts +10 -0
  53. package/dist/init/init-wizard-steps.js +87 -1
  54. package/dist/init/init-wizard.d.ts +1 -9
  55. package/dist/init/init-wizard.js +3 -69
  56. package/dist/init/orchestrator.js +0 -1
  57. package/dist/init/phases/01-detection.js +0 -27
  58. package/dist/init/phases/07-hooks.js +6 -4
  59. package/dist/init/phases/phase-interface.d.ts +0 -1
  60. package/dist/init/settings-merge.js +1 -1
  61. package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
  62. package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
  63. package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
  64. package/dist/integrations/browser/qe-dashboard/index.js +15 -0
  65. package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
  66. package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
  67. package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
  68. package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
  69. package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
  70. package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
  71. package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
  72. package/dist/integrations/ruvector/cognitive-container.js +306 -0
  73. package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
  74. package/dist/integrations/ruvector/coherence-gate.js +631 -0
  75. package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
  76. package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
  77. package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
  78. package/dist/integrations/ruvector/dither-adapter.js +295 -0
  79. package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
  80. package/dist/integrations/ruvector/domain-transfer.js +220 -0
  81. package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
  82. package/dist/integrations/ruvector/feature-flags.js +167 -2
  83. package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
  84. package/dist/integrations/ruvector/filter-adapter.js +285 -0
  85. package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
  86. package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
  87. package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
  88. package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
  89. package/dist/integrations/ruvector/index.d.ts +8 -2
  90. package/dist/integrations/ruvector/index.js +18 -2
  91. package/dist/integrations/ruvector/interfaces.d.ts +40 -0
  92. package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
  93. package/dist/integrations/ruvector/sona-persistence.js +162 -0
  94. package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
  95. package/dist/integrations/ruvector/sona-three-loop.js +814 -0
  96. package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
  97. package/dist/integrations/ruvector/sona-wrapper.js +147 -3
  98. package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
  99. package/dist/integrations/ruvector/spectral-math.js +254 -0
  100. package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
  101. package/dist/integrations/ruvector/temporal-compression.js +318 -0
  102. package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
  103. package/dist/integrations/ruvector/thompson-sampler.js +118 -0
  104. package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
  105. package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
  106. package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
  107. package/dist/integrations/ruvector/transfer-verification.js +115 -0
  108. package/dist/kernel/hnsw-adapter.d.ts +52 -1
  109. package/dist/kernel/hnsw-adapter.js +139 -4
  110. package/dist/kernel/hnsw-index-provider.d.ts +5 -0
  111. package/dist/kernel/native-hnsw-backend.d.ts +110 -0
  112. package/dist/kernel/native-hnsw-backend.js +408 -0
  113. package/dist/kernel/unified-memory.js +5 -6
  114. package/dist/learning/aqe-learning-engine.d.ts +2 -0
  115. package/dist/learning/aqe-learning-engine.js +65 -0
  116. package/dist/learning/experience-capture-middleware.js +20 -0
  117. package/dist/learning/experience-capture.d.ts +10 -0
  118. package/dist/learning/experience-capture.js +34 -0
  119. package/dist/learning/index.d.ts +2 -2
  120. package/dist/learning/index.js +4 -4
  121. package/dist/learning/metrics-tracker.d.ts +11 -0
  122. package/dist/learning/metrics-tracker.js +29 -13
  123. package/dist/learning/pattern-lifecycle.d.ts +30 -1
  124. package/dist/learning/pattern-lifecycle.js +92 -20
  125. package/dist/learning/pattern-store.d.ts +8 -0
  126. package/dist/learning/pattern-store.js +8 -2
  127. package/dist/learning/qe-unified-memory.js +1 -28
  128. package/dist/learning/regret-tracker.d.ts +201 -0
  129. package/dist/learning/regret-tracker.js +361 -0
  130. package/dist/mcp/bundle.js +5915 -474
  131. package/dist/routing/index.d.ts +4 -2
  132. package/dist/routing/index.js +3 -1
  133. package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
  134. package/dist/routing/neural-tiny-dancer-router.js +514 -0
  135. package/dist/routing/queen-integration.js +5 -5
  136. package/dist/routing/routing-config.d.ts +6 -0
  137. package/dist/routing/routing-config.js +1 -0
  138. package/dist/routing/simple-neural-router.d.ts +76 -0
  139. package/dist/routing/simple-neural-router.js +202 -0
  140. package/dist/routing/tiny-dancer-router.d.ts +20 -1
  141. package/dist/routing/tiny-dancer-router.js +21 -2
  142. package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
  143. package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
  144. package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
  145. package/dist/test-scheduling/dag-attention-types.js +10 -0
  146. package/dist/test-scheduling/index.d.ts +1 -0
  147. package/dist/test-scheduling/index.js +4 -0
  148. package/dist/test-scheduling/pipeline.d.ts +8 -0
  149. package/dist/test-scheduling/pipeline.js +28 -0
  150. package/package.json +6 -2
  151. package/dist/cli/commands/migrate.d.ts +0 -9
  152. package/dist/cli/commands/migrate.js +0 -566
  153. package/dist/init/init-wizard-migration.d.ts +0 -52
  154. package/dist/init/init-wizard-migration.js +0 -345
  155. package/dist/init/migration/config-migrator.d.ts +0 -31
  156. package/dist/init/migration/config-migrator.js +0 -149
  157. package/dist/init/migration/data-migrator.d.ts +0 -72
  158. package/dist/init/migration/data-migrator.js +0 -232
  159. package/dist/init/migration/detector.d.ts +0 -44
  160. package/dist/init/migration/detector.js +0 -105
  161. package/dist/init/migration/index.d.ts +0 -8
  162. package/dist/init/migration/index.js +0 -8
  163. package/dist/learning/v2-to-v3-migration.d.ts +0 -86
  164. 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;