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,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Command Hooks (guard, pre-command, post-command)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles file guardian and Bash command lifecycle hooks.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
/**
|
|
9
|
+
* Register guard, pre-command, and post-command subcommands on the hooks command.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerCommandHooks(hooks: Command): void;
|
|
12
|
+
//# sourceMappingURL=command-hooks.d.ts.map
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Command Hooks (guard, pre-command, post-command)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles file guardian and Bash command lifecycle hooks.
|
|
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, persistCommandExperience, printJson, printSuccess, printError, } from './hooks-shared.js';
|
|
12
|
+
/**
|
|
13
|
+
* Register guard, pre-command, and post-command subcommands on the hooks command.
|
|
14
|
+
*/
|
|
15
|
+
export function registerCommandHooks(hooks) {
|
|
16
|
+
// -------------------------------------------------------------------------
|
|
17
|
+
// guard: File guardian - block edits to protected files (PreToolUse)
|
|
18
|
+
// -------------------------------------------------------------------------
|
|
19
|
+
hooks
|
|
20
|
+
.command('guard')
|
|
21
|
+
.description('File guardian - block edits to protected files')
|
|
22
|
+
.requiredOption('-f, --file <path>', 'File path to check')
|
|
23
|
+
.option('--json', 'Output as JSON (required for hook API)')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
try {
|
|
26
|
+
const filePath = options.file || '';
|
|
27
|
+
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
28
|
+
// Protected file patterns
|
|
29
|
+
const protectedPatterns = [
|
|
30
|
+
{ pattern: /^\.env($|\.)/, reason: 'Environment file contains secrets' },
|
|
31
|
+
{ pattern: /\.env\.[a-zA-Z]+$/, reason: 'Environment file contains secrets' },
|
|
32
|
+
{ pattern: /\.lock$/, reason: 'Lock files are auto-generated' },
|
|
33
|
+
{ pattern: /(^|\/)node_modules\//, reason: 'node_modules is managed by package manager' },
|
|
34
|
+
{ pattern: /(^|\/)\.agentic-qe\/memory\.db/, reason: 'AQE memory database must not be directly edited' },
|
|
35
|
+
{ pattern: /(^|\/)\.agentic-qe\/memory\.db-wal$/, reason: 'AQE WAL file must not be directly edited' },
|
|
36
|
+
{ pattern: /(^|\/)\.agentic-qe\/memory\.db-shm$/, reason: 'AQE shared memory file must not be directly edited' },
|
|
37
|
+
];
|
|
38
|
+
const match = protectedPatterns.find(p => p.pattern.test(normalizedPath));
|
|
39
|
+
if (match) {
|
|
40
|
+
// Deny - use Claude Code hookSpecificOutput API format
|
|
41
|
+
if (options.json) {
|
|
42
|
+
printJson({
|
|
43
|
+
hookSpecificOutput: {
|
|
44
|
+
hookEventName: 'PreToolUse',
|
|
45
|
+
permissionDecision: 'deny',
|
|
46
|
+
permissionDecisionReason: `Protected file: ${match.reason} (${filePath})`,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
printError(`Blocked: ${match.reason} (${filePath})`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Allow
|
|
56
|
+
if (options.json) {
|
|
57
|
+
printJson({
|
|
58
|
+
hookSpecificOutput: {
|
|
59
|
+
hookEventName: 'PreToolUse',
|
|
60
|
+
permissionDecision: 'allow',
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
printSuccess(`Allowed: ${filePath}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// On error, allow (fail-open for non-critical guard)
|
|
72
|
+
if (options.json) {
|
|
73
|
+
printJson({
|
|
74
|
+
hookSpecificOutput: {
|
|
75
|
+
hookEventName: 'PreToolUse',
|
|
76
|
+
permissionDecision: 'allow',
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
// pre-command: Get guidance before Bash command (called by PreToolUse hook)
|
|
85
|
+
// -------------------------------------------------------------------------
|
|
86
|
+
hooks
|
|
87
|
+
.command('pre-command')
|
|
88
|
+
.description('Get context before executing a Bash command')
|
|
89
|
+
.option('-c, --command <cmd>', 'Command to be executed')
|
|
90
|
+
.option('--json', 'Output as JSON')
|
|
91
|
+
.action(async (options) => {
|
|
92
|
+
try {
|
|
93
|
+
const command = options.command || '';
|
|
94
|
+
// Dangerous command patterns that should be BLOCKED
|
|
95
|
+
const dangerousPatterns = [
|
|
96
|
+
{ pattern: /rm\s+(-[a-zA-Z]*f[a-zA-Z]*\s+)?-[a-zA-Z]*r[a-zA-Z]*\s+\/(?!\w)/, reason: 'Recursive delete of root filesystem' },
|
|
97
|
+
{ pattern: /rm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+)?-[a-zA-Z]*f[a-zA-Z]*\s+\/(?!\w)/, reason: 'Recursive delete of root filesystem' },
|
|
98
|
+
{ pattern: /rm\s+-rf\s+~/, reason: 'Recursive delete of home directory' },
|
|
99
|
+
{ pattern: /DROP\s+(TABLE|DATABASE|SCHEMA)/i, reason: 'Destructive SQL operation' },
|
|
100
|
+
{ pattern: /git\s+push\s+.*--force(?!-)/, reason: 'Force push can overwrite remote history' },
|
|
101
|
+
{ pattern: /git\s+reset\s+--hard/, reason: 'Hard reset discards uncommitted changes' },
|
|
102
|
+
{ pattern: />\s*\/dev\/sd[a-z]/, reason: 'Direct write to block device' },
|
|
103
|
+
{ pattern: /dd\s+if=.*of=\/dev\/sd/, reason: 'Direct disk write via dd' },
|
|
104
|
+
{ pattern: /chmod\s+777\s/, reason: 'World-writable permissions are a security risk' },
|
|
105
|
+
{ pattern: /:\(\)\s*\{\s*:\|\s*:&\s*\}\s*;?\s*:/, reason: 'Fork bomb detected' },
|
|
106
|
+
{ pattern: /mkfs\./, reason: 'Filesystem format operation' },
|
|
107
|
+
{ pattern: />\s*\/dev\/null\s*2>&1\s*&\s*disown/, reason: 'Stealth background process' },
|
|
108
|
+
];
|
|
109
|
+
// Warning patterns (inform but don't block)
|
|
110
|
+
const warningPatterns = [
|
|
111
|
+
{ pattern: /\.agentic-qe.*rm/, reason: 'Deleting AQE data files' },
|
|
112
|
+
{ pattern: /rm\s+-rf\s/, reason: 'Recursive force delete' },
|
|
113
|
+
{ pattern: /git\s+clean\s+-[a-zA-Z]*f/, reason: 'Force cleaning untracked files' },
|
|
114
|
+
];
|
|
115
|
+
const dangerMatch = dangerousPatterns.find(p => p.pattern.test(command));
|
|
116
|
+
const warnings = warningPatterns
|
|
117
|
+
.filter(p => p.pattern.test(command))
|
|
118
|
+
.map(p => p.reason);
|
|
119
|
+
if (dangerMatch) {
|
|
120
|
+
// BLOCK the command
|
|
121
|
+
if (options.json) {
|
|
122
|
+
printJson({
|
|
123
|
+
hookSpecificOutput: {
|
|
124
|
+
hookEventName: 'PreToolUse',
|
|
125
|
+
permissionDecision: 'deny',
|
|
126
|
+
permissionDecisionReason: `Dangerous command blocked: ${dangerMatch.reason}`,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
printError(`Blocked: ${dangerMatch.reason}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Allow (with optional warnings as context)
|
|
136
|
+
if (options.json) {
|
|
137
|
+
const result = {
|
|
138
|
+
hookSpecificOutput: {
|
|
139
|
+
hookEventName: 'PreToolUse',
|
|
140
|
+
permissionDecision: 'allow',
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
if (warnings.length > 0) {
|
|
144
|
+
result.hookSpecificOutput.additionalContext =
|
|
145
|
+
`Warnings: ${warnings.join('; ')}`;
|
|
146
|
+
}
|
|
147
|
+
printJson(result);
|
|
148
|
+
}
|
|
149
|
+
else if (warnings.length > 0) {
|
|
150
|
+
console.log(chalk.yellow('\n⚠️ Command Warnings:'));
|
|
151
|
+
warnings.forEach(w => console.log(chalk.yellow(` - ${w}`)));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
// Fail-open on error
|
|
158
|
+
if (options.json) {
|
|
159
|
+
printJson({
|
|
160
|
+
hookSpecificOutput: {
|
|
161
|
+
hookEventName: 'PreToolUse',
|
|
162
|
+
permissionDecision: 'allow',
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
// -------------------------------------------------------------------------
|
|
170
|
+
// post-command: Record command outcome (called by PostToolUse hook)
|
|
171
|
+
// -------------------------------------------------------------------------
|
|
172
|
+
hooks
|
|
173
|
+
.command('post-command')
|
|
174
|
+
.description('Record Bash command outcome')
|
|
175
|
+
.option('-c, --command <cmd>', 'Command that was executed')
|
|
176
|
+
.option('--success <bool>', 'Whether command succeeded', 'true')
|
|
177
|
+
.option('--exit-code <code>', 'Command exit code')
|
|
178
|
+
.option('--json', 'Output as JSON')
|
|
179
|
+
.action(async (options) => {
|
|
180
|
+
try {
|
|
181
|
+
const success = options.success === 'true' || options.success === true;
|
|
182
|
+
const exitCode = options.exitCode ? parseInt(options.exitCode, 10) : (success ? 0 : 1);
|
|
183
|
+
const command = (options.command || '').substring(0, 200);
|
|
184
|
+
// Determine if this is a test/build/lint command for richer learning
|
|
185
|
+
const isTestCmd = /\b(test|vitest|jest|pytest|mocha)\b/i.test(command);
|
|
186
|
+
const isBuildCmd = /\b(build|compile|tsc)\b/i.test(command);
|
|
187
|
+
const isLintCmd = /\b(lint|eslint|prettier)\b/i.test(command);
|
|
188
|
+
let patternsLearned = 0;
|
|
189
|
+
let experienceRecorded = false;
|
|
190
|
+
try {
|
|
191
|
+
const { reasoningBank } = await getHooksSystem();
|
|
192
|
+
// For test commands, emit TestExecutionResult for pattern learning
|
|
193
|
+
if (isTestCmd) {
|
|
194
|
+
const { hookRegistry } = await getHooksSystem();
|
|
195
|
+
await hookRegistry.emit(QE_HOOK_EVENTS.TestExecutionResult, {
|
|
196
|
+
runId: `cmd-${Date.now()}`,
|
|
197
|
+
patternId: `cmd:test:${command.split(/\s+/).slice(0, 3).join('-')}`,
|
|
198
|
+
passed: success ? 1 : 0,
|
|
199
|
+
failed: success ? 0 : 1,
|
|
200
|
+
duration: 0,
|
|
201
|
+
flaky: false,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Record outcome for all commands
|
|
205
|
+
const cmdSlug = command.replace(/[^a-zA-Z0-9]/g, '-').slice(0, 80);
|
|
206
|
+
const domain = isTestCmd ? 'test-execution' : isBuildCmd ? 'code-intelligence' : isLintCmd ? 'quality-assessment' : 'code-intelligence';
|
|
207
|
+
await reasoningBank.recordOutcome({
|
|
208
|
+
patternId: `cmd:${cmdSlug}`,
|
|
209
|
+
success,
|
|
210
|
+
metrics: { executionTimeMs: 0 },
|
|
211
|
+
feedback: `Command: ${command}, exit: ${exitCode}`,
|
|
212
|
+
});
|
|
213
|
+
patternsLearned = 1;
|
|
214
|
+
// Persist as captured experience
|
|
215
|
+
await persistCommandExperience({
|
|
216
|
+
task: `bash: ${command}`,
|
|
217
|
+
agent: 'cli-hook',
|
|
218
|
+
domain,
|
|
219
|
+
success,
|
|
220
|
+
source: 'cli-hook-post-command',
|
|
221
|
+
});
|
|
222
|
+
experienceRecorded = true;
|
|
223
|
+
// Increment dream experience counter
|
|
224
|
+
const projectRoot = findProjectRoot();
|
|
225
|
+
const dataDir = path.join(projectRoot, '.agentic-qe');
|
|
226
|
+
const memoryBackend = await createHybridBackendWithTimeout(dataDir);
|
|
227
|
+
await incrementDreamExperience(memoryBackend);
|
|
228
|
+
}
|
|
229
|
+
catch (initError) {
|
|
230
|
+
console.error(chalk.dim(`[hooks] post-command learning: ${initError instanceof Error ? initError.message : 'unknown'}`));
|
|
231
|
+
}
|
|
232
|
+
if (options.json) {
|
|
233
|
+
printJson({
|
|
234
|
+
success: true,
|
|
235
|
+
command: command.substring(0, 100),
|
|
236
|
+
commandSuccess: success,
|
|
237
|
+
exitCode,
|
|
238
|
+
patternsLearned,
|
|
239
|
+
experienceRecorded,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// Silent in non-JSON mode to avoid cluttering output
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
if (options.json) {
|
|
247
|
+
printJson({ success: false, error: error instanceof Error ? error.message : 'unknown' });
|
|
248
|
+
}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=command-hooks.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Editing Hooks (pre-edit, post-edit)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles file editing lifecycle hooks for pattern learning.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
/**
|
|
9
|
+
* Register pre-edit and post-edit subcommands on the hooks command.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerEditingHooks(hooks: Command): void;
|
|
12
|
+
//# sourceMappingURL=editing-hooks.d.ts.map
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Editing Hooks (pre-edit, post-edit)
|
|
3
|
+
* ADR-021: QE ReasoningBank for Pattern Learning
|
|
4
|
+
*
|
|
5
|
+
* Handles file editing 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, persistCommandExperience, printJson, printSuccess, printError, printGuidance, } from './hooks-shared.js';
|
|
12
|
+
/**
|
|
13
|
+
* Register pre-edit and post-edit subcommands on the hooks command.
|
|
14
|
+
*/
|
|
15
|
+
export function registerEditingHooks(hooks) {
|
|
16
|
+
// -------------------------------------------------------------------------
|
|
17
|
+
// pre-edit: Get guidance before editing a file
|
|
18
|
+
// -------------------------------------------------------------------------
|
|
19
|
+
hooks
|
|
20
|
+
.command('pre-edit')
|
|
21
|
+
.description('Get context and guidance before editing a file')
|
|
22
|
+
.requiredOption('-f, --file <path>', 'File path to edit')
|
|
23
|
+
.option('-o, --operation <type>', 'Operation type: create, update, delete, refactor', 'update')
|
|
24
|
+
.option('--json', 'Output as JSON')
|
|
25
|
+
.action(async (options) => {
|
|
26
|
+
try {
|
|
27
|
+
const { hookRegistry } = await getHooksSystem();
|
|
28
|
+
const results = await hookRegistry.emit(QE_HOOK_EVENTS.PreTestGeneration, {
|
|
29
|
+
targetFile: options.file,
|
|
30
|
+
testType: 'unit',
|
|
31
|
+
operation: options.operation,
|
|
32
|
+
});
|
|
33
|
+
const result = results[0] || { success: true, guidance: [], routing: null };
|
|
34
|
+
if (options.json) {
|
|
35
|
+
// Build additionalContext for Claude from guidance
|
|
36
|
+
const guidanceLines = result.guidance || [];
|
|
37
|
+
const agentHint = result.routing?.recommendedAgent
|
|
38
|
+
? `Recommended agent: ${result.routing.recommendedAgent} (${(result.routing.confidence * 100).toFixed(0)}% confidence).`
|
|
39
|
+
: '';
|
|
40
|
+
const contextStr = [
|
|
41
|
+
agentHint,
|
|
42
|
+
...guidanceLines.map((g) => g),
|
|
43
|
+
].filter(Boolean).join(' ');
|
|
44
|
+
printJson({
|
|
45
|
+
hookSpecificOutput: {
|
|
46
|
+
hookEventName: 'PreToolUse',
|
|
47
|
+
additionalContext: contextStr || undefined,
|
|
48
|
+
},
|
|
49
|
+
file: options.file,
|
|
50
|
+
operation: options.operation,
|
|
51
|
+
patterns: result.routing?.patterns?.length || 0,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log(chalk.bold('\n📝 Pre-Edit Analysis'));
|
|
56
|
+
console.log(chalk.dim(` File: ${options.file}`));
|
|
57
|
+
console.log(chalk.dim(` Operation: ${options.operation}`));
|
|
58
|
+
if (result.routing) {
|
|
59
|
+
console.log(chalk.bold('\n🎯 Recommended Agent:'), chalk.cyan(result.routing.recommendedAgent));
|
|
60
|
+
console.log(chalk.dim(` Confidence: ${(result.routing.confidence * 100).toFixed(1)}%`));
|
|
61
|
+
}
|
|
62
|
+
console.log(chalk.bold('\n💡 Guidance:'));
|
|
63
|
+
printGuidance(result.guidance || []);
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
printError(`pre-edit failed: ${error instanceof Error ? error.message : 'unknown'}`);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// -------------------------------------------------------------------------
|
|
73
|
+
// post-edit: Record editing outcome for learning
|
|
74
|
+
// -------------------------------------------------------------------------
|
|
75
|
+
hooks
|
|
76
|
+
.command('post-edit')
|
|
77
|
+
.description('Record editing outcome for pattern learning')
|
|
78
|
+
.requiredOption('-f, --file <path>', 'File path that was edited')
|
|
79
|
+
.option('--success', 'Edit was successful')
|
|
80
|
+
.option('--failure', 'Edit failed')
|
|
81
|
+
.option('--pattern-id <id>', 'Pattern ID that was applied')
|
|
82
|
+
.option('--json', 'Output as JSON')
|
|
83
|
+
.action(async (options) => {
|
|
84
|
+
try {
|
|
85
|
+
const { hookRegistry } = await getHooksSystem();
|
|
86
|
+
const success = options.success || !options.failure;
|
|
87
|
+
// Generate synthetic patternId from file path if none provided
|
|
88
|
+
const filePath = options.file || '';
|
|
89
|
+
const fileName = filePath.split('/').pop() || 'unknown';
|
|
90
|
+
const isTestFile = /\.(test|spec)\.(ts|js|tsx|jsx)$/.test(fileName);
|
|
91
|
+
const domain = isTestFile ? 'test-generation' : 'code-intelligence';
|
|
92
|
+
const syntheticPatternId = options.patternId || `edit:${domain}:${fileName}`;
|
|
93
|
+
const results = await hookRegistry.emit(QE_HOOK_EVENTS.PostTestGeneration, {
|
|
94
|
+
targetFile: options.file,
|
|
95
|
+
success,
|
|
96
|
+
patternId: syntheticPatternId,
|
|
97
|
+
generatedTests: null,
|
|
98
|
+
testCount: 0,
|
|
99
|
+
});
|
|
100
|
+
const result = results[0] || { success: true, patternsLearned: 0 };
|
|
101
|
+
// Also explicitly call recordOutcome so qe_pattern_usage gets a row
|
|
102
|
+
try {
|
|
103
|
+
const { reasoningBank } = await getHooksSystem();
|
|
104
|
+
await reasoningBank.recordOutcome({
|
|
105
|
+
patternId: syntheticPatternId,
|
|
106
|
+
success,
|
|
107
|
+
metrics: { executionTimeMs: 0 },
|
|
108
|
+
feedback: `Edit ${success ? 'succeeded' : 'failed'}: ${filePath}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// best-effort
|
|
113
|
+
}
|
|
114
|
+
// Persist as captured experience
|
|
115
|
+
try {
|
|
116
|
+
await persistCommandExperience({
|
|
117
|
+
task: `edit: ${filePath}`,
|
|
118
|
+
agent: 'cli-hook',
|
|
119
|
+
domain,
|
|
120
|
+
success,
|
|
121
|
+
source: 'cli-hook-post-edit',
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// best-effort
|
|
126
|
+
}
|
|
127
|
+
// Record experience for dream scheduler
|
|
128
|
+
let dreamTriggered = false;
|
|
129
|
+
try {
|
|
130
|
+
const projectRoot = findProjectRoot();
|
|
131
|
+
const dataDir = path.join(projectRoot, '.agentic-qe');
|
|
132
|
+
const memoryBackend = await createHybridBackendWithTimeout(dataDir);
|
|
133
|
+
await incrementDreamExperience(memoryBackend);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// best-effort
|
|
137
|
+
}
|
|
138
|
+
if (options.json) {
|
|
139
|
+
printJson({
|
|
140
|
+
success: true,
|
|
141
|
+
file: options.file,
|
|
142
|
+
editSuccess: success,
|
|
143
|
+
patternsLearned: result.patternsLearned || 0,
|
|
144
|
+
dreamTriggered,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
printSuccess(`Recorded edit outcome for ${options.file}`);
|
|
149
|
+
if (result.patternsLearned) {
|
|
150
|
+
console.log(chalk.green(` Patterns learned: ${result.patternsLearned}`));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
printError(`post-edit failed: ${error instanceof Error ? error.message : 'unknown'}`);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=editing-hooks.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
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 type { MemoryBackend } from '../../../kernel/interfaces.js';
|
|
8
|
+
export declare const DREAM_STATE_KEY = "dream-scheduler:hook-state";
|
|
9
|
+
export declare const DREAM_INTERVAL_MS = 3600000;
|
|
10
|
+
export declare const DREAM_EXPERIENCE_THRESHOLD = 20;
|
|
11
|
+
export declare const DREAM_MIN_GAP_MS = 300000;
|
|
12
|
+
export interface DreamHookState {
|
|
13
|
+
lastDreamTime: string | null;
|
|
14
|
+
experienceCount: number;
|
|
15
|
+
sessionStartTime: string;
|
|
16
|
+
totalDreamsThisSession: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if a dream cycle should be triggered and run it if so.
|
|
20
|
+
* Called from post-task hook after recording each experience.
|
|
21
|
+
*
|
|
22
|
+
* Trigger conditions (any of):
|
|
23
|
+
* 1. Time-based: >1hr since last dream
|
|
24
|
+
* 2. Experience-based: >20 experiences since last dream
|
|
25
|
+
*
|
|
26
|
+
* Guard: minimum 5 minutes between dreams
|
|
27
|
+
*/
|
|
28
|
+
export declare function checkAndTriggerDream(memoryBackend: MemoryBackend): Promise<{
|
|
29
|
+
triggered: boolean;
|
|
30
|
+
reason?: string;
|
|
31
|
+
insightsGenerated?: number;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Increment the experience counter in dream state.
|
|
35
|
+
* Called from post-task hook.
|
|
36
|
+
*/
|
|
37
|
+
export declare function incrementDreamExperience(memoryBackend: MemoryBackend): Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* Persist a command/edit experience directly to the captured_experiences table.
|
|
40
|
+
* CLI hooks cannot use the MCP middleware wrapper, so they write directly.
|
|
41
|
+
*/
|
|
42
|
+
export declare function persistCommandExperience(opts: {
|
|
43
|
+
task: string;
|
|
44
|
+
agent: string;
|
|
45
|
+
domain: string;
|
|
46
|
+
success: boolean;
|
|
47
|
+
durationMs?: number;
|
|
48
|
+
source: string;
|
|
49
|
+
}): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Lightweight experience-to-pattern consolidation.
|
|
52
|
+
* Aggregates captured_experiences by domain+agent, and for clusters that meet
|
|
53
|
+
* quality thresholds, creates new qe_patterns entries.
|
|
54
|
+
* Called at session-end so patterns grow with each session.
|
|
55
|
+
*/
|
|
56
|
+
export declare function consolidateExperiencesToPatterns(): Promise<number>;
|
|
57
|
+
//# sourceMappingURL=hooks-dream-learning.d.ts.map
|