@archpilotlabs/archpilot 0.2.3 → 0.2.5

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.
@@ -13660,11 +13660,11 @@ ${lanes.join("\n")}
13660
13660
  return toComponents;
13661
13661
  }
13662
13662
  const components = toComponents.slice(start);
13663
- const relative17 = [];
13663
+ const relative18 = [];
13664
13664
  for (; start < fromComponents.length; start++) {
13665
- relative17.push("..");
13665
+ relative18.push("..");
13666
13666
  }
13667
- return ["", ...relative17, ...components];
13667
+ return ["", ...relative18, ...components];
13668
13668
  }
13669
13669
  function getRelativePathFromDirectory(fromDirectory, to, getCanonicalFileNameOrIgnoreCase) {
13670
13670
  Debug.assert(getRootLength(fromDirectory) > 0 === getRootLength(to) > 0, "Paths must either both be absolute or both be relative");
@@ -52233,11 +52233,11 @@ ${lanes.join("\n")}
52233
52233
  if (i < rootLength) {
52234
52234
  return void 0;
52235
52235
  }
52236
- const sep = directory.lastIndexOf(directorySeparator, i - 1);
52237
- if (sep === -1) {
52236
+ const sep2 = directory.lastIndexOf(directorySeparator, i - 1);
52237
+ if (sep2 === -1) {
52238
52238
  return void 0;
52239
52239
  }
52240
- return directory.substr(0, Math.max(sep, rootLength));
52240
+ return directory.substr(0, Math.max(sep2, rootLength));
52241
52241
  }
52242
52242
  }
52243
52243
  }
@@ -58143,9 +58143,9 @@ ${lanes.join("\n")}
58143
58143
  if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) {
58144
58144
  return;
58145
58145
  }
58146
- const relative17 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
58146
+ const relative18 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
58147
58147
  for (const symlinkDirectory of symlinkDirectories) {
58148
- const option = resolvePath(symlinkDirectory, relative17);
58148
+ const option = resolvePath(symlinkDirectory, relative18);
58149
58149
  const result2 = cb(option, target === referenceRedirect);
58150
58150
  shouldFilterIgnoredPaths = true;
58151
58151
  if (result2) return result2;
@@ -127982,7 +127982,7 @@ ${lanes.join("\n")}
127982
127982
  }
127983
127983
  }
127984
127984
  function createImportCallExpressionAMD(arg, containsLexicalThis) {
127985
- const resolve9 = factory2.createUniqueName("resolve");
127985
+ const resolve10 = factory2.createUniqueName("resolve");
127986
127986
  const reject = factory2.createUniqueName("reject");
127987
127987
  const parameters = [
127988
127988
  factory2.createParameterDeclaration(
@@ -127991,7 +127991,7 @@ ${lanes.join("\n")}
127991
127991
  /*dotDotDotToken*/
127992
127992
  void 0,
127993
127993
  /*name*/
127994
- resolve9
127994
+ resolve10
127995
127995
  ),
127996
127996
  factory2.createParameterDeclaration(
127997
127997
  /*modifiers*/
@@ -128008,7 +128008,7 @@ ${lanes.join("\n")}
128008
128008
  factory2.createIdentifier("require"),
128009
128009
  /*typeArguments*/
128010
128010
  void 0,
128011
- [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve9, reject]
128011
+ [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve10, reject]
128012
128012
  )
128013
128013
  )
128014
128014
  ]);
