agentic-qe 3.7.18 → 3.7.20
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/iterative-loop/SKILL.md +371 -0
- package/.claude/skills/skills-manifest.json +36 -8
- package/.claude/skills/validation-pipeline/SKILL.md +164 -0
- package/.claude/skills/validation-pipeline/evals/validation-pipeline.yaml +544 -0
- package/.claude/skills/validation-pipeline/schemas/output.json +193 -0
- package/.claude/skills/validation-pipeline/scripts/validate-config.json +34 -0
- package/CHANGELOG.md +7 -0
- package/README.md +5 -3
- package/assets/skills/skills-manifest.json +17 -1
- package/assets/skills/validation-pipeline/SKILL.md +164 -0
- package/assets/skills/validation-pipeline/evals/validation-pipeline.yaml +544 -0
- package/assets/skills/validation-pipeline/schemas/output.json +193 -0
- package/assets/skills/validation-pipeline/scripts/validate-config.json +34 -0
- package/dist/cli/bundle.js +9 -7
- package/dist/context/compiler.js +4 -0
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.js +2 -0
- package/dist/context/sources/defect-source.d.ts +17 -0
- package/dist/context/sources/defect-source.js +102 -0
- package/dist/context/sources/index.d.ts +2 -0
- package/dist/context/sources/index.js +2 -0
- package/dist/context/sources/requirements-source.d.ts +17 -0
- package/dist/context/sources/requirements-source.js +119 -0
- package/dist/coordination/task-executor.js +7 -1
- package/dist/coordination/yaml-pipeline-loader.d.ts +32 -0
- package/dist/coordination/yaml-pipeline-loader.js +389 -0
- package/dist/coordination/yaml-pipeline-registry.d.ts +61 -0
- package/dist/coordination/yaml-pipeline-registry.js +143 -0
- package/dist/governance/continue-gate-integration.js +1 -1
- package/dist/governance/feature-flags.js +2 -2
- package/dist/init/settings-merge.js +2 -0
- package/dist/mcp/bundle.js +8674 -1248
- package/dist/mcp/entry.js +21 -0
- package/dist/mcp/handlers/domain-handler-configs.js +11 -0
- package/dist/mcp/handlers/index.d.ts +2 -0
- package/dist/mcp/handlers/index.js +4 -0
- package/dist/mcp/handlers/pipeline-handlers.d.ts +75 -0
- package/dist/mcp/handlers/pipeline-handlers.js +208 -0
- package/dist/mcp/handlers/validation-pipeline-handler.d.ts +53 -0
- package/dist/mcp/handlers/validation-pipeline-handler.js +118 -0
- package/dist/mcp/protocol-server.js +167 -1
- package/dist/mcp/server.js +75 -1
- package/dist/workers/daemon.js +3 -2
- package/dist/workers/index.d.ts +6 -0
- package/dist/workers/index.js +6 -0
- package/dist/workers/workers/heartbeat-scheduler.d.ts +45 -0
- package/dist/workers/workers/heartbeat-scheduler.js +312 -0
- package/dist/workers/workers/index.d.ts +2 -1
- package/dist/workers/workers/index.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://agentic-qe.dev/schemas/validation-pipeline-output.json",
|
|
4
|
+
"title": "AQE Validation Pipeline Skill Output Schema",
|
|
5
|
+
"description": "Schema for validation pipeline skill output. Includes step results, scores, findings, and blockers.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["skillName", "version", "timestamp", "status", "trustTier", "output"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"skillName": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"const": "validation-pipeline",
|
|
12
|
+
"description": "Must be 'validation-pipeline'"
|
|
13
|
+
},
|
|
14
|
+
"version": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9]+)?$"
|
|
17
|
+
},
|
|
18
|
+
"timestamp": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"format": "date-time"
|
|
21
|
+
},
|
|
22
|
+
"status": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["success", "partial", "failed", "skipped"]
|
|
25
|
+
},
|
|
26
|
+
"trustTier": {
|
|
27
|
+
"type": "integer",
|
|
28
|
+
"const": 3,
|
|
29
|
+
"description": "Trust tier 3 indicates full validation with eval suite"
|
|
30
|
+
},
|
|
31
|
+
"output": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"required": ["pipelineId", "pipelineName", "overall", "score", "steps"],
|
|
34
|
+
"properties": {
|
|
35
|
+
"pipelineId": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Pipeline identifier"
|
|
38
|
+
},
|
|
39
|
+
"pipelineName": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Human-readable pipeline name"
|
|
42
|
+
},
|
|
43
|
+
"overall": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"enum": ["pass", "fail", "warn"],
|
|
46
|
+
"description": "Overall pipeline verdict"
|
|
47
|
+
},
|
|
48
|
+
"score": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"minimum": 0,
|
|
51
|
+
"maximum": 100,
|
|
52
|
+
"description": "Weighted average score across all steps"
|
|
53
|
+
},
|
|
54
|
+
"steps": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": { "$ref": "#/$defs/stepResult" },
|
|
57
|
+
"minItems": 1,
|
|
58
|
+
"description": "Per-step results"
|
|
59
|
+
},
|
|
60
|
+
"blockers": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": { "$ref": "#/$defs/finding" },
|
|
63
|
+
"description": "Findings from blocking steps that failed"
|
|
64
|
+
},
|
|
65
|
+
"halted": {
|
|
66
|
+
"type": "boolean",
|
|
67
|
+
"description": "Whether pipeline halted early"
|
|
68
|
+
},
|
|
69
|
+
"haltedAt": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"description": "Step ID where pipeline halted"
|
|
72
|
+
},
|
|
73
|
+
"totalDuration": {
|
|
74
|
+
"type": "integer",
|
|
75
|
+
"minimum": 0,
|
|
76
|
+
"description": "Total execution time in ms"
|
|
77
|
+
},
|
|
78
|
+
"summary": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"minLength": 20,
|
|
81
|
+
"maxLength": 2000,
|
|
82
|
+
"description": "Human-readable summary"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"metadata": { "$ref": "#/$defs/metadata" },
|
|
87
|
+
"validation": { "$ref": "#/$defs/validationResult" },
|
|
88
|
+
"learning": { "$ref": "#/$defs/learningData" }
|
|
89
|
+
},
|
|
90
|
+
"$defs": {
|
|
91
|
+
"stepResult": {
|
|
92
|
+
"type": "object",
|
|
93
|
+
"required": ["stepId", "stepName", "status", "score", "findings", "evidence", "duration"],
|
|
94
|
+
"properties": {
|
|
95
|
+
"stepId": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"description": "Step identifier"
|
|
98
|
+
},
|
|
99
|
+
"stepName": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"description": "Human-readable step name"
|
|
102
|
+
},
|
|
103
|
+
"status": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"enum": ["pass", "fail", "warn", "skip"],
|
|
106
|
+
"description": "Step verdict"
|
|
107
|
+
},
|
|
108
|
+
"score": {
|
|
109
|
+
"type": "integer",
|
|
110
|
+
"minimum": 0,
|
|
111
|
+
"maximum": 100,
|
|
112
|
+
"description": "Step score"
|
|
113
|
+
},
|
|
114
|
+
"findings": {
|
|
115
|
+
"type": "array",
|
|
116
|
+
"items": { "$ref": "#/$defs/finding" }
|
|
117
|
+
},
|
|
118
|
+
"evidence": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": { "type": "string" },
|
|
121
|
+
"description": "What was checked"
|
|
122
|
+
},
|
|
123
|
+
"duration": {
|
|
124
|
+
"type": "integer",
|
|
125
|
+
"minimum": 0,
|
|
126
|
+
"description": "Step duration in ms"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"finding": {
|
|
131
|
+
"type": "object",
|
|
132
|
+
"required": ["id", "stepId", "severity", "title", "description"],
|
|
133
|
+
"properties": {
|
|
134
|
+
"id": {
|
|
135
|
+
"type": "string"
|
|
136
|
+
},
|
|
137
|
+
"stepId": {
|
|
138
|
+
"type": "string"
|
|
139
|
+
},
|
|
140
|
+
"severity": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"enum": ["critical", "high", "medium", "low", "info"]
|
|
143
|
+
},
|
|
144
|
+
"title": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"minLength": 5,
|
|
147
|
+
"maxLength": 200
|
|
148
|
+
},
|
|
149
|
+
"description": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"maxLength": 2000
|
|
152
|
+
},
|
|
153
|
+
"location": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": "File path or document section"
|
|
156
|
+
},
|
|
157
|
+
"suggestion": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"description": "Suggested fix"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"metadata": {
|
|
164
|
+
"type": "object",
|
|
165
|
+
"properties": {
|
|
166
|
+
"executionTimeMs": { "type": "integer", "minimum": 0 },
|
|
167
|
+
"toolsUsed": { "type": "array", "items": { "type": "string" } },
|
|
168
|
+
"agentId": { "type": "string" },
|
|
169
|
+
"pipelineType": { "type": "string" },
|
|
170
|
+
"targetFile": { "type": "string" },
|
|
171
|
+
"stepsExecuted": { "type": "integer", "minimum": 0 },
|
|
172
|
+
"stepsSkipped": { "type": "integer", "minimum": 0 }
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"validationResult": {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"properties": {
|
|
178
|
+
"schemaValid": { "type": "boolean" },
|
|
179
|
+
"contentValid": { "type": "boolean" },
|
|
180
|
+
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
181
|
+
"warnings": { "type": "array", "items": { "type": "string" }, "maxItems": 20 },
|
|
182
|
+
"errors": { "type": "array", "items": { "type": "string" }, "maxItems": 20 }
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"learningData": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"properties": {
|
|
188
|
+
"patternsDetected": { "type": "array", "items": { "type": "string" }, "maxItems": 20 },
|
|
189
|
+
"reward": { "type": "number", "minimum": 0, "maximum": 1 }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skillName": "validation-pipeline",
|
|
3
|
+
"skillVersion": "1.0.0",
|
|
4
|
+
"requiredTools": [],
|
|
5
|
+
"optionalTools": ["jq"],
|
|
6
|
+
"schemaPath": "schemas/output.json",
|
|
7
|
+
"requiredFields": [
|
|
8
|
+
"skillName",
|
|
9
|
+
"status",
|
|
10
|
+
"output",
|
|
11
|
+
"output.pipelineId",
|
|
12
|
+
"output.pipelineName",
|
|
13
|
+
"output.overall",
|
|
14
|
+
"output.score",
|
|
15
|
+
"output.steps"
|
|
16
|
+
],
|
|
17
|
+
"requiredNonEmptyFields": [
|
|
18
|
+
"output.pipelineName",
|
|
19
|
+
"output.steps"
|
|
20
|
+
],
|
|
21
|
+
"mustContainTerms": [
|
|
22
|
+
"pipeline",
|
|
23
|
+
"validation"
|
|
24
|
+
],
|
|
25
|
+
"mustNotContainTerms": [
|
|
26
|
+
"TODO",
|
|
27
|
+
"placeholder",
|
|
28
|
+
"FIXME"
|
|
29
|
+
],
|
|
30
|
+
"enumValidations": {
|
|
31
|
+
".status": ["success", "partial", "failed", "skipped"],
|
|
32
|
+
".output.overall": ["pass", "fail", "warn"]
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/cli/bundle.js
CHANGED
|
@@ -49930,8 +49930,8 @@ var DEFAULT_GOVERNANCE_FLAGS = {
|
|
|
49930
49930
|
enabled: true,
|
|
49931
49931
|
maxConsecutiveRetries: 3,
|
|
49932
49932
|
reworkRatioThreshold: 0.5,
|
|
49933
|
-
idleTimeoutMs:
|
|
49934
|
-
//
|
|
49933
|
+
idleTimeoutMs: 15 * 60 * 1e3,
|
|
49934
|
+
// 15 minutes
|
|
49935
49935
|
throttleOnExceed: true
|
|
49936
49936
|
},
|
|
49937
49937
|
memoryWriteGate: {
|
|
@@ -50066,7 +50066,7 @@ function loadFlagsFromEnv() {
|
|
|
50066
50066
|
enabled: env.GOVERNANCE_CONTINUE_GATE !== "false",
|
|
50067
50067
|
maxConsecutiveRetries: parseInt(env.GOVERNANCE_MAX_RETRIES || "3", 10),
|
|
50068
50068
|
reworkRatioThreshold: parseFloat(env.GOVERNANCE_REWORK_THRESHOLD || "0.5"),
|
|
50069
|
-
idleTimeoutMs: parseInt(env.GOVERNANCE_IDLE_TIMEOUT || "
|
|
50069
|
+
idleTimeoutMs: parseInt(env.GOVERNANCE_IDLE_TIMEOUT || "900000", 10),
|
|
50070
50070
|
throttleOnExceed: env.GOVERNANCE_THROTTLE !== "false"
|
|
50071
50071
|
},
|
|
50072
50072
|
memoryWriteGate: {
|
|
@@ -50390,7 +50390,7 @@ var ContinueGateIntegration = class _ContinueGateIntegration {
|
|
|
50390
50390
|
budgetRemaining: {
|
|
50391
50391
|
tokens: Math.max(0, flags.maxConsecutiveRetries * 10 * 500 - history.length * 500),
|
|
50392
50392
|
toolCalls: Math.max(0, flags.maxConsecutiveRetries * 10 - history.length),
|
|
50393
|
-
timeMs: Math.max(0, flags.idleTimeoutMs - (history.length > 0 ? Date.now() - history[
|
|
50393
|
+
timeMs: Math.max(0, flags.idleTimeoutMs - (history.length > 0 ? Date.now() - history[history.length - 1].timestamp : 0))
|
|
50394
50394
|
},
|
|
50395
50395
|
recentDecisions: []
|
|
50396
50396
|
};
|
|
@@ -135299,7 +135299,7 @@ var ALL_DOMAINS2 = [
|
|
|
135299
135299
|
"enterprise-integration"
|
|
135300
135300
|
];
|
|
135301
135301
|
function getAQEVersion() {
|
|
135302
|
-
return true ? "3.7.
|
|
135302
|
+
return true ? "3.7.20" : "3.0.0";
|
|
135303
135303
|
}
|
|
135304
135304
|
function createDefaultConfig(projectName, projectRoot) {
|
|
135305
135305
|
return {
|
|
@@ -136509,7 +136509,9 @@ var AQE_COMMAND_PATTERNS = [
|
|
|
136509
136509
|
/\baqe\b/i,
|
|
136510
136510
|
/\bagentic-qe\b/i,
|
|
136511
136511
|
/\bnpx\s+agentic-qe\b/i,
|
|
136512
|
-
/\bnpx\s+@anthropics\/agentic-qe\b/i
|
|
136512
|
+
/\bnpx\s+@anthropics\/agentic-qe\b/i,
|
|
136513
|
+
/brain-checkpoint\.cjs/i,
|
|
136514
|
+
/\.claude\/helpers\//i
|
|
136513
136515
|
];
|
|
136514
136516
|
function isAqeHookEntry(entry) {
|
|
136515
136517
|
const hookEntry = entry;
|
|
@@ -166104,7 +166106,7 @@ async function cleanupAndExit(code = 0) {
|
|
|
166104
166106
|
process.exit(code);
|
|
166105
166107
|
}
|
|
166106
166108
|
var program = new Command21();
|
|
166107
|
-
var VERSION = true ? "3.7.
|
|
166109
|
+
var VERSION = true ? "3.7.20" : "0.0.0-dev";
|
|
166108
166110
|
program.name("aqe").description("Agentic QE - Domain-Driven Quality Engineering").version(VERSION);
|
|
166109
166111
|
var registry2 = createCommandRegistry(context, cleanupAndExit, ensureInitialized, ensureInitializedStrict);
|
|
166110
166112
|
registry2.registerAll(program);
|
package/dist/context/compiler.js
CHANGED
|
@@ -8,6 +8,8 @@ import { MemoryContextSource } from './sources/memory-source.js';
|
|
|
8
8
|
import { GitContextSource } from './sources/git-source.js';
|
|
9
9
|
import { TestContextSource } from './sources/test-source.js';
|
|
10
10
|
import { CoverageContextSource } from './sources/coverage-source.js';
|
|
11
|
+
import { RequirementsContextSource } from './sources/requirements-source.js';
|
|
12
|
+
import { DefectContextSource } from './sources/defect-source.js';
|
|
11
13
|
const DEFAULT_TOKEN_BUDGET = 8000;
|
|
12
14
|
const DEFAULT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
13
15
|
/**
|
|
@@ -16,7 +18,9 @@ const DEFAULT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
|
16
18
|
export function createDefaultSources() {
|
|
17
19
|
return [
|
|
18
20
|
new MemoryContextSource(),
|
|
21
|
+
new RequirementsContextSource(),
|
|
19
22
|
new TestContextSource(),
|
|
23
|
+
new DefectContextSource(),
|
|
20
24
|
new GitContextSource(),
|
|
21
25
|
new CoverageContextSource(),
|
|
22
26
|
];
|
package/dist/context/index.d.ts
CHANGED
|
@@ -5,4 +5,6 @@ export { MemoryContextSource } from './sources/memory-source.js';
|
|
|
5
5
|
export { GitContextSource } from './sources/git-source.js';
|
|
6
6
|
export { TestContextSource } from './sources/test-source.js';
|
|
7
7
|
export { CoverageContextSource } from './sources/coverage-source.js';
|
|
8
|
+
export { RequirementsContextSource } from './sources/requirements-source.js';
|
|
9
|
+
export { DefectContextSource } from './sources/defect-source.js';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/context/index.js
CHANGED
|
@@ -3,4 +3,6 @@ export { MemoryContextSource } from './sources/memory-source.js';
|
|
|
3
3
|
export { GitContextSource } from './sources/git-source.js';
|
|
4
4
|
export { TestContextSource } from './sources/test-source.js';
|
|
5
5
|
export { CoverageContextSource } from './sources/coverage-source.js';
|
|
6
|
+
export { RequirementsContextSource } from './sources/requirements-source.js';
|
|
7
|
+
export { DefectContextSource } from './sources/defect-source.js';
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defect Source - Historical defect patterns for target files
|
|
3
|
+
*
|
|
4
|
+
* Queries the learning database for defect intelligence data,
|
|
5
|
+
* providing historical bug patterns and regression hotspots
|
|
6
|
+
* relevant to the files under analysis.
|
|
7
|
+
*/
|
|
8
|
+
import type { ContextSource, ContextRequest, ContextFragment } from './types.js';
|
|
9
|
+
export declare class DefectContextSource implements ContextSource {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
priority: number;
|
|
13
|
+
maxTokens: number;
|
|
14
|
+
gather(request: ContextRequest): Promise<ContextFragment[]>;
|
|
15
|
+
private extractDefectKeywords;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=defect-source.d.ts.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defect Source - Historical defect patterns for target files
|
|
3
|
+
*
|
|
4
|
+
* Queries the learning database for defect intelligence data,
|
|
5
|
+
* providing historical bug patterns and regression hotspots
|
|
6
|
+
* relevant to the files under analysis.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
export class DefectContextSource {
|
|
11
|
+
id = 'defects';
|
|
12
|
+
name = 'Defect Intelligence';
|
|
13
|
+
priority = 65;
|
|
14
|
+
maxTokens = 1500;
|
|
15
|
+
async gather(request) {
|
|
16
|
+
const fragments = [];
|
|
17
|
+
try {
|
|
18
|
+
const dbPath = join(process.cwd(), '.agentic-qe', 'memory.db');
|
|
19
|
+
if (!existsSync(dbPath)) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
const Database = (await import('better-sqlite3')).default;
|
|
23
|
+
const db = new Database(dbPath, { readonly: true });
|
|
24
|
+
try {
|
|
25
|
+
// Check if patterns table exists
|
|
26
|
+
const tableCheck = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='qe_patterns'").get();
|
|
27
|
+
if (!tableCheck) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
// Query defect patterns related to target files
|
|
31
|
+
const filePatterns = request.targetFiles.map(f => `%${f.split('/').pop()}%`);
|
|
32
|
+
if (filePatterns.length > 0) {
|
|
33
|
+
const placeholders = filePatterns.map(() => 'description LIKE ?').join(' OR ');
|
|
34
|
+
const stmt = db.prepare(`SELECT name, domain, description, confidence
|
|
35
|
+
FROM qe_patterns
|
|
36
|
+
WHERE domain LIKE '%defect%'
|
|
37
|
+
AND (${placeholders})
|
|
38
|
+
ORDER BY confidence DESC
|
|
39
|
+
LIMIT 8`);
|
|
40
|
+
const defects = stmt.all(...filePatterns);
|
|
41
|
+
if (defects.length > 0) {
|
|
42
|
+
const content = defects.map(d => `- **${d.name}** (confidence: ${(d.confidence * 100).toFixed(0)}%): ${d.description || 'No description'}`).join('\n');
|
|
43
|
+
fragments.push({
|
|
44
|
+
sourceId: this.id,
|
|
45
|
+
title: 'Historical Defect Patterns',
|
|
46
|
+
content: `Found ${defects.length} defect patterns for target files:\n\n${content}`,
|
|
47
|
+
estimatedTokens: Math.ceil(content.length / 3.5),
|
|
48
|
+
relevance: 0.7,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Query regression hotspots based on task description
|
|
53
|
+
const regressionKeywords = this.extractDefectKeywords(request.taskDescription);
|
|
54
|
+
if (regressionKeywords.length > 0) {
|
|
55
|
+
const kwPlaceholders = regressionKeywords.map(() => 'description LIKE ?').join(' OR ');
|
|
56
|
+
const kwPatterns = regressionKeywords.map(k => `%${k}%`);
|
|
57
|
+
const stmt = db.prepare(`SELECT name, domain, description, confidence
|
|
58
|
+
FROM qe_patterns
|
|
59
|
+
WHERE (domain LIKE '%defect%' OR domain LIKE '%regression%')
|
|
60
|
+
AND (${kwPlaceholders})
|
|
61
|
+
ORDER BY confidence DESC
|
|
62
|
+
LIMIT 5`);
|
|
63
|
+
const regressions = stmt.all(...kwPatterns);
|
|
64
|
+
if (regressions.length > 0) {
|
|
65
|
+
const content = regressions.map(r => `- **${r.name}**: ${r.description || 'No description'}`).join('\n');
|
|
66
|
+
fragments.push({
|
|
67
|
+
sourceId: this.id,
|
|
68
|
+
title: 'Regression Hotspots',
|
|
69
|
+
content: `Known regression patterns:\n\n${content}`,
|
|
70
|
+
estimatedTokens: Math.ceil(content.length / 3.5),
|
|
71
|
+
relevance: 0.6,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
db.close();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Database access failed — return empty (defect context is optional)
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
return fragments;
|
|
85
|
+
}
|
|
86
|
+
extractDefectKeywords(description) {
|
|
87
|
+
const keywords = [];
|
|
88
|
+
const desc = description.toLowerCase();
|
|
89
|
+
const defectTerms = [
|
|
90
|
+
'bug', 'defect', 'regression', 'fix', 'crash', 'error',
|
|
91
|
+
'null', 'undefined', 'timeout', 'race condition', 'deadlock',
|
|
92
|
+
'memory leak', 'overflow', 'injection', 'broken',
|
|
93
|
+
];
|
|
94
|
+
for (const term of defectTerms) {
|
|
95
|
+
if (desc.includes(term)) {
|
|
96
|
+
keywords.push(term);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return keywords.slice(0, 5);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=defect-source.js.map
|
|
@@ -3,4 +3,6 @@ export { MemoryContextSource } from './memory-source.js';
|
|
|
3
3
|
export { GitContextSource } from './git-source.js';
|
|
4
4
|
export { TestContextSource } from './test-source.js';
|
|
5
5
|
export { CoverageContextSource } from './coverage-source.js';
|
|
6
|
+
export { RequirementsContextSource } from './requirements-source.js';
|
|
7
|
+
export { DefectContextSource } from './defect-source.js';
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,4 +2,6 @@ export { MemoryContextSource } from './memory-source.js';
|
|
|
2
2
|
export { GitContextSource } from './git-source.js';
|
|
3
3
|
export { TestContextSource } from './test-source.js';
|
|
4
4
|
export { CoverageContextSource } from './coverage-source.js';
|
|
5
|
+
export { RequirementsContextSource } from './requirements-source.js';
|
|
6
|
+
export { DefectContextSource } from './defect-source.js';
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements Source - Linked requirements for target files
|
|
3
|
+
*
|
|
4
|
+
* Queries the learning database for requirements traceability data,
|
|
5
|
+
* mapping target files to their associated requirements and acceptance criteria.
|
|
6
|
+
*/
|
|
7
|
+
import type { ContextSource, ContextRequest, ContextFragment } from './types.js';
|
|
8
|
+
export declare class RequirementsContextSource implements ContextSource {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
priority: number;
|
|
12
|
+
maxTokens: number;
|
|
13
|
+
gather(request: ContextRequest): Promise<ContextFragment[]>;
|
|
14
|
+
private fallbackGather;
|
|
15
|
+
private extractRequirementKeywords;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=requirements-source.d.ts.map
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements Source - Linked requirements for target files
|
|
3
|
+
*
|
|
4
|
+
* Queries the learning database for requirements traceability data,
|
|
5
|
+
* mapping target files to their associated requirements and acceptance criteria.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
export class RequirementsContextSource {
|
|
10
|
+
id = 'requirements';
|
|
11
|
+
name = 'Requirements Traceability';
|
|
12
|
+
priority = 75;
|
|
13
|
+
maxTokens = 2000;
|
|
14
|
+
async gather(request) {
|
|
15
|
+
const fragments = [];
|
|
16
|
+
try {
|
|
17
|
+
const dbPath = join(process.cwd(), '.agentic-qe', 'memory.db');
|
|
18
|
+
if (!existsSync(dbPath)) {
|
|
19
|
+
return this.fallbackGather(request);
|
|
20
|
+
}
|
|
21
|
+
const Database = (await import('better-sqlite3')).default;
|
|
22
|
+
const db = new Database(dbPath, { readonly: true });
|
|
23
|
+
try {
|
|
24
|
+
// Check if requirements table exists
|
|
25
|
+
const tableCheck = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='qe_patterns'").get();
|
|
26
|
+
if (!tableCheck) {
|
|
27
|
+
return this.fallbackGather(request);
|
|
28
|
+
}
|
|
29
|
+
// Query patterns in the requirements domain linked to target files
|
|
30
|
+
const filePatterns = request.targetFiles.map(f => `%${f.split('/').pop()}%`);
|
|
31
|
+
if (filePatterns.length > 0) {
|
|
32
|
+
const placeholders = filePatterns.map(() => 'description LIKE ?').join(' OR ');
|
|
33
|
+
const stmt = db.prepare(`SELECT name, domain, description, confidence
|
|
34
|
+
FROM qe_patterns
|
|
35
|
+
WHERE domain LIKE '%requirement%'
|
|
36
|
+
AND (${placeholders})
|
|
37
|
+
ORDER BY confidence DESC
|
|
38
|
+
LIMIT 10`);
|
|
39
|
+
const requirements = stmt.all(...filePatterns);
|
|
40
|
+
if (requirements.length > 0) {
|
|
41
|
+
const content = requirements.map(r => `- **${r.name}** (confidence: ${(r.confidence * 100).toFixed(0)}%): ${r.description || 'No description'}`).join('\n');
|
|
42
|
+
fragments.push({
|
|
43
|
+
sourceId: this.id,
|
|
44
|
+
title: 'Linked Requirements',
|
|
45
|
+
content: `Found ${requirements.length} requirements linked to target files:\n\n${content}`,
|
|
46
|
+
estimatedTokens: Math.ceil(content.length / 3.5),
|
|
47
|
+
relevance: 0.75,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Also search by task description keywords for broader requirement context
|
|
52
|
+
const keywords = this.extractRequirementKeywords(request.taskDescription);
|
|
53
|
+
if (keywords.length > 0) {
|
|
54
|
+
const kwPlaceholders = keywords.map(() => 'name LIKE ? OR description LIKE ?').join(' OR ');
|
|
55
|
+
const kwPatterns = keywords.flatMap(k => [`%${k}%`, `%${k}%`]);
|
|
56
|
+
const stmt = db.prepare(`SELECT DISTINCT name, domain, description, confidence
|
|
57
|
+
FROM qe_patterns
|
|
58
|
+
WHERE domain LIKE '%requirement%'
|
|
59
|
+
AND (${kwPlaceholders})
|
|
60
|
+
ORDER BY confidence DESC
|
|
61
|
+
LIMIT 5`);
|
|
62
|
+
const related = stmt.all(...kwPatterns);
|
|
63
|
+
if (related.length > 0) {
|
|
64
|
+
const content = related.map(r => `- **${r.name}**: ${r.description || 'No description'}`).join('\n');
|
|
65
|
+
fragments.push({
|
|
66
|
+
sourceId: this.id,
|
|
67
|
+
title: 'Related Requirements',
|
|
68
|
+
content: `Requirements related to task:\n\n${content}`,
|
|
69
|
+
estimatedTokens: Math.ceil(content.length / 3.5),
|
|
70
|
+
relevance: 0.6,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
db.close();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return this.fallbackGather(request);
|
|
81
|
+
}
|
|
82
|
+
if (fragments.length === 0) {
|
|
83
|
+
return this.fallbackGather(request);
|
|
84
|
+
}
|
|
85
|
+
return fragments;
|
|
86
|
+
}
|
|
87
|
+
fallbackGather(request) {
|
|
88
|
+
// Provide basic file-to-requirement mapping hint
|
|
89
|
+
const fileList = request.targetFiles.join(', ');
|
|
90
|
+
const content = `No requirements traceability data found for: ${fileList}. Consider running requirements validation to establish traceability.`;
|
|
91
|
+
return [{
|
|
92
|
+
sourceId: this.id,
|
|
93
|
+
title: 'Requirements Context',
|
|
94
|
+
content,
|
|
95
|
+
estimatedTokens: Math.ceil(content.length / 3.5),
|
|
96
|
+
relevance: 0.3,
|
|
97
|
+
}];
|
|
98
|
+
}
|
|
99
|
+
extractRequirementKeywords(description) {
|
|
100
|
+
const keywords = [];
|
|
101
|
+
const desc = description.toLowerCase();
|
|
102
|
+
// Extract requirement-like identifiers (REQ-001, US-123, etc.)
|
|
103
|
+
const reqIds = desc.match(/(?:req|us|story|epic|feat)-?\d+/gi) || [];
|
|
104
|
+
keywords.push(...reqIds);
|
|
105
|
+
// Extract domain terms relevant to requirements
|
|
106
|
+
const domainTerms = [
|
|
107
|
+
'authentication', 'authorization', 'payment', 'registration',
|
|
108
|
+
'notification', 'search', 'api', 'login', 'user', 'admin',
|
|
109
|
+
'report', 'dashboard', 'import', 'export', 'integration',
|
|
110
|
+
];
|
|
111
|
+
for (const term of domainTerms) {
|
|
112
|
+
if (desc.includes(term)) {
|
|
113
|
+
keywords.push(term);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return keywords.slice(0, 5); // Cap at 5 keywords
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=requirements-source.js.map
|
|
@@ -324,9 +324,15 @@ export class DomainTaskExecutor {
|
|
|
324
324
|
const payload = task.payload;
|
|
325
325
|
const routingTier = payload?.routingTier ?? 2;
|
|
326
326
|
const useAgentBooster = payload?.useAgentBooster ?? false;
|
|
327
|
+
const compiledContext = payload?.compiledContext ?? undefined;
|
|
327
328
|
const modelId = getModelForTier(routingTier);
|
|
329
|
+
// BMAD-005: Attach compiled context to task metadata for domain handlers
|
|
330
|
+
if (compiledContext && task.payload) {
|
|
331
|
+
task.payload.__compiledContext = compiledContext;
|
|
332
|
+
}
|
|
328
333
|
console.debug(`[TaskExecutor] Executing task ${task.id}: type=${task.type}, ` +
|
|
329
|
-
`tier=${routingTier}, model=${modelId}, useAgentBooster=${useAgentBooster}`
|
|
334
|
+
`tier=${routingTier}, model=${modelId}, useAgentBooster=${useAgentBooster}` +
|
|
335
|
+
`${compiledContext ? ', hasContext=true' : ''}`);
|
|
330
336
|
try {
|
|
331
337
|
// ADR-051: Tier 0 - Try Agent Booster for mechanical transforms
|
|
332
338
|
if (routingTier === 0 || useAgentBooster) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML Pipeline Loader (Imp-9)
|
|
3
|
+
*
|
|
4
|
+
* Converts declarative YAML files into WorkflowDefinition objects for
|
|
5
|
+
* deterministic, token-free execution through the WorkflowOrchestrator.
|
|
6
|
+
* Supports ${VAR} variable interpolation and schema validation.
|
|
7
|
+
*/
|
|
8
|
+
import { Result } from '../shared/types/index.js';
|
|
9
|
+
import type { WorkflowDefinition } from './workflow-types.js';
|
|
10
|
+
export declare class YamlPipelineLoader {
|
|
11
|
+
/** Parse a YAML string into a WorkflowDefinition with optional variable interpolation. */
|
|
12
|
+
parse(yaml: string, vars?: Record<string, unknown>): Result<WorkflowDefinition, Error>;
|
|
13
|
+
/** Load a WorkflowDefinition from a YAML file on disk. */
|
|
14
|
+
loadFromFile(filePath: string, vars?: Record<string, unknown>): Promise<Result<WorkflowDefinition, Error>>;
|
|
15
|
+
/** Interpolate ${VAR} placeholders. Supports flat and dot-path keys. */
|
|
16
|
+
interpolateVariables(yaml: string, vars: Record<string, unknown>): string;
|
|
17
|
+
/** Validate a raw parsed object against the WorkflowDefinition schema. */
|
|
18
|
+
validateSchema(parsed: unknown): Result<WorkflowDefinition, Error>;
|
|
19
|
+
private validateAndConvert;
|
|
20
|
+
private validateSteps;
|
|
21
|
+
private validateCondition;
|
|
22
|
+
private validateTriggers;
|
|
23
|
+
private validateRetry;
|
|
24
|
+
private validateRollback;
|
|
25
|
+
/** Validate that a value is Record<string, string>, undefined, or return an Error. */
|
|
26
|
+
private validateStringRecord;
|
|
27
|
+
/** Resolve a dot-path variable (e.g. "foo.bar") from a variables map. */
|
|
28
|
+
private resolveVarPath;
|
|
29
|
+
/** Detect circular dependencies. Returns a cycle description or null. */
|
|
30
|
+
private detectCircularDependencies;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=yaml-pipeline-loader.d.ts.map
|