agentic-qe 3.8.4 → 3.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/.claude/skills/skills-manifest.json +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/cli/bundle.js +694 -694
  4. package/dist/cli/commands/hooks-handlers/command-hooks.d.ts +12 -0
  5. package/dist/cli/commands/hooks-handlers/command-hooks.js +253 -0
  6. package/dist/cli/commands/hooks-handlers/editing-hooks.d.ts +12 -0
  7. package/dist/cli/commands/hooks-handlers/editing-hooks.js +161 -0
  8. package/dist/cli/commands/hooks-handlers/hooks-dream-learning.d.ts +57 -0
  9. package/dist/cli/commands/hooks-handlers/hooks-dream-learning.js +263 -0
  10. package/dist/cli/commands/hooks-handlers/hooks-shared.d.ts +52 -0
  11. package/dist/cli/commands/hooks-handlers/hooks-shared.js +223 -0
  12. package/dist/cli/commands/hooks-handlers/routing-hooks.d.ts +12 -0
  13. package/dist/cli/commands/hooks-handlers/routing-hooks.js +107 -0
  14. package/dist/cli/commands/hooks-handlers/session-hooks.d.ts +12 -0
  15. package/dist/cli/commands/hooks-handlers/session-hooks.js +171 -0
  16. package/dist/cli/commands/hooks-handlers/stats-hooks.d.ts +12 -0
  17. package/dist/cli/commands/hooks-handlers/stats-hooks.js +248 -0
  18. package/dist/cli/commands/hooks-handlers/task-hooks.d.ts +12 -0
  19. package/dist/cli/commands/hooks-handlers/task-hooks.js +152 -0
  20. package/dist/cli/commands/hooks.d.ts +3 -23
  21. package/dist/cli/commands/hooks.js +16 -1459
  22. package/dist/domains/base-domain-coordinator.d.ts +0 -15
  23. package/dist/domains/base-domain-coordinator.js +7 -5
  24. package/dist/domains/chaos-resilience/coordinator.d.ts +0 -4
  25. package/dist/domains/chaos-resilience/coordinator.js +24 -22
  26. package/dist/domains/chaos-resilience/services/chaos-engineer.d.ts +0 -4
  27. package/dist/domains/chaos-resilience/services/chaos-engineer.js +47 -45
  28. package/dist/domains/chaos-resilience/services/performance-profiler.d.ts +0 -4
  29. package/dist/domains/chaos-resilience/services/performance-profiler.js +10 -8
  30. package/dist/domains/code-intelligence/coordinator-consensus.d.ts +0 -3
  31. package/dist/domains/code-intelligence/coordinator-consensus.js +8 -6
  32. package/dist/domains/code-intelligence/coordinator-gnn.d.ts +0 -3
  33. package/dist/domains/code-intelligence/coordinator-gnn.js +8 -6
  34. package/dist/domains/code-intelligence/coordinator-hypergraph.d.ts +0 -3
  35. package/dist/domains/code-intelligence/coordinator-hypergraph.js +13 -11
  36. package/dist/domains/code-intelligence/coordinator.d.ts +0 -3
  37. package/dist/domains/code-intelligence/coordinator.js +21 -19
  38. package/dist/domains/code-intelligence/services/c4-model/index.d.ts +0 -3
  39. package/dist/domains/code-intelligence/services/c4-model/index.js +5 -3
  40. package/dist/domains/code-intelligence/services/knowledge-graph.d.ts +0 -6
  41. package/dist/domains/code-intelligence/services/knowledge-graph.js +4 -2
  42. package/dist/domains/code-intelligence/services/product-factors-bridge.d.ts +0 -5
  43. package/dist/domains/code-intelligence/services/product-factors-bridge.js +9 -7
  44. package/dist/domains/contract-testing/coordinator.d.ts +0 -6
  45. package/dist/domains/contract-testing/coordinator.js +25 -23
  46. package/dist/domains/contract-testing/services/contract-validator.d.ts +0 -4
  47. package/dist/domains/contract-testing/services/contract-validator.js +4 -2
  48. package/dist/domains/contract-testing/services/schema-validator.js +1 -1
  49. package/dist/domains/coverage-analysis/coordinator.js +13 -11
  50. package/dist/domains/coverage-analysis/services/coverage-analyzer.js +4 -2
  51. package/dist/domains/coverage-analysis/services/gap-detector.js +3 -1
  52. package/dist/domains/coverage-analysis/services/hnsw-index.d.ts +0 -15
  53. package/dist/domains/coverage-analysis/services/hnsw-index.js +3 -1
  54. package/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +0 -26
  55. package/dist/domains/coverage-analysis/services/sublinear-analyzer.js +3 -1
  56. package/dist/domains/defect-intelligence/coordinator.d.ts +1 -10
  57. package/dist/domains/defect-intelligence/coordinator.js +5 -3
  58. package/dist/domains/defect-intelligence/services/causal-root-cause-analyzer.d.ts +0 -6
  59. package/dist/domains/defect-intelligence/services/causal-root-cause-analyzer.js +3 -1
  60. package/dist/domains/defect-intelligence/services/defect-predictor.d.ts +0 -6
  61. package/dist/domains/defect-intelligence/services/defect-predictor.js +5 -3
  62. package/dist/domains/defect-intelligence/services/pattern-learner.d.ts +0 -4
  63. package/dist/domains/defect-intelligence/services/pattern-learner.js +3 -1
  64. package/dist/domains/defect-intelligence/services/root-cause-analyzer.d.ts +0 -6
  65. package/dist/domains/defect-intelligence/services/root-cause-analyzer.js +3 -1
  66. package/dist/domains/enterprise-integration/coordinator.js +6 -4
  67. package/dist/domains/learning-optimization/coordinator-consensus.d.ts +0 -3
  68. package/dist/domains/learning-optimization/coordinator-consensus.js +8 -6
  69. package/dist/domains/learning-optimization/coordinator.d.ts +0 -3
  70. package/dist/domains/learning-optimization/coordinator.js +15 -13
  71. package/dist/domains/learning-optimization/services/learning-coordinator.d.ts +0 -4
  72. package/dist/domains/learning-optimization/services/learning-coordinator.js +4 -2
  73. package/dist/domains/quality-assessment/coordinator-claim-verifier.d.ts +0 -3
  74. package/dist/domains/quality-assessment/coordinator-claim-verifier.js +6 -4
  75. package/dist/domains/quality-assessment/coordinator-gate-evaluation.d.ts +0 -4
  76. package/dist/domains/quality-assessment/coordinator-gate-evaluation.js +9 -7
  77. package/dist/domains/quality-assessment/coordinator-rl-integration.d.ts +0 -3
  78. package/dist/domains/quality-assessment/coordinator-rl-integration.js +10 -8
  79. package/dist/domains/quality-assessment/coordinator.d.ts +0 -15
  80. package/dist/domains/quality-assessment/coordinator.js +14 -12
  81. package/dist/domains/quality-assessment/services/deployment-advisor.d.ts +0 -10
  82. package/dist/domains/quality-assessment/services/deployment-advisor.js +4 -2
  83. package/dist/domains/quality-assessment/services/quality-analyzer.d.ts +0 -6
  84. package/dist/domains/quality-assessment/services/quality-analyzer.js +4 -2
  85. package/dist/domains/requirements-validation/coordinator.d.ts +0 -3
  86. package/dist/domains/requirements-validation/coordinator.js +15 -13
  87. package/dist/domains/requirements-validation/services/product-factors-assessment/code-intelligence/codebase-analyzer.d.ts +0 -5
  88. package/dist/domains/requirements-validation/services/product-factors-assessment/code-intelligence/codebase-analyzer.js +15 -13
  89. package/dist/domains/requirements-validation/services/product-factors-assessment/product-factors-service.d.ts +0 -6
  90. package/dist/domains/requirements-validation/services/product-factors-assessment/product-factors-service.js +9 -7
  91. package/dist/domains/requirements-validation/services/requirements-validator.d.ts +0 -6
  92. package/dist/domains/requirements-validation/services/requirements-validator.js +4 -2
  93. package/dist/domains/security-compliance/coordinator.js +24 -22
  94. package/dist/domains/security-compliance/services/scanners/dast-scanner.d.ts +0 -21
  95. package/dist/domains/security-compliance/services/scanners/dast-scanner.js +4 -2
  96. package/dist/domains/security-compliance/services/scanners/sast-scanner.d.ts +0 -4
  97. package/dist/domains/security-compliance/services/scanners/sast-scanner.js +3 -1
  98. package/dist/domains/security-compliance/services/security-auditor-dast.d.ts +0 -4
  99. package/dist/domains/security-compliance/services/security-auditor-dast.js +3 -1
  100. package/dist/domains/security-compliance/services/security-auditor-sast.d.ts +0 -3
  101. package/dist/domains/security-compliance/services/security-auditor-sast.js +3 -1
  102. package/dist/domains/security-compliance/services/security-auditor-secrets.d.ts +0 -3
  103. package/dist/domains/security-compliance/services/security-auditor-secrets.js +3 -1
  104. package/dist/domains/security-compliance/services/security-auditor.js +11 -9
  105. package/dist/domains/test-execution/coordinator.js +11 -9
  106. package/dist/domains/test-execution/services/auth-state-manager.d.ts +0 -3
  107. package/dist/domains/test-execution/services/auth-state-manager.js +4 -2
  108. package/dist/domains/test-execution/services/e2e/e2e-coordinator.d.ts +0 -14
  109. package/dist/domains/test-execution/services/e2e/e2e-coordinator.js +3 -1
  110. package/dist/domains/test-execution/services/flaky-detector.js +4 -2
  111. package/dist/domains/test-execution/services/retry-handler.js +3 -1
  112. package/dist/domains/test-execution/services/test-executor.js +3 -1
  113. package/dist/domains/test-generation/coordinator.d.ts +0 -17
  114. package/dist/domains/test-generation/coordinator.js +33 -31
  115. package/dist/domains/test-generation/pattern-injection/edge-case-injector.d.ts +0 -5
  116. package/dist/domains/test-generation/pattern-injection/edge-case-injector.js +3 -1
  117. package/dist/domains/test-generation/services/code-transform-integration.d.ts +0 -7
  118. package/dist/domains/test-generation/services/code-transform-integration.js +3 -1
  119. package/dist/domains/test-generation/services/coherence-gate-service.d.ts +0 -3
  120. package/dist/domains/test-generation/services/coherence-gate-service.js +3 -1
  121. package/dist/domains/test-generation/services/test-generator.d.ts +0 -8
  122. package/dist/domains/test-generation/services/test-generator.js +5 -3
  123. package/dist/domains/visual-accessibility/coordinator.d.ts +0 -3
  124. package/dist/domains/visual-accessibility/coordinator.js +14 -12
  125. package/dist/domains/visual-accessibility/services/accessibility-tester-browser.d.ts +0 -3
  126. package/dist/domains/visual-accessibility/services/accessibility-tester-browser.js +52 -50
  127. package/dist/domains/visual-accessibility/services/accessibility-tester.d.ts +0 -4
  128. package/dist/domains/visual-accessibility/services/accessibility-tester.js +8 -6
  129. package/dist/domains/visual-accessibility/services/axe-core-integration.d.ts +0 -3
  130. package/dist/domains/visual-accessibility/services/axe-core-integration.js +20 -18
  131. package/dist/domains/visual-accessibility/services/browser-security-scanner.d.ts +0 -4
  132. package/dist/domains/visual-accessibility/services/browser-security-scanner.js +6 -4
  133. package/dist/domains/visual-accessibility/services/browser-swarm-coordinator.d.ts +0 -30
  134. package/dist/domains/visual-accessibility/services/browser-swarm-coordinator.js +5 -3
  135. package/dist/domains/visual-accessibility/services/viewport-capture.d.ts +0 -27
  136. package/dist/domains/visual-accessibility/services/viewport-capture.js +6 -4
  137. package/dist/domains/visual-accessibility/services/visual-regression.d.ts +0 -26
  138. package/dist/domains/visual-accessibility/services/visual-regression.js +4 -2
  139. package/dist/domains/visual-accessibility/services/visual-tester.d.ts +0 -4
  140. package/dist/domains/visual-accessibility/services/visual-tester.js +4 -2
  141. package/dist/governance/deterministic-gateway-integration.js +1 -1
  142. package/dist/mcp/bundle.js +335 -335
  143. package/dist/mcp/security/validators/command-validator.d.ts +1 -40
  144. package/dist/mcp/security/validators/command-validator.js +2 -122
  145. package/dist/mcp/security/validators/crypto-validator.d.ts +1 -39
  146. package/dist/mcp/security/validators/crypto-validator.js +2 -71
  147. package/dist/mcp/security/validators/input-sanitizer.d.ts +1 -55
  148. package/dist/mcp/security/validators/input-sanitizer.js +2 -156
  149. package/dist/mcp/security/validators/interfaces.d.ts +1 -163
  150. package/dist/mcp/security/validators/interfaces.js +2 -5
  151. package/dist/mcp/security/validators/path-traversal-validator.d.ts +1 -49
  152. package/dist/mcp/security/validators/path-traversal-validator.js +2 -241
  153. package/dist/mcp/security/validators/regex-safety-validator.d.ts +1 -49
  154. package/dist/mcp/security/validators/regex-safety-validator.js +2 -182
  155. package/dist/mcp/security/validators/validation-orchestrator.d.ts +1 -65
  156. package/dist/mcp/security/validators/validation-orchestrator.js +2 -145
  157. package/dist/shared/io/file-reader.js +1 -1
  158. package/dist/shared/security/command-validator.d.ts +44 -0
  159. package/dist/shared/security/command-validator.js +126 -0
  160. package/dist/shared/security/crypto-validator.d.ts +43 -0
  161. package/dist/shared/security/crypto-validator.js +75 -0
  162. package/dist/shared/security/index.d.ts +7 -0
  163. package/dist/shared/security/index.js +15 -0
  164. package/dist/shared/security/input-sanitizer.d.ts +59 -0
  165. package/dist/shared/security/input-sanitizer.js +160 -0
  166. package/dist/shared/security/path-traversal-validator.d.ts +53 -0
  167. package/dist/shared/security/path-traversal-validator.js +245 -0
  168. package/dist/shared/security/regex-safety-validator.d.ts +53 -0
  169. package/dist/shared/security/regex-safety-validator.js +186 -0
  170. package/dist/shared/security/validation-orchestrator.d.ts +69 -0
  171. package/dist/shared/security/validation-orchestrator.js +149 -0
  172. package/dist/shared/security/validators-interfaces.d.ts +167 -0
  173. package/dist/shared/security/validators-interfaces.js +9 -0
  174. package/package.json +1 -1