@@ -214726,8 +214726,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
214726
214726
  installPackage(options) {
214727
214727
  this.packageInstallId++;
214728
214728
  const request3 = { kind: "installPackage", ...options, id: this.packageInstallId };
214729
- const promise = new Promise((resolve9, reject) => {
214730
- (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve9, reject });
214729
+ const promise = new Promise((resolve10, reject) => {
214730
+ (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve10, reject });
214731
214731
  });
214732
214732
  this.installer.send(request3);
214733
214733
  return promise;
@@ -215444,6 +215444,8 @@ function classifyValidationSourceScope(relativePath) {
215444
215444
  const isFixture = hasPathSegment(normalized, /^(?:fixtures?|__fixtures__)$/u);
215445
215445
  const isTestPlugin = hasPathSegment(normalized, /^(?:test-plugins?|testing-plugins?)$/u);
215446
215446
  const isExamplePlugin = hasPathSegment(normalized, /^example-plugins?$/u) || hasTopLevelPathSegment(normalized, /^examples?$/u);
215447
+ const isMavenIntegrationTestModule = hasTopLevelPathSegment(normalized, /^[a-z0-9_.-]+-integration-tests?$/u) || hasTopLevelPathSegment(normalized, /^[a-z0-9_.-]+-it$/u);
215448
+ const isMavenExampleModule = hasTopLevelPathSegment(normalized, /^[a-z0-9_.-]+-examples?$/u);
215447
215449
  const isGenerated = hasPathSegment(normalized, /^(?:generated|__generated__|gen|templates?)$/u) || /\.(?:generated|gen|g)\.(?:ts|tsx|js|jsx|java|cs|py|php|go)$/u.test(fileName) || /\.d\.ts$/u.test(fileName);
215448
215450
  const isMigration = hasPathSegment(normalized, /^(?:migrations?|schema-migrations?|data-migrations|migration-utils?)$/u);
215449
215451
  const isCliTooling = hasPathSegment(normalized, /^(?:cli|bin|scripts?|tools?|scaffold|scaffolding|generators?)$/u) || /(?:^|[./_-])(?:cli|script|tool|generator|scaffold)(?:[./_-]|$)/u.test(fileName);
@@ -215454,11 +215456,11 @@ function classifyValidationSourceScope(relativePath) {
215454
215456
  category = "generated";
215455
215457
  } else if (isE2e) {
215456
215458
  category = "e2e";
215457
- } else if (isTestFile || hasPathSegment(normalized, /^(?:test|tests|__tests__|spec|specs|__mocks__|cypress|cypress-tests)$/u)) {
215459
+ } else if (isTestFile || isMavenIntegrationTestModule || hasPathSegment(normalized, /^(?:test|tests|__tests__|spec|specs|__mocks__|cypress|cypress-tests)$/u)) {
215458
215460
  category = "test";
215459
215461
  } else if (isTestPlugin) {
215460
215462
  category = "test-plugin";
215461
- } else if (isExamplePlugin) {
215463
+ } else if (isExamplePlugin || isMavenExampleModule) {
215462
215464
  category = "example-plugin";
215463
215465
  } else if (isFixture) {
215464
215466
  category = "fixture";
@@ -215970,6 +215972,41 @@ async function buildExplicitStandaloneModulePathMap(workspaceRoot, architectureC
215970
215972
  function isTestSourcePath(relativePath) {
215971
215973
  return classifyValidationSourceScope(relativePath).isTestLike;
215972
215974
  }
215975
+ function hasStandardTestSourceRoot(relativePath) {
215976
+ const normalized = normalizePath4(relativePath);
215977
+ return /(?:^|\/)src\/(?:test|it|integration-test|integration-tests)\//u.test(normalized) || /(?:^|\/)(?:test|tests|__tests__|spec|specs|e2e|cypress)\//u.test(normalized) || /\.(?:spec|test|e2e-spec|integration-test)\.(?:ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(
215978
+ normalized.split("/").at(-1) ?? normalized
215979
+ );
215980
+ }
215981
+ function shouldSkipDependencySource(relativePath, moduleRoot, workspaceRoot, includeTestFiles, includeConfiguredNonProductionModuleSources) {
215982
+ if (includeTestFiles) {
215983
+ return false;
215984
+ }
215985
+ const moduleRootRelativePath = normalizePath4(path7.relative(workspaceRoot, moduleRoot));
215986
+ const moduleRootScope = classifyValidationSourceScope(moduleRootRelativePath);
215987
+ if (hasStandardTestSourceRoot(relativePath)) {
215988
+ return !includeConfiguredNonProductionModuleSources || moduleRootScope.isProduction || moduleRootScope.isTestLike;
215989
+ }
215990
+ if (!isTestSourcePath(relativePath)) {
215991
+ return false;
215992
+ }
215993
+ return !includeConfiguredNonProductionModuleSources || !moduleRootScope.isTestLike;
215994
+ }
215995
+ function filterImportsForBoundaryChecks(imports, moduleRoots, workspaceRoot) {
215996
+ return imports.filter((dependencyImport) => {
215997
+ const moduleRoot = moduleRoots.get(dependencyImport.sourceModule);
215998
+ if (!moduleRoot) {
215999
+ return true;
216000
+ }
216001
+ return !shouldSkipDependencySource(
216002
+ dependencyImport.sourceFileRelativePath,
216003
+ moduleRoot,
216004
+ workspaceRoot,
216005
+ false,
216006
+ false
216007
+ );
216008
+ });
216009
+ }
215973
216010
  async function collectSourceFiles(directoryPath, adapter, scanRootPath = directoryPath, excludedDirectoryRoots = []) {
215974
216011
  const entries = await import_node_fs6.promises.readdir(directoryPath, { withFileTypes: true });
215975
216012
  entries.sort((left, right) => left.name.localeCompare(right.name));
@@ -216197,7 +216234,7 @@ function extractJavaPackageName(sourceText) {
216197
216234
  const match = /^\s*package\s+([a-zA-Z_][\w.]*)\s*;/mu.exec(sourceText);
216198
216235
  return match?.[1];
216199
216236
  }
216200
- async function buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) {
216237
+ async function buildJavaImportIndex(workspaceRoot, moduleRoots, adapter, options) {
216201
216238
  const classes = /* @__PURE__ */ new Map();
216202
216239
  const packageCandidates = /* @__PURE__ */ new Map();
216203
216240
  for (const [moduleId, moduleRoot] of [...moduleRoots.entries()].sort(
@@ -216207,7 +216244,13 @@ async function buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) {
216207
216244
  const sourceFiles = await collectSourceFiles(moduleRoot, adapter, moduleRoot, childModuleRoots);
216208
216245
  for (const sourceFilePath of sourceFiles) {
216209
216246
  const relativePath = normalizePath4(path7.relative(workspaceRoot, sourceFilePath));
216210
- if (isTestSourcePath(relativePath)) {
216247
+ if (shouldSkipDependencySource(
216248
+ relativePath,
216249
+ moduleRoot,
216250
+ workspaceRoot,
216251
+ false,
216252
+ options?.includeConfiguredNonProductionModuleSources === true
216253
+ )) {
216211
216254
  continue;
216212
216255
  }
216213
216256
  const sourceText = await readTextFileIfExists2(sourceFilePath);
@@ -216850,10 +216893,13 @@ async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath,
216850
216893
  async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath, moduleRoots, explicitStandaloneModuleByPath, workspacePackageAliases, adapter, options) {
216851
216894
  const imports = [];
216852
216895
  const includeTestFiles = options?.includeTestFiles === true;
216896
+ const includeConfiguredNonProductionModuleSources = options?.includeConfiguredNonProductionModuleSources === true;
216853
216897
  if (!supportsDependencyImportParsing(adapter)) {
216854
216898
  return imports;
216855
216899
  }
216856
- const javaImportIndex = usesJavaImportParser(adapter) ? await buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) : void 0;
216900
+ const javaImportIndex = usesJavaImportParser(adapter) ? await buildJavaImportIndex(workspaceRoot, moduleRoots, adapter, {
216901
+ includeConfiguredNonProductionModuleSources
216902
+ }) : void 0;
216857
216903
  for (const [moduleName, moduleRoot] of [...moduleRoots.entries()].sort(
216858
216904
  ([left], [right]) => left.localeCompare(right)
216859
216905
  )) {
@@ -216868,7 +216914,13 @@ async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath,
216868
216914
  const sourceFileRelativePath = normalizePath4(
216869
216915
  path7.relative(workspaceRoot, sourceFilePath)
216870
216916
  );
216871
- if (!includeTestFiles && isTestSourcePath(sourceFileRelativePath)) {
216917
+ if (shouldSkipDependencySource(
216918
+ sourceFileRelativePath,
216919
+ moduleRoot,
216920
+ workspaceRoot,
216921
+ includeTestFiles,
216922
+ includeConfiguredNonProductionModuleSources
216923
+ )) {
216872
216924
  continue;
216873
216925
  }
216874
216926
  const sourceText = await readTextFileIfExists2(sourceFilePath);
@@ -217418,7 +217470,10 @@ async function buildDependencyGraphSummary(workspaceRoot, architectureContract,
217418
217470
  explicitStandaloneModuleByPath,
217419
217471
  workspacePackageAliases,
217420
217472
  adapter,
217421
- { resolutionContext }
217473
+ {
217474
+ includeConfiguredNonProductionModuleSources: true,
217475
+ resolutionContext
217476
+ }
217422
217477
  );
217423
217478
  options?.onCollectedImports?.(imports);
217424
217479
  options?.onResolutionStats?.(resolutionContext.getStats());
@@ -217522,10 +217577,11 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217522
217577
  workspacePackageAliases,
217523
217578
  adapter
217524
217579
  );
217580
+ const boundaryImports = filterImportsForBoundaryChecks(imports, moduleRoots, workspaceRoot);
217525
217581
  const dependencyContextResolver = createArchitectureDependencyContextResolver(
217526
217582
  architectureContract
217527
217583
  );
217528
- const peerImports = filterPeerModuleImports(imports);
217584
+ const peerImports = filterPeerModuleImports(boundaryImports);
217529
217585
  const moduleScopedPeerImports = peerImports.filter(
217530
217586
  (dependencyImport) => isModuleScopedDependencyImport(
217531
217587
  architectureContract,
@@ -217836,7 +217892,8 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217836
217892
  workspaceRoot,
217837
217893
  canonicalModuleRoots
217838
217894
  ),
217839
- adapter
217895
+ adapter,
217896
+ { includeConfiguredNonProductionModuleSources: true }
217840
217897
  );
217841
217898
  const canonicalPeerImports = filterPeerModuleImports(canonicalImports).filter(
217842
217899
  (dependencyImport) => isModuleScopedDependencyImport(architectureContract, dependencyImport)
@@ -217934,8 +217991,9 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
217934
217991
  workspacePackageAliases,
217935
217992
  adapter
217936
217993
  );
217994
+ const boundaryImports = filterImportsForBoundaryChecks(imports, moduleRoots, workspaceRoot);
217937
217995
  const dependencyContextResolver = parsedArchitectureContract ? createArchitectureDependencyContextResolver(parsedArchitectureContract) : void 0;
217938
- const peerImports = filterPeerModuleImports(imports);
217996
+ const peerImports = filterPeerModuleImports(boundaryImports);
217939
217997
  const moduleScopedPeerImports = peerImports.filter(
217940
217998
  (dependencyImport) => isModuleScopedDependencyImport(
217941
217999
  parsedArchitectureContract,
@@ -218191,7 +218249,8 @@ async function buildModuleDependencyGraphSnapshot(workspaceRoot, options) {
218191
218249
  moduleRoots,
218192
218250
  explicitStandaloneModuleByPath,
218193
218251
  workspacePackageAliases,
218194
- adapter
218252
+ adapter,
218253
+ { includeConfiguredNonProductionModuleSources: true }
218195
218254
  );
218196
218255
  const imports = filterPeerModuleImports(allImports).filter(
218197
218256
  (dependencyImport) => moduleSet.has(dependencyImport.sourceModule) && moduleSet.has(dependencyImport.targetModule)
@@ -222217,7 +222276,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222217
222276
  "AP-ARCH-005",
222218
222277
  "error",
222219
222278
  true,
222220
- "No modules are registered in architecture.json. Module registry path checks are not applicable."
222279
+ "No explicit root modules are registered in architecture.json. Root module registry path checks are not applicable; component-backed contracts are validated by dependency checks."
222221
222280
  )
222222
222281
  });
222223
222282
  }
@@ -222227,7 +222286,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222227
222286
  "AP-ARCH-006",
222228
222287
  "error",
222229
222288
  true,
222230
- "No modules are registered in architecture.json. Module contract file checks are not applicable."
222289
+ "No explicit root modules are registered in architecture.json. Root module contract file checks are not applicable; component-backed contracts are validated by dependency checks."
222231
222290
  )
222232
222291
  });
222233
222292
  }
@@ -222237,7 +222296,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222237
222296
  "AP-ARCH-007",
222238
222297
  "error",
222239
222298
  true,
222240
- "No modules are registered in architecture.json. Module contract identity checks are not applicable."
222299
+ "No explicit root modules are registered in architecture.json. Root module contract identity checks are not applicable; component-backed contracts are validated by dependency checks."
222241
222300
  )
222242
222301
  });
222243
222302
  }
@@ -222247,7 +222306,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222247
222306
  "AP-ARCH-008",
222248
222307
  "error",
222249
222308
  true,
222250
- "No modules are registered in architecture.json. Module public entrypoint alignment checks are not applicable."
222309
+ "No explicit root modules are registered in architecture.json. Root module public entrypoint alignment checks are not applicable; component-backed contracts are validated by dependency checks."
222251
222310
  )
222252
222311
  });
222253
222312
  }
@@ -223196,7 +223255,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223196
223255
  "info",
223197
223256
  `Remote policy configured. Loading policy from ${policySourceUrl}.`
223198
223257
  );
