@archpilotlabs/archpilot 0.2.2 → 0.2.4

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 (298) hide show
  1. package/CHANGELOG.md +538 -0
  2. package/README.md +1 -0
  3. package/dist/archpilot-cli.js +850 -159
  4. package/dist/cli/src/archpilot-cli.js +5523 -0
  5. package/dist/cli/src/archpilot-cli.js.map +1 -0
  6. package/dist/core/src/adr/adrLoader.js +97 -0
  7. package/dist/core/src/adr/adrLoader.js.map +1 -0
  8. package/dist/core/src/adr/adrParser.js +77 -0
  9. package/dist/core/src/adr/adrParser.js.map +1 -0
  10. package/dist/core/src/adr/adrTemplate.js +45 -0
  11. package/dist/core/src/adr/adrTemplate.js.map +1 -0
  12. package/dist/core/src/adr/adrTypes.js +3 -0
  13. package/dist/core/src/adr/adrTypes.js.map +1 -0
  14. package/dist/core/src/adr/adrValidation.js +160 -0
  15. package/dist/core/src/adr/adrValidation.js.map +1 -0
  16. package/dist/core/src/adr/index.js +9 -0
  17. package/dist/core/src/adr/index.js.map +1 -0
  18. package/dist/core/src/adrManagement.js +174 -0
  19. package/dist/core/src/adrManagement.js.map +1 -0
  20. package/dist/core/src/adrRequirementStatus.js +62 -0
  21. package/dist/core/src/adrRequirementStatus.js.map +1 -0
  22. package/dist/core/src/adrScaffoldGeneration.js +325 -0
  23. package/dist/core/src/adrScaffoldGeneration.js.map +1 -0
  24. package/dist/core/src/apiDesignAnalysis.js +869 -0
  25. package/dist/core/src/apiDesignAnalysis.js.map +1 -0
  26. package/dist/core/src/applicationLayeringAnalysis.js +920 -0
  27. package/dist/core/src/applicationLayeringAnalysis.js.map +1 -0
  28. package/dist/core/src/applyRulePack.js +117 -0
  29. package/dist/core/src/applyRulePack.js.map +1 -0
  30. package/dist/core/src/architectureBaseline.js +271 -0
  31. package/dist/core/src/architectureBaseline.js.map +1 -0
  32. package/dist/core/src/architectureComponentDiscoveryDefaults.js +139 -0
  33. package/dist/core/src/architectureComponentDiscoveryDefaults.js.map +1 -0
  34. package/dist/core/src/architectureDependencyContext.js +316 -0
  35. package/dist/core/src/architectureDependencyContext.js.map +1 -0
  36. package/dist/core/src/architectureDriftDetection.js +96 -0
  37. package/dist/core/src/architectureDriftDetection.js.map +1 -0
  38. package/dist/core/src/architectureDriftTimeline.js +221 -0
  39. package/dist/core/src/architectureDriftTimeline.js.map +1 -0
  40. package/dist/core/src/architectureGovernanceBaseline.js +469 -0
  41. package/dist/core/src/architectureGovernanceBaseline.js.map +1 -0
  42. package/dist/core/src/architectureHealthHistory.js +208 -0
  43. package/dist/core/src/architectureHealthHistory.js.map +1 -0
  44. package/dist/core/src/architectureHealthScore.js +657 -0
  45. package/dist/core/src/architectureHealthScore.js.map +1 -0
  46. package/dist/core/src/architectureInit.js +826 -0
  47. package/dist/core/src/architectureInit.js.map +1 -0
  48. package/dist/core/src/architectureMap.js +727 -0
  49. package/dist/core/src/architectureMap.js.map +1 -0
  50. package/dist/core/src/architectureMigrationPreview.js +467 -0
  51. package/dist/core/src/architectureMigrationPreview.js.map +1 -0
  52. package/dist/core/src/architectureModelRefresh.js +209 -0
  53. package/dist/core/src/architectureModelRefresh.js.map +1 -0
  54. package/dist/core/src/architectureReportWorkflow.js +139 -0
  55. package/dist/core/src/architectureReportWorkflow.js.map +1 -0
  56. package/dist/core/src/architectureValidation.js +3879 -0
  57. package/dist/core/src/architectureValidation.js.map +1 -0
  58. package/dist/core/src/architectureWorkspaceModel.js +166 -0
  59. package/dist/core/src/architectureWorkspaceModel.js.map +1 -0
  60. package/dist/core/src/authorizationTenantAnalysis.js +652 -0
  61. package/dist/core/src/authorizationTenantAnalysis.js.map +1 -0
  62. package/dist/core/src/bootstrapArchitectureConfig.js +150 -0
  63. package/dist/core/src/bootstrapArchitectureConfig.js.map +1 -0
  64. package/dist/core/src/changeRisk/changeRiskAssessment.js +251 -0
  65. package/dist/core/src/changeRisk/changeRiskAssessment.js.map +1 -0
  66. package/dist/core/src/changeRisk/changeRiskTypes.js +3 -0
  67. package/dist/core/src/changeRisk/changeRiskTypes.js.map +1 -0
  68. package/dist/core/src/changeRisk/index.js +6 -0
  69. package/dist/core/src/changeRisk/index.js.map +1 -0
  70. package/dist/core/src/ci/githubInlineAnnotations.js +245 -0
  71. package/dist/core/src/ci/githubInlineAnnotations.js.map +1 -0
  72. package/dist/core/src/ci/githubPrCommentAdapter.js +232 -0
  73. package/dist/core/src/ci/githubPrCommentAdapter.js.map +1 -0
  74. package/dist/core/src/ciWorkflowTemplates.js +1042 -0
  75. package/dist/core/src/ciWorkflowTemplates.js.map +1 -0
  76. package/dist/core/src/compliance/complianceExportBuilder.js +122 -0
  77. package/dist/core/src/compliance/complianceExportBuilder.js.map +1 -0
  78. package/dist/core/src/compliance/complianceExportTypes.js +3 -0
  79. package/dist/core/src/compliance/complianceExportTypes.js.map +1 -0
  80. package/dist/core/src/compliance/complianceExportWriter.js +48 -0
  81. package/dist/core/src/compliance/complianceExportWriter.js.map +1 -0
  82. package/dist/core/src/compliance/complianceRulePackResolver.js +62 -0
  83. package/dist/core/src/compliance/complianceRulePackResolver.js.map +1 -0
  84. package/dist/core/src/config/index.js +17 -0
  85. package/dist/core/src/config/index.js.map +1 -0
  86. package/dist/core/src/config/projectConfig.js +224 -0
  87. package/dist/core/src/config/projectConfig.js.map +1 -0
  88. package/dist/core/src/config/projectIdentity.js +160 -0
  89. package/dist/core/src/config/projectIdentity.js.map +1 -0
  90. package/dist/core/src/dataQueryRiskDetection.js +1203 -0
  91. package/dist/core/src/dataQueryRiskDetection.js.map +1 -0
  92. package/dist/core/src/dependencyValidation.js +2557 -0
  93. package/dist/core/src/dependencyValidation.js.map +1 -0
  94. package/dist/core/src/discoverAdrs.js +15 -0
  95. package/dist/core/src/discoverAdrs.js.map +1 -0
  96. package/dist/core/src/drift/driftComparator.js +49 -0
  97. package/dist/core/src/drift/driftComparator.js.map +1 -0
  98. package/dist/core/src/drift/driftSnapshotLoader.js +136 -0
  99. package/dist/core/src/drift/driftSnapshotLoader.js.map +1 -0
  100. package/dist/core/src/drift/driftSnapshotTypes.js +3 -0
  101. package/dist/core/src/drift/driftSnapshotTypes.js.map +1 -0
  102. package/dist/core/src/drift/driftSnapshotWriter.js +48 -0
  103. package/dist/core/src/drift/driftSnapshotWriter.js.map +1 -0
  104. package/dist/core/src/drift/index.js +6 -0
  105. package/dist/core/src/drift/index.js.map +1 -0
  106. package/dist/core/src/eventArchitectureAnalysis.js +925 -0
  107. package/dist/core/src/eventArchitectureAnalysis.js.map +1 -0
  108. package/dist/core/src/findingTargetResolution.js +117 -0
  109. package/dist/core/src/findingTargetResolution.js.map +1 -0
  110. package/dist/core/src/generateArchitectureDiagrams.js +57 -0
  111. package/dist/core/src/generateArchitectureDiagrams.js.map +1 -0
  112. package/dist/core/src/generateImpactAnalysis.js +366 -0
  113. package/dist/core/src/generateImpactAnalysis.js.map +1 -0
  114. package/dist/core/src/generateOnboardingDocs.js +262 -0
  115. package/dist/core/src/generateOnboardingDocs.js.map +1 -0
  116. package/dist/core/src/governance/cloudConnection.js +203 -0
  117. package/dist/core/src/governance/cloudConnection.js.map +1 -0
  118. package/dist/core/src/governance/governanceContracts.js +129 -0
  119. package/dist/core/src/governance/governanceContracts.js.map +1 -0
  120. package/dist/core/src/governance/governanceGitMetadata.js +78 -0
  121. package/dist/core/src/governance/governanceGitMetadata.js.map +1 -0
  122. package/dist/core/src/governance/governanceUploadClient.js +119 -0
  123. package/dist/core/src/governance/governanceUploadClient.js.map +1 -0
  124. package/dist/core/src/governance/governanceUploadLimitErrorFormatting.js +155 -0
  125. package/dist/core/src/governance/governanceUploadLimitErrorFormatting.js.map +1 -0
  126. package/dist/core/src/governance/governanceUploadPayload.js +439 -0
  127. package/dist/core/src/governance/governanceUploadPayload.js.map +1 -0
  128. package/dist/core/src/governance/runGovernanceUpload.js +103 -0
  129. package/dist/core/src/governance/runGovernanceUpload.js.map +1 -0
  130. package/dist/core/src/impactAnalysisEngine.js +376 -0
  131. package/dist/core/src/impactAnalysisEngine.js.map +1 -0
  132. package/dist/core/src/initializationState.js +99 -0
  133. package/dist/core/src/initializationState.js.map +1 -0
  134. package/dist/core/src/managedArtifacts.js +151 -0
  135. package/dist/core/src/managedArtifacts.js.map +1 -0
  136. package/dist/core/src/moduleContractValidation.js +266 -0
  137. package/dist/core/src/moduleContractValidation.js.map +1 -0
  138. package/dist/core/src/moduleContractsGenerator.js +337 -0
  139. package/dist/core/src/moduleContractsGenerator.js.map +1 -0
  140. package/dist/core/src/moduleDiscovery.js +416 -0
  141. package/dist/core/src/moduleDiscovery.js.map +1 -0
  142. package/dist/core/src/moduleScope.js +426 -0
  143. package/dist/core/src/moduleScope.js.map +1 -0
  144. package/dist/core/src/onboardingGuidance.js +74 -0
  145. package/dist/core/src/onboardingGuidance.js.map +1 -0
  146. package/dist/core/src/operationalLogging.js +7 -0
  147. package/dist/core/src/operationalLogging.js.map +1 -0
  148. package/dist/core/src/packageVersion.js +52 -0
  149. package/dist/core/src/packageVersion.js.map +1 -0
  150. package/dist/core/src/policy/effectivePolicyResolver.js +91 -0
  151. package/dist/core/src/policy/effectivePolicyResolver.js.map +1 -0
  152. package/dist/core/src/policy/exceptionLoader.js +285 -0
  153. package/dist/core/src/policy/exceptionLoader.js.map +1 -0
  154. package/dist/core/src/policy/remotePolicyLoader.js +227 -0
  155. package/dist/core/src/policy/remotePolicyLoader.js.map +1 -0
  156. package/dist/core/src/policy/remotePolicyTypes.js +3 -0
  157. package/dist/core/src/policy/remotePolicyTypes.js.map +1 -0
  158. package/dist/core/src/policy/riskPolicyConfig.js +206 -0
  159. package/dist/core/src/policy/riskPolicyConfig.js.map +1 -0
  160. package/dist/core/src/policy/riskPolicyEnforcement.js +203 -0
  161. package/dist/core/src/policy/riskPolicyEnforcement.js.map +1 -0
  162. package/dist/core/src/policy/riskPolicyExitCode.js +16 -0
  163. package/dist/core/src/policy/riskPolicyExitCode.js.map +1 -0
  164. package/dist/core/src/policy/riskPolicyInitializer.js +90 -0
  165. package/dist/core/src/policy/riskPolicyInitializer.js.map +1 -0
  166. package/dist/core/src/quickFix/quickFixEngine.js +132 -0
  167. package/dist/core/src/quickFix/quickFixEngine.js.map +1 -0
  168. package/dist/core/src/quickFix/quickFixMessaging.js +15 -0
  169. package/dist/core/src/quickFix/quickFixMessaging.js.map +1 -0
  170. package/dist/core/src/quickFix/quickFixProviders.js +87 -0
  171. package/dist/core/src/quickFix/quickFixProviders.js.map +1 -0
  172. package/dist/core/src/quickFix/quickFixTypes.js +3 -0
  173. package/dist/core/src/quickFix/quickFixTypes.js.map +1 -0
  174. package/dist/core/src/remediation/fileHelpers.js +86 -0
  175. package/dist/core/src/remediation/fileHelpers.js.map +1 -0
  176. package/dist/core/src/remediation/fixRegistry.js +645 -0
  177. package/dist/core/src/remediation/fixRegistry.js.map +1 -0
  178. package/dist/core/src/remediation/index.js +8 -0
  179. package/dist/core/src/remediation/index.js.map +1 -0
  180. package/dist/core/src/remediation/remediationEngine.js +207 -0
  181. package/dist/core/src/remediation/remediationEngine.js.map +1 -0
  182. package/dist/core/src/reporting/adrReporter.js +59 -0
  183. package/dist/core/src/reporting/adrReporter.js.map +1 -0
  184. package/dist/core/src/reporting/architectureBaselineReporter.js +64 -0
  185. package/dist/core/src/reporting/architectureBaselineReporter.js.map +1 -0
  186. package/dist/core/src/reporting/architectureDiagramReporter.js +148 -0
  187. package/dist/core/src/reporting/architectureDiagramReporter.js.map +1 -0
  188. package/dist/core/src/reporting/architectureDriftTimelineReporter.js +44 -0
  189. package/dist/core/src/reporting/architectureDriftTimelineReporter.js.map +1 -0
  190. package/dist/core/src/reporting/architectureHealthHistoryReporter.js +51 -0
  191. package/dist/core/src/reporting/architectureHealthHistoryReporter.js.map +1 -0
  192. package/dist/core/src/reporting/architectureMapReporter.js +228 -0
  193. package/dist/core/src/reporting/architectureMapReporter.js.map +1 -0
  194. package/dist/core/src/reporting/architecturePrCommentReporter.js +324 -0
  195. package/dist/core/src/reporting/architecturePrCommentReporter.js.map +1 -0
  196. package/dist/core/src/reporting/architecturePrReviewReporter.js +389 -0
  197. package/dist/core/src/reporting/architecturePrReviewReporter.js.map +1 -0
  198. package/dist/core/src/reporting/architectureReportArtifacts.js +166 -0
  199. package/dist/core/src/reporting/architectureReportArtifacts.js.map +1 -0
  200. package/dist/core/src/reporting/architectureReviewReportGenerator.js +382 -0
  201. package/dist/core/src/reporting/architectureReviewReportGenerator.js.map +1 -0
  202. package/dist/core/src/reporting/architectureReviewReporter.js +1633 -0
  203. package/dist/core/src/reporting/architectureReviewReporter.js.map +1 -0
  204. package/dist/core/src/reporting/architectureRiskAssessment.js +101 -0
  205. package/dist/core/src/reporting/architectureRiskAssessment.js.map +1 -0
  206. package/dist/core/src/reporting/architectureScoreBadge.js +177 -0
  207. package/dist/core/src/reporting/architectureScoreBadge.js.map +1 -0
  208. package/dist/core/src/reporting/architectureSupplementalReporters.js +124 -0
  209. package/dist/core/src/reporting/architectureSupplementalReporters.js.map +1 -0
  210. package/dist/core/src/reporting/changeRiskAssessment.js +6 -0
  211. package/dist/core/src/reporting/changeRiskAssessment.js.map +1 -0
  212. package/dist/core/src/reporting/changeRiskTypes.js +3 -0
  213. package/dist/core/src/reporting/changeRiskTypes.js.map +1 -0
  214. package/dist/core/src/reporting/impactAnalysisReporter.js +111 -0
  215. package/dist/core/src/reporting/impactAnalysisReporter.js.map +1 -0
  216. package/dist/core/src/reporting/onboardingDocsReporter.js +113 -0
  217. package/dist/core/src/reporting/onboardingDocsReporter.js.map +1 -0
  218. package/dist/core/src/reporting/rulePackReporter.js +61 -0
  219. package/dist/core/src/reporting/rulePackReporter.js.map +1 -0
  220. package/dist/core/src/reporting/safetyControlsDetection.js +343 -0
  221. package/dist/core/src/reporting/safetyControlsDetection.js.map +1 -0
  222. package/dist/core/src/resolveRuleAdrs.js +31 -0
  223. package/dist/core/src/resolveRuleAdrs.js.map +1 -0
  224. package/dist/core/src/reviewGenerationWorkflow.js +220 -0
  225. package/dist/core/src/reviewGenerationWorkflow.js.map +1 -0
  226. package/dist/core/src/rulePacks/index.js +17 -0
  227. package/dist/core/src/rulePacks/index.js.map +1 -0
  228. package/dist/core/src/rulePacks/layeredMonolithRulePack.js +45 -0
  229. package/dist/core/src/rulePacks/layeredMonolithRulePack.js.map +1 -0
  230. package/dist/core/src/rulePacks/modularMonolithRulePack.js +41 -0
  231. package/dist/core/src/rulePacks/modularMonolithRulePack.js.map +1 -0
  232. package/dist/core/src/rulePacks/types.js +3 -0
  233. package/dist/core/src/rulePacks/types.js.map +1 -0
  234. package/dist/core/src/setupNextSteps.js +939 -0
  235. package/dist/core/src/setupNextSteps.js.map +1 -0
  236. package/dist/core/src/setupRefresh.js +152 -0
  237. package/dist/core/src/setupRefresh.js.map +1 -0
  238. package/dist/core/src/smartInit/apiDbHintDetection.js +836 -0
  239. package/dist/core/src/smartInit/apiDbHintDetection.js.map +1 -0
  240. package/dist/core/src/smartInit/architectureProposalBuilder.js +1215 -0
  241. package/dist/core/src/smartInit/architectureProposalBuilder.js.map +1 -0
  242. package/dist/core/src/smartInit/architectureStyleDetection.js +472 -0
  243. package/dist/core/src/smartInit/architectureStyleDetection.js.map +1 -0
  244. package/dist/core/src/smartInit/archpilotIgnore.js +139 -0
  245. package/dist/core/src/smartInit/archpilotIgnore.js.map +1 -0
  246. package/dist/core/src/smartInit/componentDetection.js +1084 -0
  247. package/dist/core/src/smartInit/componentDetection.js.map +1 -0
  248. package/dist/core/src/smartInit/implementationProfileResolution.js +53 -0
  249. package/dist/core/src/smartInit/implementationProfileResolution.js.map +1 -0
  250. package/dist/core/src/smartInit/index.js +31 -0
  251. package/dist/core/src/smartInit/index.js.map +1 -0
  252. package/dist/core/src/smartInit/moduleDetection.js +982 -0
  253. package/dist/core/src/smartInit/moduleDetection.js.map +1 -0
  254. package/dist/core/src/smartInit/projectKindDetection.js +437 -0
  255. package/dist/core/src/smartInit/projectKindDetection.js.map +1 -0
  256. package/dist/core/src/smartInit/repoTopologyDetection.js +470 -0
  257. package/dist/core/src/smartInit/repoTopologyDetection.js.map +1 -0
  258. package/dist/core/src/smartInit/runContext.js +112 -0
  259. package/dist/core/src/smartInit/runContext.js.map +1 -0
  260. package/dist/core/src/smartInit/smartInitEngine.js +94 -0
  261. package/dist/core/src/smartInit/smartInitEngine.js.map +1 -0
  262. package/dist/core/src/smartInit/stackDetection.js +503 -0
  263. package/dist/core/src/smartInit/stackDetection.js.map +1 -0
  264. package/dist/core/src/smartInit/toolingHintDetection.js +345 -0
  265. package/dist/core/src/smartInit/toolingHintDetection.js.map +1 -0
  266. package/dist/core/src/sourceScopeClassification.js +83 -0
  267. package/dist/core/src/sourceScopeClassification.js.map +1 -0
  268. package/dist/core/src/stackAdapters.js +2475 -0
  269. package/dist/core/src/stackAdapters.js.map +1 -0
  270. package/dist/core/src/stackMetadata.js +157 -0
  271. package/dist/core/src/stackMetadata.js.map +1 -0
  272. package/dist/core/src/suppressions/index.js +3 -0
  273. package/dist/core/src/suppressions/index.js.map +1 -0
  274. package/dist/core/src/suppressions/suppressionReporter.js +38 -0
  275. package/dist/core/src/suppressions/suppressionReporter.js.map +1 -0
  276. package/dist/core/src/suppressions/suppressionTypes.js +3 -0
  277. package/dist/core/src/suppressions/suppressionTypes.js.map +1 -0
  278. package/dist/core/src/suppressions/suppressionValidator.js +119 -0
  279. package/dist/core/src/suppressions/suppressionValidator.js.map +1 -0
  280. package/dist/core/src/transactionDomainAnalysis.js +1416 -0
  281. package/dist/core/src/transactionDomainAnalysis.js.map +1 -0
  282. package/dist/core/src/validation/changedFilesResolver.js +165 -0
  283. package/dist/core/src/validation/changedFilesResolver.js.map +1 -0
  284. package/dist/core/src/validationProfiling.js +33 -0
  285. package/dist/core/src/validationProfiling.js.map +1 -0
  286. package/dist/core/src/validationRuleExplanations.js +69 -0
  287. package/dist/core/src/validationRuleExplanations.js.map +1 -0
  288. package/dist/core/src/validationSourceInventory.js +200 -0
  289. package/dist/core/src/validationSourceInventory.js.map +1 -0
  290. package/dist/core/src/validationSuppressions.js +231 -0
  291. package/dist/core/src/validationSuppressions.js.map +1 -0
  292. package/dist/core/src/validationTypeScriptAstCache.js +82 -0
  293. package/dist/core/src/validationTypeScriptAstCache.js.map +1 -0
  294. package/dist/core/src/validationWorkflow.js +222 -0
  295. package/dist/core/src/validationWorkflow.js.map +1 -0
  296. package/dist/core/src/workspaceRoot.js +68 -0
  297. package/dist/core/src/workspaceRoot.js.map +1 -0
  298. package/package.json +3 -2
