agentic-qe 3.8.4 ā 3.8.6
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/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/cli/bundle.js +694 -694
- package/dist/cli/commands/hooks-handlers/command-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/command-hooks.js +253 -0
- package/dist/cli/commands/hooks-handlers/editing-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/editing-hooks.js +161 -0
- package/dist/cli/commands/hooks-handlers/hooks-dream-learning.d.ts +57 -0
- package/dist/cli/commands/hooks-handlers/hooks-dream-learning.js +263 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.d.ts +52 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.js +223 -0
- package/dist/cli/commands/hooks-handlers/routing-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/routing-hooks.js +107 -0
- package/dist/cli/commands/hooks-handlers/session-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/session-hooks.js +171 -0
- package/dist/cli/commands/hooks-handlers/stats-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/stats-hooks.js +248 -0
- package/dist/cli/commands/hooks-handlers/task-hooks.d.ts +12 -0
- package/dist/cli/commands/hooks-handlers/task-hooks.js +152 -0
- package/dist/cli/commands/hooks.d.ts +3 -23
- package/dist/cli/commands/hooks.js +16 -1459
- package/dist/coordination/mincut/phase-executor.d.ts +27 -0
- package/dist/coordination/mincut/phase-executor.js +70 -0
- package/dist/coordination/mincut/time-crystal-analysis.d.ts +35 -0
- package/dist/coordination/mincut/time-crystal-analysis.js +237 -0
- package/dist/coordination/mincut/time-crystal-persistence.d.ts +35 -0
- package/dist/coordination/mincut/time-crystal-persistence.js +81 -0
- package/dist/coordination/mincut/time-crystal-scheduling.d.ts +34 -0
- package/dist/coordination/mincut/time-crystal-scheduling.js +213 -0
- package/dist/coordination/mincut/time-crystal-types.d.ts +278 -0
- package/dist/coordination/mincut/time-crystal-types.js +67 -0
- package/dist/coordination/mincut/time-crystal.d.ts +8 -438
- package/dist/coordination/mincut/time-crystal.js +87 -905
- package/dist/domains/base-domain-coordinator.d.ts +0 -15
- package/dist/domains/base-domain-coordinator.js +7 -5
- package/dist/domains/chaos-resilience/coordinator.d.ts +0 -4
- package/dist/domains/chaos-resilience/coordinator.js +24 -22
- package/dist/domains/chaos-resilience/services/chaos-engineer.d.ts +0 -4
- package/dist/domains/chaos-resilience/services/chaos-engineer.js +47 -45
- package/dist/domains/chaos-resilience/services/performance-profiler.d.ts +0 -4
- package/dist/domains/chaos-resilience/services/performance-profiler.js +10 -8
- package/dist/domains/code-intelligence/coordinator-consensus.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator-consensus.js +8 -6
- package/dist/domains/code-intelligence/coordinator-gnn.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator-gnn.js +8 -6
- package/dist/domains/code-intelligence/coordinator-hypergraph.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator-hypergraph.js +13 -11
- package/dist/domains/code-intelligence/coordinator.d.ts +0 -3
- package/dist/domains/code-intelligence/coordinator.js +21 -19
- package/dist/domains/code-intelligence/services/c4-model/index.d.ts +0 -3
- package/dist/domains/code-intelligence/services/c4-model/index.js +5 -3
- package/dist/domains/code-intelligence/services/knowledge-graph.d.ts +0 -6
- package/dist/domains/code-intelligence/services/knowledge-graph.js +4 -2
- package/dist/domains/code-intelligence/services/product-factors-bridge.d.ts +0 -5
- package/dist/domains/code-intelligence/services/product-factors-bridge.js +9 -7
- package/dist/domains/contract-testing/coordinator.d.ts +0 -6
- package/dist/domains/contract-testing/coordinator.js +25 -23
- package/dist/domains/contract-testing/services/contract-validator.d.ts +0 -4
- package/dist/domains/contract-testing/services/contract-validator.js +4 -2
- package/dist/domains/contract-testing/services/schema-validator.js +1 -1
- package/dist/domains/coverage-analysis/coordinator.js +13 -11
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +4 -2
- package/dist/domains/coverage-analysis/services/gap-detector.js +3 -1
- package/dist/domains/coverage-analysis/services/hnsw-index.d.ts +0 -15
- package/dist/domains/coverage-analysis/services/hnsw-index.js +3 -1
- package/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +0 -26
- package/dist/domains/coverage-analysis/services/sublinear-analyzer.js +3 -1
- package/dist/domains/defect-intelligence/coordinator.d.ts +1 -10
- package/dist/domains/defect-intelligence/coordinator.js +5 -3
- package/dist/domains/defect-intelligence/services/causal-root-cause-analyzer.d.ts +0 -6
- package/dist/domains/defect-intelligence/services/causal-root-cause-analyzer.js +3 -1
- package/dist/domains/defect-intelligence/services/defect-predictor.d.ts +0 -6
- package/dist/domains/defect-intelligence/services/defect-predictor.js +5 -3
- package/dist/domains/defect-intelligence/services/pattern-learner.d.ts +0 -4
- package/dist/domains/defect-intelligence/services/pattern-learner.js +3 -1
- package/dist/domains/defect-intelligence/services/root-cause-analyzer.d.ts +0 -6
- package/dist/domains/defect-intelligence/services/root-cause-analyzer.js +3 -1
- package/dist/domains/enterprise-integration/coordinator.js +6 -4
- package/dist/domains/learning-optimization/coordinator-consensus.d.ts +0 -3
- package/dist/domains/learning-optimization/coordinator-consensus.js +8 -6
- package/dist/domains/learning-optimization/coordinator.d.ts +0 -3
- package/dist/domains/learning-optimization/coordinator.js +15 -13
- package/dist/domains/learning-optimization/services/learning-coordinator.d.ts +0 -4
- package/dist/domains/learning-optimization/services/learning-coordinator.js +4 -2
- package/dist/domains/quality-assessment/coordinator-claim-verifier.d.ts +0 -3
- package/dist/domains/quality-assessment/coordinator-claim-verifier.js +6 -4
- package/dist/domains/quality-assessment/coordinator-gate-evaluation.d.ts +0 -4
- package/dist/domains/quality-assessment/coordinator-gate-evaluation.js +9 -7
- package/dist/domains/quality-assessment/coordinator-rl-integration.d.ts +0 -3
- package/dist/domains/quality-assessment/coordinator-rl-integration.js +10 -8
- package/dist/domains/quality-assessment/coordinator.d.ts +0 -15
- package/dist/domains/quality-assessment/coordinator.js +14 -12
- package/dist/domains/quality-assessment/services/deployment-advisor.d.ts +0 -10
- package/dist/domains/quality-assessment/services/deployment-advisor.js +4 -2
- package/dist/domains/quality-assessment/services/quality-analyzer.d.ts +0 -6
- package/dist/domains/quality-assessment/services/quality-analyzer.js +4 -2
- package/dist/domains/requirements-validation/coordinator.d.ts +0 -3
- package/dist/domains/requirements-validation/coordinator.js +15 -13
- package/dist/domains/requirements-validation/services/product-factors-assessment/code-intelligence/codebase-analyzer.d.ts +0 -5
- package/dist/domains/requirements-validation/services/product-factors-assessment/code-intelligence/codebase-analyzer.js +15 -13
- package/dist/domains/requirements-validation/services/product-factors-assessment/product-factors-service.d.ts +0 -6
- package/dist/domains/requirements-validation/services/product-factors-assessment/product-factors-service.js +9 -7
- package/dist/domains/requirements-validation/services/requirements-validator.d.ts +0 -6
- package/dist/domains/requirements-validation/services/requirements-validator.js +4 -2
- package/dist/domains/security-compliance/coordinator.js +24 -22
- package/dist/domains/security-compliance/services/scanners/dast-scanner.d.ts +0 -21
- package/dist/domains/security-compliance/services/scanners/dast-scanner.js +4 -2
- package/dist/domains/security-compliance/services/scanners/sast-scanner.d.ts +0 -4
- package/dist/domains/security-compliance/services/scanners/sast-scanner.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor-dast.d.ts +0 -4
- package/dist/domains/security-compliance/services/security-auditor-dast.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor-sast.d.ts +0 -3
- package/dist/domains/security-compliance/services/security-auditor-sast.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor-secrets.d.ts +0 -3
- package/dist/domains/security-compliance/services/security-auditor-secrets.js +3 -1
- package/dist/domains/security-compliance/services/security-auditor.js +11 -9
- package/dist/domains/test-execution/coordinator.js +11 -9
- package/dist/domains/test-execution/services/auth-state-manager.d.ts +0 -3
- package/dist/domains/test-execution/services/auth-state-manager.js +4 -2
- package/dist/domains/test-execution/services/e2e/e2e-coordinator.d.ts +0 -14
- package/dist/domains/test-execution/services/e2e/e2e-coordinator.js +3 -1
- package/dist/domains/test-execution/services/flaky-detector.js +4 -2
- package/dist/domains/test-execution/services/retry-handler.js +3 -1
- package/dist/domains/test-execution/services/test-executor.js +3 -1
- package/dist/domains/test-generation/coordinator.d.ts +0 -17
- package/dist/domains/test-generation/coordinator.js +33 -31
- package/dist/domains/test-generation/pattern-injection/edge-case-injector.d.ts +0 -5
- package/dist/domains/test-generation/pattern-injection/edge-case-injector.js +3 -1
- package/dist/domains/test-generation/services/code-transform-integration.d.ts +0 -7
- package/dist/domains/test-generation/services/code-transform-integration.js +3 -1
- package/dist/domains/test-generation/services/coherence-gate-service.d.ts +0 -3
- package/dist/domains/test-generation/services/coherence-gate-service.js +3 -1
- package/dist/domains/test-generation/services/test-generator.d.ts +0 -8
- package/dist/domains/test-generation/services/test-generator.js +5 -3
- package/dist/domains/visual-accessibility/coordinator.d.ts +0 -3
- package/dist/domains/visual-accessibility/coordinator.js +14 -12
- package/dist/domains/visual-accessibility/services/accessibility-tester-browser.d.ts +0 -3
- package/dist/domains/visual-accessibility/services/accessibility-tester-browser.js +52 -50
- package/dist/domains/visual-accessibility/services/accessibility-tester.d.ts +0 -4
- package/dist/domains/visual-accessibility/services/accessibility-tester.js +8 -6
- package/dist/domains/visual-accessibility/services/axe-core-integration.d.ts +0 -3
- package/dist/domains/visual-accessibility/services/axe-core-integration.js +20 -18
- package/dist/domains/visual-accessibility/services/browser-security-scanner.d.ts +0 -4
- package/dist/domains/visual-accessibility/services/browser-security-scanner.js +6 -4
- package/dist/domains/visual-accessibility/services/browser-swarm-coordinator.d.ts +0 -30
- package/dist/domains/visual-accessibility/services/browser-swarm-coordinator.js +5 -3
- package/dist/domains/visual-accessibility/services/viewport-capture.d.ts +0 -27
- package/dist/domains/visual-accessibility/services/viewport-capture.js +6 -4
- package/dist/domains/visual-accessibility/services/visual-regression.d.ts +0 -26
- package/dist/domains/visual-accessibility/services/visual-regression.js +4 -2
- package/dist/domains/visual-accessibility/services/visual-tester.d.ts +0 -4
- package/dist/domains/visual-accessibility/services/visual-tester.js +4 -2
- package/dist/governance/deterministic-gateway-integration.js +1 -1
- package/dist/learning/agent-routing.d.ts +53 -0
- package/dist/learning/agent-routing.js +142 -0
- package/dist/learning/embedding-utils.d.ts +34 -0
- package/dist/learning/embedding-utils.js +95 -0
- package/dist/learning/pattern-promotion.d.ts +63 -0
- package/dist/learning/pattern-promotion.js +187 -0
- package/dist/learning/pretrained-patterns.d.ts +14 -0
- package/dist/learning/pretrained-patterns.js +726 -0
- package/dist/learning/qe-reasoning-bank-types.d.ts +174 -0
- package/dist/learning/qe-reasoning-bank-types.js +24 -0
- package/dist/learning/qe-reasoning-bank.d.ts +9 -192
- package/dist/learning/qe-reasoning-bank.js +48 -1093
- package/dist/mcp/bundle.js +335 -335
- package/dist/mcp/security/validators/command-validator.d.ts +1 -40
- package/dist/mcp/security/validators/command-validator.js +2 -122
- package/dist/mcp/security/validators/crypto-validator.d.ts +1 -39
- package/dist/mcp/security/validators/crypto-validator.js +2 -71
- package/dist/mcp/security/validators/input-sanitizer.d.ts +1 -55
- package/dist/mcp/security/validators/input-sanitizer.js +2 -156
- package/dist/mcp/security/validators/interfaces.d.ts +1 -163
- package/dist/mcp/security/validators/interfaces.js +2 -5
- package/dist/mcp/security/validators/path-traversal-validator.d.ts +1 -49
- package/dist/mcp/security/validators/path-traversal-validator.js +2 -241
- package/dist/mcp/security/validators/regex-safety-validator.d.ts +1 -49
- package/dist/mcp/security/validators/regex-safety-validator.js +2 -182
- package/dist/mcp/security/validators/validation-orchestrator.d.ts +1 -65
- package/dist/mcp/security/validators/validation-orchestrator.js +2 -145
- package/dist/shared/io/file-reader.js +1 -1
- package/dist/shared/security/command-validator.d.ts +44 -0
- package/dist/shared/security/command-validator.js +126 -0
- package/dist/shared/security/crypto-validator.d.ts +43 -0
- package/dist/shared/security/crypto-validator.js +75 -0
- package/dist/shared/security/index.d.ts +7 -0
- package/dist/shared/security/index.js +15 -0
- package/dist/shared/security/input-sanitizer.d.ts +59 -0
- package/dist/shared/security/input-sanitizer.js +160 -0
- package/dist/shared/security/path-traversal-validator.d.ts +53 -0
- package/dist/shared/security/path-traversal-validator.js +245 -0
- package/dist/shared/security/regex-safety-validator.d.ts +53 -0
- package/dist/shared/security/regex-safety-validator.js +186 -0
- package/dist/shared/security/validation-orchestrator.d.ts +69 -0
- package/dist/shared/security/validation-orchestrator.js +149 -0
- package/dist/shared/security/validators-interfaces.d.ts +167 -0
- package/dist/shared/security/validators-interfaces.js +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Hooks Dream Scheduler & Learning Persistence
|
|
3
|
+
*
|
|
4
|
+
* Dream cycle scheduling, experience recording, and experience-to-pattern
|
|
5
|
+
* consolidation. Extracted from hooks-shared.ts to keep files under 500 lines.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'crypto';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Dream Scheduler State (persisted in kv_store between hook invocations)
|
|
11
|
+
// ============================================================================
|
|
12
|
+
export const DREAM_STATE_KEY = 'dream-scheduler:hook-state';
|
|
13
|
+
export const DREAM_INTERVAL_MS = 3600000; // 1 hour between auto-dreams
|
|
14
|
+
export const DREAM_EXPERIENCE_THRESHOLD = 20; // experiences before triggering
|
|
15
|
+
export const DREAM_MIN_GAP_MS = 300000; // 5 minutes minimum between dreams
|
|
16
|
+
/**
|
|
17
|
+
* Check if a dream cycle should be triggered and run it if so.
|
|
18
|
+
* Called from post-task hook after recording each experience.
|
|
19
|
+
*
|
|
20
|
+
* Trigger conditions (any of):
|
|
21
|
+
* 1. Time-based: >1hr since last dream
|
|
22
|
+
* 2. Experience-based: >20 experiences since last dream
|
|
23
|
+
*
|
|
24
|
+
* Guard: minimum 5 minutes between dreams
|
|
25
|
+
*/
|
|
26
|
+
export async function checkAndTriggerDream(memoryBackend) {
|
|
27
|
+
try {
|
|
28
|
+
// Load persisted dream state
|
|
29
|
+
const dreamState = await memoryBackend.get(DREAM_STATE_KEY);
|
|
30
|
+
if (!dreamState) {
|
|
31
|
+
return { triggered: false, reason: 'no-state' };
|
|
32
|
+
}
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
const lastDreamTime = dreamState.lastDreamTime ? new Date(dreamState.lastDreamTime).getTime() : 0;
|
|
35
|
+
const timeSinceLastDream = now - lastDreamTime;
|
|
36
|
+
// Guard: minimum gap
|
|
37
|
+
if (timeSinceLastDream < DREAM_MIN_GAP_MS) {
|
|
38
|
+
return { triggered: false, reason: 'too-soon' };
|
|
39
|
+
}
|
|
40
|
+
// Check triggers
|
|
41
|
+
const timeTriggered = timeSinceLastDream >= DREAM_INTERVAL_MS;
|
|
42
|
+
const experienceTriggered = dreamState.experienceCount >= DREAM_EXPERIENCE_THRESHOLD;
|
|
43
|
+
if (!timeTriggered && !experienceTriggered) {
|
|
44
|
+
return { triggered: false, reason: 'conditions-not-met' };
|
|
45
|
+
}
|
|
46
|
+
const reason = timeTriggered ? 'time-interval' : 'experience-threshold';
|
|
47
|
+
console.log(chalk.dim(`[hooks] Dream trigger: ${reason} (${dreamState.experienceCount} experiences, ${Math.round(timeSinceLastDream / 60000)}min since last dream)`));
|
|
48
|
+
// Run a quick dream cycle
|
|
49
|
+
const { createDreamEngine } = await import('../../../learning/dream/index.js');
|
|
50
|
+
const { createQEReasoningBank: createRB } = await import('../../../learning/qe-reasoning-bank.js');
|
|
51
|
+
const engine = createDreamEngine({
|
|
52
|
+
maxDurationMs: 10000, // 10s for hook-triggered dreams
|
|
53
|
+
minConceptsRequired: 3,
|
|
54
|
+
});
|
|
55
|
+
await engine.initialize();
|
|
56
|
+
// Load patterns from ReasoningBank
|
|
57
|
+
const rb = createRB(memoryBackend, undefined, {
|
|
58
|
+
enableLearning: true,
|
|
59
|
+
enableGuidance: false,
|
|
60
|
+
enableRouting: false,
|
|
61
|
+
embeddingDimension: 384,
|
|
62
|
+
useONNXEmbeddings: true,
|
|
63
|
+
});
|
|
64
|
+
await rb.initialize();
|
|
65
|
+
const patternsResult = await rb.searchPatterns('', { limit: 100, minConfidence: 0.3 });
|
|
66
|
+
if (patternsResult.success && patternsResult.value.length > 0) {
|
|
67
|
+
const importPatterns = patternsResult.value.map(r => ({
|
|
68
|
+
id: r.pattern.id,
|
|
69
|
+
name: r.pattern.name,
|
|
70
|
+
description: r.pattern.description || `${r.pattern.patternType} pattern`,
|
|
71
|
+
domain: r.pattern.qeDomain || 'learning-optimization',
|
|
72
|
+
patternType: r.pattern.patternType,
|
|
73
|
+
confidence: r.pattern.confidence,
|
|
74
|
+
successRate: r.pattern.successRate || 0.5,
|
|
75
|
+
}));
|
|
76
|
+
await engine.loadPatternsAsConcepts(importPatterns);
|
|
77
|
+
}
|
|
78
|
+
const result = await engine.dream(10000);
|
|
79
|
+
// Update state
|
|
80
|
+
dreamState.lastDreamTime = new Date().toISOString();
|
|
81
|
+
dreamState.experienceCount = 0;
|
|
82
|
+
dreamState.totalDreamsThisSession++;
|
|
83
|
+
await memoryBackend.set(DREAM_STATE_KEY, dreamState);
|
|
84
|
+
await engine.close();
|
|
85
|
+
return {
|
|
86
|
+
triggered: true,
|
|
87
|
+
reason,
|
|
88
|
+
insightsGenerated: result.insights.length,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error(chalk.dim(`[hooks] Dream trigger failed: ${error instanceof Error ? error.message : 'unknown'}`));
|
|
93
|
+
return { triggered: false, reason: 'error' };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Increment the experience counter in dream state.
|
|
98
|
+
* Called from post-task hook.
|
|
99
|
+
*/
|
|
100
|
+
export async function incrementDreamExperience(memoryBackend) {
|
|
101
|
+
try {
|
|
102
|
+
let dreamState = await memoryBackend.get(DREAM_STATE_KEY);
|
|
103
|
+
if (!dreamState) {
|
|
104
|
+
dreamState = {
|
|
105
|
+
lastDreamTime: null,
|
|
106
|
+
experienceCount: 0,
|
|
107
|
+
sessionStartTime: new Date().toISOString(),
|
|
108
|
+
totalDreamsThisSession: 0,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
dreamState.experienceCount++;
|
|
112
|
+
await memoryBackend.set(DREAM_STATE_KEY, dreamState);
|
|
113
|
+
return dreamState.experienceCount;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Persist a command/edit experience directly to the captured_experiences table.
|
|
121
|
+
* CLI hooks cannot use the MCP middleware wrapper, so they write directly.
|
|
122
|
+
*/
|
|
123
|
+
export async function persistCommandExperience(opts) {
|
|
124
|
+
try {
|
|
125
|
+
const { getUnifiedMemory } = await import('../../../kernel/unified-memory.js');
|
|
126
|
+
const um = getUnifiedMemory();
|
|
127
|
+
if (!um.isInitialized()) {
|
|
128
|
+
await um.initialize();
|
|
129
|
+
}
|
|
130
|
+
const db = um.getDatabase();
|
|
131
|
+
const id = `cli-${Date.now()}-${randomUUID().slice(0, 8)}`;
|
|
132
|
+
// Compute quality based on context rather than binary success/fail.
|
|
133
|
+
// Duration-aware: fast successful ops get higher quality.
|
|
134
|
+
// Source-aware: post-task and post-edit are higher signal than post-command.
|
|
135
|
+
const durationMs = opts.durationMs || 0;
|
|
136
|
+
let quality;
|
|
137
|
+
if (opts.success) {
|
|
138
|
+
// Successful: base 0.7, bonus for fast execution (< 5s), bonus for high-signal sources
|
|
139
|
+
const speedBonus = durationMs > 0 && durationMs < 5000 ? 0.1 : 0;
|
|
140
|
+
const sourceBonus = opts.source.includes('post-task') ? 0.1 : opts.source.includes('post-edit') ? 0.05 : 0;
|
|
141
|
+
quality = Math.min(0.95, 0.7 + speedBonus + sourceBonus);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Failed: base 0.3, but higher for post-task (still learned something)
|
|
145
|
+
const sourceBonus = opts.source.includes('post-task') ? 0.15 : opts.source.includes('post-edit') ? 0.1 : 0;
|
|
146
|
+
quality = Math.min(0.6, 0.3 + sourceBonus);
|
|
147
|
+
}
|
|
148
|
+
db.prepare(`
|
|
149
|
+
INSERT OR REPLACE INTO captured_experiences
|
|
150
|
+
(id, task, agent, domain, success, quality, duration_ms,
|
|
151
|
+
started_at, completed_at, source)
|
|
152
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'), ?)
|
|
153
|
+
`).run(id, opts.task.slice(0, 500), opts.agent, opts.domain, opts.success ? 1 : 0, quality, durationMs, opts.source);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
// Best-effort ā don't fail the hook
|
|
157
|
+
console.error(chalk.dim(`[hooks] persistCommandExperience: ${error instanceof Error ? error.message : 'unknown'}`));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Lightweight experience-to-pattern consolidation.
|
|
162
|
+
* Aggregates captured_experiences by domain+agent, and for clusters that meet
|
|
163
|
+
* quality thresholds, creates new qe_patterns entries.
|
|
164
|
+
* Called at session-end so patterns grow with each session.
|
|
165
|
+
*/
|
|
166
|
+
export async function consolidateExperiencesToPatterns() {
|
|
167
|
+
const { getUnifiedMemory } = await import('../../../kernel/unified-memory.js');
|
|
168
|
+
const um = getUnifiedMemory();
|
|
169
|
+
if (!um.isInitialized()) {
|
|
170
|
+
await um.initialize();
|
|
171
|
+
}
|
|
172
|
+
const db = um.getDatabase();
|
|
173
|
+
// Ensure consolidation columns exist (may be missing on older DBs)
|
|
174
|
+
const existingCols = new Set(db.prepare('PRAGMA table_info(captured_experiences)').all().map(c => c.name));
|
|
175
|
+
const migrations = [
|
|
176
|
+
['consolidated_into', 'TEXT DEFAULT NULL'],
|
|
177
|
+
['consolidation_count', 'INTEGER DEFAULT 1'],
|
|
178
|
+
['quality_updated_at', 'TEXT DEFAULT NULL'],
|
|
179
|
+
['reuse_success_count', 'INTEGER DEFAULT 0'],
|
|
180
|
+
['reuse_failure_count', 'INTEGER DEFAULT 0'],
|
|
181
|
+
];
|
|
182
|
+
for (const [col, def] of migrations) {
|
|
183
|
+
if (!existingCols.has(col)) {
|
|
184
|
+
db.exec(`ALTER TABLE captured_experiences ADD COLUMN ${col} ${def}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Aggregate unprocessed experiences by domain+agent with quality thresholds.
|
|
188
|
+
// Exclude 'cli-hook' agent ā these are low-quality hook telemetry events
|
|
189
|
+
// (quality ~0.40, success_rate ~0.24) that flood the pipeline and block
|
|
190
|
+
// real pattern creation. See issue #348.
|
|
191
|
+
const aggregates = db.prepare(`
|
|
192
|
+
SELECT
|
|
193
|
+
domain,
|
|
194
|
+
agent,
|
|
195
|
+
COUNT(*) as cnt,
|
|
196
|
+
AVG(quality) as avg_quality,
|
|
197
|
+
SUM(success) as successes,
|
|
198
|
+
CAST(SUM(success) AS REAL) / COUNT(*) as success_rate,
|
|
199
|
+
AVG(duration_ms) as avg_duration,
|
|
200
|
+
GROUP_CONCAT(DISTINCT source) as sources
|
|
201
|
+
FROM captured_experiences
|
|
202
|
+
WHERE application_count = 0
|
|
203
|
+
AND agent != 'cli-hook'
|
|
204
|
+
GROUP BY domain, agent
|
|
205
|
+
HAVING cnt >= 3 AND avg_quality >= 0.5 AND success_rate >= 0.6
|
|
206
|
+
ORDER BY avg_quality DESC
|
|
207
|
+
LIMIT 50
|
|
208
|
+
`).all();
|
|
209
|
+
if (aggregates.length === 0)
|
|
210
|
+
return 0;
|
|
211
|
+
const { v4: uuidv4 } = await import('uuid');
|
|
212
|
+
let created = 0;
|
|
213
|
+
for (const agg of aggregates) {
|
|
214
|
+
try {
|
|
215
|
+
// Use date-bucketed names so new patterns emerge as usage evolves,
|
|
216
|
+
// instead of silently reinforcing one static pattern forever.
|
|
217
|
+
const dateBucket = new Date().toISOString().slice(0, 7); // YYYY-MM
|
|
218
|
+
const patternName = `${agg.agent}-${agg.domain}-${dateBucket}`;
|
|
219
|
+
// Check for existing pattern with same name this month
|
|
220
|
+
const existing = db.prepare(`
|
|
221
|
+
SELECT id FROM qe_patterns
|
|
222
|
+
WHERE qe_domain = ? AND name = ?
|
|
223
|
+
LIMIT 1
|
|
224
|
+
`).get(agg.domain, patternName);
|
|
225
|
+
if (existing) {
|
|
226
|
+
// Reinforce existing monthly pattern
|
|
227
|
+
db.prepare(`
|
|
228
|
+
UPDATE qe_patterns
|
|
229
|
+
SET usage_count = usage_count + ?,
|
|
230
|
+
successful_uses = successful_uses + ?,
|
|
231
|
+
confidence = MIN(0.99, confidence + 0.01),
|
|
232
|
+
quality_score = MIN(0.99, quality_score + 0.005),
|
|
233
|
+
updated_at = datetime('now')
|
|
234
|
+
WHERE id = ?
|
|
235
|
+
`).run(agg.cnt, agg.successes, existing.id);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const patternId = uuidv4();
|
|
239
|
+
const confidence = Math.min(0.95, agg.avg_quality * 0.8 + agg.success_rate * 0.2);
|
|
240
|
+
const qualityScore = confidence * 0.3 + (Math.min(agg.cnt, 100) / 100) * 0.2 + agg.success_rate * 0.5;
|
|
241
|
+
db.prepare(`
|
|
242
|
+
INSERT INTO qe_patterns (
|
|
243
|
+
id, pattern_type, qe_domain, domain, name, description,
|
|
244
|
+
confidence, usage_count, success_rate, quality_score, tier,
|
|
245
|
+
template_json, context_json, created_at, successful_uses
|
|
246
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), ?)
|
|
247
|
+
`).run(patternId, 'workflow', agg.domain, agg.domain, patternName, `Auto-consolidated from ${agg.cnt} experiences. Agent: ${agg.agent}, success rate: ${(agg.success_rate * 100).toFixed(0)}%`, confidence, agg.cnt, agg.success_rate, qualityScore, 'short-term', JSON.stringify({ type: 'workflow', content: `${agg.agent} pattern for ${agg.domain}`, variables: [] }), JSON.stringify({ tags: (agg.sources || '').split(','), sourceType: 'session-consolidation', extractedAt: new Date().toISOString() }), agg.successes);
|
|
248
|
+
created++;
|
|
249
|
+
}
|
|
250
|
+
// Mark experiences as processed
|
|
251
|
+
db.prepare(`
|
|
252
|
+
UPDATE captured_experiences
|
|
253
|
+
SET application_count = application_count + 1
|
|
254
|
+
WHERE domain = ? AND agent = ? AND application_count = 0
|
|
255
|
+
`).run(agg.domain, agg.agent);
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
// Skip on error (e.g. constraint violations)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return created;
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=hooks-dream-learning.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Agentic QE v3 - Hooks Shared State & Utilities
|
|
4
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
5
|
+
*
|
|
6
|
+
* Shared state, initialization, dream scheduler, learning utils, and output helpers
|
|
7
|
+
* used by all hooks handler modules.
|
|
8
|
+
*/
|
|
9
|
+
import { QEReasoningBank } from '../../../learning/qe-reasoning-bank.js';
|
|
10
|
+
import { QEHookRegistry } from '../../../learning/qe-hooks.js';
|
|
11
|
+
import type { MemoryBackend } from '../../../kernel/interfaces.js';
|
|
12
|
+
import { type ICoherenceService } from '../../../integrations/coherence/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Singleton state for hooks system
|
|
15
|
+
*/
|
|
16
|
+
export interface HooksSystemState {
|
|
17
|
+
reasoningBank: QEReasoningBank | null;
|
|
18
|
+
hookRegistry: QEHookRegistry | null;
|
|
19
|
+
coherenceService: ICoherenceService | null;
|
|
20
|
+
sessionId: string | null;
|
|
21
|
+
initialized: boolean;
|
|
22
|
+
initializationPromise: Promise<void> | null;
|
|
23
|
+
}
|
|
24
|
+
export declare const state: HooksSystemState;
|
|
25
|
+
/**
|
|
26
|
+
* Get or create the hooks system with proper initialization
|
|
27
|
+
*/
|
|
28
|
+
export declare function getHooksSystem(): Promise<{
|
|
29
|
+
reasoningBank: QEReasoningBank;
|
|
30
|
+
hookRegistry: QEHookRegistry;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Initialize the hooks system
|
|
34
|
+
*/
|
|
35
|
+
export declare function initializeHooksSystem(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Create hybrid backend with timeout protection
|
|
38
|
+
*
|
|
39
|
+
* ADR-046: Uses unified memory.db path for consistency with all other components.
|
|
40
|
+
* HybridMemoryBackend delegates to UnifiedMemoryManager singleton.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createHybridBackendWithTimeout(dataDir: string): Promise<MemoryBackend>;
|
|
43
|
+
/**
|
|
44
|
+
* Create in-memory fallback backend
|
|
45
|
+
*/
|
|
46
|
+
export declare function createInMemoryBackend(): MemoryBackend;
|
|
47
|
+
export declare function printJson(data: unknown): void;
|
|
48
|
+
export declare function printSuccess(message: string): void;
|
|
49
|
+
export declare function printError(message: string): void;
|
|
50
|
+
export declare function printGuidance(guidance: string[]): void;
|
|
51
|
+
export { DREAM_STATE_KEY, DREAM_INTERVAL_MS, DREAM_EXPERIENCE_THRESHOLD, DREAM_MIN_GAP_MS, type DreamHookState, checkAndTriggerDream, incrementDreamExperience, persistCommandExperience, consolidateExperiencesToPatterns, } from './hooks-dream-learning.js';
|
|
52
|
+
//# sourceMappingURL=hooks-shared.d.ts.map
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Agentic QE v3 - Hooks Shared State & Utilities
|
|
4
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
5
|
+
*
|
|
6
|
+
* Shared state, initialization, dream scheduler, learning utils, and output helpers
|
|
7
|
+
* used by all hooks handler modules.
|
|
8
|
+
*/
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { createQEReasoningBank, } from '../../../learning/qe-reasoning-bank.js';
|
|
12
|
+
import { QEHookRegistry, setupQEHooks, } from '../../../learning/qe-hooks.js';
|
|
13
|
+
import { HybridMemoryBackend } from '../../../kernel/hybrid-backend.js';
|
|
14
|
+
import { findProjectRoot } from '../../../kernel/unified-memory.js';
|
|
15
|
+
import { wasmLoader, createCoherenceService, } from '../../../integrations/coherence/index.js';
|
|
16
|
+
export const state = {
|
|
17
|
+
reasoningBank: null,
|
|
18
|
+
hookRegistry: null,
|
|
19
|
+
coherenceService: null,
|
|
20
|
+
sessionId: null,
|
|
21
|
+
initialized: false,
|
|
22
|
+
initializationPromise: null,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Get or create the hooks system with proper initialization
|
|
26
|
+
*/
|
|
27
|
+
export async function getHooksSystem() {
|
|
28
|
+
// If already initializing, wait for it
|
|
29
|
+
if (state.initializationPromise) {
|
|
30
|
+
await state.initializationPromise;
|
|
31
|
+
}
|
|
32
|
+
// If already initialized, return
|
|
33
|
+
if (state.initialized && state.reasoningBank && state.hookRegistry) {
|
|
34
|
+
return {
|
|
35
|
+
reasoningBank: state.reasoningBank,
|
|
36
|
+
hookRegistry: state.hookRegistry,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Initialize with timeout protection
|
|
40
|
+
state.initializationPromise = initializeHooksSystem();
|
|
41
|
+
await state.initializationPromise;
|
|
42
|
+
state.initializationPromise = null;
|
|
43
|
+
if (!state.reasoningBank || !state.hookRegistry) {
|
|
44
|
+
throw new Error('Failed to initialize hooks system');
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
reasoningBank: state.reasoningBank,
|
|
48
|
+
hookRegistry: state.hookRegistry,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Initialize the hooks system
|
|
53
|
+
*/
|
|
54
|
+
export async function initializeHooksSystem() {
|
|
55
|
+
if (state.initialized)
|
|
56
|
+
return;
|
|
57
|
+
try {
|
|
58
|
+
// Create memory backend ā always resolve to project root DB
|
|
59
|
+
const projectRoot = findProjectRoot();
|
|
60
|
+
const dataDir = path.join(projectRoot, '.agentic-qe');
|
|
61
|
+
// Use hybrid backend with timeout protection
|
|
62
|
+
const memoryBackend = await createHybridBackendWithTimeout(dataDir);
|
|
63
|
+
// Initialize CoherenceService (optional - falls back to TypeScript implementation)
|
|
64
|
+
try {
|
|
65
|
+
state.coherenceService = await createCoherenceService(wasmLoader);
|
|
66
|
+
console.log(chalk.dim('[hooks] CoherenceService initialized with WASM engines'));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
// WASM not available - will use fallback
|
|
70
|
+
console.log(chalk.dim(`[hooks] CoherenceService WASM unavailable, using fallback: ${error instanceof Error ? error.message : 'unknown'}`));
|
|
71
|
+
}
|
|
72
|
+
// Create reasoning bank with coherence service
|
|
73
|
+
state.reasoningBank = createQEReasoningBank(memoryBackend, undefined, {
|
|
74
|
+
enableLearning: true,
|
|
75
|
+
enableGuidance: true,
|
|
76
|
+
enableRouting: true,
|
|
77
|
+
embeddingDimension: 384,
|
|
78
|
+
useONNXEmbeddings: true, // Use real transformer embeddings (384-dim)
|
|
79
|
+
}, state.coherenceService ?? undefined);
|
|
80
|
+
// Initialize with timeout
|
|
81
|
+
const initTimeout = 10000; // 10 seconds
|
|
82
|
+
const initPromise = state.reasoningBank.initialize();
|
|
83
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('ReasoningBank init timeout')), initTimeout));
|
|
84
|
+
await Promise.race([initPromise, timeoutPromise]);
|
|
85
|
+
// Wire RVF dual-writer for vector replication (optional, best-effort)
|
|
86
|
+
try {
|
|
87
|
+
const { getSharedRvfDualWriter } = await import('../../../integrations/ruvector/shared-rvf-dual-writer.js');
|
|
88
|
+
const dualWriter = await getSharedRvfDualWriter();
|
|
89
|
+
if (dualWriter)
|
|
90
|
+
state.reasoningBank.setRvfDualWriter(dualWriter);
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
if (process.env.DEBUG)
|
|
94
|
+
console.debug('[hooks] RVF wiring skipped:', e instanceof Error ? e.message : e);
|
|
95
|
+
}
|
|
96
|
+
// Setup hook registry
|
|
97
|
+
state.hookRegistry = setupQEHooks(state.reasoningBank);
|
|
98
|
+
state.initialized = true;
|
|
99
|
+
console.log(chalk.dim('[hooks] System initialized'));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
// Create minimal fallback state
|
|
103
|
+
console.warn(chalk.yellow(`[hooks] Using fallback mode: ${error instanceof Error ? error.message : 'unknown error'}`));
|
|
104
|
+
// Create in-memory fallback backend
|
|
105
|
+
// NOTE: RVF dual-writer is intentionally NOT wired here ā the fallback
|
|
106
|
+
// uses an in-memory backend with no disk access, so RVF replication
|
|
107
|
+
// (which requires the unified memory DB) is not meaningful.
|
|
108
|
+
const fallbackBackend = createInMemoryBackend();
|
|
109
|
+
state.reasoningBank = createQEReasoningBank(fallbackBackend, undefined, {
|
|
110
|
+
enableLearning: true,
|
|
111
|
+
enableGuidance: true,
|
|
112
|
+
enableRouting: true,
|
|
113
|
+
});
|
|
114
|
+
// Skip full initialization for fallback
|
|
115
|
+
state.hookRegistry = new QEHookRegistry();
|
|
116
|
+
state.hookRegistry.initialize(state.reasoningBank);
|
|
117
|
+
state.initialized = true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Create hybrid backend with timeout protection
|
|
122
|
+
*
|
|
123
|
+
* ADR-046: Uses unified memory.db path for consistency with all other components.
|
|
124
|
+
* HybridMemoryBackend delegates to UnifiedMemoryManager singleton.
|
|
125
|
+
*/
|
|
126
|
+
export async function createHybridBackendWithTimeout(dataDir) {
|
|
127
|
+
const timeoutMs = 5000;
|
|
128
|
+
// ADR-046: Use unified memory.db path - same as all other components
|
|
129
|
+
// HybridMemoryBackend is a facade over UnifiedMemoryManager
|
|
130
|
+
const backend = new HybridMemoryBackend({
|
|
131
|
+
sqlite: {
|
|
132
|
+
path: path.join(dataDir, 'memory.db'), // ADR-046: Unified storage
|
|
133
|
+
walMode: true,
|
|
134
|
+
poolSize: 3,
|
|
135
|
+
busyTimeout: 5000,
|
|
136
|
+
},
|
|
137
|
+
// agentdb.path is ignored - vectors stored in unified memory.db
|
|
138
|
+
enableFallback: true,
|
|
139
|
+
defaultNamespace: 'qe-patterns',
|
|
140
|
+
});
|
|
141
|
+
const initPromise = backend.initialize();
|
|
142
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Backend init timeout')), timeoutMs));
|
|
143
|
+
await Promise.race([initPromise, timeoutPromise]);
|
|
144
|
+
return backend;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create in-memory fallback backend
|
|
148
|
+
*/
|
|
149
|
+
export function createInMemoryBackend() {
|
|
150
|
+
const store = new Map();
|
|
151
|
+
return {
|
|
152
|
+
initialize: async () => { },
|
|
153
|
+
dispose: async () => {
|
|
154
|
+
store.clear();
|
|
155
|
+
},
|
|
156
|
+
get: async (key) => {
|
|
157
|
+
const entry = store.get(key);
|
|
158
|
+
return entry ? entry.value : undefined;
|
|
159
|
+
},
|
|
160
|
+
set: async (key, value, _options) => {
|
|
161
|
+
store.set(key, { value });
|
|
162
|
+
},
|
|
163
|
+
delete: async (key) => {
|
|
164
|
+
return store.delete(key);
|
|
165
|
+
},
|
|
166
|
+
has: async (key) => store.has(key),
|
|
167
|
+
search: async (pattern, _limit) => {
|
|
168
|
+
const regex = new RegExp(pattern.replace(/\*/g, '.*'));
|
|
169
|
+
return Array.from(store.keys()).filter((k) => regex.test(k));
|
|
170
|
+
},
|
|
171
|
+
vectorSearch: async (_embedding, _k) => {
|
|
172
|
+
return [];
|
|
173
|
+
},
|
|
174
|
+
storeVector: async (_key, _embedding, _metadata) => {
|
|
175
|
+
// No-op for in-memory fallback
|
|
176
|
+
},
|
|
177
|
+
count: async (namespace) => {
|
|
178
|
+
let count = 0;
|
|
179
|
+
const prefix = `${namespace}:`;
|
|
180
|
+
for (const key of store.keys()) {
|
|
181
|
+
if (key.startsWith(prefix)) {
|
|
182
|
+
count++;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return count;
|
|
186
|
+
},
|
|
187
|
+
hasCodeIntelligenceIndex: async () => {
|
|
188
|
+
const prefix = 'code-intelligence:kg:';
|
|
189
|
+
for (const key of store.keys()) {
|
|
190
|
+
if (key.startsWith(prefix)) {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// Helper Functions
|
|
200
|
+
// ============================================================================
|
|
201
|
+
export function printJson(data) {
|
|
202
|
+
console.log(JSON.stringify(data, null, 2));
|
|
203
|
+
}
|
|
204
|
+
export function printSuccess(message) {
|
|
205
|
+
console.log(chalk.green('ā'), message);
|
|
206
|
+
}
|
|
207
|
+
export function printError(message) {
|
|
208
|
+
console.error(chalk.red('ā'), message);
|
|
209
|
+
}
|
|
210
|
+
export function printGuidance(guidance) {
|
|
211
|
+
if (guidance.length === 0) {
|
|
212
|
+
console.log(chalk.dim(' No specific guidance'));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
guidance.forEach((g, i) => {
|
|
216
|
+
console.log(chalk.cyan(` ${i + 1}.`), g);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
// ============================================================================
|
|
220
|
+
// Dream Scheduler & Learning ā re-exported from hooks-dream-learning.ts
|
|
221
|
+
// ============================================================================
|
|
222
|
+
export { DREAM_STATE_KEY, DREAM_INTERVAL_MS, DREAM_EXPERIENCE_THRESHOLD, DREAM_MIN_GAP_MS, checkAndTriggerDream, incrementDreamExperience, persistCommandExperience, consolidateExperiencesToPatterns, } from './hooks-dream-learning.js';
|
|
223
|
+
//# sourceMappingURL=hooks-shared.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Routing Hooks (route)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles task routing to optimal QE agent.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
/**
|
|
9
|
+
* Register route subcommand on the hooks command.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerRoutingHooks(hooks: Command): void;
|
|
12
|
+
//# sourceMappingURL=routing-hooks.d.ts.map
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Routing Hooks (route)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles task routing to optimal QE agent.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'crypto';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { findProjectRoot } from '../../../kernel/unified-memory.js';
|
|
11
|
+
import { getHooksSystem, createHybridBackendWithTimeout, incrementDreamExperience, printJson, printError, printGuidance, } from './hooks-shared.js';
|
|
12
|
+
/**
|
|
13
|
+
* Register route subcommand on the hooks command.
|
|
14
|
+
*/
|
|
15
|
+
export function registerRoutingHooks(hooks) {
|
|
16
|
+
// -------------------------------------------------------------------------
|
|
17
|
+
// route: Route task to optimal agent
|
|
18
|
+
// -------------------------------------------------------------------------
|
|
19
|
+
hooks
|
|
20
|
+
.command('route')
|
|
21
|
+
.description('Route a task to the optimal QE agent')
|
|
22
|
+
.requiredOption('-t, --task <description>', 'Task description')
|
|
23
|
+
.option('-d, --domain <domain>', 'Target QE domain hint')
|
|
24
|
+
.option('-c, --capabilities <caps...>', 'Required capabilities')
|
|
25
|
+
.option('--json', 'Output as JSON')
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
try {
|
|
28
|
+
const { reasoningBank } = await getHooksSystem();
|
|
29
|
+
const request = {
|
|
30
|
+
task: options.task,
|
|
31
|
+
domain: options.domain,
|
|
32
|
+
capabilities: options.capabilities,
|
|
33
|
+
};
|
|
34
|
+
const result = await reasoningBank.routeTask(request);
|
|
35
|
+
if (!result.success) {
|
|
36
|
+
throw new Error(result.error.message);
|
|
37
|
+
}
|
|
38
|
+
const routing = result.value;
|
|
39
|
+
if (options.json) {
|
|
40
|
+
printJson({
|
|
41
|
+
recommendedAgent: routing.recommendedAgent,
|
|
42
|
+
confidence: routing.confidence,
|
|
43
|
+
alternatives: routing.alternatives,
|
|
44
|
+
domains: routing.domains,
|
|
45
|
+
patternCount: routing.patterns.length,
|
|
46
|
+
guidance: routing.guidance,
|
|
47
|
+
reasoning: routing.reasoning,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log(chalk.bold('\nšÆ Task Routing Result'));
|
|
52
|
+
console.log(chalk.dim(` Task: "${options.task}"`));
|
|
53
|
+
console.log(chalk.bold('\nš¤ Recommended Agent:'), chalk.cyan(routing.recommendedAgent));
|
|
54
|
+
console.log(chalk.dim(` Confidence: ${(routing.confidence * 100).toFixed(1)}%`));
|
|
55
|
+
if (routing.alternatives.length > 0) {
|
|
56
|
+
console.log(chalk.bold('\nš Alternatives:'));
|
|
57
|
+
routing.alternatives.forEach((alt) => {
|
|
58
|
+
console.log(chalk.dim(` - ${alt.agent}: ${(alt.score * 100).toFixed(1)}%`));
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
console.log(chalk.bold('\nš Detected Domains:'), routing.domains.join(', '));
|
|
62
|
+
console.log(chalk.bold('\nš” Guidance:'));
|
|
63
|
+
printGuidance(routing.guidance);
|
|
64
|
+
console.log(chalk.bold('\nš Reasoning:'), chalk.dim(routing.reasoning));
|
|
65
|
+
}
|
|
66
|
+
// Persist routing decision for learning
|
|
67
|
+
try {
|
|
68
|
+
const { getUnifiedMemory } = await import('../../../kernel/unified-memory.js');
|
|
69
|
+
const um = getUnifiedMemory();
|
|
70
|
+
if (!um.isInitialized()) {
|
|
71
|
+
await um.initialize();
|
|
72
|
+
}
|
|
73
|
+
const db = um.getDatabase();
|
|
74
|
+
const outcomeId = `route-${Date.now()}-${randomUUID().slice(0, 8)}`;
|
|
75
|
+
db.prepare(`
|
|
76
|
+
INSERT OR REPLACE INTO routing_outcomes (
|
|
77
|
+
id, task_json, decision_json, used_agent,
|
|
78
|
+
followed_recommendation, success, quality_score,
|
|
79
|
+
duration_ms, error
|
|
80
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
81
|
+
`).run(outcomeId, JSON.stringify({ description: options.task, domain: options.domain }), JSON.stringify({
|
|
82
|
+
recommended: routing.recommendedAgent,
|
|
83
|
+
confidence: routing.confidence,
|
|
84
|
+
alternatives: routing.alternatives,
|
|
85
|
+
}), routing.recommendedAgent, 1, // followed_recommendation = true (recommendation stage)
|
|
86
|
+
1, // success = true (routing itself succeeded)
|
|
87
|
+
routing.confidence, 0, // duration not tracked at routing stage
|
|
88
|
+
null);
|
|
89
|
+
// Increment dream experience counter
|
|
90
|
+
const projectRoot = findProjectRoot();
|
|
91
|
+
const dataDir = path.join(projectRoot, '.agentic-qe');
|
|
92
|
+
const memoryBackend = await createHybridBackendWithTimeout(dataDir);
|
|
93
|
+
await incrementDreamExperience(memoryBackend);
|
|
94
|
+
}
|
|
95
|
+
catch (persistError) {
|
|
96
|
+
// Best-effort ā don't fail the hook
|
|
97
|
+
console.error(chalk.dim(`[hooks] route persist: ${persistError instanceof Error ? persistError.message : 'unknown'}`));
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
printError(`route failed: ${error instanceof Error ? error.message : 'unknown'}`);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=routing-hooks.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Session Hooks (session-start, session-end)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles session lifecycle hooks.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
/**
|
|
9
|
+
* Register session-start and session-end subcommands on the hooks command.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerSessionHooks(hooks: Command): void;
|
|
12
|
+
//# sourceMappingURL=session-hooks.d.ts.map
|