@archpilotlabs/archpilot 0.2.1 → 0.2.2

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 (2) hide show
  1. package/dist/archpilot-cli.js +521 -237
  2. package/package.json +1 -1
@@ -140818,9 +140818,9 @@ ${lanes.join("\n")}
140818
140818
  /*ignoreCase*/
140819
140819
  false
140820
140820
  )) {
140821
- const basename8 = getBaseFileName(a.fileName);
140822
- if (basename8 === "lib.d.ts" || basename8 === "lib.es6.d.ts") return 0;
140823
- const name = removeSuffix(removePrefix(basename8, "lib."), ".d.ts");
140821
+ const basename9 = getBaseFileName(a.fileName);
140822
+ if (basename9 === "lib.d.ts" || basename9 === "lib.es6.d.ts") return 0;
140823
+ const name = removeSuffix(removePrefix(basename9, "lib."), ".d.ts");
140824
140824
  const index = libs.indexOf(name);
140825
140825
  if (index !== -1) return index + 1;
140826
140826
  }
@@ -204566,8 +204566,8 @@ ${options.prefix}` : "\n" : options.prefix
204566
204566
  }
204567
204567
  };
204568
204568
  for (const file of files) {
204569
- const basename8 = getBaseFileName(file);
204570
- if (basename8 === "package.json" || basename8 === "bower.json") {
204569
+ const basename9 = getBaseFileName(file);
204570
+ if (basename9 === "package.json" || basename9 === "bower.json") {
204571
204571
  createProjectWatcher(
204572
204572
  file,
204573
204573
  "FileWatcher"
@@ -208239,8 +208239,8 @@ All files are: ${JSON.stringify(names)}`,
208239
208239
  var _a;
208240
208240
  const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
208241
208241
  if (!fileOrDirectoryPath) return;