@@ -13660,11 +13660,11 @@ ${lanes.join("\n")}
13660
13660
  return toComponents;
13661
13661
  }
13662
13662
  const components = toComponents.slice(start);
13663
- const relative17 = [];
13663
+ const relative18 = [];
13664
13664
  for (; start < fromComponents.length; start++) {
13665
- relative17.push("..");
13665
+ relative18.push("..");
13666
13666
  }
13667
- return ["", ...relative17, ...components];
13667
+ return ["", ...relative18, ...components];
13668
13668
  }
13669
13669
  function getRelativePathFromDirectory(fromDirectory, to, getCanonicalFileNameOrIgnoreCase) {
13670
13670
  Debug.assert(getRootLength(fromDirectory) > 0 === getRootLength(to) > 0, "Paths must either both be absolute or both be relative");
@@ -52233,11 +52233,11 @@ ${lanes.join("\n")}
52233
52233
  if (i < rootLength) {
52234
52234
  return void 0;
52235
52235
  }
52236
- const sep = directory.lastIndexOf(directorySeparator, i - 1);
52237
- if (sep === -1) {
52236
+ const sep2 = directory.lastIndexOf(directorySeparator, i - 1);
52237
+ if (sep2 === -1) {
52238
52238
  return void 0;
52239
52239
  }
52240
- return directory.substr(0, Math.max(sep, rootLength));
52240
+ return directory.substr(0, Math.max(sep2, rootLength));
52241
52241
  }
52242
52242
  }
52243
52243
  }
@@ -58143,9 +58143,9 @@ ${lanes.join("\n")}
58143
58143
  if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) {
58144
58144
  return;
58145
58145
  }
58146
- const relative17 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
58146
+ const relative18 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
58147
58147
  for (const symlinkDirectory of symlinkDirectories) {
58148
- const option = resolvePath(symlinkDirectory, relative17);
58148
+ const option = resolvePath(symlinkDirectory, relative18);
58149
58149
  const result2 = cb(option, target === referenceRedirect);
58150
58150
  shouldFilterIgnoredPaths = true;
58151
58151
  if (result2) return result2;
@@ -127982,7 +127982,7 @@ ${lanes.join("\n")}
127982
127982
  }
127983
127983
  }
127984
127984
  function createImportCallExpressionAMD(arg, containsLexicalThis) {
127985
- const resolve9 = factory2.createUniqueName("resolve");
127985
+ const resolve10 = factory2.createUniqueName("resolve");
127986
127986
  const reject = factory2.createUniqueName("reject");
127987
127987
  const parameters = [
127988
127988
  factory2.createParameterDeclaration(
@@ -127991,7 +127991,7 @@ ${lanes.join("\n")}
127991
127991
  /*dotDotDotToken*/
127992
127992
  void 0,
127993
127993
  /*name*/
127994
- resolve9
127994
+ resolve10
127995
127995
  ),
127996
127996
  factory2.createParameterDeclaration(
127997
127997
  /*modifiers*/
@@ -128008,7 +128008,7 @@ ${lanes.join("\n")}
128008
128008
  factory2.createIdentifier("require"),
128009
128009
  /*typeArguments*/
128010
128010
  void 0,
128011
- [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve9, reject]
128011
+ [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve10, reject]
128012
128012
  )
128013
128013
  )
128014
128014
  ]);
