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,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG Attention Scheduler for Intelligent Test Execution Ordering
|
|
3
|
+
* RuVector Integration Plan - Phase 4, Task 4.2
|
|
4
|
+
*
|
|
5
|
+
* Uses DAG-based attention mechanisms to intelligently order test execution:
|
|
6
|
+
* - Critical Path Attention: Identifies the longest chain in the test dependency DAG
|
|
7
|
+
* - Parallel Branch Attention: Finds sets of tests that can run concurrently
|
|
8
|
+
* - MinCut-Gated Attention: Prunes low-value tests to speed up execution
|
|
9
|
+
*
|
|
10
|
+
* Self-learning: tracks execution times and improves ordering over runs.
|
|
11
|
+
* TypeScript implementation (no native package exists for DAG attention).
|
|
12
|
+
*
|
|
13
|
+
* @module test-scheduling/dag-attention-scheduler
|
|
14
|
+
*/
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Native WASM Backend Status
|
|
17
|
+
// No native package exists for DAG attention — the TypeScript
|
|
18
|
+
// implementation IS the production implementation.
|
|
19
|
+
// ============================================================================
|
|
20
|
+
const _nativeAvailable = false;
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// DAGAttentionScheduler
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* DAG-based test scheduler using attention mechanisms for intelligent ordering.
|
|
26
|
+
*
|
|
27
|
+
* Three attention types control scheduling:
|
|
28
|
+
* 1. Critical Path Attention - finds the longest dependency chain
|
|
29
|
+
* 2. Parallel Branch Attention - finds independent test groups
|
|
30
|
+
* 3. MinCut-Gated Attention - prunes low-value tests under a time budget
|
|
31
|
+
*
|
|
32
|
+
* Self-learning: records actual execution times and adjusts estimated
|
|
33
|
+
* durations over successive runs via exponential moving average.
|
|
34
|
+
*/
|
|
35
|
+
export class DAGAttentionScheduler {
|
|
36
|
+
executionHistory = [];
|
|
37
|
+
learnedDurations = new Map();
|
|
38
|
+
runCount = 0;
|
|
39
|
+
lastPrunedCount = 0;
|
|
40
|
+
learningRate;
|
|
41
|
+
maxHistorySize;
|
|
42
|
+
constructor(options) {
|
|
43
|
+
this.learningRate = options?.learningRate ?? 0.3;
|
|
44
|
+
this.maxHistorySize = options?.maxHistorySize ?? 10_000;
|
|
45
|
+
}
|
|
46
|
+
// --------------------------------------------------------------------------
|
|
47
|
+
// Public API
|
|
48
|
+
// --------------------------------------------------------------------------
|
|
49
|
+
/**
|
|
50
|
+
* Build the internal TestDAG from an array of test nodes.
|
|
51
|
+
* Validates dependencies, computes forward edges, critical path,
|
|
52
|
+
* and parallel groups.
|
|
53
|
+
* @throws Error if a dependency references a non-existent test ID
|
|
54
|
+
*/
|
|
55
|
+
buildTestDAG(tests) {
|
|
56
|
+
const nodes = new Map();
|
|
57
|
+
const edges = new Map();
|
|
58
|
+
for (const test of tests) {
|
|
59
|
+
const adjusted = this.applyLearnedDuration(test);
|
|
60
|
+
nodes.set(adjusted.id, adjusted);
|
|
61
|
+
edges.set(adjusted.id, []);
|
|
62
|
+
}
|
|
63
|
+
for (const test of tests) {
|
|
64
|
+
for (const depId of test.dependencies) {
|
|
65
|
+
if (!nodes.has(depId)) {
|
|
66
|
+
throw new Error(`Test '${test.id}' depends on '${depId}' which does not exist in the test set`);
|
|
67
|
+
}
|
|
68
|
+
edges.get(depId).push(test.id);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const criticalPath = this.computeCriticalPath(nodes, edges);
|
|
72
|
+
const parallelGroups = this.computeParallelGroups(nodes, edges);
|
|
73
|
+
return { nodes, edges, criticalPath, parallelGroups };
|
|
74
|
+
}
|
|
75
|
+
/** Find the critical path (longest duration chain) through the DAG. */
|
|
76
|
+
findCriticalPath(dag) {
|
|
77
|
+
return dag.criticalPath
|
|
78
|
+
.map((id) => dag.nodes.get(id))
|
|
79
|
+
.filter((n) => n !== undefined);
|
|
80
|
+
}
|
|
81
|
+
/** Find groups of tests that can execute concurrently. */
|
|
82
|
+
findParallelBranches(dag) {
|
|
83
|
+
return dag.parallelGroups.map((group) => group
|
|
84
|
+
.map((id) => dag.nodes.get(id))
|
|
85
|
+
.filter((n) => n !== undefined));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Prune low-value tests from the DAG to fit within a time budget.
|
|
89
|
+
* Tests are scored by attention weight (priority * failure weight *
|
|
90
|
+
* downstream impact). Lowest-scored tests are removed first, unless
|
|
91
|
+
* they are on the critical path or have active dependents.
|
|
92
|
+
*/
|
|
93
|
+
pruneByMinCut(dag, budget) {
|
|
94
|
+
const totalDuration = this.sumDurations(dag.nodes);
|
|
95
|
+
if (totalDuration <= budget) {
|
|
96
|
+
this.lastPrunedCount = 0;
|
|
97
|
+
return dag;
|
|
98
|
+
}
|
|
99
|
+
const scores = this.computeAttentionScores(dag);
|
|
100
|
+
const sortedTests = Array.from(scores.entries()).sort((a, b) => a[1] - b[1]);
|
|
101
|
+
const criticalSet = new Set(dag.criticalPath);
|
|
102
|
+
const prunedIds = new Set();
|
|
103
|
+
let currentDuration = totalDuration;
|
|
104
|
+
for (const [testId] of sortedTests) {
|
|
105
|
+
if (currentDuration <= budget)
|
|
106
|
+
break;
|
|
107
|
+
if (criticalSet.has(testId))
|
|
108
|
+
continue;
|
|
109
|
+
const dependents = dag.edges.get(testId) ?? [];
|
|
110
|
+
if (dependents.some((depId) => !prunedIds.has(depId)))
|
|
111
|
+
continue;
|
|
112
|
+
const node = dag.nodes.get(testId);
|
|
113
|
+
if (!node)
|
|
114
|
+
continue;
|
|
115
|
+
prunedIds.add(testId);
|
|
116
|
+
currentDuration -= node.estimatedDuration;
|
|
117
|
+
}
|
|
118
|
+
this.lastPrunedCount = prunedIds.size;
|
|
119
|
+
const remaining = Array.from(dag.nodes.values()).filter((n) => !prunedIds.has(n.id));
|
|
120
|
+
return this.buildTestDAG(remaining);
|
|
121
|
+
}
|
|
122
|
+
/** Produce a complete execution schedule for the given tests. */
|
|
123
|
+
schedule(tests) {
|
|
124
|
+
if (tests.length === 0) {
|
|
125
|
+
return { phases: [], totalEstimatedTime: 0, criticalPathTime: 0, parallelism: 0 };
|
|
126
|
+
}
|
|
127
|
+
const dag = this.buildTestDAG(tests);
|
|
128
|
+
const parallelBranches = this.findParallelBranches(dag);
|
|
129
|
+
const phases = parallelBranches.map((group) => ({
|
|
130
|
+
tests: group,
|
|
131
|
+
canRunInParallel: group.length > 1,
|
|
132
|
+
}));
|
|
133
|
+
const criticalPathTime = this.computeCriticalPathDuration(dag);
|
|
134
|
+
const totalWork = this.sumDurations(dag.nodes);
|
|
135
|
+
const wallClockEstimate = phases.reduce((total, phase) => {
|
|
136
|
+
if (phase.canRunInParallel) {
|
|
137
|
+
return total + Math.max(...phase.tests.map((t) => t.estimatedDuration));
|
|
138
|
+
}
|
|
139
|
+
return total + phase.tests.reduce((s, t) => s + t.estimatedDuration, 0);
|
|
140
|
+
}, 0);
|
|
141
|
+
const parallelism = wallClockEstimate > 0 ? totalWork / wallClockEstimate : 1;
|
|
142
|
+
this.runCount++;
|
|
143
|
+
return { phases, totalEstimatedTime: wallClockEstimate, criticalPathTime, parallelism };
|
|
144
|
+
}
|
|
145
|
+
/** Return optimization statistics. */
|
|
146
|
+
getOptimizationStats() {
|
|
147
|
+
return {
|
|
148
|
+
totalTests: 0,
|
|
149
|
+
criticalPathLength: 0,
|
|
150
|
+
parallelGroupCount: 0,
|
|
151
|
+
prunedTests: this.lastPrunedCount,
|
|
152
|
+
estimatedTimeSaved: 0,
|
|
153
|
+
historicalRuns: this.runCount,
|
|
154
|
+
usingNativeBackend: _nativeAvailable,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/** Record actual execution results for self-learning via EMA. */
|
|
158
|
+
recordExecution(testId, actualDuration, result) {
|
|
159
|
+
this.executionHistory.push({ testId, actualDuration, result, timestamp: Date.now() });
|
|
160
|
+
if (this.executionHistory.length > this.maxHistorySize) {
|
|
161
|
+
this.executionHistory = this.executionHistory.slice(-this.maxHistorySize);
|
|
162
|
+
}
|
|
163
|
+
const current = this.learnedDurations.get(testId);
|
|
164
|
+
if (current !== undefined) {
|
|
165
|
+
this.learnedDurations.set(testId, current * (1 - this.learningRate) + actualDuration * this.learningRate);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
this.learnedDurations.set(testId, actualDuration);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** Get learned duration for a test, or undefined if no history. */
|
|
172
|
+
getLearnedDuration(testId) {
|
|
173
|
+
return this.learnedDurations.get(testId);
|
|
174
|
+
}
|
|
175
|
+
/** Check whether the native ruvector-dag-wasm backend is available. */
|
|
176
|
+
isNativeBackendAvailable() {
|
|
177
|
+
return _nativeAvailable;
|
|
178
|
+
}
|
|
179
|
+
// --------------------------------------------------------------------------
|
|
180
|
+
// Internal: Critical Path (longest-path DP on topological order)
|
|
181
|
+
// --------------------------------------------------------------------------
|
|
182
|
+
computeCriticalPath(nodes, edges) {
|
|
183
|
+
const sorted = this.topologicalSort(nodes, edges);
|
|
184
|
+
if (sorted.length === 0)
|
|
185
|
+
return [];
|
|
186
|
+
const dist = new Map();
|
|
187
|
+
const pred = new Map();
|
|
188
|
+
for (const id of sorted) {
|
|
189
|
+
dist.set(id, nodes.get(id).estimatedDuration);
|
|
190
|
+
pred.set(id, null);
|
|
191
|
+
}
|
|
192
|
+
for (const id of sorted) {
|
|
193
|
+
const currentDist = dist.get(id);
|
|
194
|
+
for (const depId of edges.get(id) ?? []) {
|
|
195
|
+
const depNode = nodes.get(depId);
|
|
196
|
+
if (!depNode)
|
|
197
|
+
continue;
|
|
198
|
+
const newDist = currentDist + depNode.estimatedDuration;
|
|
199
|
+
if (newDist > (dist.get(depId) ?? 0)) {
|
|
200
|
+
dist.set(depId, newDist);
|
|
201
|
+
pred.set(depId, id);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
let maxDist = 0;
|
|
206
|
+
let endNode = null;
|
|
207
|
+
for (const [id, d] of dist) {
|
|
208
|
+
if (d > maxDist) {
|
|
209
|
+
maxDist = d;
|
|
210
|
+
endNode = id;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (!endNode)
|
|
214
|
+
return [];
|
|
215
|
+
const path = [];
|
|
216
|
+
let cur = endNode;
|
|
217
|
+
while (cur !== null) {
|
|
218
|
+
path.unshift(cur);
|
|
219
|
+
cur = pred.get(cur) ?? null;
|
|
220
|
+
}
|
|
221
|
+
return path;
|
|
222
|
+
}
|
|
223
|
+
computeCriticalPathDuration(dag) {
|
|
224
|
+
return dag.criticalPath.reduce((total, id) => total + (dag.nodes.get(id)?.estimatedDuration ?? 0), 0);
|
|
225
|
+
}
|
|
226
|
+
// --------------------------------------------------------------------------
|
|
227
|
+
// Internal: Parallel Groups (topological levels)
|
|
228
|
+
// --------------------------------------------------------------------------
|
|
229
|
+
computeParallelGroups(nodes, edges) {
|
|
230
|
+
const sorted = this.topologicalSort(nodes, edges);
|
|
231
|
+
if (sorted.length === 0)
|
|
232
|
+
return [];
|
|
233
|
+
const depSets = new Map();
|
|
234
|
+
for (const [id, node] of nodes) {
|
|
235
|
+
depSets.set(id, new Set(node.dependencies));
|
|
236
|
+
}
|
|
237
|
+
const level = new Map();
|
|
238
|
+
for (const id of sorted) {
|
|
239
|
+
let maxDepLevel = -1;
|
|
240
|
+
for (const depId of depSets.get(id) ?? new Set()) {
|
|
241
|
+
const depLevel = level.get(depId);
|
|
242
|
+
if (depLevel !== undefined && depLevel > maxDepLevel)
|
|
243
|
+
maxDepLevel = depLevel;
|
|
244
|
+
}
|
|
245
|
+
level.set(id, maxDepLevel + 1);
|
|
246
|
+
}
|
|
247
|
+
const groups = new Map();
|
|
248
|
+
for (const id of sorted) {
|
|
249
|
+
const lvl = level.get(id) ?? 0;
|
|
250
|
+
if (!groups.has(lvl))
|
|
251
|
+
groups.set(lvl, []);
|
|
252
|
+
groups.get(lvl).push(id);
|
|
253
|
+
}
|
|
254
|
+
const maxLevel = Math.max(...Array.from(groups.keys()), -1);
|
|
255
|
+
const result = [];
|
|
256
|
+
for (let i = 0; i <= maxLevel; i++) {
|
|
257
|
+
const group = groups.get(i);
|
|
258
|
+
if (group && group.length > 0)
|
|
259
|
+
result.push(group);
|
|
260
|
+
}
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
// --------------------------------------------------------------------------
|
|
264
|
+
// Internal: Attention Scores for MinCut Pruning
|
|
265
|
+
// --------------------------------------------------------------------------
|
|
266
|
+
computeAttentionScores(dag) {
|
|
267
|
+
const scores = new Map();
|
|
268
|
+
const transitiveCounts = this.countTransitiveDependents(dag);
|
|
269
|
+
for (const [id, node] of dag.nodes) {
|
|
270
|
+
const failureWeight = node.lastResult === 'fail' ? 2.0 : 1.0;
|
|
271
|
+
const downstream = transitiveCounts.get(id) ?? 0;
|
|
272
|
+
scores.set(id, node.priority * failureWeight * (1 + downstream));
|
|
273
|
+
}
|
|
274
|
+
return scores;
|
|
275
|
+
}
|
|
276
|
+
countTransitiveDependents(dag) {
|
|
277
|
+
const counts = new Map();
|
|
278
|
+
const visited = new Map();
|
|
279
|
+
const getTransitive = (id) => {
|
|
280
|
+
if (visited.has(id))
|
|
281
|
+
return visited.get(id);
|
|
282
|
+
const result = new Set();
|
|
283
|
+
for (const depId of dag.edges.get(id) ?? []) {
|
|
284
|
+
result.add(depId);
|
|
285
|
+
for (const transId of getTransitive(depId))
|
|
286
|
+
result.add(transId);
|
|
287
|
+
}
|
|
288
|
+
visited.set(id, result);
|
|
289
|
+
return result;
|
|
290
|
+
};
|
|
291
|
+
for (const id of dag.nodes.keys()) {
|
|
292
|
+
counts.set(id, getTransitive(id).size);
|
|
293
|
+
}
|
|
294
|
+
return counts;
|
|
295
|
+
}
|
|
296
|
+
// --------------------------------------------------------------------------
|
|
297
|
+
// Internal: Topological Sort (Kahn's Algorithm)
|
|
298
|
+
// --------------------------------------------------------------------------
|
|
299
|
+
topologicalSort(nodes, edges) {
|
|
300
|
+
const inDegree = new Map();
|
|
301
|
+
for (const id of nodes.keys())
|
|
302
|
+
inDegree.set(id, 0);
|
|
303
|
+
for (const children of edges.values()) {
|
|
304
|
+
for (const childId of children) {
|
|
305
|
+
if (inDegree.has(childId)) {
|
|
306
|
+
inDegree.set(childId, (inDegree.get(childId) ?? 0) + 1);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const queue = [];
|
|
311
|
+
for (const [id, deg] of inDegree) {
|
|
312
|
+
if (deg === 0)
|
|
313
|
+
queue.push(id);
|
|
314
|
+
}
|
|
315
|
+
const sorted = [];
|
|
316
|
+
while (queue.length > 0) {
|
|
317
|
+
const nodeId = queue.shift();
|
|
318
|
+
sorted.push(nodeId);
|
|
319
|
+
for (const childId of edges.get(nodeId) ?? []) {
|
|
320
|
+
const newDeg = (inDegree.get(childId) ?? 0) - 1;
|
|
321
|
+
inDegree.set(childId, newDeg);
|
|
322
|
+
if (newDeg === 0)
|
|
323
|
+
queue.push(childId);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (sorted.length !== nodes.size) {
|
|
327
|
+
throw new Error(`Cycle detected in test DAG: sorted ${sorted.length} of ${nodes.size} nodes`);
|
|
328
|
+
}
|
|
329
|
+
return sorted;
|
|
330
|
+
}
|
|
331
|
+
// --------------------------------------------------------------------------
|
|
332
|
+
// Internal: Self-Learning
|
|
333
|
+
// --------------------------------------------------------------------------
|
|
334
|
+
applyLearnedDuration(test) {
|
|
335
|
+
const learned = this.learnedDurations.get(test.id);
|
|
336
|
+
if (learned !== undefined) {
|
|
337
|
+
return { ...test, estimatedDuration: Math.round(learned) };
|
|
338
|
+
}
|
|
339
|
+
return test;
|
|
340
|
+
}
|
|
341
|
+
// --------------------------------------------------------------------------
|
|
342
|
+
// Internal: Utilities
|
|
343
|
+
// --------------------------------------------------------------------------
|
|
344
|
+
sumDurations(nodes) {
|
|
345
|
+
let total = 0;
|
|
346
|
+
for (const node of nodes.values())
|
|
347
|
+
total += node.estimatedDuration;
|
|
348
|
+
return total;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// ============================================================================
|
|
352
|
+
// Factory Function
|
|
353
|
+
// ============================================================================
|
|
354
|
+
/** Create a DAGAttentionScheduler with optional configuration. */
|
|
355
|
+
export function createDAGAttentionScheduler(options) {
|
|
356
|
+
return new DAGAttentionScheduler(options);
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=dag-attention-scheduler.js.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG Attention Scheduler Types
|
|
3
|
+
* RuVector Integration Plan - Phase 4, Task 4.2
|
|
4
|
+
*
|
|
5
|
+
* Type definitions for DAG-based test execution ordering.
|
|
6
|
+
*
|
|
7
|
+
* @module test-scheduling/dag-attention-types
|
|
8
|
+
*/
|
|
9
|
+
/** A test node in the dependency graph */
|
|
10
|
+
export interface TestNode {
|
|
11
|
+
/** Unique identifier */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Human-readable test name */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Estimated duration in milliseconds */
|
|
16
|
+
estimatedDuration: number;
|
|
17
|
+
/** IDs of tests that must complete before this test can start */
|
|
18
|
+
dependencies: string[];
|
|
19
|
+
/** Numeric priority (higher = more important) */
|
|
20
|
+
priority: number;
|
|
21
|
+
/** Tags for categorization (e.g., 'unit', 'integration') */
|
|
22
|
+
tags: string[];
|
|
23
|
+
/** Last recorded execution time in ms */
|
|
24
|
+
lastExecutionTime?: number;
|
|
25
|
+
/** Last test result */
|
|
26
|
+
lastResult?: 'pass' | 'fail' | 'skip';
|
|
27
|
+
}
|
|
28
|
+
/** Internal DAG representation built from TestNode[] */
|
|
29
|
+
export interface TestDAG {
|
|
30
|
+
/** All nodes indexed by ID */
|
|
31
|
+
nodes: Map<string, TestNode>;
|
|
32
|
+
/** Forward edges: node -> its direct dependents */
|
|
33
|
+
edges: Map<string, string[]>;
|
|
34
|
+
/** IDs on the critical path, in execution order */
|
|
35
|
+
criticalPath: string[];
|
|
36
|
+
/** Groups of test IDs that can run in parallel */
|
|
37
|
+
parallelGroups: string[][];
|
|
38
|
+
}
|
|
39
|
+
/** A single phase in the scheduled execution */
|
|
40
|
+
export interface SchedulePhase {
|
|
41
|
+
/** Tests assigned to this phase */
|
|
42
|
+
tests: TestNode[];
|
|
43
|
+
/** Whether the tests in this phase can run concurrently */
|
|
44
|
+
canRunInParallel: boolean;
|
|
45
|
+
}
|
|
46
|
+
/** Full scheduled execution plan */
|
|
47
|
+
export interface ScheduledExecution {
|
|
48
|
+
/** Ordered phases of execution */
|
|
49
|
+
phases: SchedulePhase[];
|
|
50
|
+
/** Total estimated wall-clock time in ms */
|
|
51
|
+
totalEstimatedTime: number;
|
|
52
|
+
/** Sum of durations along the critical path in ms */
|
|
53
|
+
criticalPathTime: number;
|
|
54
|
+
/** Effective parallelism factor (total work / wall-clock) */
|
|
55
|
+
parallelism: number;
|
|
56
|
+
}
|
|
57
|
+
/** Statistics about scheduler optimizations */
|
|
58
|
+
export interface SchedulerStats {
|
|
59
|
+
/** Total number of tests in the DAG */
|
|
60
|
+
totalTests: number;
|
|
61
|
+
/** Number of tests on the critical path */
|
|
62
|
+
criticalPathLength: number;
|
|
63
|
+
/** Number of parallel groups discovered */
|
|
64
|
+
parallelGroupCount: number;
|
|
65
|
+
/** Number of tests pruned by MinCut */
|
|
66
|
+
prunedTests: number;
|
|
67
|
+
/** Estimated time saved via parallelism (ms) */
|
|
68
|
+
estimatedTimeSaved: number;
|
|
69
|
+
/** Number of completed scheduling runs tracked */
|
|
70
|
+
historicalRuns: number;
|
|
71
|
+
/** Whether the native WASM backend is in use */
|
|
72
|
+
usingNativeBackend: boolean;
|
|
73
|
+
}
|
|
74
|
+
/** Historical record for self-learning */
|
|
75
|
+
export interface ExecutionRecord {
|
|
76
|
+
testId: string;
|
|
77
|
+
actualDuration: number;
|
|
78
|
+
result: 'pass' | 'fail' | 'skip';
|
|
79
|
+
timestamp: number;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=dag-attention-types.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG Attention Scheduler Types
|
|
3
|
+
* RuVector Integration Plan - Phase 4, Task 4.2
|
|
4
|
+
*
|
|
5
|
+
* Type definitions for DAG-based test execution ordering.
|
|
6
|
+
*
|
|
7
|
+
* @module test-scheduling/dag-attention-types
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=dag-attention-types.js.map
|
|
@@ -72,4 +72,5 @@ export { GitAwareTestSelector, createTestSelector, getAffectedTests, type TestSe
|
|
|
72
72
|
export { FlakyTestTracker, createFlakyTracker, loadFlakyTracker, saveFlakyTracker, type FlakyTrackerConfig, type FlakyAnalysis, } from './flaky-tracking/flaky-tracker';
|
|
73
73
|
export { GitHubActionsReporter, createGitHubActionsReporter, reportToGitHubActions, detectCIEnvironment, type GitHubActionsConfig, } from './cicd/github-actions';
|
|
74
74
|
export { TestSchedulingPipeline, createTestPipeline, runTestPipeline, type PipelineConfig, type PipelineResult, } from './pipeline';
|
|
75
|
+
export { DAGAttentionScheduler, createDAGAttentionScheduler, type TestNode, type TestDAG, type SchedulePhase, type ScheduledExecution, type SchedulerStats as DAGSchedulerStats, } from './dag-attention-scheduler';
|
|
75
76
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -89,4 +89,8 @@ export { GitHubActionsReporter, createGitHubActionsReporter, reportToGitHubActio
|
|
|
89
89
|
// Integration Pipeline
|
|
90
90
|
// ============================================================================
|
|
91
91
|
export { TestSchedulingPipeline, createTestPipeline, runTestPipeline, } from './pipeline';
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// DAG Attention Scheduler (Phase 4, Task 4.2)
|
|
94
|
+
// ============================================================================
|
|
95
|
+
export { DAGAttentionScheduler, createDAGAttentionScheduler, } from './dag-attention-scheduler';
|
|
92
96
|
//# sourceMappingURL=index.js.map
|
|
@@ -55,6 +55,14 @@ export interface PipelineConfig {
|
|
|
55
55
|
flakyTracker?: Partial<FlakyTrackerConfig>;
|
|
56
56
|
/** Run all tests (skip git-aware selection) */
|
|
57
57
|
runAllTests?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Enable DAG attention scheduling for dependency-aware test ordering.
|
|
60
|
+
* When enabled and test dependencies are available, uses DAGAttentionScheduler
|
|
61
|
+
* to optimize execution order via critical path and parallel branch detection.
|
|
62
|
+
* Requires feature flag useDAGAttention to also be on.
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
useDAGAttention?: boolean;
|
|
58
66
|
}
|
|
59
67
|
export interface PipelineResult {
|
|
60
68
|
/** Test phase results */
|
|
@@ -123,6 +123,34 @@ export class TestSchedulingPipeline {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
const selectionMs = performance.now() - selectionStart;
|
|
126
|
+
// Step 1b: DAG attention-based ordering (when enabled and tests selected)
|
|
127
|
+
if (this.config.useDAGAttention && selectedTests.length > 0) {
|
|
128
|
+
try {
|
|
129
|
+
const { isDAGAttentionEnabled } = await import('../integrations/ruvector/feature-flags.js');
|
|
130
|
+
if (isDAGAttentionEnabled()) {
|
|
131
|
+
const { createDAGAttentionScheduler } = await import('./dag-attention-scheduler.js');
|
|
132
|
+
const dagScheduler = createDAGAttentionScheduler();
|
|
133
|
+
const nodes = selectedTests.map(t => ({
|
|
134
|
+
id: t, name: t, estimatedDuration: 1000,
|
|
135
|
+
dependencies: [], priority: 1, tags: [],
|
|
136
|
+
}));
|
|
137
|
+
const schedule = dagScheduler.schedule(nodes);
|
|
138
|
+
// Flatten scheduled phases into ordered test list
|
|
139
|
+
const orderedTests = [];
|
|
140
|
+
for (const phase of schedule.phases) {
|
|
141
|
+
orderedTests.push(...phase.tests.map(t => t.id));
|
|
142
|
+
}
|
|
143
|
+
if (orderedTests.length > 0) {
|
|
144
|
+
selectedTests = orderedTests;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
// DAG scheduling is best-effort; fall through to default ordering
|
|
150
|
+
if (process.env.DEBUG)
|
|
151
|
+
console.debug('[Pipeline] DAG attention scheduling skipped:', err instanceof Error ? err.message : err);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
126
154
|
// Step 2: Execute tests
|
|
127
155
|
const executionStart = performance.now();
|
|
128
156
|
let phaseResults;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-qe",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "Agentic Quality Engineering V3 - Domain-Driven Design Architecture with 13 Bounded Contexts, O(log n) coverage analysis, ReasoningBank learning, 60 specialized QE agents, mathematical Coherence verification, deep Claude Flow integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -131,6 +131,8 @@
|
|
|
131
131
|
"@faker-js/faker": "^10.2.0",
|
|
132
132
|
"@ruvector/attention": "0.1.3",
|
|
133
133
|
"@ruvector/gnn": "0.1.19",
|
|
134
|
+
"@ruvector/learning-wasm": "^0.1.29",
|
|
135
|
+
"@ruvector/router": "^0.1.28",
|
|
134
136
|
"@ruvector/rvf-node": "^0.1.7",
|
|
135
137
|
"@ruvector/sona": "0.1.5",
|
|
136
138
|
"@xenova/transformers": "^2.17.2",
|
|
@@ -164,7 +166,9 @@
|
|
|
164
166
|
"@ruvector/gnn-linux-arm64-gnu": "0.1.19",
|
|
165
167
|
"@ruvector/gnn-linux-arm64-musl": "npm:@ruvector/gnn-linux-arm64-gnu@0.1.19",
|
|
166
168
|
"@ruvector/gnn-linux-x64-gnu": "0.1.19",
|
|
167
|
-
"@ruvector/gnn-linux-x64-musl": "npm:@ruvector/gnn-linux-x64-gnu@0.1.19"
|
|
169
|
+
"@ruvector/gnn-linux-x64-musl": "npm:@ruvector/gnn-linux-x64-gnu@0.1.19",
|
|
170
|
+
"@ruvector/tiny-dancer-linux-arm64-gnu": "^0.1.17",
|
|
171
|
+
"rvlite": "^0.2.4"
|
|
168
172
|
},
|
|
169
173
|
"resolutions": {
|
|
170
174
|
"graceful-fs": "^4.2.11",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agentic QE v3 - Migrate Command
|
|
3
|
-
*
|
|
4
|
-
* V2-to-V3 migration tools with agent compatibility (ADR-048).
|
|
5
|
-
*/
|
|
6
|
-
import { Command } from 'commander';
|
|
7
|
-
import type { CLIContext } from '../handlers/interfaces.js';
|
|
8
|
-
export declare function createMigrateCommand(context: CLIContext, cleanupAndExit: (code: number) => Promise<never>, ensureInitialized: () => Promise<boolean>): Command;
|
|
9
|
-
//# sourceMappingURL=migrate.d.ts.map
|