agentic-qe 3.6.11 → 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.
Files changed (105) hide show
  1. package/.claude/helpers/learning-service.mjs +2 -0
  2. package/.claude/helpers/statusline-v3.cjs +2 -0
  3. package/.claude/skills/skills-manifest.json +1 -1
  4. package/package.json +1 -1
  5. package/scripts/migrate-v2-to-v3-memory.js +2 -0
  6. package/scripts/sync-claude-flow.cjs +1 -0
  7. package/v3/CHANGELOG.md +14 -0
  8. package/v3/dist/adapters/claude-flow/trajectory-bridge.js +2 -2
  9. package/v3/dist/adapters/claude-flow/trajectory-bridge.js.map +1 -1
  10. package/v3/dist/benchmarks/performance-benchmarks.js +1 -1
  11. package/v3/dist/cli/bundle.js +198 -91
  12. package/v3/dist/cli/commands/learning-helpers.d.ts.map +1 -1
  13. package/v3/dist/cli/commands/learning-helpers.js +3 -4
  14. package/v3/dist/cli/commands/learning-helpers.js.map +1 -1
  15. package/v3/dist/cli/commands/learning.d.ts.map +1 -1
  16. package/v3/dist/cli/commands/learning.js +5 -8
  17. package/v3/dist/cli/commands/learning.js.map +1 -1
  18. package/v3/dist/cli/commands/migrate.js +2 -2
  19. package/v3/dist/coordination/constants.d.ts +1 -1
  20. package/v3/dist/coordination/constants.js +1 -1
  21. package/v3/dist/coordination/task-executor.d.ts.map +1 -1
  22. package/v3/dist/coordination/task-executor.js +322 -74
  23. package/v3/dist/coordination/task-executor.js.map +1 -1
  24. package/v3/dist/domains/code-intelligence/coordinator-hypergraph.js +2 -2
  25. package/v3/dist/domains/code-intelligence/coordinator-hypergraph.js.map +1 -1
  26. package/v3/dist/domains/code-intelligence/coordinator.js +2 -2
  27. package/v3/dist/domains/code-intelligence/coordinator.js.map +1 -1
  28. package/v3/dist/domains/coverage-analysis/coordinator.js +1 -1
  29. package/v3/dist/domains/coverage-analysis/services/coverage-analyzer.js +1 -1
  30. package/v3/dist/domains/coverage-analysis/services/coverage-embedder.d.ts +1 -1
  31. package/v3/dist/domains/coverage-analysis/services/coverage-embedder.js +1 -1
  32. package/v3/dist/domains/coverage-analysis/services/gap-detector.js +1 -1
  33. package/v3/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.js +1 -1
  34. package/v3/dist/domains/coverage-analysis/services/hnsw-index.d.ts +2 -2
  35. package/v3/dist/domains/coverage-analysis/services/hnsw-index.js +3 -3
  36. package/v3/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +1 -1
  37. package/v3/dist/domains/coverage-analysis/services/sublinear-analyzer.js +1 -1
  38. package/v3/dist/init/fleet-integration.d.ts.map +1 -1
  39. package/v3/dist/init/fleet-integration.js +3 -4
  40. package/v3/dist/init/fleet-integration.js.map +1 -1
  41. package/v3/dist/init/init-wizard-migration.d.ts.map +1 -1
  42. package/v3/dist/init/init-wizard-migration.js +3 -7
  43. package/v3/dist/init/init-wizard-migration.js.map +1 -1
  44. package/v3/dist/init/init-wizard-steps.d.ts.map +1 -1
  45. package/v3/dist/init/init-wizard-steps.js +3 -4
  46. package/v3/dist/init/init-wizard-steps.js.map +1 -1
  47. package/v3/dist/init/migration/data-migrator.d.ts.map +1 -1
  48. package/v3/dist/init/migration/data-migrator.js +6 -10
  49. package/v3/dist/init/migration/data-migrator.js.map +1 -1
  50. package/v3/dist/init/migration/detector.d.ts.map +1 -1
  51. package/v3/dist/init/migration/detector.js +2 -4
  52. package/v3/dist/init/migration/detector.js.map +1 -1
  53. package/v3/dist/init/phases/01-detection.d.ts.map +1 -1
  54. package/v3/dist/init/phases/01-detection.js +2 -4
  55. package/v3/dist/init/phases/01-detection.js.map +1 -1
  56. package/v3/dist/init/phases/06-code-intelligence.d.ts.map +1 -1
  57. package/v3/dist/init/phases/06-code-intelligence.js +4 -6
  58. package/v3/dist/init/phases/06-code-intelligence.js.map +1 -1
  59. package/v3/dist/init/phases/07-hooks.d.ts +11 -0
  60. package/v3/dist/init/phases/07-hooks.d.ts.map +1 -1
  61. package/v3/dist/init/phases/07-hooks.js +91 -1
  62. package/v3/dist/init/phases/07-hooks.js.map +1 -1
  63. package/v3/dist/init/phases/12-verification.d.ts.map +1 -1
  64. package/v3/dist/init/phases/12-verification.js +2 -4
  65. package/v3/dist/init/phases/12-verification.js.map +1 -1
  66. package/v3/dist/integrations/embeddings/cache/EmbeddingCache.d.ts.map +1 -1
  67. package/v3/dist/integrations/embeddings/cache/EmbeddingCache.js +2 -2
  68. package/v3/dist/integrations/embeddings/cache/EmbeddingCache.js.map +1 -1
  69. package/v3/dist/kernel/constants.d.ts +1 -1
  70. package/v3/dist/kernel/constants.js +1 -1
  71. package/v3/dist/kernel/unified-memory-hnsw.d.ts.map +1 -1
  72. package/v3/dist/kernel/unified-memory-hnsw.js +25 -6
  73. package/v3/dist/kernel/unified-memory-hnsw.js.map +1 -1
  74. package/v3/dist/kernel/unified-memory-migration.d.ts.map +1 -1
  75. package/v3/dist/kernel/unified-memory-migration.js +3 -3
  76. package/v3/dist/kernel/unified-memory-migration.js.map +1 -1
  77. package/v3/dist/learning/metrics-tracker.d.ts.map +1 -1
  78. package/v3/dist/learning/metrics-tracker.js +2 -2
  79. package/v3/dist/learning/metrics-tracker.js.map +1 -1
  80. package/v3/dist/learning/sqlite-persistence.d.ts.map +1 -1
  81. package/v3/dist/learning/sqlite-persistence.js +3 -6
  82. package/v3/dist/learning/sqlite-persistence.js.map +1 -1
  83. package/v3/dist/learning/v2-to-v3-migration.d.ts.map +1 -1
  84. package/v3/dist/learning/v2-to-v3-migration.js +4 -5
  85. package/v3/dist/learning/v2-to-v3-migration.js.map +1 -1
  86. package/v3/dist/mcp/bundle.js +733 -162
  87. package/v3/dist/mcp/tools/security-compliance/scan.d.ts +3 -1
  88. package/v3/dist/mcp/tools/security-compliance/scan.d.ts.map +1 -1
  89. package/v3/dist/mcp/tools/security-compliance/scan.js +417 -72
  90. package/v3/dist/mcp/tools/security-compliance/scan.js.map +1 -1
  91. package/v3/dist/planning/plan-executor.d.ts.map +1 -1
  92. package/v3/dist/planning/plan-executor.js +2 -2
  93. package/v3/dist/planning/plan-executor.js.map +1 -1
  94. package/v3/dist/shared/safe-db.d.ts +32 -0
  95. package/v3/dist/shared/safe-db.d.ts.map +1 -0
  96. package/v3/dist/shared/safe-db.js +41 -0
  97. package/v3/dist/shared/safe-db.js.map +1 -0
  98. package/v3/dist/sync/claude-flow-bridge.js +5 -5
  99. package/v3/dist/sync/claude-flow-bridge.js.map +1 -1
  100. package/v3/dist/sync/embeddings/sync-embedding-generator.js +3 -3
  101. package/v3/dist/sync/embeddings/sync-embedding-generator.js.map +1 -1
  102. package/v3/dist/sync/readers/sqlite-reader.d.ts.map +1 -1
  103. package/v3/dist/sync/readers/sqlite-reader.js +2 -2
  104. package/v3/dist/sync/readers/sqlite-reader.js.map +1 -1
  105. package/v3/package.json +1 -1