223199
- return new Promise((resolve9) => {
223258
+ return new Promise((resolve10) => {
223200
223259
  const request3 = https.request(
223201
223260
  {
223202
223261
  protocol: validated.url.protocol,
@@ -223223,7 +223282,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223223
223282
  "warn",
223224
223283
  `Remote policy request failed with HTTP ${statusCode}. Using local policy only.`
223225
223284
  );
223226
- resolve9({
223285
+ resolve10({
223227
223286
  message: `Remote policy request failed with HTTP ${statusCode}. Using local policy only.`
223228
223287
  });
223229
223288
  return;
@@ -223237,7 +223296,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223237
223296
  "warn",
223238
223297
  "Remote policy payload is invalid JSON. Using local policy only."
223239
223298
  );
223240
- resolve9({
223299
+ resolve10({
223241
223300
  message: "Remote policy payload is invalid JSON. Using local policy only."
223242
223301
  });
223243
223302
  return;
@@ -223249,7 +223308,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223249
223308
  "warn",
223250
223309
  "Remote policy payload has an invalid structure. Using local policy only."
223251
223310
  );
223252
- resolve9({
223311
+ resolve10({
223253
223312
  message: "Remote policy payload has an invalid structure. Using local policy only."
223254
223313
  });
223255
223314
  return;
@@ -223259,7 +223318,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223259
223318
  "info",
223260
223319
  "Remote policy loaded successfully."
223261
223320
  );
223262
- resolve9({
223321
+ resolve10({
223263
223322
  policy: normalized,
223264
223323
  message: "Remote policy loaded successfully."
223265
223324
  });
@@ -223275,7 +223334,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223275
223334
  "warn",
223276
223335
  "Remote policy unavailable. Using local policy only."
223277
223336
  );
223278
- resolve9({
223337
+ resolve10({
223279
223338
  message: "Remote policy unavailable. Using local policy only."
223280
223339
  });
223281
223340
  });
@@ -225597,19 +225656,40 @@ function hasSelectStar(statement) {
225597
225656
  return /\bselect\s+(distinct\s+)?\*/i.test(statement);
225598
225657
  }
225599
225658
  function hasPaginationEvidence(statement) {
225600
- return /\blimit\s+\d+\b|\boffset\s+\d+\b|\bfetch\s+(first|next)\b|\btop\s+\d+\b/i.test(
225659
+ const boundValuePattern = "(?:\\d+|\\$\\d+|\\?|:[A-Za-z_]\\w*|@[A-Za-z_]\\w*|\\$\\{[^}]{1,120}\\}|[A-Za-z_]\\w*)";
225660
+ const valueTerminatorPattern = "(?=\\s|,|;|\\)|$)";
225661
+ return new RegExp(
225662
+ `\\blimit\\s+${boundValuePattern}${valueTerminatorPattern}|\\boffset\\s+${boundValuePattern}${valueTerminatorPattern}|\\bfetch\\s+(first|next)\\b|\\btop\\s+${boundValuePattern}${valueTerminatorPattern}`,
225663
+ "i"
225664
+ ).test(
225601
225665
  statement
225602
225666
  );
225603
225667
  }
225668
+ function hasEqualityPredicate(statement, columnPattern) {
225669
+ return new RegExp(
225670
+ `\\bwhere\\b[\\s\\S]*\\b(?:${columnPattern})\\b\\s*=\\s*(?:[\\w$:@?]+|'[^']+'|"[^"]+"|\\d+)`,
225671
+ "iu"
225672
+ ).test(statement);
225673
+ }
225674
+ function isCatalogIdentifierPointLookup(statement) {
225675
+ const metadataSourcePattern = /\bfrom\s+(?:information_schema\.(?:schemata|tables|columns|key_column_usage|table_constraints)|pg_catalog\.(?:pg_class|pg_namespace|pg_attribute|pg_constraint|pg_type|pg_enum|pg_tables|pg_indexes)|pg_(?:class|namespace|attribute|constraint|type|enum|tables|indexes))\b/iu;
225676
+ if (!metadataSourcePattern.test(statement)) {
225677
+ return false;
225678
+ }
225679
+ return hasEqualityPredicate(statement, "schema_name|table_schema|table_name|column_name|constraint_name") || hasEqualityPredicate(statement, "schemaname|tablename|relname|nspname|attname|conname|typname|enumlabel|indexname");
225680
+ }
225604
225681
  function isObviousPointLookup(statement) {
225605
225682
  const normalized = statement.toLowerCase();
225683
+ if (/\bselect\s+exists\s*\(/i.test(normalized)) {
225684
+ return true;
225685
+ }
225606
225686
  if (!normalized.includes("where")) {
225607
225687
  return false;
225608
225688
  }
225609
225689
  if (normalized.includes(" or ")) {
225610
225690
  return false;
225611
225691
  }
225612
- return /\bwhere\b[\s\S]*\b([a-z_]*id)\b\s*=\s*([\w$:@?]+|'[^']+'|\d+)/i.test(normalized);
225692
+ return hasEqualityPredicate(normalized, "id|uuid|slug|email|identifier") || isCatalogIdentifierPointLookup(normalized);
225613
225693
  }
225614
225694
  function listModulePathEntries(contract) {
225615
225695
  return Object.entries(contract.modules ?? {}).map(([moduleName, reference]) => {
@@ -226190,13 +226270,14 @@ function detectRepeatedQueryPattern(method) {
226190
226270
  }
226191
226271
  function extractSqlQueryLiterals(content) {
226192
226272
  const queries = [];
226273
+ const searchableContent = maskSourceComments(content);
226193
226274
  const patterns = [
226194
226275
  /(?:\b(?:[\w$]+\.)?(?:query|execute|executeQuery|createNativeQuery|createQuery|FromSqlRaw|FromSqlInterpolated|Query|QueryContext|QueryRow|QueryRowContext|Exec|ExecContext|Raw|text)|\$queryRaw|\$executeRaw)\s*\([^'"`)]{0,180}?(['"`])([\s\S]{0,900}?)\1/giu,
226195
226276
  /\b(?:DB::select|DB::statement|DB::raw|DB::table)\s*\([^'"`)]{0,180}?(['"`])([\s\S]{0,900}?)\1/gu,
226196
226277
  /@Query\s*\(\s*(['"`])([\s\S]{0,900}?)\1/gu
226197
226278
  ];
226198
226279
  for (const pattern of patterns) {
226199
- for (const match of content.matchAll(pattern)) {
226280
+ for (const match of searchableContent.matchAll(pattern)) {
226200
226281
  const sql = match[2];
226201
226282
  if (!sql || !/\b(?:select|update|delete|insert)\b/iu.test(sql)) {
226202
226283
  continue;
@@ -226209,6 +226290,71 @@ function extractSqlQueryLiterals(content) {
226209
226290
  }
226210
226291
  return queries;
226211
226292
  }
226293
+ function maskSourceComments(content) {
226294
+ let masked = "";
226295
+ let index = 0;
226296
+ let state = "code";
226297
+ let escaped = false;
226298
+ while (index < content.length) {
226299
+ const current = content[index] ?? "";
226300
+ const next = content[index + 1] ?? "";
226301
+ if (state === "line-comment") {
226302
+ if (current === "\r" || current === "\n") {
226303
+ masked += current;
226304
+ state = "code";
226305
+ } else {
226306
+ masked += " ";
226307
+ }
226308
+ index += 1;
226309
+ continue;
226310
+ }
226311
+ if (state === "block-comment") {
226312
+ if (current === "*" && next === "/") {
226313
+ masked += " ";
226314
+ index += 2;
226315
+ state = "code";
226316
+ continue;
226317
+ }
226318
+ masked += current === "\r" || current === "\n" ? current : " ";
226319
+ index += 1;
226320
+ continue;
226321
+ }
226322
+ if (state === "single" || state === "double" || state === "template") {
226323
+ masked += current;
226324
+ if (escaped) {
226325
+ escaped = false;
226326
+ } else if (current === "\\") {
226327
+ escaped = true;
226328
+ } else if (state === "single" && current === "'" || state === "double" && current === '"' || state === "template" && current === "`") {
226329
+ state = "code";
226330
+ }
226331
+ index += 1;
226332
+ continue;
226333
+ }
226334
+ if (current === "/" && next === "/") {
226335
+ masked += " ";
226336
+ index += 2;
226337
+ state = "line-comment";
226338
+ continue;
226339
+ }
226340
+ if (current === "/" && next === "*") {
226341
+ masked += " ";
226342
+ index += 2;
226343
+ state = "block-comment";
226344
+ continue;
226345
+ }
226346
+ if (current === "'") {
226347
+ state = "single";
226348
+ } else if (current === '"') {
226349
+ state = "double";
226350
+ } else if (current === "`") {
226351
+ state = "template";
226352
+ }
226353
+ masked += current;
226354
+ index += 1;
226355
+ }
226356
+ return masked;
226357
+ }
226212
226358
  function detectCodeSqlQueryShapeFindings(file, config) {
226213
226359
  const findings = [];
226214
226360
  for (const query of extractSqlQueryLiterals(file.content)) {
@@ -226298,12 +226444,18 @@ function hasAssignedBuilderBoundedTerminal(methodBody, snippet) {
226298
226444
  }
226299
226445
  return new RegExp(`\\b${variableName}\\s*\\.\\s*(?:getOne|getRawOne|loadOne|getCount|getExists)\\s*\\(`, "iu").test(methodBody);
226300
226446
  }
226447
+ function hasIdentifierPredicateEvidence(snippet) {
226448
+ return /\.(?:where|andWhere|orWhere)\s*\(\s*['"`][^'"`]{0,240}\b(?:\w*id|uuid|slug|email|identifier)\b[^'"`]{0,120}(?:=| in\b|IN\b)/iu.test(snippet) || /\bwhere\s*:\s*\{[\s\S]{0,420}\b(?:id|uuid|slug|email|identifier|channelId|orderId|customerId|userId|productId|variantId)\b\s*[:=]/iu.test(snippet);
226449
+ }
226450
+ function hasQueryBuilderTerminalEvidence(snippet, methodBody) {
226451
+ return /\.(?:getMany|getRawMany|loadMany|getOne|getRawOne|loadOne|getCount|getExists|execute)\s*\(/iu.test(snippet) || hasAssignedBuilderBoundedTerminal(methodBody, snippet);
226452
+ }
226301
226453
  function isNonCollectionOrmRead(label, snippet, methodBody = snippet) {
226302
226454
  const terminal = getOrmTerminalOperation(snippet);
226303
226455
  return /\b(?:findOne|findOneOrFail|findOneBy|findOneByOrFail|findUnique|findFirst|count|exists|aggregate)\b/iu.test(label) || !!terminal && /^(?:getOne|getRawOne|loadOne|getCount|getExists|findOne|findOneOrFail|findOneBy|findOneByOrFail|findUnique|findFirst|count|exists|update|delete|remove|save|insert|execute)$/iu.test(terminal) || isScopedRelationLoad(snippet) || hasAssignedBuilderBoundedTerminal(methodBody, snippet);
226304
226456
  }
226305
226457
  function hasOrmBoundEvidence(snippet) {
226306
- return codePaginationEvidencePattern.test(snippet) || /\.(?:take|limit|offset|skip)\s*\(/iu.test(snippet) || /\b(?:maxResults|setMaxResults|firstResult|setFirstResult)\s*\(/iu.test(snippet) || /\b(?:pageSize|perPage|limit|take)\s*[:=]\s*\d+\b/iu.test(snippet);
226458
+ return codePaginationEvidencePattern.test(snippet) || /\.(?:take|limit|offset|skip)\s*\(/iu.test(snippet) || /\b(?:maxResults|setMaxResults|firstResult|setFirstResult)\s*\(/iu.test(snippet) || /\b(?:pageSize|perPage|limit|take)\s*[:=]\s*\d+\b/iu.test(snippet) || hasIdentifierPredicateEvidence(snippet);
226307
226459
  }
226308
226460
  function getOrmQueryTarget(method, label, snippet) {
226309
226461
  const terminal = getOrmTerminalOperation(snippet);
@@ -226326,6 +226478,9 @@ function getOrmQueryLabel(method, label, snippet) {
226326
226478
  function detectOrmQueryShapeFindings(method, config) {
226327
226479
  const findings = [];
226328
226480
  for (const evidence of collectOrmReadEvidence(method)) {
226481
+ if (evidence.label === "node.query" && !hasQueryBuilderTerminalEvidence(evidence.snippet, method.body)) {
226482
+ continue;
226483
+ }
226329
226484
  if (config.tenantModel === "same_db_same_schema" && !tenantPredicatePattern.test(evidence.snippet)) {
226330
226485
  findings.push(createCodeFinding({
226331
226486
  id: "AP-DQR-001",
@@ -227034,7 +227189,7 @@ function detectControllerBusinessLogic(entry, classification, moduleName, contex
227034
227189
  });
227035
227190
  }
227036
227191
  function detectRepositoryBusinessLogic(entry, classification, moduleName) {
227037
- if (!classification.isRepository) {
227192
+ if (!classification.isRepository || !isProductionBackendGovernanceScope(classification.scope)) {
227038
227193
  return void 0;
227039
227194
  }
227040
227195
  if (entry.extension === ".java" && isPureSpringDataRepositoryInterface(entry.content)) {
@@ -227324,6 +227479,7 @@ var import_node_fs26 = require("node:fs");
227324
227479
  var ts4 = __toESM(require_typescript());
227325
227480
  init_moduleDiscovery();
227326
227481
  init_archpilotIgnore();
227482
+ init_sourceScopeClassification();
227327
227483
  var RuleIds = {
227328
227484
  AUTH_MISSING_ENFORCEMENT: "AP-AUTH-001",
227329
227485
  AUTH_INCONSISTENT_ENFORCEMENT: "AP-AUTH-002",
@@ -227362,7 +227518,7 @@ var publicEvidencePattern = /@Public\b|@PermitAll\b|\[AllowAnonymous\b[^\]]*\]|p
227362
227518
  var roleEvidencePattern = /@(?:Roles|Permissions|RequirePermission|PreAuthorize|Secured|RolesAllowed)\s*(?:\(|\b)([^)\n]*)|\[Authorize\s*\([^)\]]*(?:Roles|Policy)\s*=|(?:requireRole\w*|RequireRole\w*|require_role|RoleChecker|adminMiddleware|can:|permission:|scopes?\s*=|Security\s*\([^)]*scopes)\b/u;
227363
227519
  var tenantSignalPattern = /\b(?:tenantId|tenant_id|organizationId|organization_id|orgId|org_id|workspaceId|workspace_id|accountId|account_id|companyId|company_id|customerId|customer_id|TenantContext|CurrentTenant|TenantResolver|TenantProvider|request\.tenant|req\.tenant|user\.tenantId|user\.tenant_id|user\.organizationId|user\.organization_id|user\.orgId|user\.accountId|user\.workspaceId|user\.companyId|user\.customerId|HibernateFilter|CurrentTenant)\b/u;
227364
227520
  var tenantPredicateEvidencePattern = /\b(?:tenantId|tenant_id|organizationId|organization_id|orgId|org_id|workspaceId|workspace_id|accountId|account_id|companyId|company_id|customerId|customer_id|TenantContext|CurrentTenant|TenantResolver|TenantProvider|request\.tenant|req\.tenant|user\.tenantId|user\.tenant_id|user\.organizationId|user\.organization_id|user\.orgId|user\.accountId|user\.workspaceId|user\.companyId|user\.customerId|HibernateFilter|CurrentTenant)\b/u;
227365
- var repositoryRolePattern = /\b(?:role|roles|permission|permissions|isAdmin|hasRole|hasPermission|SecurityContextHolder|Authentication|Principal)\b/u;
227521
+ var executableAuthorizationDecisionPattern = /@(?:PreAuthorize|PostAuthorize|Secured|RolesAllowed)\b|\[(?:Authorize)\b[^\]]*(?:Roles|Policy)\s*=|\b(?:hasRole|hasAuthority|hasPermission|isUserInRole|checkPermission|requireRole\w*|RequireRole\w*|require_role|canActivate|authorize|assertAuthorized|PermissionChecker|AccessDecisionManager|SecurityContextHolder\.getContext\(\)\.getAuthentication)\s*\(|\b(?:user|principal|currentUser|account)\.(?:role|roles|permission|permissions|isAdmin)\b\s*(?:[=!]==?|\.includes\s*\(|\.contains\s*\()/u;
227366
227522
  function normalizePath12(value) {
227367
227523
  return value.replace(/\\/g, "/");
227368
227524
  }
@@ -227754,7 +227910,10 @@ function isProtectedLooking(endpoint) {
227754
227910
  }
227755
227911
  function detectAuthorizationFindings(files, contract, astCache) {
227756
227912
  const findings = [];
227757
- for (const file of files) {
227913
+ const productionFiles = files.filter(
227914
+ (file) => isProductionBackendGovernanceScope(classifyValidationSourceScope(file.relativePath))
227915
+ );
227916
+ for (const file of productionFiles) {
227758
227917
  const moduleName = inferModuleForPath3(contract, file.relativePath);
227759
227918
  const endpoints = extractEndpoints(file, moduleName);
227760
227919
  if (endpoints.length === 0 && !isControllerFile(file, astCache)) {
@@ -227789,8 +227948,8 @@ function detectAuthorizationFindings(files, contract, astCache) {
227789
227948
  }
227790
227949
  }
227791
227950
  }
227792
- for (const file of files.filter((candidate) => isRepositoryFile(candidate, astCache))) {
227793
- const roleMatch = repositoryRolePattern.exec(file.content);
227951
+ for (const file of productionFiles.filter((candidate) => isRepositoryFile(candidate, astCache))) {
227952
+ const roleMatch = executableAuthorizationDecisionPattern.exec(file.content);
227794
227953
  if (!roleMatch) {
227795
227954
  continue;
227796
227955
  }
@@ -228272,7 +228431,7 @@ function classifySourceFile2(file, contract, astCache) {
228272
228431
  const scope = classifyValidationSourceScope(file.relativePath);
228273
228432
  const roles = new Set(getDeclaredRoles2(file, astCache));
228274
228433
  const lowerPath = file.relativePath.toLowerCase();
228275
- if (/(^|[./_-])controller\.(ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(lowerPath) || /(^|\/)(controllers?|routers?|routes?|handlers?)\//u.test(lowerPath)) {
228434
+ if (/(^|[./_-])controller\.(ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(lowerPath) || /(^|\/)(controllers?|routers?|routes?)\//u.test(lowerPath)) {
228276
228435
  roles.add("controller");
228277
228436
  }
228278
228437
  if (/(^|[./_-])service\.(ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(lowerPath) || /(^|\/)(services?)\//u.test(lowerPath)) {
@@ -230589,8 +230748,9 @@ function extractJavaSignals(file) {
230589
230748
  publishes: []
230590
230749
  });
230591
230750
  }
230592
- for (const match of file.content.matchAll(/(?:await\s+)?(?:\w+\.)?(?:publishEvent|publish|emit)\s*\(\s*(?:new\s+)?(["']?)([A-Za-z][\w.]*Event?|[a-z][\w.]+)\1/gu)) {
230593
- const eventName = match[2];
230751
+ for (const match of file.content.matchAll(/(?:await\s+)?(?:\w+\.)?(?:publishEvent|publish|emit)\s*\(\s*(?:(new)\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\s*\(|(["'])([A-Za-z][\w.]*Event?|[a-z][\w.]+)\3|([A-Z][A-Za-z0-9_]*Event)\b)/gu)) {
230752
+ const constructedType = match[2]?.split(".").at(-1);
230753
+ const eventName = constructedType ?? match[4] ?? match[5];
230594
230754
  if (!eventName) {
230595
230755
  continue;
230596
230756
  }
@@ -234446,7 +234606,7 @@ ${infoLines.join("\n")}
234446
234606
  ## Passed Checks
234447
234607
  ${passedLines.join("\n")}
234448
234608
 
234449
- ## Module Dependency Summary
234609
+ ## Module / Component Contract Dependency Summary
234450
234610
  ${dependencyGraphLines.join("\n")}
234451
234611
 
234452
234612
  ## Disabled Rules
@@ -236682,7 +236842,7 @@ ${appliedFixesSection}
236682
236842
  ## Remaining Violations
236683
236843
  ${remainingViolationsLine}
236684
236844
 
236685
- ## Module Dependency Summary
236845
+ ## Module / Component Contract Dependency Summary
236686
236846
  ${moduleCatalog.length === 0 ? "- Module details are not available in this run." : moduleCatalog.map(
236687
236847
  (entry) => `- ${entry.moduleName} | Role: ${entry.role} | Path: ${entry.path ?? "(not configured)"} | Contract: ${entry.hasContract ? "yes" : "no"} | Declared deps: ${entry.declaredDependencyCount} | Actual deps: ${entry.actualDependencyCount} | Used by: ${entry.inboundDependencyCount}`
236688
236848
  ).join("\n")}
@@ -238934,11 +239094,11 @@ function normalizeAnnotationPath(workspaceRoot, sourceFile) {
238934
239094
  if (!path43.isAbsolute(sourceFile)) {
238935
239095
  return normalized;
238936
239096
  }
238937
- const relative17 = path43.relative(workspaceRoot, sourceFile).replace(/\\/g, "/");
238938
- if (relative17.startsWith("..") || path43.isAbsolute(relative17)) {
239097
+ const relative18 = path43.relative(workspaceRoot, sourceFile).replace(/\\/g, "/");
239098
+ if (relative18.startsWith("..") || path43.isAbsolute(relative18)) {
238939
239099
  return void 0;
238940
239100
  }
238941
- return relative17;
239101
+ return relative18;
238942
239102
  }
238943
239103
  function toAnnotatableFinding(workspaceRoot, finding) {
238944
239104
  if (typeof finding.id !== "string" || !finding.id.startsWith("AP-DEP-")) {
@@ -239122,7 +239282,7 @@ async function emitGithubInlineArchitectureAnnotations(workspaceRoot) {
239122
239282
  var reviewCommentMarker = "<!-- archpilot-pr-review -->";
239123
239283
  var legacyReviewCommentMarker = "<!-- ARCHPILOT_REVIEW_COMMENT -->";
239124
239284
  function requestGithubApi(options) {
239125
- return new Promise((resolve9, reject) => {
239285
+ return new Promise((resolve10, reject) => {
239126
239286
  const payload = options.body !== void 0 ? JSON.stringify(options.body) : void 0;
239127
239287
  const request3 = https2.request(
239128
239288
  {
@@ -239143,7 +239303,7 @@ function requestGithubApi(options) {
239143
239303
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
239144
239304
  });
239145
239305
  response.on("end", () => {
239146
- resolve9({
239306
+ resolve10({
239147
239307
  statusCode: response.statusCode ?? 0,
239148
239308
  body: Buffer.concat(chunks).toString("utf8")
239149
239309
  });
@@ -245420,6 +245580,9 @@ function addEvidence6(evidence, value) {
245420
245580
  evidence.push(value);
245421
245581
  }
245422
245582
  }
245583
+ function hasDeclaredMavenReactorEvidence(candidate) {
245584
+ return candidate.evidence.some((entry) => /Declared (?:by )?Maven|nested Maven reactor/iu.test(entry));
245585
+ }
245423
245586
  function isIgnoredComponentCandidatePath(componentPath) {
245424
245587
  const normalized = normalizePath25(componentPath).replace(/^\.\//u, "");
245425
245588
  if (normalized === "." || normalized.length === 0) {
@@ -245459,7 +245622,9 @@ function isIgnoredComponentCandidatePath(componentPath) {
245459
245622
  "build",
245460
245623
  "coverage"
245461
245624
  ];
245462
- return ignoredRootSegments.includes(firstSegment ?? "") || segments.some((segment) => ignoredSupportingSegments.includes(segment.toLowerCase()));
245625
+ const isExampleContainer = firstSegment === "examples" || firstSegment === "example";
245626
+ const isIgnoredRootSegment = ignoredRootSegments.includes(firstSegment ?? "") && (!isExampleContainer || segments.length === 1);
245627
+ return isIgnoredRootSegment || segments.some((segment) => ignoredSupportingSegments.includes(segment.toLowerCase()));
245463
245628
  }
245464
245629
  function pathExists19(pathValue) {
245465
245630
  try {
@@ -245502,6 +245667,14 @@ function hasObject(value) {
245502
245667
  function hasPackagePublishSurface(packageJson) {
245503
245668
  return hasObject(packageJson?.exports) || typeof packageJson?.main === "string" || typeof packageJson?.module === "string" || typeof packageJson?.types === "string" || hasObject(packageJson?.publishConfig) || Array.isArray(packageJson?.files);
245504
245669
  }
245670
+ function packageDependencyNames(packageJson) {
245671
+ return [
245672
+ ...recordKeys(packageJson?.dependencies),
245673
+ ...recordKeys(packageJson?.devDependencies),
245674
+ ...recordKeys(packageJson?.peerDependencies),
245675
+ ...recordKeys(packageJson?.optionalDependencies)
245676
+ ];
245677
+ }
245505
245678
  function absoluteComponentRoot(workspaceRoot, componentPath) {
245506
245679
  return componentPath === "." ? workspaceRoot : path64.join(workspaceRoot, ...componentPath.split("/"));
245507
245680
  }
@@ -245509,6 +245682,10 @@ function readPackageJson(workspaceRoot, componentPath) {
245509
245682
  const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
245510
245683
  return safeReadJson(path64.join(absoluteRoot, "package.json"));
245511
245684
  }
245685
+ function readProjectJson(workspaceRoot, componentPath) {
245686
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
245687
+ return safeReadJson(path64.join(absoluteRoot, "project.json"));
245688
+ }
245512
245689
  function readTextFileSafe(filePath) {
245513
245690
  try {
245514
245691
  return fs58.readFileSync(filePath, { encoding: "utf8" });
@@ -245523,6 +245700,9 @@ function readFirstXmlTag(value, tagName) {
245523
245700
  const match = value.match(new RegExp(`<${tagName}(?:\\s[^>]*)?>([\\s\\S]*?)</${tagName}>`, "iu"));
245524
245701
  return match?.[1]?.trim().replace(/\s+/gu, " ");
245525
245702
  }
245703
+ function readXmlTagValues(value, tagName) {
245704
+ return [...value.matchAll(new RegExp(`<${tagName}(?:\\s[^>]*)?>([\\s\\S]*?)</${tagName}>`, "giu"))].map((match) => match[1]?.trim().replace(/\s+/gu, " ") ?? "").filter((entry) => entry.length > 0);
245705
+ }
245526
245706
  function readMavenMetadata(workspaceRoot, componentPath) {
245527
245707
  if (isUnderJvmResourceRoot4(componentPath)) {
245528
245708
  return void 0;
@@ -245560,6 +245740,95 @@ function readMavenMetadata(workspaceRoot, componentPath) {
245560
245740
  hasTestResources: pathExists19(path64.join(absoluteRoot, "src", "test", "resources"))
245561
245741
  };
245562
245742
  }
245743
+ function workspaceRelativePath(workspaceRoot, absolutePathValue) {
245744
+ const relative18 = path64.relative(workspaceRoot, absolutePathValue);
245745
+ if (relative18.length === 0) {
245746
+ return ".";
245747
+ }
245748
+ if (relative18.startsWith("..") || path64.isAbsolute(relative18)) {
245749
+ return void 0;
245750
+ }
245751
+ return normalizePath25(relative18);
245752
+ }
245753
+ function canonicalRealPath(filePath) {
245754
+ try {
245755
+ return fs58.realpathSync.native(filePath);
245756
+ } catch {
245757
+ return void 0;
245758
+ }
245759
+ }
245760
+ function readMavenDeclaredModules(pomPath) {
245761
+ const pomXml = readTextFileSafe(pomPath);
245762
+ if (!pomXml) {
245763
+ return [];
245764
+ }
245765
+ return uniqueSorted4(
245766
+ readXmlTagValues(stripXmlComments(pomXml), "module").filter((modulePath) => !/[${}]/u.test(modulePath))
245767
+ );
245768
+ }
245769
+ function collectMavenReactorCandidates(workspaceRoot, rootPaths) {
245770
+ const candidates = /* @__PURE__ */ new Map();
245771
+ const visitedPomPaths = /* @__PURE__ */ new Set();
245772
+ const workspaceRealPath = canonicalRealPath(workspaceRoot) ?? path64.resolve(workspaceRoot);
245773
+ const workspaceRealPathForCompare = process.platform === "win32" ? workspaceRealPath.toLowerCase() : workspaceRealPath;
245774
+ const maxVisitedPoms = 500;
245775
+ const addCandidate = (candidatePath, evidence, parentPath) => {
245776
+ const normalized = normalizePath25(candidatePath);
245777
+ const existing = candidates.get(normalized) ?? { path: normalized, evidence: [] };
245778
+ addEvidence6(existing.evidence, evidence);
245779
+ if (parentPath && !existing.parentPath) {
245780
+ existing.parentPath = parentPath;
245781
+ }
245782
+ candidates.set(normalized, existing);
245783
+ };
245784
+ const visitPom = (pomPath, parentPath) => {
245785
+ if (visitedPomPaths.size >= maxVisitedPoms) {
245786
+ return;
245787
+ }
245788
+ const realPomPath = canonicalRealPath(pomPath);
245789
+ if (!realPomPath || visitedPomPaths.has(realPomPath)) {
245790
+ return;
245791
+ }
245792
+ const realPomPathForCompare = process.platform === "win32" ? realPomPath.toLowerCase() : realPomPath;
245793
+ if (realPomPathForCompare !== workspaceRealPathForCompare && !realPomPathForCompare.startsWith(`${workspaceRealPathForCompare}${path64.sep}`)) {
245794
+ return;
245795
+ }
245796
+ visitedPomPaths.add(realPomPath);
245797
+ const pomDirectory = path64.dirname(pomPath);
245798
+ const relativePomDirectory = workspaceRelativePath(workspaceRoot, pomDirectory);
245799
+ if (!relativePomDirectory) {
245800
+ return;
245801
+ }
245802
+ addCandidate(
245803
+ relativePomDirectory,
245804
+ parentPath ? `Declared by Maven reactor parent ${parentPath}` : "Detected Maven reactor root",
245805
+ parentPath
245806
+ );
245807
+ for (const declaredModule of readMavenDeclaredModules(pomPath)) {
245808
+ const childDirectory = path64.resolve(pomDirectory, declaredModule);
245809
+ const childRelativePath = workspaceRelativePath(workspaceRoot, childDirectory);
245810
+ if (!childRelativePath || isUnderJvmResourceRoot4(childRelativePath)) {
245811
+ continue;
245812
+ }
245813
+ const childPom = path64.join(childDirectory, "pom.xml");
245814
+ if (!pathExists19(childPom)) {
245815
+ addCandidate(childRelativePath, `Declared Maven module '${declaredModule}' is missing pom.xml`, relativePomDirectory);
245816
+ continue;
245817
+ }
245818
+ addCandidate(childRelativePath, `Declared Maven module '${declaredModule}' from ${relativePomDirectory}`, relativePomDirectory);
245819
+ visitPom(childPom, relativePomDirectory);
245820
+ }
245821
+ };
245822
+ for (const rootPath of uniqueSorted4(rootPaths)) {
245823
+ const normalizedRoot = normalizePath25(rootPath);
245824
+ const absoluteRoot = normalizedRoot === "." ? workspaceRoot : path64.join(workspaceRoot, ...normalizedRoot.split("/"));
245825
+ const pomPath = path64.join(absoluteRoot, "pom.xml");
245826
+ if (pathExists19(pomPath)) {
245827
+ visitPom(pomPath);
245828
+ }
245829
+ }
245830
+ return [...candidates.values()].sort((left, right) => left.path.localeCompare(right.path));
245831
+ }
245563
245832
  function toComponentRoot(modulePath) {
245564
245833
  const normalized = normalizePath25(modulePath);
245565
245834
  const segments = normalized.split("/").filter((segment) => segment.length > 0);
@@ -245594,6 +245863,18 @@ function buildRootCandidates(input2) {
245594
245863
  for (const root of input2.topology.detectedRoots ?? []) {
245595
245864
  addCandidate(root, `Detected project root ${root}`);
245596
245865
  }
245866
+ if (input2.workspaceRoot) {
245867
+ const mavenRoots = [".", ...input2.topology.detectedRoots ?? []];
245868
+ for (const candidate of collectMavenReactorCandidates(input2.workspaceRoot, mavenRoots)) {
245869
+ addCandidate(
245870
+ candidate.path,
245871
+ candidate.parentPath ? `Detected nested Maven reactor module under ${candidate.parentPath}` : "Detected Maven reactor module"
245872
+ );
245873
+ for (const evidence of candidate.evidence) {
245874
+ addCandidate(candidate.path, evidence);
245875
+ }
245876
+ }
245877
+ }
245597
245878
  for (const moduleEntry of input2.modules?.modules ?? []) {
245598
245879
  const componentRoot = toComponentRoot(moduleEntry.path);
245599
245880
  if (componentRoot) {
@@ -245972,11 +246253,57 @@ function hasRuntimeSourceFiles(workspaceRoot, componentPath) {
245972
246253
  }
245973
246254
  return false;
245974
246255
  }
246256
+ function hasFileMatchingUnderRoot(root, pattern) {
246257
+ if (!pathExists19(root)) {
246258
+ return false;
246259
+ }
246260
+ const entries = fs58.readdirSync(root, { recursive: true, withFileTypes: true });
246261
+ return entries.some((entry) => entry.isFile() && pattern.test(normalizePath25(path64.join(entry.parentPath, entry.name))));
246262
+ }
246263
+ function hasNestRuntimeApplicationEvidence(workspaceRoot, componentPath, packageJson = readPackageJson(workspaceRoot, componentPath)) {
246264
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
246265
+ const dependencies = new Set(packageDependencyNames(packageJson));
246266
+ const scripts = recordKeys(packageJson?.scripts);
246267
+ const hasNestCore = dependencies.has("@nestjs/core");
246268
+ if (!hasNestCore) {
246269
+ return false;
246270
+ }
246271
+ const hasRuntimePlatform = dependencies.has("@nestjs/platform-express") || dependencies.has("@nestjs/platform-fastify") || dependencies.has("@nestjs/microservices") || dependencies.has("@nestjs/graphql") || dependencies.has("@nestjs/apollo");
246272
+ const hasRunnableScript = scripts.some((script) => /^(?:start|serve|dev|worker)(?::|$)/u.test(script));
246273
+ const hasNestCliConfig = ["nest-cli.json", "nest.config.js", "nest.config.ts"].some(
246274
+ (fileName) => pathExists19(path64.join(absoluteRoot, fileName))
246275
+ );
246276
+ const hasBootstrapEntrypoint = [
246277
+ path64.join(absoluteRoot, "src", "main.ts"),
246278
+ path64.join(absoluteRoot, "src", "main.js"),
246279
+ path64.join(absoluteRoot, "main.ts"),
246280
+ path64.join(absoluteRoot, "main.js")
246281
+ ].some((filePath) => {
246282
+ const contents = readTextFileSafe(filePath);
246283
+ return Boolean(contents && /\bNestFactory\.create(?:ApplicationContext)?\s*\(/u.test(contents));
246284
+ });
246285
+ const srcRoot = path64.join(absoluteRoot, "src");
246286
+ const hasRuntimeSourceShape = hasFileMatchingUnderRoot(srcRoot, /\.(?:controller|resolver|gateway|processor|module|worker|queue)\.(?:ts|js)$/iu) || hasFileMatchingUnderRoot(srcRoot, /[/\\](?:controllers?|resolvers?|queues?|workers?)[/\\][^/\\]+\.(?:ts|js)$/iu);
246287
+ const hasDatabaseRuntimeIntegration = [...dependencies].some(
246288
+ (dependency) => /^(?:typeorm|@nestjs\/typeorm|@prisma\/client|prisma|mongoose|@nestjs\/mongoose|sequelize|@mikro-orm\/core)$/u.test(dependency)
246289
+ );
246290
+ const structuralEvidenceCount = [
246291
+ hasRuntimePlatform,
246292
+ hasRunnableScript,
246293
+ hasNestCliConfig,
246294
+ hasBootstrapEntrypoint,
246295
+ hasRuntimeSourceShape,
246296
+ hasDatabaseRuntimeIntegration
246297
+ ].filter(Boolean).length;
246298
+ return hasBootstrapEntrypoint || hasRuntimePlatform && structuralEvidenceCount >= 2 || hasRunnableScript && hasRuntimeSourceShape && structuralEvidenceCount >= 3;
246299
+ }
245975
246300
  function resolveKind(workspaceRoot, candidate, localProjectKinds) {
245976
246301
  const lowerPath = candidate.path.toLowerCase();
245977
246302
  const packageJson = readPackageJson(workspaceRoot, candidate.path);
245978
246303
  const maven = readMavenMetadata(workspaceRoot, candidate.path);
246304
+ const dependencies = new Set(packageDependencyNames(packageJson));
245979
246305
  const hasRunnableFrontendEvidence = hasRunnableFrontendComponentEvidence(workspaceRoot, candidate.path);
246306
+ const hasNestRuntimeEvidence = hasNestRuntimeApplicationEvidence(workspaceRoot, candidate.path, packageJson);
245980
246307
  const hasPublishSurface = hasPackagePublishSurface(packageJson);
245981
246308
  const hasMavenRunnableEvidence = Boolean(
245982
246309
  maven && (hasMavenMainEntrypoint(workspaceRoot, candidate.path) || hasMavenConfiguredMainClassEntrypoint(workspaceRoot, candidate.path, maven.configuredMainClass) || maven.hasSpringBootPlugin && maven.hasSpringBootRepackageGoal && hasMavenMainEntrypoint(workspaceRoot, candidate.path) || maven.packaging === "war" && hasMavenMainEntrypoint(workspaceRoot, candidate.path))
@@ -245998,6 +246325,12 @@ function resolveKind(workspaceRoot, candidate, localProjectKinds) {
245998
246325
  return hasPublishSurface && !hasRunnableFrontendEvidence ? "library" : "frontend";
245999
246326
  }
246000
246327
  if (classification === "backend_app") {
246328
+ if (hasPublishSurface && dependencies.has("@nestjs/core") && !hasNestRuntimeEvidence) {
246329
+ return "library";
246330
+ }
246331
+ return "backend";
246332
+ }
246333
+ if (hasNestRuntimeEvidence) {
246001
246334
  return "backend";
246002
246335
  }
246003
246336
  if (hasRunnableFrontendEvidence && localProjectKinds.primaryKind !== "backend" && localProjectKinds.primaryKind !== "service" && localProjectKinds.primaryKind !== "cli") {
@@ -246061,6 +246394,7 @@ function hasAnyToken(value, patterns) {
246061
246394
  }
246062
246395
  function classifyGovernanceRole(input2) {
246063
246396
  const packageJson = readPackageJson(input2.workspaceRoot, input2.candidate.path);
246397
+ const projectJson = readProjectJson(input2.workspaceRoot, input2.candidate.path);
246064
246398
  const maven = readMavenMetadata(input2.workspaceRoot, input2.candidate.path);
246065
246399
  const evidence = [];
246066
246400
  let supportScore = 0;
@@ -246074,11 +246408,15 @@ function classifyGovernanceRole(input2) {
246074
246408
  const scripts = recordKeys(packageJson?.scripts);
246075
246409
  const dependencies = recordKeys(packageJson?.dependencies);
246076
246410
  const devDependencies = recordKeys(packageJson?.devDependencies);
246411
+ const projectTags = toStringArray(projectJson?.tags);
246412
+ const projectTargets = recordKeys(projectJson?.targets);
246077
246413
  const scriptText = scripts.join(" ").toLowerCase();
246414
+ const projectMetadataText = `${projectTags.join(" ")} ${projectTargets.join(" ")}`.toLowerCase();
246078
246415
  const dependencyText = [...dependencies, ...devDependencies].join(" ").toLowerCase();
246416
+ const hasNestRuntimeEvidence = hasNestRuntimeApplicationEvidence(input2.workspaceRoot, input2.candidate.path, packageJson);
246079
246417
  const hasStrongSupportPath = hasAnyToken(pathText, [
246080
- /(^|\/)(testing|test-plugins|cypress-tests|fixtures?|examples?|benchmarks?|smoke)(\/|$)/u,
246081
- /(^|\/)(dev-server|scaffold|scaffolding|generators?|devkit|tooling|tools)(\/|$)/u
246418
+ /(^|\/)(testing|e2e-testing|test-plugins|cypress-tests|fixtures?|benchmarks?|smoke)(\/|$)/u,
246419
+ /(^|\/)(dev-server|scaffold|scaffolding|generators?|devkit|tooling|tools|templates?)(\/|$)/u
246082
246420
  ]);
246083
246421
  const isPlainResourcesSurface = isUnderJvmResourceRoot4(pathText) && !hasRuntimeSourceFiles(input2.workspaceRoot, input2.candidate.path) && !packageJson && !maven;
246084
246422
  const hasPublishSurface = hasPackagePublishSurface(packageJson);
@@ -246102,6 +246440,9 @@ function classifyGovernanceRole(input2) {
246102
246440
  const hasMavenDistributionPackagingEvidence = Boolean(
246103
246441
  maven?.packaging === "pom" && !hasMavenMainSource && hasAnyToken(pathText, [/(^|\/)(distribution|dist|downloads|assembl(y|ies)|feature-packs?)(\/|$)/u])
246104
246442
  );
246443
+ const hasMavenStarterPackagingEvidence = Boolean(
246444
+ maven && !hasMavenMainJvmSourceEvidence && hasAnyToken(`${pathText} ${mavenMetadataText}`, [/\bstarters?\b|\bspring-boot-starter\b|\bstarter[-\s]/u])
246445
+ );
246105
246446
  if (input2.candidate.architectureRoot?.classification === "backend_app" || input2.candidate.architectureRoot?.classification === "frontend_app") {
246106
246447
  runtimeScore += 3;
246107
246448
  addEvidence6(evidence, `Runtime architecture root signal: ${input2.candidate.architectureRoot.classification}`);
@@ -246120,6 +246461,10 @@ function classifyGovernanceRole(input2) {
246120
246461
  runtimeScore += 1;
246121
246462
  addEvidence6(evidence, `Runtime framework stack signal: ${input2.stack}`);
246122
246463
  }
246464
+ if (hasNestRuntimeEvidence) {
246465
+ runtimeScore += 3;
246466
+ addEvidence6(evidence, "NestJS runtime application evidence");
246467
+ }
246123
246468
  if (hasPublishSurface && !isPrivate) {
246124
246469
  runtimeScore += 1;
246125
246470
  addEvidence6(evidence, "Published package surface signal");
@@ -246144,25 +246489,37 @@ function classifyGovernanceRole(input2) {
246144
246489
  if (hasMavenAutoConfigurationEvidence && !hasMavenRunnableApplicationEvidence) {
246145
246490
  addEvidence6(evidence, "Maven Spring Boot auto-configuration/starter library evidence");
246146
246491
  }
246147
- if (hasAnyToken(descriptiveManifestText, [/\b(e2e|end-to-end|testing|test helper|test utilities|fixtures?)\b/u])) {
246492
+ if (hasAnyToken(descriptiveManifestText, [/\b(e2e|end-to-end|testing|test helper|test utilities|fixtures?|test harness)\b/u])) {
246148
246493
  supportScore += 3;
246149
246494
  addEvidence6(evidence, "Package metadata describes test/support usage");
246150
246495
  }
246496
+ if (hasAnyToken(`${packageName.toLowerCase()} ${projectMetadataText}`, [/\b(e2e|end-to-end|testing|test harness|scope:testing|test:ui|test:debug|test:report)\b/u]) && hasAnyToken(dependencyText, [/\b(?:playwright|@playwright\/test|cypress|vitest|jest|mocha)\b/u])) {
246497
+ supportScore += 4;
246498
+ addEvidence6(evidence, "Project metadata and dependencies indicate test-only workspace");
246499
+ }
246151
246500
  if (hasAnyToken(descriptiveManifestText, [/\b(scaffold|scaffolding|generator|codegen|template|starter|create)\b/u])) {
246152
246501
  supportScore += 3;
246153
246502
  addEvidence6(evidence, "Package metadata describes scaffolding/generation usage");
246154
246503
  }
246155
- if (hasAnyToken(descriptiveManifestText, [/\b(dev server|development server|development tooling|tooling|devkit)\b/u])) {
246504
+ if (hasAnyToken(descriptiveManifestText, [/\b(dev server|development server|development tooling|tooling|devkit|lint rules?|linter|build tooling|repository tooling)\b/u])) {
246156
246505
  supportScore += 2;
246157
246506
  addEvidence6(evidence, "Package metadata describes development/tooling usage");
246158
246507
  }
246159
246508
  if (hasAnyToken(pathText, [
246160
- /(^|\/)(test|tests|testing|__tests__|cypress|cypress-tests|fixtures?|examples?|benchmarks?|smoke)(\/|$)/u,
246161
- /(^|\/)(dev-server|test-plugins|scaffold|scaffolding|generators?|devkit|tooling|tools)(\/|$)/u
246509
+ /(^|\/)(test|tests|testing|e2e-testing|__tests__|cypress|cypress-tests|fixtures?|benchmarks?|smoke)(\/|$)/u,
246510
+ /(^|\/)(dev-server|test-plugins|scaffold|scaffolding|generators?|devkit|tooling|tools|templates?)(\/|$)/u
246162
246511
  ])) {
246163
246512
  supportScore += 1;
246164
246513
  addEvidence6(evidence, "Path contains support/tooling role tokens");
246165
246514
  }
246515
+ if (hasAnyToken(pathText, [/(^|\/)(?:src\/constants\/)?templates?(\/|$)/u])) {
246516
+ supportScore += 4;
246517
+ addEvidence6(evidence, "Nested scaffold/template source surface");
246518
+ }
246519
+ if (hasAnyToken(dependencyText, [/\b(?:eslint|oxlint|prettier|typescript-eslint|ts-morph|jscodeshift|schematics|yeoman)\b/u])) {
246520
+ supportScore += 2;
246521
+ addEvidence6(evidence, "Package dependencies indicate lint/build/generation tooling");
246522
+ }
246166
246523
  if (scripts.length > 0 && scripts.every((script) => /^(test|e2e|smoke|bench|benchmark|lint|typecheck|dev|dev:|load-test|generate|scaffold)/u.test(script))) {
246167
246524
  supportScore += 1;
246168
246525
  addEvidence6(evidence, "Package scripts are dominated by development/test workflows");
@@ -246211,6 +246568,10 @@ function classifyGovernanceRole(input2) {
246211
246568
  supportScore += 1;
246212
246569
  addEvidence6(evidence, "Maven POM-only aggregator/packaging module");
246213
246570
  }
246571
+ if (hasMavenStarterPackagingEvidence) {
246572
+ supportScore += 4;
246573
+ addEvidence6(evidence, "Maven starter/resource artifact without JVM runtime source");
246574
+ }
246214
246575
  if (isPlainResourcesSurface) {
246215
246576
  supportScore += 4;
246216
246577
  addEvidence6(evidence, "Resources-only surface without runtime source or manifest evidence");
@@ -246222,6 +246583,13 @@ function classifyGovernanceRole(input2) {
246222
246583
  selectedByDefault: false
246223
246584
  };
246224
246585
  }
246586
+ if (hasMavenStarterPackagingEvidence && !hasMavenMainJvmSourceEvidence) {
246587
+ return {
246588
+ governanceRole: "support",
246589
+ governanceEvidence: uniqueSorted4(evidence),
246590
+ selectedByDefault: false
246591
+ };
246592
+ }
246225
246593
  if (hasMavenDistributionPackagingEvidence && hasAnyToken(mavenMetadataText, [/\b(docs?|documentation|metadata tests?|licenses?|maven plugins?|builds?)\b/u])) {
246226
246594
  supportScore += 3;
246227
246595
  addEvidence6(evidence, "Maven documentation/build/distribution packaging evidence without runtime source");
@@ -246281,7 +246649,7 @@ function detectComponents(input2) {
246281
246649
  const manifestBackedRoots = new Set(
246282
246650
  (input2.topology.detectedRoots ?? []).filter((root) => !isUnderJvmResourceRoot4(root))
246283
246651
  );
246284
- const rootCandidates = buildRootCandidates(input2).filter((candidate) => !ignoreMatcher.isIgnored(candidate.path)).filter((candidate) => !isIgnoredComponentCandidatePath(candidate.path)).filter((candidate) => !(isUnderJvmResourceRoot4(candidate.path) && !hasRuntimeSourceFiles(input2.workspaceRoot, candidate.path))).filter((candidate) => {
246652
+ const rootCandidates = buildRootCandidates({ ...input2, workspaceRoot: input2.workspaceRoot }).filter((candidate) => !ignoreMatcher.isIgnored(candidate.path) || hasDeclaredMavenReactorEvidence(candidate)).filter((candidate) => !isIgnoredComponentCandidatePath(candidate.path)).filter((candidate) => !(isUnderJvmResourceRoot4(candidate.path) && !hasRuntimeSourceFiles(input2.workspaceRoot, candidate.path))).filter((candidate) => {
246285
246653
  if (input2.topology.topology !== "monorepo" || manifestBackedRoots.size === 0) {
246286
246654
  return true;
246287
246655
  }
@@ -246579,7 +246947,7 @@ function isCliSupportCandidate(component, allComponents) {
246579
246947
  }
246580
246948
  function hasIndependentRuntimeEvidence(component) {
246581
246949
  const text = componentEvidenceText(component);
246582
- return component.governanceRole === "runtime" && (/Maven executable application evidence/iu.test(text) || /Maven deployable WAR artifact/iu.test(text) || /Published package surface signal/iu.test(text) && !/Path contains support\/tooling role tokens/iu.test(text));
246950
+ return component.governanceRole === "runtime" && (/Maven executable application evidence/iu.test(text) || /Maven deployable WAR artifact/iu.test(text) || /Maven library main source\/resource surface/iu.test(text) || /Maven Spring Boot auto-configuration\/starter library evidence/iu.test(text) || /Published package surface signal/iu.test(text) && !/Path contains support\/tooling role tokens/iu.test(text));
246583
246951
  }
246584
246952
  function hasSupportRoleEvidence(component) {
246585
246953
  const text = componentEvidenceText(component);
@@ -246789,7 +247157,20 @@ function hasAttributableBackendRoot(detection) {
246789
247157
  return getBackendComponents(detection).length > 0;
246790
247158
  }
246791
247159
  function isGenericLibraryStack(stack) {
246792
- return stack === "node_typescript" || stack === "node_javascript" || stack === "python" || stack === "go" || stack === "kotlin" || stack === "terraform" || stack === "ansible";
247160
+ return stack === "node_typescript" || stack === "node_javascript" || stack === "library_generic" || stack === "java" || stack === "spring" || stack === "python" || stack === "go" || stack === "kotlin" || stack === "kotlin_spring" || stack === "terraform" || stack === "ansible";
247161
+ }
247162
+ function preferredLibraryStack(stacks) {
247163
+ const uniqueStacks = uniqueInOrder2(stacks);
247164
+ if (uniqueStacks.length <= 1) {
247165
+ return isJvmLibraryStack(uniqueStacks[0]) ? "library_generic" : uniqueStacks[0];
247166
+ }
247167
+ if (uniqueStacks.some(isJvmLibraryStack) && uniqueStacks.every((candidate) => isJvmLibraryStack(candidate) || candidate === "node_typescript" || candidate === "node_javascript")) {
247168
+ return "library_generic";
247169
+ }
247170
+ return void 0;
247171
+ }
247172
+ function isJvmLibraryStack(stack) {
247173
+ return stack === "java" || stack === "spring";
246793
247174
  }
246794
247175
  function hasProjectKindEvidence(detection, patterns) {
246795
247176
  const evidence = detection.projectKinds?.evidence ?? [];
@@ -247211,7 +247592,7 @@ function resolveStackSelections(detection, projectKinds) {
247211
247592
  const libraryComponentStacks = uniqueInOrder2(
247212
247593
  libraryComponents.map((component) => component.stack).filter((stack) => isGenericLibraryStack(stack))
247213
247594
  );
247214
- const selectedLibrary = detection.topology.topology === "monorepo" ? libraryComponentStacks.length === 1 ? libraryComponentStacks[0] : void 0 : detection.stacks.selectedAdapterId;
247595
+ const selectedLibrary = detection.topology.topology === "monorepo" ? preferredLibraryStack(libraryComponentStacks) : detection.stacks.selectedAdapterId;
247215
247596
  if (isGenericLibraryStack(selectedLibrary)) {
247216
247597
  selections.library = selectedLibrary;
247217
247598
  }
@@ -247233,7 +247614,7 @@ function resolveProjectProfiles(detection, projectKinds, stackSelections, apiSty
247233
247614
  selectedAdapterId: stackId,
247234
247615
  selectedAdapterCategory: getStackAdapterById(stackId).category,
247235
247616
  projectKinds: [kind],
247236
- apiStyleHint: kind === "backend" && apiStyle ? apiStyle : resolveRoleApiStyleHint(detection, stackId, component),
247617
+ apiStyleHint: kind === "backend" && apiStyle ? apiStyle : stackId === "library_generic" ? void 0 : resolveRoleApiStyleHint(detection, stackId, component),
247237
247618
  databaseHints: detection.toolingHints?.databaseHints,
247238
247619
  toolingHints: detection.toolingHints?.toolingHints,
247239
247620
  repoTopology: detection.topology.topology === "unknown" ? "single_project" : detection.topology.topology
@@ -249874,6 +250255,9 @@ function readFlagValue(args, flag) {
249874
250255
  return value && value.length > 0 ? value : void 0;
249875
250256
  }
249876
250257
  async function readCliPackageVersion() {
250258
+ if ("0.2.5".trim().length > 0) {
250259
+ return "0.2.5".trim();
250260
+ }
249877
250261
  const candidatePackageJsonPaths = [
249878
250262
  path73.join(__dirname, "..", "package.json"),
249879
250263
  path73.join(__dirname, "..", "..", "..", "..", "cli", "package.json")