208242
- const basename8 = getBaseFileName(fileOrDirectoryPath);
208243
- if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (basename8 === "package.json" || basename8 === "node_modules")) {
208242
+ const basename9 = getBaseFileName(fileOrDirectoryPath);
208243
+ if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (basename9 === "package.json" || basename9 === "node_modules")) {
208244
208244
  result.affectedModuleSpecifierCacheProjects.forEach((project) => {
208245
208245
  var _a2;
208246
208246
  (_a2 = project.getModuleSpecifierCache()) == null ? void 0 : _a2.clear();
@@ -215396,15 +215396,83 @@ var init_architectureDependencyContext = __esm({
215396
215396
  }
215397
215397
  });
215398
215398
 
215399
+ // ../core/src/sourceScopeClassification.ts
215400
+ function normalizePath3(value) {
215401
+ return value.replace(/\\/g, "/").toLowerCase();
215402
+ }
215403
+ function hasPathSegment(pathValue, pattern) {
215404
+ return pathValue.split("/").some((segment) => pattern.test(segment));
215405
+ }
215406
+ function hasTopLevelPathSegment(pathValue, pattern) {
215407
+ const [firstSegment] = pathValue.split("/");
215408
+ return !!firstSegment && pattern.test(firstSegment);
215409
+ }
215410
+ function classifyValidationSourceScope(relativePath) {
215411
+ const normalized = normalizePath3(relativePath);
215412
+ const fileName = normalized.split("/").at(-1) ?? normalized;
215413
+ const extension = fileName.includes(".") ? fileName.slice(fileName.lastIndexOf(".")) : "";
215414
+ const isTestFile = /\.(?:spec|test|e2e-spec|integration-test)\.(?:ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(fileName);
215415
+ const isE2e = isTestFile && /(?:^|[./_-])e2e(?:[./_-]|$)/u.test(fileName) || hasPathSegment(normalized, /^e2e$/u);
215416
+ const isFixture = hasPathSegment(normalized, /^(?:fixtures?|__fixtures__)$/u);
215417
+ const isTestPlugin = hasPathSegment(normalized, /^(?:test-plugins?|testing-plugins?)$/u);
215418
+ const isExamplePlugin = hasPathSegment(normalized, /^example-plugins?$/u) || hasTopLevelPathSegment(normalized, /^examples?$/u);
215419
+ 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);
215420
+ const isMigration = hasPathSegment(normalized, /^(?:migrations?|schema-migrations?|data-migrations|migration-utils?)$/u);
215421
+ const isCliTooling = hasPathSegment(normalized, /^(?:cli|bin|scripts?|tools?|scaffold|scaffolding|generators?)$/u) || /(?:^|[./_-])(?:cli|script|tool|generator|scaffold)(?:[./_-]|$)/u.test(fileName);
215422
+ const isFrontend = extension === ".tsx" || extension === ".jsx" || hasPathSegment(normalized, /^(?:frontend|client|browser|ui|admin-ui|dashboard|web-app)$/u) || /\b(?:react|angular|vue|svelte)\b/u.test(normalized);
215423
+ const isInfrastructure = hasPathSegment(normalized, /^(?:infrastructure|infra|framework|adapters?|persistence|providers?)$/u) || /(?:transactional-connection|transaction-wrapper|transaction-subscriber|transaction-manager|query-runner|query-builder|event-bus|telemetry|interceptor)\.(?:ts|js|java|cs|py|php|go)$/u.test(fileName);
215424
+ let category = "production-backend";
215425
+ if (isGenerated) {
215426
+ category = "generated";
215427
+ } else if (isE2e) {
215428
+ category = "e2e";
215429
+ } else if (isTestFile || hasPathSegment(normalized, /^(?:test|tests|__tests__|spec|specs|__mocks__|cypress|cypress-tests)$/u)) {
215430
+ category = "test";
215431
+ } else if (isTestPlugin) {
215432
+ category = "test-plugin";
215433
+ } else if (isExamplePlugin) {
215434
+ category = "example-plugin";
215435
+ } else if (isFixture) {
215436
+ category = "fixture";
215437
+ } else if (isMigration) {
215438
+ category = "migration";
215439
+ } else if (isCliTooling) {
215440
+ category = "cli-tooling";
215441
+ } else if (isFrontend) {
215442
+ category = "production-frontend";
215443
+ } else if (isInfrastructure) {
215444
+ category = "infrastructure";
215445
+ }
215446
+ const isTestLike = category === "test" || category === "e2e" || category === "fixture" || category === "test-plugin" || category === "example-plugin";
215447
+ return {
215448
+ category,
215449
+ isProduction: category === "production-backend" || category === "production-frontend" || category === "infrastructure",
215450
+ isFrontend: category === "production-frontend",
215451
+ isTestLike,
215452
+ isGenerated: category === "generated",
215453
+ isMigration: category === "migration",
215454
+ isCliTooling: category === "cli-tooling",
215455
+ isInfrastructure: category === "infrastructure"
215456
+ };
215457
+ }
215458
+ function isProductionBackendGovernanceScope(scope) {
215459
+ return scope.category === "production-backend";
215460
+ }
215461
+ var init_sourceScopeClassification = __esm({
215462
+ "../core/src/sourceScopeClassification.ts"() {
215463
+ "use strict";
215464
+ }
215465
+ });
215466
+
215399
215467
  // ../core/src/dependencyValidation.ts
215400
- function normalizePath3(filePath) {
215468
+ function normalizePath4(filePath) {
215401
215469
  return filePath.replace(/\\/g, "/");
215402
215470
  }
215403
215471
  function toSafeContractModuleFileStem(moduleName) {
215404
- return normalizePath3(moduleName).split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0).join(".");
215472
+ return normalizePath4(moduleName).split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0).join(".");
215405
215473
  }
215406
215474
  function normalizeAbsolutePath(filePath) {
215407
- return normalizePath3(path7.resolve(filePath)).toLowerCase();
215475
+ return normalizePath4(path7.resolve(filePath)).toLowerCase();
215408
215476
  }
215409
215477
  function isPathInsideOrEqual2(childPath, parentPath) {
215410
215478
  const child = normalizeAbsolutePath(childPath);
@@ -215442,7 +215510,7 @@ function getComponentModuleRoots(workspaceRoot, architectureContract) {
215442
215510
  }
215443
215511
  const typed = value;
215444
215512
  const componentId = typeof typed.id === "string" && typed.id.trim().length > 0 ? typed.id.trim() : typeof key === "string" && key.trim().length > 0 ? key.trim() : void 0;
215445
- const componentPath = typeof typed.path === "string" && typed.path.trim().length > 0 ? normalizePath3(typed.path.trim()) : void 0;
215513
+ const componentPath = typeof typed.path === "string" && typed.path.trim().length > 0 ? normalizePath4(typed.path.trim()) : void 0;
215446
215514
  if (!componentId || !componentPath || componentPath === ".") {
215447
215515
  continue;
215448
215516
  }
@@ -215642,7 +215710,7 @@ async function buildTsConfigPathAliasMap(workspaceRoot, moduleRoots) {
215642
215710
  continue;
215643
215711
  }
215644
215712
  const isWildcard = /\/\*$/u.test(aliasPattern) && /\/\*$/u.test(targetPattern);
215645
- const normalizedTarget = normalizePath3(targetPattern).replace(/\/\*$/u, "");
215713
+ const normalizedTarget = normalizePath4(targetPattern).replace(/\/\*$/u, "");
215646
215714
  const absoluteTarget = path7.join(workspaceRoot, ...normalizedTarget.split("/"));
215647
215715
  const moduleEntry = [...moduleRoots.entries()].filter(([, moduleRoot2]) => isPathInsideOrEqual2(absoluteTarget, moduleRoot2)).sort((left, right) => right[1].length - left[1].length || left[0].localeCompare(right[0]))[0];
215648
215716
  if (!moduleEntry) {
@@ -215745,7 +215813,7 @@ async function findModuleRoots(workspaceRoot, modulesRootRelativePath = "src/mod
215745
215813
  if (!configuredPath || typeof configuredPath !== "string") {
215746
215814
  continue;
215747
215815
  }
215748
- const normalizedConfiguredPath = normalizePath3(configuredPath);
215816
+ const normalizedConfiguredPath = normalizePath4(configuredPath);
215749
215817
  if (/\.[a-z0-9]+$/iu.test(normalizedConfiguredPath)) {
215750
215818
  continue;
215751
215819
  }
@@ -215853,7 +215921,7 @@ async function buildExplicitStandaloneModulePathMap(workspaceRoot, architectureC
215853
215921
  if (!configuredPath || typeof configuredPath !== "string") {
215854
215922
  continue;
215855
215923
  }
215856
- const normalizedConfiguredPath = normalizePath3(configuredPath);
215924
+ const normalizedConfiguredPath = normalizePath4(configuredPath);
215857
215925
  if (!/\.[a-z0-9]+$/iu.test(normalizedConfiguredPath)) {
215858
215926
  continue;
215859
215927
  }
@@ -215869,11 +215937,7 @@ async function buildExplicitStandaloneModulePathMap(workspaceRoot, architectureC
215869
215937
  return map;
215870
215938
  }
215871
215939
  function isTestSourcePath(relativePath) {
215872
- const normalized = normalizePath3(relativePath).toLowerCase();
215873
- if (normalized.includes("/__tests__/") || normalized.includes("/test/") || normalized.includes("/tests/") || normalized.includes("/__mocks__/")) {
215874
- return true;
215875
- }
215876
- return /(^|\/)[^/]+\.(test|spec)\.[cm]?[jt]sx?$/u.test(normalized);
215940
+ return classifyValidationSourceScope(relativePath).isTestLike;
215877
215941
  }
215878
215942
  async function collectSourceFiles(directoryPath, adapter, scanRootPath = directoryPath, excludedDirectoryRoots = []) {
215879
215943
  const entries = await import_node_fs6.promises.readdir(directoryPath, { withFileTypes: true });
@@ -215887,7 +215951,7 @@ async function collectSourceFiles(directoryPath, adapter, scanRootPath = directo
215887
215951
  )) {
215888
215952
  continue;
215889
215953
  }
215890
- const normalizedRelativeDirectory = normalizePath3(
215954
+ const normalizedRelativeDirectory = normalizePath4(
215891
215955
  path7.relative(scanRootPath, fullPath)
215892
215956
  );
215893
215957
  if (adapter.ignoreDirectoryNames.includes(entry.name) || adapter.ignoreDirectoryNames.includes(normalizedRelativeDirectory)) {
@@ -216098,6 +216162,80 @@ function extractGoImportSpecifiers(sourceText) {
216098
216162
  return left.specifier.localeCompare(right.specifier);
216099
216163
  });
216100
216164
  }
216165
+ function extractJavaPackageName(sourceText) {
216166
+ const match = /^\s*package\s+([a-zA-Z_][\w.]*)\s*;/mu.exec(sourceText);
216167
+ return match?.[1];
216168
+ }
216169
+ async function buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) {
216170
+ const classes = /* @__PURE__ */ new Map();
216171
+ const packageCandidates = /* @__PURE__ */ new Map();
216172
+ for (const [moduleId, moduleRoot] of [...moduleRoots.entries()].sort(
216173
+ ([left], [right]) => left.localeCompare(right)
216174
+ )) {
216175
+ const childModuleRoots = [...moduleRoots.entries()].filter(([childModuleName, childModuleRoot]) => childModuleName !== moduleId && isPathInsideOrEqual2(childModuleRoot, moduleRoot)).map(([, childModuleRoot]) => childModuleRoot);
216176
+ const sourceFiles = await collectSourceFiles(moduleRoot, adapter, moduleRoot, childModuleRoots);
216177
+ for (const sourceFilePath of sourceFiles) {
216178
+ const relativePath = normalizePath4(path7.relative(workspaceRoot, sourceFilePath));
216179
+ if (isTestSourcePath(relativePath)) {
216180
+ continue;
216181
+ }
216182
+ const sourceText = await readTextFileIfExists2(sourceFilePath);
216183
+ if (!sourceText) {
216184
+ continue;
216185
+ }
216186
+ const packageName = extractJavaPackageName(sourceText);
216187
+ if (!packageName) {
216188
+ continue;
216189
+ }
216190
+ const className = path7.basename(sourceFilePath, path7.extname(sourceFilePath));
216191
+ const entry = { moduleId, resolvedPath: sourceFilePath };
216192
+ classes.set(`${packageName}.${className}`, entry);
216193
+ const existing = packageCandidates.get(packageName) ?? [];
216194
+ existing.push(entry);
216195
+ packageCandidates.set(packageName, existing);
216196
+ }
216197
+ }
216198
+ const packages = /* @__PURE__ */ new Map();
216199
+ for (const [packageName, entries] of packageCandidates) {
216200
+ const moduleIds = new Set(entries.map((entry) => entry.moduleId));
216201
+ packages.set(packageName, moduleIds.size === 1 ? entries[0] : "ambiguous");
216202
+ }
216203
+ return { classes, packages };
216204
+ }
216205
+ function resolveJavaImportFromIndex(importSpecifier, index, workspaceRoot) {
216206
+ if (!index) {
216207
+ return void 0;
216208
+ }
216209
+ if (importSpecifier.endsWith(".*")) {
216210
+ const packageName = importSpecifier.slice(0, -2);
216211
+ const entry = index.packages.get(packageName);
216212
+ if (!entry || entry === "ambiguous") {
216213
+ return void 0;
216214
+ }
216215
+ return {
216216
+ targetModule: entry.moduleId,
216217
+ resolvedRelativePath: normalizePath4(path7.relative(workspaceRoot, entry.resolvedPath)),
216218
+ isPublicImport: false
216219
+ };
216220
+ }
216221
+ const exactEntry = index.classes.get(importSpecifier);
216222
+ if (exactEntry) {
216223
+ return {
216224
+ targetModule: exactEntry.moduleId,
216225
+ resolvedRelativePath: normalizePath4(path7.relative(workspaceRoot, exactEntry.resolvedPath)),
216226
+ isPublicImport: false
216227
+ };
216228
+ }
216229
+ const ownerCandidate = [...index.classes.entries()].filter(([classImport]) => importSpecifier.startsWith(`${classImport}.`)).sort((left, right) => right[0].length - left[0].length || left[0].localeCompare(right[0]))[0];
216230
+ if (!ownerCandidate) {
216231
+ return void 0;
216232
+ }
216233
+ return {
216234
+ targetModule: ownerCandidate[1].moduleId,
216235
+ resolvedRelativePath: normalizePath4(path7.relative(workspaceRoot, ownerCandidate[1].resolvedPath)),
216236
+ isPublicImport: false
216237
+ };
216238
+ }
216101
216239
  function extractPythonImportSpecifiers(sourceText) {
216102
216240
  const imports = [];
216103
216241
  const lines = sourceText.split(/\r?\n/u);
@@ -216200,7 +216338,7 @@ function resolveJavaModuleImport(modulesRootRelativePath, moduleRoots, importSpe
216200
216338
  const lastSegment = segments[segments.length - 1];
216201
216339
  const defaultEntrypointFileName = adapter.scaffoldingDefaults?.moduleIndexFileName ?? "Application.java";
216202
216340
  const resolvedFileName = lastSegment === "*" ? defaultEntrypointFileName : lastSegment.endsWith(".java") ? lastSegment : `${lastSegment}.java`;
216203
- const resolvedRelativePath = normalizePath3(
216341
+ const resolvedRelativePath = normalizePath4(
216204
216342
  `${modulesRootRelativePath}/${targetModule}/${resolvedFileName}`
216205
216343
  );
216206
216344
  return {
@@ -216538,13 +216676,17 @@ async function resolveWorkspacePackageImportTarget(importSpecifier, workspacePac
216538
216676
  }
216539
216677
  return void 0;
216540
216678
  }
216541
- async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath, moduleRoots, explicitStandaloneModuleByPath, workspacePackageAliases, sourceFilePath, importSpecifier, adapter, resolutionContext) {
216679
+ async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath, moduleRoots, explicitStandaloneModuleByPath, workspacePackageAliases, sourceFilePath, importSpecifier, adapter, javaImportIndex, resolutionContext) {
216542
216680
  const candidateBasePaths = [];
216543
216681
  let packageAliasTargetModule;
216544
216682
  let packageAliasTargetModuleRoot;
216545
216683
  let isPublicPackageAliasImport = false;
216546
- const normalizedModulesRoot = normalizePath3(modulesRootRelativePath).replace(/^\/+/, "");
216684
+ const normalizedModulesRoot = normalizePath4(modulesRootRelativePath).replace(/^\/+/, "");
216547
216685
  if (usesJavaImportParser(adapter) && !importSpecifier.startsWith(".")) {
216686
+ const indexedJava = resolveJavaImportFromIndex(importSpecifier, javaImportIndex, workspaceRoot);
216687
+ if (indexedJava) {
216688
+ return indexedJava;
216689
+ }
216548
216690
  const resolvedJava = resolveJavaModuleImport(
216549
216691
  normalizedModulesRoot,
216550
216692
  moduleRoots,
@@ -216641,19 +216783,19 @@ async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath,
216641
216783
  const targetModuleEntry = packageAliasTargetModule && packageAliasTargetModuleRoot ? [packageAliasTargetModule, packageAliasTargetModuleRoot] : [...moduleRoots.entries()].filter(([, moduleRoot]) => isPathInsideOrEqual2(resolvedPath, moduleRoot)).sort((left, right) => right[1].length - left[1].length || left[0].localeCompare(right[0]))[0];
216642
216784
  if (!targetModuleEntry) {
216643
216785
  const standaloneTargetModule = explicitStandaloneModuleByPath.get(
216644
- normalizePath3(path7.relative(workspaceRoot, resolvedPath))
216786
+ normalizePath4(path7.relative(workspaceRoot, resolvedPath))
216645
216787
  );
216646
216788
  if (!standaloneTargetModule) {
216647
216789
  return void 0;
216648
216790
  }
216649
216791
  return {
216650
216792
  targetModule: standaloneTargetModule,
216651
- resolvedRelativePath: normalizePath3(path7.relative(workspaceRoot, resolvedPath)),
216793
+ resolvedRelativePath: normalizePath4(path7.relative(workspaceRoot, resolvedPath)),
216652
216794
  isPublicImport: true
216653
216795
  };
216654
216796
  }
216655
216797
  const [targetModule, targetModuleRoot] = targetModuleEntry;
216656
- const targetSubPath = normalizePath3(path7.relative(targetModuleRoot, resolvedPath));
216798
+ const targetSubPath = normalizePath4(path7.relative(targetModuleRoot, resolvedPath));
216657
216799
  if (targetSubPath === "" || targetSubPath.startsWith("../") || targetSubPath.startsWith("..\\")) {
216658
216800
  return void 0;
216659
216801
  }
@@ -216669,7 +216811,7 @@ async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath,
216669
216811
  );
216670
216812
  return {
216671
216813
  targetModule,
216672
- resolvedRelativePath: normalizePath3(path7.relative(workspaceRoot, resolvedPath)),
216814
+ resolvedRelativePath: normalizePath4(path7.relative(workspaceRoot, resolvedPath)),
216673
216815
  isPublicImport,
216674
216816
  ...isPublicPackageAliasImport ? { isPackagePublicImport: true } : {}
216675
216817
  };
@@ -216680,6 +216822,7 @@ async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath,
216680
216822
  if (!supportsDependencyImportParsing(adapter)) {
216681
216823
  return imports;
216682
216824
  }
216825
+ const javaImportIndex = usesJavaImportParser(adapter) ? await buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) : void 0;
216683
216826
  for (const [moduleName, moduleRoot] of [...moduleRoots.entries()].sort(
216684
216827
  ([left], [right]) => left.localeCompare(right)
216685
216828
  )) {
@@ -216691,7 +216834,7 @@ async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath,
216691
216834
  childModuleRoots
216692
216835
  );
216693
216836
  for (const sourceFilePath of sourceFiles) {
216694
- const sourceFileRelativePath = normalizePath3(
216837
+ const sourceFileRelativePath = normalizePath4(
216695
216838
  path7.relative(workspaceRoot, sourceFilePath)
216696
216839
  );
216697
216840
  if (!includeTestFiles && isTestSourcePath(sourceFileRelativePath)) {
@@ -216716,6 +216859,7 @@ async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath,
216716
216859
  sourceFilePath,
216717
216860
  importReference.specifier,
216718
216861
  adapter,
216862
+ javaImportIndex,
216719
216863
  options?.resolutionContext
216720
216864
  );
216721
216865
  if (!resolved || resolved.targetModule === moduleName) {
@@ -216956,7 +217100,7 @@ function buildDependencyConfigSkippedFindings(reason, options) {
216956
217100
  return findings;
216957
217101
  }
216958
217102
  function normalizePathList(values) {
216959
- return values.map((value) => normalizePath3(value)).sort((left, right) => left.localeCompare(right));
217103
+ return values.map((value) => normalizePath4(value)).sort((left, right) => left.localeCompare(right));
216960
217104
  }
216961
217105
  function normalizeModuleContract(contractLike) {
216962
217106
  if (typeof contractLike.module !== "string") {
@@ -217059,7 +217203,7 @@ function buildContractSkipMessage(ruleId, sourceModule, targetModule, sourceCont
217059
217203
  )}.`;
217060
217204
  }
217061
217205
  function isImportWithinPublicEntrypoints(resolvedTargetRelativePath, publicEntrypoints) {
217062
- const normalizedTargetPath = normalizePath3(resolvedTargetRelativePath);
217206
+ const normalizedTargetPath = normalizePath4(resolvedTargetRelativePath);
217063
217207
  for (const publicEntrypoint of normalizePathList(publicEntrypoints)) {
217064
217208
  const isFileEntrypoint = /\.[a-z0-9]+$/iu.test(publicEntrypoint);
217065
217209
  if (isFileEntrypoint && normalizedTargetPath === publicEntrypoint) {
@@ -217106,17 +217250,18 @@ async function inferExistingPublicEntrypointsFromModuleRoot(workspaceRoot, modul
217106
217250
  const candidatePath = path7.join(moduleRoot, ...candidateSubpath.split("/"));
217107
217251
  if (await pathExists4(candidatePath)) {
217108
217252
  existingEntrypoints.push(
217109
- normalizePath3(path7.relative(workspaceRoot, candidatePath))
217253
+ normalizePath4(path7.relative(workspaceRoot, candidatePath))
217110
217254
  );
217111
217255
  }
217112
217256
  }
217113
217257
  return existingEntrypoints.sort((left, right) => left.localeCompare(right));
217114
217258
  }
217115
- async function resolveModulePublicEntrypoints(workspaceRoot, architectureContract, moduleName, targetContract, moduleRoots) {
217116
- const registryPublicEntrypoints = architectureContract.modules[moduleName]?.publicEntrypoints ?? [];
217259
+ async function resolveKnownModulePublicEntrypoints(workspaceRoot, architectureContract, moduleName, targetContract, moduleRoots, adapter) {
217260
+ const registryPublicEntrypoints = architectureContract?.modules[moduleName]?.publicEntrypoints ?? [];
217261
+ const contractPublicEntrypoints = targetContract?.publicEntrypoints ?? [];
217117
217262
  const explicitPublicEntrypoints = sortUnique2([
217118
217263
  ...registryPublicEntrypoints,
217119
- ...targetContract.publicEntrypoints
217264
+ ...contractPublicEntrypoints
217120
217265
  ]);
217121
217266
  const existingExplicitEntrypoints = await filterExistingPublicEntrypoints(
217122
217267
  workspaceRoot,
@@ -217125,13 +217270,16 @@ async function resolveModulePublicEntrypoints(workspaceRoot, architectureContrac
217125
217270
  if (existingExplicitEntrypoints.length > 0) {
217126
217271
  return existingExplicitEntrypoints;
217127
217272
  }
217273
+ if (usesJavaImportParser(adapter)) {
217274
+ return [];
217275
+ }
217128
217276
  return inferExistingPublicEntrypointsFromModuleRoot(
217129
217277
  workspaceRoot,
217130
217278
  moduleRoots.get(moduleName)
217131
217279
  );
217132
217280
  }
217133
217281
  function labelPublicEntrypoint(publicEntrypoint) {
217134
- const normalizedEntrypoint = normalizePath3(publicEntrypoint);
217282
+ const normalizedEntrypoint = normalizePath4(publicEntrypoint);
217135
217283
  const fileName = normalizedEntrypoint.split("/").at(-1) ?? "";
217136
217284
  return /^index\.[cm]?[jt]sx?$/iu.test(fileName) ? `${fileName} public entrypoint` : "public entrypoint";
217137
217285
  }
@@ -217151,7 +217299,7 @@ async function describeModulePublicImportGuidance(workspaceRoot, moduleName, mod
217151
217299
  return `Use the public entrypoint at ${describePublicEntrypointTargets(inferredEntrypoints)} instead.`;
217152
217300
  }
217153
217301
  if (moduleRoot) {
217154
- return `Use an existing public entrypoint under ${normalizePath3(path7.relative(workspaceRoot, moduleRoot))} instead.`;
217302
+ return `Use an existing public entrypoint under ${normalizePath4(path7.relative(workspaceRoot, moduleRoot))} instead.`;
217155
217303
  }
217156
217304
  return "Use an existing target module public entrypoint instead.";
217157
217305
  }
@@ -217548,12 +217696,13 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217548
217696
  }
217549
217697
  continue;
217550
217698
  }
217551
- const publicEntrypoints = await resolveModulePublicEntrypoints(
217699
+ const publicEntrypoints = await resolveKnownModulePublicEntrypoints(
217552
217700
  workspaceRoot,
217553
217701
  architectureContract,
217554
217702
  dependencyImport.targetModule,
217555
217703
  targetContract.contract,
217556
- moduleRoots
217704
+ moduleRoots,
217705
+ adapter
217557
217706
  );
217558
217707
  if (publicEntrypoints.length === 0) {
217559
217708
  continue;
@@ -217737,6 +217886,7 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
217737
217886
  (dependencyImport) => isModuleScopedDependencyImport(parsedArchitectureContract, dependencyImport)
217738
217887
  );
217739
217888
  const findings = [];
217889
+ const moduleContractCache = /* @__PURE__ */ new Map();
217740
217890
  let dependencyRules;
217741
217891
  let dependencyRulesSkipReason;
217742
217892
  if (options.dependencyRulesConfigOverride) {
@@ -217853,19 +218003,49 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
217853
218003
  })
217854
218004
  );
217855
218005
  } else {
217856
- const violations = moduleScopedPeerImports.filter((dependencyImport) => {
218006
+ const violations = [];
218007
+ for (const dependencyImport of moduleScopedPeerImports) {
217857
218008
  if (parsedArchitectureContract) {
217858
218009
  const dependencyMetadata = resolveImportDependencyContextMetadata(
217859
218010
  parsedArchitectureContract,
217860
218011
  dependencyImport
217861
218012
  );
217862
218013
  if (dependencyMetadata.isExternal) {
217863
- return false;
218014
+ continue;
217864
218015
  }
217865
218016
  }
217866
218017
  const moduleRules = dependencyRules.modules[dependencyImport.sourceModule];
217867
- return moduleRules?.publicEntrypointsOnly === true && !dependencyImport.isPublicImport;
217868
- });
218018
+ if (moduleRules?.publicEntrypointsOnly !== true || dependencyImport.isPublicImport) {
218019
+ continue;
218020
+ }
218021
+ if (dependencyImport.isPackagePublicImport === true) {
218022
+ continue;
218023
+ }
218024
+ const targetContract = parsedArchitectureContract ? await loadModuleArchitectureContract(
218025
+ workspaceRoot,
218026
+ parsedArchitectureContract,
218027
+ dependencyImport.targetModule,
218028
+ moduleContractCache
218029
+ ) : void 0;
218030
+ const publicEntrypoints = await resolveKnownModulePublicEntrypoints(
218031
+ workspaceRoot,
218032
+ parsedArchitectureContract,
218033
+ dependencyImport.targetModule,
218034
+ targetContract?.contract,
218035
+ moduleRoots,
218036
+ adapter
218037
+ );
218038
+ if (publicEntrypoints.length === 0) {
218039
+ continue;
218040
+ }
218041
+ if (isImportWithinPublicEntrypoints(
218042
+ dependencyImport.resolvedTargetRelativePath,
218043
+ publicEntrypoints
218044
+ )) {
218045
+ continue;
218046
+ }
218047
+ violations.push(dependencyImport);
218048
+ }
217869
218049
  if (violations.length === 0) {
217870
218050
  findings.push({
217871
218051
  result: makeValidationResult(
@@ -218014,6 +218194,7 @@ var init_dependencyValidation = __esm({
218014
218194
  init_architectureDependencyContext();
218015
218195
  init_moduleDiscovery();
218016
218196
  init_stackAdapters();
218197
+ init_sourceScopeClassification();
218017
218198
  dependencyRulesConfigFile = ".archpilot/dependency-rules.json";
218018
218199
  DependencyRulesConfigError = class extends Error {
218019
218200
  };
@@ -218021,7 +218202,7 @@ var init_dependencyValidation = __esm({
218021
218202
  });
218022
218203
 
218023
218204
  // ../core/src/moduleScope.ts
218024
- function normalizePath4(value) {
218205
+ function normalizePath5(value) {
218025
218206
  return value.replace(/\\/g, "/").replace(/^\.\/+/u, "").replace(/\/+$/u, "").toLowerCase();
218026
218207
  }
218027
218208
  function pathExists5(targetPath) {
@@ -218074,7 +218255,7 @@ function hasJsxEnabled(configPath) {
218074
218255
  return typeof jsx === "string" && jsx.trim().length > 0;
218075
218256
  }
218076
218257
  function listPathSegments(modulePath) {
218077
- return normalizePath4(modulePath).split("/").filter((entry) => entry.length > 0);
218258
+ return normalizePath5(modulePath).split("/").filter((entry) => entry.length > 0);
218078
218259
  }
218079
218260
  function getCandidateRoots(workspaceRoot, modulePath) {
218080
218261
  const resolvedWorkspaceRoot = path8.resolve(workspaceRoot);
@@ -218406,9 +218587,12 @@ var init_moduleScope = __esm({
218406
218587
  });
218407
218588
 
218408
218589
  // ../core/src/smartInit/moduleDetection.ts
218409
- function normalizePath5(value) {
218590
+ function normalizePath6(value) {
218410
218591
  return value.replaceAll("\\", "/");
218411
218592
  }
218593
+ function isUnderJvmResourceRoot(relativePath) {
218594
+ return /(^|\/)src\/main\/resources(?:\/|$)/u.test(normalizePath6(relativePath).toLowerCase());
218595
+ }
218412
218596
  function safeReadDirEntries(directoryPath) {
218413
218597
  try {
218414
218598
  return fs8.readdirSync(directoryPath, { withFileTypes: true });
@@ -218425,7 +218609,7 @@ function pathExists6(pathValue) {
218425
218609
  }
218426
218610
  }
218427
218611
  function isIgnoredPath(context, relativePath) {
218428
- return context?.ignoreMatcher?.isIgnored(normalizePath5(relativePath)) ?? false;
218612
+ return context?.ignoreMatcher?.isIgnored(normalizePath6(relativePath)) ?? false;
218429
218613
  }
218430
218614
  function uniqueSorted(values) {
218431
218615
  return [...new Set(values)].sort((left, right) => left.localeCompare(right));
@@ -218440,15 +218624,15 @@ function normalizeIdentity(value) {
218440
218624
  return value.toLowerCase().replace(/[^a-z0-9]+/gu, "");
218441
218625
  }
218442
218626
  function pathLeafIdentity(value) {
218443
- const normalized = normalizePath5(value).replace(/\/+$/gu, "");
218627
+ const normalized = normalizePath6(value).replace(/\/+$/gu, "");
218444
218628
  const leaf = normalized.split("/").filter((segment) => segment.length > 0).at(-1) ?? normalized;
218445
218629
  return normalizeIdentity(leaf);
218446
218630
  }
218447
218631
  function getComponentAlignedEvidence(input2) {
218448
- const modulePath = normalizePath5(input2.modulePath).replace(/\/+$/gu, "");
218632
+ const modulePath = normalizePath6(input2.modulePath).replace(/\/+$/gu, "");
218449
218633
  const moduleNameIdentity = normalizeIdentity(input2.moduleName);
218450
218634
  const modulePathLeaf = pathLeafIdentity(modulePath);
218451
- const matchingPath = input2.context?.componentPaths?.map((entry) => normalizePath5(entry).replace(/\/+$/gu, "")).find(
218635
+ const matchingPath = input2.context?.componentPaths?.map((entry) => normalizePath6(entry).replace(/\/+$/gu, "")).find(
218452
218636
  (componentPath) => componentPath.length > 0 && componentPath !== "." && (componentPath === modulePath || componentPath.startsWith(`${modulePath}/`))
218453
218637
  );
218454
218638
  if (matchingPath) {
@@ -218458,7 +218642,7 @@ function getComponentAlignedEvidence(input2) {
218458
218642
  if (matchingName) {
218459
218643
  return `Matches detected component/service/app identity ${input2.moduleName}`;
218460
218644
  }
218461
- const matchingResourcePath = input2.context?.resourcePaths?.map((entry) => normalizePath5(entry).replace(/\/+$/gu, "")).find(
218645
+ const matchingResourcePath = input2.context?.resourcePaths?.map((entry) => normalizePath6(entry).replace(/\/+$/gu, "")).find(
218462
218646
  (resourcePath) => resourcePath.length > 0 && resourcePath !== "." && (resourcePath === modulePath || resourcePath.startsWith(`${modulePath}/`))
218463
218647
  );
218464
218648
  if (matchingResourcePath) {
@@ -218638,6 +218822,9 @@ function containsAppRouteFiles(absolutePath) {
218638
218822
  return false;
218639
218823
  }
218640
218824
  function makeDetectedModule(workspaceRoot, moduleName, modulePath, rootPath, hasSourceFiles, hasRoleFiles, sourceFileCount, context) {
218825
+ if (isUnderJvmResourceRoot(modulePath)) {
218826
+ return void 0;
218827
+ }
218641
218828
  const evidence = [];
218642
218829
  if (hasSourceFiles) {
218643
218830
  evidence.push("Contains source files");
@@ -218696,11 +218883,14 @@ function collectModuleCandidatesFromRoot(workspaceRoot, modulesRootRelative, def
218696
218883
  const rootLower = modulesRootRelative.toLowerCase();
218697
218884
  const skipFrontendUtilities = rootLower === "src/features" || rootLower.endsWith("/src/features") || rootLower === "app" || rootLower === "src/app" || rootLower.endsWith("/app") || rootLower.endsWith("/src/app");
218698
218885
  const entries = safeReadDirEntries(absoluteRoot).filter(
218699
- (entry) => entry.isDirectory() && !ignoredDirectoryNames.has(entry.name) && !isIgnoredPath(context, normalizePath5(`${modulesRootRelative}/${entry.name}`))
218886
+ (entry) => entry.isDirectory() && !ignoredDirectoryNames.has(entry.name) && !isIgnoredPath(context, normalizePath6(`${modulesRootRelative}/${entry.name}`))
218700
218887
  ).sort((left, right) => left.name.localeCompare(right.name));
218701
218888
  const modules = [];
218702
218889
  for (const entry of entries) {
218703
- const candidateProjectRoot = normalizePath5(`${modulesRootRelative}/${entry.name}`);
218890
+ const candidateProjectRoot = normalizePath6(`${modulesRootRelative}/${entry.name}`);
218891
+ if (isUnderJvmResourceRoot(candidateProjectRoot)) {
218892
+ continue;
218893
+ }
218704
218894
  if (["apps", "packages", "services", "libs"].includes(rootLower) && (context?.projectRoots?.length ?? 0) > 0 && !context?.projectRoots?.includes(candidateProjectRoot)) {
218705
218895
  continue;
218706
218896
  }
@@ -218717,7 +218907,7 @@ function collectModuleCandidatesFromRoot(workspaceRoot, modulesRootRelative, def
218717
218907
  const detected = makeDetectedModule(
218718
218908
  workspaceRoot,
218719
218909
  moduleName,
218720
- normalizePath5(`${modulesRootRelative}/${entry.name}`),
218910
+ normalizePath6(`${modulesRootRelative}/${entry.name}`),
218721
218911
  modulesRootRelative,
218722
218912
  inspected.hasSourceFiles,
218723
218913
  inspected.hasRoleFiles,
@@ -218740,7 +218930,7 @@ function collectAppRouteModules(workspaceRoot, appRootRelative, context) {
218740
218930
  return [];
218741
218931
  }
218742
218932
  const entries = safeReadDirEntries(absoluteRoot).filter(
218743
- (entry) => entry.isDirectory() && !ignoredDirectoryNames.has(entry.name) && !isIgnoredPath(context, normalizePath5(`${appRootRelative}/${entry.name}`))
218933
+ (entry) => entry.isDirectory() && !ignoredDirectoryNames.has(entry.name) && !isIgnoredPath(context, normalizePath6(`${appRootRelative}/${entry.name}`))
218744
218934
  ).sort((left, right) => left.name.localeCompare(right.name));
218745
218935
  const modules = [];
218746
218936
  for (const entry of entries) {
@@ -218754,7 +218944,7 @@ function collectAppRouteModules(workspaceRoot, appRootRelative, context) {
218754
218944
  if (!moduleName || frontendUtilityDirectoryNames.has(moduleName.toLowerCase())) {
218755
218945
  continue;
218756
218946
  }
218757
- const moduleRelativePath = normalizePath5(`${appRootRelative}/${rawName}`);
218947
+ const moduleRelativePath = normalizePath6(`${appRootRelative}/${rawName}`);
218758
218948
  const moduleAbsolutePath = path9.join(absoluteRoot, rawName);
218759
218949
  if (!containsAppRouteFiles(moduleAbsolutePath)) {
218760
218950
  continue;
@@ -218881,14 +219071,14 @@ function collectJavaPackageRoots(workspaceRoot, context) {
218881
219071
  continue;
218882
219072
  }
218883
219073
  for (const entry of safeReadDirEntries(current.absolutePath)) {
218884
- const childRelativePath = normalizePath5(`${current.relativePath}/${entry.name}`);
219074
+ const childRelativePath = normalizePath6(`${current.relativePath}/${entry.name}`);
218885
219075
  if (!entry.isDirectory() || ignoredDirectoryNames.has(entry.name) || isIgnoredPath(context, childRelativePath)) {
218886
219076
  continue;
218887
219077
  }
218888
219078
  const lowerName = entry.name.toLowerCase();
218889
219079
  if (lowerName === "modules" || lowerName === "features") {
218890
219080
  const childCount = safeReadDirEntries(path9.join(current.absolutePath, entry.name)).filter(
218891
- (child) => child.isDirectory() && !ignoredDirectoryNames.has(child.name) && !isIgnoredPath(context, normalizePath5(`${childRelativePath}/${child.name}`))
219081
+ (child) => child.isDirectory() && !ignoredDirectoryNames.has(child.name) && !isIgnoredPath(context, normalizePath6(`${childRelativePath}/${child.name}`))
218892
219082
  ).length;
218893
219083
  if (childCount >= 2) {
218894
219084
  roots.push(childRelativePath);
@@ -218947,10 +219137,10 @@ function detectModules(workspaceRoot, options) {
218947
219137
  projectKinds: options?.projectKinds,
218948
219138
  stacks: options?.stacks,
218949
219139
  ignoreMatcher: options?.ignoreMatcher,
218950
- projectRoots: options?.projectRoots?.map(normalizePath5),
218951
- componentPaths: options?.componentPaths?.map(normalizePath5),
219140
+ projectRoots: options?.projectRoots?.map(normalizePath6),
219141
+ componentPaths: options?.componentPaths?.map(normalizePath6),
218952
219142
  componentNames: options?.componentNames,
218953
- resourcePaths: options?.resourcePaths?.map(normalizePath5),
219143
+ resourcePaths: options?.resourcePaths?.map(normalizePath6),
218954
219144
  resourceNames: options?.resourceNames
218955
219145
  };
218956
219146
  const explicitRoots = collectExplicitRoots(workspaceRoot, context);
@@ -219028,7 +219218,7 @@ function detectModules(workspaceRoot, options) {
219028
219218
  };
219029
219219
  }
219030
219220
  function detectModuleCandidatesForRoot(workspaceRoot, modulesRootRelative, options) {
219031
- const normalizedRoot = normalizePath5(modulesRootRelative.trim()).replace(/^\/+|\/+$/gu, "");
219221
+ const normalizedRoot = normalizePath6(modulesRootRelative.trim()).replace(/^\/+|\/+$/gu, "");
219032
219222
  if (normalizedRoot.length === 0) {
219033
219223
  return [];
219034
219224
  }
@@ -219040,10 +219230,10 @@ function detectModuleCandidatesForRoot(workspaceRoot, modulesRootRelative, optio
219040
219230
  projectKinds: options?.projectKinds,
219041
219231
  stacks: options?.stacks,
219042
219232
  ignoreMatcher: options?.ignoreMatcher,
219043
- projectRoots: options?.projectRoots?.map(normalizePath5),
219044
- componentPaths: options?.componentPaths?.map(normalizePath5),
219233
+ projectRoots: options?.projectRoots?.map(normalizePath6),
219234
+ componentPaths: options?.componentPaths?.map(normalizePath6),
219045
219235
  componentNames: options?.componentNames,
219046
- resourcePaths: options?.resourcePaths?.map(normalizePath5),
219236
+ resourcePaths: options?.resourcePaths?.map(normalizePath6),
219047
219237
  resourceNames: options?.resourceNames
219048
219238
  }
219049
219239
  );
@@ -219084,6 +219274,7 @@ var init_moduleDetection = __esm({
219084
219274
  "scripts",
219085
219275
  "test",
219086
219276
  "tests",
219277
+ "cypress-tests",
219087
219278
  "__tests__",
219088
219279
  "fixtures",
219089
219280
  "docs",
@@ -219307,7 +219498,7 @@ var init_moduleDetection = __esm({
219307
219498
  });
219308
219499
 
219309
219500
  // ../core/src/architectureMap.ts
219310
- function normalizePath6(value) {
219501
+ function normalizePath7(value) {
219311
219502
  return value.replace(/\\/g, "/");
219312
219503
  }
219313
219504
  async function pathExists7(targetPath) {
@@ -219329,7 +219520,7 @@ function sortUnique3(values) {
219329
219520
  return [...new Set(values)].sort((left, right) => left.localeCompare(right));
219330
219521
  }
219331
219522
  function toSafeContractModuleFileStem2(moduleName) {
219332
- return normalizePath6(moduleName).split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0).join(".");
219523
+ return normalizePath7(moduleName).split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0).join(".");
219333
219524
  }
219334
219525
  function getModuleRegistry(contract) {
219335
219526
  const modules = contract?.modules;
@@ -219374,7 +219565,7 @@ function hasExplicitModuleRegistry(config) {
219374
219565
  );
219375
219566
  }
219376
219567
  function normalizePublicEntrypointList(entries) {
219377
- return sortUnique3(entries.map((entry) => normalizePath6(entry.trim())).filter((entry) => entry.length > 0));
219568
+ return sortUnique3(entries.map((entry) => normalizePath7(entry.trim())).filter((entry) => entry.length > 0));
219378
219569
  }
219379
219570
  function hasConfiguredPublicEntrypoint(registryEntry) {
219380
219571
  return Array.isArray(registryEntry?.publicEntrypoints) && registryEntry.publicEntrypoints.some(
@@ -219484,10 +219675,10 @@ function parseCycleString(cycle) {
219484
219675
  }
219485
219676
  async function discoverModulesFromArchitectureContract(workspaceRoot, contract, modulesRoot) {
219486
219677
  const moduleRegistry = getModuleRegistry(contract);
219487
- const normalizedModulesRoot = normalizePath6(modulesRoot);
219488
- const contractsRoot = normalizePath6(contract.structure.contractsRoot ?? ".archpilot/contracts");
219678
+ const normalizedModulesRoot = normalizePath7(modulesRoot);
219679
+ const contractsRoot = normalizePath7(contract.structure.contractsRoot ?? ".archpilot/contracts");
219489
219680
  const discovered = [];
219490
- const toContractPath = (moduleName, registryEntry) => normalizePath6(
219681
+ const toContractPath = (moduleName, registryEntry) => normalizePath7(
219491
219682
  typeof registryEntry?.contract === "string" ? registryEntry.contract : `${contractsRoot}/${toSafeContractModuleFileStem2(moduleName)}.contract.json`
219492
219683
  );
219493
219684
  const resolveMissingPublicEntrypointAlignment = async (registryEntry, contractPath) => {
@@ -219515,7 +219706,7 @@ async function discoverModulesFromArchitectureContract(workspaceRoot, contract,
219515
219706
  if (!registryEntry.path || typeof registryEntry.path !== "string") {
219516
219707
  continue;
219517
219708
  }
219518
- const normalizedSourcePath = normalizePath6(registryEntry.path);
219709
+ const normalizedSourcePath = normalizePath7(registryEntry.path);
219519
219710
  const absoluteSourcePath = path10.join(workspaceRoot, ...normalizedSourcePath.split("/"));
219520
219711
  let sourcePathExists = false;
219521
219712
  let sourceIsDirectory = false;
@@ -219531,7 +219722,7 @@ async function discoverModulesFromArchitectureContract(workspaceRoot, contract,
219531
219722
  if (!sourceIsDirectory && !sourceIsFile) {
219532
219723
  continue;
219533
219724
  }
219534
- const contractPath = normalizePath6(
219725
+ const contractPath = normalizePath7(
219535
219726
  typeof registryEntry.contract === "string" ? registryEntry.contract : `${contractsRoot}/${toSafeContractModuleFileStem2(moduleName)}.contract.json`
219536
219727
  );
219537
219728
  const contractExists = await pathExists7(path10.join(workspaceRoot, ...contractPath.split("/")));
@@ -219615,7 +219806,7 @@ function getComponentEntries(contract) {
219615
219806
  }
219616
219807
  const typed = value;
219617
219808
  const componentId = typeof typed.id === "string" && typed.id.trim().length > 0 ? typed.id.trim() : typeof key === "string" && key.trim().length > 0 ? key.trim() : void 0;
219618
- const sourcePath = typeof typed.path === "string" && typed.path.trim().length > 0 ? normalizePath6(typed.path.trim()) : void 0;
219809
+ const sourcePath = typeof typed.path === "string" && typed.path.trim().length > 0 ? normalizePath7(typed.path.trim()) : void 0;
219619
219810
  if (!componentId || !sourcePath || sourcePath === ".") {
219620
219811
  continue;
219621
219812
  }
@@ -219740,7 +219931,7 @@ async function generateArchitectureMap(workspaceRoot, options) {
219740
219931
  const shouldUseConfiguredRootInference = hasArchitectureJson && !contractHasConfiguredModules && !hasExplicitEmptyModuleRegistry && hasExplicitModuleRootConfig(rawArchitectureConfig);
219741
219932
  const shouldUseTopLevelWorkspaceInference = hasArchitectureJson && !contractHasConfiguredModules && !hasExplicitEmptyModuleRegistry && !shouldUseConfiguredRootInference;
219742
219933
  const discoveryMode = hasArchitectureJson ? "architecture-json" : "inferred-src-modules";
219743
- const modulesRoot = normalizePath6(
219934
+ const modulesRoot = normalizePath7(
219744
219935
  await resolveConfiguredModulesRoot(
219745
219936
  workspaceRoot,
219746
219937
  resolveModulesRootFromContract(contract)
@@ -220638,7 +220829,7 @@ var init_archpilotIgnore = __esm({
220638
220829
  });
220639
220830
 
220640
220831
  // ../core/src/moduleContractsGenerator.ts
220641
- function normalizePath7(value) {
220832
+ function normalizePath8(value) {
220642
220833
  return value.replace(/\\/g, "/");
220643
220834
  }
220644
220835
  function toAbsolutePath(workspaceRoot, relativePath) {
@@ -220656,7 +220847,7 @@ function sortUnique4(values) {
220656
220847
  return [...new Set(values)].sort((left, right) => left.localeCompare(right));
220657
220848
  }
220658
220849
  function toSafeContractModuleFileStem3(moduleName) {
220659
- return normalizePath7(moduleName).split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0).join(".");
220850
+ return normalizePath8(moduleName).split("/").map((segment) => segment.trim()).filter((segment) => segment.length > 0).join(".");
220660
220851
  }
220661
220852
  function wildcardToRegex(pattern) {
220662
220853
  const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
@@ -220670,14 +220861,14 @@ function getModuleRegistry2(contract) {
220670
220861
  return modules;
220671
220862
  }
220672
220863
  async function inferModulePublicEntrypoints(workspaceRoot, moduleSourcePath, adapter) {
220673
- const normalizedSourcePath = normalizePath7(moduleSourcePath);
220864
+ const normalizedSourcePath = normalizePath8(moduleSourcePath);
220674
220865
  if (/\.[a-z0-9]+$/iu.test(normalizedSourcePath)) {
220675
220866
  const absoluteSourcePath = toAbsolutePath(workspaceRoot, normalizedSourcePath);
220676
220867
  if (await pathExists8(absoluteSourcePath)) {
220677
220868
  return [normalizedSourcePath];
220678
220869
  }
220679
220870
  }
220680
- const candidateFiles = adapter.defaultEntrypointHints.map((hint) => normalizePath7(hint)).filter((hint) => !hint.includes("/"));
220871
+ const candidateFiles = adapter.defaultEntrypointHints.map((hint) => normalizePath8(hint)).filter((hint) => !hint.includes("/"));
220681
220872
  const exactCandidates = candidateFiles.filter((hint) => !hint.includes("*"));
220682
220873
  const wildcardCandidates = candidateFiles.filter((hint) => hint.includes("*"));
220683
220874
  const resolvedWildcardCandidates = [];
@@ -220712,10 +220903,6 @@ async function inferModulePublicEntrypoints(workspaceRoot, moduleSourcePath, ada
220712
220903
  break;
220713
220904
  }
220714
220905
  }
220715
- if (inferred.length === 0) {
220716
- const fallbackName = adapter.scaffoldingDefaults?.moduleIndexFileName ?? orderedCandidates.find((entry) => entry.startsWith("index.")) ?? "index.ts";
220717
- inferred.push(`${normalizedSourcePath}/${fallbackName}`);
220718
- }
220719
220906
  return sortUnique4(inferred);
220720
220907
  }
220721
220908
  function buildDependsOnBySource(edges) {
@@ -220736,9 +220923,9 @@ function resolveContractPath(contract, moduleName) {
220736
220923
  const moduleRegistry = getModuleRegistry2(contract);
220737
220924
  const configured = moduleRegistry[moduleName]?.contract;
220738
220925
  if (configured && configured.trim().length > 0) {
220739
- return normalizePath7(configured);
220926
+ return normalizePath8(configured);
220740
220927
  }
220741
- return normalizePath7(
220928
+ return normalizePath8(
220742
220929
  path15.posix.join(
220743
220930
  resolveContractsRootFromContract(contract),
220744
220931
  `${toSafeContractModuleFileStem3(moduleName)}.contract.json`
@@ -220769,7 +220956,7 @@ async function readExistingModuleContractPublicEntrypoints(workspaceRoot, contra
220769
220956
  if (parsed.publicEntrypoints.some((entry) => typeof entry !== "string")) {
220770
220957
  return void 0;
220771
220958
  }
220772
- return sortUnique4(parsed.publicEntrypoints.map((entry) => normalizePath7(entry)));
220959
+ return sortUnique4(parsed.publicEntrypoints.map((entry) => normalizePath8(entry)));
220773
220960
  } catch {
220774
220961
  return void 0;
220775
220962
  }
@@ -220832,14 +221019,14 @@ async function generateMissingModuleContracts(workspaceRoot) {
220832
221019
  (left, right) => left.moduleName.localeCompare(right.moduleName)
220833
221020
  )) {
220834
221021
  const contractPath = resolveContractPath(contract, moduleEntry.moduleName);
220835
- const sourcePath = normalizePath7(moduleEntry.sourcePath);
221022
+ const sourcePath = normalizePath8(moduleEntry.sourcePath);
220836
221023
  const absoluteContractPath = toAbsolutePath(workspaceRoot, contractPath);
220837
221024
  const contractExists = await pathExists8(absoluteContractPath);
220838
221025
  const existingContract = contractExists ? await readExistingModuleContract(workspaceRoot, contractPath) : void 0;
220839
221026
  const existingContractPublicEntrypoints = contractExists ? await readExistingModuleContractPublicEntrypoints(workspaceRoot, contractPath) : void 0;
220840
221027
  const configuredPublicEntrypoints = !contractExists && Array.isArray(getModuleRegistry2(contract)[moduleEntry.moduleName]?.publicEntrypoints) ? sortUnique4(
220841
221028
  getModuleRegistry2(contract)[moduleEntry.moduleName]?.publicEntrypoints?.map(
220842
- (entry) => normalizePath7(entry)
221029
+ (entry) => normalizePath8(entry)
220843
221030
  ) ?? []
220844
221031
  ) : void 0;
220845
221032
  const publicEntrypoints = existingContractPublicEntrypoints ?? configuredPublicEntrypoints ?? await inferModulePublicEntrypoints(
@@ -220941,7 +221128,7 @@ var bootstrapArchitectureConfig_exports = {};
220941
221128
  __export(bootstrapArchitectureConfig_exports, {
220942
221129
  bootstrapArchitectureConfig: () => bootstrapArchitectureConfig
220943
221130
  });
220944
- function normalizePath8(value) {
221131
+ function normalizePath9(value) {
220945
221132
  return value.replace(/\\/g, "/");
220946
221133
  }
220947
221134
  function toAbsolutePath2(workspaceRoot, relativePath) {
@@ -221044,9 +221231,9 @@ async function bootstrapArchitectureConfig(workspaceRoot, options) {
221044
221231
  }
221045
221232
  }
221046
221233
  return {
221047
- createdFiles: sortUnique5(createdFiles.map((entry) => normalizePath8(entry))),
221048
- ensuredDirectories: sortUnique5(ensuredDirectories.map((entry) => normalizePath8(entry))),
221049
- skippedExistingFiles: sortUnique5(skippedExistingFiles.map((entry) => normalizePath8(entry))),
221234
+ createdFiles: sortUnique5(createdFiles.map((entry) => normalizePath9(entry))),
221235
+ ensuredDirectories: sortUnique5(ensuredDirectories.map((entry) => normalizePath9(entry))),
221236
+ skippedExistingFiles: sortUnique5(skippedExistingFiles.map((entry) => normalizePath9(entry))),
221050
221237
  moduleCount: modules.length,
221051
221238
  ...contractGeneration ? { contractGeneration } : {},
221052
221239
  ...contractGenerationSkippedReason ? { contractGenerationSkippedReason } : {}
@@ -221871,7 +222058,15 @@ function formatArchitectureDriftSummaryMessage(areas) {
221871
222058
  }
221872
222059
  return `Architecture drift detected in ${labels.slice(0, -1).join(", ")}, and ${labels.at(-1)}.`;
221873
222060
  }
221874
- function buildArchitectureDriftSummary(results, _suppressedResults = []) {
222061
+ function buildArchitectureDriftSummary(results, _suppressedResults = [], options = {}) {
222062
+ if (options.baselineAvailable !== true) {
222063
+ return {
222064
+ detected: false,
222065
+ areas: [],
222066
+ message: "No comparison baseline available; architecture drift was not evaluated.",
222067
+ baselineAvailable: false
222068
+ };
222069
+ }
221875
222070
  const activeFailedResults = results.filter(
221876
222071
  (result) => !result.passed && result.severity !== "info"
221877
222072
  );
@@ -221879,7 +222074,8 @@ function buildArchitectureDriftSummary(results, _suppressedResults = []) {
221879
222074
  return {
221880
222075
  detected: areas.length > 0,
221881
222076
  areas,
221882
- message: formatArchitectureDriftSummaryMessage(areas)
222077
+ message: formatArchitectureDriftSummaryMessage(areas),
222078
+ baselineAvailable: true
221883
222079
  };
221884
222080
  }
221885
222081
 
@@ -222179,7 +222375,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222179
222375
  var path19 = __toESM(require("node:path"));
222180
222376
  var import_node_fs15 = require("node:fs");
222181
222377
  var suppressionsRelativePath = ".archpilot/suppressions.json";
222182
- function normalizePath9(value) {
222378
+ function normalizePath10(value) {
222183
222379
  let normalized = value.replace(/\\/g, "/").trim();
222184
222380
  while (normalized.startsWith("./")) {
222185
222381
  normalized = normalized.slice(2);
@@ -222217,8 +222413,8 @@ function globToRegex(pattern) {
222217
222413
  return new RegExp(expression, "u");
222218
222414
  }
222219
222415
  function isSuppressionPathMatch(pattern, findingPath) {
222220
- const normalizedPattern = normalizePath9(pattern);
222221
- const normalizedFindingPath = normalizePath9(findingPath);
222416
+ const normalizedPattern = normalizePath10(pattern);
222417
+ const normalizedFindingPath = normalizePath10(findingPath);
222222
222418
  if (!normalizedPattern || !normalizedFindingPath) {
222223
222419
  return false;
222224
222420
  }
@@ -222321,7 +222517,7 @@ async function readValidationSuppressions(workspaceRoot, knownRuleIds) {
222321
222517
  ignored.push({
222322
222518
  index,
222323
222519
  ruleId,
222324
- ...entryScopeValue ? { scope: normalizePath9(entryScopeValue) } : {},
222520
+ ...entryScopeValue ? { scope: normalizePath10(entryScopeValue) } : {},
222325
222521
  reason: "Unknown rule ID. Entry was ignored.",
222326
222522
  ...expiresOn ? { expiresOn } : {}
222327
222523
  });
@@ -222330,7 +222526,7 @@ async function readValidationSuppressions(workspaceRoot, knownRuleIds) {
222330
222526
  suppressions.push({
222331
222527
  index,
222332
222528
  ruleId,
222333
- ...entryScopeValue ? { scope: normalizePath9(entryScopeValue) } : {},
222529
+ ...entryScopeValue ? { scope: normalizePath10(entryScopeValue) } : {},
222334
222530
  ...reason ? { reason } : {},
222335
222531
  ...expiresOn ? { expiresOn } : {}
222336
222532
  });
@@ -225107,66 +225303,8 @@ async function profileValidationPhase(label, run, details) {
225107
225303
  }
225108
225304
  }
225109
225305
 
225110
- // ../core/src/sourceScopeClassification.ts
225111
- function normalizePath10(value) {
225112
- return value.replace(/\\/g, "/").toLowerCase();
225113
- }
225114
- function hasPathSegment(pathValue, pattern) {
225115
- return pathValue.split("/").some((segment) => pattern.test(segment));
225116
- }
225117
- function classifyValidationSourceScope(relativePath) {
225118
- const normalized = normalizePath10(relativePath);
225119
- const fileName = normalized.split("/").at(-1) ?? normalized;
225120
- const extension = fileName.includes(".") ? fileName.slice(fileName.lastIndexOf(".")) : "";
225121
- const isTestFile = /\.(?:spec|test|e2e-spec)\.(?:ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(fileName);
225122
- const isE2e = isTestFile && /(?:^|[./_-])e2e(?:[./_-]|$)/u.test(fileName) || hasPathSegment(normalized, /^e2e$/u);
225123
- const isFixture = hasPathSegment(normalized, /^(?:fixtures?|__fixtures__)$/u);
225124
- const isTestPlugin = hasPathSegment(normalized, /^(?:test-plugins?|testing-plugins?)$/u);
225125
- const isExamplePlugin = hasPathSegment(normalized, /^(?:example-plugins?|examples?)$/u);
225126
- 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);
225127
- const isMigration = hasPathSegment(normalized, /^(?:migrations?|schema-migrations?|migration-utils?)$/u) || /(?:^|[./_-])migration(?:[./_-]|$)/u.test(fileName);
225128
- const isCliTooling = hasPathSegment(normalized, /^(?:cli|bin|scripts?|tools?|scaffold|scaffolding|generators?)$/u) || /(?:^|[./_-])(?:cli|script|tool|generator|scaffold)(?:[./_-]|$)/u.test(fileName);
225129
- const isFrontend = extension === ".tsx" || extension === ".jsx" || hasPathSegment(normalized, /^(?:frontend|client|browser|ui|admin-ui|dashboard|web-app)$/u) || /\b(?:react|angular|vue|svelte)\b/u.test(normalized);
225130
- const isInfrastructure = hasPathSegment(normalized, /^(?:infrastructure|infra|framework|adapters?|persistence|providers?)$/u) || /(?:transactional-connection|transaction-wrapper|transaction-subscriber|transaction-manager|query-runner|query-builder|event-bus|telemetry|interceptor)\.(?:ts|js|java|cs|py|php|go)$/u.test(fileName);
225131
- let category = "production-backend";
225132
- if (isGenerated) {
225133
- category = "generated";
225134
- } else if (isE2e) {
225135
- category = "e2e";
225136
- } else if (isTestFile || hasPathSegment(normalized, /^(?:test|tests|__tests__|spec|specs)$/u)) {
225137
- category = "test";
225138
- } else if (isTestPlugin) {
225139
- category = "test-plugin";
225140
- } else if (isExamplePlugin) {
225141
- category = "example-plugin";
225142
- } else if (isFixture) {
225143
- category = "fixture";
225144
- } else if (isMigration) {
225145
- category = "migration";
225146
- } else if (isCliTooling) {
225147
- category = "cli-tooling";
225148
- } else if (isFrontend) {
225149
- category = "production-frontend";
225150
- } else if (isInfrastructure) {
225151
- category = "infrastructure";
225152
- }
225153
- const isTestLike = category === "test" || category === "e2e" || category === "fixture" || category === "test-plugin" || category === "example-plugin";
225154
- return {
225155
- category,
225156
- isProduction: category === "production-backend" || category === "production-frontend" || category === "infrastructure",
225157
- isFrontend: category === "production-frontend",
225158
- isTestLike,
225159
- isGenerated: category === "generated",
225160
- isMigration: category === "migration",
225161
- isCliTooling: category === "cli-tooling",
225162
- isInfrastructure: category === "infrastructure"
225163
- };
225164
- }
225165
- function isProductionBackendGovernanceScope(scope) {
225166
- return scope.category === "production-backend";
225167
- }
225168
-
225169
225306
  // ../core/src/dataQueryRiskDetection.ts
225307
+ init_sourceScopeClassification();
225170
225308
  var maxFileSizeBytes = 256 * 1024;
225171
225309
  var supplementalRiskScanExtensions = [".json", ".yaml", ".yml", ".sql"];
225172
225310
  var backendCodeExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".java", ".cs", ".py", ".php", ".go"];
@@ -225174,7 +225312,7 @@ var supplementalIgnoredDirectoryNames = [".vscode-test", ".tmp"];
225174
225312
  var batchingEvidencePattern = /\b(?:DataLoader|Promise\.all|findMany\s*\([\s\S]{0,300}\bin\b|where\s*:\s*\{[\s\S]{0,300}\bin\s*:|include\s*:|join\s*\(|leftJoin|innerJoin|JOIN\b)\b/iu;
225175
225313
  var queryReadPattern = /\b((?:this\.)?(?:prisma\.(\w+)|([A-Za-z_$][\w$]*Repository|repository))\.(find\w*|count|aggregate|groupBy)\s*\()/giu;
225176
225314
  var unboundedLoadPattern = /\b(?:const|let|var)\s+(\w+)\s*=\s*await\s+((?:this\.)?(?:prisma\.\w+|\w*Repository|repository)\.(?:findMany|findAll|find))\s*\(([\s\S]{0,700}?)\)\s*;?[\s\S]{0,1000}\b\1\.(?:filter|map|reduce)\s*\(/iu;
225177
- var boundEvidencePattern = /\b(?:take|limit|page|cursor|skip|offset|PageRequest|Pageable)\b/iu;
225315
+ var boundEvidencePattern = /\b(?:take|limit|page|cursor|skip|offset|PageRequest|Pageable|findOne|findOneOrFail|findOneBy|findOneByOrFail|findUnique|findFirst|getOne|getRawOne|first)\b/iu;
225178
225316
  var repeatedQueryPattern = /\b((?:this\.)?(?:prisma\.(\w+)|(\w*Repository|repository))\.(find\w*|count|aggregate|groupBy)\s*\(\s*(?:\{[\s\S]{0,300}?\}|\w+)\s*\))/giu;
225179
225317
  var tenantPredicatePattern = /\b(?:tenantId|tenant_id|organizationId|organization_id|orgId|org_id|accountId|account_id|workspaceId|workspace_id|companyId|company_id|customerId|customer_id)\b/u;
225180
225318
  var codePaginationEvidencePattern = /\b(?:take|skip|limit|offset|page|perPage|pageSize|cursor|Pageable|PageRequest|paginate|simplePaginate|Limit|Offset|Take|Skip|TOP\s+\d+)\b/iu;
@@ -225985,7 +226123,7 @@ function detectRepeatedQueryPattern(method) {
225985
226123
  function extractSqlQueryLiterals(content) {
225986
226124
  const queries = [];
225987
226125
  const patterns = [
225988
- /(?:\b(?: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,
226126
+ /(?:\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,
225989
226127
  /\b(?:DB::select|DB::statement|DB::raw|DB::table)\s*\([^'"`)]{0,180}?(['"`])([\s\S]{0,900}?)\1/gu,
225990
226128
  /@Query\s*\(\s*(['"`])([\s\S]{0,900}?)\1/gu
225991
226129
  ];
@@ -226072,7 +226210,7 @@ function collectOrmReadEvidence(method) {
226072
226210
  return evidence;
226073
226211
  }
226074
226212
  function getOrmTerminalOperation(snippet) {
226075
- const match = /\.(getMany|getRawMany|getOne|getRawOne|getCount|getExists|execute|findOne|findOneBy|findUnique|findFirst|count|exists|update|delete|remove|save|insert)\s*\(/iu.exec(snippet);
226213
+ const match = /\.(getMany|getRawMany|loadMany|getOne|getRawOne|loadOne|getCount|getExists|execute|findOne|findOneOrFail|findOneBy|findOneByOrFail|findUnique|findFirst|count|exists|update|delete|remove|save|insert)\s*\(/iu.exec(snippet);
226076
226214
  return match?.[1];
226077
226215
  }
226078
226216
  function isOperationalOrBatchQueryContext(file, methodName) {
@@ -226081,12 +226219,20 @@ function isOperationalOrBatchQueryContext(file, methodName) {
226081
226219
  const method = methodName?.toLowerCase() ?? "";
226082
226220
  return segments.some((segment) => /\b(?:health|cache|job|queue|scheduler|indexer|telemetry|metrics)\b/u.test(segment.replace(/-/g, " "))) || /(^|\/)(?:health-check|healthchecks?|cache|job-queue|scheduler|search|indexer|telemetry|metrics)(?:\/|-)/u.test(pathValue) || /(?:health-check|healthcheck|cache|job-queue|scheduler|search|indexer|telemetry|metrics)\.(?:ts|tsx|js|jsx|java|cs|py|php|go)$/u.test(pathValue) || /\b(?:health|cache|job|queue|schedule|scheduler|index|telemetry|metrics|buffer|worker|batch)\b/u.test(method) || method.includes("batch") || /^on(?:moduleinit|applicationbootstrap|applicationstart|init)$/u.test(method);
226083
226221
  }
226084
- function isPointLookupMethodName(methodName) {
226085
- return /^(?:getorcreate|findone|findby|getby|loadby|resolveby)/iu.test(methodName);
226222
+ function isScopedRelationLoad(snippet) {
226223
+ return /\.relation\s*\(/iu.test(snippet) && /\.of\s*\(\s*[^)]{1,180}\)\s*\.loadMany\s*\(/iu.test(snippet);
226224
+ }
226225
+ function hasAssignedBuilderBoundedTerminal(methodBody, snippet) {
226226
+ const variableMatch = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:[\s\S]{0,240}?)createQueryBuilder\s*\(/iu.exec(snippet);
226227
+ const variableName = variableMatch?.[1];
226228
+ if (!variableName) {
226229
+ return false;
226230
+ }
226231
+ return new RegExp(`\\b${variableName}\\s*\\.\\s*(?:getOne|getRawOne|loadOne|getCount|getExists)\\s*\\(`, "iu").test(methodBody);
226086
226232
  }
226087
- function isNonCollectionOrmRead(label, snippet) {
226233
+ function isNonCollectionOrmRead(label, snippet, methodBody = snippet) {
226088
226234
  const terminal = getOrmTerminalOperation(snippet);
226089
- return /\b(?:findOne|findOneBy|findUnique|findFirst|count|exists|aggregate)\b/iu.test(label) || !!terminal && /^(?:getOne|getRawOne|getCount|getExists|findOne|findOneBy|findUnique|findFirst|count|exists|update|delete|remove|save|insert|execute)$/iu.test(terminal);
226235
+ 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);
226090
226236
  }
226091
226237
  function hasOrmBoundEvidence(snippet) {
226092
226238
  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);
@@ -226121,7 +226267,7 @@ function detectOrmQueryShapeFindings(method, config) {
226121
226267
  target: evidence.label
226122
226268
  }));
226123
226269
  }
226124
- if (!isOperationalOrBatchQueryContext(method.file, method.name) && !isPointLookupMethodName(method.name) && !isNonCollectionOrmRead(evidence.label, evidence.snippet) && !hasOrmBoundEvidence(evidence.snippet)) {
226270
+ if (!isOperationalOrBatchQueryContext(method.file, method.name) && !isNonCollectionOrmRead(evidence.label, evidence.snippet, method.body) && !hasOrmBoundEvidence(evidence.snippet)) {
226125
226271
  const target = getOrmQueryTarget(method, evidence.label, evidence.snippet);
226126
226272
  const label = getOrmQueryLabel(method, evidence.label, evidence.snippet);
226127
226273
  findings.push(createCodeFinding({
@@ -226146,9 +226292,12 @@ function detectCodeQueryRiskFindings(files, config, astCache) {
226146
226292
  findings.push(...detectCodeSqlQueryShapeFindings(file, config));
226147
226293
  }
226148
226294
  for (const method of extractMethodBodies(file, astCache)) {
226295
+ if (!isProductionBackend) {
226296
+ continue;
226297
+ }
226149
226298
  nPlusOneEvidence.push(...detectNPlusOneQueryRisk(method));
226150
226299
  findings.push(
226151
- ...isProductionBackend ? detectOrmQueryShapeFindings(method, config) : [],
226300
+ ...detectOrmQueryShapeFindings(method, config),
226152
226301
  ...detectLargeCollectionLoading(method),
226153
226302
  ...detectMissingProjection(method),
226154
226303
  ...detectRepeatedQueryPattern(method)
@@ -226241,6 +226390,7 @@ var import_node_fs25 = require("node:fs");
226241
226390
  var ts3 = __toESM(require_typescript());
226242
226391
  init_moduleDiscovery();
226243
226392
  init_archpilotIgnore();
226393
+ init_sourceScopeClassification();
226244
226394
  var ApplicationLayeringRuleIds = {
226245
226395
  CONTROLLER_BUSINESS_LOGIC: "AP-APP-001",
226246
226396
  REPOSITORY_BUSINESS_LOGIC: "AP-APP-002",
@@ -226912,35 +227062,30 @@ function isDbModelEvidenceToken(value) {
226912
227062
  const lower = normalized.toLowerCase();
226913
227063
  const excluded = /* @__PURE__ */ new Set([
226914
227064
  "a",
227065
+ "all",
226915
227066
  "an",
226916
- "api",
226917
- "client",
226918
- "database",
226919
- "from",
226920
- "into",
226921
- "join",
226922
- "openapi",
226923
- "or",
226924
- "paddle",
226925
- "provider",
227067
+ "doing",
227068
+ "first",
227069
+ "is",
227070
+ "outside",
226926
227071
  "resend",
226927
- "s3",
226928
- "select",
226929
- "stripe",
227072
+ "scratch",
226930
227073
  "swagger",
226931
- "table",
226932
- "the",
226933
- "this",
226934
- "to",
226935
- "update",
226936
- "where",
226937
- "with"
227074
+ "the"
226938
227075
  ]);
226939
227076
  if (excluded.has(lower)) {
226940
227077
  return false;
226941
227078
  }
226942
227079
  return !/(?:client|provider|service|controller|guard|swagger|openapi)$/iu.test(normalized);
226943
227080
  }
227081
+ function isStructuredSqlTableEvidence(value, keyword, quote, following = "") {
227082
+ const normalized = value.trim();
227083
+ const hasStructuralEvidence = /^(?:from|update|into)$/iu.test(keyword) || quote !== void 0 && quote.length > 0 || /[_.]/u.test(normalized) || /^join$/iu.test(keyword) && /\bon\b/iu.test(following);
227084
+ return hasStructuralEvidence && isDbModelEvidenceToken(normalized);
227085
+ }
227086
+ function extractSqlLikeLiterals(content) {
227087
+ return [...content.matchAll(/(['"`])([\s\S]{0,1200}?)\1/gu)].map((match) => match[2] ?? "").filter((literal) => /\b(?:select|update|delete|insert)\b[\s\S]{0,400}\b(?:from|join|into|update)\b/iu.test(literal));
227088
+ }
226944
227089
  function extractDbModelsTouched(content) {
226945
227090
  const models = /* @__PURE__ */ new Set();
226946
227091
  for (const match of content.matchAll(/\b(?:this\.)?prisma\.([a-z]\w*)\./giu)) {
@@ -226948,9 +227093,13 @@ function extractDbModelsTouched(content) {
226948
227093
  models.add(match[1]);
226949
227094
  }
226950
227095
  }
226951
- for (const match of content.matchAll(/\b(?:from|join|update|into)\s+["`]?([A-Za-z_][\w]*)["`]?/giu)) {
226952
- if (match[1] && isDbModelEvidenceToken(match[1])) {
226953
- models.add(match[1]);
227096
+ for (const sqlLiteral of extractSqlLikeLiterals(content)) {
227097
+ for (const match of sqlLiteral.matchAll(/\b(?:from|join|update|into)\s+(["`]?)([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)?)\1/giu)) {
227098
+ const keyword = /\b(from|join|update|into)\b/iu.exec(match[0])?.[1] ?? "";
227099
+ const following = sqlLiteral.slice((match.index ?? 0) + match[0].length, (match.index ?? 0) + match[0].length + 120);
227100
+ if (match[2] && isStructuredSqlTableEvidence(match[2], keyword, match[1], following)) {
227101
+ models.add(match[2]);
227102
+ }
226954
227103
  }
226955
227104
  }
226956
227105
  return sortUnique6(models).slice(0, 6);
@@ -227694,6 +227843,7 @@ var import_node_fs27 = require("node:fs");
227694
227843
  var ts5 = __toESM(require_typescript());
227695
227844
  init_moduleDiscovery();
227696
227845
  init_archpilotIgnore();
227846
+ init_sourceScopeClassification();
227697
227847
  var RuleIds2 = {
227698
227848
  TXN_BOUNDARY_TOO_BROAD: "AP-TXN-001",
227699
227849
  TXN_IN_CONTROLLER: "AP-TXN-002",
@@ -228737,35 +228887,30 @@ function isDbModelEvidenceToken2(value) {
228737
228887
  const lower = normalized.toLowerCase();
228738
228888
  const excluded = /* @__PURE__ */ new Set([
228739
228889
  "a",
228890
+ "all",
228740
228891
  "an",
228741
- "api",
228742
- "client",
228743
- "database",
228744
- "from",
228745
- "into",
228746
- "join",
228747
- "openapi",
228748
- "or",
228749
- "paddle",
228750
- "provider",
228892
+ "doing",
228893
+ "first",
228894
+ "is",
228895
+ "outside",
228751
228896
  "resend",
228752
- "s3",
228753
- "select",
228754
- "stripe",
228897
+ "scratch",
228755
228898
  "swagger",
228756
- "table",
228757
- "the",
228758
- "this",
228759
- "to",
228760
- "update",
228761
- "where",
228762
- "with"
228899
+ "the"
228763
228900
  ]);
228764
228901
  if (excluded.has(lower)) {
228765
228902
  return false;
228766
228903
  }
228767
228904
  return !/(?:client|provider|service|controller|guard|swagger|openapi)$/iu.test(normalized);
228768
228905
  }
228906
+ function isStructuredSqlTableEvidence2(value, keyword, quote, following = "") {
228907
+ const normalized = value.trim();
228908
+ const hasStructuralEvidence = /^(?:from|update|into)$/iu.test(keyword) || quote !== void 0 && quote.length > 0 || /[_.]/u.test(normalized) || /^join$/iu.test(keyword) && /\bon\b/iu.test(following);
228909
+ return hasStructuralEvidence && isDbModelEvidenceToken2(normalized);
228910
+ }
228911
+ function extractSqlLikeLiterals2(content) {
228912
+ return [...content.matchAll(/(['"`])([\s\S]{0,1200}?)\1/gu)].map((match) => match[2] ?? "").filter((literal) => /\b(?:select|update|delete|insert)\b[\s\S]{0,400}\b(?:from|join|into|update)\b/iu.test(literal));
228913
+ }
228769
228914
  function extractDbModelsTouched2(content) {
228770
228915
  const models = /* @__PURE__ */ new Set();
228771
228916
  for (const match of content.matchAll(/\b(?:this\.)?prisma\.([a-z]\w*)\./giu)) {
@@ -228773,9 +228918,13 @@ function extractDbModelsTouched2(content) {
228773
228918
  models.add(match[1]);
228774
228919
  }
228775
228920
  }
228776
- for (const match of content.matchAll(/\b(?:from|join|update|into)\s+["`]?([A-Za-z_][\w]*)["`]?/giu)) {
228777
- if (match[1] && isDbModelEvidenceToken2(match[1])) {
228778
- models.add(match[1]);
228921
+ for (const sqlLiteral of extractSqlLikeLiterals2(content)) {
228922
+ for (const match of sqlLiteral.matchAll(/\b(?:from|join|update|into)\s+(["`]?)([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)?)\1/giu)) {
228923
+ const keyword = /\b(from|join|update|into)\b/iu.exec(match[0])?.[1] ?? "";
228924
+ const following = sqlLiteral.slice((match.index ?? 0) + match[0].length, (match.index ?? 0) + match[0].length + 120);
228925
+ if (match[2] && isStructuredSqlTableEvidence2(match[2], keyword, match[1], following)) {
228926
+ models.add(match[2]);
228927
+ }
228779
228928
  }
228780
228929
  }
228781
228930
  return sortUnique7(models).slice(0, 6);
@@ -229025,6 +229174,7 @@ var path33 = __toESM(require("node:path"));
229025
229174
  var import_node_fs28 = require("node:fs");
229026
229175
  init_moduleDiscovery();
229027
229176
  init_archpilotIgnore();
229177
+ init_sourceScopeClassification();
229028
229178
  var RuleIds3 = {
229029
229179
  MISSING_PAGINATION: "AP-API-010",
229030
229180
  BULK_OPERATION_RISK: "AP-API-011",
@@ -229541,8 +229691,34 @@ function hasPaginationEvidence2(endpoint, contractEndpoints) {
229541
229691
  ${endpoint.signature}
229542
229692
  ${endpoint.body}`);
229543
229693
  }
229694
+ function stripStaticLiteralNoise(value) {
229695
+ return value.replace(/\/\*[\s\S]*?\*\//gu, " ").replace(/\/\/.*$/gmu, " ").replace(/(['"`])(?:\\.|(?!\1)[\s\S])*\1/gu, '""');
229696
+ }
229697
+ function isStaticCollectionExpression(expression) {
229698
+ const normalized = expression.trim().replace(/;$/u, "").trim();
229699
+ return /^(?:Object\.)?(?:freeze|values|entries|keys)\s*\(/u.test(normalized) || /^(?:\[[\s\S]*\]|\{[\s\S]*\})$/u.test(normalized) || /^(?:[A-Z][A-Za-z0-9_]*|[a-z][A-Za-z0-9_]*(?:Config|Configs|Catalog|Catalogs|Metadata|Definitions|Types|Widgets|Constants))$/u.test(normalized);
229700
+ }
229701
+ function hasStaticDeclarationEvidence(fileContent, identifier) {
229702
+ const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
229703
+ return new RegExp(`\\bimport\\s+(?:\\{[^}]*\\b${escaped}\\b[^}]*\\}|${escaped}\\b)`, "u").test(fileContent) || new RegExp(`\\b(?:const|readonly)\\s+${escaped}\\s*=\\s*(?:Object\\.freeze\\s*\\(|\\[|\\{)`, "u").test(fileContent) || new RegExp(`\\benum\\s+${escaped}\\b`, "u").test(fileContent);
229704
+ }
229705
+ function isStaticCollectionBackedEndpoint(endpoint) {
229706
+ const body = endpoint.body.trim();
229707
+ if (/\b(?:await|repository|Repository|createQueryBuilder|findMany|findAll|find\s*\(|query\s*\(|execute\s*\(|service\.)\b/iu.test(body)) {
229708
+ return false;
229709
+ }
229710
+ const returnMatch = /\breturn\s+([\s\S]{0,500}?);/u.exec(body) ?? /\bres\.(?:json|send)\s*\(\s*([\s\S]{0,500}?)\s*\)\s*;?/u.exec(body) ?? /\bOk\s*\(\s*([\s\S]{0,500}?)\s*\)\s*;?/u.exec(body);
229711
+ if (!returnMatch?.[1]) {
229712
+ return false;
229713
+ }
229714
+ const expression = returnMatch[1].trim();
229715
+ if (/^[A-Za-z_$][\w$]*$/u.test(expression)) {
229716
+ return hasStaticDeclarationEvidence(endpoint.file.content, expression);
229717
+ }
229718
+ return isStaticCollectionExpression(stripStaticLiteralNoise(expression));
229719
+ }
229544
229720
  function detectPaginationFindings(endpoints, contractEndpoints) {
229545
- return endpoints.filter((endpoint) => isCollectionGet(endpoint) && !hasPaginationEvidence2(endpoint, contractEndpoints)).map((endpoint) => createFinding4({
229721
+ return endpoints.filter((endpoint) => isCollectionGet(endpoint) && !hasPaginationEvidence2(endpoint, contractEndpoints) && !isStaticCollectionBackedEndpoint(endpoint)).map((endpoint) => createFinding4({
229546
229722
  id: RuleIds3.MISSING_PAGINATION,
229547
229723
  message: `Collection endpoint ${endpoint.httpMethod.toUpperCase()} ${endpoint.path} lacks visible pagination evidence.`,
229548
229724
  endpoint
@@ -231200,7 +231376,7 @@ src/
231200
231376
  architectureScope: "module",
231201
231377
  applicability: { requiresArchitectureModules: true },
231202
231378
  description: "Checks whether cross-module imports target another module through its public entrypoints rather than internal implementation files.",
231203
- recommendedFix: "Import another module through src/modules/<module>/index.ts or src/modules/<module>/public rather than reaching into internal files."
231379
+ recommendedFix: "Import through the target module or package public entrypoint declared in its contract rather than reaching into internal implementation files."
231204
231380
  },
231205
231381
  DEP_CROSS_MODULE_DEPENDENCY_DECLARED_IN_CONTRACT: {
231206
231382
  id: ValidationRuleIds.DEP_CROSS_MODULE_DEPENDENCY_DECLARED_IN_CONTRACT,
@@ -242593,6 +242769,9 @@ var ignoredRootPathPrefixes = [
242593
242769
  function normalizeRelativePath5(value) {
242594
242770
  return value.replaceAll("\\", "/");
242595
242771
  }
242772
+ function isUnderJvmResourceRoot2(relativePath) {
242773
+ return /(^|\/)src\/main\/resources(?:\/|$)/u.test(normalizeRelativePath5(relativePath).toLowerCase());
242774
+ }
242596
242775
  function sortUnique16(values) {
242597
242776
  return [...new Set(values)].sort((left, right) => left.localeCompare(right));
242598
242777
  }
@@ -242730,7 +242909,7 @@ function collectDetectedRoots(scan) {
242730
242909
  const roots = /* @__PURE__ */ new Set();
242731
242910
  for (const manifestName of manifestFileNames) {
242732
242911
  for (const manifestPath of scan.manifestPathsByName[manifestName]) {
242733
- if (isIgnoredRelativePath(manifestPath)) {
242912
+ if (isIgnoredRelativePath(manifestPath) || isUnderJvmResourceRoot2(manifestPath)) {
242734
242913
  continue;
242735
242914
  }
242736
242915
  const containingDirectory = normalizeRelativePath5(path58.dirname(manifestPath));
@@ -242745,11 +242924,11 @@ function buildResultFromScan(scan) {
242745
242924
  const evidence = [];
242746
242925
  const detectedRoots = collectDetectedRoots(scan);
242747
242926
  const filteredManifestPathsByName = {
242748
- "package.json": scan.manifestPathsByName["package.json"].filter((entry) => !isIgnoredRelativePath(entry)),
242749
- "pom.xml": scan.manifestPathsByName["pom.xml"].filter((entry) => !isIgnoredRelativePath(entry)),
242750
- "requirements.txt": scan.manifestPathsByName["requirements.txt"].filter((entry) => !isIgnoredRelativePath(entry)),
242751
- "go.mod": scan.manifestPathsByName["go.mod"].filter((entry) => !isIgnoredRelativePath(entry)),
242752
- "composer.json": scan.manifestPathsByName["composer.json"].filter((entry) => !isIgnoredRelativePath(entry))
242927
+ "package.json": scan.manifestPathsByName["package.json"].filter((entry) => !isIgnoredRelativePath(entry) && !isUnderJvmResourceRoot2(entry)),
242928
+ "pom.xml": scan.manifestPathsByName["pom.xml"].filter((entry) => !isIgnoredRelativePath(entry) && !isUnderJvmResourceRoot2(entry)),
242929
+ "requirements.txt": scan.manifestPathsByName["requirements.txt"].filter((entry) => !isIgnoredRelativePath(entry) && !isUnderJvmResourceRoot2(entry)),
242930
+ "go.mod": scan.manifestPathsByName["go.mod"].filter((entry) => !isIgnoredRelativePath(entry) && !isUnderJvmResourceRoot2(entry)),
242931
+ "composer.json": scan.manifestPathsByName["composer.json"].filter((entry) => !isIgnoredRelativePath(entry) && !isUnderJvmResourceRoot2(entry))
242753
242932
  };
242754
242933
  let monorepoStrongSignals = 0;
242755
242934
  let monorepoWeakSignals = 0;
@@ -243049,6 +243228,12 @@ function confidenceWeight(confidence) {
243049
243228
  return 1;
243050
243229
  }
243051
243230
  function compareCandidates2(left, right) {
243231
+ if (left.result.confidence === "high" && right.result.confidence === "high" && left.adapter.category === "framework" && right.adapter.category === "generic-language" && left.adapter.ecosystem === right.adapter.ecosystem) {
243232
+ return -1;
243233
+ }
243234
+ if (left.result.confidence === "high" && right.result.confidence === "high" && left.adapter.category === "generic-language" && right.adapter.category === "framework" && left.adapter.ecosystem === right.adapter.ecosystem) {
243235
+ return 1;
243236
+ }
243052
243237
  const confidenceDiff = confidenceWeight(right.result.confidence) - confidenceWeight(left.result.confidence);
243053
243238
  if (confidenceDiff !== 0) {
243054
243239
  return confidenceDiff;
@@ -244794,6 +244979,9 @@ var ignoredDirectoryNames12 = /* @__PURE__ */ new Set([
244794
244979
  function normalizePath24(value) {
244795
244980
  return value.replaceAll("\\", "/");
244796
244981
  }
244982
+ function isUnderJvmResourceRoot3(relativePath) {
244983
+ return /(^|\/)src\/main\/resources(?:\/|$)/u.test(normalizePath24(relativePath).toLowerCase());
244984
+ }
244797
244985
  function unique(values) {
244798
244986
  return [...new Set(values)];
244799
244987
  }
@@ -244942,7 +245130,7 @@ function hasAnyDependency2(summary, dependencyNames) {
244942
245130
  function collectCandidateRoots(workspaceRoot, topology, ignoreMatcher) {
244943
245131
  const roots = /* @__PURE__ */ new Set();
244944
245132
  for (const root of topology.detectedRoots ?? []) {
244945
- if (root && root !== "." && !isIgnoredPath6(ignoreMatcher, root) && !isSupportingAssetRoot(root)) {
245133
+ if (root && root !== "." && !isIgnoredPath6(ignoreMatcher, root) && !isSupportingAssetRoot(root) && !isUnderJvmResourceRoot3(root)) {
244946
245134
  roots.add(normalizePath24(root));
244947
245135
  }
244948
245136
  }
@@ -244950,7 +245138,7 @@ function collectCandidateRoots(workspaceRoot, topology, ignoreMatcher) {
244950
245138
  const absoluteBase = path63.join(workspaceRoot, base);
244951
245139
  for (const entry of safeReadDirEntries4(absoluteBase)) {
244952
245140
  const relativePath = `${base}/${entry.name}`;
244953
- if (!entry.isDirectory() || ignoredDirectoryNames12.has(entry.name) || isIgnoredPath6(ignoreMatcher, relativePath) || isSupportingAssetRoot(relativePath) || (topology.detectedRoots?.length ?? 0) > 0 && !topology.detectedRoots?.includes(relativePath) && !hasManifest(workspaceRoot, relativePath)) {
245141
+ if (!entry.isDirectory() || ignoredDirectoryNames12.has(entry.name) || isIgnoredPath6(ignoreMatcher, relativePath) || isSupportingAssetRoot(relativePath) || isUnderJvmResourceRoot3(relativePath) || (topology.detectedRoots?.length ?? 0) > 0 && !topology.detectedRoots?.includes(relativePath) && !hasManifest(workspaceRoot, relativePath)) {
244954
245142
  continue;
244955
245143
  }
244956
245144
  roots.add(relativePath);
@@ -245034,9 +245222,10 @@ function inspectRoot(workspaceRoot, root, ignoreMatcher) {
245034
245222
  addEvidence5(evidence, "Detected modules root");
245035
245223
  }
245036
245224
  const hasFrontendSignals = fileExists5(scan.files, "next.config.js") || fileExists5(scan.files, "next.config.ts") || fileExists5(scan.files, "angular.json") || fileExists5(scan.files, "vite.config.ts") || fileExists5(scan.files, "vite.config.js") || hasDirectory(scan.directories, "pages") || hasDirectory(scan.directories, "public") || hasAnyDependency2(packageJson, ["next", "react", "vue", "@angular/core"]);
245225
+ const hasRunnableFrontendSignals = fileExists5(scan.files, "next.config.js") || fileExists5(scan.files, "next.config.ts") || fileExists5(scan.files, "angular.json") || fileExists5(scan.files, "vite.config.ts") || fileExists5(scan.files, "vite.config.js") || fileExists5(scan.files, "index.html") || hasDirectory(scan.directories, "pages") || hasDirectory(scan.directories, "src/app");
245037
245226
  const hasBackendSignals = hasApiBoundary || hasDatabaseAccess || fileExists5(scan.files, "pom.xml") || fileExists5(scan.files, "requirements.txt") || fileExists5(scan.files, "go.mod") || hasDirectory(scan.directories, "src/main/java");
245038
245227
  let classification = "unknown";
245039
- if ((root.startsWith("packages/") || root.startsWith("libs/")) && !hasApiBoundary) {
245228
+ if ((root.startsWith("packages/") || root.startsWith("libs/")) && !hasRunnableFrontendSignals && !hasApiBoundary) {
245040
245229
  classification = "shared_package";
245041
245230
  } else if (hasBackendSignals && !hasFrontendSignals) {
245042
245231
  classification = "backend_app";
@@ -245147,6 +245336,8 @@ function isIgnoredComponentCandidatePath(componentPath) {
245147
245336
  const ignoredRootSegments = [
245148
245337
  "tests",
245149
245338
  "test",
245339
+ "cypress",
245340
+ "cypress-tests",
245150
245341
  "__tests__",
245151
245342
  "fixtures",
245152
245343
  "smoke",
@@ -245214,8 +245405,14 @@ function recordKeys(value) {
245214
245405
  function hasObject(value) {
245215
245406
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
245216
245407
  }
245408
+ function hasPackagePublishSurface(packageJson) {
245409
+ return hasObject(packageJson?.exports) || typeof packageJson?.main === "string" || typeof packageJson?.module === "string" || typeof packageJson?.types === "string" || hasObject(packageJson?.publishConfig) || Array.isArray(packageJson?.files);
245410
+ }
245411
+ function absoluteComponentRoot(workspaceRoot, componentPath) {
245412
+ return componentPath === "." ? workspaceRoot : path64.join(workspaceRoot, ...componentPath.split("/"));
245413
+ }
245217
245414
  function readPackageJson(workspaceRoot, componentPath) {
245218
- const absoluteRoot = componentPath === "." ? workspaceRoot : path64.join(workspaceRoot, ...componentPath.split("/"));
245415
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
245219
245416
  return safeReadJson(path64.join(absoluteRoot, "package.json"));
245220
245417
  }
245221
245418
  function readTextFileSafe(filePath) {
@@ -245233,7 +245430,10 @@ function readFirstXmlTag(value, tagName) {
245233
245430
  return match?.[1]?.trim().replace(/\s+/gu, " ");
245234
245431
  }
245235
245432
  function readMavenMetadata(workspaceRoot, componentPath) {
245236
- const absoluteRoot = componentPath === "." ? workspaceRoot : path64.join(workspaceRoot, ...componentPath.split("/"));
245433
+ if (isUnderJvmResourceRoot4(componentPath)) {
245434
+ return void 0;
245435
+ }
245436
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
245237
245437
  const pomXml = readTextFileSafe(path64.join(absoluteRoot, "pom.xml"));
245238
245438
  if (!pomXml) {
245239
245439
  return void 0;
@@ -245329,21 +245529,86 @@ function resolveId(componentPath, usedIds) {
245329
245529
  usedIds.add(id);
245330
245530
  return id;
245331
245531
  }
245332
- function resolveKind(candidate, localProjectKinds) {
245532
+ function hasRunnableFrontendComponentEvidence(workspaceRoot, componentPath) {
245533
+ const absoluteRoot = componentPath === "." ? workspaceRoot : path64.join(workspaceRoot, ...componentPath.split("/"));
245534
+ const packageJson = readPackageJson(workspaceRoot, componentPath);
245535
+ const dependencies = [
245536
+ ...recordKeys(packageJson?.dependencies),
245537
+ ...recordKeys(packageJson?.devDependencies)
245538
+ ];
245539
+ const scripts = recordKeys(packageJson?.scripts);
245540
+ const hasFrontendFramework = dependencies.some(
245541
+ (dependency) => /^(?:react|next|vue|@angular\/core|@sveltejs\/kit)$/u.test(dependency)
245542
+ );
245543
+ const hasInteractiveRunnableScript = scripts.some(
245544
+ (script) => /^(?:dev|start|serve|preview)(?::|$)/u.test(script)
245545
+ );
245546
+ const hasBundlerConfig = [
245547
+ "next.config.js",
245548
+ "next.config.ts",
245549
+ "vite.config.js",
245550
+ "vite.config.ts",
245551
+ "angular.json"
245552
+ ].some((relativePath) => pathExists19(path64.join(absoluteRoot, ...relativePath.split("/"))));
245553
+ const hasApplicationEntry = [
245554
+ "index.html",
245555
+ "src/main.tsx",
245556
+ "src/main.ts",
245557
+ "src/App.tsx",
245558
+ "src/app",
245559
+ "pages"
245560
+ ].some((relativePath) => pathExists19(path64.join(absoluteRoot, ...relativePath.split("/"))));
245561
+ return hasFrontendFramework && (hasApplicationEntry || hasInteractiveRunnableScript && hasBundlerConfig);
245562
+ }
245563
+ function isUnderJvmResourceRoot4(componentPath) {
245564
+ return /(^|\/)src\/main\/resources(?:\/|$)/u.test(normalizePath25(componentPath).toLowerCase());
245565
+ }
245566
+ function hasRuntimeSourceFiles(workspaceRoot, componentPath) {
245567
+ if (isUnderJvmResourceRoot4(componentPath)) {
245568
+ return false;
245569
+ }
245570
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
245571
+ const sourceRoots = [
245572
+ path64.join(absoluteRoot, "src", "main", "java"),
245573
+ path64.join(absoluteRoot, "src"),
245574
+ path64.join(absoluteRoot, "app"),
245575
+ path64.join(absoluteRoot, "server")
245576
+ ];
245577
+ for (const sourceRoot of sourceRoots) {
245578
+ if (!pathExists19(sourceRoot)) {
245579
+ continue;
245580
+ }
245581
+ const entries = fs58.readdirSync(sourceRoot, { recursive: true, withFileTypes: true });
245582
+ if (entries.some((entry) => entry.isFile() && /\.(?:ts|tsx|js|jsx|java|cs|py|php|go)$/iu.test(entry.name))) {
245583
+ return true;
245584
+ }
245585
+ }
245586
+ return false;
245587
+ }
245588
+ function resolveKind(workspaceRoot, candidate, localProjectKinds) {
245333
245589
  const lowerPath = candidate.path.toLowerCase();
245590
+ const packageJson = readPackageJson(workspaceRoot, candidate.path);
245591
+ const hasRunnableFrontendEvidence = hasRunnableFrontendComponentEvidence(workspaceRoot, candidate.path);
245592
+ const hasPublishSurface = hasPackagePublishSurface(packageJson);
245334
245593
  if (lowerPath.endsWith("/db") || lowerPath.endsWith("/database") || lowerPath.endsWith("/data")) {
245335
245594
  return "data";
245336
245595
  }
245337
245596
  const classification = candidate.architectureRoot?.classification;
245338
245597
  if (classification === "frontend_app") {
245339
- return "frontend";
245598
+ return hasPublishSurface && !hasRunnableFrontendEvidence ? "library" : "frontend";
245340
245599
  }
245341
245600
  if (classification === "backend_app") {
245342
245601
  return "backend";
245343
245602
  }
245603
+ if (hasRunnableFrontendEvidence && localProjectKinds.primaryKind !== "backend" && localProjectKinds.primaryKind !== "service" && localProjectKinds.primaryKind !== "cli") {
245604
+ return "frontend";
245605
+ }
245344
245606
  if (classification === "shared_package") {
245345
245607
  return "library";
245346
245608
  }
245609
+ if (hasPublishSurface && !hasRunnableFrontendEvidence) {
245610
+ return "library";
245611
+ }
245347
245612
  if (localProjectKinds.primaryKind === "service") {
245348
245613
  return "worker";
245349
245614
  }
@@ -245412,10 +245677,11 @@ function classifyGovernanceRole(input2) {
245412
245677
  const scriptText = scripts.join(" ").toLowerCase();
245413
245678
  const dependencyText = [...dependencies, ...devDependencies].join(" ").toLowerCase();
245414
245679
  const hasStrongSupportPath = hasAnyToken(pathText, [
245415
- /(^|\/)(testing|test-plugins|fixtures?|examples?|benchmarks?|smoke)(\/|$)/u,
245680
+ /(^|\/)(testing|test-plugins|cypress-tests|fixtures?|examples?|benchmarks?|smoke)(\/|$)/u,
245416
245681
  /(^|\/)(dev-server|scaffold|scaffolding|generators?|devkit|tooling|tools)(\/|$)/u
245417
245682
  ]);
245418
- const hasPublishSurface = hasObject(packageJson?.exports) || typeof packageJson?.main === "string" || typeof packageJson?.module === "string" || typeof packageJson?.types === "string" || hasObject(packageJson?.publishConfig) || Array.isArray(packageJson?.files);
245683
+ const isPlainResourcesSurface = isUnderJvmResourceRoot4(pathText) && !hasRuntimeSourceFiles(input2.workspaceRoot, input2.candidate.path) && !packageJson && !maven;
245684
+ const hasPublishSurface = hasPackagePublishSurface(packageJson);
245419
245685
  const isPrivate = packageJson?.private === true;
245420
245686
  const hasBin = hasObject(packageJson?.bin) || typeof packageJson?.bin === "string";
245421
245687
  const mavenMetadataText = `${maven?.artifactId ?? ""} ${maven?.name ?? ""}`.toLowerCase();
@@ -245484,7 +245750,7 @@ function classifyGovernanceRole(input2) {
245484
245750
  addEvidence6(evidence, "Package metadata describes development/tooling usage");
245485
245751
  }
245486
245752
  if (hasAnyToken(pathText, [
245487
- /(^|\/)(test|tests|testing|__tests__|fixtures?|examples?|benchmarks?|smoke)(\/|$)/u,
245753
+ /(^|\/)(test|tests|testing|__tests__|cypress|cypress-tests|fixtures?|examples?|benchmarks?|smoke)(\/|$)/u,
245488
245754
  /(^|\/)(dev-server|test-plugins|scaffold|scaffolding|generators?|devkit|tooling|tools)(\/|$)/u
245489
245755
  ])) {
245490
245756
  supportScore += 1;
@@ -245534,6 +245800,17 @@ function classifyGovernanceRole(input2) {
245534
245800
  supportScore += 1;
245535
245801
  addEvidence6(evidence, "Maven POM-only aggregator/packaging module");
245536
245802
  }
245803
+ if (isPlainResourcesSurface) {
245804
+ supportScore += 4;
245805
+ addEvidence6(evidence, "Resources-only surface without runtime source or manifest evidence");
245806
+ }
245807
+ if (isPlainResourcesSurface && input2.kind !== "infrastructure" && input2.stack !== "terraform" && input2.stack !== "ansible") {
245808
+ return {
245809
+ governanceRole: "support",
245810
+ governanceEvidence: uniqueSorted4(evidence),
245811
+ selectedByDefault: false
245812
+ };
245813
+ }
245537
245814
  if (hasMavenDistributionPackagingEvidence && hasAnyToken(mavenMetadataText, [/\b(docs?|documentation|metadata tests?|licenses?|maven plugins?|builds?)\b/u])) {
245538
245815
  supportScore += 3;
245539
245816
  addEvidence6(evidence, "Maven documentation/build/distribution packaging evidence without runtime source");
@@ -245547,9 +245824,9 @@ function classifyGovernanceRole(input2) {
245547
245824
  }
245548
245825
  if (maven && (isMavenPomOnly || hasMavenDistributionPackagingEvidence) && supportScore >= 1) {
245549
245826
  return {
245550
- governanceRole: "ambiguous",
245827
+ governanceRole: "support",
245551
245828
  governanceEvidence: uniqueSorted4(evidence),
245552
- selectedByDefault: true
245829
+ selectedByDefault: false
245553
245830
  };
245554
245831
  }
245555
245832
  if (runtimeScore >= 2) {
@@ -245590,8 +245867,10 @@ function maybeAddAttributedApiAndDb(component, workspaceRoot, componentPath, arc
245590
245867
  }
245591
245868
  function detectComponents(input2) {
245592
245869
  const ignoreMatcher = input2.ignoreMatcher ?? loadArchpilotIgnoreMatcher(input2.workspaceRoot);
245593
- const manifestBackedRoots = new Set(input2.topology.detectedRoots ?? []);
245594
- const rootCandidates = buildRootCandidates(input2).filter((candidate) => !ignoreMatcher.isIgnored(candidate.path)).filter((candidate) => !isIgnoredComponentCandidatePath(candidate.path)).filter((candidate) => {
245870
+ const manifestBackedRoots = new Set(
245871
+ (input2.topology.detectedRoots ?? []).filter((root) => !isUnderJvmResourceRoot4(root))
245872
+ );
245873
+ 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) => {
245595
245874
  if (input2.topology.topology !== "monorepo" || manifestBackedRoots.size === 0) {
245596
245875
  return true;
245597
245876
  }
@@ -245614,7 +245893,7 @@ function detectComponents(input2) {
245614
245893
  }
245615
245894
  const localProjectKinds = input2.runContext?.detectProjectKinds(absoluteRoot) ?? detectProjectKinds(absoluteRoot);
245616
245895
  const stackDetection = input2.runContext?.detectStacks(absoluteRoot) ?? detectStacks(absoluteRoot);
245617
- const kind = resolveKind(candidate, localProjectKinds);
245896
+ const kind = resolveKind(input2.workspaceRoot, candidate, localProjectKinds);
245618
245897
  const stack = resolveStack(kind, stackDetection);
245619
245898
  const evidence = [...candidate.evidence];
245620
245899
  if (candidate.architectureRoot?.classification && candidate.architectureRoot.classification !== "unknown") {
@@ -245851,6 +246130,10 @@ function getSelectedCandidate(detection) {
245851
246130
  function getBackendComponents(detection) {
245852
246131
  return (detection.detectedComponents ?? []).filter((component) => component.kind === "backend" || component.kind === "worker");
245853
246132
  }
246133
+ function getDefaultGovernedBackendComponents(detection) {
246134
+ const components = detection.detectedComponents ?? [];
246135
+ return components.filter((component) => component.kind === "backend" || component.kind === "worker").filter((component) => isDefaultGovernedComponent(component, components));
246136
+ }
245854
246137
  function getFrontendComponents(detection) {
245855
246138
  return (detection.detectedComponents ?? []).filter((component) => component.kind === "frontend");
245856
246139
  }
@@ -245990,7 +246273,8 @@ function resolveProposalComponents(detection) {
245990
246273
  return components.length > 0 ? components : void 0;
245991
246274
  }
245992
246275
  function resolveResourceOwnerComponent(detection) {
245993
- return getBackendComponents(detection).find((component) => component.kind === "backend") ?? getBackendComponents(detection)[0];
246276
+ const backendComponents = getDefaultGovernedBackendComponents(detection);
246277
+ return backendComponents.find((component) => component.kind === "backend") ?? backendComponents[0];
245994
246278
  }
245995
246279
  function resourceIdFor(ownerId, suffix) {
245996
246280
  if (suffix === "api" && /(^|-)api$/u.test(ownerId)) {
@@ -246025,7 +246309,7 @@ function resolveProposalResources(input2) {
246025
246309
  usedIds.add(resource.id);
246026
246310
  resources.push(resource);
246027
246311
  };
246028
- for (const component of getBackendComponents(input2.detection)) {
246312
+ for (const component of getDefaultGovernedBackendComponents(input2.detection)) {
246029
246313
  if (component.apiStyle && component.apiStyle !== "unknown" && component.apiStyle !== "none") {
246030
246314
  addResource({
246031
246315
  id: resourceIdFor(component.id, "api"),