agentic-qe 3.8.5 → 3.8.7
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 +26 -0
- package/assets/governance/constitution.md +1 -1
- package/assets/governance/shards/chaos-resilience.shard.md +1 -1
- package/assets/governance/shards/code-intelligence.shard.md +1 -1
- package/assets/governance/shards/contract-testing.shard.md +1 -1
- package/assets/governance/shards/coverage-analysis.shard.md +1 -1
- package/assets/governance/shards/defect-intelligence.shard.md +1 -1
- package/assets/governance/shards/learning-optimization.shard.md +1 -1
- package/assets/governance/shards/quality-assessment.shard.md +1 -1
- package/assets/governance/shards/requirements-validation.shard.md +1 -1
- package/assets/governance/shards/security-compliance.shard.md +1 -1
- package/assets/governance/shards/test-execution.shard.md +1 -1
- package/assets/governance/shards/test-generation.shard.md +1 -1
- package/assets/governance/shards/visual-accessibility.shard.md +1 -1
- package/dist/cli/bundle.js +715 -643
- package/dist/cli/command-registry.js +3 -1
- package/dist/cli/completions/index.d.ts +17 -0
- package/dist/cli/completions/index.js +49 -1
- package/dist/cli/handlers/hypergraph-handler.d.ts +27 -0
- package/dist/cli/handlers/hypergraph-handler.js +248 -0
- package/dist/cli/handlers/index.d.ts +1 -0
- package/dist/cli/handlers/index.js +1 -0
- 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/coordination/protocols/code-intelligence-index.js +2 -11
- package/dist/domains/code-intelligence/coordinator-hypergraph.js +1 -1
- package/dist/domains/code-intelligence/coordinator.d.ts +5 -0
- package/dist/domains/code-intelligence/coordinator.js +35 -3
- package/dist/init/phases/06-code-intelligence.d.ts +8 -3
- package/dist/init/phases/06-code-intelligence.js +70 -32
- 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 +1084 -1083
- package/dist/mcp/handlers/hypergraph-handler.d.ts +27 -0
- package/dist/mcp/handlers/hypergraph-handler.js +140 -0
- package/dist/mcp/handlers/index.d.ts +1 -0
- package/dist/mcp/handlers/index.js +2 -0
- package/dist/mcp/server.js +19 -0
- package/dist/mcp/tool-scoping.js +5 -0
- package/dist/shared/code-index-extractor.d.ts +23 -0
- package/dist/shared/code-index-extractor.js +101 -0
- package/dist/shared/security/command-validator.js +2 -2
- package/dist/shared/security/input-sanitizer.js +1 -1
- package/dist/shared/security/path-traversal-validator.js +1 -1
- package/dist/shared/security/regex-safety-validator.js +7 -7
- package/package.json +1 -1
|
@@ -17,28 +17,17 @@ import { LoggerFactory } from '../logging/index.js';
|
|
|
17
17
|
const logger = LoggerFactory.create('QEReasoningBank');
|
|
18
18
|
import { ok, err } from '../shared/types/index.js';
|
|
19
19
|
import { toError, toErrorMessage } from '../shared/error-utils.js';
|
|
20
|
-
import { detectQEDomains, QE_DOMAIN_LIST,
|
|
20
|
+
import { detectQEDomains, QE_DOMAIN_LIST, } from './qe-patterns.js';
|
|
21
21
|
import { getGuidance, getCombinedGuidance, generateGuidanceContext, checkAntiPatterns, } from './qe-guidance.js';
|
|
22
22
|
import { createPatternStore, } from './pattern-store.js';
|
|
23
23
|
import { createSQLitePatternStore, } from './sqlite-persistence.js';
|
|
24
24
|
import { getWitnessChain } from '../audit/witness-chain.js';
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
enableRouting: true,
|
|
32
|
-
embeddingDimension: 384, // Native all-MiniLM-L6-v2 dimension — no interpolation needed
|
|
33
|
-
useONNXEmbeddings: true, // ADR-051: Enable ONNX embeddings by default
|
|
34
|
-
maxRoutingCandidates: 10,
|
|
35
|
-
routingWeights: {
|
|
36
|
-
similarity: 0.3,
|
|
37
|
-
performance: 0.4,
|
|
38
|
-
capabilities: 0.3,
|
|
39
|
-
},
|
|
40
|
-
coherenceThreshold: 0.4, // ADR-052: Coherence gate threshold
|
|
41
|
-
};
|
|
25
|
+
// Import extracted modules
|
|
26
|
+
import { DEFAULT_QE_REASONING_BANK_CONFIG } from './qe-reasoning-bank-types.js';
|
|
27
|
+
import { PRETRAINED_PATTERNS } from './pretrained-patterns.js';
|
|
28
|
+
import { AGENT_CAPABILITIES, calculateAgentScores, } from './agent-routing.js';
|
|
29
|
+
import { resizeEmbedding, hashEmbedding } from './embedding-utils.js';
|
|
30
|
+
import { checkPatternPromotionWithCoherence, promotePattern as promotePatternFn, seedCrossDomainPatterns as seedCrossDomainPatternsFn, } from './pattern-promotion.js';
|
|
42
31
|
// ============================================================================
|
|
43
32
|
// QEReasoningBank Implementation
|
|
44
33
|
// ============================================================================
|
|
@@ -103,64 +92,6 @@ export class QEReasoningBank {
|
|
|
103
92
|
learningOutcomes: 0,
|
|
104
93
|
successfulOutcomes: 0,
|
|
105
94
|
};
|
|
106
|
-
// Agent capability mapping (QE agents)
|
|
107
|
-
agentCapabilities = {
|
|
108
|
-
'qe-test-generator': {
|
|
109
|
-
domains: ['test-generation'],
|
|
110
|
-
capabilities: ['test-generation', 'tdd', 'bdd', 'unit-test', 'integration-test'],
|
|
111
|
-
performanceScore: 0.85,
|
|
112
|
-
},
|
|
113
|
-
'qe-coverage-analyzer': {
|
|
114
|
-
domains: ['coverage-analysis'],
|
|
115
|
-
capabilities: ['coverage-analysis', 'gap-detection', 'risk-scoring'],
|
|
116
|
-
performanceScore: 0.92,
|
|
117
|
-
},
|
|
118
|
-
'qe-coverage-specialist': {
|
|
119
|
-
domains: ['coverage-analysis'],
|
|
120
|
-
capabilities: ['sublinear-analysis', 'branch-coverage', 'mutation-testing'],
|
|
121
|
-
performanceScore: 0.88,
|
|
122
|
-
},
|
|
123
|
-
'qe-test-architect': {
|
|
124
|
-
domains: ['test-generation', 'coverage-analysis'],
|
|
125
|
-
capabilities: ['test-strategy', 'test-pyramid', 'architecture'],
|
|
126
|
-
performanceScore: 0.9,
|
|
127
|
-
},
|
|
128
|
-
'qe-api-contract-validator': {
|
|
129
|
-
domains: ['contract-testing'],
|
|
130
|
-
capabilities: ['contract-testing', 'openapi', 'graphql', 'pact'],
|
|
131
|
-
performanceScore: 0.87,
|
|
132
|
-
},
|
|
133
|
-
'qe-security-auditor': {
|
|
134
|
-
domains: ['security-compliance'],
|
|
135
|
-
capabilities: ['sast', 'dast', 'vulnerability', 'owasp'],
|
|
136
|
-
performanceScore: 0.82,
|
|
137
|
-
},
|
|
138
|
-
'qe-visual-tester': {
|
|
139
|
-
domains: ['visual-accessibility'],
|
|
140
|
-
capabilities: ['screenshot', 'visual-regression', 'percy', 'chromatic'],
|
|
141
|
-
performanceScore: 0.8,
|
|
142
|
-
},
|
|
143
|
-
'qe-a11y-ally': {
|
|
144
|
-
domains: ['visual-accessibility'],
|
|
145
|
-
capabilities: ['wcag', 'aria', 'screen-reader', 'contrast'],
|
|
146
|
-
performanceScore: 0.85,
|
|
147
|
-
},
|
|
148
|
-
'qe-performance-tester': {
|
|
149
|
-
domains: ['chaos-resilience'],
|
|
150
|
-
capabilities: ['load-testing', 'stress-testing', 'k6', 'artillery'],
|
|
151
|
-
performanceScore: 0.83,
|
|
152
|
-
},
|
|
153
|
-
'qe-flaky-investigator': {
|
|
154
|
-
domains: ['test-execution'],
|
|
155
|
-
capabilities: ['flaky-detection', 'test-stability', 'retry'],
|
|
156
|
-
performanceScore: 0.78,
|
|
157
|
-
},
|
|
158
|
-
'qe-chaos-engineer': {
|
|
159
|
-
domains: ['chaos-resilience'],
|
|
160
|
-
capabilities: ['chaos-testing', 'resilience', 'fault-injection'],
|
|
161
|
-
performanceScore: 0.75,
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
95
|
constructor(memory, eventBus, config = {}, coherenceService) {
|
|
165
96
|
this.memory = memory;
|
|
166
97
|
this.eventBus = eventBus;
|
|
@@ -225,719 +156,8 @@ export class QEReasoningBank {
|
|
|
225
156
|
logger.info('Found existing patterns', { totalPatterns: stats.totalPatterns });
|
|
226
157
|
return;
|
|
227
158
|
}
|
|
228
|
-
// Add foundational patterns
|
|
229
|
-
const
|
|
230
|
-
{
|
|
231
|
-
patternType: 'test-template',
|
|
232
|
-
name: 'AAA Unit Test',
|
|
233
|
-
description: 'Arrange-Act-Assert pattern for clear, maintainable unit tests',
|
|
234
|
-
template: {
|
|
235
|
-
type: 'code',
|
|
236
|
-
content: `describe('{{className}}', () => {
|
|
237
|
-
describe('{{methodName}}', () => {
|
|
238
|
-
it('should {{expectedBehavior}}', {{async}} () => {
|
|
239
|
-
// Arrange
|
|
240
|
-
{{arrangeCode}}
|
|
241
|
-
|
|
242
|
-
// Act
|
|
243
|
-
{{actCode}}
|
|
244
|
-
|
|
245
|
-
// Assert
|
|
246
|
-
{{assertCode}}
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
});`,
|
|
250
|
-
variables: [
|
|
251
|
-
{ name: 'className', type: 'string', required: true, description: 'Class under test' },
|
|
252
|
-
{ name: 'methodName', type: 'string', required: true, description: 'Method under test' },
|
|
253
|
-
{ name: 'expectedBehavior', type: 'string', required: true, description: 'Expected behavior in plain English' },
|
|
254
|
-
{ name: 'async', type: 'string', required: false, defaultValue: '', description: 'async keyword if needed' },
|
|
255
|
-
{ name: 'arrangeCode', type: 'code', required: true, description: 'Setup code' },
|
|
256
|
-
{ name: 'actCode', type: 'code', required: true, description: 'Action code' },
|
|
257
|
-
{ name: 'assertCode', type: 'code', required: true, description: 'Assertion code' },
|
|
258
|
-
],
|
|
259
|
-
},
|
|
260
|
-
context: {
|
|
261
|
-
testType: 'unit',
|
|
262
|
-
tags: ['unit-test', 'aaa', 'arrange-act-assert', 'best-practice'],
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
patternType: 'mock-pattern',
|
|
267
|
-
name: 'Dependency Mock',
|
|
268
|
-
description: 'Pattern for mocking external dependencies in tests',
|
|
269
|
-
template: {
|
|
270
|
-
type: 'code',
|
|
271
|
-
content: `const mock{{DependencyName}} = {
|
|
272
|
-
{{mockMethods}}
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
vi.mock('{{modulePath}}', () => ({
|
|
276
|
-
{{DependencyName}}: vi.fn(() => mock{{DependencyName}}),
|
|
277
|
-
}));`,
|
|
278
|
-
variables: [
|
|
279
|
-
{ name: 'DependencyName', type: 'string', required: true, description: 'Name of dependency to mock' },
|
|
280
|
-
{ name: 'modulePath', type: 'string', required: true, description: 'Module path to mock' },
|
|
281
|
-
{ name: 'mockMethods', type: 'code', required: true, description: 'Mock method implementations' },
|
|
282
|
-
],
|
|
283
|
-
},
|
|
284
|
-
context: {
|
|
285
|
-
framework: 'vitest',
|
|
286
|
-
testType: 'unit',
|
|
287
|
-
tags: ['mock', 'vitest', 'dependency-injection'],
|
|
288
|
-
},
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
patternType: 'coverage-strategy',
|
|
292
|
-
name: 'Risk-Based Coverage',
|
|
293
|
-
description: 'Prioritize coverage by code risk and complexity',
|
|
294
|
-
template: {
|
|
295
|
-
type: 'prompt',
|
|
296
|
-
content: `Analyze coverage gaps for {{targetPath}} with focus on:
|
|
297
|
-
1. Critical business logic paths
|
|
298
|
-
2. Error handling branches
|
|
299
|
-
3. Edge cases and boundary conditions
|
|
300
|
-
4. High-complexity functions (cyclomatic complexity > 10)
|
|
301
|
-
|
|
302
|
-
Risk scoring:
|
|
303
|
-
- Critical: Business logic, auth, payments
|
|
304
|
-
- High: Data validation, external integrations
|
|
305
|
-
- Medium: Internal utilities, helpers
|
|
306
|
-
- Low: Config, constants`,
|
|
307
|
-
variables: [
|
|
308
|
-
{ name: 'targetPath', type: 'string', required: true, description: 'Path to analyze' },
|
|
309
|
-
],
|
|
310
|
-
},
|
|
311
|
-
context: {
|
|
312
|
-
tags: ['coverage', 'risk-based', 'prioritization'],
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
patternType: 'flaky-fix',
|
|
317
|
-
name: 'Timing-Based Flakiness',
|
|
318
|
-
description: 'Fix flaky tests caused by timing issues',
|
|
319
|
-
template: {
|
|
320
|
-
type: 'prompt',
|
|
321
|
-
content: `The test {{testName}} is flaky due to timing issues.
|
|
322
|
-
|
|
323
|
-
Common fixes:
|
|
324
|
-
1. Replace setTimeout with explicit waits
|
|
325
|
-
2. Use waitFor or waitForCondition
|
|
326
|
-
3. Mock time-dependent functions
|
|
327
|
-
4. Increase timeouts for async operations
|
|
328
|
-
5. Add retry logic with exponential backoff
|
|
329
|
-
|
|
330
|
-
Check for:
|
|
331
|
-
- Race conditions in async code
|
|
332
|
-
- Missing await keywords
|
|
333
|
-
- Shared state between tests
|
|
334
|
-
- External service dependencies`,
|
|
335
|
-
variables: [
|
|
336
|
-
{ name: 'testName', type: 'string', required: true, description: 'Name of flaky test' },
|
|
337
|
-
],
|
|
338
|
-
},
|
|
339
|
-
context: {
|
|
340
|
-
tags: ['flaky', 'timing', 'async', 'stability'],
|
|
341
|
-
},
|
|
342
|
-
},
|
|
343
|
-
// ================================================================
|
|
344
|
-
// quality-assessment domain seeds
|
|
345
|
-
// ================================================================
|
|
346
|
-
{
|
|
347
|
-
patternType: 'assertion-pattern',
|
|
348
|
-
qeDomain: 'quality-assessment',
|
|
349
|
-
name: 'Quality Gate Checklist',
|
|
350
|
-
description: 'Evaluate deployment readiness against quality gate criteria',
|
|
351
|
-
template: {
|
|
352
|
-
type: 'prompt',
|
|
353
|
-
content: `Quality gate evaluation for {{targetModule}}:
|
|
354
|
-
|
|
355
|
-
1. Test coverage >= {{coverageThreshold}}%
|
|
356
|
-
2. No critical/high severity bugs open
|
|
357
|
-
3. All P1 tests passing
|
|
358
|
-
4. Performance benchmarks within SLA (p95 < {{latencyThresholdMs}}ms)
|
|
359
|
-
5. Security scan clean (no critical CVEs)
|
|
360
|
-
6. Code review approved
|
|
361
|
-
|
|
362
|
-
Fail the gate if ANY criterion is unmet. Report which criteria passed/failed.`,
|
|
363
|
-
variables: [
|
|
364
|
-
{ name: 'targetModule', type: 'string', required: true, description: 'Module or service to evaluate' },
|
|
365
|
-
{ name: 'coverageThreshold', type: 'number', required: false, defaultValue: 80, description: 'Minimum coverage %' },
|
|
366
|
-
{ name: 'latencyThresholdMs', type: 'number', required: false, defaultValue: 500, description: 'P95 latency limit in ms' },
|
|
367
|
-
],
|
|
368
|
-
},
|
|
369
|
-
context: {
|
|
370
|
-
tags: ['quality-gate', 'deployment', 'readiness', 'sla'],
|
|
371
|
-
},
|
|
372
|
-
confidence: 0.6,
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
patternType: 'assertion-pattern',
|
|
376
|
-
qeDomain: 'quality-assessment',
|
|
377
|
-
name: 'Metric Threshold Validator',
|
|
378
|
-
description: 'Validate quality metrics against configurable thresholds',
|
|
379
|
-
template: {
|
|
380
|
-
type: 'code',
|
|
381
|
-
content: `function validateMetrics(metrics: Record<string, number>, thresholds: Record<string, { min?: number; max?: number }>) {
|
|
382
|
-
const violations: string[] = [];
|
|
383
|
-
for (const [metric, value] of Object.entries(metrics)) {
|
|
384
|
-
const threshold = thresholds[metric];
|
|
385
|
-
if (!threshold) continue;
|
|
386
|
-
if (threshold.min !== undefined && value < threshold.min) {
|
|
387
|
-
violations.push(\`\${metric}: \${value} < min \${threshold.min}\`);
|
|
388
|
-
}
|
|
389
|
-
if (threshold.max !== undefined && value > threshold.max) {
|
|
390
|
-
violations.push(\`\${metric}: \${value} > max \${threshold.max}\`);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return { pass: violations.length === 0, violations };
|
|
394
|
-
}`,
|
|
395
|
-
variables: [],
|
|
396
|
-
},
|
|
397
|
-
context: {
|
|
398
|
-
tags: ['metrics', 'threshold', 'validation', 'scoring'],
|
|
399
|
-
},
|
|
400
|
-
confidence: 0.6,
|
|
401
|
-
},
|
|
402
|
-
// ================================================================
|
|
403
|
-
// defect-intelligence domain seeds
|
|
404
|
-
// ================================================================
|
|
405
|
-
{
|
|
406
|
-
patternType: 'error-handling',
|
|
407
|
-
qeDomain: 'defect-intelligence',
|
|
408
|
-
name: 'Root Cause Analysis Workflow',
|
|
409
|
-
description: 'Systematic root cause analysis for test failures and production incidents',
|
|
410
|
-
template: {
|
|
411
|
-
type: 'prompt',
|
|
412
|
-
content: `Root cause analysis for: {{incidentDescription}}
|
|
413
|
-
|
|
414
|
-
1. **Reproduce**: Confirm the failure is deterministic
|
|
415
|
-
2. **Isolate**: Narrow down to the smallest failing component
|
|
416
|
-
3. **Timeline**: When did it last pass? What changed since?
|
|
417
|
-
4. **Categorize**: Is it a code bug, config issue, data issue, or environment?
|
|
418
|
-
5. **Five Whys**: Ask why at least 5 times to reach the root cause
|
|
419
|
-
6. **Fix**: Propose fix with test to prevent regression
|
|
420
|
-
7. **Verify**: Run the fix and confirm the original failure is resolved`,
|
|
421
|
-
variables: [
|
|
422
|
-
{ name: 'incidentDescription', type: 'string', required: true, description: 'Description of the failure or incident' },
|
|
423
|
-
],
|
|
424
|
-
},
|
|
425
|
-
context: {
|
|
426
|
-
tags: ['root-cause', 'rca', 'debugging', 'incident'],
|
|
427
|
-
},
|
|
428
|
-
confidence: 0.6,
|
|
429
|
-
},
|
|
430
|
-
{
|
|
431
|
-
patternType: 'error-handling',
|
|
432
|
-
qeDomain: 'defect-intelligence',
|
|
433
|
-
name: 'Regression Risk Scorer',
|
|
434
|
-
description: 'Score change risk for regression based on code complexity and history',
|
|
435
|
-
template: {
|
|
436
|
-
type: 'prompt',
|
|
437
|
-
content: `Regression risk assessment for {{changePath}}:
|
|
438
|
-
|
|
439
|
-
Risk factors (score each 0-3):
|
|
440
|
-
- Lines changed: {{linesChanged}} → complexity risk
|
|
441
|
-
- Files affected: {{filesAffected}} → blast radius
|
|
442
|
-
- Previous bugs in area: historical defect density
|
|
443
|
-
- Test coverage of changed code: gap risk
|
|
444
|
-
- Dependency depth: cascade risk
|
|
445
|
-
|
|
446
|
-
Total risk = sum / 15 → Low (<0.3), Medium (0.3-0.6), High (>0.6)`,
|
|
447
|
-
variables: [
|
|
448
|
-
{ name: 'changePath', type: 'string', required: true, description: 'File or module changed' },
|
|
449
|
-
{ name: 'linesChanged', type: 'number', required: true, description: 'Number of lines changed' },
|
|
450
|
-
{ name: 'filesAffected', type: 'number', required: true, description: 'Number of files affected' },
|
|
451
|
-
],
|
|
452
|
-
},
|
|
453
|
-
context: {
|
|
454
|
-
tags: ['regression', 'risk', 'prediction', 'change-analysis'],
|
|
455
|
-
},
|
|
456
|
-
confidence: 0.6,
|
|
457
|
-
},
|
|
458
|
-
// ================================================================
|
|
459
|
-
// requirements-validation domain seeds
|
|
460
|
-
// ================================================================
|
|
461
|
-
{
|
|
462
|
-
patternType: 'test-template',
|
|
463
|
-
qeDomain: 'requirements-validation',
|
|
464
|
-
name: 'Gherkin BDD Scenario',
|
|
465
|
-
description: 'Behavior-driven development scenario in Given/When/Then format',
|
|
466
|
-
template: {
|
|
467
|
-
type: 'code',
|
|
468
|
-
content: `Feature: {{featureName}}
|
|
469
|
-
|
|
470
|
-
Scenario: {{scenarioDescription}}
|
|
471
|
-
Given {{precondition}}
|
|
472
|
-
When {{action}}
|
|
473
|
-
Then {{expectedOutcome}}
|
|
474
|
-
|
|
475
|
-
Scenario: {{scenarioDescription}} - error case
|
|
476
|
-
Given {{precondition}}
|
|
477
|
-
When {{errorAction}}
|
|
478
|
-
Then {{errorOutcome}}`,
|
|
479
|
-
variables: [
|
|
480
|
-
{ name: 'featureName', type: 'string', required: true, description: 'Feature under test' },
|
|
481
|
-
{ name: 'scenarioDescription', type: 'string', required: true, description: 'What the scenario validates' },
|
|
482
|
-
{ name: 'precondition', type: 'string', required: true, description: 'Given precondition' },
|
|
483
|
-
{ name: 'action', type: 'string', required: true, description: 'When action' },
|
|
484
|
-
{ name: 'expectedOutcome', type: 'string', required: true, description: 'Then expected result' },
|
|
485
|
-
{ name: 'errorAction', type: 'string', required: true, description: 'When error action' },
|
|
486
|
-
{ name: 'errorOutcome', type: 'string', required: true, description: 'Then error result' },
|
|
487
|
-
],
|
|
488
|
-
},
|
|
489
|
-
context: {
|
|
490
|
-
tags: ['bdd', 'gherkin', 'requirements', 'acceptance'],
|
|
491
|
-
},
|
|
492
|
-
confidence: 0.6,
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
patternType: 'test-template',
|
|
496
|
-
qeDomain: 'requirements-validation',
|
|
497
|
-
name: 'Acceptance Criteria Testability Check',
|
|
498
|
-
description: 'Evaluate whether acceptance criteria are testable and complete',
|
|
499
|
-
template: {
|
|
500
|
-
type: 'prompt',
|
|
501
|
-
content: `Testability assessment for: {{requirementId}} - {{requirementTitle}}
|
|
502
|
-
|
|
503
|
-
Acceptance criteria:
|
|
504
|
-
{{acceptanceCriteria}}
|
|
505
|
-
|
|
506
|
-
Evaluate each criterion:
|
|
507
|
-
1. **Observable**: Can we verify the outcome without internal knowledge?
|
|
508
|
-
2. **Measurable**: Is there a quantifiable threshold or clear pass/fail?
|
|
509
|
-
3. **Atomic**: Does each criterion test exactly one thing?
|
|
510
|
-
4. **Achievable**: Can this be tested with available tools?
|
|
511
|
-
5. **Complete**: Are edge cases and error paths covered?
|
|
512
|
-
|
|
513
|
-
Flag any untestable or ambiguous criteria with suggested rewrites.`,
|
|
514
|
-
variables: [
|
|
515
|
-
{ name: 'requirementId', type: 'string', required: true, description: 'Requirement identifier' },
|
|
516
|
-
{ name: 'requirementTitle', type: 'string', required: true, description: 'Requirement title' },
|
|
517
|
-
{ name: 'acceptanceCriteria', type: 'string', required: true, description: 'The acceptance criteria text' },
|
|
518
|
-
],
|
|
519
|
-
},
|
|
520
|
-
context: {
|
|
521
|
-
tags: ['requirements', 'testability', 'acceptance-criteria', 'validation'],
|
|
522
|
-
},
|
|
523
|
-
confidence: 0.6,
|
|
524
|
-
},
|
|
525
|
-
// ================================================================
|
|
526
|
-
// code-intelligence domain seeds
|
|
527
|
-
// ================================================================
|
|
528
|
-
{
|
|
529
|
-
patternType: 'refactor-safe',
|
|
530
|
-
name: 'Safe Refactoring Checklist',
|
|
531
|
-
description: 'Ensure refactoring preserves behavior with systematic safety checks',
|
|
532
|
-
template: {
|
|
533
|
-
type: 'prompt',
|
|
534
|
-
content: `Safe refactoring checklist for {{targetPath}}:
|
|
535
|
-
|
|
536
|
-
Before refactoring:
|
|
537
|
-
1. Run existing tests — capture baseline results
|
|
538
|
-
2. Check coverage of code being refactored
|
|
539
|
-
3. Identify all callers and dependents via references
|
|
540
|
-
|
|
541
|
-
During refactoring:
|
|
542
|
-
4. Make one semantic change at a time
|
|
543
|
-
5. Keep public API signatures stable (or update all callers)
|
|
544
|
-
6. Preserve error handling contracts
|
|
545
|
-
|
|
546
|
-
After refactoring:
|
|
547
|
-
7. Run full test suite — compare to baseline
|
|
548
|
-
8. Check for any new uncovered paths
|
|
549
|
-
9. Verify no unused imports or dead code introduced`,
|
|
550
|
-
variables: [
|
|
551
|
-
{ name: 'targetPath', type: 'string', required: true, description: 'Path to refactor' },
|
|
552
|
-
],
|
|
553
|
-
},
|
|
554
|
-
context: {
|
|
555
|
-
tags: ['refactor', 'safety', 'code-change', 'impact'],
|
|
556
|
-
},
|
|
557
|
-
confidence: 0.6,
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
patternType: 'refactor-safe',
|
|
561
|
-
name: 'Dependency Impact Analysis',
|
|
562
|
-
description: 'Analyze the blast radius of a code change through the dependency graph',
|
|
563
|
-
template: {
|
|
564
|
-
type: 'prompt',
|
|
565
|
-
content: `Impact analysis for changes in {{changedFile}}:
|
|
566
|
-
|
|
567
|
-
1. Direct dependents: files that import/require {{changedFile}}
|
|
568
|
-
2. Transitive dependents: files that depend on direct dependents
|
|
569
|
-
3. Test coverage: which tests exercise the changed code?
|
|
570
|
-
4. Integration points: does this affect API contracts or events?
|
|
571
|
-
5. Risk tier: Critical (auth/payments) > High (business logic) > Medium (utils)
|
|
572
|
-
|
|
573
|
-
Output: sorted list of affected files with risk scores.`,
|
|
574
|
-
variables: [
|
|
575
|
-
{ name: 'changedFile', type: 'string', required: true, description: 'File being changed' },
|
|
576
|
-
],
|
|
577
|
-
},
|
|
578
|
-
context: {
|
|
579
|
-
tags: ['impact', 'dependency', 'blast-radius', 'analysis'],
|
|
580
|
-
},
|
|
581
|
-
confidence: 0.6,
|
|
582
|
-
},
|
|
583
|
-
// ================================================================
|
|
584
|
-
// security-compliance domain seeds
|
|
585
|
-
// ================================================================
|
|
586
|
-
{
|
|
587
|
-
patternType: 'assertion-pattern',
|
|
588
|
-
qeDomain: 'security-compliance',
|
|
589
|
-
name: 'OWASP Top 10 Security Audit',
|
|
590
|
-
description: 'Check code against OWASP Top 10 vulnerability categories',
|
|
591
|
-
template: {
|
|
592
|
-
type: 'prompt',
|
|
593
|
-
content: `Security audit for {{targetPath}} against OWASP Top 10:
|
|
594
|
-
|
|
595
|
-
1. **A01 Broken Access Control**: Check authorization on every endpoint
|
|
596
|
-
2. **A02 Cryptographic Failures**: No plaintext secrets, proper hashing
|
|
597
|
-
3. **A03 Injection**: Parameterized queries, input sanitization
|
|
598
|
-
4. **A04 Insecure Design**: Threat modeling, least privilege
|
|
599
|
-
5. **A05 Security Misconfiguration**: Default creds, verbose errors
|
|
600
|
-
6. **A06 Vulnerable Components**: Check dependencies for CVEs
|
|
601
|
-
7. **A07 Auth Failures**: Brute force protection, session management
|
|
602
|
-
8. **A08 Data Integrity Failures**: Verify signatures, safe deserialization
|
|
603
|
-
9. **A09 Logging Failures**: Audit trail, no sensitive data in logs
|
|
604
|
-
10. **A10 SSRF**: Validate/allowlist outbound URLs
|
|
605
|
-
|
|
606
|
-
Flag findings as Critical/High/Medium/Low with remediation guidance.`,
|
|
607
|
-
variables: [
|
|
608
|
-
{ name: 'targetPath', type: 'string', required: true, description: 'Code path to audit' },
|
|
609
|
-
],
|
|
610
|
-
},
|
|
611
|
-
context: {
|
|
612
|
-
tags: ['owasp', 'security', 'audit', 'vulnerability'],
|
|
613
|
-
},
|
|
614
|
-
confidence: 0.6,
|
|
615
|
-
},
|
|
616
|
-
{
|
|
617
|
-
patternType: 'assertion-pattern',
|
|
618
|
-
qeDomain: 'security-compliance',
|
|
619
|
-
name: 'Input Sanitization Pattern',
|
|
620
|
-
description: 'Validate and sanitize inputs at system boundaries to prevent injection',
|
|
621
|
-
template: {
|
|
622
|
-
type: 'code',
|
|
623
|
-
content: `// Input validation at system boundary
|
|
624
|
-
function validateInput(input: unknown, schema: {
|
|
625
|
-
type: 'string' | 'number' | 'boolean';
|
|
626
|
-
maxLength?: number;
|
|
627
|
-
pattern?: RegExp;
|
|
628
|
-
allowedValues?: unknown[];
|
|
629
|
-
}): { valid: boolean; sanitized: unknown; errors: string[] } {
|
|
630
|
-
const errors: string[] = [];
|
|
631
|
-
if (typeof input !== schema.type) {
|
|
632
|
-
errors.push(\`Expected \${schema.type}, got \${typeof input}\`);
|
|
633
|
-
return { valid: false, sanitized: null, errors };
|
|
634
|
-
}
|
|
635
|
-
if (schema.type === 'string') {
|
|
636
|
-
let str = input as string;
|
|
637
|
-
if (schema.maxLength && str.length > schema.maxLength) {
|
|
638
|
-
str = str.slice(0, schema.maxLength);
|
|
639
|
-
errors.push('Input truncated to max length');
|
|
640
|
-
}
|
|
641
|
-
if (schema.pattern && !schema.pattern.test(str)) {
|
|
642
|
-
errors.push('Input does not match expected pattern');
|
|
643
|
-
return { valid: false, sanitized: null, errors };
|
|
644
|
-
}
|
|
645
|
-
return { valid: errors.length === 0, sanitized: str, errors };
|
|
646
|
-
}
|
|
647
|
-
return { valid: true, sanitized: input, errors };
|
|
648
|
-
}`,
|
|
649
|
-
variables: [],
|
|
650
|
-
},
|
|
651
|
-
context: {
|
|
652
|
-
tags: ['security', 'validation', 'sanitization', 'injection-prevention'],
|
|
653
|
-
},
|
|
654
|
-
confidence: 0.6,
|
|
655
|
-
},
|
|
656
|
-
// ================================================================
|
|
657
|
-
// contract-testing domain seeds
|
|
658
|
-
// ================================================================
|
|
659
|
-
{
|
|
660
|
-
patternType: 'api-contract',
|
|
661
|
-
name: 'OpenAPI Contract Validator',
|
|
662
|
-
description: 'Validate API responses against OpenAPI/Swagger schema',
|
|
663
|
-
template: {
|
|
664
|
-
type: 'code',
|
|
665
|
-
content: `describe('{{apiEndpoint}} contract', () => {
|
|
666
|
-
it('should match the OpenAPI schema for {{operationId}}', async () => {
|
|
667
|
-
const response = await request(app).{{httpMethod}}('{{apiEndpoint}}');
|
|
668
|
-
expect(response.status).toBe({{expectedStatus}});
|
|
669
|
-
expect(response.body).toMatchSchema(openApiSpec.paths['{{apiEndpoint}}'].{{httpMethod}}.responses['{{expectedStatus}}'].content['application/json'].schema);
|
|
670
|
-
});
|
|
671
|
-
|
|
672
|
-
it('should return proper error for invalid input', async () => {
|
|
673
|
-
const response = await request(app).{{httpMethod}}('{{apiEndpoint}}').send({{invalidPayload}});
|
|
674
|
-
expect(response.status).toBe(400);
|
|
675
|
-
expect(response.body).toHaveProperty('errors');
|
|
676
|
-
});
|
|
677
|
-
});`,
|
|
678
|
-
variables: [
|
|
679
|
-
{ name: 'apiEndpoint', type: 'string', required: true, description: 'API endpoint path' },
|
|
680
|
-
{ name: 'operationId', type: 'string', required: true, description: 'OpenAPI operation ID' },
|
|
681
|
-
{ name: 'httpMethod', type: 'string', required: true, description: 'HTTP method (get/post/put/delete)' },
|
|
682
|
-
{ name: 'expectedStatus', type: 'number', required: true, description: 'Expected HTTP status code' },
|
|
683
|
-
{ name: 'invalidPayload', type: 'object', required: true, description: 'Invalid request body for error case' },
|
|
684
|
-
],
|
|
685
|
-
},
|
|
686
|
-
context: {
|
|
687
|
-
tags: ['api', 'contract', 'openapi', 'schema-validation'],
|
|
688
|
-
},
|
|
689
|
-
confidence: 0.6,
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
patternType: 'api-contract',
|
|
693
|
-
name: 'Consumer-Driven Contract Test',
|
|
694
|
-
description: 'Pact-style consumer-driven contract testing between services',
|
|
695
|
-
template: {
|
|
696
|
-
type: 'code',
|
|
697
|
-
content: `// Consumer side contract
|
|
698
|
-
const pact = new Pact({
|
|
699
|
-
consumer: '{{consumerName}}',
|
|
700
|
-
provider: '{{providerName}}',
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
describe('{{consumerName}} -> {{providerName}} contract', () => {
|
|
704
|
-
beforeAll(() => pact.setup());
|
|
705
|
-
afterAll(() => pact.finalize());
|
|
706
|
-
|
|
707
|
-
it('should receive {{expectedResource}}', async () => {
|
|
708
|
-
await pact.addInteraction({
|
|
709
|
-
state: '{{providerState}}',
|
|
710
|
-
uponReceiving: '{{interactionDescription}}',
|
|
711
|
-
withRequest: { method: '{{httpMethod}}', path: '{{requestPath}}' },
|
|
712
|
-
willRespondWith: {
|
|
713
|
-
status: 200,
|
|
714
|
-
body: like({{expectedShape}}),
|
|
715
|
-
},
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
const result = await client.{{clientMethod}}();
|
|
719
|
-
expect(result).toBeDefined();
|
|
720
|
-
});
|
|
721
|
-
});`,
|
|
722
|
-
variables: [
|
|
723
|
-
{ name: 'consumerName', type: 'string', required: true, description: 'Consumer service name' },
|
|
724
|
-
{ name: 'providerName', type: 'string', required: true, description: 'Provider service name' },
|
|
725
|
-
{ name: 'expectedResource', type: 'string', required: true, description: 'Resource being consumed' },
|
|
726
|
-
{ name: 'providerState', type: 'string', required: true, description: 'Provider state precondition' },
|
|
727
|
-
{ name: 'interactionDescription', type: 'string', required: true, description: 'Interaction description' },
|
|
728
|
-
{ name: 'httpMethod', type: 'string', required: true, description: 'HTTP method' },
|
|
729
|
-
{ name: 'requestPath', type: 'string', required: true, description: 'Request path' },
|
|
730
|
-
{ name: 'expectedShape', type: 'object', required: true, description: 'Expected response shape' },
|
|
731
|
-
{ name: 'clientMethod', type: 'string', required: true, description: 'Client method to call' },
|
|
732
|
-
],
|
|
733
|
-
},
|
|
734
|
-
context: {
|
|
735
|
-
tags: ['contract', 'pact', 'consumer-driven', 'microservice'],
|
|
736
|
-
},
|
|
737
|
-
confidence: 0.6,
|
|
738
|
-
},
|
|
739
|
-
// ================================================================
|
|
740
|
-
// visual-accessibility domain seeds
|
|
741
|
-
// ================================================================
|
|
742
|
-
{
|
|
743
|
-
patternType: 'a11y-check',
|
|
744
|
-
name: 'WCAG Contrast and ARIA Check',
|
|
745
|
-
description: 'Validate WCAG 2.2 color contrast ratios and ARIA attribute correctness',
|
|
746
|
-
template: {
|
|
747
|
-
type: 'prompt',
|
|
748
|
-
content: `Accessibility audit for {{componentName}}:
|
|
749
|
-
|
|
750
|
-
WCAG 2.2 AA Compliance:
|
|
751
|
-
1. **Color Contrast**: Text contrast ratio >= 4.5:1 (normal), >= 3:1 (large)
|
|
752
|
-
2. **ARIA Roles**: All interactive elements have correct role attributes
|
|
753
|
-
3. **ARIA Labels**: Forms and buttons have aria-label or aria-labelledby
|
|
754
|
-
4. **Focus Management**: Tab order is logical, focus visible on all interactive elements
|
|
755
|
-
5. **Screen Reader**: Content is meaningful when linearized
|
|
756
|
-
6. **Keyboard**: All functionality accessible via keyboard alone
|
|
757
|
-
|
|
758
|
-
Test with: axe-core, pa11y, or lighthouse --accessibility`,
|
|
759
|
-
variables: [
|
|
760
|
-
{ name: 'componentName', type: 'string', required: true, description: 'UI component to audit' },
|
|
761
|
-
],
|
|
762
|
-
},
|
|
763
|
-
context: {
|
|
764
|
-
tags: ['wcag', 'accessibility', 'aria', 'contrast', 'a11y'],
|
|
765
|
-
},
|
|
766
|
-
confidence: 0.6,
|
|
767
|
-
},
|
|
768
|
-
{
|
|
769
|
-
patternType: 'visual-baseline',
|
|
770
|
-
name: 'Visual Regression Baseline',
|
|
771
|
-
description: 'Capture and compare screenshots for visual regression detection',
|
|
772
|
-
template: {
|
|
773
|
-
type: 'code',
|
|
774
|
-
content: `describe('{{pageName}} visual regression', () => {
|
|
775
|
-
it('should match baseline screenshot', async () => {
|
|
776
|
-
await page.goto('{{pageUrl}}');
|
|
777
|
-
await page.waitForLoadState('networkidle');
|
|
778
|
-
|
|
779
|
-
const screenshot = await page.screenshot({ fullPage: {{fullPage}} });
|
|
780
|
-
expect(screenshot).toMatchSnapshot('{{pageName}}-baseline.png', {
|
|
781
|
-
maxDiffPixelRatio: {{maxDiffRatio}},
|
|
782
|
-
});
|
|
783
|
-
});
|
|
784
|
-
|
|
785
|
-
it('should match baseline at mobile viewport', async () => {
|
|
786
|
-
await page.setViewportSize({ width: 375, height: 812 });
|
|
787
|
-
await page.goto('{{pageUrl}}');
|
|
788
|
-
const screenshot = await page.screenshot({ fullPage: {{fullPage}} });
|
|
789
|
-
expect(screenshot).toMatchSnapshot('{{pageName}}-mobile-baseline.png', {
|
|
790
|
-
maxDiffPixelRatio: {{maxDiffRatio}},
|
|
791
|
-
});
|
|
792
|
-
});
|
|
793
|
-
});`,
|
|
794
|
-
variables: [
|
|
795
|
-
{ name: 'pageName', type: 'string', required: true, description: 'Page name for snapshot naming' },
|
|
796
|
-
{ name: 'pageUrl', type: 'string', required: true, description: 'Page URL to capture' },
|
|
797
|
-
{ name: 'fullPage', type: 'boolean', required: false, defaultValue: true, description: 'Capture full page' },
|
|
798
|
-
{ name: 'maxDiffRatio', type: 'number', required: false, defaultValue: 0.01, description: 'Max pixel diff ratio' },
|
|
799
|
-
],
|
|
800
|
-
},
|
|
801
|
-
context: {
|
|
802
|
-
tags: ['visual', 'screenshot', 'regression', 'baseline', 'playwright'],
|
|
803
|
-
},
|
|
804
|
-
confidence: 0.6,
|
|
805
|
-
},
|
|
806
|
-
// ================================================================
|
|
807
|
-
// chaos-resilience domain seeds
|
|
808
|
-
// ================================================================
|
|
809
|
-
{
|
|
810
|
-
patternType: 'perf-benchmark',
|
|
811
|
-
name: 'Load Test Scenario',
|
|
812
|
-
description: 'k6-style load test with ramp-up stages and SLA assertions',
|
|
813
|
-
template: {
|
|
814
|
-
type: 'code',
|
|
815
|
-
content: `import http from 'k6/http';
|
|
816
|
-
import { check, sleep } from 'k6';
|
|
817
|
-
|
|
818
|
-
export const options = {
|
|
819
|
-
stages: [
|
|
820
|
-
{ duration: '{{rampUpDuration}}', target: {{peakUsers}} },
|
|
821
|
-
{ duration: '{{steadyDuration}}', target: {{peakUsers}} },
|
|
822
|
-
{ duration: '{{rampDownDuration}}', target: 0 },
|
|
823
|
-
],
|
|
824
|
-
thresholds: {
|
|
825
|
-
http_req_duration: ['p(95)<{{p95ThresholdMs}}'],
|
|
826
|
-
http_req_failed: ['rate<{{errorRateThreshold}}'],
|
|
827
|
-
},
|
|
828
|
-
};
|
|
829
|
-
|
|
830
|
-
export default function () {
|
|
831
|
-
const res = http.get('{{targetUrl}}');
|
|
832
|
-
check(res, {
|
|
833
|
-
'status is 200': (r) => r.status === 200,
|
|
834
|
-
'response time < {{p95ThresholdMs}}ms': (r) => r.timings.duration < {{p95ThresholdMs}},
|
|
835
|
-
});
|
|
836
|
-
sleep(1);
|
|
837
|
-
}`,
|
|
838
|
-
variables: [
|
|
839
|
-
{ name: 'targetUrl', type: 'string', required: true, description: 'Target URL to load test' },
|
|
840
|
-
{ name: 'peakUsers', type: 'number', required: true, description: 'Peak concurrent users' },
|
|
841
|
-
{ name: 'rampUpDuration', type: 'string', required: false, defaultValue: '2m', description: 'Ramp-up duration' },
|
|
842
|
-
{ name: 'steadyDuration', type: 'string', required: false, defaultValue: '5m', description: 'Steady state duration' },
|
|
843
|
-
{ name: 'rampDownDuration', type: 'string', required: false, defaultValue: '1m', description: 'Ramp-down duration' },
|
|
844
|
-
{ name: 'p95ThresholdMs', type: 'number', required: false, defaultValue: 500, description: 'P95 latency threshold in ms' },
|
|
845
|
-
{ name: 'errorRateThreshold', type: 'number', required: false, defaultValue: 0.01, description: 'Max error rate (0-1)' },
|
|
846
|
-
],
|
|
847
|
-
},
|
|
848
|
-
context: {
|
|
849
|
-
tags: ['load-test', 'k6', 'performance', 'sla'],
|
|
850
|
-
},
|
|
851
|
-
confidence: 0.6,
|
|
852
|
-
},
|
|
853
|
-
{
|
|
854
|
-
patternType: 'perf-benchmark',
|
|
855
|
-
name: 'Circuit Breaker Resilience Test',
|
|
856
|
-
description: 'Test circuit breaker behavior under fault injection',
|
|
857
|
-
template: {
|
|
858
|
-
type: 'prompt',
|
|
859
|
-
content: `Resilience test for {{serviceName}} circuit breaker:
|
|
860
|
-
|
|
861
|
-
1. **Closed state**: Verify normal requests pass through
|
|
862
|
-
2. **Fault injection**: Inject {{faultType}} faults at {{faultRate}}% rate
|
|
863
|
-
3. **Trip threshold**: Verify breaker opens after {{failureThreshold}} consecutive failures
|
|
864
|
-
4. **Open state**: Verify requests fail fast (no upstream calls)
|
|
865
|
-
5. **Half-open probe**: After {{cooldownMs}}ms, verify single probe request
|
|
866
|
-
6. **Recovery**: On probe success, verify breaker closes and traffic resumes
|
|
867
|
-
7. **Metrics**: Verify circuit state changes are logged and observable`,
|
|
868
|
-
variables: [
|
|
869
|
-
{ name: 'serviceName', type: 'string', required: true, description: 'Service with circuit breaker' },
|
|
870
|
-
{ name: 'faultType', type: 'string', required: false, defaultValue: 'latency', description: 'Type of fault (latency/error/timeout)' },
|
|
871
|
-
{ name: 'faultRate', type: 'number', required: false, defaultValue: 50, description: 'Fault injection rate %' },
|
|
872
|
-
{ name: 'failureThreshold', type: 'number', required: false, defaultValue: 5, description: 'Failures to trip breaker' },
|
|
873
|
-
{ name: 'cooldownMs', type: 'number', required: false, defaultValue: 30000, description: 'Cooldown before half-open' },
|
|
874
|
-
],
|
|
875
|
-
},
|
|
876
|
-
context: {
|
|
877
|
-
tags: ['chaos', 'circuit-breaker', 'resilience', 'fault-injection'],
|
|
878
|
-
},
|
|
879
|
-
confidence: 0.6,
|
|
880
|
-
},
|
|
881
|
-
// ================================================================
|
|
882
|
-
// learning-optimization domain seeds
|
|
883
|
-
// ================================================================
|
|
884
|
-
{
|
|
885
|
-
patternType: 'coverage-strategy',
|
|
886
|
-
qeDomain: 'learning-optimization',
|
|
887
|
-
name: 'Cross-Domain Pattern Transfer',
|
|
888
|
-
description: 'Strategy for transferring useful patterns from one QE domain to related domains',
|
|
889
|
-
template: {
|
|
890
|
-
type: 'prompt',
|
|
891
|
-
content: `Pattern transfer from {{sourceDomain}} to {{targetDomain}}:
|
|
892
|
-
|
|
893
|
-
1. Identify generalizable patterns in source domain (success rate > 70%)
|
|
894
|
-
2. Check domain compatibility (related domains get 80% relevance, unrelated 50%)
|
|
895
|
-
3. Adapt pattern context: replace domain-specific terms with target equivalents
|
|
896
|
-
4. Set transferred pattern confidence to source * compatibility factor
|
|
897
|
-
5. Store in target domain with provenance metadata
|
|
898
|
-
6. Track transfer outcomes to learn which transfers are valuable`,
|
|
899
|
-
variables: [
|
|
900
|
-
{ name: 'sourceDomain', type: 'string', required: true, description: 'Source QE domain' },
|
|
901
|
-
{ name: 'targetDomain', type: 'string', required: true, description: 'Target QE domain' },
|
|
902
|
-
],
|
|
903
|
-
},
|
|
904
|
-
context: {
|
|
905
|
-
tags: ['transfer', 'cross-domain', 'learning', 'pattern-reuse'],
|
|
906
|
-
},
|
|
907
|
-
confidence: 0.6,
|
|
908
|
-
},
|
|
909
|
-
{
|
|
910
|
-
patternType: 'coverage-strategy',
|
|
911
|
-
qeDomain: 'learning-optimization',
|
|
912
|
-
name: 'Pattern Quality Promotion Pipeline',
|
|
913
|
-
description: 'Pipeline for promoting short-term patterns to long-term based on success evidence',
|
|
914
|
-
template: {
|
|
915
|
-
type: 'prompt',
|
|
916
|
-
content: `Pattern promotion evaluation for {{patternName}}:
|
|
917
|
-
|
|
918
|
-
Criteria (all must pass):
|
|
919
|
-
1. Usage count >= 3 successful applications
|
|
920
|
-
2. Success rate >= 70%
|
|
921
|
-
3. Confidence score >= 0.6
|
|
922
|
-
4. Coherence check: no contradiction with existing long-term patterns
|
|
923
|
-
5. Age: pattern has existed for at least 24 hours (not rushed)
|
|
924
|
-
|
|
925
|
-
On promotion:
|
|
926
|
-
- Move from short-term to long-term tier
|
|
927
|
-
- Boost confidence by 10%
|
|
928
|
-
- Enable for cross-domain transfer to related domains
|
|
929
|
-
- Mark as reusable for token savings optimization`,
|
|
930
|
-
variables: [
|
|
931
|
-
{ name: 'patternName', type: 'string', required: true, description: 'Pattern to evaluate for promotion' },
|
|
932
|
-
],
|
|
933
|
-
},
|
|
934
|
-
context: {
|
|
935
|
-
tags: ['promotion', 'learning', 'quality', 'pipeline'],
|
|
936
|
-
},
|
|
937
|
-
confidence: 0.6,
|
|
938
|
-
},
|
|
939
|
-
];
|
|
940
|
-
for (const options of foundationalPatterns) {
|
|
159
|
+
// Add foundational patterns from extracted module
|
|
160
|
+
for (const options of PRETRAINED_PATTERNS) {
|
|
941
161
|
try {
|
|
942
162
|
await this.patternStore.create(options);
|
|
943
163
|
}
|
|
@@ -945,7 +165,7 @@ On promotion:
|
|
|
945
165
|
logger.warn('Failed to load pattern', { name: options.name, error });
|
|
946
166
|
}
|
|
947
167
|
}
|
|
948
|
-
logger.info('Loaded foundational patterns', { count:
|
|
168
|
+
logger.info('Loaded foundational patterns', { count: PRETRAINED_PATTERNS.length });
|
|
949
169
|
}
|
|
950
170
|
/**
|
|
951
171
|
* Seed cross-domain patterns by transferring generalizable patterns
|
|
@@ -958,88 +178,11 @@ On promotion:
|
|
|
958
178
|
if (!this.initialized) {
|
|
959
179
|
await this.initialize();
|
|
960
180
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
'test-generation': ['test-execution', 'coverage-analysis', 'requirements-validation'],
|
|
967
|
-
'test-execution': ['test-generation', 'coverage-analysis', 'quality-assessment'],
|
|
968
|
-
'coverage-analysis': ['test-generation', 'test-execution', 'quality-assessment'],
|
|
969
|
-
'quality-assessment': ['test-execution', 'coverage-analysis', 'defect-intelligence'],
|
|
970
|
-
'defect-intelligence': ['quality-assessment', 'code-intelligence'],
|
|
971
|
-
'requirements-validation': ['test-generation', 'quality-assessment'],
|
|
972
|
-
'code-intelligence': ['defect-intelligence', 'security-compliance'],
|
|
973
|
-
'security-compliance': ['code-intelligence', 'quality-assessment'],
|
|
974
|
-
'contract-testing': ['test-generation', 'test-execution'],
|
|
975
|
-
'visual-accessibility': ['quality-assessment'],
|
|
976
|
-
'chaos-resilience': ['test-execution', 'quality-assessment'],
|
|
977
|
-
'learning-optimization': ['test-generation', 'test-execution', 'coverage-analysis', 'quality-assessment', 'defect-intelligence'],
|
|
978
|
-
};
|
|
979
|
-
// For each domain that has patterns, transfer to related domains
|
|
980
|
-
for (const [sourceDomainStr, targetDomains] of Object.entries(relatedDomains)) {
|
|
981
|
-
const sourceDomain = sourceDomainStr;
|
|
982
|
-
const sourceCount = stats.byDomain[sourceDomain] || 0;
|
|
983
|
-
if (sourceCount === 0)
|
|
984
|
-
continue;
|
|
985
|
-
// Get source domain patterns
|
|
986
|
-
const sourceResult = await this.searchPatterns('', {
|
|
987
|
-
domain: sourceDomain,
|
|
988
|
-
limit: 50,
|
|
989
|
-
});
|
|
990
|
-
if (!sourceResult.success)
|
|
991
|
-
continue;
|
|
992
|
-
for (const targetDomain of targetDomains) {
|
|
993
|
-
// Only transfer to domains that have few patterns (less than source)
|
|
994
|
-
const targetCount = stats.byDomain[targetDomain] || 0;
|
|
995
|
-
if (targetCount >= sourceCount) {
|
|
996
|
-
skipped++;
|
|
997
|
-
continue;
|
|
998
|
-
}
|
|
999
|
-
// Transfer each source pattern to the target domain
|
|
1000
|
-
for (const { pattern: sourcePattern } of sourceResult.value) {
|
|
1001
|
-
// Check if a similar pattern already exists in target domain
|
|
1002
|
-
const existingCheck = await this.searchPatterns(sourcePattern.name, {
|
|
1003
|
-
domain: targetDomain,
|
|
1004
|
-
limit: 1,
|
|
1005
|
-
});
|
|
1006
|
-
if (existingCheck.success && existingCheck.value.length > 0) {
|
|
1007
|
-
const bestMatch = existingCheck.value[0];
|
|
1008
|
-
if (bestMatch.score > 0.8) {
|
|
1009
|
-
skipped++;
|
|
1010
|
-
continue; // Similar pattern already exists
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
// Create transferred pattern with reduced confidence
|
|
1014
|
-
const transferredConfidence = Math.max(0.3, (sourcePattern.confidence || 0.5) * 0.8);
|
|
1015
|
-
const transferResult = await this.storePattern({
|
|
1016
|
-
patternType: sourcePattern.patternType,
|
|
1017
|
-
qeDomain: targetDomain,
|
|
1018
|
-
name: `${sourcePattern.name} (from ${sourceDomain})`,
|
|
1019
|
-
description: `${sourcePattern.description} [Transferred from ${sourceDomain} domain]`,
|
|
1020
|
-
template: sourcePattern.template,
|
|
1021
|
-
context: {
|
|
1022
|
-
...sourcePattern.context,
|
|
1023
|
-
relatedDomains: [sourceDomain, targetDomain],
|
|
1024
|
-
tags: [
|
|
1025
|
-
...sourcePattern.context.tags,
|
|
1026
|
-
'cross-domain-transfer',
|
|
1027
|
-
`source:${sourceDomain}`,
|
|
1028
|
-
],
|
|
1029
|
-
},
|
|
1030
|
-
confidence: transferredConfidence,
|
|
1031
|
-
});
|
|
1032
|
-
if (transferResult.success) {
|
|
1033
|
-
transferred++;
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
skipped++;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
logger.info('Cross-domain transfer complete', { transferred, skipped });
|
|
1042
|
-
return { transferred, skipped };
|
|
181
|
+
return seedCrossDomainPatternsFn({
|
|
182
|
+
searchPatterns: this.searchPatterns.bind(this),
|
|
183
|
+
storePattern: this.storePattern.bind(this),
|
|
184
|
+
patternStore: this.patternStore,
|
|
185
|
+
});
|
|
1043
186
|
}
|
|
1044
187
|
/**
|
|
1045
188
|
* Store a new pattern
|
|
@@ -1140,121 +283,28 @@ On promotion:
|
|
|
1140
283
|
getWitnessChain().then(wc => wc.append('PATTERN_UPDATE', { patternId: outcome.patternId, success: outcome.success }, 'reasoning-bank')).catch((e) => { logger.warn('Witness chain PATTERN_UPDATE failed', { error: toErrorMessage(e) }); });
|
|
1141
284
|
// Check if pattern should be promoted (with coherence gate)
|
|
1142
285
|
const pattern = await this.getPattern(outcome.patternId);
|
|
1143
|
-
|
|
1144
|
-
|
|
286
|
+
const deps = this.getPromotionDeps();
|
|
287
|
+
if (pattern && await checkPatternPromotionWithCoherence(pattern, deps)) {
|
|
288
|
+
await promotePatternFn(outcome.patternId, deps);
|
|
1145
289
|
logger.info('Pattern promoted to long-term', { name: pattern.name });
|
|
1146
290
|
}
|
|
1147
291
|
}
|
|
1148
292
|
return result;
|
|
1149
293
|
}
|
|
1150
294
|
/**
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
* This method implements a two-stage promotion check:
|
|
1154
|
-
* 1. Basic criteria (usage and quality) - cheap to check
|
|
1155
|
-
* 2. Coherence criteria (only if basic passes) - expensive, requires coherence service
|
|
1156
|
-
*
|
|
1157
|
-
* @param pattern - Pattern to evaluate for promotion
|
|
1158
|
-
* @returns true if pattern should be promoted, false otherwise
|
|
295
|
+
* Get promotion dependencies for the extracted promotion module
|
|
1159
296
|
*/
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
const coherenceNodes = allPatterns.map(p => ({
|
|
1172
|
-
id: p.id,
|
|
1173
|
-
embedding: p.embedding || [],
|
|
1174
|
-
weight: p.confidence,
|
|
1175
|
-
metadata: { name: p.name, domain: p.qeDomain },
|
|
1176
|
-
}));
|
|
1177
|
-
const coherenceResult = await this.coherenceService.checkCoherence(coherenceNodes);
|
|
1178
|
-
if (coherenceResult.energy >= (this.config.coherenceThreshold || 0.4)) {
|
|
1179
|
-
// Promotion blocked due to coherence violation
|
|
1180
|
-
const event = {
|
|
1181
|
-
patternId: pattern.id,
|
|
1182
|
-
patternName: pattern.name,
|
|
1183
|
-
reason: 'coherence_violation',
|
|
1184
|
-
energy: coherenceResult.energy,
|
|
1185
|
-
existingPatternConflicts: coherenceResult.contradictions?.map(c => c.nodeIds).flat(),
|
|
1186
|
-
};
|
|
1187
|
-
// Publish event if eventBus is available
|
|
1188
|
-
if (this.eventBus) {
|
|
1189
|
-
await this.eventBus.publish({
|
|
1190
|
-
id: `pattern-promotion-blocked-${pattern.id}`,
|
|
1191
|
-
type: 'pattern:promotion_blocked',
|
|
1192
|
-
timestamp: new Date(),
|
|
1193
|
-
source: 'learning-optimization',
|
|
1194
|
-
payload: event,
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
logger.info('Pattern promotion blocked due to coherence violation', {
|
|
1198
|
-
name: pattern.name,
|
|
1199
|
-
energy: coherenceResult.energy,
|
|
1200
|
-
});
|
|
1201
|
-
return false;
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
return true;
|
|
1205
|
-
}
|
|
1206
|
-
/**
|
|
1207
|
-
* Get all long-term patterns for coherence checking
|
|
1208
|
-
*
|
|
1209
|
-
* @returns Array of long-term patterns
|
|
1210
|
-
*/
|
|
1211
|
-
async getLongTermPatterns() {
|
|
1212
|
-
const result = await this.searchPatterns('', { tier: 'long-term', limit: 1000 });
|
|
1213
|
-
return result.success ? result.value.map(r => r.pattern) : [];
|
|
1214
|
-
}
|
|
1215
|
-
/**
|
|
1216
|
-
* Promote a pattern to long-term storage
|
|
1217
|
-
*
|
|
1218
|
-
* @param patternId - Pattern ID to promote
|
|
1219
|
-
*/
|
|
1220
|
-
async promotePattern(patternId) {
|
|
1221
|
-
const result = await this.patternStore.promote(patternId);
|
|
1222
|
-
if (result.success) {
|
|
1223
|
-
// Persist promotion to SQLite
|
|
1224
|
-
try {
|
|
1225
|
-
this.getSqliteStore().promotePattern(patternId);
|
|
1226
|
-
}
|
|
1227
|
-
catch (e) {
|
|
1228
|
-
logger.warn('SQLite pattern promotion persist failed', { error: toErrorMessage(e) });
|
|
1229
|
-
}
|
|
1230
|
-
// Phase 3: Best-effort RVF dual-write on promotion (re-sync embedding)
|
|
1231
|
-
if (this.rvfDualWriter) {
|
|
1232
|
-
try {
|
|
1233
|
-
const promoted = await this.getPattern(patternId);
|
|
1234
|
-
if (promoted?.embedding && promoted.embedding.length > 0) {
|
|
1235
|
-
this.rvfDualWriter.writePattern(patternId, promoted.embedding);
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
catch (rvfErr) {
|
|
1239
|
-
logger.warn('RVF dual-write on promote failed (non-fatal)', { patternId, error: toErrorMessage(rvfErr) });
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
// ADR-070: Record pattern promotion in witness chain
|
|
1243
|
-
getWitnessChain().then(wc => wc.append('PATTERN_PROMOTE', { patternId }, 'reasoning-bank')).catch((e) => { logger.warn('Witness chain PATTERN_PROMOTE failed', { error: toErrorMessage(e) }); });
|
|
1244
|
-
logger.info('Promoted pattern to long-term', { patternId });
|
|
1245
|
-
if (this.eventBus) {
|
|
1246
|
-
await this.eventBus.publish({
|
|
1247
|
-
id: `pattern-promoted-${patternId}`,
|
|
1248
|
-
type: 'pattern:promoted',
|
|
1249
|
-
timestamp: new Date(),
|
|
1250
|
-
source: 'learning-optimization',
|
|
1251
|
-
payload: { patternId, newTier: 'long-term' },
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
else {
|
|
1256
|
-
logger.error('Failed to promote pattern', result.error, { patternId });
|
|
1257
|
-
}
|
|
297
|
+
getPromotionDeps() {
|
|
298
|
+
return {
|
|
299
|
+
patternStore: this.patternStore,
|
|
300
|
+
coherenceService: this.coherenceService,
|
|
301
|
+
eventBus: this.eventBus,
|
|
302
|
+
coherenceThreshold: this.config.coherenceThreshold || 0.4,
|
|
303
|
+
getSqliteStore: this.getSqliteStore.bind(this),
|
|
304
|
+
rvfDualWriter: this.rvfDualWriter,
|
|
305
|
+
searchPatterns: this.searchPatterns.bind(this),
|
|
306
|
+
getPattern: this.getPattern.bind(this),
|
|
307
|
+
};
|
|
1258
308
|
}
|
|
1259
309
|
/**
|
|
1260
310
|
* Route a task to optimal agent
|
|
@@ -1285,44 +335,16 @@ On promotion:
|
|
|
1285
335
|
const patterns = patternResults.success
|
|
1286
336
|
? patternResults.value.map((r) => r.pattern)
|
|
1287
337
|
: [];
|
|
1288
|
-
// 3.
|
|
1289
|
-
const
|
|
1290
|
-
for (const [agentType, profile] of Object.entries(
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
const domainMatch = detectedDomains.filter((d) => profile.domains.includes(d)).length;
|
|
1295
|
-
const domainScore = domainMatch > 0 ? (domainMatch / detectedDomains.length) * 0.4 : 0;
|
|
1296
|
-
score += domainScore * this.config.routingWeights.similarity;
|
|
1297
|
-
if (domainScore > 0) {
|
|
1298
|
-
reasoning.push(`Domain match: ${(domainScore * 100).toFixed(0)}%`);
|
|
1299
|
-
}
|
|
1300
|
-
// Capability match (0-0.3)
|
|
1301
|
-
if (request.capabilities && request.capabilities.length > 0) {
|
|
1302
|
-
const capMatch = request.capabilities.filter((c) => profile.capabilities.some((pc) => pc.toLowerCase().includes(c.toLowerCase()))).length;
|
|
1303
|
-
const capScore = capMatch > 0 ? (capMatch / request.capabilities.length) * 0.3 : 0;
|
|
1304
|
-
score += capScore * this.config.routingWeights.capabilities;
|
|
1305
|
-
if (capScore > 0) {
|
|
1306
|
-
reasoning.push(`Capability match: ${(capScore * 100).toFixed(0)}%`);
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
else {
|
|
1310
|
-
score += 0.15 * this.config.routingWeights.capabilities;
|
|
1311
|
-
}
|
|
1312
|
-
// Historical performance (0-0.3)
|
|
1313
|
-
score += profile.performanceScore * 0.3 * this.config.routingWeights.performance;
|
|
1314
|
-
reasoning.push(`Performance score: ${(profile.performanceScore * 100).toFixed(0)}%`);
|
|
1315
|
-
// Pattern similarity boost
|
|
1316
|
-
const agentPatterns = patterns.filter((p) => profile.domains.includes(p.qeDomain));
|
|
1317
|
-
if (agentPatterns.length > 0) {
|
|
1318
|
-
const patternBoost = Math.min(0.1, agentPatterns.length * 0.02);
|
|
1319
|
-
score += patternBoost;
|
|
1320
|
-
reasoning.push(`Pattern matches: ${agentPatterns.length}`);
|
|
338
|
+
// 3. Build agent-to-pattern-count map for scoring
|
|
339
|
+
const agentDomainPatternCounts = new Map();
|
|
340
|
+
for (const [agentType, profile] of Object.entries(AGENT_CAPABILITIES)) {
|
|
341
|
+
const count = patterns.filter((p) => profile.domains.includes(p.qeDomain)).length;
|
|
342
|
+
if (count > 0) {
|
|
343
|
+
agentDomainPatternCounts.set(agentType, count);
|
|
1321
344
|
}
|
|
1322
|
-
agentScores.push({ agent: agentType, score, reasoning });
|
|
1323
345
|
}
|
|
1324
|
-
//
|
|
1325
|
-
agentScores
|
|
346
|
+
// 4. Calculate agent scores using extracted function
|
|
347
|
+
const agentScores = calculateAgentScores(detectedDomains, request.capabilities, agentDomainPatternCounts, this.config.routingWeights);
|
|
1326
348
|
const recommended = agentScores[0];
|
|
1327
349
|
const alternatives = agentScores.slice(1, 4);
|
|
1328
350
|
// Generate guidance
|
|
@@ -1384,7 +406,7 @@ On promotion:
|
|
|
1384
406
|
const embedding = await computeRealEmbedding(text);
|
|
1385
407
|
// Resize to configured dimension if needed (384 -> 128)
|
|
1386
408
|
if (embedding.length !== this.config.embeddingDimension) {
|
|
1387
|
-
return
|
|
409
|
+
return resizeEmbedding(embedding, this.config.embeddingDimension);
|
|
1388
410
|
}
|
|
1389
411
|
return embedding;
|
|
1390
412
|
}
|
|
@@ -1399,81 +421,7 @@ On promotion:
|
|
|
1399
421
|
}
|
|
1400
422
|
}
|
|
1401
423
|
// Hash-based fallback (always works, including ARM64)
|
|
1402
|
-
return
|
|
1403
|
-
}
|
|
1404
|
-
/**
|
|
1405
|
-
* Resize embedding to target dimension using averaging or truncation
|
|
1406
|
-
*/
|
|
1407
|
-
resizeEmbedding(embedding, targetDim) {
|
|
1408
|
-
if (embedding.length === targetDim) {
|
|
1409
|
-
return embedding;
|
|
1410
|
-
}
|
|
1411
|
-
if (embedding.length > targetDim) {
|
|
1412
|
-
// Average adjacent values to reduce dimension
|
|
1413
|
-
const ratio = embedding.length / targetDim;
|
|
1414
|
-
const result = new Array(targetDim).fill(0);
|
|
1415
|
-
for (let i = 0; i < targetDim; i++) {
|
|
1416
|
-
const start = Math.floor(i * ratio);
|
|
1417
|
-
const end = Math.floor((i + 1) * ratio);
|
|
1418
|
-
let sum = 0;
|
|
1419
|
-
for (let j = start; j < end; j++) {
|
|
1420
|
-
sum += embedding[j];
|
|
1421
|
-
}
|
|
1422
|
-
result[i] = sum / (end - start);
|
|
1423
|
-
}
|
|
1424
|
-
// Normalize
|
|
1425
|
-
const magnitude = Math.sqrt(result.reduce((sum, val) => sum + val * val, 0));
|
|
1426
|
-
if (magnitude > 0) {
|
|
1427
|
-
for (let i = 0; i < targetDim; i++) {
|
|
1428
|
-
result[i] /= magnitude;
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
return result;
|
|
1432
|
-
}
|
|
1433
|
-
else {
|
|
1434
|
-
// Interpolate to increase dimension (less common)
|
|
1435
|
-
const result = new Array(targetDim).fill(0);
|
|
1436
|
-
const ratio = (embedding.length - 1) / (targetDim - 1);
|
|
1437
|
-
for (let i = 0; i < targetDim; i++) {
|
|
1438
|
-
const pos = i * ratio;
|
|
1439
|
-
const lower = Math.floor(pos);
|
|
1440
|
-
const upper = Math.min(lower + 1, embedding.length - 1);
|
|
1441
|
-
const weight = pos - lower;
|
|
1442
|
-
result[i] = embedding[lower] * (1 - weight) + embedding[upper] * weight;
|
|
1443
|
-
}
|
|
1444
|
-
// Normalize
|
|
1445
|
-
const magnitude = Math.sqrt(result.reduce((sum, val) => sum + val * val, 0));
|
|
1446
|
-
if (magnitude > 0) {
|
|
1447
|
-
for (let i = 0; i < targetDim; i++) {
|
|
1448
|
-
result[i] /= magnitude;
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
return result;
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
/**
|
|
1455
|
-
* Simple hash-based embedding fallback
|
|
1456
|
-
*/
|
|
1457
|
-
hashEmbedding(text) {
|
|
1458
|
-
const dimension = this.config.embeddingDimension;
|
|
1459
|
-
const embedding = new Array(dimension).fill(0);
|
|
1460
|
-
const normalized = text.toLowerCase().trim();
|
|
1461
|
-
// Use multiple hash passes for better distribution
|
|
1462
|
-
for (let pass = 0; pass < 3; pass++) {
|
|
1463
|
-
for (let i = 0; i < normalized.length; i++) {
|
|
1464
|
-
const charCode = normalized.charCodeAt(i);
|
|
1465
|
-
const idx = (charCode * (i + 1) * (pass + 1)) % dimension;
|
|
1466
|
-
embedding[idx] += Math.sin(charCode * (pass + 1)) / (i + 1);
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
// Normalize to unit vector
|
|
1470
|
-
const magnitude = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
|
|
1471
|
-
if (magnitude > 0) {
|
|
1472
|
-
for (let i = 0; i < dimension; i++) {
|
|
1473
|
-
embedding[i] /= magnitude;
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
return embedding;
|
|
424
|
+
return hashEmbedding(text, this.config.embeddingDimension);
|
|
1477
425
|
}
|
|
1478
426
|
/**
|
|
1479
427
|
* Get statistics
|
|
@@ -1530,7 +478,14 @@ export function createQEReasoningBank(memory, eventBus, config, coherenceService
|
|
|
1530
478
|
return new QEReasoningBank(memory, eventBus, config, coherenceService);
|
|
1531
479
|
}
|
|
1532
480
|
// ============================================================================
|
|
1533
|
-
//
|
|
481
|
+
// Re-exports from extracted modules
|
|
482
|
+
// ============================================================================
|
|
483
|
+
// Re-export all types/interfaces/constants so existing import paths work unchanged
|
|
484
|
+
export { DEFAULT_QE_REASONING_BANK_CONFIG } from './qe-reasoning-bank-types.js';
|
|
485
|
+
export { PRETRAINED_PATTERNS } from './pretrained-patterns.js';
|
|
486
|
+
export { AGENT_CAPABILITIES, RELATED_DOMAINS, calculateAgentScores, } from './agent-routing.js';
|
|
487
|
+
// ============================================================================
|
|
488
|
+
// Convenience Exports (preserved from original)
|
|
1534
489
|
// ============================================================================
|
|
1535
490
|
export { detectQEDomain, detectQEDomains, mapQEDomainToAQE, applyPatternTemplate, } from './qe-patterns.js';
|
|
1536
491
|
export { getGuidance, getCombinedGuidance, generateGuidanceContext, } from './qe-guidance.js';
|