@@ -0,0 +1,171 @@
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 chalk from 'chalk';
8
+ import path from 'node:path';
9
+ import { findProjectRoot } from '../../../kernel/unified-memory.js';
10
+ import { state, getHooksSystem, createHybridBackendWithTimeout, consolidateExperiencesToPatterns, printJson, printSuccess, DREAM_STATE_KEY, } from './hooks-shared.js';
11
+ /**
12
+ * Register session-start and session-end subcommands on the hooks command.
13
+ */
14
+ export function registerSessionHooks(hooks) {
15
+ // -------------------------------------------------------------------------
16
+ // session-start: Initialize session state (called by SessionStart hook)
17
+ // -------------------------------------------------------------------------
18
+ hooks
19
+ .command('session-start')
20
+ .description('Initialize session state when Claude Code session starts')
21
+ .option('-s, --session-id <id>', 'Session ID')
22
+ .option('--json', 'Output as JSON')
23
+ .action(async (options) => {
24
+ try {
25
+ const sessionId = options.sessionId || `session-${Date.now()}`;
26
+ state.sessionId = sessionId;
27
+ // Initialize hooks system (lazy)
28
+ const { reasoningBank } = await getHooksSystem();
29
+ // Get initial stats for context
30
+ const stats = await reasoningBank.getStats();
31
+ // Initialize dream scheduler state for this session
32
+ const projectRoot = findProjectRoot();
33
+ const dataDir = path.join(projectRoot, '.agentic-qe');
34
+ const memoryBackend = await createHybridBackendWithTimeout(dataDir);
35
+ // Load existing dream state or create fresh one
36
+ let dreamState = await memoryBackend.get(DREAM_STATE_KEY);
37
+ const isNewSession = !dreamState || !dreamState.sessionStartTime;
38
+ if (!dreamState) {
39
+ dreamState = {
40
+ lastDreamTime: null,
41
+ experienceCount: 0,
42
+ sessionStartTime: new Date().toISOString(),
43
+ totalDreamsThisSession: 0,
44
+ };
45
+ }
46
+ else {
47
+ // Reset session counters but preserve lastDreamTime across sessions
48
+ dreamState.sessionStartTime = new Date().toISOString();
49
+ dreamState.totalDreamsThisSession = 0;
50
+ // Don't reset experienceCount — carry over unfulfilled experiences
51
+ }
52
+ await memoryBackend.set(DREAM_STATE_KEY, dreamState);
53
+ // Build context injection for Claude
54
+ const contextParts = [];
55
+ contextParts.push(`AQE Learning: ${stats.totalPatterns} patterns loaded`);
56
+ // Top domains by pattern count
57
+ const domainEntries = Object.entries(stats.byDomain)
58
+ .filter(([, count]) => count > 0)
59
+ .sort(([, a], [, b]) => b - a)
60
+ .slice(0, 5);
61
+ if (domainEntries.length > 0) {
62
+ contextParts.push(`Top domains: ${domainEntries.map(([d, c]) => `${d}(${c})`).join(', ')}`);
63
+ }
64
+ if (stats.patternSuccessRate > 0) {
65
+ contextParts.push(`Pattern success rate: ${(stats.patternSuccessRate * 100).toFixed(0)}%`);
66
+ }
67
+ if (stats.routingRequests > 0) {
68
+ contextParts.push(`Routing confidence: ${(stats.avgRoutingConfidence * 100).toFixed(0)}% across ${stats.routingRequests} requests`);
69
+ }
70
+ const additionalContext = contextParts.join('. ') + '.';
71
+ if (options.json) {
72
+ printJson({
73
+ hookSpecificOutput: {
74
+ hookEventName: 'SessionStart',
75
+ additionalContext,
76
+ },
77
+ sessionId,
78
+ initialized: true,
79
+ patternsLoaded: stats.totalPatterns,
80
+ dreamScheduler: {
81
+ enabled: true,
82
+ lastDreamTime: dreamState.lastDreamTime,
83
+ pendingExperiences: dreamState.experienceCount,
84
+ },
85
+ });
86
+ }
87
+ else {
88
+ printSuccess(`Session started: ${sessionId}`);
89
+ console.log(chalk.dim(` Patterns loaded: ${stats.totalPatterns}`));
90
+ console.log(chalk.dim(` Dream scheduler: enabled (${dreamState.experienceCount} pending experiences)`));
91
+ }
92
+ return;
93
+ }
94
+ catch (error) {
95
+ // Don't fail the hook - just log and return cleanly
96
+ if (options.json) {
97
+ printJson({ success: false, error: error instanceof Error ? error.message : 'unknown' });
98
+ }
99
+ return; // Return cleanly even on error (continueOnError)
100
+ }
101
+ });
102
+ // -------------------------------------------------------------------------
103
+ // session-end: Save session state (called by Stop hook)
104
+ // -------------------------------------------------------------------------
105
+ hooks
106
+ .command('session-end')
107
+ .description('Save session state when Claude Code session ends')
108
+ .option('--save-state', 'Save learning state to disk')
109
+ .option('--export-metrics', 'Export session metrics')
110
+ .option('--json', 'Output as JSON')
111
+ .action(async (options) => {
112
+ try {
113
+ const sessionId = state.sessionId || 'unknown';
114
+ // Get final stats if system is already initialized (don't init just for shutdown)
115
+ let stats = null;
116
+ if (state.initialized && state.reasoningBank) {
117
+ try {
118
+ stats = await state.reasoningBank.getStats();
119
+ }
120
+ catch {
121
+ // Ignore - system may not be available during shutdown
122
+ }
123
+ }
124
+ // Run lightweight experience-to-pattern consolidation
125
+ let patternsCreated = 0;
126
+ try {
127
+ patternsCreated = await consolidateExperiencesToPatterns();
128
+ }
129
+ catch {
130
+ // Non-critical — don't block session end
131
+ }
132
+ if (options.json) {
133
+ const summary = stats
134
+ ? `Session complete: ${stats.totalPatterns} patterns, ${stats.routingRequests} routings, ${(stats.patternSuccessRate * 100).toFixed(0)}% success rate`
135
+ : 'Session complete';
136
+ // Stop hooks don't support hookSpecificOutput — only simple fields
137
+ printJson({
138
+ continue: true,
139
+ sessionId,
140
+ stateSaved: options.saveState || false,
141
+ metricsExported: options.exportMetrics || false,
142
+ patternsConsolidated: patternsCreated,
143
+ finalStats: stats ? {
144
+ patternsLearned: stats.totalPatterns,
145
+ routingRequests: stats.routingRequests,
146
+ successRate: stats.patternSuccessRate,
147
+ } : null,
148
+ });
149
+ }
150
+ else {
151
+ printSuccess(`Session ended: ${sessionId}`);
152
+ if (stats) {
153
+ console.log(chalk.dim(` Patterns: ${stats.totalPatterns}`));
154
+ console.log(chalk.dim(` Routing requests: ${stats.routingRequests}`));
155
+ }
156
+ if (patternsCreated > 0) {
157
+ console.log(chalk.dim(` Patterns consolidated: ${patternsCreated}`));
158
+ }
159
+ }
160
+ return;
161
+ }
162
+ catch (error) {
163
+ // Don't fail the hook - just return cleanly
164
+ if (options.json) {
165
+ printJson({ success: false, error: error instanceof Error ? error.message : 'unknown' });
166
+ }
167
+ return;
168
+ }
169
+ });
170
+ }
171
+ //# sourceMappingURL=session-hooks.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Agentic QE v3 - Stats Hooks (stats, list, emit, learn, search)
3
+ * ADR-021: QE ReasoningBank for Pattern Learning
4
+ *
5
+ * Handles pattern management and statistics subcommands.
6
+ */
7
+ import { Command } from 'commander';
8
+ /**
9
+ * Register stats, list, emit, learn, and search subcommands on the hooks command.
10
+ */
11
+ export declare function registerStatsHooks(hooks: Command): void;
12
+ //# sourceMappingURL=stats-hooks.d.ts.map
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Agentic QE v3 - Stats Hooks (stats, list, emit, learn, search)
3
+ * ADR-021: QE ReasoningBank for Pattern Learning
4
+ *
5
+ * Handles pattern management and statistics subcommands.
6
+ */
7
+ import chalk from 'chalk';
8
+ import { QE_HOOK_EVENTS } from '../../../learning/qe-hooks.js';
9
+ import { safeJsonParse } from '../../../shared/safe-json.js';
10
+ import { getHooksSystem, printJson, printSuccess, printError, } from './hooks-shared.js';
11
+ /**
12
+ * Register stats, list, emit, learn, and search subcommands on the hooks command.
13
+ */
14
+ export function registerStatsHooks(hooks) {
15
+ // -------------------------------------------------------------------------
16
+ // stats: Get hooks system statistics
17
+ // -------------------------------------------------------------------------
18
+ hooks
19
+ .command('stats')
20
+ .description('Display hooks system statistics')
21
+ .option('--json', 'Output as JSON')
22
+ .action(async (options) => {
23
+ try {
24
+ const { reasoningBank } = await getHooksSystem();
25
+ const stats = await reasoningBank.getStats();
26
+ if (options.json) {
27
+ printJson(stats);
28
+ }
29
+ else {
30
+ console.log(chalk.bold('\nšŸ“Š Hooks System Statistics\n'));
31
+ console.log(chalk.bold('Patterns:'));
32
+ console.log(` Total: ${chalk.cyan(stats.totalPatterns)}`);
33
+ console.log(` Short-term: ${stats.patternStoreStats.byTier.shortTerm}`);
34
+ console.log(` Long-term: ${stats.patternStoreStats.byTier.longTerm}`);
35
+ console.log(chalk.bold('\nBy Domain:'));
36
+ for (const [domain, count] of Object.entries(stats.byDomain)) {
37
+ if (count > 0) {
38
+ console.log(` ${domain}: ${count}`);
39
+ }
40
+ }
41
+ console.log(chalk.bold('\nRouting:'));
42
+ console.log(` Requests: ${stats.routingRequests}`);
43
+ console.log(` Avg Confidence: ${(stats.avgRoutingConfidence * 100).toFixed(1)}%`);
44
+ console.log(chalk.bold('\nLearning:'));
45
+ console.log(` Outcomes: ${stats.learningOutcomes}`);
46
+ console.log(` Success Rate: ${(stats.patternSuccessRate * 100).toFixed(1)}%`);
47
+ console.log(chalk.bold('\nSearch Performance:'));
48
+ console.log(` Operations: ${stats.patternStoreStats.searchOperations}`);
49
+ console.log(` Avg Latency: ${stats.patternStoreStats.avgSearchLatencyMs.toFixed(2)}ms`);
50
+ console.log(` HNSW Native: ${stats.patternStoreStats.hnswStats.nativeAvailable ? 'āœ“' : 'āœ—'}`);
51
+ }
52
+ }
53
+ catch (error) {
54
+ printError(`stats failed: ${error instanceof Error ? error.message : 'unknown'}`);
55
+ throw error;
56
+ }
57
+ });
58
+ // -------------------------------------------------------------------------
59
+ // list: List registered hook events
60
+ // -------------------------------------------------------------------------
61
+ hooks
62
+ .command('list')
63
+ .description('List all registered QE hook events')
64
+ .option('--json', 'Output as JSON')
65
+ .action(async (options) => {
66
+ try {
67
+ const { hookRegistry } = await getHooksSystem();
68
+ const events = hookRegistry.getRegisteredEvents();
69
+ if (options.json) {
70
+ printJson({
71
+ events,
72
+ totalEvents: Object.keys(QE_HOOK_EVENTS).length,
73
+ registeredEvents: events.length,
74
+ });
75
+ }
76
+ else {
77
+ console.log(chalk.bold('\nšŸ“‹ Registered QE Hook Events\n'));
78
+ console.log(chalk.bold('All Available Events:'));
79
+ for (const [name, event] of Object.entries(QE_HOOK_EVENTS)) {
80
+ const isRegistered = events.includes(event);
81
+ const status = isRegistered ? chalk.green('āœ“') : chalk.dim('ā—‹');
82
+ console.log(` ${status} ${name}: ${chalk.dim(event)}`);
83
+ }
84
+ console.log(chalk.dim(`\nRegistered: ${events.length}/${Object.keys(QE_HOOK_EVENTS).length}`));
85
+ }
86
+ }
87
+ catch (error) {
88
+ printError(`list failed: ${error instanceof Error ? error.message : 'unknown'}`);
89
+ throw error;
90
+ }
91
+ });
92
+ // -------------------------------------------------------------------------
93
+ // emit: Emit a hook event (for testing/integration)
94
+ // -------------------------------------------------------------------------
95
+ hooks
96
+ .command('emit')
97
+ .description('Emit a QE hook event')
98
+ .requiredOption('-e, --event <name>', 'Event name (e.g., qe:pattern-applied)')
99
+ .option('-d, --data <json>', 'Event data as JSON', '{}')
100
+ .option('--json', 'Output as JSON')
101
+ .action(async (options) => {
102
+ try {
103
+ const { hookRegistry } = await getHooksSystem();
104
+ let data;
105
+ try {
106
+ data = safeJsonParse(options.data);
107
+ }
108
+ catch {
109
+ throw new Error(`Invalid JSON data: ${options.data}`);
110
+ }
111
+ const results = await hookRegistry.emit(options.event, data);
112
+ if (options.json) {
113
+ printJson({
114
+ event: options.event,
115
+ results,
116
+ });
117
+ }
118
+ else {
119
+ console.log(chalk.bold('\nšŸ“” Hook Event Emitted'));
120
+ console.log(chalk.dim(` Event: ${options.event}`));
121
+ console.log(chalk.dim(` Handlers: ${results.length}`));
122
+ results.forEach((result, i) => {
123
+ const status = result.success ? chalk.green('āœ“') : chalk.red('āœ—');
124
+ console.log(` ${status} Handler ${i + 1}: ${result.success ? 'success' : result.error}`);
125
+ if (result.patternsLearned) {
126
+ console.log(chalk.green(` Patterns learned: ${result.patternsLearned}`));
127
+ }
128
+ });
129
+ }
130
+ }
131
+ catch (error) {
132
+ printError(`emit failed: ${error instanceof Error ? error.message : 'unknown'}`);
133
+ throw error;
134
+ }
135
+ });
136
+ // -------------------------------------------------------------------------
137
+ // learn: Store a new pattern for learning
138
+ // -------------------------------------------------------------------------
139
+ hooks
140
+ .command('learn')
141
+ .description('Store a new pattern in the reasoning bank')
142
+ .requiredOption('-n, --name <name>', 'Pattern name')
143
+ .requiredOption('-d, --description <desc>', 'Pattern description')
144
+ .option('-t, --type <type>', 'Pattern type', 'test-template')
145
+ .option('--domain <domain>', 'QE domain')
146
+ .option('--tags <tags...>', 'Pattern tags')
147
+ .option('--json', 'Output as JSON')
148
+ .action(async (options) => {
149
+ try {
150
+ const { reasoningBank } = await getHooksSystem();
151
+ const result = await reasoningBank.storePattern({
152
+ patternType: options.type,
153
+ name: options.name,
154
+ description: options.description,
155
+ template: {
156
+ type: 'prompt',
157
+ content: options.description,
158
+ variables: [],
159
+ },
160
+ context: {
161
+ tags: options.tags || [],
162
+ },
163
+ });
164
+ if (!result.success) {
165
+ throw new Error(result.error.message);
166
+ }
167
+ const pattern = result.value;
168
+ if (options.json) {
169
+ printJson({
170
+ success: true,
171
+ pattern: {
172
+ id: pattern.id,
173
+ name: pattern.name,
174
+ type: pattern.patternType,
175
+ domain: pattern.qeDomain,
176
+ },
177
+ });
178
+ }
179
+ else {
180
+ printSuccess(`Pattern stored: ${pattern.name}`);
181
+ console.log(chalk.dim(` ID: ${pattern.id}`));
182
+ console.log(chalk.dim(` Domain: ${pattern.qeDomain}`));
183
+ console.log(chalk.dim(` Tier: ${pattern.tier}`));
184
+ }
185
+ }
186
+ catch (error) {
187
+ printError(`learn failed: ${error instanceof Error ? error.message : 'unknown'}`);
188
+ throw error;
189
+ }
190
+ });
191
+ // -------------------------------------------------------------------------
192
+ // search: Search for patterns
193
+ // -------------------------------------------------------------------------
194
+ hooks
195
+ .command('search')
196
+ .description('Search for patterns in the reasoning bank')
197
+ .requiredOption('-q, --query <query>', 'Search query')
198
+ .option('-l, --limit <n>', 'Maximum results', '10')
199
+ .option('-d, --domain <domain>', 'Filter by domain')
200
+ .option('--json', 'Output as JSON')
201
+ .action(async (options) => {
202
+ try {
203
+ const { reasoningBank } = await getHooksSystem();
204
+ const result = await reasoningBank.searchPatterns(options.query, {
205
+ limit: parseInt(options.limit, 10),
206
+ domain: options.domain,
207
+ });
208
+ if (!result.success) {
209
+ throw new Error(result.error.message);
210
+ }
211
+ const patterns = result.value;
212
+ if (options.json) {
213
+ printJson({
214
+ query: options.query,
215
+ total: patterns.length,
216
+ patterns: patterns.map((p) => ({
217
+ id: p.pattern.id,
218
+ name: p.pattern.name,
219
+ score: p.score,
220
+ domain: p.pattern.qeDomain,
221
+ matchType: p.matchType,
222
+ })),
223
+ });
224
+ }
225
+ else {
226
+ console.log(chalk.bold(`\nšŸ” Search Results for "${options.query}"\n`));
227
+ if (patterns.length === 0) {
228
+ console.log(chalk.dim(' No patterns found'));
229
+ }
230
+ else {
231
+ patterns.forEach((p, i) => {
232
+ console.log(`${chalk.cyan(`${i + 1}.`)} ${p.pattern.name} ${chalk.dim(`(${(p.score * 100).toFixed(1)}%)`)}`);
233
+ console.log(chalk.dim(` Domain: ${p.pattern.qeDomain}`));
234
+ console.log(chalk.dim(` Match: ${p.matchType}`));
235
+ console.log(chalk.dim(` ID: ${p.pattern.id}`));
236
+ console.log();
237
+ });
238
+ }
239
+ console.log(chalk.dim(`Found ${patterns.length} pattern(s)`));
240
+ }
241
+ }
242
+ catch (error) {
243
+ printError(`search failed: ${error instanceof Error ? error.message : 'unknown'}`);
244
+ throw error;
245
+ }
246
+ });
247
+ }
248
+ //# sourceMappingURL=stats-hooks.js.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Agentic QE v3 - Task Hooks (pre-task, post-task)
3
+ * ADR-021: QE ReasoningBank for Pattern Learning
4
+ *
5
+ * Handles task lifecycle hooks for pattern learning.
6
+ */
7
+ import { Command } from 'commander';
8
+ /**
9
+ * Register pre-task and post-task subcommands on the hooks command.
10
+ */
11
+ export declare function registerTaskHooks(hooks: Command): void;
12
+ //# sourceMappingURL=task-hooks.d.ts.map
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Agentic QE v3 - Task Hooks (pre-task, post-task)
3
+ * ADR-021: QE ReasoningBank for Pattern Learning
4
+ *
5
+ * Handles task lifecycle hooks for pattern learning.
6
+ */
7
+ import chalk from 'chalk';
8
+ import path from 'node:path';
9
+ import { QE_HOOK_EVENTS } from '../../../learning/qe-hooks.js';
10
+ import { findProjectRoot } from '../../../kernel/unified-memory.js';
11
+ import { getHooksSystem, createHybridBackendWithTimeout, incrementDreamExperience, checkAndTriggerDream, printJson, printSuccess, } from './hooks-shared.js';
12
+ /**
13
+ * Register pre-task and post-task subcommands on the hooks command.
14
+ */
15
+ export function registerTaskHooks(hooks) {
16
+ // -------------------------------------------------------------------------
17
+ // pre-task: Get guidance before spawning a Task (called by PreToolUse hook)
18
+ // -------------------------------------------------------------------------
19
+ hooks
20
+ .command('pre-task')
21
+ .description('Get context and guidance before spawning a Task agent')
22
+ .option('--task-id <id>', 'Task identifier')
23
+ .option('-d, --description <desc>', 'Task description')
24
+ .option('--json', 'Output as JSON')
25
+ .action(async (options) => {
26
+ try {
27
+ const { reasoningBank } = await getHooksSystem();
28
+ // Route the task to get agent recommendation
29
+ let routing = null;
30
+ if (options.description) {
31
+ const result = await reasoningBank.routeTask({
32
+ task: options.description,
33
+ });
34
+ if (result.success) {
35
+ routing = result.value;
36
+ }
37
+ }
38
+ if (options.json) {
39
+ printJson({
40
+ success: true,
41
+ taskId: options.taskId,
42
+ description: options.description,
43
+ recommendedAgent: routing?.recommendedAgent,
44
+ confidence: routing?.confidence,
45
+ guidance: routing?.guidance || [],
46
+ });
47
+ }
48
+ else {
49
+ console.log(chalk.bold('\nšŸš€ Pre-Task Analysis'));
50
+ console.log(chalk.dim(` Task ID: ${options.taskId || 'N/A'}`));
51
+ if (routing) {
52
+ console.log(chalk.bold('\nšŸŽÆ Recommended:'), chalk.cyan(routing.recommendedAgent));
53
+ console.log(chalk.dim(` Confidence: ${(routing.confidence * 100).toFixed(1)}%`));
54
+ }
55
+ }
56
+ return;
57
+ }
58
+ catch (error) {
59
+ if (options.json) {
60
+ printJson({ success: false, error: error instanceof Error ? error.message : 'unknown' });
61
+ }
62
+ return;
63
+ }
64
+ });
65
+ // -------------------------------------------------------------------------
66
+ // post-task: Record task outcome for learning (called by PostToolUse hook)
67
+ // -------------------------------------------------------------------------
68
+ hooks
69
+ .command('post-task')
70
+ .description('Record task outcome for pattern learning')
71
+ .option('--task-id <id>', 'Task identifier')
72
+ .option('--success <bool>', 'Whether task succeeded', 'true')
73
+ .option('--agent <name>', 'Agent that executed the task')
74
+ .option('--duration <ms>', 'Task duration in milliseconds')
75
+ .option('--json', 'Output as JSON')
76
+ .action(async (options) => {
77
+ try {
78
+ const success = options.success === 'true' || options.success === true;
79
+ // Initialize hooks system and record learning outcome
80
+ // BUG FIX: Must call getHooksSystem() FIRST to initialize, not check state.initialized
81
+ let patternsLearned = 0;
82
+ let dreamResult = { triggered: false };
83
+ try {
84
+ // Initialize system (creates ReasoningBank and HookRegistry)
85
+ const { hookRegistry, reasoningBank } = await getHooksSystem();
86
+ // Emit learning event for task completion
87
+ const results = await hookRegistry.emit(QE_HOOK_EVENTS.QEAgentCompletion, {
88
+ taskId: options.taskId,
89
+ success,
90
+ agent: options.agent,
91
+ duration: options.duration ? parseInt(options.duration, 10) : undefined,
92
+ timestamp: Date.now(),
93
+ });
94
+ patternsLearned = results.reduce((sum, r) => sum + (r.patternsLearned || 0), 0);
95
+ // Record as learning experience for every post-task invocation
96
+ if (options.taskId) {
97
+ const agent = options.agent || 'unknown';
98
+ await reasoningBank.recordOutcome({
99
+ patternId: `task:${agent}:${options.taskId}`,
100
+ success,
101
+ metrics: {
102
+ executionTimeMs: options.duration ? parseInt(options.duration, 10) : 0,
103
+ },
104
+ feedback: `Agent: ${agent}, Task: ${options.taskId}`,
105
+ });
106
+ }
107
+ // Record experience for dream scheduler and check if dream should trigger
108
+ const projectRoot = findProjectRoot();
109
+ const dataDir = path.join(projectRoot, '.agentic-qe');
110
+ const memoryBackend = await createHybridBackendWithTimeout(dataDir);
111
+ const expCount = await incrementDreamExperience(memoryBackend);
112
+ // Check if dream cycle should be triggered
113
+ // Always check — time-based triggers need every invocation, and the
114
+ // check itself is lightweight (just reads state + compares timestamps)
115
+ dreamResult = await checkAndTriggerDream(memoryBackend);
116
+ }
117
+ catch (initError) {
118
+ // Log but don't fail - learning is best-effort
119
+ console.error(chalk.dim(`[hooks] Learning init: ${initError instanceof Error ? initError.message : 'unknown'}`));
120
+ }
121
+ if (options.json) {
122
+ printJson({
123
+ success: true,
124
+ taskId: options.taskId,
125
+ taskSuccess: success,
126
+ patternsLearned,
127
+ dreamTriggered: dreamResult.triggered,
128
+ dreamReason: dreamResult.reason,
129
+ dreamInsights: dreamResult.insightsGenerated,
130
+ });
131
+ }
132
+ else {
133
+ printSuccess(`Task completed: ${options.taskId || 'unknown'}`);
134
+ console.log(chalk.dim(` Success: ${success}`));
135
+ if (patternsLearned > 0) {
136
+ console.log(chalk.green(` Patterns learned: ${patternsLearned}`));
137
+ }
138
+ if (dreamResult.triggered) {
139
+ console.log(chalk.blue(` šŸŒ™ Dream cycle triggered (${dreamResult.reason}): ${dreamResult.insightsGenerated} insights`));
140
+ }
141
+ }
142
+ return;
143
+ }
144
+ catch (error) {
145
+ if (options.json) {
146
+ printJson({ success: false, error: error instanceof Error ? error.message : 'unknown' });
147
+ }
148
+ return;
149
+ }
150
+ });
151
+ }
152
+ //# sourceMappingURL=task-hooks.js.map
@@ -4,31 +4,11 @@
4
4
  * ADR-021: QE ReasoningBank for Pattern Learning
5
5
  *
6
6
  * Self-learning hooks system for pattern recognition and guidance generation.
7
- * This module provides CLI commands for the QE hooks system.
7
+ * This module composes all hooks subcommands from per-handler modules.
8
8
  */
9
9
  import { Command } from 'commander';
10
- import { QEReasoningBank } from '../../learning/qe-reasoning-bank.js';
11
- import { QEHookRegistry, QE_HOOK_EVENTS } from '../../learning/qe-hooks.js';
12
- import { type ICoherenceService } from '../../integrations/coherence/index.js';
13
- /**
14
- * Singleton state for hooks system
15
- */
16
- 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
- declare const state: HooksSystemState;
25
- /**
26
- * Get or create the hooks system with proper initialization
27
- */
28
- declare function getHooksSystem(): Promise<{
29
- reasoningBank: QEReasoningBank;
30
- hookRegistry: QEHookRegistry;
31
- }>;
10
+ import { QE_HOOK_EVENTS } from '../../learning/qe-hooks.js';
11
+ import { getHooksSystem, state, type HooksSystemState } from './hooks-handlers/hooks-shared.js';
32
12
  /**
33
13
  * Create the hooks command with all subcommands
34
14
  */