@@ -4421,7 +4421,7 @@ var init_constants = __esm({
4421
4421
  /**
4422
4422
  * Vector dimension for coverage analysis embeddings.
4423
4423
  */
4424
- COVERAGE_VECTOR_DIMENSION: 128
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
- if (ruvectorDifferentiableSearch && this.vectors.length > 0) {
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
- scored.push({
5058
- id: this.ids[i58],
5059
- score: fastCosine(queryF32, this.vectors[i58], queryNorm, this.norms[i58])
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 = 128;
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: 128,
11388
+ dimensions: 768,
11370
11389
  M: 16,
11371
11390
  efConstruction: 200,
11372
11391
  efSearch: 100,
@@ -11618,7 +11637,7 @@ var init_hnsw_index = __esm({
11618
11637
  /**
11619
11638
  * Validate and auto-resize vectors to match HNSW configured dimensions.
11620
11639
  * Fix #279: Prevents Rust WASM panic when RealEmbeddings (768-dim) are
11621
- * passed to a 128-dim HNSW index.
11640
+ * passed to a mismatched-dim HNSW index.
11622
11641
  */
11623
11642
  validateVector(vector) {
11624
11643
  if (vector.length !== this.config.dimensions) {
@@ -11721,6 +11740,33 @@ var init_hnsw_index = __esm({
11721
11740
  }
11722
11741
  });
11723
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
+
11724
11770
  // src/integrations/vibium/types.ts
11725
11771
  var init_types2 = __esm({
11726
11772
  "src/integrations/vibium/types.ts"() {
@@ -16333,7 +16379,7 @@ var DEFAULT_SQLITE_CONFIG, SQLitePatternStore;
16333
16379
  var init_sqlite_persistence = __esm({
16334
16380
  "src/learning/sqlite-persistence.ts"() {
16335
16381
  "use strict";
16336
- init_better_sqlite3();
16382
+ init_safe_db();
16337
16383
  init_esm_node();
16338
16384
  init_safe_json();
16339
16385
  init_error_utils();
@@ -16377,10 +16423,7 @@ var init_sqlite_persistence = __esm({
16377
16423
  if (!fs21.existsSync(dir)) {
16378
16424
  fs21.mkdirSync(dir, { recursive: true });
16379
16425
  }
16380
- this.db = new better_sqlite3_default(this.config.dbPath);
16381
- if (this.config.walMode) {
16382
- this.db.pragma("journal_mode = WAL");
16383
- }
16426
+ this.db = openDatabase(this.config.dbPath);
16384
16427
  this.db.pragma(`mmap_size = ${this.config.mmapSize}`);
16385
16428
  this.db.pragma(`cache_size = ${this.config.cacheSize}`);
16386
16429
  if (this.config.foreignKeys) {
@@ -21712,13 +21755,13 @@ var init_trajectory_bridge = __esm({
21712
21755
  const { existsSync: existsSync18, mkdirSync: mkdirSync6 } = await import("fs");
21713
21756
  const { createRequire: createRequire11 } = await import("module");
21714
21757
  const require3 = createRequire11(import.meta.url);
21715
- const Database = require3("better-sqlite3");
21758
+ const { openDatabase: openDatabase2 } = require3("../../shared/safe-db.js");
21716
21759
  const dbPath = join26(this.options.projectRoot, ".agentic-qe", "trajectories.db");
21717
21760
  const dir = join26(this.options.projectRoot, ".agentic-qe");
21718
21761
  if (!existsSync18(dir)) {
21719
21762
  mkdirSync6(dir, { recursive: true });
21720
21763
  }
21721
- const db = new Database(dbPath);
21764
+ const db = openDatabase2(dbPath);
21722
21765
  db.exec(`
21723
21766
  CREATE TABLE IF NOT EXISTS trajectories (
21724
21767
  id TEXT PRIMARY KEY,
@@ -65134,7 +65177,7 @@ var DEFAULT_CONFIG18 = {
65134
65177
  };
65135
65178
  var CoverageAnalyzerService = class _CoverageAnalyzerService {
65136
65179
  static DEFAULT_THRESHOLD = 80;
65137
- static VECTOR_DIMENSION = 128;
65180
+ static VECTOR_DIMENSION = 768;
65138
65181
  memory;
65139
65182
  config;
65140
65183
  llmRouter;
@@ -65668,7 +65711,7 @@ var DEFAULT_CONFIG19 = {
65668
65711
  };
65669
65712
  var GapDetectorService = class _GapDetectorService {
65670
65713
  static DEFAULT_MIN_COVERAGE = 80;
65671
- static VECTOR_DIMENSION = 128;
65714
+ static VECTOR_DIMENSION = 768;
65672
65715
  memory;
65673
65716
  config;
65674
65717
  llmRouter;
@@ -66666,7 +66709,7 @@ init_hnsw_index();
66666
66709
 
66667
66710
  // src/domains/coverage-analysis/services/coverage-embedder.ts
66668
66711
  var DEFAULT_EMBEDDER_CONFIG = {
66669
- dimensions: 128,
66712
+ dimensions: 768,
66670
66713
  includePathFeatures: true,
66671
66714
  includeTemporalFeatures: true,
66672
66715
  normalization: "l2"
@@ -67098,7 +67141,7 @@ var ALL_CATEGORIES = [
67098
67141
  "missing-security-check"
67099
67142
  ];
67100
67143
  var DEFAULT_CONFIG20 = {
67101
- dimensions: 128,
67144
+ dimensions: 768,
67102
67145
  minConfidence: 0.3,
67103
67146
  maxGaps: 50,
67104
67147
  riskWeight: 0.6,
@@ -68807,7 +68850,7 @@ var CoverageAnalysisCoordinator = class extends BaseDomainCoordinator {
68807
68850
  return forecast;
68808
68851
  }
68809
68852
  createGapEmbedding(gap) {
68810
- const VECTOR_DIMENSION = 128;
68853
+ const VECTOR_DIMENSION = 768;
68811
68854
  const embedding = new Array(VECTOR_DIMENSION).fill(0);
68812
68855
  embedding[0] = gap.riskScore;
68813
68856
  embedding[1] = Math.min(1, gap.lines.length / 100);
@@ -88568,7 +88611,7 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
88568
88611
  */
88569
88612
  async initializeHypergraph() {
88570
88613
  try {
88571
- const Database = (await Promise.resolve().then(() => (init_better_sqlite3(), better_sqlite3_exports))).default;
88614
+ const { openDatabase: openDatabase2 } = await Promise.resolve().then(() => (init_safe_db(), safe_db_exports));
88572
88615
  const fs21 = await import("fs");
88573
88616
  const path23 = await import("path");
88574
88617
  const { findProjectRoot: findProjectRoot2 } = await Promise.resolve().then(() => (init_unified_memory(), unified_memory_exports));
@@ -88578,7 +88621,7 @@ var CodeIntelligenceCoordinator = class extends BaseDomainCoordinator {
88578
88621
  if (!fs21.existsSync(dir)) {
88579
88622
  fs21.mkdirSync(dir, { recursive: true });
88580
88623
  }
88581
- this.hypergraphDb = new Database(dbPath);
88624
+ this.hypergraphDb = openDatabase2(dbPath);
88582
88625
  this.hypergraph = await createHypergraphEngine({
88583
88626
  db: this.hypergraphDb,
88584
88627
  maxTraversalDepth: 10,
@@ -132789,10 +132832,16 @@ function detectTransformType(task) {
132789
132832
  }
132790
132833
  async function loadCoverageData(targetPath) {
132791
132834
  const coverageLocations = [
132835
+ // JavaScript/TypeScript (Istanbul/nyc/vitest)
132792
132836
  path16.join(targetPath, "coverage", "coverage-final.json"),
132793
132837
  path16.join(targetPath, "coverage", "lcov.info"),
132794
132838
  path16.join(targetPath, ".nyc_output", "coverage-final.json"),
132795
- 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")
132796
132845
  ];
132797
132846
  for (const coveragePath of coverageLocations) {
132798
132847
  try {
@@ -132801,6 +132850,8 @@ async function loadCoverageData(targetPath) {
132801
132850
  return parseCoverageJson(content);
132802
132851
  } else if (coveragePath.endsWith(".info")) {
132803
132852
  return parseLcovInfo(content);
132853
+ } else if (coveragePath.endsWith(".xml")) {
132854
+ return parseCoberturaXml(content);
132804
132855
  }
132805
132856
  } catch {
132806
132857
  }
@@ -132952,6 +133003,111 @@ function parseLcovInfo(content) {
132952
133003
  }
132953
133004
  };
132954
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
+ }
132955
133111
  async function discoverSourceFiles(targetPath, options = {}) {
132956
133112
  const files = [];
132957
133113
  const { includeTests = true, languages } = options;
@@ -133342,12 +133498,14 @@ var DomainTaskExecutor = class {
133342
133498
  const lines = content.split("\n");
133343
133499
  const relPath = filePath.startsWith(targetPath) ? filePath.slice(targetPath.length).replace(/^\//, "") : filePath;
133344
133500
  const secretPatterns = [
133345
- { regex: /(?:secret|password|api_key|apikey|token|jwt_secret|private_key)\s*[=:]\s*['"][^'"]{8,}['"]/gi, title: "Hardcoded secret", severity: "critical" },
133346
- { regex: /(?:AWS_SECRET|GITHUB_TOKEN|SLACK_TOKEN)\s*[=:]\s*['"][^'"]+['"]/gi, title: "Hardcoded cloud credential", severity: "critical" }
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" }
133347
133504
  ];
133348
133505
  for (const pattern of secretPatterns) {
133349
133506
  for (let i58 = 0; i58 < lines.length; i58++) {
133350
- if (pattern.regex.test(lines[i58])) {
133507
+ const matches = [...lines[i58].matchAll(pattern.regex)];
133508
+ for (const _m of matches) {
133351
133509
  crossLangVulns.push({
133352
133510
  title: pattern.title,
133353
133511
  severity: pattern.severity,
@@ -133356,7 +133514,6 @@ var DomainTaskExecutor = class {
133356
133514
  category: "sensitive-data"
133357
133515
  });
133358
133516
  }
133359
- pattern.regex.lastIndex = 0;
133360
133517
  }
133361
133518
  }
133362
133519
  const sqlPatterns = /(?:execute|query|cursor\.execute)\s*\(\s*(?:f['"]|['"].*%s|['"].*\+\s*\w)/gi;
@@ -133372,14 +133529,29 @@ var DomainTaskExecutor = class {
133372
133529
  }
133373
133530
  sqlPatterns.lastIndex = 0;
133374
133531
  }
133375
- if (/allow_origins\s*=\s*\[?\s*['"]?\*['"]?\s*\]?/i.test(content)) {
133376
- crossLangVulns.push({
133377
- title: "CORS wildcard origin",
133378
- severity: "high",
133379
- location: { file: relPath, line: lines.findIndex((l75) => /allow_origins/i.test(l75)) + 1 },
133380
- description: "CORS configured with wildcard (*) origin \u2014 restrict to specific domains",
133381
- category: "security-misconfiguration"
133382
- });
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
+ }
133383
133555
  }
133384
133556
  if (/(?:DEBUG|debug)\s*[=:]\s*(?:True|true|1)/i.test(content)) {
133385
133557
  crossLangVulns.push({
@@ -133634,19 +133806,58 @@ var DomainTaskExecutor = class {
133634
133806
  });
133635
133807
  this.taskHandlers.set("execute-tests", async (task) => {
133636
133808
  const payload = task.payload;
133637
- const testCount = payload.testFiles?.length || 10;
133638
- const passed = Math.floor(testCount * 0.9);
133639
- const failed = testCount - passed;
133640
- return ok({
133641
- total: testCount,
133642
- passed,
133643
- failed,
133644
- skipped: 0,
133645
- duration: testCount * 50,
133646
- // ~50ms per test
133647
- coverage: 82.5,
133648
- failedTests: failed > 0 ? ["example.test.ts:42"] : []
133649
- });
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
+ }
133650
133861
  });
133651
133862
  this.taskHandlers.set("predict-defects", async (task) => {
133652
133863
  const payload = task.payload;
@@ -133750,68 +133961,116 @@ var DomainTaskExecutor = class {
133750
133961
  });
133751
133962
  this.taskHandlers.set("validate-requirements", async (task) => {
133752
133963
  const payload = task.payload;
133753
- return ok({
133754
- requirementsAnalyzed: 15,
133755
- testable: 12,
133756
- ambiguous: 2,
133757
- untestable: 1,
133758
- coverage: 80,
133759
- bddScenarios: payload.generateBDD ? [
133760
- "Given a user is logged in, When they view the dashboard, Then they see their metrics",
133761
- "Given an API request fails, When the retry limit is exceeded, Then an error is returned"
133762
- ] : []
133763
- });
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
+ }
133764
133990
  });
133765
133991
  this.taskHandlers.set("validate-contracts", async (task) => {
133766
133992
  const payload = task.payload;
133767
- return ok({
133768
- contractPath: payload.contractPath,
133769
- valid: true,
133770
- breakingChanges: [],
133771
- warnings: [
133772
- 'Deprecated field "legacyId" should be removed in next major version'
133773
- ],
133774
- coverage: 95
133775
- });
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
+ }
133776
134032
  });
133777
134033
  this.taskHandlers.set("test-accessibility", async (task) => {
133778
134034
  const payload = task.payload;
133779
134035
  return ok({
133780
- url: payload.url,
134036
+ url: payload.url || "",
133781
134037
  standard: payload.standard || "wcag21-aa",
133782
- passed: true,
134038
+ passed: false,
133783
134039
  violations: [],
133784
- warnings: [
133785
- { rule: "color-contrast", impact: "minor", element: "nav > a" }
133786
- ],
133787
- 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>")
133788
134043
  });
133789
134044
  });
133790
134045
  this.taskHandlers.set("run-chaos", async (task) => {
133791
134046
  const payload = task.payload;
133792
134047
  return ok({
133793
- faultType: payload.faultType,
133794
- target: payload.target,
133795
- dryRun: payload.dryRun,
133796
- duration: payload.duration,
133797
- systemBehavior: payload.dryRun ? "simulated" : "tested",
133798
- resilience: {
133799
- recovered: true,
133800
- recoveryTime: 2500,
133801
- dataLoss: false
133802
- }
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)."
133803
134055
  });
133804
134056
  });
133805
134057
  this.taskHandlers.set("optimize-learning", async (_task) => {
133806
- return ok({
133807
- patternsLearned: 12,
133808
- modelsUpdated: 3,
133809
- memoryConsolidated: true,
133810
- recommendations: [
133811
- "Pattern recognition improved for error handling",
133812
- "Test generation templates optimized"
133813
- ]
133814
- });
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
+ }
133815
134074
  });
133816
134075
  }
133817
134076
  // ============================================================================
@@ -143208,6 +143467,44 @@ function extractHighlights(content, query) {
143208
143467
 
143209
143468
  // src/mcp/tools/security-compliance/scan.ts
143210
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
+ ];
143211
143508
  var SecurityScanTool = class extends MCPToolBase {
143212
143509
  config = {
143213
143510
  name: "qe/security/scan",
@@ -143236,18 +143533,21 @@ var SecurityScanTool = class extends MCPToolBase {
143236
143533
  if (this.isAborted(context)) {
143237
143534
  return { success: false, error: "Operation aborted" };
143238
143535
  }
143536
+ const files = await discoverFiles(target, depth);
143537
+ this.emitStream(context, {
143538
+ status: "discovered",
143539
+ message: `Found ${files.length} files to scan`
143540
+ });
143239
143541
  const vulnerabilities = [];
143240
- if (scanType.includes("sast")) {
143542
+ if (scanType.includes("sast") || scanType.includes("secret")) {
143241
143543
  this.emitStream(context, { status: "sast", message: "Running static analysis" });
143242
- vulnerabilities.push(...generateSASTFindings());
143544
+ const sastVulns = await scanFilesWithPatterns(files, scanType);
143545
+ vulnerabilities.push(...sastVulns);
143243
143546
  }
143244
143547
  if (scanType.includes("dependency")) {
143245
143548
  this.emitStream(context, { status: "dependency", message: "Scanning dependencies" });
143246
- vulnerabilities.push(...generateDependencyFindings());
143247
- }
143248
- if (scanType.includes("secret")) {
143249
- this.emitStream(context, { status: "secret", message: "Scanning for secrets" });
143250
- vulnerabilities.push(...generateSecretFindings());
143549
+ const depVulns = await scanDependencies(target);
143550
+ vulnerabilities.push(...depVulns);
143251
143551
  }
143252
143552
  if (scanType.includes("dast") && dastUrl) {
143253
143553
  this.emitStream(context, { status: "dast", message: `Scanning ${dastUrl}` });
@@ -143262,7 +143562,7 @@ var SecurityScanTool = class extends MCPToolBase {
143262
143562
  medium: vulnerabilities.filter((v62) => v62.severity === "medium").length,
143263
143563
  low: vulnerabilities.filter((v62) => v62.severity === "low").length,
143264
143564
  informational: vulnerabilities.filter((v62) => v62.severity === "informational").length,
143265
- totalFiles: 150,
143565
+ totalFiles: files.length,
143266
143566
  scanDurationMs: Date.now() - startTime
143267
143567
  };
143268
143568
  const severityOrder = ["critical", "high", "medium", "low", "informational"];
@@ -143271,7 +143571,7 @@ var SecurityScanTool = class extends MCPToolBase {
143271
143571
  const passed = worstSeverity > failThreshold;
143272
143572
  this.emitStream(context, {
143273
143573
  status: "complete",
143274
- message: `Scan complete: ${vulnerabilities.length} vulnerabilities found`,
143574
+ message: `Scan complete: ${vulnerabilities.length} vulnerabilities found in ${files.length} files`,
143275
143575
  progress: 100
143276
143576
  });
143277
143577
  return {
@@ -143338,72 +143638,340 @@ var SECURITY_SCAN_SCHEMA = {
143338
143638
  }
143339
143639
  }
143340
143640
  };
143341
- function generateSASTFindings() {
143342
- return [
143343
- {
143344
- id: "SAST-001",
143345
- title: "SQL Injection Risk",
143346
- severity: "high",
143347
- category: "injection",
143348
- location: { file: "src/db/queries.ts", line: 45, snippet: "query = `SELECT * FROM ${table}`" },
143349
- description: "User input directly concatenated in SQL query",
143350
- remediation: "Use parameterized queries or prepared statements",
143351
- cweId: "CWE-89",
143352
- references: ["https://owasp.org/www-community/attacks/SQL_Injection"]
143353
- },
143354
- {
143355
- id: "SAST-002",
143356
- title: "Hardcoded Credentials",
143357
- severity: "critical",
143358
- category: "sensitive-data",
143359
- location: { file: "src/config/database.ts", line: 12, snippet: 'password: "admin123"' },
143360
- description: "Hardcoded password found in source code",
143361
- remediation: "Use environment variables or secure vault for credentials",
143362
- cweId: "CWE-798",
143363
- references: ["https://cwe.mitre.org/data/definitions/798.html"]
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;
143364
143708
  }
143365
- ];
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;
143366
143737
  }
143367
- function generateDependencyFindings() {
143368
- return [
143369
- {
143370
- id: "DEP-001",
143371
- title: "Vulnerable lodash version",
143372
- severity: "medium",
143373
- category: "vulnerable-components",
143374
- location: { file: "package.json", dependency: { name: "lodash", version: "4.17.19" } },
143375
- description: "lodash < 4.17.21 has prototype pollution vulnerability",
143376
- remediation: "Upgrade lodash to 4.17.21 or later",
143377
- cveId: "CVE-2021-23337",
143378
- references: ["https://nvd.nist.gov/vuln/detail/CVE-2021-23337"]
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
+ });
143379
143756
  }
143380
- ];
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;
143381
143832
  }
143382
- function generateSecretFindings() {
143383
- return [
143384
- {
143385
- id: "SECRET-001",
143386
- title: "AWS Access Key Detected",
143387
- severity: "critical",
143388
- category: "sensitive-data",
143389
- location: { file: "src/services/aws.ts", line: 8, snippet: "AKIA...[REDACTED]" },
143390
- description: "AWS access key found in source code",
143391
- remediation: "Remove key, rotate credentials, use AWS IAM roles",
143392
- references: ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"]
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 {
143393
143845
  }
143394
- ];
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;
143395
143963
  }
143396
143964
  function generateDASTFindings(url) {
143397
143965
  return [
143398
143966
  {
143399
- id: "DAST-001",
143400
- title: "Missing Security Headers",
143401
- severity: "medium",
143967
+ id: "DAST-INFO-001",
143968
+ title: "DAST scan target noted",
143969
+ severity: "informational",
143402
143970
  category: "security-misconfiguration",
143403
143971
  location: { file: url },
143404
- description: "X-Frame-Options and Content-Security-Policy headers missing",
143405
- remediation: "Add security headers to HTTP responses",
143406
- references: ["https://owasp.org/www-project-secure-headers/"]
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/"]
143407
143975
  }
143408
143976
  ];
143409
143977
  }
@@ -143441,6 +144009,9 @@ function generateRecommendations5(vulnerabilities, summary) {
143441
144009
  if (vulnerabilities.some((v62) => v62.category === "sensitive-data")) {
143442
144010
  recs.push("Implement proper secrets management");
143443
144011
  }
144012
+ if (vulnerabilities.some((v62) => v62.category === "vulnerable-components")) {
144013
+ recs.push("Run full dependency audit and update vulnerable packages");
144014
+ }
143444
144015
  if (recs.length === 0) {
143445
144016
  recs.push("No critical issues found. Continue regular security reviews.");
143446
144017
  }
@@ -147777,7 +148348,7 @@ function getSharedGOAPPlanner() {
147777
148348
  }
147778
148349
 
147779
148350
  // src/planning/plan-executor.ts
147780
- init_better_sqlite3();
148351
+ init_safe_db();
147781
148352
  init_unified_memory();
147782
148353
  init_error_utils();
147783
148354
  init_safe_json();
@@ -147812,7 +148383,7 @@ var PlanExecutor = class {
147812
148383
  this.spawner = spawner;
147813
148384
  this.config = { ...DEFAULT_CONFIG69, ...config };
147814
148385
  if (!this.config.useUnified) {
147815
- this.db = new better_sqlite3_default(dbPath ?? ":memory:");
148386
+ this.db = openDatabase(dbPath ?? ":memory:", { walMode: false });
147816
148387
  this.db.pragma("journal_mode = WAL");
147817
148388
  }
147818
148389
  }
@@ -149756,7 +150327,7 @@ init_logging();
149756
150327
  init_types();
149757
150328
 
149758
150329
  // src/learning/v2-to-v3-migration.ts
149759
- init_better_sqlite3();
150330
+ init_safe_db();
149760
150331
  init_error_utils();
149761
150332
  init_safe_json();
149762
150333
  init_logging();
@@ -150201,7 +150772,7 @@ init_logging();
150201
150772
  var logger17 = LoggerFactory.create("pattern-lifecycle");
150202
150773
 
150203
150774
  // src/learning/metrics-tracker.ts
150204
- init_better_sqlite3();
150775
+ init_safe_db();
150205
150776
  init_qe_patterns();
150206
150777
  init_safe_json();
150207
150778
  init_logging();