@@ -214726,8 +214726,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
214726
214726
  installPackage(options) {
214727
214727
  this.packageInstallId++;
214728
214728
  const request3 = { kind: "installPackage", ...options, id: this.packageInstallId };
214729
- const promise = new Promise((resolve9, reject) => {
214730
- (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve9, reject });
214729
+ const promise = new Promise((resolve10, reject) => {
214730
+ (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve10, reject });
214731
214731
  });
214732
214732
  this.installer.send(request3);
214733
214733
  return promise;
@@ -215175,9 +215175,9 @@ function pathHasFileExtension(value) {
215175
215175
  function isRelativeImport(importSpecifier) {
215176
215176
  return importSpecifier === "." || importSpecifier === ".." || importSpecifier.startsWith("./") || importSpecifier.startsWith("../");
215177
215177
  }
215178
- function isPathInsideOrEqual(childPath, parentPath) {
215179
- const child = normalizePath2(childPath).toLowerCase();
215180
- const parent = normalizePath2(parentPath).toLowerCase();
215178
+ function isNormalizedPathInsideOrEqual(normalizedChildPath, normalizedParentPath) {
215179
+ const child = normalizedChildPath.toLowerCase();
215180
+ const parent = normalizedParentPath.toLowerCase();
215181
215181
  return child === parent || child.startsWith(`${parent}/`);
215182
215182
  }
215183
215183
  function toEndpoint(candidate) {
@@ -215196,38 +215196,43 @@ function compareCandidates(left, right) {
215196
215196
  }
215197
215197
  return left.component.id.localeCompare(right.component.id);
215198
215198
  }
215199
- function modulePathMatchScore(inputPath, modulePath) {
215200
- const normalizedModulePath = normalizePath2(modulePath);
215199
+ function normalizedModulePathMatchScore(normalizedInputPath, normalizedModulePath) {
215201
215200
  if (pathHasFileExtension(normalizedModulePath)) {
215202
- return isPathInsideOrEqual(inputPath, normalizedModulePath) || isPathInsideOrEqual(normalizedModulePath, inputPath) ? normalizedModulePath.length + 1e3 : void 0;
215201
+ return isNormalizedPathInsideOrEqual(normalizedInputPath, normalizedModulePath) || isNormalizedPathInsideOrEqual(normalizedModulePath, normalizedInputPath) ? normalizedModulePath.length + 1e3 : void 0;
215203
215202
  }
215204
- return isPathInsideOrEqual(inputPath, normalizedModulePath) ? normalizedModulePath.length + 1e3 : void 0;
215203
+ return isNormalizedPathInsideOrEqual(normalizedInputPath, normalizedModulePath) ? normalizedModulePath.length + 1e3 : void 0;
215204
+ }
215205
+ function modulePathMatchScore(inputPath, modulePath) {
215206
+ return normalizedModulePathMatchScore(normalizePath2(inputPath), normalizePath2(modulePath));
215205
215207
  }
215206
215208
  function findComponentForPath(components, inputPath) {
215207
215209
  const normalizedInputPath = normalizePath2(inputPath);
215208
215210
  const candidates = [];
215209
215211
  for (const component of components) {
215210
- for (const [moduleId, moduleReference] of Object.entries(component.modules)) {
215211
- if (!moduleReference.path) {
215212
+ for (const moduleReference of component.modules) {
215213
+ if (!moduleReference.normalizedPath) {
215212
215214
  continue;
215213
215215
  }
215214
- const score = modulePathMatchScore(normalizedInputPath, moduleReference.path);
215216
+ const score = normalizedModulePathMatchScore(
215217
+ normalizedInputPath,
215218
+ moduleReference.normalizedPath
215219
+ );
215215
215220
  if (score !== void 0) {
215216
215221
  candidates.push({
215217
- component,
215218
- moduleId,
215222
+ component: component.component,
215223
+ moduleId: moduleReference.moduleId,
215219
215224
  path: moduleReference.path,
215220
215225
  ownership: "module-path",
215221
215226
  score
215222
215227
  });
215223
215228
  }
215224
215229
  }
215225
- if (component.path && isPathInsideOrEqual(normalizedInputPath, component.path)) {
215230
+ if (component.normalizedPath && isNormalizedPathInsideOrEqual(normalizedInputPath, component.normalizedPath)) {
215226
215231
  candidates.push({
215227
- component,
215228
- path: component.path,
215232
+ component: component.component,
215233
+ path: component.component.path,
215229
215234
  ownership: "component-path",
215230
- score: normalizePath2(component.path).length
215235
+ score: component.normalizedPath.length
215231
215236
  });
215232
215237
  }
215233
215238
  }
@@ -215238,19 +215243,20 @@ function findComponentForModuleSpecifier(components, importSpecifier) {
215238
215243
  const normalizedSegments = normalizedImport.split("/").filter((segment) => segment.length > 0);
215239
215244
  const candidates = [];
215240
215245
  for (const component of components) {
215241
- for (const [moduleId, moduleReference] of Object.entries(component.modules)) {
215246
+ for (const moduleReference of component.modules) {
215247
+ const moduleId = moduleReference.moduleId;
215242
215248
  if (normalizedImport === moduleId || normalizedImport.startsWith(`${moduleId}/`)) {
215243
215249
  candidates.push({
215244
- component,
215250
+ component: component.component,
215245
215251
  moduleId,
215246
215252
  ...moduleReference.path ? { path: moduleReference.path } : {},
215247
215253
  ownership: moduleReference.path ? "module-path" : "component-path",
215248
215254
  score: moduleId.length + 500
215249
215255
  });
215250
215256
  }
215251
- if (component.id === VIRTUAL_WORKSPACE_COMPONENT_ID && normalizedSegments.includes(moduleId)) {
215257
+ if (component.component.id === VIRTUAL_WORKSPACE_COMPONENT_ID && normalizedSegments.includes(moduleId)) {
215252
215258
  candidates.push({
215253
- component,
215259
+ component: component.component,
215254
215260
  moduleId,
215255
215261
  ...moduleReference.path ? { path: moduleReference.path } : {},
215256
215262
  ownership: "virtual-workspace",
@@ -215258,20 +215264,20 @@ function findComponentForModuleSpecifier(components, importSpecifier) {
215258
215264
  });
215259
215265
  }
215260
215266
  }
215261
- if (component.path && isPathInsideOrEqual(normalizedImport, component.path)) {
215267
+ if (component.normalizedPath && isNormalizedPathInsideOrEqual(normalizedImport, component.normalizedPath)) {
215262
215268
  candidates.push({
215263
- component,
215264
- path: component.path,
215269
+ component: component.component,
215270
+ path: component.component.path,
215265
215271
  ownership: "component-path",
215266
- score: normalizePath2(component.path).length
215272
+ score: component.normalizedPath.length
215267
215273
  });
215268
215274
  }
215269
- if (normalizedImport === component.id || normalizedImport.startsWith(`${component.id}/`)) {
215275
+ if (normalizedImport === component.component.id || normalizedImport.startsWith(`${component.component.id}/`)) {
215270
215276
  candidates.push({
215271
- component,
215272
- ...component.path ? { path: component.path } : {},
215273
- ownership: component.path ? "component-path" : "virtual-workspace",
215274
- score: component.id.length
215277
+ component: component.component,
215278
+ ...component.component.path ? { path: component.component.path } : {},
215279
+ ownership: component.component.path ? "component-path" : "virtual-workspace",
215280
+ score: component.component.id.length
215275
215281
  });
215276
215282
  }
215277
215283
  }
@@ -215315,12 +215321,12 @@ function resolveSourceCandidate(contract, components, sourceFile) {
215315
215321
  return directMatch;
215316
215322
  }
215317
215323
  const virtualComponent = components.find(
215318
- (component) => component.id === VIRTUAL_WORKSPACE_COMPONENT_ID
215319
- );
215324
+ (component) => component.component.id === VIRTUAL_WORKSPACE_COMPONENT_ID
215325
+ )?.component;
215320
215326
  if (virtualComponent) {
215321
215327
  return resolveLegacyVirtualSource(contract, sourceFile, virtualComponent);
215322
215328
  }
215323
- const fallback = [...components].sort((left, right) => left.id.localeCompare(right.id))[0];
215329
+ const fallback = [...components].map((component) => component.component).sort((left, right) => left.id.localeCompare(right.id))[0];
215324
215330
  if (fallback) {
215325
215331
  return {
215326
215332
  component: fallback,
@@ -215331,7 +215337,7 @@ function resolveSourceCandidate(contract, components, sourceFile) {
215331
215337
  }
215332
215338
  throw new Error("Architecture dependency context requires at least one normalized component.");
215333
215339
  }
215334
- function resolveTargetCandidate(components, sourceFile, importSpecifier) {
215340
+ function resolveTargetCandidate(contract, components, sourceFile, importSpecifier) {
215335
215341
  if (isRelativeImport(importSpecifier)) {
215336
215342
  const resolvedTargetPath = resolveRelativeImportPath(sourceFile, importSpecifier);
215337
215343
  return {
@@ -215340,7 +215346,8 @@ function resolveTargetCandidate(components, sourceFile, importSpecifier) {
215340
215346
  };
215341
215347
  }
215342
215348
  const normalizedImport = normalizeImportPath(importSpecifier);
215343
- if (normalizedImport.startsWith("src/") || normalizedImport.startsWith("apps/") || normalizedImport.startsWith("services/") || normalizedImport.startsWith("packages/") || normalizedImport.startsWith("libs/") || normalizedImport.startsWith("libraries/") || normalizedImport.startsWith("workers/")) {
215349
+ const normalizedModulesRoot = normalizePath2(resolveModulesRootFromContract(contract));
215350
+ if (normalizedModulesRoot.length > 0 && normalizedImport.startsWith(`${normalizedModulesRoot}/`) || normalizedImport.startsWith("src/") || normalizedImport.startsWith("app/") || normalizedImport.startsWith("apps/") || normalizedImport.startsWith("services/") || normalizedImport.startsWith("packages/") || normalizedImport.startsWith("libs/") || normalizedImport.startsWith("libraries/") || normalizedImport.startsWith("workers/")) {
215344
215351
  return {
215345
215352
  candidate: findComponentForPath(components, normalizedImport),
215346
215353
  resolvedTargetPath: normalizedImport
@@ -215352,20 +215359,28 @@ function resolveTargetCandidate(components, sourceFile, importSpecifier) {
215352
215359
  }
215353
215360
  return {};
215354
215361
  }
215355
- function resolveDependencyContext(contract, input2) {
215356
- const model = normalizeArchitectureWorkspaceModel(contract);
215357
- const sourceCandidate = resolveSourceCandidate(contract, model.components, input2.sourceFile);
215362
+ function prepareComponentReferences(components) {
215363
+ return components.map((component) => ({
215364
+ component,
215365
+ ...component.path ? { normalizedPath: normalizePath2(component.path) } : {},
215366
+ modules: Object.entries(component.modules).map(([moduleId, moduleReference]) => ({
215367
+ moduleId,
215368
+ ...moduleReference.path ? {
215369
+ path: moduleReference.path,
215370
+ normalizedPath: normalizePath2(moduleReference.path)
215371
+ } : {}
215372
+ }))
215373
+ }));
215374
+ }
215375
+ function resolveDependencyContextWithPreparedComponents(contract, components, input2) {
215376
+ const sourceCandidate = resolveSourceCandidate(contract, components, input2.sourceFile);
215358
215377
  const { candidate: resolvedTargetCandidate, resolvedTargetPath } = resolveTargetCandidate(
215359
- model.components,
215378
+ contract,
215379
+ components,
215360
215380
  input2.sourceFile,
215361
215381
  input2.importSpecifier
215362
215382
  );
215363
- const targetCandidate = resolvedTargetCandidate ?? (resolvedTargetPath ? {
215364
- ...sourceCandidate,
215365
- path: resolvedTargetPath,
215366
- ownership: sourceCandidate.ownership,
215367
- score: 0
215368
- } : void 0);
215383
+ const targetCandidate = resolvedTargetCandidate ?? (resolvedTargetPath ? resolveSourceCandidate(contract, components, resolvedTargetPath) : void 0);
215369
215384
  if (!targetCandidate) {
215370
215385
  return {
215371
215386
  dependencyType: "external",
@@ -215386,6 +215401,19 @@ function resolveDependencyContext(contract, input2) {
215386
215401
  isExternal: false
215387
215402
  };
215388
215403
  }
215404
+ function createArchitectureDependencyContextResolver(contract) {
215405
+ const model = normalizeArchitectureWorkspaceModel(contract);
215406
+ const components = prepareComponentReferences(model.components);
215407
+ return {
215408
+ contract,
215409
+ model,
215410
+ resolve: (input2) => resolveDependencyContextWithPreparedComponents(
215411
+ contract,
215412
+ components,
215413
+ input2
215414
+ )
215415
+ };
215416
+ }
215389
215417
  var path6;
215390
215418
  var init_architectureDependencyContext = __esm({
215391
215419
  "../core/src/architectureDependencyContext.ts"() {
@@ -215416,6 +215444,8 @@ function classifyValidationSourceScope(relativePath) {
215416
215444
  const isFixture = hasPathSegment(normalized, /^(?:fixtures?|__fixtures__)$/u);
215417
215445
  const isTestPlugin = hasPathSegment(normalized, /^(?:test-plugins?|testing-plugins?)$/u);
215418
215446
  const isExamplePlugin = hasPathSegment(normalized, /^example-plugins?$/u) || hasTopLevelPathSegment(normalized, /^examples?$/u);
215447
+ const isMavenIntegrationTestModule = hasTopLevelPathSegment(normalized, /^[a-z0-9_.-]+-integration-tests?$/u) || hasTopLevelPathSegment(normalized, /^[a-z0-9_.-]+-it$/u);
215448
+ const isMavenExampleModule = hasTopLevelPathSegment(normalized, /^[a-z0-9_.-]+-examples?$/u);
215419
215449
  const isGenerated = hasPathSegment(normalized, /^(?:generated|__generated__|gen|templates?)$/u) || /\.(?:generated|gen|g)\.(?:ts|tsx|js|jsx|java|cs|py|php|go)$/u.test(fileName) || /\.d\.ts$/u.test(fileName);
215420
215450
  const isMigration = hasPathSegment(normalized, /^(?:migrations?|schema-migrations?|data-migrations|migration-utils?)$/u);
215421
215451
  const isCliTooling = hasPathSegment(normalized, /^(?:cli|bin|scripts?|tools?|scaffold|scaffolding|generators?)$/u) || /(?:^|[./_-])(?:cli|script|tool|generator|scaffold)(?:[./_-]|$)/u.test(fileName);
@@ -215426,11 +215456,11 @@ function classifyValidationSourceScope(relativePath) {
215426
215456
  category = "generated";
215427
215457
  } else if (isE2e) {
215428
215458
  category = "e2e";
215429
- } else if (isTestFile || hasPathSegment(normalized, /^(?:test|tests|__tests__|spec|specs|__mocks__|cypress|cypress-tests)$/u)) {
215459
+ } else if (isTestFile || isMavenIntegrationTestModule || hasPathSegment(normalized, /^(?:test|tests|__tests__|spec|specs|__mocks__|cypress|cypress-tests)$/u)) {
215430
215460
  category = "test";
215431
215461
  } else if (isTestPlugin) {
215432
215462
  category = "test-plugin";
215433
- } else if (isExamplePlugin) {
215463
+ } else if (isExamplePlugin || isMavenExampleModule) {
215434
215464
  category = "example-plugin";
215435
215465
  } else if (isFixture) {
215436
215466
  category = "fixture";
@@ -215474,7 +215504,7 @@ function toSafeContractModuleFileStem(moduleName) {
215474
215504
  function normalizeAbsolutePath(filePath) {
215475
215505
  return normalizePath4(path7.resolve(filePath)).toLowerCase();
215476
215506
  }
215477
- function isPathInsideOrEqual2(childPath, parentPath) {
215507
+ function isPathInsideOrEqual(childPath, parentPath) {
215478
215508
  const child = normalizeAbsolutePath(childPath);
215479
215509
  const parent = normalizeAbsolutePath(parentPath);
215480
215510
  return child === parent || child.startsWith(`${parent}/`);
@@ -215555,6 +215585,9 @@ function buildChildModulesByParent(hierarchyEdges) {
215555
215585
  ])
215556
215586
  );
215557
215587
  }
215588
+ function isIsolatedContractlessHierarchyModule(input2) {
215589
+ return !input2.hasContract && input2.parentModule !== void 0 && input2.declaredDependencies.length === 0 && input2.actualDependencies.length === 0 && input2.inboundDeclaredFrom.length === 0 && input2.inboundActualFrom.length === 0 && input2.unusedDeclaredDependencies.length === 0 && input2.undeclaredActualDependencies.length === 0;
215590
+ }
215558
215591
  function getScriptKind(filePath) {
215559
215592
  const extension = path7.extname(filePath).toLowerCase();
215560
215593
  switch (extension) {
@@ -215712,7 +215745,7 @@ async function buildTsConfigPathAliasMap(workspaceRoot, moduleRoots) {
215712
215745
  const isWildcard = /\/\*$/u.test(aliasPattern) && /\/\*$/u.test(targetPattern);
215713
215746
  const normalizedTarget = normalizePath4(targetPattern).replace(/\/\*$/u, "");
215714
215747
  const absoluteTarget = path7.join(workspaceRoot, ...normalizedTarget.split("/"));
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];
215748
+ const moduleEntry = [...moduleRoots.entries()].filter(([, moduleRoot2]) => isPathInsideOrEqual(absoluteTarget, moduleRoot2)).sort((left, right) => right[1].length - left[1].length || left[0].localeCompare(right[0]))[0];
215716
215749
  if (!moduleEntry) {
215717
215750
  continue;
215718
215751
  }
@@ -215939,6 +215972,41 @@ async function buildExplicitStandaloneModulePathMap(workspaceRoot, architectureC
215939
215972
  function isTestSourcePath(relativePath) {
215940
215973
  return classifyValidationSourceScope(relativePath).isTestLike;
215941
215974
  }
215975
+ function hasStandardTestSourceRoot(relativePath) {
215976
+ const normalized = normalizePath4(relativePath);
215977
+ return /(?:^|\/)src\/(?:test|it|integration-test|integration-tests)\//u.test(normalized) || /(?:^|\/)(?:test|tests|__tests__|spec|specs|e2e|cypress)\//u.test(normalized) || /\.(?:spec|test|e2e-spec|integration-test)\.(?:ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/u.test(
215978
+ normalized.split("/").at(-1) ?? normalized
215979
+ );
215980
+ }
215981
+ function shouldSkipDependencySource(relativePath, moduleRoot, workspaceRoot, includeTestFiles, includeConfiguredNonProductionModuleSources) {
215982
+ if (includeTestFiles) {
215983
+ return false;
215984
+ }
215985
+ const moduleRootRelativePath = normalizePath4(path7.relative(workspaceRoot, moduleRoot));
215986
+ const moduleRootScope = classifyValidationSourceScope(moduleRootRelativePath);
215987
+ if (hasStandardTestSourceRoot(relativePath)) {
215988
+ return !includeConfiguredNonProductionModuleSources || moduleRootScope.isProduction || moduleRootScope.isTestLike;
215989
+ }
215990
+ if (!isTestSourcePath(relativePath)) {
215991
+ return false;
215992
+ }
215993
+ return !includeConfiguredNonProductionModuleSources || !moduleRootScope.isTestLike;
215994
+ }
215995
+ function filterImportsForBoundaryChecks(imports, moduleRoots, workspaceRoot) {
215996
+ return imports.filter((dependencyImport) => {
215997
+ const moduleRoot = moduleRoots.get(dependencyImport.sourceModule);
215998
+ if (!moduleRoot) {
215999
+ return true;
216000
+ }
216001
+ return !shouldSkipDependencySource(
216002
+ dependencyImport.sourceFileRelativePath,
216003
+ moduleRoot,
216004
+ workspaceRoot,
216005
+ false,
216006
+ false
216007
+ );
216008
+ });
216009
+ }
215942
216010
  async function collectSourceFiles(directoryPath, adapter, scanRootPath = directoryPath, excludedDirectoryRoots = []) {
215943
216011
  const entries = await import_node_fs6.promises.readdir(directoryPath, { withFileTypes: true });
215944
216012
  entries.sort((left, right) => left.name.localeCompare(right.name));
@@ -215947,7 +216015,7 @@ async function collectSourceFiles(directoryPath, adapter, scanRootPath = directo
215947
216015
  const fullPath = path7.join(directoryPath, entry.name);
215948
216016
  if (entry.isDirectory()) {
215949
216017
  if (excludedDirectoryRoots.some(
215950
- (excludedRoot) => isPathInsideOrEqual2(fullPath, excludedRoot)
216018
+ (excludedRoot) => isPathInsideOrEqual(fullPath, excludedRoot)
215951
216019
  )) {
215952
216020
  continue;
215953
216021
  }
@@ -216166,17 +216234,23 @@ function extractJavaPackageName(sourceText) {
216166
216234
  const match = /^\s*package\s+([a-zA-Z_][\w.]*)\s*;/mu.exec(sourceText);
216167
216235
  return match?.[1];
216168
216236
  }
216169
- async function buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) {
216237
+ async function buildJavaImportIndex(workspaceRoot, moduleRoots, adapter, options) {
216170
216238
  const classes = /* @__PURE__ */ new Map();
216171
216239
  const packageCandidates = /* @__PURE__ */ new Map();
216172
216240
  for (const [moduleId, moduleRoot] of [...moduleRoots.entries()].sort(
216173
216241
  ([left], [right]) => left.localeCompare(right)
216174
216242
  )) {
216175
- const childModuleRoots = [...moduleRoots.entries()].filter(([childModuleName, childModuleRoot]) => childModuleName !== moduleId && isPathInsideOrEqual2(childModuleRoot, moduleRoot)).map(([, childModuleRoot]) => childModuleRoot);
216243
+ const childModuleRoots = [...moduleRoots.entries()].filter(([childModuleName, childModuleRoot]) => childModuleName !== moduleId && isPathInsideOrEqual(childModuleRoot, moduleRoot)).map(([, childModuleRoot]) => childModuleRoot);
216176
216244
  const sourceFiles = await collectSourceFiles(moduleRoot, adapter, moduleRoot, childModuleRoots);
216177
216245
  for (const sourceFilePath of sourceFiles) {
216178
216246
  const relativePath = normalizePath4(path7.relative(workspaceRoot, sourceFilePath));
216179
- if (isTestSourcePath(relativePath)) {
216247
+ if (shouldSkipDependencySource(
216248
+ relativePath,
216249
+ moduleRoot,
216250
+ workspaceRoot,
216251
+ false,
216252
+ options?.includeConfiguredNonProductionModuleSources === true
216253
+ )) {
216180
216254
  continue;
216181
216255
  }
216182
216256
  const sourceText = await readTextFileIfExists2(sourceFilePath);
@@ -216780,7 +216854,7 @@ async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath,
216780
216854
  if (!resolvedPath) {
216781
216855
  return void 0;
216782
216856
  }
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];
216857
+ const targetModuleEntry = packageAliasTargetModule && packageAliasTargetModuleRoot ? [packageAliasTargetModule, packageAliasTargetModuleRoot] : [...moduleRoots.entries()].filter(([, moduleRoot]) => isPathInsideOrEqual(resolvedPath, moduleRoot)).sort((left, right) => right[1].length - left[1].length || left[0].localeCompare(right[0]))[0];
216784
216858
  if (!targetModuleEntry) {
216785
216859
  const standaloneTargetModule = explicitStandaloneModuleByPath.get(
216786
216860
  normalizePath4(path7.relative(workspaceRoot, resolvedPath))
@@ -216819,14 +216893,17 @@ async function resolveCrossModuleImport(workspaceRoot, modulesRootRelativePath,
216819
216893
  async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath, moduleRoots, explicitStandaloneModuleByPath, workspacePackageAliases, adapter, options) {
216820
216894
  const imports = [];
216821
216895
  const includeTestFiles = options?.includeTestFiles === true;
216896
+ const includeConfiguredNonProductionModuleSources = options?.includeConfiguredNonProductionModuleSources === true;
216822
216897
  if (!supportsDependencyImportParsing(adapter)) {
216823
216898
  return imports;
216824
216899
  }
216825
- const javaImportIndex = usesJavaImportParser(adapter) ? await buildJavaImportIndex(workspaceRoot, moduleRoots, adapter) : void 0;
216900
+ const javaImportIndex = usesJavaImportParser(adapter) ? await buildJavaImportIndex(workspaceRoot, moduleRoots, adapter, {
216901
+ includeConfiguredNonProductionModuleSources
216902
+ }) : void 0;
216826
216903
  for (const [moduleName, moduleRoot] of [...moduleRoots.entries()].sort(
216827
216904
  ([left], [right]) => left.localeCompare(right)
216828
216905
  )) {
216829
- const childModuleRoots = [...moduleRoots.entries()].filter(([childModuleName, childModuleRoot]) => childModuleName !== moduleName && isPathInsideOrEqual2(childModuleRoot, moduleRoot)).map(([, childModuleRoot]) => childModuleRoot);
216906
+ const childModuleRoots = [...moduleRoots.entries()].filter(([childModuleName, childModuleRoot]) => childModuleName !== moduleName && isPathInsideOrEqual(childModuleRoot, moduleRoot)).map(([, childModuleRoot]) => childModuleRoot);
216830
216907
  const sourceFiles = await collectSourceFiles(
216831
216908
  moduleRoot,
216832
216909
  adapter,
@@ -216837,7 +216914,13 @@ async function collectCrossModuleImports(workspaceRoot, modulesRootRelativePath,
216837
216914
  const sourceFileRelativePath = normalizePath4(
216838
216915
  path7.relative(workspaceRoot, sourceFilePath)
216839
216916
  );
216840
- if (!includeTestFiles && isTestSourcePath(sourceFileRelativePath)) {
216917
+ if (shouldSkipDependencySource(
216918
+ sourceFileRelativePath,
216919
+ moduleRoot,
216920
+ workspaceRoot,
216921
+ includeTestFiles,
216922
+ includeConfiguredNonProductionModuleSources
216923
+ )) {
216841
216924
  continue;
216842
216925
  }
216843
216926
  const sourceText = await readTextFileIfExists2(sourceFilePath);
@@ -216962,15 +217045,15 @@ function toDependencyContextMetadata(context) {
216962
217045
  isExternal: context.isExternal
216963
217046
  };
216964
217047
  }
216965
- function resolveImportDependencyContextMetadata(architectureContract, dependencyImport) {
216966
- const directContext = resolveDependencyContext(architectureContract, {
217048
+ function resolveImportDependencyContextMetadata(architectureContract, dependencyImport, resolver = createArchitectureDependencyContextResolver(architectureContract)) {
217049
+ const directContext = resolver.resolve({
216967
217050
  sourceFile: dependencyImport.sourceFileRelativePath,
216968
217051
  importSpecifier: dependencyImport.importSpecifier
216969
217052
  });
216970
217053
  if (!directContext.isExternal) {
216971
217054
  return toDependencyContextMetadata(directContext);
216972
217055
  }
216973
- const moduleTargetContext = resolveDependencyContext(architectureContract, {
217056
+ const moduleTargetContext = resolver.resolve({
216974
217057
  sourceFile: dependencyImport.sourceFileRelativePath,
216975
217058
  importSpecifier: dependencyImport.targetModule
216976
217059
  });
@@ -216981,7 +217064,7 @@ function resolveImportDependencyContextMetadata(architectureContract, dependency
216981
217064
  resolvedTargetPath: dependencyImport.resolvedTargetRelativePath
216982
217065
  });
216983
217066
  }
216984
- const resolvedPathContext = resolveDependencyContext(architectureContract, {
217067
+ const resolvedPathContext = resolver.resolve({
216985
217068
  sourceFile: dependencyImport.sourceFileRelativePath,
216986
217069
  importSpecifier: dependencyImport.resolvedTargetRelativePath
216987
217070
  });
@@ -217019,11 +217102,15 @@ function validateComponentDependencyPolicies(architectureContract, imports) {
217019
217102
  if (!architectureContract || policies.size === 0) {
217020
217103
  return [];
217021
217104
  }
217105
+ const dependencyContextResolver = createArchitectureDependencyContextResolver(
217106
+ architectureContract
217107
+ );
217022
217108
  const findings = [];
217023
217109
  for (const dependencyImport of imports) {
217024
217110
  const dependencyMetadata = resolveImportDependencyContextMetadata(
217025
217111
  architectureContract,
217026
- dependencyImport
217112
+ dependencyImport,
217113
+ dependencyContextResolver
217027
217114
  );
217028
217115
  if (dependencyMetadata.dependencyType !== "cross-component" || dependencyMetadata.isExternal || !dependencyMetadata.sourceComponentId || !dependencyMetadata.targetComponentId) {
217029
217116
  continue;
@@ -217059,7 +217146,7 @@ function validateComponentDependencyPolicies(architectureContract, imports) {
217059
217146
  }
217060
217147
  return findings;
217061
217148
  }
217062
- function isModuleScopedDependencyImport(architectureContract, dependencyImport) {
217149
+ function isModuleScopedDependencyImport(architectureContract, dependencyImport, resolver) {
217063
217150
  if (dependencyImport.sourceModule === dependencyImport.targetModule || isParentChildModuleRelationship(
217064
217151
  dependencyImport.sourceModule,
217065
217152
  dependencyImport.targetModule
@@ -217071,7 +217158,8 @@ function isModuleScopedDependencyImport(architectureContract, dependencyImport)
217071
217158
  }
217072
217159
  const dependencyMetadata = resolveImportDependencyContextMetadata(
217073
217160
  architectureContract,
217074
- dependencyImport
217161
+ dependencyImport,
217162
+ resolver
217075
217163
  );
217076
217164
  return !dependencyMetadata.isExternal;
217077
217165
  }
@@ -217382,7 +217470,10 @@ async function buildDependencyGraphSummary(workspaceRoot, architectureContract,
217382
217470
  explicitStandaloneModuleByPath,
217383
217471
  workspacePackageAliases,
217384
217472
  adapter,
217385
- { resolutionContext }
217473
+ {
217474
+ includeConfiguredNonProductionModuleSources: true,
217475
+ resolutionContext
217476
+ }
217386
217477
  );
217387
217478
  options?.onCollectedImports?.(imports);
217388
217479
  options?.onResolutionStats?.(resolutionContext.getStats());
@@ -217421,34 +217512,42 @@ async function buildDependencyGraphSummary(workspaceRoot, architectureContract,
217421
217512
  const inboundDeclared = buildInboundDependencyMap(declaredBySource, moduleIds);
217422
217513
  const inboundActual = buildInboundDependencyMap(actualBySource, moduleIds);
217423
217514
  const hierarchyEdges = buildModuleHierarchyEdges(moduleIds);
217424
- const childModulesByParent = buildChildModulesByParent(hierarchyEdges);
217425
217515
  const parentModuleByChild = new Map(
217426
217516
  hierarchyEdges.map((edge) => [edge.childModule, edge.parentModule])
217427
217517
  );
217518
+ const moduleSummaries = moduleIds.map((moduleId) => {
217519
+ const declaredDependencies = sortUnique2(declaredBySource.get(moduleId) ?? []);
217520
+ const actualDependencies = sortUnique2(actualBySource.get(moduleId) ?? []);
217521
+ const unusedDeclaredDependencies = declaredDependencies.filter(
217522
+ (declaredDependency) => !actualDependencies.includes(declaredDependency)
217523
+ );
217524
+ const undeclaredActualDependencies = actualDependencies.filter(
217525
+ (actualDependency) => !declaredDependencies.includes(actualDependency)
217526
+ );
217527
+ return {
217528
+ module: moduleId,
217529
+ hasContract: hasContractByModule.get(moduleId) ?? false,
217530
+ ...parentModuleByChild.has(moduleId) ? { parentModule: parentModuleByChild.get(moduleId) } : {},
217531
+ childModules: [],
217532
+ declaredDependencies,
217533
+ actualDependencies,
217534
+ inboundDeclaredFrom: inboundDeclared.get(moduleId) ?? [],
217535
+ inboundActualFrom: inboundActual.get(moduleId) ?? [],
217536
+ unusedDeclaredDependencies,
217537
+ undeclaredActualDependencies
217538
+ };
217539
+ }).filter((moduleSummary) => !isIsolatedContractlessHierarchyModule(moduleSummary));
217540
+ const retainedModuleIds = new Set(moduleSummaries.map((moduleSummary) => moduleSummary.module));
217541
+ const retainedHierarchyEdges = hierarchyEdges.filter(
217542
+ (edge) => retainedModuleIds.has(edge.parentModule) && retainedModuleIds.has(edge.childModule)
217543
+ );
217544
+ const childModulesByParent = buildChildModulesByParent(retainedHierarchyEdges);
217428
217545
  return {
217429
- modules: moduleIds.map((moduleId) => {
217430
- const declaredDependencies = sortUnique2(declaredBySource.get(moduleId) ?? []);
217431
- const actualDependencies = sortUnique2(actualBySource.get(moduleId) ?? []);
217432
- const unusedDeclaredDependencies = declaredDependencies.filter(
217433
- (declaredDependency) => !actualDependencies.includes(declaredDependency)
217434
- );
217435
- const undeclaredActualDependencies = actualDependencies.filter(
217436
- (actualDependency) => !declaredDependencies.includes(actualDependency)
217437
- );
217438
- return {
217439
- module: moduleId,
217440
- hasContract: hasContractByModule.get(moduleId) ?? false,
217441
- ...parentModuleByChild.has(moduleId) ? { parentModule: parentModuleByChild.get(moduleId) } : {},
217442
- childModules: childModulesByParent.get(moduleId) ?? [],
217443
- declaredDependencies,
217444
- actualDependencies,
217445
- inboundDeclaredFrom: inboundDeclared.get(moduleId) ?? [],
217446
- inboundActualFrom: inboundActual.get(moduleId) ?? [],
217447
- unusedDeclaredDependencies,
217448
- undeclaredActualDependencies
217449
- };
217450
- }),
217451
- hierarchyEdges
217546
+ modules: moduleSummaries.map((moduleSummary) => ({
217547
+ ...moduleSummary,
217548
+ childModules: childModulesByParent.get(moduleSummary.module) ?? []
217549
+ })),
217550
+ hierarchyEdges: retainedHierarchyEdges
217452
217551
  };
217453
217552
  }
217454
217553
  async function validateDependencyContractBoundaries(workspaceRoot, architectureContract, options) {
@@ -217478,9 +217577,17 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217478
217577
  workspacePackageAliases,
217479
217578
  adapter
217480
217579
  );
217481
- const peerImports = filterPeerModuleImports(imports);
217580
+ const boundaryImports = filterImportsForBoundaryChecks(imports, moduleRoots, workspaceRoot);
217581
+ const dependencyContextResolver = createArchitectureDependencyContextResolver(
217582
+ architectureContract
217583
+ );
217584
+ const peerImports = filterPeerModuleImports(boundaryImports);
217482
217585
  const moduleScopedPeerImports = peerImports.filter(
217483
- (dependencyImport) => isModuleScopedDependencyImport(architectureContract, dependencyImport)
217586
+ (dependencyImport) => isModuleScopedDependencyImport(
217587
+ architectureContract,
217588
+ dependencyImport,
217589
+ dependencyContextResolver
217590
+ )
217484
217591
  );
217485
217592
  const findings = [];
217486
217593
  const moduleContractCache = /* @__PURE__ */ new Map();
@@ -217490,7 +217597,8 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217490
217597
  for (const dependencyImport of moduleScopedPeerImports) {
217491
217598
  const dependencyMetadata = resolveImportDependencyContextMetadata(
217492
217599
  architectureContract,
217493
- dependencyImport
217600
+ dependencyImport,
217601
+ dependencyContextResolver
217494
217602
  );
217495
217603
  if (dependencyMetadata.isExternal) {
217496
217604
  continue;
@@ -217622,7 +217730,8 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217622
217730
  for (const dependencyImport of moduleScopedPeerImports) {
217623
217731
  const dependencyMetadata = resolveImportDependencyContextMetadata(
217624
217732
  architectureContract,
217625
- dependencyImport
217733
+ dependencyImport,
217734
+ dependencyContextResolver
217626
217735
  );
217627
217736
  if (dependencyMetadata.isExternal) {
217628
217737
  continue;
@@ -217783,7 +217892,8 @@ async function validateDependencyContractBoundaries(workspaceRoot, architectureC
217783
217892
  workspaceRoot,
217784
217893
  canonicalModuleRoots
217785
217894
  ),
217786
- adapter
217895
+ adapter,
217896
+ { includeConfiguredNonProductionModuleSources: true }
217787
217897
  );
217788
217898
  const canonicalPeerImports = filterPeerModuleImports(canonicalImports).filter(
217789
217899
  (dependencyImport) => isModuleScopedDependencyImport(architectureContract, dependencyImport)
@@ -217881,9 +217991,15 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
217881
217991
  workspacePackageAliases,
217882
217992
  adapter
217883
217993
  );
217884
- const peerImports = filterPeerModuleImports(imports);
217994
+ const boundaryImports = filterImportsForBoundaryChecks(imports, moduleRoots, workspaceRoot);
217995
+ const dependencyContextResolver = parsedArchitectureContract ? createArchitectureDependencyContextResolver(parsedArchitectureContract) : void 0;
217996
+ const peerImports = filterPeerModuleImports(boundaryImports);
217885
217997
  const moduleScopedPeerImports = peerImports.filter(
217886
- (dependencyImport) => isModuleScopedDependencyImport(parsedArchitectureContract, dependencyImport)
217998
+ (dependencyImport) => isModuleScopedDependencyImport(
217999
+ parsedArchitectureContract,
218000
+ dependencyImport,
218001
+ dependencyContextResolver
218002
+ )
217887
218003
  );
217888
218004
  const findings = [];
217889
218005
  const moduleContractCache = /* @__PURE__ */ new Map();
@@ -217942,7 +218058,8 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
217942
218058
  if (parsedArchitectureContract) {
217943
218059
  const dependencyMetadata = resolveImportDependencyContextMetadata(
217944
218060
  parsedArchitectureContract,
217945
- dependencyImport
218061
+ dependencyImport,
218062
+ dependencyContextResolver
217946
218063
  );
217947
218064
  if (dependencyMetadata.isExternal) {
217948
218065
  return false;
@@ -217966,7 +218083,11 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
217966
218083
  });
217967
218084
  } else {
217968
218085
  for (const violation of violations) {
217969
- const dependencyMetadata = parsedArchitectureContract ? resolveImportDependencyContextMetadata(parsedArchitectureContract, violation) : void 0;
218086
+ const dependencyMetadata = parsedArchitectureContract ? resolveImportDependencyContextMetadata(
218087
+ parsedArchitectureContract,
218088
+ violation,
218089
+ dependencyContextResolver
218090
+ ) : void 0;
217970
218091
  const allowedDependencies = dependencyRules.modules[violation.sourceModule]?.allowedDependencies ?? [];
217971
218092
  const allowedDescription = allowedDependencies.length === 0 ? "may not depend on any other modules" : `may only depend on: ${allowedDependencies.join(", ")}`;
217972
218093
  findings.push({
@@ -218008,7 +218129,8 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
218008
218129
  if (parsedArchitectureContract) {
218009
218130
  const dependencyMetadata = resolveImportDependencyContextMetadata(
218010
218131
  parsedArchitectureContract,
218011
- dependencyImport
218132
+ dependencyImport,
218133
+ dependencyContextResolver
218012
218134
  );
218013
218135
  if (dependencyMetadata.isExternal) {
218014
218136
  continue;
@@ -218057,7 +218179,11 @@ async function validateDependencyBoundaries(workspaceRoot, options) {
218057
218179
  });
218058
218180
  } else {
218059
218181
  for (const violation of violations) {
218060
- const dependencyMetadata = parsedArchitectureContract ? resolveImportDependencyContextMetadata(parsedArchitectureContract, violation) : void 0;
218182
+ const dependencyMetadata = parsedArchitectureContract ? resolveImportDependencyContextMetadata(
218183
+ parsedArchitectureContract,
218184
+ violation,
218185
+ dependencyContextResolver
218186
+ ) : void 0;
218061
218187
  const publicImportGuidance = await describeModulePublicImportGuidance(
218062
218188
  workspaceRoot,
218063
218189
  violation.targetModule,
@@ -218123,7 +218249,8 @@ async function buildModuleDependencyGraphSnapshot(workspaceRoot, options) {
218123
218249
  moduleRoots,
218124
218250
  explicitStandaloneModuleByPath,
218125
218251
  workspacePackageAliases,
218126
- adapter
218252
+ adapter,
218253
+ { includeConfiguredNonProductionModuleSources: true }
218127
218254
  );
218128
218255
  const imports = filterPeerModuleImports(allImports).filter(
218129
218256
  (dependencyImport) => moduleSet.has(dependencyImport.sourceModule) && moduleSet.has(dependencyImport.targetModule)
@@ -221079,7 +221206,7 @@ async function generateMissingModuleContracts(workspaceRoot) {
221079
221206
  });
221080
221207
  createdContracts.push(contractPath);
221081
221208
  }
221082
- if (isRegistryEntryDifferent({
221209
+ if (moduleEntry.discoverySource === "architecture.json" && isRegistryEntryDifferent({
221083
221210
  contract,
221084
221211
  moduleName: moduleEntry.moduleName,
221085
221212
  sourcePath,
@@ -222149,7 +222276,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222149
222276
  "AP-ARCH-005",
222150
222277
  "error",
222151
222278
  true,
222152
- "No modules are registered in architecture.json. Module registry path checks are not applicable."
222279
+ "No explicit root modules are registered in architecture.json. Root module registry path checks are not applicable; component-backed contracts are validated by dependency checks."
222153
222280
  )
222154
222281
  });
222155
222282
  }
@@ -222159,7 +222286,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222159
222286
  "AP-ARCH-006",
222160
222287
  "error",
222161
222288
  true,
222162
- "No modules are registered in architecture.json. Module contract file checks are not applicable."
222289
+ "No explicit root modules are registered in architecture.json. Root module contract file checks are not applicable; component-backed contracts are validated by dependency checks."
222163
222290
  )
222164
222291
  });
222165
222292
  }
@@ -222169,7 +222296,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222169
222296
  "AP-ARCH-007",
222170
222297
  "error",
222171
222298
  true,
222172
- "No modules are registered in architecture.json. Module contract identity checks are not applicable."
222299
+ "No explicit root modules are registered in architecture.json. Root module contract identity checks are not applicable; component-backed contracts are validated by dependency checks."
222173
222300
  )
222174
222301
  });
222175
222302
  }
@@ -222179,7 +222306,7 @@ async function validateModuleContractIntegrity(workspaceRoot, contract, options)
222179
222306
  "AP-ARCH-008",
222180
222307
  "error",
222181
222308
  true,
222182
- "No modules are registered in architecture.json. Module public entrypoint alignment checks are not applicable."
222309
+ "No explicit root modules are registered in architecture.json. Root module public entrypoint alignment checks are not applicable; component-backed contracts are validated by dependency checks."
222183
222310
  )
222184
222311
  });
222185
222312
  }
@@ -223128,7 +223255,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223128
223255
  "info",
223129
223256
  `Remote policy configured. Loading policy from ${policySourceUrl}.`
223130
223257
  );
223131
- return new Promise((resolve9) => {
223258
+ return new Promise((resolve10) => {
223132
223259
  const request3 = https.request(
223133
223260
  {
223134
223261
  protocol: validated.url.protocol,
@@ -223155,7 +223282,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223155
223282
  "warn",
223156
223283
  `Remote policy request failed with HTTP ${statusCode}. Using local policy only.`
223157
223284
  );
223158
- resolve9({
223285
+ resolve10({
223159
223286
  message: `Remote policy request failed with HTTP ${statusCode}. Using local policy only.`
223160
223287
  });
223161
223288
  return;
@@ -223169,7 +223296,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223169
223296
  "warn",
223170
223297
  "Remote policy payload is invalid JSON. Using local policy only."
223171
223298
  );
223172
- resolve9({
223299
+ resolve10({
223173
223300
  message: "Remote policy payload is invalid JSON. Using local policy only."
223174
223301
  });
223175
223302
  return;
@@ -223181,7 +223308,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223181
223308
  "warn",
223182
223309
  "Remote policy payload has an invalid structure. Using local policy only."
223183
223310
  );
223184
- resolve9({
223311
+ resolve10({
223185
223312
  message: "Remote policy payload has an invalid structure. Using local policy only."
223186
223313
  });
223187
223314
  return;
@@ -223191,7 +223318,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223191
223318
  "info",
223192
223319
  "Remote policy loaded successfully."
223193
223320
  );
223194
- resolve9({
223321
+ resolve10({
223195
223322
  policy: normalized,
223196
223323
  message: "Remote policy loaded successfully."
223197
223324
  });
@@ -223207,7 +223334,7 @@ async function loadRemotePolicyWithStatus(policySourceUrl, options) {
223207
223334
  "warn",
223208
223335
  "Remote policy unavailable. Using local policy only."
223209
223336
  );
223210
- resolve9({
223337
+ resolve10({
223211
223338
  message: "Remote policy unavailable. Using local policy only."
223212
223339
  });
223213
223340
  });
@@ -225533,6 +225660,15 @@ function hasPaginationEvidence(statement) {
225533
225660
  statement
225534
225661
  );
225535
225662
  }
225663
+ function hasEqualityPredicate(statement, columnPattern) {
225664
+ return new RegExp(
225665
+ `\\bwhere\\b[\\s\\S]*\\b(?:${columnPattern})\\b\\s*=\\s*(?:[\\w$:@?]+|'[^']+'|"[^"]+"|\\d+)`,
225666
+ "iu"
225667
+ ).test(statement);
225668
+ }
225669
+ function isCatalogIdentifierPointLookup(statement) {
225670
+ return /\bfrom\s+information_schema\.schemata\b/iu.test(statement) && hasEqualityPredicate(statement, "schema_name");
225671
+ }
225536
225672
  function isObviousPointLookup(statement) {
225537
225673
  const normalized = statement.toLowerCase();
225538
225674
  if (!normalized.includes("where")) {
@@ -225541,7 +225677,7 @@ function isObviousPointLookup(statement) {
225541
225677
  if (normalized.includes(" or ")) {
225542
225678
  return false;
225543
225679
  }
225544
- return /\bwhere\b[\s\S]*\b([a-z_]*id)\b\s*=\s*([\w$:@?]+|'[^']+'|\d+)/i.test(normalized);
225680
+ return hasEqualityPredicate(normalized, "id|uuid|slug|email|identifier") || isCatalogIdentifierPointLookup(normalized);
225545
225681
  }
225546
225682
  function listModulePathEntries(contract) {
225547
225683
  return Object.entries(contract.modules ?? {}).map(([moduleName, reference]) => {
@@ -226122,13 +226258,14 @@ function detectRepeatedQueryPattern(method) {
226122
226258
  }
226123
226259
  function extractSqlQueryLiterals(content) {
226124
226260
  const queries = [];
226261
+ const searchableContent = maskSourceComments(content);
226125
226262
  const patterns = [
226126
226263
  /(?:\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,
226127
226264
  /\b(?:DB::select|DB::statement|DB::raw|DB::table)\s*\([^'"`)]{0,180}?(['"`])([\s\S]{0,900}?)\1/gu,
226128
226265
  /@Query\s*\(\s*(['"`])([\s\S]{0,900}?)\1/gu
226129
226266
  ];
226130
226267
  for (const pattern of patterns) {
226131
- for (const match of content.matchAll(pattern)) {
226268
+ for (const match of searchableContent.matchAll(pattern)) {
226132
226269
  const sql = match[2];
226133
226270
  if (!sql || !/\b(?:select|update|delete|insert)\b/iu.test(sql)) {
226134
226271
  continue;
@@ -226141,6 +226278,71 @@ function extractSqlQueryLiterals(content) {
226141
226278
  }
226142
226279
  return queries;
226143
226280
  }
226281
+ function maskSourceComments(content) {
226282
+ let masked = "";
226283
+ let index = 0;
226284
+ let state = "code";
226285
+ let escaped = false;
226286
+ while (index < content.length) {
226287
+ const current = content[index] ?? "";
226288
+ const next = content[index + 1] ?? "";
226289
+ if (state === "line-comment") {
226290
+ if (current === "\r" || current === "\n") {
226291
+ masked += current;
226292
+ state = "code";
226293
+ } else {
226294
+ masked += " ";
226295
+ }
226296
+ index += 1;
226297
+ continue;
226298
+ }
226299
+ if (state === "block-comment") {
226300
+ if (current === "*" && next === "/") {
226301
+ masked += " ";
226302
+ index += 2;
226303
+ state = "code";
226304
+ continue;
226305
+ }
226306
+ masked += current === "\r" || current === "\n" ? current : " ";
226307
+ index += 1;
226308
+ continue;
226309
+ }
226310
+ if (state === "single" || state === "double" || state === "template") {
226311
+ masked += current;
226312
+ if (escaped) {
226313
+ escaped = false;
226314
+ } else if (current === "\\") {
226315
+ escaped = true;
226316
+ } else if (state === "single" && current === "'" || state === "double" && current === '"' || state === "template" && current === "`") {
226317
+ state = "code";
226318
+ }
226319
+ index += 1;
226320
+ continue;
226321
+ }
226322
+ if (current === "/" && next === "/") {
226323
+ masked += " ";
226324
+ index += 2;
226325
+ state = "line-comment";
226326
+ continue;
226327
+ }
226328
+ if (current === "/" && next === "*") {
226329
+ masked += " ";
226330
+ index += 2;
226331
+ state = "block-comment";
226332
+ continue;
226333
+ }
226334
+ if (current === "'") {
226335
+ state = "single";
226336
+ } else if (current === '"') {
226337
+ state = "double";
226338
+ } else if (current === "`") {
226339
+ state = "template";
226340
+ }
226341
+ masked += current;
226342
+ index += 1;
226343
+ }
226344
+ return masked;
226345
+ }
226144
226346
  function detectCodeSqlQueryShapeFindings(file, config) {
226145
226347
  const findings = [];
226146
226348
  for (const query of extractSqlQueryLiterals(file.content)) {
@@ -226230,12 +226432,18 @@ function hasAssignedBuilderBoundedTerminal(methodBody, snippet) {
226230
226432
  }
226231
226433
  return new RegExp(`\\b${variableName}\\s*\\.\\s*(?:getOne|getRawOne|loadOne|getCount|getExists)\\s*\\(`, "iu").test(methodBody);
226232
226434
  }
226435
+ function hasIdentifierPredicateEvidence(snippet) {
226436
+ return /\.(?:where|andWhere|orWhere)\s*\(\s*['"`][^'"`]{0,240}\b(?:\w*id|uuid|slug|email|identifier)\b[^'"`]{0,120}(?:=| in\b|IN\b)/iu.test(snippet) || /\bwhere\s*:\s*\{[\s\S]{0,420}\b(?:id|uuid|slug|email|identifier|channelId|orderId|customerId|userId|productId|variantId)\b\s*[:=]/iu.test(snippet);
226437
+ }
226438
+ function hasQueryBuilderTerminalEvidence(snippet, methodBody) {
226439
+ return /\.(?:getMany|getRawMany|loadMany|getOne|getRawOne|loadOne|getCount|getExists|execute)\s*\(/iu.test(snippet) || hasAssignedBuilderBoundedTerminal(methodBody, snippet);
226440
+ }
226233
226441
  function isNonCollectionOrmRead(label, snippet, methodBody = snippet) {
226234
226442
  const terminal = getOrmTerminalOperation(snippet);
226235
226443
  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);
226236
226444
  }
226237
226445
  function hasOrmBoundEvidence(snippet) {
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);
226446
+ return codePaginationEvidencePattern.test(snippet) || /\.(?:take|limit|offset|skip)\s*\(/iu.test(snippet) || /\b(?:maxResults|setMaxResults|firstResult|setFirstResult)\s*\(/iu.test(snippet) || /\b(?:pageSize|perPage|limit|take)\s*[:=]\s*\d+\b/iu.test(snippet) || hasIdentifierPredicateEvidence(snippet);
226239
226447
  }
226240
226448
  function getOrmQueryTarget(method, label, snippet) {
226241
226449
  const terminal = getOrmTerminalOperation(snippet);
@@ -226258,6 +226466,9 @@ function getOrmQueryLabel(method, label, snippet) {
226258
226466
  function detectOrmQueryShapeFindings(method, config) {
226259
226467
  const findings = [];
226260
226468
  for (const evidence of collectOrmReadEvidence(method)) {
226469
+ if (evidence.label === "node.query" && !hasQueryBuilderTerminalEvidence(evidence.snippet, method.body)) {
226470
+ continue;
226471
+ }
226261
226472
  if (config.tenantModel === "same_db_same_schema" && !tenantPredicatePattern.test(evidence.snippet)) {
226262
226473
  findings.push(createCodeFinding({
226263
226474
  id: "AP-DQR-001",
@@ -226727,17 +226938,40 @@ function getModulePathForName(contract, moduleName) {
226727
226938
  const reference = contract.modules?.[moduleName];
226728
226939
  return normalizePath11(reference?.path ?? `${modulesRoot}/${moduleName}`);
226729
226940
  }
226730
- function getPathSegmentsInsideModule(relativePath, modulePath) {
226941
+ function getComponentEntries2(contract) {
226942
+ const components = contract.components;
226943
+ if (!components) {
226944
+ return [];
226945
+ }
226946
+ return Array.isArray(components) ? components.map((component, index) => [
226947
+ typeof component.id === "string" && component.id.trim().length > 0 ? component.id.trim() : `component-${index}`,
226948
+ component
226949
+ ]) : Object.entries(components);
226950
+ }
226951
+ function getComponentPathForFile(contract, relativePath) {
226731
226952
  const normalized = normalizePath11(relativePath).toLowerCase();
226732
- if (!modulePath) {
226953
+ const candidates = getComponentEntries2(contract).map(([, component]) => component.path).filter(
226954
+ (componentPath) => typeof componentPath === "string" && componentPath.trim().length > 0
226955
+ ).map((componentPath) => normalizePath11(componentPath)).filter((componentPath) => {
226956
+ const normalizedComponentPath = componentPath.toLowerCase();
226957
+ return normalized === normalizedComponentPath || normalized.startsWith(`${normalizedComponentPath}/`);
226958
+ }).sort((left, right) => right.length - left.length || left.localeCompare(right));
226959
+ return candidates[0];
226960
+ }
226961
+ function getOwnershipPathForFile(contract, relativePath, moduleName) {
226962
+ return getModulePathForName(contract, moduleName) ?? getComponentPathForFile(contract, relativePath);
226963
+ }
226964
+ function getPathSegmentsInsideModule(relativePath, ownershipPath) {
226965
+ const normalized = normalizePath11(relativePath).toLowerCase();
226966
+ if (!ownershipPath) {
226733
226967
  return normalized.split("/");
226734
226968
  }
226735
- const normalizedModulePath = normalizePath11(modulePath).toLowerCase();
226736
- if (normalized === normalizedModulePath) {
226969
+ const normalizedOwnershipPath = normalizePath11(ownershipPath).toLowerCase();
226970
+ if (normalized === normalizedOwnershipPath) {
226737
226971
  return [];
226738
226972
  }
226739
- if (normalized.startsWith(`${normalizedModulePath}/`)) {
226740
- return normalized.slice(normalizedModulePath.length + 1).split("/");
226973
+ if (normalized.startsWith(`${normalizedOwnershipPath}/`)) {
226974
+ return normalized.slice(normalizedOwnershipPath.length + 1).split("/");
226741
226975
  }
226742
226976
  return normalized.split("/");
226743
226977
  }
@@ -226873,7 +227107,10 @@ function createFinding(input2) {
226873
227107
  function hasRepositoryLayer(files, contract) {
226874
227108
  return files.some((file) => {
226875
227109
  const moduleName = inferModuleForPath2(contract, file.relativePath);
226876
- return classifySourceFile(file, getModulePathForName(contract, moduleName)).isRepository;
227110
+ return classifySourceFile(
227111
+ file,
227112
+ getOwnershipPathForFile(contract, file.relativePath, moduleName)
227113
+ ).isRepository;
226877
227114
  });
226878
227115
  }
226879
227116
  function hasServiceLayer(files) {
@@ -226940,7 +227177,7 @@ function detectControllerBusinessLogic(entry, classification, moduleName, contex
226940
227177
  });
226941
227178
  }
226942
227179
  function detectRepositoryBusinessLogic(entry, classification, moduleName) {
226943
- if (!classification.isRepository) {
227180
+ if (!classification.isRepository || !isProductionBackendGovernanceScope(classification.scope)) {
226944
227181
  return void 0;
226945
227182
  }
226946
227183
  if (entry.extension === ".java" && isPureSpringDataRepositoryInterface(entry.content)) {
@@ -227195,7 +227432,7 @@ async function detectApplicationLayeringFindings(input2) {
227195
227432
  const moduleName = inferModuleForPath2(input2.contract, file.relativePath);
227196
227433
  const classification = classifySourceFile(
227197
227434
  file,
227198
- getModulePathForName(input2.contract, moduleName),
227435
+ getOwnershipPathForFile(input2.contract, file.relativePath, moduleName),
227199
227436
  input2.astCache
227200
227437
  );
227201
227438
  const candidates = [
@@ -227268,7 +227505,7 @@ var publicEvidencePattern = /@Public\b|@PermitAll\b|\[AllowAnonymous\b[^\]]*\]|p
227268
227505
  var roleEvidencePattern = /@(?:Roles|Permissions|RequirePermission|PreAuthorize|Secured|RolesAllowed)\s*(?:\(|\b)([^)\n]*)|\[Authorize\s*\([^)\]]*(?:Roles|Policy)\s*=|(?:requireRole\w*|RequireRole\w*|require_role|RoleChecker|adminMiddleware|can:|permission:|scopes?\s*=|Security\s*\([^)]*scopes)\b/u;
227269
227506
  var tenantSignalPattern = /\b(?:tenantId|tenant_id|organizationId|organization_id|orgId|org_id|workspaceId|workspace_id|accountId|account_id|companyId|company_id|customerId|customer_id|TenantContext|CurrentTenant|TenantResolver|TenantProvider|request\.tenant|req\.tenant|user\.tenantId|user\.tenant_id|user\.organizationId|user\.organization_id|user\.orgId|user\.accountId|user\.workspaceId|user\.companyId|user\.customerId|HibernateFilter|CurrentTenant)\b/u;
227270
227507
  var tenantPredicateEvidencePattern = /\b(?:tenantId|tenant_id|organizationId|organization_id|orgId|org_id|workspaceId|workspace_id|accountId|account_id|companyId|company_id|customerId|customer_id|TenantContext|CurrentTenant|TenantResolver|TenantProvider|request\.tenant|req\.tenant|user\.tenantId|user\.tenant_id|user\.organizationId|user\.organization_id|user\.orgId|user\.accountId|user\.workspaceId|user\.companyId|user\.customerId|HibernateFilter|CurrentTenant)\b/u;
227271
- var repositoryRolePattern = /\b(?:role|roles|permission|permissions|isAdmin|hasRole|hasPermission|SecurityContextHolder|Authentication|Principal)\b/u;
227508
+ var executableAuthorizationDecisionPattern = /@(?:PreAuthorize|PostAuthorize|Secured|RolesAllowed)\b|\[(?:Authorize)\b[^\]]*(?:Roles|Policy)\s*=|\b(?:hasRole|hasAuthority|hasPermission|isUserInRole|checkPermission|requireRole\w*|RequireRole\w*|require_role|canActivate|authorize|assertAuthorized|PermissionChecker|AccessDecisionManager|SecurityContextHolder\.getContext\(\)\.getAuthentication)\s*\(|\b(?:user|principal|currentUser|account)\.(?:role|roles|permission|permissions|isAdmin)\b\s*(?:[=!]==?|\.includes\s*\(|\.contains\s*\()/u;
227272
227509
  function normalizePath12(value) {
227273
227510
  return value.replace(/\\/g, "/");
227274
227511
  }
@@ -227696,7 +227933,7 @@ function detectAuthorizationFindings(files, contract, astCache) {
227696
227933
  }
227697
227934
  }
227698
227935
  for (const file of files.filter((candidate) => isRepositoryFile(candidate, astCache))) {
227699
- const roleMatch = repositoryRolePattern.exec(file.content);
227936
+ const roleMatch = executableAuthorizationDecisionPattern.exec(file.content);
227700
227937
  if (!roleMatch) {
227701
227938
  continue;
227702
227939
  }
@@ -230495,8 +230732,9 @@ function extractJavaSignals(file) {
230495
230732
  publishes: []
230496
230733
  });
230497
230734
  }
230498
- for (const match of file.content.matchAll(/(?:await\s+)?(?:\w+\.)?(?:publishEvent|publish|emit)\s*\(\s*(?:new\s+)?(["']?)([A-Za-z][\w.]*Event?|[a-z][\w.]+)\1/gu)) {
230499
- const eventName = match[2];
230735
+ for (const match of file.content.matchAll(/(?:await\s+)?(?:\w+\.)?(?:publishEvent|publish|emit)\s*\(\s*(?:(new)\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\s*\(|(["'])([A-Za-z][\w.]*Event?|[a-z][\w.]+)\3|([A-Z][A-Za-z0-9_]*Event)\b)/gu)) {
230736
+ const constructedType = match[2]?.split(".").at(-1);
230737
+ const eventName = constructedType ?? match[4] ?? match[5];
230500
230738
  if (!eventName) {
230501
230739
  continue;
230502
230740
  }
@@ -234352,7 +234590,7 @@ ${infoLines.join("\n")}
234352
234590
  ## Passed Checks
234353
234591
  ${passedLines.join("\n")}
234354
234592
 
234355
- ## Module Dependency Summary
234593
+ ## Module / Component Contract Dependency Summary
234356
234594
  ${dependencyGraphLines.join("\n")}
234357
234595
 
234358
234596
  ## Disabled Rules
@@ -236588,7 +236826,7 @@ ${appliedFixesSection}
236588
236826
  ## Remaining Violations
236589
236827
  ${remainingViolationsLine}
236590
236828
 
236591
- ## Module Dependency Summary
236829
+ ## Module / Component Contract Dependency Summary
236592
236830
  ${moduleCatalog.length === 0 ? "- Module details are not available in this run." : moduleCatalog.map(
236593
236831
  (entry) => `- ${entry.moduleName} | Role: ${entry.role} | Path: ${entry.path ?? "(not configured)"} | Contract: ${entry.hasContract ? "yes" : "no"} | Declared deps: ${entry.declaredDependencyCount} | Actual deps: ${entry.actualDependencyCount} | Used by: ${entry.inboundDependencyCount}`
236594
236832
  ).join("\n")}
@@ -238840,11 +239078,11 @@ function normalizeAnnotationPath(workspaceRoot, sourceFile) {
238840
239078
  if (!path43.isAbsolute(sourceFile)) {
238841
239079
  return normalized;
238842
239080
  }
238843
- const relative17 = path43.relative(workspaceRoot, sourceFile).replace(/\\/g, "/");
238844
- if (relative17.startsWith("..") || path43.isAbsolute(relative17)) {
239081
+ const relative18 = path43.relative(workspaceRoot, sourceFile).replace(/\\/g, "/");
239082
+ if (relative18.startsWith("..") || path43.isAbsolute(relative18)) {
238845
239083
  return void 0;
238846
239084
  }
238847
- return relative17;
239085
+ return relative18;
238848
239086
  }
238849
239087
  function toAnnotatableFinding(workspaceRoot, finding) {
238850
239088
  if (typeof finding.id !== "string" || !finding.id.startsWith("AP-DEP-")) {
@@ -239028,7 +239266,7 @@ async function emitGithubInlineArchitectureAnnotations(workspaceRoot) {
239028
239266
  var reviewCommentMarker = "<!-- archpilot-pr-review -->";
239029
239267
  var legacyReviewCommentMarker = "<!-- ARCHPILOT_REVIEW_COMMENT -->";
239030
239268
  function requestGithubApi(options) {
239031
- return new Promise((resolve9, reject) => {
239269
+ return new Promise((resolve10, reject) => {
239032
239270
  const payload = options.body !== void 0 ? JSON.stringify(options.body) : void 0;
239033
239271
  const request3 = https2.request(
239034
239272
  {
@@ -239049,7 +239287,7 @@ function requestGithubApi(options) {
239049
239287
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
239050
239288
  });
239051
239289
  response.on("end", () => {
239052
- resolve9({
239290
+ resolve10({
239053
239291
  statusCode: response.statusCode ?? 0,
239054
239292
  body: Buffer.concat(chunks).toString("utf8")
239055
239293
  });
@@ -245326,6 +245564,9 @@ function addEvidence6(evidence, value) {
245326
245564
  evidence.push(value);
245327
245565
  }
245328
245566
  }
245567
+ function hasDeclaredMavenReactorEvidence(candidate) {
245568
+ return candidate.evidence.some((entry) => /Declared (?:by )?Maven|nested Maven reactor/iu.test(entry));
245569
+ }
245329
245570
  function isIgnoredComponentCandidatePath(componentPath) {
245330
245571
  const normalized = normalizePath25(componentPath).replace(/^\.\//u, "");
245331
245572
  if (normalized === "." || normalized.length === 0) {
@@ -245365,7 +245606,9 @@ function isIgnoredComponentCandidatePath(componentPath) {
245365
245606
  "build",
245366
245607
  "coverage"
245367
245608
  ];
245368
- return ignoredRootSegments.includes(firstSegment ?? "") || segments.some((segment) => ignoredSupportingSegments.includes(segment.toLowerCase()));
245609
+ const isExampleContainer = firstSegment === "examples" || firstSegment === "example";
245610
+ const isIgnoredRootSegment = ignoredRootSegments.includes(firstSegment ?? "") && (!isExampleContainer || segments.length === 1);
245611
+ return isIgnoredRootSegment || segments.some((segment) => ignoredSupportingSegments.includes(segment.toLowerCase()));
245369
245612
  }
245370
245613
  function pathExists19(pathValue) {
245371
245614
  try {
@@ -245429,6 +245672,9 @@ function readFirstXmlTag(value, tagName) {
245429
245672
  const match = value.match(new RegExp(`<${tagName}(?:\\s[^>]*)?>([\\s\\S]*?)</${tagName}>`, "iu"));
245430
245673
  return match?.[1]?.trim().replace(/\s+/gu, " ");
245431
245674
  }
245675
+ function readXmlTagValues(value, tagName) {
245676
+ return [...value.matchAll(new RegExp(`<${tagName}(?:\\s[^>]*)?>([\\s\\S]*?)</${tagName}>`, "giu"))].map((match) => match[1]?.trim().replace(/\s+/gu, " ") ?? "").filter((entry) => entry.length > 0);
245677
+ }
245432
245678
  function readMavenMetadata(workspaceRoot, componentPath) {
245433
245679
  if (isUnderJvmResourceRoot4(componentPath)) {
245434
245680
  return void 0;
@@ -245446,7 +245692,15 @@ function readMavenMetadata(workspaceRoot, componentPath) {
245446
245692
  artifactId: readFirstXmlTag(normalizedPom, "artifactId"),
245447
245693
  name: readFirstXmlTag(normalizedPom, "name"),
245448
245694
  hasPom: true,
245695
+ hasModules: /<modules\b/iu.test(normalizedPom),
245449
245696
  hasDependencyManagement: /<dependencyManagement\b/iu.test(normalizedPom),
245697
+ hasSpringBootPlugin: /\bspring-boot-maven-plugin\b/iu.test(normalizedPom),
245698
+ hasSpringBootRepackageGoal: /<goal>\s*repackage\s*<\/goal>/iu.test(normalizedPom),
245699
+ configuredMainClass: readFirstXmlTag(normalizedPom, "mainClass") ?? readFirstXmlTag(normalizedPom, "start-class"),
245700
+ hasSpringBootStarterDependency: dependencyBlocks.some((block) => /<artifactId>\s*spring-boot-starter(?:-[^<]+)?\s*<\/artifactId>/iu.test(block)),
245701
+ hasSpringBootAutoconfigureDependency: dependencyBlocks.some((block) => /<artifactId>\s*spring-boot-autoconfigure\s*<\/artifactId>/iu.test(block)),
245702
+ hasSpringBootAutoconfigureProcessor: /spring-boot-autoconfigure-processor|spring-boot-configuration-processor/iu.test(normalizedPom),
245703
+ hasDocumentationTooling: /asciidoctor-maven-plugin|maven-site-plugin|doxia|antora|javadoc|<goal>\s*site\s*<\/goal>/iu.test(normalizedPom),
245450
245704
  testScopedDependencyCount: dependencyBlocks.filter((block) => /<scope>\s*test\s*<\/scope>/iu.test(block)).length,
245451
245705
  totalDependencyCount: dependencyBlocks.length,
245452
245706
  hasMavenPluginConfiguration: packaging === "maven-plugin" || /maven-plugin-plugin|<goalPrefix>|<mojo/iu.test(normalizedPom),
@@ -245458,6 +245712,95 @@ function readMavenMetadata(workspaceRoot, componentPath) {
245458
245712
  hasTestResources: pathExists19(path64.join(absoluteRoot, "src", "test", "resources"))
245459
245713
  };
245460
245714
  }
245715
+ function workspaceRelativePath(workspaceRoot, absolutePathValue) {
245716
+ const relative18 = path64.relative(workspaceRoot, absolutePathValue);
245717
+ if (relative18.length === 0) {
245718
+ return ".";
245719
+ }
245720
+ if (relative18.startsWith("..") || path64.isAbsolute(relative18)) {
245721
+ return void 0;
245722
+ }
245723
+ return normalizePath25(relative18);
245724
+ }
245725
+ function canonicalRealPath(filePath) {
245726
+ try {
245727
+ return fs58.realpathSync.native(filePath);
245728
+ } catch {
245729
+ return void 0;
245730
+ }
245731
+ }
245732
+ function readMavenDeclaredModules(pomPath) {
245733
+ const pomXml = readTextFileSafe(pomPath);
245734
+ if (!pomXml) {
245735
+ return [];
245736
+ }
245737
+ return uniqueSorted4(
245738
+ readXmlTagValues(stripXmlComments(pomXml), "module").filter((modulePath) => !/[${}]/u.test(modulePath))
245739
+ );
245740
+ }
245741
+ function collectMavenReactorCandidates(workspaceRoot, rootPaths) {
245742
+ const candidates = /* @__PURE__ */ new Map();
245743
+ const visitedPomPaths = /* @__PURE__ */ new Set();
245744
+ const workspaceRealPath = canonicalRealPath(workspaceRoot) ?? path64.resolve(workspaceRoot);
245745
+ const workspaceRealPathForCompare = process.platform === "win32" ? workspaceRealPath.toLowerCase() : workspaceRealPath;
245746
+ const maxVisitedPoms = 500;
245747
+ const addCandidate = (candidatePath, evidence, parentPath) => {
245748
+ const normalized = normalizePath25(candidatePath);
245749
+ const existing = candidates.get(normalized) ?? { path: normalized, evidence: [] };
245750
+ addEvidence6(existing.evidence, evidence);
245751
+ if (parentPath && !existing.parentPath) {
245752
+ existing.parentPath = parentPath;
245753
+ }
245754
+ candidates.set(normalized, existing);
245755
+ };
245756
+ const visitPom = (pomPath, parentPath) => {
245757
+ if (visitedPomPaths.size >= maxVisitedPoms) {
245758
+ return;
245759
+ }
245760
+ const realPomPath = canonicalRealPath(pomPath);
245761
+ if (!realPomPath || visitedPomPaths.has(realPomPath)) {
245762
+ return;
245763
+ }
245764
+ const realPomPathForCompare = process.platform === "win32" ? realPomPath.toLowerCase() : realPomPath;
245765
+ if (realPomPathForCompare !== workspaceRealPathForCompare && !realPomPathForCompare.startsWith(`${workspaceRealPathForCompare}${path64.sep}`)) {
245766
+ return;
245767
+ }
245768
+ visitedPomPaths.add(realPomPath);
245769
+ const pomDirectory = path64.dirname(pomPath);
245770
+ const relativePomDirectory = workspaceRelativePath(workspaceRoot, pomDirectory);
245771
+ if (!relativePomDirectory) {
245772
+ return;
245773
+ }
245774
+ addCandidate(
245775
+ relativePomDirectory,
245776
+ parentPath ? `Declared by Maven reactor parent ${parentPath}` : "Detected Maven reactor root",
245777
+ parentPath
245778
+ );
245779
+ for (const declaredModule of readMavenDeclaredModules(pomPath)) {
245780
+ const childDirectory = path64.resolve(pomDirectory, declaredModule);
245781
+ const childRelativePath = workspaceRelativePath(workspaceRoot, childDirectory);
245782
+ if (!childRelativePath || isUnderJvmResourceRoot4(childRelativePath)) {
245783
+ continue;
245784
+ }
245785
+ const childPom = path64.join(childDirectory, "pom.xml");
245786
+ if (!pathExists19(childPom)) {
245787
+ addCandidate(childRelativePath, `Declared Maven module '${declaredModule}' is missing pom.xml`, relativePomDirectory);
245788
+ continue;
245789
+ }
245790
+ addCandidate(childRelativePath, `Declared Maven module '${declaredModule}' from ${relativePomDirectory}`, relativePomDirectory);
245791
+ visitPom(childPom, relativePomDirectory);
245792
+ }
245793
+ };
245794
+ for (const rootPath of uniqueSorted4(rootPaths)) {
245795
+ const normalizedRoot = normalizePath25(rootPath);
245796
+ const absoluteRoot = normalizedRoot === "." ? workspaceRoot : path64.join(workspaceRoot, ...normalizedRoot.split("/"));
245797
+ const pomPath = path64.join(absoluteRoot, "pom.xml");
245798
+ if (pathExists19(pomPath)) {
245799
+ visitPom(pomPath);
245800
+ }
245801
+ }
245802
+ return [...candidates.values()].sort((left, right) => left.path.localeCompare(right.path));
245803
+ }
245461
245804
  function toComponentRoot(modulePath) {
245462
245805
  const normalized = normalizePath25(modulePath);
245463
245806
  const segments = normalized.split("/").filter((segment) => segment.length > 0);
@@ -245492,6 +245835,18 @@ function buildRootCandidates(input2) {
245492
245835
  for (const root of input2.topology.detectedRoots ?? []) {
245493
245836
  addCandidate(root, `Detected project root ${root}`);
245494
245837
  }
245838
+ if (input2.workspaceRoot) {
245839
+ const mavenRoots = [".", ...input2.topology.detectedRoots ?? []];
245840
+ for (const candidate of collectMavenReactorCandidates(input2.workspaceRoot, mavenRoots)) {
245841
+ addCandidate(
245842
+ candidate.path,
245843
+ candidate.parentPath ? `Detected nested Maven reactor module under ${candidate.parentPath}` : "Detected Maven reactor module"
245844
+ );
245845
+ for (const evidence of candidate.evidence) {
245846
+ addCandidate(candidate.path, evidence);
245847
+ }
245848
+ }
245849
+ }
245495
245850
  for (const moduleEntry of input2.modules?.modules ?? []) {
245496
245851
  const componentRoot = toComponentRoot(moduleEntry.path);
245497
245852
  if (componentRoot) {
@@ -245563,6 +245918,291 @@ function hasRunnableFrontendComponentEvidence(workspaceRoot, componentPath) {
245563
245918
  function isUnderJvmResourceRoot4(componentPath) {
245564
245919
  return /(^|\/)src\/main\/resources(?:\/|$)/u.test(normalizePath25(componentPath).toLowerCase());
245565
245920
  }
245921
+ function hasFileUnderRoot(root, pattern) {
245922
+ if (!pathExists19(root)) {
245923
+ return false;
245924
+ }
245925
+ const entries = fs58.readdirSync(root, { recursive: true, withFileTypes: true });
245926
+ return entries.some((entry) => entry.isFile() && pattern.test(entry.name));
245927
+ }
245928
+ var javaMainMethodPattern = /\bpublic\s+static\s+void\s+main\s*\(\s*String\s*(?:(?:\[\s*\]\s*)|\.\.\.\s*)[A-Za-z_$][\w$]*\s*(?:\[\s*\])?\s*\)/u;
245929
+ function stripJavaLikeCommentsAndStrings(value) {
245930
+ let result = "";
245931
+ let index = 0;
245932
+ let state = "code";
245933
+ while (index < value.length) {
245934
+ const current = value[index] ?? "";
245935
+ const next = value[index + 1] ?? "";
245936
+ const nextTwo = value.slice(index, index + 3);
245937
+ if (state === "code") {
245938
+ if (current === "/" && next === "/") {
245939
+ result += " ";
245940
+ index += 2;
245941
+ state = "line-comment";
245942
+ continue;
245943
+ }
245944
+ if (current === "/" && next === "*") {
245945
+ result += " ";
245946
+ index += 2;
245947
+ state = "block-comment";
245948
+ continue;
245949
+ }
245950
+ if (nextTwo === '"""') {
245951
+ result += " ";
245952
+ index += 3;
245953
+ state = "text-block";
245954
+ continue;
245955
+ }
245956
+ if (current === '"') {
245957
+ result += " ";
245958
+ index += 1;
245959
+ state = "string";
245960
+ continue;
245961
+ }
245962
+ if (current === "'") {
245963
+ result += " ";
245964
+ index += 1;
245965
+ state = "char";
245966
+ continue;
245967
+ }
245968
+ result += current;
245969
+ index += 1;
245970
+ continue;
245971
+ }
245972
+ if (state === "line-comment") {
245973
+ result += current === "\n" || current === "\r" ? current : " ";
245974
+ index += 1;
245975
+ if (current === "\n") {
245976
+ state = "code";
245977
+ }
245978
+ continue;
245979
+ }
245980
+ if (state === "block-comment") {
245981
+ if (current === "*" && next === "/") {
245982
+ result += " ";
245983
+ index += 2;
245984
+ state = "code";
245985
+ continue;
245986
+ }
245987
+ result += current === "\n" || current === "\r" ? current : " ";
245988
+ index += 1;
245989
+ continue;
245990
+ }
245991
+ if (state === "text-block") {
245992
+ if (nextTwo === '"""') {
245993
+ result += " ";
245994
+ index += 3;
245995
+ state = "code";
245996
+ continue;
245997
+ }
245998
+ result += current === "\n" || current === "\r" ? current : " ";
245999
+ index += 1;
246000
+ continue;
246001
+ }
246002
+ if (state === "string") {
246003
+ if (current === "\\") {
246004
+ result += " ";
246005
+ index += next ? 2 : 1;
246006
+ if (next) {
246007
+ result += " ";
246008
+ }
246009
+ continue;
246010
+ }
246011
+ result += current === "\n" || current === "\r" ? current : " ";
246012
+ index += 1;
246013
+ if (current === '"') {
246014
+ state = "code";
246015
+ }
246016
+ continue;
246017
+ }
246018
+ if (current === "\\") {
246019
+ result += " ";
246020
+ index += next ? 2 : 1;
246021
+ if (next) {
246022
+ result += " ";
246023
+ }
246024
+ continue;
246025
+ }
246026
+ result += current === "\n" || current === "\r" ? current : " ";
246027
+ index += 1;
246028
+ if (current === "'") {
246029
+ state = "code";
246030
+ }
246031
+ }
246032
+ return result;
246033
+ }
246034
+ function readMavenProductionSourceFiles(workspaceRoot, componentPath) {
246035
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
246036
+ const mainRoots = [
246037
+ path64.join(absoluteRoot, "src", "main", "java"),
246038
+ path64.join(absoluteRoot, "src", "main", "kotlin"),
246039
+ path64.join(absoluteRoot, "src", "main", "scala")
246040
+ ];
246041
+ const files = [];
246042
+ for (const sourceRoot of mainRoots) {
246043
+ if (!pathExists19(sourceRoot)) {
246044
+ continue;
246045
+ }
246046
+ const entries = fs58.readdirSync(sourceRoot, { recursive: true, withFileTypes: true });
246047
+ for (const entry of entries) {
246048
+ if (!entry.isFile() || !/\.(?:java|kt|scala)$/iu.test(entry.name)) {
246049
+ continue;
246050
+ }
246051
+ const contents = readTextFileSafe(path64.join(entry.parentPath, entry.name));
246052
+ if (contents) {
246053
+ files.push({ fileName: entry.name, contents });
246054
+ }
246055
+ }
246056
+ }
246057
+ return files;
246058
+ }
246059
+ function findMatchingBrace6(value, openBraceIndex) {
246060
+ let depth = 0;
246061
+ for (let index = openBraceIndex; index < value.length; index += 1) {
246062
+ const current = value[index];
246063
+ if (current === "{") {
246064
+ depth += 1;
246065
+ } else if (current === "}") {
246066
+ depth -= 1;
246067
+ if (depth === 0) {
246068
+ return index;
246069
+ }
246070
+ }
246071
+ }
246072
+ return -1;
246073
+ }
246074
+ function getDeclaredPackageName(value) {
246075
+ return value.match(/\bpackage\s+([a-zA-Z_$][\w$]*(?:\.[a-zA-Z_$][\w$]*)*)\s*;/u)?.[1];
246076
+ }
246077
+ function classNameMatchesConfiguredMainClass(className, packageName, configuredMainClass) {
246078
+ const normalized = configuredMainClass.trim();
246079
+ if (normalized.length === 0) {
246080
+ return false;
246081
+ }
246082
+ return normalized === className || (packageName ? normalized === `${packageName}.${className}` : false);
246083
+ }
246084
+ function normalizeAnnotationName(value) {
246085
+ return value.slice(value.lastIndexOf(".") + 1);
246086
+ }
246087
+ function hasAnnotation(annotations, annotationNames) {
246088
+ return annotations.some((annotation) => annotationNames.has(normalizeAnnotationName(annotation)));
246089
+ }
246090
+ function extractAnnotations(annotationBlock) {
246091
+ return [...annotationBlock.matchAll(/@\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)/gu)].map((match) => match[1]).filter((annotation) => Boolean(annotation));
246092
+ }
246093
+ function extractConcreteClassDeclarations(contents) {
246094
+ const sanitized = stripJavaLikeCommentsAndStrings(contents);
246095
+ const packageName = getDeclaredPackageName(sanitized);
246096
+ const classPattern = /((?:@\s*[\w.]+(?:\s*\([^)]*\))?\s*)*)(?:public\s+|protected\s+|private\s+|abstract\s+|final\s+|sealed\s+|non-sealed\s+|static\s+)*class\s+([A-Za-z_$][\w$]*)[^{]*\{/gu;
246097
+ const declarations = [];
246098
+ for (const match of sanitized.matchAll(classPattern)) {
246099
+ const annotationBlock = match[1] ?? "";
246100
+ const className = match[2] ?? "";
246101
+ const openBraceIndex = (match.index ?? 0) + match[0].length - 1;
246102
+ const closeBraceIndex = findMatchingBrace6(sanitized, openBraceIndex);
246103
+ if (closeBraceIndex < 0) {
246104
+ continue;
246105
+ }
246106
+ declarations.push({
246107
+ className,
246108
+ ...packageName ? { packageName } : {},
246109
+ annotations: extractAnnotations(annotationBlock),
246110
+ body: sanitized.slice(openBraceIndex + 1, closeBraceIndex)
246111
+ });
246112
+ }
246113
+ return declarations;
246114
+ }
246115
+ function extractApplicationAnnotationNames(sourceFiles) {
246116
+ const applicationAnnotations = /* @__PURE__ */ new Set(["SpringBootApplication"]);
246117
+ let changed = true;
246118
+ while (changed) {
246119
+ changed = false;
246120
+ for (const sourceFile of sourceFiles) {
246121
+ const sanitized = stripJavaLikeCommentsAndStrings(sourceFile.contents);
246122
+ const annotationPattern = /((?:@\s*[\w.]+(?:\s*\([^)]*\))?\s*)*)public\s+@interface\s+([A-Za-z_$][\w$]*)\b/gu;
246123
+ for (const match of sanitized.matchAll(annotationPattern)) {
246124
+ const annotations = extractAnnotations(match[1] ?? "");
246125
+ const annotationName = match[2];
246126
+ if (annotationName && !applicationAnnotations.has(annotationName) && hasAnnotation(annotations, applicationAnnotations)) {
246127
+ applicationAnnotations.add(annotationName);
246128
+ changed = true;
246129
+ }
246130
+ }
246131
+ }
246132
+ }
246133
+ return applicationAnnotations;
246134
+ }
246135
+ function hasSpringApplicationRunForClass(body, className) {
246136
+ return new RegExp(`\\bSpringApplication\\.run\\s*\\(\\s*${className}\\.class\\b`, "u").test(body);
246137
+ }
246138
+ function hasIndirectSpringApplicationRunForClass(body, className) {
246139
+ const helperCalls = [...body.matchAll(/\b([A-Za-z_$][\w$]*)\s*\(\s*([A-Za-z_$][\w$]*)\.class\s*,/gu)].filter((match) => match[2] === className).map((match) => match[1]).filter((methodName) => Boolean(methodName));
246140
+ return helperCalls.some(
246141
+ (methodName) => new RegExp(`\\b${methodName}\\s*\\([^)]*\\)\\s*\\{[\\s\\S]*?\\bSpringApplication\\.run\\s*\\(`, "u").test(body)
246142
+ );
246143
+ }
246144
+ function hasConcreteSpringBootApplicationBootstrap(sourceFiles) {
246145
+ const applicationAnnotations = extractApplicationAnnotationNames(sourceFiles);
246146
+ const declarations = sourceFiles.flatMap((sourceFile) => extractConcreteClassDeclarations(sourceFile.contents));
246147
+ const applicationClassNames = new Set(
246148
+ declarations.filter((declaration) => hasAnnotation(declaration.annotations, applicationAnnotations)).map((declaration) => declaration.className)
246149
+ );
246150
+ if (applicationClassNames.size === 0) {
246151
+ return false;
246152
+ }
246153
+ const hasLauncherForApplicationClass = (declaration) => javaMainMethodPattern.test(declaration.body) && [...applicationClassNames].some(
246154
+ (applicationClassName) => hasSpringApplicationRunForClass(declaration.body, applicationClassName) || applicationClassName === declaration.className && hasIndirectSpringApplicationRunForClass(declaration.body, applicationClassName)
246155
+ );
246156
+ if (declarations.some(hasLauncherForApplicationClass)) {
246157
+ return true;
246158
+ }
246159
+ for (const sourceFile of sourceFiles) {
246160
+ for (const declaration of extractConcreteClassDeclarations(sourceFile.contents)) {
246161
+ if (!hasAnnotation(declaration.annotations, applicationAnnotations)) {
246162
+ continue;
246163
+ }
246164
+ if (javaMainMethodPattern.test(declaration.body) && (hasSpringApplicationRunForClass(declaration.body, declaration.className) || hasIndirectSpringApplicationRunForClass(declaration.body, declaration.className))) {
246165
+ return true;
246166
+ }
246167
+ }
246168
+ }
246169
+ return false;
246170
+ }
246171
+ function hasConfiguredMainClassEntrypoint(contents, configuredMainClass) {
246172
+ for (const declaration of extractConcreteClassDeclarations(contents)) {
246173
+ if (!classNameMatchesConfiguredMainClass(declaration.className, declaration.packageName, configuredMainClass)) {
246174
+ continue;
246175
+ }
246176
+ if (javaMainMethodPattern.test(declaration.body)) {
246177
+ return true;
246178
+ }
246179
+ }
246180
+ return false;
246181
+ }
246182
+ function hasMavenMainEntrypoint(workspaceRoot, componentPath) {
246183
+ return hasConcreteSpringBootApplicationBootstrap(readMavenProductionSourceFiles(workspaceRoot, componentPath));
246184
+ }
246185
+ function hasMavenConfiguredMainClassEntrypoint(workspaceRoot, componentPath, configuredMainClass) {
246186
+ if (!configuredMainClass) {
246187
+ return false;
246188
+ }
246189
+ return readMavenProductionSourceFiles(workspaceRoot, componentPath).some((sourceFile) => hasConfiguredMainClassEntrypoint(sourceFile.contents, configuredMainClass));
246190
+ }
246191
+ function hasMavenAutoConfigurationMetadata(workspaceRoot, componentPath) {
246192
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
246193
+ return [
246194
+ path64.join(absoluteRoot, "src", "main", "resources", "META-INF", "spring.factories"),
246195
+ path64.join(absoluteRoot, "src", "main", "resources", "META-INF", "spring", "org.springframework.boot.autoconfigure.AutoConfiguration.imports")
246196
+ ].some(pathExists19);
246197
+ }
246198
+ function hasMavenMainJvmSource(workspaceRoot, componentPath) {
246199
+ const absoluteRoot = absoluteComponentRoot(workspaceRoot, componentPath);
246200
+ return [
246201
+ path64.join(absoluteRoot, "src", "main", "java"),
246202
+ path64.join(absoluteRoot, "src", "main", "kotlin"),
246203
+ path64.join(absoluteRoot, "src", "main", "scala")
246204
+ ].some((root) => hasFileUnderRoot(root, /\.(?:java|kt|scala)$/iu));
246205
+ }
245566
246206
  function hasRuntimeSourceFiles(workspaceRoot, componentPath) {
245567
246207
  if (isUnderJvmResourceRoot4(componentPath)) {
245568
246208
  return false;
@@ -245588,11 +246228,24 @@ function hasRuntimeSourceFiles(workspaceRoot, componentPath) {
245588
246228
  function resolveKind(workspaceRoot, candidate, localProjectKinds) {
245589
246229
  const lowerPath = candidate.path.toLowerCase();
245590
246230
  const packageJson = readPackageJson(workspaceRoot, candidate.path);
246231
+ const maven = readMavenMetadata(workspaceRoot, candidate.path);
245591
246232
  const hasRunnableFrontendEvidence = hasRunnableFrontendComponentEvidence(workspaceRoot, candidate.path);
245592
246233
  const hasPublishSurface = hasPackagePublishSurface(packageJson);
246234
+ const hasMavenRunnableEvidence = Boolean(
246235
+ maven && (hasMavenMainEntrypoint(workspaceRoot, candidate.path) || hasMavenConfiguredMainClassEntrypoint(workspaceRoot, candidate.path, maven.configuredMainClass) || maven.hasSpringBootPlugin && maven.hasSpringBootRepackageGoal && hasMavenMainEntrypoint(workspaceRoot, candidate.path) || maven.packaging === "war" && hasMavenMainEntrypoint(workspaceRoot, candidate.path))
246236
+ );
246237
+ const hasMavenLibraryEvidence = Boolean(
246238
+ maven && !hasMavenRunnableEvidence && (maven.packaging === "jar" || maven.packaging === "maven-plugin" || maven.packaging === "pom") && (hasMavenMainJvmSource(workspaceRoot, candidate.path) || maven.hasMainResources || maven.hasDependencyManagement || maven.hasSpringBootAutoconfigureDependency || maven.hasSpringBootAutoconfigureProcessor || hasMavenAutoConfigurationMetadata(workspaceRoot, candidate.path) || maven.hasDocumentationTooling || maven.hasTestJava || maven.hasTestResources)
246239
+ );
245593
246240
  if (lowerPath.endsWith("/db") || lowerPath.endsWith("/database") || lowerPath.endsWith("/data")) {
245594
246241
  return "data";
245595
246242
  }
246243
+ if (hasMavenLibraryEvidence) {
246244
+ return "library";
246245
+ }
246246
+ if (maven && !hasMavenRunnableEvidence && localProjectKinds.primaryKind === "backend") {
246247
+ return "library";
246248
+ }
245596
246249
  const classification = candidate.architectureRoot?.classification;
245597
246250
  if (classification === "frontend_app") {
245598
246251
  return hasPublishSurface && !hasRunnableFrontendEvidence ? "library" : "frontend";
@@ -245687,6 +246340,11 @@ function classifyGovernanceRole(input2) {
245687
246340
  const mavenMetadataText = `${maven?.artifactId ?? ""} ${maven?.name ?? ""}`.toLowerCase();
245688
246341
  const hasMavenMainSource = Boolean(maven?.hasMainJava || maven?.hasMainResources);
245689
246342
  const hasMavenTestSource = Boolean(maven?.hasTestJava || maven?.hasTestResources);
246343
+ const hasMavenMainEntrypointEvidence = Boolean(maven && hasMavenMainEntrypoint(input2.workspaceRoot, input2.candidate.path));
246344
+ const hasMavenMainJvmSourceEvidence = Boolean(maven && hasMavenMainJvmSource(input2.workspaceRoot, input2.candidate.path));
246345
+ const hasMavenAutoConfigurationEvidence = Boolean(maven && (hasMavenAutoConfigurationMetadata(input2.workspaceRoot, input2.candidate.path) || maven.hasSpringBootAutoconfigureDependency || maven.hasSpringBootAutoconfigureProcessor));
246346
+ const hasMavenExecutableConfiguration = Boolean(maven && (hasMavenConfiguredMainClassEntrypoint(input2.workspaceRoot, input2.candidate.path, maven.configuredMainClass) || maven.hasSpringBootPlugin && maven.hasSpringBootRepackageGoal && hasMavenMainEntrypointEvidence || maven.packaging === "war" && hasMavenMainEntrypointEvidence));
246347
+ const hasMavenRunnableApplicationEvidence = Boolean(hasMavenMainEntrypointEvidence || hasMavenExecutableConfiguration);
245690
246348
  const isMavenPomOnly = Boolean(maven?.packaging === "pom" && !hasMavenMainSource && !hasMavenTestSource);
245691
246349
  const hasMavenTestContext = hasAnyToken(pathText, [
245692
246350
  /(^|\/)(test-framework|testsuite|integration-tests?|test-apps)(\/|$)/u
@@ -245697,6 +246355,9 @@ function classifyGovernanceRole(input2) {
245697
246355
  const hasMavenDistributionPackagingEvidence = Boolean(
245698
246356
  maven?.packaging === "pom" && !hasMavenMainSource && hasAnyToken(pathText, [/(^|\/)(distribution|dist|downloads|assembl(y|ies)|feature-packs?)(\/|$)/u])
245699
246357
  );
246358
+ const hasMavenStarterPackagingEvidence = Boolean(
246359
+ maven && !hasMavenMainJvmSourceEvidence && hasAnyToken(`${pathText} ${mavenMetadataText}`, [/\bstarters?\b|\bspring-boot-starter\b|\bstarter[-\s]/u])
246360
+ );
245700
246361
  if (input2.candidate.architectureRoot?.classification === "backend_app" || input2.candidate.architectureRoot?.classification === "frontend_app") {
245701
246362
  runtimeScore += 3;
245702
246363
  addEvidence6(evidence, `Runtime architecture root signal: ${input2.candidate.architectureRoot.classification}`);
@@ -245725,17 +246386,19 @@ function classifyGovernanceRole(input2) {
245725
246386
  if (maven?.hasPom) {
245726
246387
  addEvidence6(evidence, `Maven packaging ${maven.packaging ?? "jar"}`);
245727
246388
  }
245728
- if (maven && (maven.packaging === "jar" || maven.packaging === "war") && hasMavenMainSource) {
246389
+ if (maven && (maven.packaging === "jar" || maven.packaging === "war") && hasMavenRunnableApplicationEvidence) {
245729
246390
  runtimeScore += 3;
245730
- addEvidence6(evidence, "Maven runtime source layout");
246391
+ addEvidence6(evidence, "Maven executable application evidence");
245731
246392
  }
245732
- if (maven?.packaging === "war" && hasMavenMainSource) {
246393
+ if (maven?.packaging === "war" && hasMavenMainJvmSourceEvidence) {
245733
246394
  runtimeScore += 1;
245734
246395
  addEvidence6(evidence, "Maven deployable WAR artifact");
245735
246396
  }
245736
- if (maven && hasMavenMainSource && !hasMavenTestContext && !hasMavenBomEvidence && maven.packaging !== "maven-plugin") {
245737
- runtimeScore += 1;
245738
- addEvidence6(evidence, "Maven main source/resource surface");
246397
+ if (maven && hasMavenMainSource && !hasMavenRunnableApplicationEvidence && !hasMavenTestContext && !hasMavenBomEvidence && maven.packaging !== "maven-plugin") {
246398
+ addEvidence6(evidence, "Maven library main source/resource surface");
246399
+ }
246400
+ if (hasMavenAutoConfigurationEvidence && !hasMavenRunnableApplicationEvidence) {
246401
+ addEvidence6(evidence, "Maven Spring Boot auto-configuration/starter library evidence");
245739
246402
  }
245740
246403
  if (hasAnyToken(descriptiveManifestText, [/\b(e2e|end-to-end|testing|test helper|test utilities|fixtures?)\b/u])) {
245741
246404
  supportScore += 3;
@@ -245776,6 +246439,10 @@ function classifyGovernanceRole(input2) {
245776
246439
  supportScore += 5;
245777
246440
  addEvidence6(evidence, "Maven plugin/build-tooling module");
245778
246441
  }
246442
+ if (maven?.hasDocumentationTooling && !hasMavenMainJvmSourceEvidence) {
246443
+ supportScore += 4;
246444
+ addEvidence6(evidence, "Maven documentation tooling without JVM runtime source");
246445
+ }
245779
246446
  if (hasMavenBomEvidence) {
245780
246447
  supportScore += 5;
245781
246448
  addEvidence6(evidence, "Maven BOM/dependency-management module without runtime source");
@@ -245800,6 +246467,10 @@ function classifyGovernanceRole(input2) {
245800
246467
  supportScore += 1;
245801
246468
  addEvidence6(evidence, "Maven POM-only aggregator/packaging module");
245802
246469
  }
246470
+ if (hasMavenStarterPackagingEvidence) {
246471
+ supportScore += 4;
246472
+ addEvidence6(evidence, "Maven starter/resource artifact without JVM runtime source");
246473
+ }
245803
246474
  if (isPlainResourcesSurface) {
245804
246475
  supportScore += 4;
245805
246476
  addEvidence6(evidence, "Resources-only surface without runtime source or manifest evidence");
@@ -245811,6 +246482,13 @@ function classifyGovernanceRole(input2) {
245811
246482
  selectedByDefault: false
245812
246483
  };
245813
246484
  }
246485
+ if (hasMavenStarterPackagingEvidence && !hasMavenMainJvmSourceEvidence) {
246486
+ return {
246487
+ governanceRole: "support",
246488
+ governanceEvidence: uniqueSorted4(evidence),
246489
+ selectedByDefault: false
246490
+ };
246491
+ }
245814
246492
  if (hasMavenDistributionPackagingEvidence && hasAnyToken(mavenMetadataText, [/\b(docs?|documentation|metadata tests?|licenses?|maven plugins?|builds?)\b/u])) {
245815
246493
  supportScore += 3;
245816
246494
  addEvidence6(evidence, "Maven documentation/build/distribution packaging evidence without runtime source");
@@ -245870,7 +246548,7 @@ function detectComponents(input2) {
245870
246548
  const manifestBackedRoots = new Set(
245871
246549
  (input2.topology.detectedRoots ?? []).filter((root) => !isUnderJvmResourceRoot4(root))
245872
246550
  );
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) => {
246551
+ const rootCandidates = buildRootCandidates({ ...input2, workspaceRoot: input2.workspaceRoot }).filter((candidate) => !ignoreMatcher.isIgnored(candidate.path) || hasDeclaredMavenReactorEvidence(candidate)).filter((candidate) => !isIgnoredComponentCandidatePath(candidate.path)).filter((candidate) => !(isUnderJvmResourceRoot4(candidate.path) && !hasRuntimeSourceFiles(input2.workspaceRoot, candidate.path))).filter((candidate) => {
245874
246552
  if (input2.topology.topology !== "monorepo" || manifestBackedRoots.size === 0) {
245875
246553
  return true;
245876
246554
  }
@@ -246168,7 +246846,7 @@ function isCliSupportCandidate(component, allComponents) {
246168
246846
  }
246169
246847
  function hasIndependentRuntimeEvidence(component) {
246170
246848
  const text = componentEvidenceText(component);
246171
- return component.governanceRole === "runtime" && (/Maven runtime source layout/iu.test(text) || /Maven main source\/resource surface/iu.test(text) || /Published package surface signal/iu.test(text) && !/Path contains support\/tooling role tokens/iu.test(text));
246849
+ return component.governanceRole === "runtime" && (/Maven executable application evidence/iu.test(text) || /Maven deployable WAR artifact/iu.test(text) || /Maven library main source\/resource surface/iu.test(text) || /Maven Spring Boot auto-configuration\/starter library evidence/iu.test(text) || /Published package surface signal/iu.test(text) && !/Path contains support\/tooling role tokens/iu.test(text));
246172
246850
  }
246173
246851
  function hasSupportRoleEvidence(component) {
246174
246852
  const text = componentEvidenceText(component);
@@ -246378,7 +247056,20 @@ function hasAttributableBackendRoot(detection) {
246378
247056
  return getBackendComponents(detection).length > 0;
246379
247057
  }
246380
247058
  function isGenericLibraryStack(stack) {
246381
- return stack === "node_typescript" || stack === "node_javascript" || stack === "python" || stack === "go" || stack === "kotlin" || stack === "terraform" || stack === "ansible";
247059
+ return stack === "node_typescript" || stack === "node_javascript" || stack === "library_generic" || stack === "java" || stack === "spring" || stack === "python" || stack === "go" || stack === "kotlin" || stack === "kotlin_spring" || stack === "terraform" || stack === "ansible";
247060
+ }
247061
+ function preferredLibraryStack(stacks) {
247062
+ const uniqueStacks = uniqueInOrder2(stacks);
247063
+ if (uniqueStacks.length <= 1) {
247064
+ return isJvmLibraryStack(uniqueStacks[0]) ? "library_generic" : uniqueStacks[0];
247065
+ }
247066
+ if (uniqueStacks.some(isJvmLibraryStack) && uniqueStacks.every((candidate) => isJvmLibraryStack(candidate) || candidate === "node_typescript" || candidate === "node_javascript")) {
247067
+ return "library_generic";
247068
+ }
247069
+ return void 0;
247070
+ }
247071
+ function isJvmLibraryStack(stack) {
247072
+ return stack === "java" || stack === "spring";
246382
247073
  }
246383
247074
  function hasProjectKindEvidence(detection, patterns) {
246384
247075
  const evidence = detection.projectKinds?.evidence ?? [];
@@ -246800,7 +247491,7 @@ function resolveStackSelections(detection, projectKinds) {
246800
247491
  const libraryComponentStacks = uniqueInOrder2(
246801
247492
  libraryComponents.map((component) => component.stack).filter((stack) => isGenericLibraryStack(stack))
246802
247493
  );
246803
- const selectedLibrary = detection.topology.topology === "monorepo" ? libraryComponentStacks.length === 1 ? libraryComponentStacks[0] : void 0 : detection.stacks.selectedAdapterId;
247494
+ const selectedLibrary = detection.topology.topology === "monorepo" ? preferredLibraryStack(libraryComponentStacks) : detection.stacks.selectedAdapterId;
246804
247495
  if (isGenericLibraryStack(selectedLibrary)) {
246805
247496
  selections.library = selectedLibrary;
246806
247497
  }
@@ -246822,7 +247513,7 @@ function resolveProjectProfiles(detection, projectKinds, stackSelections, apiSty
246822
247513
  selectedAdapterId: stackId,
246823
247514
  selectedAdapterCategory: getStackAdapterById(stackId).category,
246824
247515
  projectKinds: [kind],
246825
- apiStyleHint: kind === "backend" && apiStyle ? apiStyle : resolveRoleApiStyleHint(detection, stackId, component),
247516
+ apiStyleHint: kind === "backend" && apiStyle ? apiStyle : stackId === "library_generic" ? void 0 : resolveRoleApiStyleHint(detection, stackId, component),
246826
247517
  databaseHints: detection.toolingHints?.databaseHints,
246827
247518
  toolingHints: detection.toolingHints?.toolingHints,
246828
247519
  repoTopology: detection.topology.topology === "unknown" ? "single_project" : detection.topology.topology