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,631 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coherence Gate (Task 3.1, ADR-083)
|
|
3
|
+
*
|
|
4
|
+
* Validates AI-generated test artifacts using heuristic coherence scoring
|
|
5
|
+
* based on word-level feature similarity. Detects hallucinated or inconsistent
|
|
6
|
+
* test outputs by measuring the energy deviation from expected pattern consistency.
|
|
7
|
+
*
|
|
8
|
+
* Compute ladder:
|
|
9
|
+
* - Reflex (<1ms): Simple heuristic checks (assertion count, coverage overlap)
|
|
10
|
+
* - Retrieval (~10ms): Full word-frequency coherence computation
|
|
11
|
+
*
|
|
12
|
+
* Implements ITransferCoherenceGate for cross-domain transfer validation.
|
|
13
|
+
* Uses Blake3 hash-chained witness records for audit trail.
|
|
14
|
+
*
|
|
15
|
+
* @module integrations/ruvector/coherence-gate
|
|
16
|
+
* @see ADR-083-coherence-gated-agent-actions.md
|
|
17
|
+
*/
|
|
18
|
+
import { createHash, randomUUID } from 'crypto';
|
|
19
|
+
import { createRequire } from 'module';
|
|
20
|
+
import { LoggerFactory } from '../../logging/index.js';
|
|
21
|
+
// Use createRequire for native CJS/WASM modules
|
|
22
|
+
const esmRequire = createRequire(import.meta.url);
|
|
23
|
+
import { getRuVectorFeatureFlags } from './feature-flags.js';
|
|
24
|
+
const logger = LoggerFactory.create('coherence-gate');
|
|
25
|
+
let cohomologyEngine = null;
|
|
26
|
+
let cohomologyLoadAttempted = false;
|
|
27
|
+
/**
|
|
28
|
+
* Lazily load the CohomologyEngine from prime-radiant-advanced-wasm.
|
|
29
|
+
* Returns null if the WASM module is unavailable.
|
|
30
|
+
*/
|
|
31
|
+
function getCohomologyEngine() {
|
|
32
|
+
if (cohomologyLoadAttempted)
|
|
33
|
+
return cohomologyEngine;
|
|
34
|
+
cohomologyLoadAttempted = true;
|
|
35
|
+
try {
|
|
36
|
+
const pr = esmRequire('prime-radiant-advanced-wasm');
|
|
37
|
+
const fs = esmRequire('fs');
|
|
38
|
+
const path = esmRequire('path');
|
|
39
|
+
const wasmPath = path.join(path.dirname(require.resolve('prime-radiant-advanced-wasm')), 'prime_radiant_advanced_wasm_bg.wasm');
|
|
40
|
+
pr.initSync({ module: fs.readFileSync(wasmPath) });
|
|
41
|
+
cohomologyEngine = new pr.CohomologyEngine();
|
|
42
|
+
logger.info('CohomologyEngine loaded from prime-radiant-advanced-wasm');
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
logger.debug('CohomologyEngine unavailable, using word-frequency fallback', { error: String(err) });
|
|
46
|
+
cohomologyEngine = null;
|
|
47
|
+
}
|
|
48
|
+
return cohomologyEngine;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Reset the CohomologyEngine loader state (for testing).
|
|
52
|
+
*/
|
|
53
|
+
export function resetCohomologyEngineLoader() {
|
|
54
|
+
cohomologyEngine = null;
|
|
55
|
+
cohomologyLoadAttempted = false;
|
|
56
|
+
}
|
|
57
|
+
/** Default coherence threshold (Normal regime) */
|
|
58
|
+
export const DEFAULT_COHERENCE_THRESHOLD = 0.4;
|
|
59
|
+
/** Weights for energy component computation */
|
|
60
|
+
const ENERGY_WEIGHTS = {
|
|
61
|
+
assertionCoverage: 0.4,
|
|
62
|
+
codeCoverage: 0.3,
|
|
63
|
+
confidencePenalty: 0.3,
|
|
64
|
+
contradictionWeight: 0.2,
|
|
65
|
+
laplacianWeight: 0.15,
|
|
66
|
+
};
|
|
67
|
+
/** Reflex tier latency cutoff in ms */
|
|
68
|
+
const REFLEX_LATENCY_BUDGET_MS = 1;
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Coherence Gate Implementation
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Coherence gate for validating AI-generated test artifacts.
|
|
74
|
+
*
|
|
75
|
+
* Uses word-level heuristic coherence scoring to detect hallucinated or
|
|
76
|
+
* inconsistent test outputs. Implements ITransferCoherenceGate for
|
|
77
|
+
* cross-domain transfer validation compatibility.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const gate = new CoherenceGate();
|
|
82
|
+
* const result = gate.validate({
|
|
83
|
+
* assertions: ['expect(result).toBe(true)'],
|
|
84
|
+
* observedBehavior: ['result was true'],
|
|
85
|
+
* coverage: 0.85,
|
|
86
|
+
* domain: 'test-generation',
|
|
87
|
+
* confidence: 0.9,
|
|
88
|
+
* });
|
|
89
|
+
* if (!result.passed) {
|
|
90
|
+
* console.warn('Artifact may be hallucinated:', result.reason);
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export class CoherenceGate {
|
|
95
|
+
threshold;
|
|
96
|
+
decisionLog = [];
|
|
97
|
+
witnessChain = [];
|
|
98
|
+
lastWitnessHash = '0'.repeat(64);
|
|
99
|
+
nativeAvailable = null;
|
|
100
|
+
constructor(threshold = DEFAULT_COHERENCE_THRESHOLD) {
|
|
101
|
+
this.threshold = threshold;
|
|
102
|
+
}
|
|
103
|
+
// ==========================================================================
|
|
104
|
+
// Core API
|
|
105
|
+
// ==========================================================================
|
|
106
|
+
/**
|
|
107
|
+
* Compute coherence energy for a test artifact.
|
|
108
|
+
*
|
|
109
|
+
* Uses a two-tier compute ladder:
|
|
110
|
+
* - Reflex (<1ms): Simple heuristic checks
|
|
111
|
+
* - Retrieval (~10ms): Full sheaf Laplacian computation
|
|
112
|
+
*
|
|
113
|
+
* @param artifact - The test artifact to evaluate
|
|
114
|
+
* @param forceRetrieval - If true, skip reflex and go straight to retrieval
|
|
115
|
+
* @returns Coherence result with energy score and component breakdown
|
|
116
|
+
*/
|
|
117
|
+
computeEnergy(artifact, forceRetrieval = false) {
|
|
118
|
+
const startTime = performance.now();
|
|
119
|
+
// Tier 1: Reflex check
|
|
120
|
+
if (!forceRetrieval) {
|
|
121
|
+
const reflexResult = this.computeReflexEnergy(artifact);
|
|
122
|
+
const reflexLatency = performance.now() - startTime;
|
|
123
|
+
if (reflexLatency <= REFLEX_LATENCY_BUDGET_MS) {
|
|
124
|
+
return {
|
|
125
|
+
energy: reflexResult.energy,
|
|
126
|
+
tier: 'reflex',
|
|
127
|
+
components: reflexResult.components,
|
|
128
|
+
latencyMs: reflexLatency,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Tier 2: Full retrieval computation
|
|
133
|
+
const retrievalResult = this.computeRetrievalEnergy(artifact);
|
|
134
|
+
const latencyMs = performance.now() - startTime;
|
|
135
|
+
return {
|
|
136
|
+
energy: retrievalResult.energy,
|
|
137
|
+
tier: 'retrieval',
|
|
138
|
+
components: retrievalResult.components,
|
|
139
|
+
latencyMs,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Validate a test artifact against the coherence threshold.
|
|
144
|
+
*
|
|
145
|
+
* @param artifact - The test artifact to validate
|
|
146
|
+
* @param threshold - Optional override for the default threshold
|
|
147
|
+
* @returns Validation result with witness record
|
|
148
|
+
*/
|
|
149
|
+
validate(artifact, threshold) {
|
|
150
|
+
const effectiveThreshold = threshold ?? this.threshold;
|
|
151
|
+
const coherenceResult = this.computeEnergy(artifact);
|
|
152
|
+
const passed = coherenceResult.energy <= effectiveThreshold;
|
|
153
|
+
// Build reason for failure
|
|
154
|
+
let reason;
|
|
155
|
+
if (!passed) {
|
|
156
|
+
reason = this.buildFailureReason(coherenceResult, effectiveThreshold);
|
|
157
|
+
}
|
|
158
|
+
// Create witness record
|
|
159
|
+
const witness = this.createWitnessRecord(artifact, coherenceResult.energy, effectiveThreshold, passed);
|
|
160
|
+
// Log decision
|
|
161
|
+
this.logDecision({
|
|
162
|
+
id: witness.id,
|
|
163
|
+
timestamp: witness.timestamp,
|
|
164
|
+
domain: artifact.domain,
|
|
165
|
+
energy: coherenceResult.energy,
|
|
166
|
+
tier: coherenceResult.tier,
|
|
167
|
+
passed,
|
|
168
|
+
threshold: effectiveThreshold,
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
passed,
|
|
172
|
+
energy: coherenceResult.energy,
|
|
173
|
+
threshold: effectiveThreshold,
|
|
174
|
+
reason,
|
|
175
|
+
witness,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the decision log for observability.
|
|
180
|
+
*/
|
|
181
|
+
getDecisionLog() {
|
|
182
|
+
return [...this.decisionLog];
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get the witness chain for audit purposes.
|
|
186
|
+
*/
|
|
187
|
+
getWitnessChain() {
|
|
188
|
+
return [...this.witnessChain];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get the current threshold.
|
|
192
|
+
*/
|
|
193
|
+
getThreshold() {
|
|
194
|
+
return this.threshold;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Clear the decision log (for testing).
|
|
198
|
+
*/
|
|
199
|
+
clearDecisionLog() {
|
|
200
|
+
this.decisionLog = [];
|
|
201
|
+
}
|
|
202
|
+
// ==========================================================================
|
|
203
|
+
// ITransferCoherenceGate Implementation
|
|
204
|
+
// ==========================================================================
|
|
205
|
+
/**
|
|
206
|
+
* Validate whether a pattern can be transferred to a target domain
|
|
207
|
+
* without introducing coherence violations.
|
|
208
|
+
*
|
|
209
|
+
* Converts the pattern into a TestArtifact and runs coherence validation.
|
|
210
|
+
*/
|
|
211
|
+
validateTransfer(pattern, targetDomain) {
|
|
212
|
+
const flags = getRuVectorFeatureFlags();
|
|
213
|
+
if (!flags.useCoherenceGate) {
|
|
214
|
+
return { approved: true };
|
|
215
|
+
}
|
|
216
|
+
// Convert pattern to test artifact for coherence check
|
|
217
|
+
const artifact = {
|
|
218
|
+
assertions: this.extractAssertions(pattern),
|
|
219
|
+
observedBehavior: this.extractObservedBehavior(pattern),
|
|
220
|
+
coverage: typeof pattern.coverage === 'number' ? pattern.coverage : 0.5,
|
|
221
|
+
domain: targetDomain,
|
|
222
|
+
confidence: pattern.confidence ?? 0.5,
|
|
223
|
+
};
|
|
224
|
+
const result = this.validate(artifact);
|
|
225
|
+
return {
|
|
226
|
+
approved: result.passed,
|
|
227
|
+
energy: result.energy,
|
|
228
|
+
rejectionReason: result.reason,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
// ==========================================================================
|
|
232
|
+
// Private: Reflex Tier (Heuristic Checks)
|
|
233
|
+
// ==========================================================================
|
|
234
|
+
/**
|
|
235
|
+
* Reflex-tier energy computation using simple heuristics.
|
|
236
|
+
* Must complete in <1ms.
|
|
237
|
+
*/
|
|
238
|
+
computeReflexEnergy(artifact) {
|
|
239
|
+
const assertionCoverage = this.computeAssertionCoverageEnergy(artifact);
|
|
240
|
+
const codeCoverage = this.computeCodeCoverageEnergy(artifact);
|
|
241
|
+
const confidencePenalty = this.computeConfidencePenalty(artifact);
|
|
242
|
+
const energy = Math.min(assertionCoverage * ENERGY_WEIGHTS.assertionCoverage +
|
|
243
|
+
codeCoverage * ENERGY_WEIGHTS.codeCoverage +
|
|
244
|
+
confidencePenalty * ENERGY_WEIGHTS.confidencePenalty, 1);
|
|
245
|
+
return {
|
|
246
|
+
energy,
|
|
247
|
+
components: {
|
|
248
|
+
assertionCoverage,
|
|
249
|
+
codeCoverage,
|
|
250
|
+
confidencePenalty,
|
|
251
|
+
contradictionScore: 0,
|
|
252
|
+
laplacianDeviation: 0,
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// ==========================================================================
|
|
257
|
+
// Private: Retrieval Tier (Full Sheaf Laplacian)
|
|
258
|
+
// ==========================================================================
|
|
259
|
+
/**
|
|
260
|
+
* Retrieval-tier energy computation using sheaf Laplacian.
|
|
261
|
+
* Includes contradiction detection and Laplacian deviation.
|
|
262
|
+
*/
|
|
263
|
+
computeRetrievalEnergy(artifact) {
|
|
264
|
+
const assertionCoverage = this.computeAssertionCoverageEnergy(artifact);
|
|
265
|
+
const codeCoverage = this.computeCodeCoverageEnergy(artifact);
|
|
266
|
+
const confidencePenalty = this.computeConfidencePenalty(artifact);
|
|
267
|
+
const contradictionScore = this.detectContradictions(artifact);
|
|
268
|
+
const laplacianDeviation = this.computeLaplacianDeviation(artifact);
|
|
269
|
+
// Weighted combination including retrieval-only components
|
|
270
|
+
const baseEnergy = assertionCoverage * ENERGY_WEIGHTS.assertionCoverage +
|
|
271
|
+
codeCoverage * ENERGY_WEIGHTS.codeCoverage +
|
|
272
|
+
confidencePenalty * ENERGY_WEIGHTS.confidencePenalty;
|
|
273
|
+
const retrievalEnergy = contradictionScore * ENERGY_WEIGHTS.contradictionWeight +
|
|
274
|
+
laplacianDeviation * ENERGY_WEIGHTS.laplacianWeight;
|
|
275
|
+
// Normalize: base has weight sum 1.0, retrieval adds up to 0.35
|
|
276
|
+
// Scale so total is still in [0, 1]
|
|
277
|
+
const totalWeight = ENERGY_WEIGHTS.assertionCoverage +
|
|
278
|
+
ENERGY_WEIGHTS.codeCoverage +
|
|
279
|
+
ENERGY_WEIGHTS.confidencePenalty +
|
|
280
|
+
ENERGY_WEIGHTS.contradictionWeight +
|
|
281
|
+
ENERGY_WEIGHTS.laplacianWeight;
|
|
282
|
+
const energy = Math.min((baseEnergy + retrievalEnergy) / totalWeight, 1);
|
|
283
|
+
return {
|
|
284
|
+
energy,
|
|
285
|
+
components: {
|
|
286
|
+
assertionCoverage,
|
|
287
|
+
codeCoverage,
|
|
288
|
+
confidencePenalty,
|
|
289
|
+
contradictionScore,
|
|
290
|
+
laplacianDeviation,
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
// ==========================================================================
|
|
295
|
+
// Private: Energy Component Functions
|
|
296
|
+
// ==========================================================================
|
|
297
|
+
/**
|
|
298
|
+
* Compute assertion coverage energy.
|
|
299
|
+
* High energy when assertions far exceed observed behavior (hallucination signal).
|
|
300
|
+
*/
|
|
301
|
+
computeAssertionCoverageEnergy(artifact) {
|
|
302
|
+
if (artifact.assertions.length === 0) {
|
|
303
|
+
return 0;
|
|
304
|
+
}
|
|
305
|
+
const ratio = artifact.observedBehavior.length / artifact.assertions.length;
|
|
306
|
+
return Math.max(0, Math.min(1 - ratio, 1));
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Compute code coverage energy.
|
|
310
|
+
* Higher energy for lower coverage.
|
|
311
|
+
*/
|
|
312
|
+
computeCodeCoverageEnergy(artifact) {
|
|
313
|
+
return Math.max(0, Math.min(1 - artifact.coverage, 1));
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Compute confidence penalty.
|
|
317
|
+
* Higher energy for lower confidence.
|
|
318
|
+
*/
|
|
319
|
+
computeConfidencePenalty(artifact) {
|
|
320
|
+
return Math.max(0, Math.min(1 - artifact.confidence, 1));
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Detect contradictions between assertions and observed behavior.
|
|
324
|
+
*
|
|
325
|
+
* Simple heuristic: look for negation patterns and semantic opposites
|
|
326
|
+
* in the assertion/behavior pairing.
|
|
327
|
+
*/
|
|
328
|
+
detectContradictions(artifact) {
|
|
329
|
+
if (artifact.assertions.length === 0 || artifact.observedBehavior.length === 0) {
|
|
330
|
+
return 0;
|
|
331
|
+
}
|
|
332
|
+
let contradictions = 0;
|
|
333
|
+
const negationPatterns = ['not', 'never', 'false', 'undefined', 'null', 'error', 'fail'];
|
|
334
|
+
for (const assertion of artifact.assertions) {
|
|
335
|
+
const assertionLower = assertion.toLowerCase();
|
|
336
|
+
for (const behavior of artifact.observedBehavior) {
|
|
337
|
+
const behaviorLower = behavior.toLowerCase();
|
|
338
|
+
// Check if assertion and behavior have opposing sentiment
|
|
339
|
+
for (const neg of negationPatterns) {
|
|
340
|
+
const assertionHasNeg = assertionLower.includes(neg);
|
|
341
|
+
const behaviorHasNeg = behaviorLower.includes(neg);
|
|
342
|
+
// One has negation, the other does not, and they share a common term
|
|
343
|
+
if (assertionHasNeg !== behaviorHasNeg) {
|
|
344
|
+
const assertionWords = new Set(assertionLower.split(/\s+/));
|
|
345
|
+
const behaviorWords = new Set(behaviorLower.split(/\s+/));
|
|
346
|
+
let shared = 0;
|
|
347
|
+
for (const word of assertionWords) {
|
|
348
|
+
if (behaviorWords.has(word) && word.length > 3) {
|
|
349
|
+
shared++;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (shared > 0) {
|
|
353
|
+
contradictions++;
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return Math.min(contradictions / artifact.assertions.length, 1);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Compute coherence deviation using sheaf Laplacian energy.
|
|
364
|
+
*
|
|
365
|
+
* When `prime-radiant-advanced-wasm` CohomologyEngine is available,
|
|
366
|
+
* builds a sheaf graph from assertion vectors and computes real sheaf
|
|
367
|
+
* Laplacian consistency energy. Falls back to pairwise word-frequency
|
|
368
|
+
* cosine similarity when the WASM module is unavailable.
|
|
369
|
+
*
|
|
370
|
+
* Uses 64-dim word-level feature hashing with FNV-1a for bucket assignment
|
|
371
|
+
* and L2-normalized term-frequency vectors.
|
|
372
|
+
*/
|
|
373
|
+
computeLaplacianDeviation(artifact) {
|
|
374
|
+
if (artifact.assertions.length < 2) {
|
|
375
|
+
return 0;
|
|
376
|
+
}
|
|
377
|
+
// Build word-level feature vectors from assertions
|
|
378
|
+
const vectors = artifact.assertions.map(a => this.textToWordFeatureVector(a));
|
|
379
|
+
// Try native CohomologyEngine for real sheaf Laplacian
|
|
380
|
+
const engine = getCohomologyEngine();
|
|
381
|
+
if (engine) {
|
|
382
|
+
try {
|
|
383
|
+
return this.computeNativeLaplacianDeviation(engine, artifact, vectors);
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
logger.debug('CohomologyEngine.consistencyEnergy failed, using fallback', { error: String(err) });
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
// Fallback: pairwise cosine similarity
|
|
390
|
+
return this.computeFallbackLaplacianDeviation(vectors);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Compute Laplacian deviation using the native CohomologyEngine.
|
|
394
|
+
* Builds a sheaf graph where each assertion is a node and related
|
|
395
|
+
* assertion pairs form edges with identity restriction maps.
|
|
396
|
+
*/
|
|
397
|
+
computeNativeLaplacianDeviation(engine, artifact, vectors) {
|
|
398
|
+
const dim = vectors[0]?.length ?? 64;
|
|
399
|
+
// Build sheaf graph: each assertion is a node
|
|
400
|
+
const nodes = vectors.map((vec, i) => ({
|
|
401
|
+
id: i,
|
|
402
|
+
label: artifact.assertions[i]?.slice(0, 50) ?? `assertion-${i}`,
|
|
403
|
+
section: vec,
|
|
404
|
+
weight: artifact.confidence,
|
|
405
|
+
}));
|
|
406
|
+
// Build edges: connect all pairs with identity restriction maps
|
|
407
|
+
const edges = [];
|
|
408
|
+
for (let i = 0; i < vectors.length; i++) {
|
|
409
|
+
for (let j = i + 1; j < vectors.length; j++) {
|
|
410
|
+
// Identity restriction map (flat dim x dim matrix)
|
|
411
|
+
const identityMap = [];
|
|
412
|
+
for (let r = 0; r < dim; r++) {
|
|
413
|
+
for (let c = 0; c < dim; c++) {
|
|
414
|
+
identityMap.push(r === c ? 1.0 : 0.0);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
edges.push({
|
|
418
|
+
source: i,
|
|
419
|
+
target: j,
|
|
420
|
+
weight: 1.0,
|
|
421
|
+
restriction_map: identityMap,
|
|
422
|
+
source_dim: dim,
|
|
423
|
+
target_dim: dim,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const rawEnergy = engine.consistencyEnergy({ nodes, edges });
|
|
428
|
+
// Normalize: raw energy can vary widely; map to [0, 1]
|
|
429
|
+
// Use sigmoid-like scaling: energy / (energy + 1)
|
|
430
|
+
const normalizedEnergy = rawEnergy / (rawEnergy + 1);
|
|
431
|
+
return Math.max(0, Math.min(normalizedEnergy, 1));
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Fallback: compute pairwise word-frequency cosine consistency score.
|
|
435
|
+
*/
|
|
436
|
+
computeFallbackLaplacianDeviation(vectors) {
|
|
437
|
+
let totalSimilarity = 0;
|
|
438
|
+
let pairCount = 0;
|
|
439
|
+
for (let i = 0; i < vectors.length; i++) {
|
|
440
|
+
for (let j = i + 1; j < vectors.length; j++) {
|
|
441
|
+
totalSimilarity += this.cosineSimilarity(vectors[i], vectors[j]);
|
|
442
|
+
pairCount++;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (pairCount === 0) {
|
|
446
|
+
return 0;
|
|
447
|
+
}
|
|
448
|
+
// Average similarity -> deviation
|
|
449
|
+
// High similarity = low deviation, low similarity = high deviation
|
|
450
|
+
const avgSimilarity = totalSimilarity / pairCount;
|
|
451
|
+
return Math.max(0, Math.min(1 - avgSimilarity, 1));
|
|
452
|
+
}
|
|
453
|
+
// ==========================================================================
|
|
454
|
+
// Private: Utility Functions
|
|
455
|
+
// ==========================================================================
|
|
456
|
+
/**
|
|
457
|
+
* Hash a word to a bucket index 0-63 using FNV-1a.
|
|
458
|
+
*/
|
|
459
|
+
hashWord(word) {
|
|
460
|
+
let h = 0x811c9dc5; // FNV offset basis
|
|
461
|
+
for (let i = 0; i < word.length; i++) {
|
|
462
|
+
h ^= word.charCodeAt(i);
|
|
463
|
+
h = Math.imul(h, 0x01000193); // FNV prime
|
|
464
|
+
}
|
|
465
|
+
return ((h >>> 0) % 64);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Convert text to a 64-dim word-level feature vector using feature hashing.
|
|
469
|
+
*
|
|
470
|
+
* Tokenizes on whitespace and punctuation, hashes each word to one of 64
|
|
471
|
+
* buckets via FNV-1a, builds a term-frequency vector, and L2-normalizes it.
|
|
472
|
+
*/
|
|
473
|
+
textToWordFeatureVector(text) {
|
|
474
|
+
const vec = new Array(64).fill(0);
|
|
475
|
+
const words = text.toLowerCase().split(/[\s,;:.!?()[\]{}"']+/).filter(w => w.length > 0);
|
|
476
|
+
for (const word of words) {
|
|
477
|
+
const bucket = this.hashWord(word);
|
|
478
|
+
vec[bucket]++;
|
|
479
|
+
}
|
|
480
|
+
// L2-normalize
|
|
481
|
+
let norm = 0;
|
|
482
|
+
for (let i = 0; i < 64; i++) {
|
|
483
|
+
norm += vec[i] * vec[i];
|
|
484
|
+
}
|
|
485
|
+
norm = Math.sqrt(norm);
|
|
486
|
+
if (norm > 1e-10) {
|
|
487
|
+
for (let i = 0; i < 64; i++) {
|
|
488
|
+
vec[i] /= norm;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return vec;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Compute cosine similarity between two vectors.
|
|
495
|
+
*/
|
|
496
|
+
cosineSimilarity(a, b) {
|
|
497
|
+
let dot = 0;
|
|
498
|
+
let normA = 0;
|
|
499
|
+
let normB = 0;
|
|
500
|
+
const len = Math.min(a.length, b.length);
|
|
501
|
+
for (let i = 0; i < len; i++) {
|
|
502
|
+
dot += a[i] * b[i];
|
|
503
|
+
normA += a[i] * a[i];
|
|
504
|
+
normB += b[i] * b[i];
|
|
505
|
+
}
|
|
506
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
507
|
+
return denom > 1e-10 ? dot / denom : 0;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Build a human-readable failure reason from coherence results.
|
|
511
|
+
*/
|
|
512
|
+
buildFailureReason(result, threshold) {
|
|
513
|
+
const parts = [];
|
|
514
|
+
parts.push(`Coherence energy ${result.energy.toFixed(3)} exceeds threshold ${threshold.toFixed(3)}.`);
|
|
515
|
+
const c = result.components;
|
|
516
|
+
if (c.assertionCoverage > 0.5) {
|
|
517
|
+
parts.push('High assertion-observation mismatch (possible hallucination).');
|
|
518
|
+
}
|
|
519
|
+
if (c.codeCoverage > 0.5) {
|
|
520
|
+
parts.push('Low code coverage.');
|
|
521
|
+
}
|
|
522
|
+
if (c.confidencePenalty > 0.5) {
|
|
523
|
+
parts.push('Low generator confidence.');
|
|
524
|
+
}
|
|
525
|
+
if (c.contradictionScore > 0.3) {
|
|
526
|
+
parts.push('Contradictions detected between assertions and observed behavior.');
|
|
527
|
+
}
|
|
528
|
+
if (c.laplacianDeviation > 0.5) {
|
|
529
|
+
parts.push('Inconsistent assertion structure (high Laplacian deviation).');
|
|
530
|
+
}
|
|
531
|
+
return parts.join(' ');
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Create a Blake3-style hash-chained witness record.
|
|
535
|
+
* Falls back to SHA-256 when Blake3 is unavailable.
|
|
536
|
+
*/
|
|
537
|
+
createWitnessRecord(artifact, energy, threshold, passed) {
|
|
538
|
+
const id = randomUUID();
|
|
539
|
+
const timestamp = Date.now();
|
|
540
|
+
const artifactHash = this.hashContent(JSON.stringify(artifact));
|
|
541
|
+
const record = {
|
|
542
|
+
id,
|
|
543
|
+
timestamp,
|
|
544
|
+
artifactHash,
|
|
545
|
+
energy,
|
|
546
|
+
threshold,
|
|
547
|
+
passed,
|
|
548
|
+
previousHash: this.lastWitnessHash,
|
|
549
|
+
recordHash: '', // Will be computed below
|
|
550
|
+
};
|
|
551
|
+
// Compute record hash (chain link)
|
|
552
|
+
const hashPayload = `${id}|${timestamp}|${artifactHash}|${energy}|${threshold}|${passed}|${this.lastWitnessHash}`;
|
|
553
|
+
record.recordHash = this.hashContent(hashPayload);
|
|
554
|
+
// Update chain
|
|
555
|
+
const flags = getRuVectorFeatureFlags();
|
|
556
|
+
if (flags.useWitnessChain) {
|
|
557
|
+
this.witnessChain.push(record);
|
|
558
|
+
this.lastWitnessHash = record.recordHash;
|
|
559
|
+
}
|
|
560
|
+
return record;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Hash content using SHA-256 (Blake3 fallback).
|
|
564
|
+
*/
|
|
565
|
+
hashContent(content) {
|
|
566
|
+
return createHash('sha256').update(content).digest('hex');
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Log a coherence decision for observability.
|
|
570
|
+
*/
|
|
571
|
+
logDecision(decision) {
|
|
572
|
+
this.decisionLog.push(decision);
|
|
573
|
+
// Keep bounded
|
|
574
|
+
const maxLog = 1000;
|
|
575
|
+
if (this.decisionLog.length > maxLog) {
|
|
576
|
+
this.decisionLog = this.decisionLog.slice(-maxLog);
|
|
577
|
+
}
|
|
578
|
+
logger.debug('Coherence decision', {
|
|
579
|
+
domain: decision.domain,
|
|
580
|
+
energy: decision.energy,
|
|
581
|
+
tier: decision.tier,
|
|
582
|
+
passed: decision.passed,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Extract assertions from a transfer pattern object.
|
|
587
|
+
*/
|
|
588
|
+
extractAssertions(pattern) {
|
|
589
|
+
if (Array.isArray(pattern.assertions)) {
|
|
590
|
+
return pattern.assertions.map(String);
|
|
591
|
+
}
|
|
592
|
+
if (typeof pattern.description === 'string') {
|
|
593
|
+
return [pattern.description];
|
|
594
|
+
}
|
|
595
|
+
return ['transfer-pattern'];
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Extract observed behaviors from a transfer pattern object.
|
|
599
|
+
*/
|
|
600
|
+
extractObservedBehavior(pattern) {
|
|
601
|
+
if (Array.isArray(pattern.observedBehavior)) {
|
|
602
|
+
return pattern.observedBehavior.map(String);
|
|
603
|
+
}
|
|
604
|
+
if (typeof pattern.evidence === 'string') {
|
|
605
|
+
return [pattern.evidence];
|
|
606
|
+
}
|
|
607
|
+
return ['observed'];
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
// ============================================================================
|
|
611
|
+
// Factory
|
|
612
|
+
// ============================================================================
|
|
613
|
+
/**
|
|
614
|
+
* Create a coherence gate instance.
|
|
615
|
+
*
|
|
616
|
+
* @param threshold - Coherence energy threshold (default: 0.4)
|
|
617
|
+
* @returns A new CoherenceGate instance
|
|
618
|
+
*/
|
|
619
|
+
export function createCoherenceGate(threshold) {
|
|
620
|
+
return new CoherenceGate(threshold);
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Create a transfer coherence gate.
|
|
624
|
+
*
|
|
625
|
+
* Returns the real CoherenceGate implementation (replacing the stub).
|
|
626
|
+
* The CoherenceGate implements ITransferCoherenceGate.
|
|
627
|
+
*/
|
|
628
|
+
export function createRealTransferCoherenceGate() {
|
|
629
|
+
return new CoherenceGate();
|
|
630
|
+
}
|
|
631
|
+
//# sourceMappingURL=coherence-gate.js.map
|