agentic-qe 3.6.10 → 3.6.12
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/helpers/learning-service.mjs +2 -0
- package/.claude/helpers/statusline-v3.cjs +2 -0
- package/.claude/skills/skills-manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/migrate-v2-to-v3-memory.js +2 -0
- package/scripts/sync-claude-flow.cjs +1 -0
- package/v3/CHANGELOG.md +39 -0
- package/v3/dist/adapters/claude-flow/trajectory-bridge.js +2 -2
- package/v3/dist/adapters/claude-flow/trajectory-bridge.js.map +1 -1
- package/v3/dist/benchmarks/performance-benchmarks.js +1 -1
- package/v3/dist/cli/bundle.js +659 -427
- package/v3/dist/cli/commands/code.d.ts.map +1 -1
- package/v3/dist/cli/commands/code.js +9 -85
- package/v3/dist/cli/commands/code.js.map +1 -1
- package/v3/dist/cli/commands/coverage.d.ts.map +1 -1
- package/v3/dist/cli/commands/coverage.js +3 -28
- package/v3/dist/cli/commands/coverage.js.map +1 -1
- package/v3/dist/cli/commands/learning-helpers.d.ts.map +1 -1
- package/v3/dist/cli/commands/learning-helpers.js +3 -4
- package/v3/dist/cli/commands/learning-helpers.js.map +1 -1
- package/v3/dist/cli/commands/learning.d.ts.map +1 -1
- package/v3/dist/cli/commands/learning.js +5 -8
- package/v3/dist/cli/commands/learning.js.map +1 -1
- package/v3/dist/cli/commands/migrate.js +2 -2
- package/v3/dist/cli/commands/security.d.ts.map +1 -1
- package/v3/dist/cli/commands/security.js +3 -29
- package/v3/dist/cli/commands/security.js.map +1 -1
- package/v3/dist/cli/commands/test.d.ts.map +1 -1
- package/v3/dist/cli/commands/test.js +5 -58
- package/v3/dist/cli/commands/test.js.map +1 -1
- package/v3/dist/cli/utils/file-discovery.d.ts +27 -0
- package/v3/dist/cli/utils/file-discovery.d.ts.map +1 -0
- package/v3/dist/cli/utils/file-discovery.js +105 -0
- package/v3/dist/cli/utils/file-discovery.js.map +1 -0
- package/v3/dist/coordination/constants.d.ts +1 -1
- package/v3/dist/coordination/constants.js +1 -1
- package/v3/dist/coordination/task-executor.d.ts.map +1 -1
- package/v3/dist/coordination/task-executor.js +612 -104
- package/v3/dist/coordination/task-executor.js.map +1 -1
- package/v3/dist/domains/code-intelligence/coordinator-hypergraph.js +2 -2
- package/v3/dist/domains/code-intelligence/coordinator-hypergraph.js.map +1 -1
- package/v3/dist/domains/code-intelligence/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/code-intelligence/coordinator.js +10 -3
- package/v3/dist/domains/code-intelligence/coordinator.js.map +1 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/index.d.ts.map +1 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/index.js +10 -0
- package/v3/dist/domains/code-intelligence/services/metric-collector/index.js.map +1 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/interfaces.d.ts +7 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/interfaces.d.ts.map +1 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/interfaces.js +10 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/interfaces.js.map +1 -1
- package/v3/dist/domains/code-intelligence/services/metric-collector/loc-counter.js +34 -10
- package/v3/dist/domains/code-intelligence/services/metric-collector/loc-counter.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/coordinator.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/coverage-analyzer.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/coverage-embedder.d.ts +1 -1
- package/v3/dist/domains/coverage-analysis/services/coverage-embedder.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/gap-detector.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.js +1 -1
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.d.ts +10 -1
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.js +40 -5
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +1 -1
- package/v3/dist/domains/coverage-analysis/services/sublinear-analyzer.js +1 -1
- package/v3/dist/init/fleet-integration.d.ts.map +1 -1
- package/v3/dist/init/fleet-integration.js +3 -4
- package/v3/dist/init/fleet-integration.js.map +1 -1
- package/v3/dist/init/init-wizard-hooks.d.ts +8 -1
- package/v3/dist/init/init-wizard-hooks.d.ts.map +1 -1
- package/v3/dist/init/init-wizard-hooks.js +47 -39
- package/v3/dist/init/init-wizard-hooks.js.map +1 -1
- package/v3/dist/init/init-wizard-migration.d.ts.map +1 -1
- package/v3/dist/init/init-wizard-migration.js +3 -7
- package/v3/dist/init/init-wizard-migration.js.map +1 -1
- package/v3/dist/init/init-wizard-steps.d.ts.map +1 -1
- package/v3/dist/init/init-wizard-steps.js +3 -4
- package/v3/dist/init/init-wizard-steps.js.map +1 -1
- package/v3/dist/init/migration/data-migrator.d.ts.map +1 -1
- package/v3/dist/init/migration/data-migrator.js +6 -10
- package/v3/dist/init/migration/data-migrator.js.map +1 -1
- package/v3/dist/init/migration/detector.d.ts.map +1 -1
- package/v3/dist/init/migration/detector.js +2 -4
- package/v3/dist/init/migration/detector.js.map +1 -1
- package/v3/dist/init/phases/01-detection.d.ts.map +1 -1
- package/v3/dist/init/phases/01-detection.js +2 -4
- package/v3/dist/init/phases/01-detection.js.map +1 -1
- package/v3/dist/init/phases/06-code-intelligence.d.ts.map +1 -1
- package/v3/dist/init/phases/06-code-intelligence.js +4 -6
- package/v3/dist/init/phases/06-code-intelligence.js.map +1 -1
- package/v3/dist/init/phases/07-hooks.d.ts +22 -1
- package/v3/dist/init/phases/07-hooks.d.ts.map +1 -1
- package/v3/dist/init/phases/07-hooks.js +137 -51
- package/v3/dist/init/phases/07-hooks.js.map +1 -1
- package/v3/dist/init/phases/12-verification.d.ts.map +1 -1
- package/v3/dist/init/phases/12-verification.js +2 -4
- package/v3/dist/init/phases/12-verification.js.map +1 -1
- package/v3/dist/init/settings-merge.d.ts +35 -0
- package/v3/dist/init/settings-merge.d.ts.map +1 -0
- package/v3/dist/init/settings-merge.js +140 -0
- package/v3/dist/init/settings-merge.js.map +1 -0
- package/v3/dist/integrations/agentic-flow/model-router/router.js +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/router.js.map +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/score-calculator.d.ts.map +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/score-calculator.js +18 -3
- package/v3/dist/integrations/agentic-flow/model-router/score-calculator.js.map +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/signal-collector.d.ts +3 -3
- package/v3/dist/integrations/agentic-flow/model-router/signal-collector.d.ts.map +1 -1
- package/v3/dist/integrations/agentic-flow/model-router/signal-collector.js +18 -0
- package/v3/dist/integrations/agentic-flow/model-router/signal-collector.js.map +1 -1
- package/v3/dist/integrations/embeddings/cache/EmbeddingCache.d.ts.map +1 -1
- package/v3/dist/integrations/embeddings/cache/EmbeddingCache.js +2 -2
- package/v3/dist/integrations/embeddings/cache/EmbeddingCache.js.map +1 -1
- package/v3/dist/kernel/constants.d.ts +1 -1
- package/v3/dist/kernel/constants.js +1 -1
- package/v3/dist/kernel/unified-memory-hnsw.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory-hnsw.js +25 -6
- package/v3/dist/kernel/unified-memory-hnsw.js.map +1 -1
- package/v3/dist/kernel/unified-memory-migration.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory-migration.js +3 -3
- package/v3/dist/kernel/unified-memory-migration.js.map +1 -1
- package/v3/dist/learning/metrics-tracker.d.ts.map +1 -1
- package/v3/dist/learning/metrics-tracker.js +2 -2
- package/v3/dist/learning/metrics-tracker.js.map +1 -1
- package/v3/dist/learning/sqlite-persistence.d.ts.map +1 -1
- package/v3/dist/learning/sqlite-persistence.js +3 -6
- package/v3/dist/learning/sqlite-persistence.js.map +1 -1
- package/v3/dist/learning/v2-to-v3-migration.d.ts.map +1 -1
- package/v3/dist/learning/v2-to-v3-migration.js +4 -5
- package/v3/dist/learning/v2-to-v3-migration.js.map +1 -1
- package/v3/dist/mcp/bundle.js +1266 -245
- package/v3/dist/mcp/handlers/domain-handler-configs.d.ts.map +1 -1
- package/v3/dist/mcp/handlers/domain-handler-configs.js +40 -31
- package/v3/dist/mcp/handlers/domain-handler-configs.js.map +1 -1
- package/v3/dist/mcp/handlers/task-handlers.d.ts.map +1 -1
- package/v3/dist/mcp/handlers/task-handlers.js +68 -5
- package/v3/dist/mcp/handlers/task-handlers.js.map +1 -1
- package/v3/dist/mcp/protocol-server.d.ts.map +1 -1
- package/v3/dist/mcp/protocol-server.js +16 -2
- package/v3/dist/mcp/protocol-server.js.map +1 -1
- package/v3/dist/mcp/tools/security-compliance/scan.d.ts +3 -1
- package/v3/dist/mcp/tools/security-compliance/scan.d.ts.map +1 -1
- package/v3/dist/mcp/tools/security-compliance/scan.js +417 -72
- package/v3/dist/mcp/tools/security-compliance/scan.js.map +1 -1
- package/v3/dist/planning/plan-executor.d.ts.map +1 -1
- package/v3/dist/planning/plan-executor.js +2 -2
- package/v3/dist/planning/plan-executor.js.map +1 -1
- package/v3/dist/shared/safe-db.d.ts +32 -0
- package/v3/dist/shared/safe-db.d.ts.map +1 -0
- package/v3/dist/shared/safe-db.js +41 -0
- package/v3/dist/shared/safe-db.js.map +1 -0
- package/v3/dist/sync/claude-flow-bridge.js +5 -5
- package/v3/dist/sync/claude-flow-bridge.js.map +1 -1
- package/v3/dist/sync/embeddings/sync-embedding-generator.js +3 -3
- package/v3/dist/sync/embeddings/sync-embedding-generator.js.map +1 -1
- package/v3/dist/sync/readers/sqlite-reader.d.ts.map +1 -1
- package/v3/dist/sync/readers/sqlite-reader.js +2 -2
- package/v3/dist/sync/readers/sqlite-reader.js.map +1 -1
- package/v3/package.json +1 -1
package/v3/dist/mcp/bundle.js
CHANGED
|
@@ -4421,7 +4421,7 @@ var init_constants = __esm({
|
|
|
4421
4421
|
/**
|
|
4422
4422
|
* Vector dimension for coverage analysis embeddings.
|
|
4423
4423
|
*/
|
|
4424
|
-
COVERAGE_VECTOR_DIMENSION:
|
|
4424
|
+
COVERAGE_VECTOR_DIMENSION: 768
|
|
4425
4425
|
};
|
|
4426
4426
|
AGENT_CONSTANTS = {
|
|
4427
4427
|
/**
|
|
@@ -4643,6 +4643,12 @@ var init_gnn = __esm({
|
|
|
4643
4643
|
});
|
|
4644
4644
|
|
|
4645
4645
|
// src/kernel/unified-memory-hnsw.ts
|
|
4646
|
+
var unified_memory_hnsw_exports = {};
|
|
4647
|
+
__export(unified_memory_hnsw_exports, {
|
|
4648
|
+
BinaryHeap: () => BinaryHeap,
|
|
4649
|
+
InMemoryHNSWIndex: () => InMemoryHNSWIndex,
|
|
4650
|
+
RuvectorFlatIndex: () => RuvectorFlatIndex
|
|
4651
|
+
});
|
|
4646
4652
|
function computeNorm(v62) {
|
|
4647
4653
|
let sum = 0;
|
|
4648
4654
|
for (let i58 = 0; i58 < v62.length; i58++) sum += v62[i58] * v62[i58];
|
|
@@ -5036,7 +5042,10 @@ var init_unified_memory_hnsw = __esm({
|
|
|
5036
5042
|
search(query, k68) {
|
|
5037
5043
|
if (this.ids.length === 0) return [];
|
|
5038
5044
|
const actualK = Math.min(k68, this.ids.length);
|
|
5039
|
-
|
|
5045
|
+
const storedDim = this.vectors.length > 0 ? this.vectors[0].length : 0;
|
|
5046
|
+
const queryDim = query.length;
|
|
5047
|
+
const dimensionsMatch = storedDim === queryDim;
|
|
5048
|
+
if (ruvectorDifferentiableSearch && this.vectors.length > 0 && dimensionsMatch) {
|
|
5040
5049
|
const queryF322 = new Float32Array(query);
|
|
5041
5050
|
const queryNorm2 = computeNorm(queryF322);
|
|
5042
5051
|
const result = ruvectorDifferentiableSearch(
|
|
@@ -5054,10 +5063,20 @@ var init_unified_memory_hnsw = __esm({
|
|
|
5054
5063
|
const queryNorm = computeNorm(queryF32);
|
|
5055
5064
|
const scored = [];
|
|
5056
5065
|
for (let i58 = 0; i58 < this.ids.length; i58++) {
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5066
|
+
const vec = this.vectors[i58];
|
|
5067
|
+
if (vec.length !== queryF32.length) {
|
|
5068
|
+
if (i58 === 0) {
|
|
5069
|
+
console.warn(
|
|
5070
|
+
`[RuvectorFlatIndex] Dimension mismatch: query=${queryF32.length}, stored=${vec.length}. Skipping ${this.ids.length} mismatched vectors. Re-index with correct dimensions.`
|
|
5071
|
+
);
|
|
5072
|
+
}
|
|
5073
|
+
continue;
|
|
5074
|
+
} else {
|
|
5075
|
+
scored.push({
|
|
5076
|
+
id: this.ids[i58],
|
|
5077
|
+
score: fastCosine(queryF32, vec, queryNorm, this.norms[i58])
|
|
5078
|
+
});
|
|
5079
|
+
}
|
|
5061
5080
|
}
|
|
5062
5081
|
scored.sort((a37, b68) => b68.score - a37.score);
|
|
5063
5082
|
return scored.slice(0, actualK);
|
|
@@ -11337,7 +11356,7 @@ function createHNSWIndex(memory, config) {
|
|
|
11337
11356
|
return new HNSWIndex(memory, config);
|
|
11338
11357
|
}
|
|
11339
11358
|
async function benchmarkHNSW(index, vectorCount = 1e4, searchCount = 1e3) {
|
|
11340
|
-
const dimensions =
|
|
11359
|
+
const dimensions = 768;
|
|
11341
11360
|
const startInsert = performance.now();
|
|
11342
11361
|
for (let i58 = 0; i58 < vectorCount; i58++) {
|
|
11343
11362
|
const vector = Array.from({ length: dimensions }, () => Math.random());
|
|
@@ -11366,7 +11385,7 @@ var init_hnsw_index = __esm({
|
|
|
11366
11385
|
QEGNNEmbeddingIndexClass = null;
|
|
11367
11386
|
ruvectorLoaded = false;
|
|
11368
11387
|
DEFAULT_HNSW_CONFIG = {
|
|
11369
|
-
dimensions:
|
|
11388
|
+
dimensions: 768,
|
|
11370
11389
|
M: 16,
|
|
11371
11390
|
efConstruction: 200,
|
|
11372
11391
|
efSearch: 100,
|
|
@@ -11461,7 +11480,7 @@ var init_hnsw_index = __esm({
|
|
|
11461
11480
|
if (!this.initialized) {
|
|
11462
11481
|
await this.initialize();
|
|
11463
11482
|
}
|
|
11464
|
-
this.validateVector(vector);
|
|
11483
|
+
vector = this.validateVector(vector);
|
|
11465
11484
|
if (this.keyToLabel.has(key)) {
|
|
11466
11485
|
await this.delete(key);
|
|
11467
11486
|
}
|
|
@@ -11490,7 +11509,7 @@ var init_hnsw_index = __esm({
|
|
|
11490
11509
|
if (!this.initialized) {
|
|
11491
11510
|
await this.initialize();
|
|
11492
11511
|
}
|
|
11493
|
-
this.validateVector(query);
|
|
11512
|
+
query = this.validateVector(query);
|
|
11494
11513
|
const startTime = performance.now();
|
|
11495
11514
|
const results = this.stats.vectorCount > 0 ? this.searchRuvector(query, k68) : [];
|
|
11496
11515
|
const endTime = performance.now();
|
|
@@ -11615,17 +11634,46 @@ var init_hnsw_index = __esm({
|
|
|
11615
11634
|
// ============================================================================
|
|
11616
11635
|
// Private Helper Methods
|
|
11617
11636
|
// ============================================================================
|
|
11637
|
+
/**
|
|
11638
|
+
* Validate and auto-resize vectors to match HNSW configured dimensions.
|
|
11639
|
+
* Fix #279: Prevents Rust WASM panic when RealEmbeddings (768-dim) are
|
|
11640
|
+
* passed to a mismatched-dim HNSW index.
|
|
11641
|
+
*/
|
|
11618
11642
|
validateVector(vector) {
|
|
11619
11643
|
if (vector.length !== this.config.dimensions) {
|
|
11620
|
-
|
|
11621
|
-
`Vector dimension mismatch: expected ${this.config.dimensions}, got ${vector.length}`
|
|
11622
|
-
);
|
|
11644
|
+
return this.resizeVector(vector, this.config.dimensions);
|
|
11623
11645
|
}
|
|
11624
11646
|
for (let i58 = 0; i58 < vector.length; i58++) {
|
|
11625
11647
|
if (!Number.isFinite(vector[i58])) {
|
|
11626
11648
|
throw new Error(`Invalid vector value at index ${i58}: ${vector[i58]}`);
|
|
11627
11649
|
}
|
|
11628
11650
|
}
|
|
11651
|
+
return vector;
|
|
11652
|
+
}
|
|
11653
|
+
/**
|
|
11654
|
+
* Resize vector to target dimensions using averaging (shrink) or zero-padding (grow).
|
|
11655
|
+
*/
|
|
11656
|
+
resizeVector(vector, targetDim) {
|
|
11657
|
+
if (vector.length === targetDim) return vector;
|
|
11658
|
+
if (vector.length > targetDim) {
|
|
11659
|
+
const result2 = new Array(targetDim).fill(0);
|
|
11660
|
+
const ratio = vector.length / targetDim;
|
|
11661
|
+
for (let i58 = 0; i58 < targetDim; i58++) {
|
|
11662
|
+
const start = Math.floor(i58 * ratio);
|
|
11663
|
+
const end = Math.floor((i58 + 1) * ratio);
|
|
11664
|
+
let sum = 0;
|
|
11665
|
+
for (let j52 = start; j52 < end; j52++) {
|
|
11666
|
+
sum += vector[j52];
|
|
11667
|
+
}
|
|
11668
|
+
result2[i58] = sum / (end - start);
|
|
11669
|
+
}
|
|
11670
|
+
return result2;
|
|
11671
|
+
}
|
|
11672
|
+
const result = new Array(targetDim).fill(0);
|
|
11673
|
+
for (let i58 = 0; i58 < vector.length; i58++) {
|
|
11674
|
+
result[i58] = vector[i58];
|
|
11675
|
+
}
|
|
11676
|
+
return result;
|
|
11629
11677
|
}
|
|
11630
11678
|
buildKey(key) {
|
|
11631
11679
|
return `${this.config.namespace}:${key}`;
|
|
@@ -11692,6 +11740,33 @@ var init_hnsw_index = __esm({
|
|
|
11692
11740
|
}
|
|
11693
11741
|
});
|
|
11694
11742
|
|
|
11743
|
+
// src/shared/safe-db.ts
|
|
11744
|
+
var safe_db_exports = {};
|
|
11745
|
+
__export(safe_db_exports, {
|
|
11746
|
+
openDatabase: () => openDatabase
|
|
11747
|
+
});
|
|
11748
|
+
function openDatabase(dbPath, opts) {
|
|
11749
|
+
const readonly = opts?.readonly ?? false;
|
|
11750
|
+
const fileMustExist = opts?.fileMustExist ?? false;
|
|
11751
|
+
const busyTimeout = opts?.busyTimeout ?? 5e3;
|
|
11752
|
+
const walMode = opts?.walMode ?? !readonly;
|
|
11753
|
+
const db = new better_sqlite3_default(dbPath, {
|
|
11754
|
+
readonly,
|
|
11755
|
+
fileMustExist
|
|
11756
|
+
});
|
|
11757
|
+
db.pragma(`busy_timeout = ${busyTimeout}`);
|
|
11758
|
+
if (walMode) {
|
|
11759
|
+
db.pragma("journal_mode = WAL");
|
|
11760
|
+
}
|
|
11761
|
+
return db;
|
|
11762
|
+
}
|
|
11763
|
+
var init_safe_db = __esm({
|
|
11764
|
+
"src/shared/safe-db.ts"() {
|
|
11765
|
+
"use strict";
|
|
11766
|
+
init_better_sqlite3();
|
|
11767
|
+
}
|
|
11768
|
+
});
|
|
11769
|
+
|
|
11695
11770
|
// src/integrations/vibium/types.ts
|
|
11696
11771
|
var init_types2 = __esm({
|
|
11697
11772
|
"src/integrations/vibium/types.ts"() {
|
|
@@ -16304,7 +16379,7 @@ var DEFAULT_SQLITE_CONFIG, SQLitePatternStore;
|
|
|
16304
16379
|
var init_sqlite_persistence = __esm({
|
|
16305
16380
|
"src/learning/sqlite-persistence.ts"() {
|
|
16306
16381
|
"use strict";
|
|
16307
|
-
|
|
16382
|
+
init_safe_db();
|
|
16308
16383
|
init_esm_node();
|
|
16309
16384
|
init_safe_json();
|
|
16310
16385
|
init_error_utils();
|
|
@@ -16348,10 +16423,7 @@ var init_sqlite_persistence = __esm({
|
|
|
16348
16423
|
if (!fs21.existsSync(dir)) {
|
|
16349
16424
|
fs21.mkdirSync(dir, { recursive: true });
|
|
16350
16425
|
}
|
|
16351
|
-
this.db =
|
|
16352
|
-
if (this.config.walMode) {
|
|
16353
|
-
this.db.pragma("journal_mode = WAL");
|
|
16354
|
-
}
|
|
16426
|
+
this.db = openDatabase(this.config.dbPath);
|
|
16355
16427
|
this.db.pragma(`mmap_size = ${this.config.mmapSize}`);
|
|
16356
16428
|
this.db.pragma(`cache_size = ${this.config.cacheSize}`);
|
|
16357
16429
|
if (this.config.foreignKeys) {
|
|
@@ -17796,7 +17868,13 @@ var init_signal_collector = __esm({
|
|
|
17796
17868
|
"test generation",
|
|
17797
17869
|
"error handling",
|
|
17798
17870
|
"validation logic",
|
|
17799
|
-
"api integration"
|
|
17871
|
+
"api integration",
|
|
17872
|
+
"code index",
|
|
17873
|
+
"coverage analysis",
|
|
17874
|
+
"quality assessment",
|
|
17875
|
+
"defect prediction",
|
|
17876
|
+
"predict defect",
|
|
17877
|
+
"analyze coverage"
|
|
17800
17878
|
],
|
|
17801
17879
|
// Tier 3 - High complexity
|
|
17802
17880
|
complex: [
|
|
@@ -17807,7 +17885,14 @@ var init_signal_collector = __esm({
|
|
|
17807
17885
|
"migration",
|
|
17808
17886
|
"cross-domain",
|
|
17809
17887
|
"workflow",
|
|
17810
|
-
"system design"
|
|
17888
|
+
"system design",
|
|
17889
|
+
"analyze security",
|
|
17890
|
+
"security scan",
|
|
17891
|
+
"security analysis",
|
|
17892
|
+
"vulnerability scan",
|
|
17893
|
+
"chaos test",
|
|
17894
|
+
"resilience test",
|
|
17895
|
+
"contract validation"
|
|
17811
17896
|
],
|
|
17812
17897
|
// Tier 4 - Critical/expert
|
|
17813
17898
|
critical: [
|
|
@@ -17818,7 +17903,12 @@ var init_signal_collector = __esm({
|
|
|
17818
17903
|
"system-wide",
|
|
17819
17904
|
"vulnerability",
|
|
17820
17905
|
"cryptography",
|
|
17821
|
-
"performance critical"
|
|
17906
|
+
"performance critical",
|
|
17907
|
+
"hardcoded secret",
|
|
17908
|
+
"cve",
|
|
17909
|
+
"owasp",
|
|
17910
|
+
"penetration test",
|
|
17911
|
+
"exploit"
|
|
17822
17912
|
]
|
|
17823
17913
|
};
|
|
17824
17914
|
SCOPE_PATTERNS = {
|
|
@@ -18115,11 +18205,15 @@ var init_score_calculator = __esm({
|
|
|
18115
18205
|
* Calculate overall complexity score (0-100)
|
|
18116
18206
|
*/
|
|
18117
18207
|
calculateOverallComplexity(codeComplexity, reasoningComplexity, scopeComplexity, signals) {
|
|
18118
|
-
if (signals.isMechanicalTransform) {
|
|
18208
|
+
if (signals.isMechanicalTransform && !signals.hasSecurityScope && !signals.hasArchitectureScope && !signals.requiresMultiStepReasoning && !signals.requiresCrossDomainCoordination && codeComplexity === 0 && reasoningComplexity === 0 && scopeComplexity === 0) {
|
|
18119
18209
|
return 5;
|
|
18120
18210
|
}
|
|
18121
18211
|
const weighted = codeComplexity * 0.3 + reasoningComplexity * 0.4 + scopeComplexity * 0.3;
|
|
18122
|
-
|
|
18212
|
+
let minScore = 0;
|
|
18213
|
+
if (signals.hasSecurityScope) minScore = Math.max(minScore, 50);
|
|
18214
|
+
if (signals.hasArchitectureScope) minScore = Math.max(minScore, 55);
|
|
18215
|
+
if (signals.requiresCrossDomainCoordination) minScore = Math.max(minScore, 35);
|
|
18216
|
+
return Math.min(Math.max(Math.round(weighted), minScore), 100);
|
|
18123
18217
|
}
|
|
18124
18218
|
/**
|
|
18125
18219
|
* Calculate confidence in complexity assessment (0-1)
|
|
@@ -18922,7 +19016,7 @@ var init_router = __esm({
|
|
|
18922
19016
|
agentBoosterStats: {
|
|
18923
19017
|
eligible: agentBoosterEligible,
|
|
18924
19018
|
used: agentBoosterUsed,
|
|
18925
|
-
fallbackToLLM: agentBoosterEligible - agentBoosterUsed,
|
|
19019
|
+
fallbackToLLM: Math.max(0, agentBoosterEligible - agentBoosterUsed),
|
|
18926
19020
|
successRate: agentBoosterUsed > 0 ? agentBoosterSuccess / agentBoosterUsed : 0
|
|
18927
19021
|
},
|
|
18928
19022
|
budgetStats: {
|
|
@@ -21661,13 +21755,13 @@ var init_trajectory_bridge = __esm({
|
|
|
21661
21755
|
const { existsSync: existsSync18, mkdirSync: mkdirSync6 } = await import("fs");
|
|
21662
21756
|
const { createRequire: createRequire11 } = await import("module");
|
|
21663
21757
|
const require3 = createRequire11(import.meta.url);
|
|
21664
|
-
const
|
|
21758
|
+
const { openDatabase: openDatabase2 } = require3("../../shared/safe-db.js");
|
|
21665
21759
|
const dbPath = join26(this.options.projectRoot, ".agentic-qe", "trajectories.db");
|
|
21666
21760
|
const dir = join26(this.options.projectRoot, ".agentic-qe");
|
|
21667
21761
|
if (!existsSync18(dir)) {
|
|
21668
21762
|
mkdirSync6(dir, { recursive: true });
|
|
21669
21763
|
}
|
|
21670
|
-
const db =
|
|
21764
|
+
const db = openDatabase2(dbPath);
|
|
21671
21765
|
db.exec(`
|
|
21672
21766
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
21673
21767
|
id TEXT PRIMARY KEY,
|
|
@@ -65083,7 +65177,7 @@ var DEFAULT_CONFIG18 = {
|
|
|
65083
65177
|
};
|
|
65084
65178
|
var CoverageAnalyzerService = class _CoverageAnalyzerService {
|
|
65085
65179
|
static DEFAULT_THRESHOLD = 80;
|
|
65086
|
-
static VECTOR_DIMENSION =
|
|
65180
|
+
static VECTOR_DIMENSION = 768;
|
|
65087
65181
|
memory;
|
|
65088
65182
|
config;
|
|
65089
65183
|
llmRouter;
|
|
@@ -65617,7 +65711,7 @@ var DEFAULT_CONFIG19 = {
|
|
|
65617
65711
|
};
|
|
65618
65712
|
var GapDetectorService = class _GapDetectorService {
|
|
65619
65713
|
static DEFAULT_MIN_COVERAGE = 80;
|
|
65620
|
-
static VECTOR_DIMENSION =
|
|
65714
|
+
static VECTOR_DIMENSION = 768;
|
|
65621
65715
|
memory;
|
|
65622
65716
|
config;
|
|
65623
65717
|
llmRouter;
|
|
@@ -66615,7 +66709,7 @@ init_hnsw_index();
|
|
|
66615
66709
|
|
|
66616
66710
|
// src/domains/coverage-analysis/services/coverage-embedder.ts
|
|
66617
66711
|
var DEFAULT_EMBEDDER_CONFIG = {
|
|
66618
|
-
dimensions:
|
|
66712
|
+
dimensions: 768,
|
|
66619
66713
|
includePathFeatures: true,
|
|
66620
66714
|
includeTemporalFeatures: true,
|
|
66621
66715
|
normalization: "l2"
|
|
@@ -67047,7 +67141,7 @@ var ALL_CATEGORIES = [
|
|
|
67047
67141
|
"missing-security-check"
|
|
67048
67142
|
];
|
|
67049
67143
|
var DEFAULT_CONFIG20 = {
|
|
67050
|
-
dimensions:
|
|
67144
|
+
dimensions: 768,
|
|
67051
67145
|
minConfidence: 0.3,
|
|
67052
67146
|
maxGaps: 50,
|
|
67053
67147
|
riskWeight: 0.6,
|
|
@@ -68756,7 +68850,7 @@ var CoverageAnalysisCoordinator = class extends BaseDomainCoordinator {
|
|
|
68756
68850
|
return forecast;
|
|
68757
68851
|
}
|
|
68758
68852
|
createGapEmbedding(gap) {
|
|
68759
|
-
const VECTOR_DIMENSION =
|
|
68853
|
+
const VECTOR_DIMENSION = 768;
|
|
68760
68854
|
const embedding = new Array(VECTOR_DIMENSION).fill(0);
|
|
68761
68855
|
embedding[0] = gap.riskScore;
|
|
68762
68856
|
embedding[1] = Math.min(1, gap.lines.length / 100);
|
|
@@ -86100,7 +86194,35 @@ import { join as join10, extname as extname3 } from "path";
|
|
|
86100
86194
|
// src/domains/code-intelligence/services/metric-collector/interfaces.ts
|
|
86101
86195
|
var DEFAULT_METRIC_CONFIG = {
|
|
86102
86196
|
timeout: 6e4,
|
|
86103
|
-
excludeDirs: [
|
|
86197
|
+
excludeDirs: [
|
|
86198
|
+
// JS/TS ecosystem
|
|
86199
|
+
"node_modules",
|
|
86200
|
+
"dist",
|
|
86201
|
+
"build",
|
|
86202
|
+
"coverage",
|
|
86203
|
+
".nyc_output",
|
|
86204
|
+
".next",
|
|
86205
|
+
".nuxt",
|
|
86206
|
+
".output",
|
|
86207
|
+
// Python ecosystem
|
|
86208
|
+
"__pycache__",
|
|
86209
|
+
".venv",
|
|
86210
|
+
"venv",
|
|
86211
|
+
".tox",
|
|
86212
|
+
".mypy_cache",
|
|
86213
|
+
".pytest_cache",
|
|
86214
|
+
".eggs",
|
|
86215
|
+
"*.egg-info",
|
|
86216
|
+
// Rust / Java / Go
|
|
86217
|
+
"target",
|
|
86218
|
+
".gradle",
|
|
86219
|
+
"vendor",
|
|
86220
|
+
".bundle",
|
|
86221
|
+
// General
|
|
86222
|
+
".git",
|
|
86223
|
+
".svn",
|
|
86224
|
+
".hg"
|
|
86225
|
+
],
|
|
86104
86226
|
testPatterns: ["**/*.test.ts", "**/*.spec.ts", "**/*.test.js", "**/*.spec.js"],
|
|
86105
86227
|
enableCache: true,
|
|
86106
86228
|
cacheTTL: 3e5
|
|
@@ -86108,7 +86230,7 @@ var DEFAULT_METRIC_CONFIG = {
|
|
|
86108
86230
|
|
|
86109
86231
|
// src/domains/code-intelligence/services/metric-collector/loc-counter.ts
|
|
86110
86232
|
import { execSync as execSync3, spawnSync as spawnSync2 } from "child_process";
|
|
86111
|
-
import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync5 } from "fs";
|
|
86233
|
+
import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
86112
86234
|
import { join as join8, extname } from "path";
|
|
86113
86235
|
init_safe_json();
|
|
86114
86236
|
async function countLOC(projectPath, config = {}) {
|
|
@@ -86252,22 +86374,35 @@ function getLanguageForExtension(ext) {
|
|
|
86252
86374
|
function manualLOCCount(projectPath, config) {
|
|
86253
86375
|
const byLanguage = {};
|
|
86254
86376
|
let total = 0;
|
|
86255
|
-
|
|
86256
|
-
|
|
86377
|
+
const excludeSet = new Set(config.excludeDirs);
|
|
86378
|
+
const MAX_FILE_SIZE = 2 * 1024 * 1024;
|
|
86379
|
+
function walkDirectory2(dirPath, depth) {
|
|
86380
|
+
if (!existsSync6(dirPath) || depth > 20) {
|
|
86381
|
+
return;
|
|
86382
|
+
}
|
|
86383
|
+
let entries;
|
|
86384
|
+
try {
|
|
86385
|
+
entries = readdirSync(dirPath, { withFileTypes: true });
|
|
86386
|
+
} catch {
|
|
86257
86387
|
return;
|
|
86258
86388
|
}
|
|
86259
|
-
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
86260
86389
|
for (const entry of entries) {
|
|
86261
86390
|
const fullPath = join8(dirPath, entry.name);
|
|
86262
86391
|
if (entry.isDirectory()) {
|
|
86263
|
-
if (
|
|
86392
|
+
if (excludeSet.has(entry.name) || entry.name.startsWith(".")) {
|
|
86264
86393
|
continue;
|
|
86265
86394
|
}
|
|
86266
|
-
walkDirectory2(fullPath);
|
|
86395
|
+
walkDirectory2(fullPath, depth + 1);
|
|
86267
86396
|
} else if (entry.isFile()) {
|
|
86268
86397
|
const ext = extname(entry.name);
|
|
86269
86398
|
const language = getLanguageForExtension(ext);
|
|
86270
86399
|
if (language) {
|
|
86400
|
+
try {
|
|
86401
|
+
const stat6 = statSync2(fullPath);
|
|
86402
|
+
if (stat6.size > MAX_FILE_SIZE) continue;
|
|
86403
|
+
} catch {
|
|
86404
|
+
continue;
|
|
86405
|
+
}
|
|
86271
86406
|
const lines = countFileLines(fullPath);
|
|
86272
86407
|
byLanguage[language] = (byLanguage[language] || 0) + lines;
|
|
86273
86408
|
total += lines;
|
|
@@ -86275,11 +86410,11 @@ function manualLOCCount(projectPath, config) {
|
|
|
86275
86410
|
}
|
|
86276
86411
|
}
|
|
86277
86412
|
}
|
|
86278
|
-
walkDirectory2(projectPath);
|
|
86413
|
+
walkDirectory2(projectPath, 0);
|
|
86279
86414
|
return {
|
|
86280
86415
|
total,
|
|
86281
86416
|
byLanguage,
|
|
86282
|
-
source: "
|
|
86417
|
+
source: "node-native",
|
|
86283
86418
|
excludedDirs: config.excludeDirs
|
|
86284
86419
|
};
|
|
86285
86420
|
}
|
|
@@ -86910,12 +87045,19 @@ var MetricCollectorService = class {
|
|
|
86910
87045
|
const toolsUsed = [];
|
|
86911
87046
|
if (loc.source !== "fallback") toolsUsed.push(loc.source);
|
|
86912
87047
|
if (tests.source !== "fallback") toolsUsed.push(tests.source);
|
|
87048
|
+
const locAccuracy = loc.source === "fallback" ? "approximate" : "accurate";
|
|
87049
|
+
const testAccuracy = tests.source === "fallback" ? "approximate" : "accurate";
|
|
86913
87050
|
const metrics = {
|
|
86914
87051
|
loc,
|
|
86915
87052
|
tests,
|
|
86916
87053
|
patterns,
|
|
86917
87054
|
collectedAt: /* @__PURE__ */ new Date(),
|
|
86918
|
-
toolsUsed
|
|
87055
|
+
toolsUsed,
|
|
87056
|
+
accuracy: {
|
|
87057
|
+
loc: locAccuracy,
|
|
87058
|
+
tests: testAccuracy,
|
|
87059
|
+
overall: locAccuracy === "accurate" && testAccuracy === "accurate" ? "accurate" : "approximate"
|
|
87060
|
+
}
|
|
86919
87061
|
};
|
|
86920
87062
|
if (this.config.enableCache) {
|
|
86921
87063
|
this.setInCache(cacheKey, metrics);
|
|
@@ -88469,7 +88611,7 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
|
|
|
88469
88611
|
*/
|
|
88470
88612
|
async initializeHypergraph() {
|
|
88471
88613
|
try {
|
|
88472
|
-
const
|
|
88614
|
+
const { openDatabase: openDatabase2 } = await Promise.resolve().then(() => (init_safe_db(), safe_db_exports));
|
|
88473
88615
|
const fs21 = await import("fs");
|
|
88474
88616
|
const path23 = await import("path");
|
|
88475
88617
|
const { findProjectRoot: findProjectRoot2 } = await Promise.resolve().then(() => (init_unified_memory(), unified_memory_exports));
|
|
@@ -88479,7 +88621,7 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
|
|
|
88479
88621
|
if (!fs21.existsSync(dir)) {
|
|
88480
88622
|
fs21.mkdirSync(dir, { recursive: true });
|
|
88481
88623
|
}
|
|
88482
|
-
this.hypergraphDb =
|
|
88624
|
+
this.hypergraphDb = openDatabase2(dbPath);
|
|
88483
88625
|
this.hypergraph = await createHypergraphEngine({
|
|
88484
88626
|
db: this.hypergraphDb,
|
|
88485
88627
|
maxTraversalDepth: 10,
|
|
@@ -89145,9 +89287,15 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
|
|
|
89145
89287
|
try {
|
|
89146
89288
|
console.log(`[CodeIntelligence] Collecting real metrics for ${projectPath}`);
|
|
89147
89289
|
const metrics = await this.metricCollector.collectAll(projectPath);
|
|
89290
|
+
const toolsLabel = metrics.toolsUsed.length > 0 ? metrics.toolsUsed.join(", ") : metrics.loc.source === "node-native" ? "node-native" : "fallback";
|
|
89148
89291
|
console.log(
|
|
89149
|
-
`[CodeIntelligence] Real metrics collected: ${metrics.loc.total} LOC, ${metrics.tests.total} tests, tools: ${
|
|
89292
|
+
`[CodeIntelligence] Real metrics collected: ${metrics.loc.total} LOC, ${metrics.tests.total} tests, tools: ${toolsLabel}`
|
|
89150
89293
|
);
|
|
89294
|
+
if (metrics.loc.source === "node-native") {
|
|
89295
|
+
console.log(
|
|
89296
|
+
`[CodeIntelligence] Using Node.js-native line counter (no cloc/tokei needed)`
|
|
89297
|
+
);
|
|
89298
|
+
}
|
|
89151
89299
|
await this.storeProjectMetricsInMemory(projectPath, metrics);
|
|
89152
89300
|
if (this.config.publishEvents) {
|
|
89153
89301
|
const event = createEvent(
|
|
@@ -132684,10 +132832,16 @@ function detectTransformType(task) {
|
|
|
132684
132832
|
}
|
|
132685
132833
|
async function loadCoverageData(targetPath) {
|
|
132686
132834
|
const coverageLocations = [
|
|
132835
|
+
// JavaScript/TypeScript (Istanbul/nyc/vitest)
|
|
132687
132836
|
path16.join(targetPath, "coverage", "coverage-final.json"),
|
|
132688
132837
|
path16.join(targetPath, "coverage", "lcov.info"),
|
|
132689
132838
|
path16.join(targetPath, ".nyc_output", "coverage-final.json"),
|
|
132690
|
-
path16.join(targetPath, "coverage-final.json")
|
|
132839
|
+
path16.join(targetPath, "coverage-final.json"),
|
|
132840
|
+
// Python (pytest-cov, coverage.py)
|
|
132841
|
+
path16.join(targetPath, "coverage.xml"),
|
|
132842
|
+
path16.join(targetPath, "htmlcov", "status.json"),
|
|
132843
|
+
// Cobertura (generic)
|
|
132844
|
+
path16.join(targetPath, "cobertura-coverage.xml")
|
|
132691
132845
|
];
|
|
132692
132846
|
for (const coveragePath of coverageLocations) {
|
|
132693
132847
|
try {
|
|
@@ -132696,6 +132850,8 @@ async function loadCoverageData(targetPath) {
|
|
|
132696
132850
|
return parseCoverageJson(content);
|
|
132697
132851
|
} else if (coveragePath.endsWith(".info")) {
|
|
132698
132852
|
return parseLcovInfo(content);
|
|
132853
|
+
} else if (coveragePath.endsWith(".xml")) {
|
|
132854
|
+
return parseCoberturaXml(content);
|
|
132699
132855
|
}
|
|
132700
132856
|
} catch {
|
|
132701
132857
|
}
|
|
@@ -132847,16 +133003,166 @@ function parseLcovInfo(content) {
|
|
|
132847
133003
|
}
|
|
132848
133004
|
};
|
|
132849
133005
|
}
|
|
133006
|
+
function parseCoberturaXml(content) {
|
|
133007
|
+
const files = [];
|
|
133008
|
+
function attr(element, name) {
|
|
133009
|
+
const match = element.match(new RegExp(`${name}=["']([^"']*)["']`));
|
|
133010
|
+
return match ? match[1] : null;
|
|
133011
|
+
}
|
|
133012
|
+
const classRegex = /<class\s[^>]*?>/g;
|
|
133013
|
+
let classMatch;
|
|
133014
|
+
while ((classMatch = classRegex.exec(content)) !== null) {
|
|
133015
|
+
const classTag = classMatch[0];
|
|
133016
|
+
const filename = attr(classTag, "filename");
|
|
133017
|
+
if (!filename) continue;
|
|
133018
|
+
const lineRate = parseFloat(attr(classTag, "line-rate") || "NaN");
|
|
133019
|
+
const branchRate = parseFloat(attr(classTag, "branch-rate") || "NaN");
|
|
133020
|
+
const classStart = classMatch.index;
|
|
133021
|
+
const classEnd = content.indexOf("</class>", classStart);
|
|
133022
|
+
const classContent = classEnd > classStart ? content.slice(classStart, classEnd) : "";
|
|
133023
|
+
let linesTotal = 0, linesCovered = 0;
|
|
133024
|
+
let branchesTotal = 0, branchesCovered = 0;
|
|
133025
|
+
let functionsTotal = 0, functionsCovered = 0;
|
|
133026
|
+
const uncoveredLines = [];
|
|
133027
|
+
const uncoveredBranches = [];
|
|
133028
|
+
const lineRegex = /<line\s([^>]*?)\/>/g;
|
|
133029
|
+
let lineMatch;
|
|
133030
|
+
while ((lineMatch = lineRegex.exec(classContent)) !== null) {
|
|
133031
|
+
const lineTag = lineMatch[1];
|
|
133032
|
+
const lineNum = parseInt(attr(lineTag, "number") || "0", 10);
|
|
133033
|
+
const hits = parseInt(attr(lineTag, "hits") || "0", 10);
|
|
133034
|
+
const isBranch = attr(lineTag, "branch") === "true";
|
|
133035
|
+
const condCoverage = attr(lineTag, "condition-coverage");
|
|
133036
|
+
linesTotal++;
|
|
133037
|
+
if (hits > 0) {
|
|
133038
|
+
linesCovered++;
|
|
133039
|
+
} else {
|
|
133040
|
+
uncoveredLines.push(lineNum);
|
|
133041
|
+
}
|
|
133042
|
+
if (isBranch) {
|
|
133043
|
+
branchesTotal++;
|
|
133044
|
+
const condPct = condCoverage ? parseInt(condCoverage, 10) : hits > 0 ? 100 : 0;
|
|
133045
|
+
if (condPct === 100) {
|
|
133046
|
+
branchesCovered++;
|
|
133047
|
+
} else {
|
|
133048
|
+
uncoveredBranches.push(lineNum);
|
|
133049
|
+
}
|
|
133050
|
+
}
|
|
133051
|
+
}
|
|
133052
|
+
const methodRegex = /<method\s([^>]*?)>/g;
|
|
133053
|
+
let methodMatch;
|
|
133054
|
+
while ((methodMatch = methodRegex.exec(classContent)) !== null) {
|
|
133055
|
+
functionsTotal++;
|
|
133056
|
+
const methodStart = methodMatch.index;
|
|
133057
|
+
const methodEnd = classContent.indexOf("</method>", methodStart);
|
|
133058
|
+
if (methodEnd > methodStart) {
|
|
133059
|
+
const methodContent = classContent.slice(methodStart, methodEnd);
|
|
133060
|
+
const methodLineRegex = /<line\s([^>]*?)\/>/g;
|
|
133061
|
+
let hasHits = false;
|
|
133062
|
+
let mLineMatch;
|
|
133063
|
+
while ((mLineMatch = methodLineRegex.exec(methodContent)) !== null) {
|
|
133064
|
+
if (parseInt(attr(mLineMatch[1], "hits") || "0", 10) > 0) {
|
|
133065
|
+
hasHits = true;
|
|
133066
|
+
break;
|
|
133067
|
+
}
|
|
133068
|
+
}
|
|
133069
|
+
if (hasHits) functionsCovered++;
|
|
133070
|
+
}
|
|
133071
|
+
}
|
|
133072
|
+
if (linesTotal === 0 && !isNaN(lineRate)) {
|
|
133073
|
+
linesTotal = 1;
|
|
133074
|
+
linesCovered = lineRate >= 0.5 ? 1 : 0;
|
|
133075
|
+
}
|
|
133076
|
+
files.push({
|
|
133077
|
+
path: filename,
|
|
133078
|
+
lines: { covered: linesCovered, total: linesTotal },
|
|
133079
|
+
branches: { covered: branchesCovered, total: branchesTotal },
|
|
133080
|
+
functions: { covered: functionsCovered, total: functionsTotal },
|
|
133081
|
+
statements: { covered: linesCovered, total: linesTotal },
|
|
133082
|
+
uncoveredLines,
|
|
133083
|
+
uncoveredBranches
|
|
133084
|
+
});
|
|
133085
|
+
}
|
|
133086
|
+
let totalLines = 0, totalCoveredLines = 0;
|
|
133087
|
+
let totalBranches = 0, totalCoveredBranches = 0;
|
|
133088
|
+
let totalFunctions = 0, totalCoveredFunctions = 0;
|
|
133089
|
+
for (const file of files) {
|
|
133090
|
+
totalLines += file.lines.total;
|
|
133091
|
+
totalCoveredLines += file.lines.covered;
|
|
133092
|
+
totalBranches += file.branches.total;
|
|
133093
|
+
totalCoveredBranches += file.branches.covered;
|
|
133094
|
+
totalFunctions += file.functions.total;
|
|
133095
|
+
totalCoveredFunctions += file.functions.covered;
|
|
133096
|
+
}
|
|
133097
|
+
const coverageTag = content.match(/<coverage\s[^>]*?>/);
|
|
133098
|
+
const summaryLineRate = coverageTag ? parseFloat(attr(coverageTag[0], "line-rate") || "NaN") * 100 : NaN;
|
|
133099
|
+
const summaryBranchRate = coverageTag ? parseFloat(attr(coverageTag[0], "branch-rate") || "NaN") * 100 : NaN;
|
|
133100
|
+
return {
|
|
133101
|
+
files,
|
|
133102
|
+
summary: {
|
|
133103
|
+
line: !isNaN(summaryLineRate) ? summaryLineRate : totalLines > 0 ? totalCoveredLines / totalLines * 100 : 0,
|
|
133104
|
+
branch: !isNaN(summaryBranchRate) ? summaryBranchRate : totalBranches > 0 ? totalCoveredBranches / totalBranches * 100 : 0,
|
|
133105
|
+
function: totalFunctions > 0 ? totalCoveredFunctions / totalFunctions * 100 : 0,
|
|
133106
|
+
statement: totalLines > 0 ? totalCoveredLines / totalLines * 100 : 0,
|
|
133107
|
+
files: files.length
|
|
133108
|
+
}
|
|
133109
|
+
};
|
|
133110
|
+
}
|
|
132850
133111
|
async function discoverSourceFiles(targetPath, options = {}) {
|
|
132851
133112
|
const files = [];
|
|
132852
133113
|
const { includeTests = true, languages } = options;
|
|
132853
|
-
let extensions = [
|
|
133114
|
+
let extensions = [
|
|
133115
|
+
".ts",
|
|
133116
|
+
".tsx",
|
|
133117
|
+
".js",
|
|
133118
|
+
".jsx",
|
|
133119
|
+
".mjs",
|
|
133120
|
+
".cjs",
|
|
133121
|
+
// JavaScript/TypeScript
|
|
133122
|
+
".py",
|
|
133123
|
+
".pyw",
|
|
133124
|
+
// Python
|
|
133125
|
+
".go",
|
|
133126
|
+
// Go
|
|
133127
|
+
".rs",
|
|
133128
|
+
// Rust
|
|
133129
|
+
".java",
|
|
133130
|
+
".kt",
|
|
133131
|
+
".kts",
|
|
133132
|
+
// Java/Kotlin
|
|
133133
|
+
".rb",
|
|
133134
|
+
// Ruby
|
|
133135
|
+
".cs",
|
|
133136
|
+
// C#
|
|
133137
|
+
".php",
|
|
133138
|
+
// PHP
|
|
133139
|
+
".swift",
|
|
133140
|
+
// Swift
|
|
133141
|
+
".c",
|
|
133142
|
+
".h",
|
|
133143
|
+
".cpp",
|
|
133144
|
+
".hpp",
|
|
133145
|
+
".cc",
|
|
133146
|
+
// C/C++
|
|
133147
|
+
".scala"
|
|
133148
|
+
// Scala
|
|
133149
|
+
];
|
|
132854
133150
|
if (languages && languages.length > 0) {
|
|
132855
133151
|
extensions = [];
|
|
132856
133152
|
for (const lang of languages) {
|
|
132857
133153
|
if (lang === "typescript") extensions.push(".ts", ".tsx");
|
|
132858
133154
|
if (lang === "javascript") extensions.push(".js", ".jsx", ".mjs", ".cjs");
|
|
132859
|
-
if (lang === "python") extensions.push(".py");
|
|
133155
|
+
if (lang === "python") extensions.push(".py", ".pyw");
|
|
133156
|
+
if (lang === "go") extensions.push(".go");
|
|
133157
|
+
if (lang === "rust") extensions.push(".rs");
|
|
133158
|
+
if (lang === "java") extensions.push(".java");
|
|
133159
|
+
if (lang === "kotlin") extensions.push(".kt", ".kts");
|
|
133160
|
+
if (lang === "ruby") extensions.push(".rb");
|
|
133161
|
+
if (lang === "csharp" || lang === "c#") extensions.push(".cs");
|
|
133162
|
+
if (lang === "php") extensions.push(".php");
|
|
133163
|
+
if (lang === "swift") extensions.push(".swift");
|
|
133164
|
+
if (lang === "c" || lang === "cpp" || lang === "c++") extensions.push(".c", ".h", ".cpp", ".hpp", ".cc");
|
|
133165
|
+
if (lang === "scala") extensions.push(".scala");
|
|
132860
133166
|
}
|
|
132861
133167
|
}
|
|
132862
133168
|
async function walkDir(dir) {
|
|
@@ -132865,7 +133171,23 @@ async function discoverSourceFiles(targetPath, options = {}) {
|
|
|
132865
133171
|
for (const entry of entries) {
|
|
132866
133172
|
const fullPath = path16.join(dir, entry.name);
|
|
132867
133173
|
if (entry.isDirectory()) {
|
|
132868
|
-
if ([
|
|
133174
|
+
if ([
|
|
133175
|
+
"node_modules",
|
|
133176
|
+
".git",
|
|
133177
|
+
"dist",
|
|
133178
|
+
"build",
|
|
133179
|
+
"coverage",
|
|
133180
|
+
".nyc_output",
|
|
133181
|
+
"__pycache__",
|
|
133182
|
+
".venv",
|
|
133183
|
+
"venv",
|
|
133184
|
+
".tox",
|
|
133185
|
+
".mypy_cache",
|
|
133186
|
+
"target",
|
|
133187
|
+
".gradle",
|
|
133188
|
+
"vendor",
|
|
133189
|
+
".bundle"
|
|
133190
|
+
].includes(entry.name)) {
|
|
132869
133191
|
continue;
|
|
132870
133192
|
}
|
|
132871
133193
|
await walkDir(fullPath);
|
|
@@ -133031,7 +133353,24 @@ var DomainTaskExecutor = class {
|
|
|
133031
133353
|
} else if (payload.filePath) {
|
|
133032
133354
|
sourceFiles = [payload.filePath];
|
|
133033
133355
|
} else if (payload.sourceCode) {
|
|
133034
|
-
const
|
|
133356
|
+
const langExtMap = {
|
|
133357
|
+
python: ".py",
|
|
133358
|
+
typescript: ".ts",
|
|
133359
|
+
javascript: ".js",
|
|
133360
|
+
go: ".go",
|
|
133361
|
+
rust: ".rs",
|
|
133362
|
+
java: ".java",
|
|
133363
|
+
ruby: ".rb",
|
|
133364
|
+
kotlin: ".kt",
|
|
133365
|
+
csharp: ".cs",
|
|
133366
|
+
php: ".php",
|
|
133367
|
+
swift: ".swift",
|
|
133368
|
+
cpp: ".cpp",
|
|
133369
|
+
c: ".c",
|
|
133370
|
+
scala: ".scala"
|
|
133371
|
+
};
|
|
133372
|
+
const ext = langExtMap[payload.language?.toLowerCase() || "typescript"] || ".ts";
|
|
133373
|
+
const tempPath = `/tmp/aqe-temp-${v4_default()}${ext}`;
|
|
133035
133374
|
await fs15.writeFile(tempPath, payload.sourceCode, "utf-8");
|
|
133036
133375
|
sourceFiles = [tempPath];
|
|
133037
133376
|
}
|
|
@@ -133147,12 +133486,112 @@ var DomainTaskExecutor = class {
|
|
|
133147
133486
|
sast: payload.sast !== false,
|
|
133148
133487
|
dast: payload.dast || false
|
|
133149
133488
|
},
|
|
133150
|
-
warning: `No
|
|
133489
|
+
warning: `No source files found in ${targetPath}`
|
|
133151
133490
|
});
|
|
133152
133491
|
}
|
|
133153
|
-
const
|
|
133492
|
+
const jstsFiles = filesToScan.filter((f74) => /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(f74));
|
|
133493
|
+
const otherFiles = filesToScan.filter((f74) => !/\.(ts|tsx|js|jsx|mjs|cjs)$/.test(f74));
|
|
133494
|
+
const crossLangVulns = [];
|
|
133495
|
+
for (const filePath of otherFiles) {
|
|
133496
|
+
try {
|
|
133497
|
+
const content = await fs15.readFile(filePath, "utf-8");
|
|
133498
|
+
const lines = content.split("\n");
|
|
133499
|
+
const relPath = filePath.startsWith(targetPath) ? filePath.slice(targetPath.length).replace(/^\//, "") : filePath;
|
|
133500
|
+
const secretPatterns = [
|
|
133501
|
+
{ regex: /\w*(?:secret|password|passwd|api_key|apikey|private_key|jwt_secret)\w*\s*[=:]\s*['"][^'"]{4,}['"]/gi, title: "Hardcoded secret", severity: "critical" },
|
|
133502
|
+
{ regex: /\w*(?:token|auth_token|access_key|secret_key)\w*\s*[=:]\s*['"][^'"]{8,}['"]/gi, title: "Hardcoded credential", severity: "critical" },
|
|
133503
|
+
{ regex: /(?:AWS_SECRET|GITHUB_TOKEN|SLACK_TOKEN|OPENAI_API_KEY)\s*[=:]\s*['"][^'"]+['"]/gi, title: "Hardcoded cloud credential", severity: "critical" }
|
|
133504
|
+
];
|
|
133505
|
+
for (const pattern of secretPatterns) {
|
|
133506
|
+
for (let i58 = 0; i58 < lines.length; i58++) {
|
|
133507
|
+
const matches = [...lines[i58].matchAll(pattern.regex)];
|
|
133508
|
+
for (const _m of matches) {
|
|
133509
|
+
crossLangVulns.push({
|
|
133510
|
+
title: pattern.title,
|
|
133511
|
+
severity: pattern.severity,
|
|
133512
|
+
location: { file: relPath, line: i58 + 1 },
|
|
133513
|
+
description: `Potential hardcoded secret found at line ${i58 + 1}`,
|
|
133514
|
+
category: "sensitive-data"
|
|
133515
|
+
});
|
|
133516
|
+
}
|
|
133517
|
+
}
|
|
133518
|
+
}
|
|
133519
|
+
const sqlPatterns = /(?:execute|query|cursor\.execute)\s*\(\s*(?:f['"]|['"].*%s|['"].*\+\s*\w)/gi;
|
|
133520
|
+
for (let i58 = 0; i58 < lines.length; i58++) {
|
|
133521
|
+
if (sqlPatterns.test(lines[i58])) {
|
|
133522
|
+
crossLangVulns.push({
|
|
133523
|
+
title: "Potential SQL injection",
|
|
133524
|
+
severity: "high",
|
|
133525
|
+
location: { file: relPath, line: i58 + 1 },
|
|
133526
|
+
description: "String interpolation in SQL query \u2014 use parameterized queries",
|
|
133527
|
+
category: "injection"
|
|
133528
|
+
});
|
|
133529
|
+
}
|
|
133530
|
+
sqlPatterns.lastIndex = 0;
|
|
133531
|
+
}
|
|
133532
|
+
const corsPatterns = [
|
|
133533
|
+
/allow_origins\s*=\s*\[?\s*['"]?\*['"]?\s*\]?/i,
|
|
133534
|
+
// Python FastAPI/Flask
|
|
133535
|
+
/cors\(\s*\{[^}]*origin:\s*['"]?\*['"]?/i,
|
|
133536
|
+
// Express.js cors()
|
|
133537
|
+
/Access-Control-Allow-Origin['":\s]+\*/i,
|
|
133538
|
+
// Raw header / Nginx / .htaccess
|
|
133539
|
+
/@CrossOrigin\(\s*origins?\s*=\s*["']\*["']/i,
|
|
133540
|
+
// Spring Boot
|
|
133541
|
+
/\.Header\(\)\.Set\(["']Access-Control-Allow-Origin["'],\s*["']\*["']/i
|
|
133542
|
+
// Go
|
|
133543
|
+
];
|
|
133544
|
+
for (const corsPattern of corsPatterns) {
|
|
133545
|
+
if (corsPattern.test(content)) {
|
|
133546
|
+
crossLangVulns.push({
|
|
133547
|
+
title: "CORS wildcard origin",
|
|
133548
|
+
severity: "high",
|
|
133549
|
+
location: { file: relPath, line: lines.findIndex((l75) => corsPattern.test(l75)) + 1 },
|
|
133550
|
+
description: "CORS configured with wildcard (*) origin \u2014 restrict to specific domains",
|
|
133551
|
+
category: "security-misconfiguration"
|
|
133552
|
+
});
|
|
133553
|
+
break;
|
|
133554
|
+
}
|
|
133555
|
+
}
|
|
133556
|
+
if (/(?:DEBUG|debug)\s*[=:]\s*(?:True|true|1)/i.test(content)) {
|
|
133557
|
+
crossLangVulns.push({
|
|
133558
|
+
title: "Debug mode enabled",
|
|
133559
|
+
severity: "medium",
|
|
133560
|
+
location: { file: relPath, line: lines.findIndex((l75) => /DEBUG\s*[=:]\s*(?:True|true|1)/i.test(l75)) + 1 },
|
|
133561
|
+
description: "Debug mode should be disabled in production",
|
|
133562
|
+
category: "security-misconfiguration"
|
|
133563
|
+
});
|
|
133564
|
+
}
|
|
133565
|
+
if (/\b(?:eval|exec)\s*\(/i.test(content)) {
|
|
133566
|
+
crossLangVulns.push({
|
|
133567
|
+
title: "Dangerous eval/exec usage",
|
|
133568
|
+
severity: "high",
|
|
133569
|
+
location: { file: relPath, line: lines.findIndex((l75) => /\b(?:eval|exec)\s*\(/.test(l75)) + 1 },
|
|
133570
|
+
description: "eval/exec can lead to code injection \u2014 avoid using with user input",
|
|
133571
|
+
category: "injection"
|
|
133572
|
+
});
|
|
133573
|
+
}
|
|
133574
|
+
} catch {
|
|
133575
|
+
}
|
|
133576
|
+
}
|
|
133577
|
+
const depManifests = ["requirements.txt", "pyproject.toml", "Gemfile", "go.mod", "Cargo.toml"];
|
|
133578
|
+
for (const manifest of depManifests) {
|
|
133579
|
+
const manifestPath = path16.join(targetPath, manifest);
|
|
133580
|
+
try {
|
|
133581
|
+
await fs15.access(manifestPath);
|
|
133582
|
+
crossLangVulns.push({
|
|
133583
|
+
title: "Dependency audit recommended",
|
|
133584
|
+
severity: "informational",
|
|
133585
|
+
location: { file: manifest, line: 1 },
|
|
133586
|
+
description: `Found ${manifest} \u2014 run language-specific dependency audit (e.g., pip-audit, npm audit, cargo audit)`,
|
|
133587
|
+
category: "dependencies"
|
|
133588
|
+
});
|
|
133589
|
+
} catch {
|
|
133590
|
+
}
|
|
133591
|
+
}
|
|
133592
|
+
const filePathObjects = jstsFiles.map((filePath) => FilePath.create(filePath));
|
|
133154
133593
|
let sastResult = null;
|
|
133155
|
-
if (payload.sast !== false) {
|
|
133594
|
+
if (payload.sast !== false && filePathObjects.length > 0) {
|
|
133156
133595
|
const result = await scanner.scanFiles(filePathObjects);
|
|
133157
133596
|
if (result.success) {
|
|
133158
133597
|
sastResult = result.value;
|
|
@@ -133169,16 +133608,24 @@ var DomainTaskExecutor = class {
|
|
|
133169
133608
|
dastResult = result.value;
|
|
133170
133609
|
}
|
|
133171
133610
|
}
|
|
133611
|
+
const crossLangSeverityCounts = {
|
|
133612
|
+
critical: crossLangVulns.filter((v62) => v62.severity === "critical").length,
|
|
133613
|
+
high: crossLangVulns.filter((v62) => v62.severity === "high").length,
|
|
133614
|
+
medium: crossLangVulns.filter((v62) => v62.severity === "medium").length,
|
|
133615
|
+
low: crossLangVulns.filter((v62) => v62.severity === "low").length,
|
|
133616
|
+
informational: crossLangVulns.filter((v62) => v62.severity === "informational").length
|
|
133617
|
+
};
|
|
133172
133618
|
const summary = {
|
|
133173
|
-
critical: (sastResult?.summary?.critical || 0) + (dastResult?.summary?.critical || 0),
|
|
133174
|
-
high: (sastResult?.summary?.high || 0) + (dastResult?.summary?.high || 0),
|
|
133175
|
-
medium: (sastResult?.summary?.medium || 0) + (dastResult?.summary?.medium || 0),
|
|
133176
|
-
low: (sastResult?.summary?.low || 0) + (dastResult?.summary?.low || 0),
|
|
133177
|
-
informational: (sastResult?.summary?.informational || 0) + (dastResult?.summary?.informational || 0)
|
|
133619
|
+
critical: (sastResult?.summary?.critical || 0) + (dastResult?.summary?.critical || 0) + crossLangSeverityCounts.critical,
|
|
133620
|
+
high: (sastResult?.summary?.high || 0) + (dastResult?.summary?.high || 0) + crossLangSeverityCounts.high,
|
|
133621
|
+
medium: (sastResult?.summary?.medium || 0) + (dastResult?.summary?.medium || 0) + crossLangSeverityCounts.medium,
|
|
133622
|
+
low: (sastResult?.summary?.low || 0) + (dastResult?.summary?.low || 0) + crossLangSeverityCounts.low,
|
|
133623
|
+
informational: (sastResult?.summary?.informational || 0) + (dastResult?.summary?.informational || 0) + crossLangSeverityCounts.informational
|
|
133178
133624
|
};
|
|
133179
133625
|
const allVulns = [
|
|
133180
133626
|
...sastResult?.vulnerabilities || [],
|
|
133181
|
-
...dastResult?.vulnerabilities || []
|
|
133627
|
+
...dastResult?.vulnerabilities || [],
|
|
133628
|
+
...crossLangVulns
|
|
133182
133629
|
];
|
|
133183
133630
|
const topVulnerabilities = allVulns.sort((a37, b68) => {
|
|
133184
133631
|
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, informational: 4 };
|
|
@@ -133205,7 +133652,12 @@ var DomainTaskExecutor = class {
|
|
|
133205
133652
|
dast: payload.dast || false
|
|
133206
133653
|
},
|
|
133207
133654
|
filesScanned: filesToScan.length,
|
|
133208
|
-
|
|
133655
|
+
jstsFilesScanned: jstsFiles.length,
|
|
133656
|
+
otherFilesScanned: otherFiles.length,
|
|
133657
|
+
coverage: sastResult?.coverage,
|
|
133658
|
+
...otherFiles.length > 0 && jstsFiles.length === 0 ? {
|
|
133659
|
+
note: "Non-JS/TS files were scanned with cross-language pattern matching. For deeper analysis, use language-specific security tools."
|
|
133660
|
+
} : {}
|
|
133209
133661
|
});
|
|
133210
133662
|
} catch (error) {
|
|
133211
133663
|
return err(toError(error));
|
|
@@ -133228,9 +133680,9 @@ var DomainTaskExecutor = class {
|
|
|
133228
133680
|
edgesCreated: 0,
|
|
133229
133681
|
target: targetPath,
|
|
133230
133682
|
incremental: payload.incremental || false,
|
|
133231
|
-
languages: payload.languages || [
|
|
133683
|
+
languages: payload.languages || [],
|
|
133232
133684
|
duration: Date.now() - startTime,
|
|
133233
|
-
warning: `No source files found in ${targetPath}
|
|
133685
|
+
warning: `No source files found in ${targetPath}. Searched for: TypeScript, JavaScript, Python, Go, Rust, Java, Ruby, C/C++, and more.`
|
|
133234
133686
|
});
|
|
133235
133687
|
}
|
|
133236
133688
|
const result = await kg.index({
|
|
@@ -133244,11 +133696,35 @@ var DomainTaskExecutor = class {
|
|
|
133244
133696
|
}
|
|
133245
133697
|
const indexResult = result.value;
|
|
133246
133698
|
const detectedLanguages = /* @__PURE__ */ new Set();
|
|
133699
|
+
const extToLang = {
|
|
133700
|
+
ts: "typescript",
|
|
133701
|
+
tsx: "typescript",
|
|
133702
|
+
js: "javascript",
|
|
133703
|
+
jsx: "javascript",
|
|
133704
|
+
mjs: "javascript",
|
|
133705
|
+
cjs: "javascript",
|
|
133706
|
+
py: "python",
|
|
133707
|
+
pyw: "python",
|
|
133708
|
+
go: "go",
|
|
133709
|
+
rs: "rust",
|
|
133710
|
+
java: "java",
|
|
133711
|
+
kt: "kotlin",
|
|
133712
|
+
kts: "kotlin",
|
|
133713
|
+
rb: "ruby",
|
|
133714
|
+
cs: "csharp",
|
|
133715
|
+
php: "php",
|
|
133716
|
+
swift: "swift",
|
|
133717
|
+
c: "c",
|
|
133718
|
+
h: "c",
|
|
133719
|
+
cpp: "cpp",
|
|
133720
|
+
hpp: "cpp",
|
|
133721
|
+
cc: "cpp",
|
|
133722
|
+
scala: "scala"
|
|
133723
|
+
};
|
|
133247
133724
|
for (const file of filesToIndex) {
|
|
133248
133725
|
const ext = path16.extname(file).slice(1);
|
|
133249
|
-
|
|
133250
|
-
if (
|
|
133251
|
-
if (ext === "py") detectedLanguages.add("python");
|
|
133726
|
+
const lang = extToLang[ext];
|
|
133727
|
+
if (lang) detectedLanguages.add(lang);
|
|
133252
133728
|
}
|
|
133253
133729
|
return ok({
|
|
133254
133730
|
filesIndexed: indexResult.filesIndexed,
|
|
@@ -133330,106 +133806,271 @@ var DomainTaskExecutor = class {
|
|
|
133330
133806
|
});
|
|
133331
133807
|
this.taskHandlers.set("execute-tests", async (task) => {
|
|
133332
133808
|
const payload = task.payload;
|
|
133333
|
-
|
|
133334
|
-
|
|
133335
|
-
|
|
133336
|
-
|
|
133337
|
-
|
|
133338
|
-
|
|
133339
|
-
|
|
133340
|
-
|
|
133341
|
-
|
|
133342
|
-
|
|
133343
|
-
|
|
133344
|
-
|
|
133345
|
-
|
|
133809
|
+
try {
|
|
133810
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
133811
|
+
const testFiles = payload.testFiles || [];
|
|
133812
|
+
if (testFiles.length === 0) {
|
|
133813
|
+
return ok({
|
|
133814
|
+
total: 0,
|
|
133815
|
+
passed: 0,
|
|
133816
|
+
failed: 0,
|
|
133817
|
+
skipped: 0,
|
|
133818
|
+
duration: 0,
|
|
133819
|
+
coverage: 0,
|
|
133820
|
+
failedTests: [],
|
|
133821
|
+
warning: "No test files specified. Provide testFiles array with paths to test files."
|
|
133822
|
+
});
|
|
133823
|
+
}
|
|
133824
|
+
const cwd = process.cwd();
|
|
133825
|
+
let output;
|
|
133826
|
+
try {
|
|
133827
|
+
output = execSync6(
|
|
133828
|
+
`npx vitest run ${testFiles.join(" ")} --reporter=json 2>/dev/null || npx jest ${testFiles.join(" ")} --json 2>/dev/null`,
|
|
133829
|
+
{ cwd, timeout: 12e4, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
133830
|
+
);
|
|
133831
|
+
} catch (execError) {
|
|
133832
|
+
output = execError.stdout || "";
|
|
133833
|
+
}
|
|
133834
|
+
try {
|
|
133835
|
+
const jsonStart = output.indexOf("{");
|
|
133836
|
+
if (jsonStart >= 0) {
|
|
133837
|
+
const json = JSON.parse(output.slice(jsonStart));
|
|
133838
|
+
if (json.testResults) {
|
|
133839
|
+
const total = json.numTotalTests || 0;
|
|
133840
|
+
const passed = json.numPassedTests || 0;
|
|
133841
|
+
const failed = json.numFailedTests || 0;
|
|
133842
|
+
return ok({ total, passed, failed, skipped: total - passed - failed, duration: 0, coverage: 0, failedTests: [] });
|
|
133843
|
+
}
|
|
133844
|
+
}
|
|
133845
|
+
} catch {
|
|
133846
|
+
}
|
|
133847
|
+
return ok({
|
|
133848
|
+
total: testFiles.length,
|
|
133849
|
+
passed: 0,
|
|
133850
|
+
failed: 0,
|
|
133851
|
+
skipped: 0,
|
|
133852
|
+
duration: 0,
|
|
133853
|
+
coverage: 0,
|
|
133854
|
+
failedTests: [],
|
|
133855
|
+
warning: "Could not parse test runner output. Check that vitest or jest is installed.",
|
|
133856
|
+
rawOutput: output.slice(0, 500)
|
|
133857
|
+
});
|
|
133858
|
+
} catch (error) {
|
|
133859
|
+
return err(toError(error));
|
|
133860
|
+
}
|
|
133346
133861
|
});
|
|
133347
133862
|
this.taskHandlers.set("predict-defects", async (task) => {
|
|
133348
133863
|
const payload = task.payload;
|
|
133349
|
-
|
|
133350
|
-
|
|
133351
|
-
|
|
133352
|
-
|
|
133353
|
-
|
|
133354
|
-
|
|
133355
|
-
|
|
133356
|
-
|
|
133357
|
-
|
|
133358
|
-
|
|
133359
|
-
|
|
133864
|
+
try {
|
|
133865
|
+
const targetPath = payload.target || process.cwd();
|
|
133866
|
+
const minConfidence = payload.minConfidence || 0.5;
|
|
133867
|
+
const sourceFiles = await discoverSourceFiles(targetPath, { includeTests: false });
|
|
133868
|
+
if (sourceFiles.length === 0) {
|
|
133869
|
+
return ok({
|
|
133870
|
+
predictedDefects: [],
|
|
133871
|
+
riskScore: 0,
|
|
133872
|
+
recommendations: [
|
|
133873
|
+
`No source files found in ${targetPath}. Ensure the path contains source code files.`
|
|
133874
|
+
],
|
|
133875
|
+
warning: `No source files found in ${targetPath}`,
|
|
133876
|
+
filesAnalyzed: 0
|
|
133877
|
+
});
|
|
133878
|
+
}
|
|
133879
|
+
const predictedDefects = [];
|
|
133880
|
+
for (const filePath of sourceFiles) {
|
|
133881
|
+
try {
|
|
133882
|
+
const content = await fs15.readFile(filePath, "utf-8");
|
|
133883
|
+
const lines = content.split("\n");
|
|
133884
|
+
const lineCount = lines.length;
|
|
133885
|
+
let probability = 0;
|
|
133886
|
+
const reasons = [];
|
|
133887
|
+
if (lineCount > 500) {
|
|
133888
|
+
probability += 0.25;
|
|
133889
|
+
reasons.push(`Large file (${lineCount} lines)`);
|
|
133890
|
+
} else if (lineCount > 300) {
|
|
133891
|
+
probability += 0.15;
|
|
133892
|
+
reasons.push(`Medium-large file (${lineCount} lines)`);
|
|
133893
|
+
}
|
|
133894
|
+
const branchKeywords = content.match(/\b(if|else|switch|case|for|while|catch|&&|\|\|)\b/g) || [];
|
|
133895
|
+
const branchDensity = branchKeywords.length / Math.max(lineCount, 1);
|
|
133896
|
+
if (branchDensity > 0.15) {
|
|
133897
|
+
probability += 0.25;
|
|
133898
|
+
reasons.push(`High branch density (${branchKeywords.length} branches in ${lineCount} lines)`);
|
|
133899
|
+
} else if (branchDensity > 0.08) {
|
|
133900
|
+
probability += 0.1;
|
|
133901
|
+
reasons.push("Moderate branch complexity");
|
|
133902
|
+
}
|
|
133903
|
+
const maxIndent = Math.max(...lines.map((l75) => {
|
|
133904
|
+
const match = l75.match(/^(\s*)/);
|
|
133905
|
+
return match ? match[1].length : 0;
|
|
133906
|
+
}));
|
|
133907
|
+
if (maxIndent > 20) {
|
|
133908
|
+
probability += 0.15;
|
|
133909
|
+
reasons.push("Deep nesting detected");
|
|
133910
|
+
}
|
|
133911
|
+
const debtComments = (content.match(/\b(TODO|FIXME|HACK|XXX|WORKAROUND)\b/gi) || []).length;
|
|
133912
|
+
if (debtComments > 3) {
|
|
133913
|
+
probability += 0.15;
|
|
133914
|
+
reasons.push(`${debtComments} technical debt markers`);
|
|
133915
|
+
}
|
|
133916
|
+
const functionStarts = (content.match(/\b(function|def|func|async)\b/g) || []).length;
|
|
133917
|
+
if (functionStarts > 0 && lineCount / functionStarts > 80) {
|
|
133918
|
+
probability += 0.1;
|
|
133919
|
+
reasons.push("Potentially long functions");
|
|
133920
|
+
}
|
|
133921
|
+
probability = Math.min(probability, 0.95);
|
|
133922
|
+
if (probability >= minConfidence) {
|
|
133923
|
+
const relativePath = filePath.startsWith(targetPath) ? filePath.slice(targetPath.length).replace(/^\//, "") : filePath;
|
|
133924
|
+
predictedDefects.push({
|
|
133925
|
+
file: relativePath,
|
|
133926
|
+
probability: Math.round(probability * 100) / 100,
|
|
133927
|
+
reason: reasons.join("; ")
|
|
133928
|
+
});
|
|
133929
|
+
}
|
|
133930
|
+
} catch {
|
|
133360
133931
|
}
|
|
133361
|
-
|
|
133362
|
-
|
|
133363
|
-
|
|
133364
|
-
|
|
133365
|
-
|
|
133366
|
-
|
|
133367
|
-
|
|
133932
|
+
}
|
|
133933
|
+
predictedDefects.sort((a37, b68) => b68.probability - a37.probability);
|
|
133934
|
+
const avgProb = predictedDefects.length > 0 ? predictedDefects.reduce((sum, d74) => sum + d74.probability, 0) / predictedDefects.length : 0;
|
|
133935
|
+
const riskScore = Math.round(avgProb * 100);
|
|
133936
|
+
const recommendations = [];
|
|
133937
|
+
if (predictedDefects.length > 0) {
|
|
133938
|
+
recommendations.push(`${predictedDefects.length} files flagged for potential defects out of ${sourceFiles.length} analyzed`);
|
|
133939
|
+
const topFile = predictedDefects[0];
|
|
133940
|
+
recommendations.push(`Highest risk: ${topFile.file} (${Math.round(topFile.probability * 100)}%) \u2014 ${topFile.reason}`);
|
|
133941
|
+
}
|
|
133942
|
+
if (predictedDefects.some((d74) => d74.reason.includes("Large file"))) {
|
|
133943
|
+
recommendations.push("Consider splitting large files to reduce complexity");
|
|
133944
|
+
}
|
|
133945
|
+
if (predictedDefects.some((d74) => d74.reason.includes("technical debt"))) {
|
|
133946
|
+
recommendations.push("Address TODO/FIXME comments to reduce technical debt");
|
|
133947
|
+
}
|
|
133948
|
+
if (predictedDefects.length === 0) {
|
|
133949
|
+
recommendations.push("No files exceeded the defect probability threshold \u2014 code looks healthy");
|
|
133950
|
+
}
|
|
133951
|
+
return ok({
|
|
133952
|
+
predictedDefects: predictedDefects.slice(0, 20),
|
|
133953
|
+
// Top 20
|
|
133954
|
+
riskScore,
|
|
133955
|
+
recommendations,
|
|
133956
|
+
filesAnalyzed: sourceFiles.length
|
|
133957
|
+
});
|
|
133958
|
+
} catch (error) {
|
|
133959
|
+
return err(toError(error));
|
|
133960
|
+
}
|
|
133368
133961
|
});
|
|
133369
133962
|
this.taskHandlers.set("validate-requirements", async (task) => {
|
|
133370
133963
|
const payload = task.payload;
|
|
133371
|
-
|
|
133372
|
-
|
|
133373
|
-
|
|
133374
|
-
|
|
133375
|
-
|
|
133376
|
-
|
|
133377
|
-
|
|
133378
|
-
|
|
133379
|
-
|
|
133380
|
-
|
|
133381
|
-
|
|
133964
|
+
try {
|
|
133965
|
+
const targetPath = payload.requirementsPath || process.cwd();
|
|
133966
|
+
const reqFiles = await discoverSourceFiles(targetPath, {
|
|
133967
|
+
includeTests: false,
|
|
133968
|
+
languages: []
|
|
133969
|
+
});
|
|
133970
|
+
const reqPatterns = [".md", ".feature", ".gherkin", ".txt", ".rst"];
|
|
133971
|
+
const requirementFiles = [];
|
|
133972
|
+
for (const f74 of reqFiles) {
|
|
133973
|
+
if (reqPatterns.some((ext) => f74.endsWith(ext))) {
|
|
133974
|
+
requirementFiles.push(f74);
|
|
133975
|
+
}
|
|
133976
|
+
}
|
|
133977
|
+
return ok({
|
|
133978
|
+
requirementsAnalyzed: requirementFiles.length,
|
|
133979
|
+
testable: 0,
|
|
133980
|
+
ambiguous: 0,
|
|
133981
|
+
untestable: 0,
|
|
133982
|
+
coverage: 0,
|
|
133983
|
+
bddScenarios: [],
|
|
133984
|
+
warning: requirementFiles.length === 0 ? "No requirement files (.md, .feature, .gherkin) found. Provide requirementsPath or add requirement docs." : "Requirements validation requires LLM analysis. File inventory returned \u2014 use task_orchestrate for deep analysis.",
|
|
133985
|
+
files: requirementFiles.map((f74) => f74.startsWith(targetPath) ? f74.slice(targetPath.length + 1) : f74).slice(0, 20)
|
|
133986
|
+
});
|
|
133987
|
+
} catch (error) {
|
|
133988
|
+
return err(toError(error));
|
|
133989
|
+
}
|
|
133382
133990
|
});
|
|
133383
133991
|
this.taskHandlers.set("validate-contracts", async (task) => {
|
|
133384
133992
|
const payload = task.payload;
|
|
133385
|
-
|
|
133386
|
-
|
|
133387
|
-
|
|
133388
|
-
|
|
133389
|
-
|
|
133390
|
-
|
|
133391
|
-
|
|
133392
|
-
|
|
133393
|
-
|
|
133993
|
+
try {
|
|
133994
|
+
if (!payload.contractPath) {
|
|
133995
|
+
return ok({
|
|
133996
|
+
contractPath: "",
|
|
133997
|
+
valid: false,
|
|
133998
|
+
breakingChanges: [],
|
|
133999
|
+
warnings: [],
|
|
134000
|
+
coverage: 0,
|
|
134001
|
+
error: "contractPath is required. Provide a path to an OpenAPI spec, JSON Schema, or Protocol Buffer file."
|
|
134002
|
+
});
|
|
134003
|
+
}
|
|
134004
|
+
try {
|
|
134005
|
+
const content = await fs15.readFile(payload.contractPath, "utf-8");
|
|
134006
|
+
const isJson = payload.contractPath.endsWith(".json");
|
|
134007
|
+
const isYaml = payload.contractPath.endsWith(".yaml") || payload.contractPath.endsWith(".yml");
|
|
134008
|
+
if (isJson) {
|
|
134009
|
+
JSON.parse(content);
|
|
134010
|
+
}
|
|
134011
|
+
return ok({
|
|
134012
|
+
contractPath: payload.contractPath,
|
|
134013
|
+
valid: true,
|
|
134014
|
+
format: isJson ? "json" : isYaml ? "yaml" : "unknown",
|
|
134015
|
+
breakingChanges: [],
|
|
134016
|
+
warnings: [],
|
|
134017
|
+
linesAnalyzed: content.split("\n").length,
|
|
134018
|
+
note: "Structural validation passed. For semantic contract testing, use consumer-driven contract tests."
|
|
134019
|
+
});
|
|
134020
|
+
} catch (readErr) {
|
|
134021
|
+
return ok({
|
|
134022
|
+
contractPath: payload.contractPath,
|
|
134023
|
+
valid: false,
|
|
134024
|
+
breakingChanges: [],
|
|
134025
|
+
warnings: [],
|
|
134026
|
+
error: `Could not read or parse contract file: ${toErrorMessage(readErr)}`
|
|
134027
|
+
});
|
|
134028
|
+
}
|
|
134029
|
+
} catch (error) {
|
|
134030
|
+
return err(toError(error));
|
|
134031
|
+
}
|
|
133394
134032
|
});
|
|
133395
134033
|
this.taskHandlers.set("test-accessibility", async (task) => {
|
|
133396
134034
|
const payload = task.payload;
|
|
133397
134035
|
return ok({
|
|
133398
|
-
url: payload.url,
|
|
134036
|
+
url: payload.url || "",
|
|
133399
134037
|
standard: payload.standard || "wcag21-aa",
|
|
133400
|
-
passed:
|
|
134038
|
+
passed: false,
|
|
133401
134039
|
violations: [],
|
|
133402
|
-
warnings: [
|
|
133403
|
-
|
|
133404
|
-
|
|
133405
|
-
score: 94
|
|
134040
|
+
warnings: [],
|
|
134041
|
+
score: 0,
|
|
134042
|
+
note: "Accessibility testing requires a browser environment (Puppeteer/Playwright). Use tools like axe-core, pa11y, or Lighthouse CLI for WCAG compliance testing. Example: npx pa11y " + (payload.url || "<url>")
|
|
133406
134043
|
});
|
|
133407
134044
|
});
|
|
133408
134045
|
this.taskHandlers.set("run-chaos", async (task) => {
|
|
133409
134046
|
const payload = task.payload;
|
|
133410
134047
|
return ok({
|
|
133411
|
-
faultType: payload.faultType,
|
|
133412
|
-
target: payload.target,
|
|
133413
|
-
dryRun: payload.dryRun,
|
|
133414
|
-
duration: payload.duration,
|
|
133415
|
-
systemBehavior:
|
|
133416
|
-
resilience:
|
|
133417
|
-
|
|
133418
|
-
recoveryTime: 2500,
|
|
133419
|
-
dataLoss: false
|
|
133420
|
-
}
|
|
134048
|
+
faultType: payload.faultType || "unknown",
|
|
134049
|
+
target: payload.target || "unknown",
|
|
134050
|
+
dryRun: payload.dryRun ?? true,
|
|
134051
|
+
duration: payload.duration || 0,
|
|
134052
|
+
systemBehavior: "not-executed",
|
|
134053
|
+
resilience: null,
|
|
134054
|
+
note: "Chaos engineering requires infrastructure-level fault injection. Use tools like Chaos Monkey, Litmus, or toxiproxy for real resilience testing. For Node.js apps, consider: nock (HTTP faults), testcontainers (dependency failures)."
|
|
133421
134055
|
});
|
|
133422
134056
|
});
|
|
133423
134057
|
this.taskHandlers.set("optimize-learning", async (_task) => {
|
|
133424
|
-
|
|
133425
|
-
|
|
133426
|
-
|
|
133427
|
-
|
|
133428
|
-
|
|
133429
|
-
|
|
133430
|
-
"
|
|
133431
|
-
|
|
133432
|
-
}
|
|
134058
|
+
try {
|
|
134059
|
+
const memUsage = await Promise.resolve().then(() => (init_unified_memory_hnsw(), unified_memory_hnsw_exports));
|
|
134060
|
+
return ok({
|
|
134061
|
+
patternsLearned: 0,
|
|
134062
|
+
modelsUpdated: 0,
|
|
134063
|
+
memoryConsolidated: false,
|
|
134064
|
+
note: 'Learning optimization runs during the dream cycle (SessionEnd hook). Use "npx agentic-qe hooks session-end --save-state" to trigger pattern consolidation.'
|
|
134065
|
+
});
|
|
134066
|
+
} catch {
|
|
134067
|
+
return ok({
|
|
134068
|
+
patternsLearned: 0,
|
|
134069
|
+
modelsUpdated: 0,
|
|
134070
|
+
memoryConsolidated: false,
|
|
134071
|
+
note: 'Learning system not initialized. Run "aqe init --auto" first.'
|
|
134072
|
+
});
|
|
134073
|
+
}
|
|
133433
134074
|
});
|
|
133434
134075
|
}
|
|
133435
134076
|
// ============================================================================
|
|
@@ -137584,50 +138225,54 @@ var coverageAnalyzeConfig = {
|
|
|
137584
138225
|
const learning = generateV2LearningFeedback("coverage-analyzer");
|
|
137585
138226
|
const detailedGaps = gaps.map((gap, i58) => {
|
|
137586
138227
|
const g67 = gap;
|
|
138228
|
+
if (!g67?.file) return null;
|
|
137587
138229
|
return {
|
|
137588
138230
|
id: `gap-${Date.now()}-${i58}`,
|
|
137589
|
-
file: g67
|
|
137590
|
-
line: g67
|
|
137591
|
-
uncoveredLines: g67
|
|
137592
|
-
type: g67
|
|
137593
|
-
severity: g67
|
|
137594
|
-
reason: g67
|
|
137595
|
-
priority: g67
|
|
137596
|
-
suggestion: g67
|
|
137597
|
-
suggestedTest: g67
|
|
137598
|
-
riskScore: g67
|
|
137599
|
-
confidence: g67
|
|
138231
|
+
file: g67.file,
|
|
138232
|
+
line: g67.lines?.[0] || 0,
|
|
138233
|
+
uncoveredLines: g67.lines || [],
|
|
138234
|
+
type: g67.type || "uncovered-line",
|
|
138235
|
+
severity: g67.severity || "medium",
|
|
138236
|
+
reason: g67.reason || "Missing test case",
|
|
138237
|
+
priority: g67.priority || "medium",
|
|
138238
|
+
suggestion: g67.suggestedTest || "Add test coverage",
|
|
138239
|
+
suggestedTest: g67.suggestedTest || "Add test coverage",
|
|
138240
|
+
riskScore: g67.riskScore || 0.5,
|
|
138241
|
+
confidence: g67.confidence || 0.7
|
|
137600
138242
|
};
|
|
137601
|
-
});
|
|
137602
|
-
|
|
137603
|
-
|
|
137604
|
-
|
|
137605
|
-
|
|
137606
|
-
|
|
137607
|
-
|
|
137608
|
-
|
|
137609
|
-
|
|
137610
|
-
|
|
137611
|
-
|
|
137612
|
-
}),
|
|
138243
|
+
}).filter((g67) => g67 !== null);
|
|
138244
|
+
const coverageByFileData = data.coverageByFile;
|
|
138245
|
+
const realCoverageByFile = coverageByFileData ? coverageByFileData.map((f74) => ({
|
|
138246
|
+
file: f74.file,
|
|
138247
|
+
lineCoverage: f74.lineCoverage || 0,
|
|
138248
|
+
branchCoverage: f74.branchCoverage || 0,
|
|
138249
|
+
functionCoverage: f74.functionCoverage || 0
|
|
138250
|
+
})) : [];
|
|
138251
|
+
return {
|
|
138252
|
+
// V2-compatible fields — only real data, no synthetic file paths
|
|
138253
|
+
coverageByFile: realCoverageByFile,
|
|
137613
138254
|
gapAnalysis: {
|
|
137614
138255
|
totalGaps: detailedGaps.length,
|
|
137615
138256
|
highPriority: detailedGaps.filter((g67) => g67.priority === "high").length,
|
|
137616
138257
|
gaps: detailedGaps
|
|
137617
138258
|
},
|
|
137618
138259
|
trends: {
|
|
137619
|
-
lineCoverageTrend: "stable",
|
|
137620
|
-
branchCoverageTrend: "
|
|
137621
|
-
weeklyChange:
|
|
138260
|
+
lineCoverageTrend: totalFiles > 0 ? "stable" : "no-data",
|
|
138261
|
+
branchCoverageTrend: totalFiles > 0 ? "stable" : "no-data",
|
|
138262
|
+
weeklyChange: 0
|
|
137622
138263
|
},
|
|
137623
|
-
aiInsights: {
|
|
137624
|
-
recommendations: [
|
|
137625
|
-
"
|
|
137626
|
-
"Add edge case tests for error handling paths",
|
|
137627
|
-
"Consider property-based testing for utility functions"
|
|
138264
|
+
aiInsights: totalFiles > 0 ? {
|
|
138265
|
+
recommendations: data.recommendations || [
|
|
138266
|
+
"Run tests with coverage enabled to get accurate metrics"
|
|
137628
138267
|
],
|
|
137629
138268
|
riskAssessment: lineCoverage < 70 ? "high" : lineCoverage < 85 ? "medium" : "low",
|
|
137630
138269
|
confidence: 0.88
|
|
138270
|
+
} : {
|
|
138271
|
+
recommendations: [
|
|
138272
|
+
"No coverage data found. Run tests with coverage first (e.g., npm test -- --coverage, or pytest --cov)"
|
|
138273
|
+
],
|
|
138274
|
+
riskAssessment: "unknown",
|
|
138275
|
+
confidence: 0
|
|
137631
138276
|
},
|
|
137632
138277
|
learning,
|
|
137633
138278
|
// V3 fields
|
|
@@ -142822,6 +143467,44 @@ function extractHighlights(content, query) {
|
|
|
142822
143467
|
|
|
142823
143468
|
// src/mcp/tools/security-compliance/scan.ts
|
|
142824
143469
|
init_error_utils();
|
|
143470
|
+
var CROSS_LANG_SECRET_PATTERNS = [
|
|
143471
|
+
{
|
|
143472
|
+
id: "secret-key-assignment",
|
|
143473
|
+
pattern: /(?:SECRET_KEY|secret_key|SECRET|PRIVATE_KEY)\s*=\s*['"][^'"]{4,}['"]/g,
|
|
143474
|
+
severity: "critical",
|
|
143475
|
+
title: "Hardcoded Secret Key",
|
|
143476
|
+
description: "Secret key assigned as string literal in source code",
|
|
143477
|
+
cweId: "CWE-798",
|
|
143478
|
+
remediation: 'Use environment variables: SECRET_KEY = os.environ["SECRET_KEY"]'
|
|
143479
|
+
},
|
|
143480
|
+
{
|
|
143481
|
+
id: "cors-wildcard-credentials",
|
|
143482
|
+
pattern: /allow_origins\s*=\s*\[\s*["']\*["']\s*\]/g,
|
|
143483
|
+
severity: "high",
|
|
143484
|
+
title: "CORS Wildcard Origin",
|
|
143485
|
+
description: "CORS configured to allow all origins \u2014 combined with credentials this is a security risk",
|
|
143486
|
+
cweId: "CWE-942",
|
|
143487
|
+
remediation: "Restrict CORS origins to specific trusted domains"
|
|
143488
|
+
},
|
|
143489
|
+
{
|
|
143490
|
+
id: "cors-allow-credentials-wildcard",
|
|
143491
|
+
pattern: /allow_credentials\s*=\s*True/g,
|
|
143492
|
+
severity: "medium",
|
|
143493
|
+
title: "CORS Credentials Enabled",
|
|
143494
|
+
description: "CORS credentials enabled \u2014 verify origins are restricted",
|
|
143495
|
+
cweId: "CWE-942",
|
|
143496
|
+
remediation: 'Ensure allow_origins does not include "*" when credentials are enabled'
|
|
143497
|
+
},
|
|
143498
|
+
{
|
|
143499
|
+
id: "token-hardcoded",
|
|
143500
|
+
pattern: /(?:token|TOKEN)\s*[:=]\s*['"][a-zA-Z0-9_\-.]{20,}['"]/g,
|
|
143501
|
+
severity: "high",
|
|
143502
|
+
title: "Hardcoded Token",
|
|
143503
|
+
description: "Hardcoded token found in source code",
|
|
143504
|
+
cweId: "CWE-798",
|
|
143505
|
+
remediation: "Use environment variables or secrets manager for tokens"
|
|
143506
|
+
}
|
|
143507
|
+
];
|
|
142825
143508
|
var SecurityScanTool = class extends MCPToolBase {
|
|
142826
143509
|
config = {
|
|
142827
143510
|
name: "qe/security/scan",
|
|
@@ -142850,18 +143533,21 @@ var SecurityScanTool = class extends MCPToolBase {
|
|
|
142850
143533
|
if (this.isAborted(context)) {
|
|
142851
143534
|
return { success: false, error: "Operation aborted" };
|
|
142852
143535
|
}
|
|
143536
|
+
const files = await discoverFiles(target, depth);
|
|
143537
|
+
this.emitStream(context, {
|
|
143538
|
+
status: "discovered",
|
|
143539
|
+
message: `Found ${files.length} files to scan`
|
|
143540
|
+
});
|
|
142853
143541
|
const vulnerabilities = [];
|
|
142854
|
-
if (scanType.includes("sast")) {
|
|
143542
|
+
if (scanType.includes("sast") || scanType.includes("secret")) {
|
|
142855
143543
|
this.emitStream(context, { status: "sast", message: "Running static analysis" });
|
|
142856
|
-
|
|
143544
|
+
const sastVulns = await scanFilesWithPatterns(files, scanType);
|
|
143545
|
+
vulnerabilities.push(...sastVulns);
|
|
142857
143546
|
}
|
|
142858
143547
|
if (scanType.includes("dependency")) {
|
|
142859
143548
|
this.emitStream(context, { status: "dependency", message: "Scanning dependencies" });
|
|
142860
|
-
|
|
142861
|
-
|
|
142862
|
-
if (scanType.includes("secret")) {
|
|
142863
|
-
this.emitStream(context, { status: "secret", message: "Scanning for secrets" });
|
|
142864
|
-
vulnerabilities.push(...generateSecretFindings());
|
|
143549
|
+
const depVulns = await scanDependencies(target);
|
|
143550
|
+
vulnerabilities.push(...depVulns);
|
|
142865
143551
|
}
|
|
142866
143552
|
if (scanType.includes("dast") && dastUrl) {
|
|
142867
143553
|
this.emitStream(context, { status: "dast", message: `Scanning ${dastUrl}` });
|
|
@@ -142876,7 +143562,7 @@ var SecurityScanTool = class extends MCPToolBase {
|
|
|
142876
143562
|
medium: vulnerabilities.filter((v62) => v62.severity === "medium").length,
|
|
142877
143563
|
low: vulnerabilities.filter((v62) => v62.severity === "low").length,
|
|
142878
143564
|
informational: vulnerabilities.filter((v62) => v62.severity === "informational").length,
|
|
142879
|
-
totalFiles:
|
|
143565
|
+
totalFiles: files.length,
|
|
142880
143566
|
scanDurationMs: Date.now() - startTime
|
|
142881
143567
|
};
|
|
142882
143568
|
const severityOrder = ["critical", "high", "medium", "low", "informational"];
|
|
@@ -142885,7 +143571,7 @@ var SecurityScanTool = class extends MCPToolBase {
|
|
|
142885
143571
|
const passed = worstSeverity > failThreshold;
|
|
142886
143572
|
this.emitStream(context, {
|
|
142887
143573
|
status: "complete",
|
|
142888
|
-
message: `Scan complete: ${vulnerabilities.length} vulnerabilities found`,
|
|
143574
|
+
message: `Scan complete: ${vulnerabilities.length} vulnerabilities found in ${files.length} files`,
|
|
142889
143575
|
progress: 100
|
|
142890
143576
|
});
|
|
142891
143577
|
return {
|
|
@@ -142952,72 +143638,340 @@ var SECURITY_SCAN_SCHEMA = {
|
|
|
142952
143638
|
}
|
|
142953
143639
|
}
|
|
142954
143640
|
};
|
|
142955
|
-
|
|
142956
|
-
|
|
142957
|
-
|
|
142958
|
-
|
|
142959
|
-
|
|
142960
|
-
|
|
142961
|
-
|
|
142962
|
-
|
|
142963
|
-
|
|
142964
|
-
|
|
142965
|
-
|
|
142966
|
-
|
|
142967
|
-
|
|
142968
|
-
|
|
142969
|
-
|
|
142970
|
-
|
|
142971
|
-
|
|
142972
|
-
|
|
142973
|
-
|
|
142974
|
-
|
|
142975
|
-
|
|
142976
|
-
|
|
142977
|
-
|
|
143641
|
+
var SCANNABLE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
143642
|
+
".ts",
|
|
143643
|
+
".tsx",
|
|
143644
|
+
".js",
|
|
143645
|
+
".jsx",
|
|
143646
|
+
".mjs",
|
|
143647
|
+
".cjs",
|
|
143648
|
+
// JavaScript/TypeScript
|
|
143649
|
+
".py",
|
|
143650
|
+
".pyw",
|
|
143651
|
+
// Python
|
|
143652
|
+
".java",
|
|
143653
|
+
".kt",
|
|
143654
|
+
".scala",
|
|
143655
|
+
// JVM
|
|
143656
|
+
".go",
|
|
143657
|
+
// Go
|
|
143658
|
+
".rb",
|
|
143659
|
+
// Ruby
|
|
143660
|
+
".php",
|
|
143661
|
+
// PHP
|
|
143662
|
+
".rs",
|
|
143663
|
+
// Rust
|
|
143664
|
+
".cs",
|
|
143665
|
+
// C#
|
|
143666
|
+
".yaml",
|
|
143667
|
+
".yml",
|
|
143668
|
+
".json",
|
|
143669
|
+
".toml",
|
|
143670
|
+
".cfg",
|
|
143671
|
+
".ini",
|
|
143672
|
+
// Config
|
|
143673
|
+
".env",
|
|
143674
|
+
".env.local",
|
|
143675
|
+
".env.production",
|
|
143676
|
+
// Env files
|
|
143677
|
+
".sh",
|
|
143678
|
+
".bash"
|
|
143679
|
+
// Shell
|
|
143680
|
+
]);
|
|
143681
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
143682
|
+
"node_modules",
|
|
143683
|
+
".git",
|
|
143684
|
+
"__pycache__",
|
|
143685
|
+
".venv",
|
|
143686
|
+
"venv",
|
|
143687
|
+
"dist",
|
|
143688
|
+
"build",
|
|
143689
|
+
".next",
|
|
143690
|
+
".nuxt",
|
|
143691
|
+
"coverage",
|
|
143692
|
+
".tox"
|
|
143693
|
+
]);
|
|
143694
|
+
async function discoverFiles(target, depth) {
|
|
143695
|
+
const fs21 = await import("fs");
|
|
143696
|
+
const path23 = await import("path");
|
|
143697
|
+
const resolved = path23.resolve(target);
|
|
143698
|
+
const files = [];
|
|
143699
|
+
const maxFiles = depth === "quick" ? 50 : depth === "standard" ? 500 : 2e3;
|
|
143700
|
+
const maxDepth = depth === "quick" ? 3 : depth === "standard" ? 8 : 20;
|
|
143701
|
+
function walk(dir, currentDepth) {
|
|
143702
|
+
if (files.length >= maxFiles || currentDepth > maxDepth) return;
|
|
143703
|
+
let entries;
|
|
143704
|
+
try {
|
|
143705
|
+
entries = fs21.readdirSync(dir, { withFileTypes: true });
|
|
143706
|
+
} catch {
|
|
143707
|
+
return;
|
|
142978
143708
|
}
|
|
142979
|
-
|
|
143709
|
+
for (const entry of entries) {
|
|
143710
|
+
if (files.length >= maxFiles) break;
|
|
143711
|
+
const fullPath = path23.join(dir, entry.name);
|
|
143712
|
+
if (entry.isDirectory()) {
|
|
143713
|
+
const SCAN_DOT_DIRS = /* @__PURE__ */ new Set([".github", ".docker", ".aws", ".circleci", ".gitlab"]);
|
|
143714
|
+
if (SKIP_DIRS.has(entry.name)) {
|
|
143715
|
+
} else if (entry.name.startsWith(".") && !SCAN_DOT_DIRS.has(entry.name)) {
|
|
143716
|
+
} else {
|
|
143717
|
+
walk(fullPath, currentDepth + 1);
|
|
143718
|
+
}
|
|
143719
|
+
} else if (entry.isFile()) {
|
|
143720
|
+
const ext = path23.extname(entry.name).toLowerCase();
|
|
143721
|
+
if (SCANNABLE_EXTENSIONS.has(ext) || entry.name === "Dockerfile" || entry.name === "Makefile" || entry.name.startsWith(".env")) {
|
|
143722
|
+
files.push(fullPath);
|
|
143723
|
+
}
|
|
143724
|
+
}
|
|
143725
|
+
}
|
|
143726
|
+
}
|
|
143727
|
+
try {
|
|
143728
|
+
const stat6 = fs21.statSync(resolved);
|
|
143729
|
+
if (stat6.isFile()) {
|
|
143730
|
+
files.push(resolved);
|
|
143731
|
+
} else {
|
|
143732
|
+
walk(resolved, 0);
|
|
143733
|
+
}
|
|
143734
|
+
} catch {
|
|
143735
|
+
}
|
|
143736
|
+
return files;
|
|
142980
143737
|
}
|
|
142981
|
-
function
|
|
142982
|
-
|
|
142983
|
-
|
|
142984
|
-
|
|
142985
|
-
|
|
142986
|
-
|
|
142987
|
-
|
|
142988
|
-
|
|
142989
|
-
|
|
142990
|
-
|
|
142991
|
-
|
|
142992
|
-
|
|
143738
|
+
async function scanFilesWithPatterns(files, scanTypes) {
|
|
143739
|
+
const fs21 = await import("fs");
|
|
143740
|
+
const path23 = await import("path");
|
|
143741
|
+
const vulnerabilities = [];
|
|
143742
|
+
let vulnCounter = 0;
|
|
143743
|
+
const patterns = [];
|
|
143744
|
+
if (scanTypes.includes("sast")) {
|
|
143745
|
+
for (const p74 of ALL_SECURITY_PATTERNS) {
|
|
143746
|
+
patterns.push({
|
|
143747
|
+
id: p74.id,
|
|
143748
|
+
pattern: new RegExp(p74.pattern.source, p74.pattern.flags),
|
|
143749
|
+
severity: p74.severity,
|
|
143750
|
+
title: p74.title,
|
|
143751
|
+
description: p74.description,
|
|
143752
|
+
cweId: p74.cweId,
|
|
143753
|
+
remediation: p74.remediation,
|
|
143754
|
+
category: p74.category
|
|
143755
|
+
});
|
|
142993
143756
|
}
|
|
142994
|
-
|
|
143757
|
+
for (const p74 of CROSS_LANG_SECRET_PATTERNS) {
|
|
143758
|
+
patterns.push({
|
|
143759
|
+
id: p74.id,
|
|
143760
|
+
pattern: new RegExp(p74.pattern.source, p74.pattern.flags),
|
|
143761
|
+
severity: p74.severity,
|
|
143762
|
+
title: p74.title,
|
|
143763
|
+
description: p74.description,
|
|
143764
|
+
cweId: p74.cweId,
|
|
143765
|
+
remediation: p74.remediation,
|
|
143766
|
+
category: "sensitive-data"
|
|
143767
|
+
});
|
|
143768
|
+
}
|
|
143769
|
+
}
|
|
143770
|
+
if (scanTypes.includes("secret")) {
|
|
143771
|
+
for (const p74 of SECRET_PATTERNS) {
|
|
143772
|
+
if (!patterns.some((existing) => existing.id === p74.id)) {
|
|
143773
|
+
patterns.push({
|
|
143774
|
+
id: p74.id,
|
|
143775
|
+
pattern: new RegExp(p74.pattern.source, p74.pattern.flags),
|
|
143776
|
+
severity: p74.severity,
|
|
143777
|
+
title: p74.title,
|
|
143778
|
+
description: p74.description,
|
|
143779
|
+
cweId: p74.cweId,
|
|
143780
|
+
remediation: p74.remediation,
|
|
143781
|
+
category: p74.category
|
|
143782
|
+
});
|
|
143783
|
+
}
|
|
143784
|
+
}
|
|
143785
|
+
for (const p74 of CROSS_LANG_SECRET_PATTERNS) {
|
|
143786
|
+
if (!patterns.some((existing) => existing.id === p74.id)) {
|
|
143787
|
+
patterns.push({
|
|
143788
|
+
...p74,
|
|
143789
|
+
category: "sensitive-data"
|
|
143790
|
+
});
|
|
143791
|
+
}
|
|
143792
|
+
}
|
|
143793
|
+
}
|
|
143794
|
+
for (const filePath of files) {
|
|
143795
|
+
let content;
|
|
143796
|
+
try {
|
|
143797
|
+
content = fs21.readFileSync(filePath, "utf-8");
|
|
143798
|
+
} catch {
|
|
143799
|
+
continue;
|
|
143800
|
+
}
|
|
143801
|
+
if (content.includes("\0") || content.length > 1e6) continue;
|
|
143802
|
+
const lines = content.split("\n");
|
|
143803
|
+
const relPath = path23.relative(process.cwd(), filePath);
|
|
143804
|
+
for (const patternDef of patterns) {
|
|
143805
|
+
const regex = new RegExp(patternDef.pattern.source, patternDef.pattern.flags);
|
|
143806
|
+
let match;
|
|
143807
|
+
while ((match = regex.exec(content)) !== null) {
|
|
143808
|
+
vulnCounter++;
|
|
143809
|
+
const lineNum = content.substring(0, match.index).split("\n").length;
|
|
143810
|
+
const matchedLine = lines[lineNum - 1] || "";
|
|
143811
|
+
const snippet = matchedLine.trim().length > 100 ? matchedLine.trim().substring(0, 100) + "..." : matchedLine.trim();
|
|
143812
|
+
vulnerabilities.push({
|
|
143813
|
+
id: `${patternDef.id}-${vulnCounter}`,
|
|
143814
|
+
title: patternDef.title,
|
|
143815
|
+
severity: patternDef.severity,
|
|
143816
|
+
category: patternDef.category || "security-misconfiguration",
|
|
143817
|
+
location: {
|
|
143818
|
+
file: relPath,
|
|
143819
|
+
line: lineNum,
|
|
143820
|
+
snippet
|
|
143821
|
+
},
|
|
143822
|
+
description: patternDef.description,
|
|
143823
|
+
remediation: patternDef.remediation,
|
|
143824
|
+
cweId: patternDef.cweId,
|
|
143825
|
+
references: []
|
|
143826
|
+
});
|
|
143827
|
+
if (vulnCounter > 200) break;
|
|
143828
|
+
}
|
|
143829
|
+
}
|
|
143830
|
+
}
|
|
143831
|
+
return vulnerabilities;
|
|
142995
143832
|
}
|
|
142996
|
-
function
|
|
142997
|
-
|
|
142998
|
-
|
|
142999
|
-
|
|
143000
|
-
|
|
143001
|
-
|
|
143002
|
-
|
|
143003
|
-
|
|
143004
|
-
|
|
143005
|
-
|
|
143006
|
-
|
|
143833
|
+
async function scanDependencies(target) {
|
|
143834
|
+
const fs21 = await import("fs");
|
|
143835
|
+
const path23 = await import("path");
|
|
143836
|
+
const vulnerabilities = [];
|
|
143837
|
+
const resolved = path23.resolve(target);
|
|
143838
|
+
const pkgJsonPath = path23.join(resolved, "package.json");
|
|
143839
|
+
if (fs21.existsSync(pkgJsonPath)) {
|
|
143840
|
+
try {
|
|
143841
|
+
const pkg2 = JSON.parse(fs21.readFileSync(pkgJsonPath, "utf-8"));
|
|
143842
|
+
const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
|
|
143843
|
+
vulnerabilities.push(...checkKnownVulnerableDeps(allDeps, "package.json"));
|
|
143844
|
+
} catch {
|
|
143007
143845
|
}
|
|
143008
|
-
|
|
143846
|
+
}
|
|
143847
|
+
const pyprojectPath = path23.join(resolved, "pyproject.toml");
|
|
143848
|
+
if (fs21.existsSync(pyprojectPath)) {
|
|
143849
|
+
try {
|
|
143850
|
+
const content = fs21.readFileSync(pyprojectPath, "utf-8");
|
|
143851
|
+
const deps = extractPythonDeps(content);
|
|
143852
|
+
vulnerabilities.push(...checkKnownVulnerablePythonDeps(deps, "pyproject.toml"));
|
|
143853
|
+
} catch {
|
|
143854
|
+
}
|
|
143855
|
+
}
|
|
143856
|
+
const reqPath = path23.join(resolved, "requirements.txt");
|
|
143857
|
+
if (fs21.existsSync(reqPath)) {
|
|
143858
|
+
try {
|
|
143859
|
+
const content = fs21.readFileSync(reqPath, "utf-8");
|
|
143860
|
+
const deps = extractRequirementsTxtDeps(content);
|
|
143861
|
+
vulnerabilities.push(...checkKnownVulnerablePythonDeps(deps, "requirements.txt"));
|
|
143862
|
+
} catch {
|
|
143863
|
+
}
|
|
143864
|
+
}
|
|
143865
|
+
if (vulnerabilities.length === 0) {
|
|
143866
|
+
const manifests = [pkgJsonPath, pyprojectPath, reqPath].filter((p74) => fs21.existsSync(p74));
|
|
143867
|
+
if (manifests.length > 0) {
|
|
143868
|
+
vulnerabilities.push({
|
|
143869
|
+
id: "DEP-INFO-001",
|
|
143870
|
+
title: "Dependency audit recommended",
|
|
143871
|
+
severity: "informational",
|
|
143872
|
+
category: "vulnerable-components",
|
|
143873
|
+
location: { file: path23.relative(process.cwd(), manifests[0]) },
|
|
143874
|
+
description: `Found ${path23.basename(manifests[0])} \u2014 run language-specific dependency audit for comprehensive results`,
|
|
143875
|
+
remediation: "Run npm audit, pip-audit, or equivalent for full vulnerability check",
|
|
143876
|
+
references: []
|
|
143877
|
+
});
|
|
143878
|
+
}
|
|
143879
|
+
}
|
|
143880
|
+
return vulnerabilities;
|
|
143881
|
+
}
|
|
143882
|
+
var KNOWN_VULNERABLE_NPM = {
|
|
143883
|
+
"lodash": { maxSafe: "4.17.21", cve: "CVE-2021-23337", severity: "high", desc: "Prototype pollution in lodash" },
|
|
143884
|
+
"minimist": { maxSafe: "1.2.6", cve: "CVE-2021-44906", severity: "critical", desc: "Prototype pollution in minimist" },
|
|
143885
|
+
"node-fetch": { maxSafe: "2.6.7", cve: "CVE-2022-0235", severity: "high", desc: "Information exposure in node-fetch" },
|
|
143886
|
+
"express": { maxSafe: "4.19.2", cve: "CVE-2024-29041", severity: "medium", desc: "Open redirect in express" }
|
|
143887
|
+
};
|
|
143888
|
+
function checkKnownVulnerableDeps(deps, manifest) {
|
|
143889
|
+
const vulns = [];
|
|
143890
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
143891
|
+
const known = KNOWN_VULNERABLE_NPM[name];
|
|
143892
|
+
if (known) {
|
|
143893
|
+
const cleanVersion = version.replace(/^[\^~>=<]+/, "");
|
|
143894
|
+
if (compareVersions(cleanVersion, known.maxSafe) < 0) {
|
|
143895
|
+
vulns.push({
|
|
143896
|
+
id: `DEP-${name}-${known.cve}`,
|
|
143897
|
+
title: `Vulnerable ${name} version`,
|
|
143898
|
+
severity: known.severity,
|
|
143899
|
+
category: "vulnerable-components",
|
|
143900
|
+
location: { file: manifest, dependency: { name, version: cleanVersion } },
|
|
143901
|
+
description: known.desc,
|
|
143902
|
+
remediation: `Upgrade ${name} to >= ${known.maxSafe}`,
|
|
143903
|
+
cveId: known.cve,
|
|
143904
|
+
references: [`https://nvd.nist.gov/vuln/detail/${known.cve}`]
|
|
143905
|
+
});
|
|
143906
|
+
}
|
|
143907
|
+
}
|
|
143908
|
+
}
|
|
143909
|
+
return vulns;
|
|
143910
|
+
}
|
|
143911
|
+
var KNOWN_VULNERABLE_PYTHON = {
|
|
143912
|
+
"python-jose": { cve: "CVE-2024-33663", severity: "critical", desc: "python-jose is abandoned and has known JWT vulnerabilities" },
|
|
143913
|
+
"pyjwt": { cve: "CVE-2022-29217", severity: "high", desc: "PyJWT algorithm confusion vulnerability (upgrade to >= 2.4.0)" },
|
|
143914
|
+
"python-multipart": { cve: "CVE-2026-24486", severity: "high", desc: "python-multipart DoS vulnerability" },
|
|
143915
|
+
"jinja2": { cve: "CVE-2024-34064", severity: "medium", desc: "Jinja2 XSS via template injection" },
|
|
143916
|
+
"urllib3": { cve: "CVE-2023-45803", severity: "medium", desc: "urllib3 request body exposure on redirect" },
|
|
143917
|
+
"requests": { cve: "CVE-2023-32681", severity: "medium", desc: "Requests proxy credential exposure" }
|
|
143918
|
+
};
|
|
143919
|
+
function extractPythonDeps(tomlContent) {
|
|
143920
|
+
const deps = [];
|
|
143921
|
+
const depMatch = tomlContent.match(/dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
143922
|
+
if (depMatch) {
|
|
143923
|
+
const matches = depMatch[1].matchAll(/["']([a-zA-Z0-9_-]+)/g);
|
|
143924
|
+
for (const m74 of matches) {
|
|
143925
|
+
deps.push(m74[1].toLowerCase());
|
|
143926
|
+
}
|
|
143927
|
+
}
|
|
143928
|
+
return deps;
|
|
143929
|
+
}
|
|
143930
|
+
function extractRequirementsTxtDeps(content) {
|
|
143931
|
+
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split(/[>=<!~\[]/)[0].trim().toLowerCase()).filter(Boolean);
|
|
143932
|
+
}
|
|
143933
|
+
function checkKnownVulnerablePythonDeps(deps, manifest) {
|
|
143934
|
+
const vulns = [];
|
|
143935
|
+
for (const dep of deps) {
|
|
143936
|
+
const known = KNOWN_VULNERABLE_PYTHON[dep];
|
|
143937
|
+
if (known) {
|
|
143938
|
+
vulns.push({
|
|
143939
|
+
id: `DEP-py-${dep}-${known.cve}`,
|
|
143940
|
+
title: `Vulnerable Python dependency: ${dep}`,
|
|
143941
|
+
severity: known.severity,
|
|
143942
|
+
category: "vulnerable-components",
|
|
143943
|
+
location: { file: manifest, dependency: { name: dep, version: "any" } },
|
|
143944
|
+
description: known.desc,
|
|
143945
|
+
remediation: dep === "python-jose" ? "Migrate to PyJWT or joserfc" : `Check for updates to ${dep}`,
|
|
143946
|
+
cveId: known.cve,
|
|
143947
|
+
references: [`https://nvd.nist.gov/vuln/detail/${known.cve}`]
|
|
143948
|
+
});
|
|
143949
|
+
}
|
|
143950
|
+
}
|
|
143951
|
+
return vulns;
|
|
143952
|
+
}
|
|
143953
|
+
function compareVersions(a37, b68) {
|
|
143954
|
+
const pa9 = a37.split(".").map(Number);
|
|
143955
|
+
const pb = b68.split(".").map(Number);
|
|
143956
|
+
for (let i58 = 0; i58 < 3; i58++) {
|
|
143957
|
+
const va5 = pa9[i58] || 0;
|
|
143958
|
+
const vb = pb[i58] || 0;
|
|
143959
|
+
if (va5 < vb) return -1;
|
|
143960
|
+
if (va5 > vb) return 1;
|
|
143961
|
+
}
|
|
143962
|
+
return 0;
|
|
143009
143963
|
}
|
|
143010
143964
|
function generateDASTFindings(url) {
|
|
143011
143965
|
return [
|
|
143012
143966
|
{
|
|
143013
|
-
id: "DAST-001",
|
|
143014
|
-
title: "
|
|
143015
|
-
severity: "
|
|
143967
|
+
id: "DAST-INFO-001",
|
|
143968
|
+
title: "DAST scan target noted",
|
|
143969
|
+
severity: "informational",
|
|
143016
143970
|
category: "security-misconfiguration",
|
|
143017
143971
|
location: { file: url },
|
|
143018
|
-
description:
|
|
143019
|
-
remediation: "
|
|
143020
|
-
references: ["https://owasp.org/www-project-
|
|
143972
|
+
description: `DAST target ${url} recorded. Full DAST requires integration with a dynamic scanner (e.g., ZAP, Burp).`,
|
|
143973
|
+
remediation: "Configure a DAST tool to scan the live application",
|
|
143974
|
+
references: ["https://owasp.org/www-project-zap/"]
|
|
143021
143975
|
}
|
|
143022
143976
|
];
|
|
143023
143977
|
}
|
|
@@ -143055,6 +144009,9 @@ function generateRecommendations5(vulnerabilities, summary) {
|
|
|
143055
144009
|
if (vulnerabilities.some((v62) => v62.category === "sensitive-data")) {
|
|
143056
144010
|
recs.push("Implement proper secrets management");
|
|
143057
144011
|
}
|
|
144012
|
+
if (vulnerabilities.some((v62) => v62.category === "vulnerable-components")) {
|
|
144013
|
+
recs.push("Run full dependency audit and update vulnerable packages");
|
|
144014
|
+
}
|
|
143058
144015
|
if (recs.length === 0) {
|
|
143059
144016
|
recs.push("No critical issues found. Continue regular security reviews.");
|
|
143060
144017
|
}
|
|
@@ -147391,7 +148348,7 @@ function getSharedGOAPPlanner() {
|
|
|
147391
148348
|
}
|
|
147392
148349
|
|
|
147393
148350
|
// src/planning/plan-executor.ts
|
|
147394
|
-
|
|
148351
|
+
init_safe_db();
|
|
147395
148352
|
init_unified_memory();
|
|
147396
148353
|
init_error_utils();
|
|
147397
148354
|
init_safe_json();
|
|
@@ -147426,7 +148383,7 @@ var PlanExecutor = class {
|
|
|
147426
148383
|
this.spawner = spawner;
|
|
147427
148384
|
this.config = { ...DEFAULT_CONFIG69, ...config };
|
|
147428
148385
|
if (!this.config.useUnified) {
|
|
147429
|
-
this.db =
|
|
148386
|
+
this.db = openDatabase(dbPath ?? ":memory:", { walMode: false });
|
|
147430
148387
|
this.db.pragma("journal_mode = WAL");
|
|
147431
148388
|
}
|
|
147432
148389
|
}
|
|
@@ -149370,7 +150327,7 @@ init_logging();
|
|
|
149370
150327
|
init_types();
|
|
149371
150328
|
|
|
149372
150329
|
// src/learning/v2-to-v3-migration.ts
|
|
149373
|
-
|
|
150330
|
+
init_safe_db();
|
|
149374
150331
|
init_error_utils();
|
|
149375
150332
|
init_safe_json();
|
|
149376
150333
|
init_logging();
|
|
@@ -149815,7 +150772,7 @@ init_logging();
|
|
|
149815
150772
|
var logger17 = LoggerFactory.create("pattern-lifecycle");
|
|
149816
150773
|
|
|
149817
150774
|
// src/learning/metrics-tracker.ts
|
|
149818
|
-
|
|
150775
|
+
init_safe_db();
|
|
149819
150776
|
init_qe_patterns();
|
|
149820
150777
|
init_safe_json();
|
|
149821
150778
|
init_logging();
|
|
@@ -153347,14 +154304,22 @@ async function handleTaskOrchestrate(params) {
|
|
|
153347
154304
|
}
|
|
153348
154305
|
const { queen, workflowOrchestrator } = getFleetState();
|
|
153349
154306
|
try {
|
|
154307
|
+
const inferredDomain = params.context?.project || inferDomainFromDescription(params.task);
|
|
154308
|
+
const inferredIsCritical = params.priority === "critical" || /\b(security|vulnerability|cve|owasp|critical|production|exploit)\b/i.test(params.task);
|
|
153350
154309
|
const router = await getTaskRouter();
|
|
153351
154310
|
const routingResult = await router.routeTask({
|
|
153352
154311
|
task: params.task,
|
|
153353
154312
|
codeContext: params.codeContext,
|
|
153354
154313
|
filePaths: params.filePaths,
|
|
153355
154314
|
manualTier: params.manualTier,
|
|
153356
|
-
isCritical:
|
|
153357
|
-
|
|
154315
|
+
isCritical: inferredIsCritical,
|
|
154316
|
+
agentType: `qe-${inferredDomain}`,
|
|
154317
|
+
domain: inferredDomain,
|
|
154318
|
+
metadata: {
|
|
154319
|
+
inferredDomain,
|
|
154320
|
+
hasCodeContext: !!params.codeContext,
|
|
154321
|
+
fileCount: params.filePaths?.length
|
|
154322
|
+
}
|
|
153358
154323
|
});
|
|
153359
154324
|
const reasoningBankService = await getReasoningBankService();
|
|
153360
154325
|
const experienceGuidance = await reasoningBankService.getExperienceGuidance(
|
|
@@ -153492,14 +154457,22 @@ async function handleTaskOrchestrate(params) {
|
|
|
153492
154457
|
async function handleModelRoute(params) {
|
|
153493
154458
|
try {
|
|
153494
154459
|
const router = await getTaskRouter();
|
|
154460
|
+
const inferredDomain = params.domain || inferDomainFromDescription(params.task);
|
|
154461
|
+
const inferredIsCritical = params.isCritical ?? /\b(security|vulnerability|cve|owasp|critical|production|exploit)\b/i.test(params.task);
|
|
153495
154462
|
const result = await router.routeTask({
|
|
153496
154463
|
task: params.task,
|
|
153497
154464
|
codeContext: params.codeContext,
|
|
153498
154465
|
filePaths: params.filePaths,
|
|
153499
154466
|
manualTier: params.manualTier,
|
|
153500
|
-
isCritical:
|
|
153501
|
-
agentType: params.agentType
|
|
153502
|
-
domain:
|
|
154467
|
+
isCritical: inferredIsCritical,
|
|
154468
|
+
agentType: params.agentType || `qe-${inferredDomain}`,
|
|
154469
|
+
domain: inferredDomain,
|
|
154470
|
+
// Pass metadata to help the complexity analyzer
|
|
154471
|
+
metadata: {
|
|
154472
|
+
inferredDomain,
|
|
154473
|
+
hasCodeContext: !!params.codeContext,
|
|
154474
|
+
fileCount: params.filePaths?.length
|
|
154475
|
+
}
|
|
153503
154476
|
});
|
|
153504
154477
|
return {
|
|
153505
154478
|
success: true,
|
|
@@ -153562,6 +154535,43 @@ async function handleRoutingMetrics(params) {
|
|
|
153562
154535
|
};
|
|
153563
154536
|
}
|
|
153564
154537
|
}
|
|
154538
|
+
function inferDomainFromDescription(description) {
|
|
154539
|
+
const lower = description.toLowerCase();
|
|
154540
|
+
if (/\b(security|vulnerabilit|cve|owasp|secret|credential|injection|xss|csrf)\b/.test(lower)) {
|
|
154541
|
+
return "security-compliance";
|
|
154542
|
+
}
|
|
154543
|
+
if (/\b(chaos|resilience|fault.?inject|disaster|failover)\b/.test(lower)) {
|
|
154544
|
+
return "chaos-resilience";
|
|
154545
|
+
}
|
|
154546
|
+
if (/\b(defect|bug.?predict|risk.?assess|mutation)\b/.test(lower)) {
|
|
154547
|
+
return "defect-intelligence";
|
|
154548
|
+
}
|
|
154549
|
+
if (/\b(coverage|uncovered|gap.?analy)\b/.test(lower)) {
|
|
154550
|
+
return "coverage-analysis";
|
|
154551
|
+
}
|
|
154552
|
+
if (/\b(quality|code.?review|maintain|tech.?debt)\b/.test(lower)) {
|
|
154553
|
+
return "quality-assessment";
|
|
154554
|
+
}
|
|
154555
|
+
if (/\b(contract|api.?compat|breaking.?change|pact)\b/.test(lower)) {
|
|
154556
|
+
return "contract-testing";
|
|
154557
|
+
}
|
|
154558
|
+
if (/\b(index|knowledge.?graph|semantic|code.?intel)\b/.test(lower)) {
|
|
154559
|
+
return "code-intelligence";
|
|
154560
|
+
}
|
|
154561
|
+
if (/\b(accessib|a11y|wcag|screen.?read)\b/.test(lower)) {
|
|
154562
|
+
return "visual-accessibility";
|
|
154563
|
+
}
|
|
154564
|
+
if (/\b(requirement|bdd|acceptance|user.?stor)\b/.test(lower)) {
|
|
154565
|
+
return "requirements-validation";
|
|
154566
|
+
}
|
|
154567
|
+
if (/\b(generat.*test|test.*generat|write.*test|create.*test)\b/.test(lower)) {
|
|
154568
|
+
return "test-generation";
|
|
154569
|
+
}
|
|
154570
|
+
if (/\b(run.*test|execut.*test)\b/.test(lower)) {
|
|
154571
|
+
return "test-execution";
|
|
154572
|
+
}
|
|
154573
|
+
return "test-generation";
|
|
154574
|
+
}
|
|
153565
154575
|
function inferTaskType(description) {
|
|
153566
154576
|
const lower = description.toLowerCase();
|
|
153567
154577
|
if (/run\s+(?:\w+\s+)*tests?/.test(lower) || /execute\s+(?:\w+\s+)*tests?/.test(lower) || lower.includes("run tests") || lower.includes("execute tests")) {
|
|
@@ -155321,7 +156331,18 @@ var MCPProtocolServer = class {
|
|
|
155321
156331
|
async start() {
|
|
155322
156332
|
await initializeConnectionPool();
|
|
155323
156333
|
this.transport.onRequest(async (request) => {
|
|
155324
|
-
|
|
156334
|
+
try {
|
|
156335
|
+
return await this.handleRequest(request);
|
|
156336
|
+
} catch (err4) {
|
|
156337
|
+
const message = err4 instanceof Error ? err4.message : String(err4);
|
|
156338
|
+
console.error(`[MCP] Unhandled error in request handler: ${message}`);
|
|
156339
|
+
return {
|
|
156340
|
+
content: [{
|
|
156341
|
+
type: "text",
|
|
156342
|
+
text: JSON.stringify({ success: false, error: `Internal error: ${message}` })
|
|
156343
|
+
}]
|
|
156344
|
+
};
|
|
156345
|
+
}
|
|
155325
156346
|
});
|
|
155326
156347
|
this.transport.onNotification(async (notification) => {
|
|
155327
156348
|
await this.handleNotification(notification);
|