@archpilotlabs/archpilot 0.2.2 → 0.2.3

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 (296) hide show
  1. package/dist/archpilot-cli.js +516 -105
  2. package/dist/cli/src/archpilot-cli.js +5523 -0
  3. package/dist/cli/src/archpilot-cli.js.map +1 -0
  4. package/dist/core/src/adr/adrLoader.js +97 -0
  5. package/dist/core/src/adr/adrLoader.js.map +1 -0
  6. package/dist/core/src/adr/adrParser.js +77 -0
  7. package/dist/core/src/adr/adrParser.js.map +1 -0
  8. package/dist/core/src/adr/adrTemplate.js +45 -0
  9. package/dist/core/src/adr/adrTemplate.js.map +1 -0
  10. package/dist/core/src/adr/adrTypes.js +3 -0
  11. package/dist/core/src/adr/adrTypes.js.map +1 -0
  12. package/dist/core/src/adr/adrValidation.js +160 -0
  13. package/dist/core/src/adr/adrValidation.js.map +1 -0
  14. package/dist/core/src/adr/index.js +9 -0
  15. package/dist/core/src/adr/index.js.map +1 -0
  16. package/dist/core/src/adrManagement.js +174 -0
  17. package/dist/core/src/adrManagement.js.map +1 -0
  18. package/dist/core/src/adrRequirementStatus.js +62 -0
  19. package/dist/core/src/adrRequirementStatus.js.map +1 -0
  20. package/dist/core/src/adrScaffoldGeneration.js +325 -0
  21. package/dist/core/src/adrScaffoldGeneration.js.map +1 -0
  22. package/dist/core/src/apiDesignAnalysis.js +869 -0
  23. package/dist/core/src/apiDesignAnalysis.js.map +1 -0
  24. package/dist/core/src/applicationLayeringAnalysis.js +920 -0
  25. package/dist/core/src/applicationLayeringAnalysis.js.map +1 -0
  26. package/dist/core/src/applyRulePack.js +117 -0
  27. package/dist/core/src/applyRulePack.js.map +1 -0
  28. package/dist/core/src/architectureBaseline.js +271 -0
  29. package/dist/core/src/architectureBaseline.js.map +1 -0
  30. package/dist/core/src/architectureComponentDiscoveryDefaults.js +139 -0
  31. package/dist/core/src/architectureComponentDiscoveryDefaults.js.map +1 -0
  32. package/dist/core/src/architectureDependencyContext.js +316 -0
  33. package/dist/core/src/architectureDependencyContext.js.map +1 -0
  34. package/dist/core/src/architectureDriftDetection.js +96 -0
  35. package/dist/core/src/architectureDriftDetection.js.map +1 -0
  36. package/dist/core/src/architectureDriftTimeline.js +221 -0
  37. package/dist/core/src/architectureDriftTimeline.js.map +1 -0
  38. package/dist/core/src/architectureGovernanceBaseline.js +469 -0
  39. package/dist/core/src/architectureGovernanceBaseline.js.map +1 -0
  40. package/dist/core/src/architectureHealthHistory.js +208 -0
  41. package/dist/core/src/architectureHealthHistory.js.map +1 -0
  42. package/dist/core/src/architectureHealthScore.js +657 -0
  43. package/dist/core/src/architectureHealthScore.js.map +1 -0
  44. package/dist/core/src/architectureInit.js +826 -0
  45. package/dist/core/src/architectureInit.js.map +1 -0
  46. package/dist/core/src/architectureMap.js +727 -0
  47. package/dist/core/src/architectureMap.js.map +1 -0
  48. package/dist/core/src/architectureMigrationPreview.js +467 -0
  49. package/dist/core/src/architectureMigrationPreview.js.map +1 -0
  50. package/dist/core/src/architectureModelRefresh.js +209 -0
  51. package/dist/core/src/architectureModelRefresh.js.map +1 -0
  52. package/dist/core/src/architectureReportWorkflow.js +139 -0
  53. package/dist/core/src/architectureReportWorkflow.js.map +1 -0
  54. package/dist/core/src/architectureValidation.js +3879 -0
  55. package/dist/core/src/architectureValidation.js.map +1 -0
  56. package/dist/core/src/architectureWorkspaceModel.js +166 -0
  57. package/dist/core/src/architectureWorkspaceModel.js.map +1 -0
  58. package/dist/core/src/authorizationTenantAnalysis.js +652 -0
  59. package/dist/core/src/authorizationTenantAnalysis.js.map +1 -0
  60. package/dist/core/src/bootstrapArchitectureConfig.js +150 -0
  61. package/dist/core/src/bootstrapArchitectureConfig.js.map +1 -0
  62. package/dist/core/src/changeRisk/changeRiskAssessment.js +251 -0
  63. package/dist/core/src/changeRisk/changeRiskAssessment.js.map +1 -0
  64. package/dist/core/src/changeRisk/changeRiskTypes.js +3 -0
  65. package/dist/core/src/changeRisk/changeRiskTypes.js.map +1 -0
  66. package/dist/core/src/changeRisk/index.js +6 -0
  67. package/dist/core/src/changeRisk/index.js.map +1 -0
  68. package/dist/core/src/ci/githubInlineAnnotations.js +245 -0
  69. package/dist/core/src/ci/githubInlineAnnotations.js.map +1 -0
  70. package/dist/core/src/ci/githubPrCommentAdapter.js +232 -0
  71. package/dist/core/src/ci/githubPrCommentAdapter.js.map +1 -0
  72. package/dist/core/src/ciWorkflowTemplates.js +1042 -0
  73. package/dist/core/src/ciWorkflowTemplates.js.map +1 -0
  74. package/dist/core/src/compliance/complianceExportBuilder.js +122 -0
  75. package/dist/core/src/compliance/complianceExportBuilder.js.map +1 -0
  76. package/dist/core/src/compliance/complianceExportTypes.js +3 -0
  77. package/dist/core/src/compliance/complianceExportTypes.js.map +1 -0
  78. package/dist/core/src/compliance/complianceExportWriter.js +48 -0
  79. package/dist/core/src/compliance/complianceExportWriter.js.map +1 -0
  80. package/dist/core/src/compliance/complianceRulePackResolver.js +62 -0
  81. package/dist/core/src/compliance/complianceRulePackResolver.js.map +1 -0
  82. package/dist/core/src/config/index.js +17 -0
  83. package/dist/core/src/config/index.js.map +1 -0
  84. package/dist/core/src/config/projectConfig.js +224 -0
  85. package/dist/core/src/config/projectConfig.js.map +1 -0
  86. package/dist/core/src/config/projectIdentity.js +160 -0
  87. package/dist/core/src/config/projectIdentity.js.map +1 -0
  88. package/dist/core/src/dataQueryRiskDetection.js +1203 -0
  89. package/dist/core/src/dataQueryRiskDetection.js.map +1 -0
  90. package/dist/core/src/dependencyValidation.js +2557 -0
  91. package/dist/core/src/dependencyValidation.js.map +1 -0
  92. package/dist/core/src/discoverAdrs.js +15 -0
  93. package/dist/core/src/discoverAdrs.js.map +1 -0
  94. package/dist/core/src/drift/driftComparator.js +49 -0
  95. package/dist/core/src/drift/driftComparator.js.map +1 -0
  96. package/dist/core/src/drift/driftSnapshotLoader.js +136 -0
  97. package/dist/core/src/drift/driftSnapshotLoader.js.map +1 -0
  98. package/dist/core/src/drift/driftSnapshotTypes.js +3 -0
  99. package/dist/core/src/drift/driftSnapshotTypes.js.map +1 -0
  100. package/dist/core/src/drift/driftSnapshotWriter.js +48 -0
  101. package/dist/core/src/drift/driftSnapshotWriter.js.map +1 -0
  102. package/dist/core/src/drift/index.js +6 -0
  103. package/dist/core/src/drift/index.js.map +1 -0
  104. package/dist/core/src/eventArchitectureAnalysis.js +925 -0
  105. package/dist/core/src/eventArchitectureAnalysis.js.map +1 -0
  106. package/dist/core/src/findingTargetResolution.js +117 -0
  107. package/dist/core/src/findingTargetResolution.js.map +1 -0
  108. package/dist/core/src/generateArchitectureDiagrams.js +57 -0
  109. package/dist/core/src/generateArchitectureDiagrams.js.map +1 -0
  110. package/dist/core/src/generateImpactAnalysis.js +366 -0
  111. package/dist/core/src/generateImpactAnalysis.js.map +1 -0
  112. package/dist/core/src/generateOnboardingDocs.js +262 -0
  113. package/dist/core/src/generateOnboardingDocs.js.map +1 -0
  114. package/dist/core/src/governance/cloudConnection.js +203 -0
  115. package/dist/core/src/governance/cloudConnection.js.map +1 -0
  116. package/dist/core/src/governance/governanceContracts.js +129 -0
  117. package/dist/core/src/governance/governanceContracts.js.map +1 -0
  118. package/dist/core/src/governance/governanceGitMetadata.js +78 -0
  119. package/dist/core/src/governance/governanceGitMetadata.js.map +1 -0
  120. package/dist/core/src/governance/governanceUploadClient.js +119 -0
  121. package/dist/core/src/governance/governanceUploadClient.js.map +1 -0
  122. package/dist/core/src/governance/governanceUploadLimitErrorFormatting.js +155 -0
  123. package/dist/core/src/governance/governanceUploadLimitErrorFormatting.js.map +1 -0
  124. package/dist/core/src/governance/governanceUploadPayload.js +439 -0
  125. package/dist/core/src/governance/governanceUploadPayload.js.map +1 -0
  126. package/dist/core/src/governance/runGovernanceUpload.js +103 -0
  127. package/dist/core/src/governance/runGovernanceUpload.js.map +1 -0
  128. package/dist/core/src/impactAnalysisEngine.js +376 -0
  129. package/dist/core/src/impactAnalysisEngine.js.map +1 -0
  130. package/dist/core/src/initializationState.js +99 -0
  131. package/dist/core/src/initializationState.js.map +1 -0
  132. package/dist/core/src/managedArtifacts.js +151 -0
  133. package/dist/core/src/managedArtifacts.js.map +1 -0
  134. package/dist/core/src/moduleContractValidation.js +266 -0
  135. package/dist/core/src/moduleContractValidation.js.map +1 -0
  136. package/dist/core/src/moduleContractsGenerator.js +337 -0
  137. package/dist/core/src/moduleContractsGenerator.js.map +1 -0
  138. package/dist/core/src/moduleDiscovery.js +416 -0
  139. package/dist/core/src/moduleDiscovery.js.map +1 -0
  140. package/dist/core/src/moduleScope.js +426 -0
  141. package/dist/core/src/moduleScope.js.map +1 -0
  142. package/dist/core/src/onboardingGuidance.js +74 -0
  143. package/dist/core/src/onboardingGuidance.js.map +1 -0
  144. package/dist/core/src/operationalLogging.js +7 -0
  145. package/dist/core/src/operationalLogging.js.map +1 -0
  146. package/dist/core/src/packageVersion.js +52 -0
  147. package/dist/core/src/packageVersion.js.map +1 -0
  148. package/dist/core/src/policy/effectivePolicyResolver.js +91 -0
  149. package/dist/core/src/policy/effectivePolicyResolver.js.map +1 -0
  150. package/dist/core/src/policy/exceptionLoader.js +285 -0
  151. package/dist/core/src/policy/exceptionLoader.js.map +1 -0
  152. package/dist/core/src/policy/remotePolicyLoader.js +227 -0
  153. package/dist/core/src/policy/remotePolicyLoader.js.map +1 -0
  154. package/dist/core/src/policy/remotePolicyTypes.js +3 -0
  155. package/dist/core/src/policy/remotePolicyTypes.js.map +1 -0
  156. package/dist/core/src/policy/riskPolicyConfig.js +206 -0
  157. package/dist/core/src/policy/riskPolicyConfig.js.map +1 -0
  158. package/dist/core/src/policy/riskPolicyEnforcement.js +203 -0
  159. package/dist/core/src/policy/riskPolicyEnforcement.js.map +1 -0
  160. package/dist/core/src/policy/riskPolicyExitCode.js +16 -0
  161. package/dist/core/src/policy/riskPolicyExitCode.js.map +1 -0
  162. package/dist/core/src/policy/riskPolicyInitializer.js +90 -0
  163. package/dist/core/src/policy/riskPolicyInitializer.js.map +1 -0
  164. package/dist/core/src/quickFix/quickFixEngine.js +132 -0
  165. package/dist/core/src/quickFix/quickFixEngine.js.map +1 -0
  166. package/dist/core/src/quickFix/quickFixMessaging.js +15 -0
  167. package/dist/core/src/quickFix/quickFixMessaging.js.map +1 -0
  168. package/dist/core/src/quickFix/quickFixProviders.js +87 -0
  169. package/dist/core/src/quickFix/quickFixProviders.js.map +1 -0
  170. package/dist/core/src/quickFix/quickFixTypes.js +3 -0
  171. package/dist/core/src/quickFix/quickFixTypes.js.map +1 -0
  172. package/dist/core/src/remediation/fileHelpers.js +86 -0
  173. package/dist/core/src/remediation/fileHelpers.js.map +1 -0
  174. package/dist/core/src/remediation/fixRegistry.js +645 -0
  175. package/dist/core/src/remediation/fixRegistry.js.map +1 -0
  176. package/dist/core/src/remediation/index.js +8 -0
  177. package/dist/core/src/remediation/index.js.map +1 -0
  178. package/dist/core/src/remediation/remediationEngine.js +207 -0
  179. package/dist/core/src/remediation/remediationEngine.js.map +1 -0
  180. package/dist/core/src/reporting/adrReporter.js +59 -0
  181. package/dist/core/src/reporting/adrReporter.js.map +1 -0
  182. package/dist/core/src/reporting/architectureBaselineReporter.js +64 -0
  183. package/dist/core/src/reporting/architectureBaselineReporter.js.map +1 -0
  184. package/dist/core/src/reporting/architectureDiagramReporter.js +148 -0
  185. package/dist/core/src/reporting/architectureDiagramReporter.js.map +1 -0
  186. package/dist/core/src/reporting/architectureDriftTimelineReporter.js +44 -0
  187. package/dist/core/src/reporting/architectureDriftTimelineReporter.js.map +1 -0
  188. package/dist/core/src/reporting/architectureHealthHistoryReporter.js +51 -0
  189. package/dist/core/src/reporting/architectureHealthHistoryReporter.js.map +1 -0
  190. package/dist/core/src/reporting/architectureMapReporter.js +228 -0
  191. package/dist/core/src/reporting/architectureMapReporter.js.map +1 -0
  192. package/dist/core/src/reporting/architecturePrCommentReporter.js +324 -0
  193. package/dist/core/src/reporting/architecturePrCommentReporter.js.map +1 -0
  194. package/dist/core/src/reporting/architecturePrReviewReporter.js +389 -0
  195. package/dist/core/src/reporting/architecturePrReviewReporter.js.map +1 -0
  196. package/dist/core/src/reporting/architectureReportArtifacts.js +166 -0
  197. package/dist/core/src/reporting/architectureReportArtifacts.js.map +1 -0
  198. package/dist/core/src/reporting/architectureReviewReportGenerator.js +382 -0
  199. package/dist/core/src/reporting/architectureReviewReportGenerator.js.map +1 -0
  200. package/dist/core/src/reporting/architectureReviewReporter.js +1633 -0
  201. package/dist/core/src/reporting/architectureReviewReporter.js.map +1 -0
  202. package/dist/core/src/reporting/architectureRiskAssessment.js +101 -0
  203. package/dist/core/src/reporting/architectureRiskAssessment.js.map +1 -0
  204. package/dist/core/src/reporting/architectureScoreBadge.js +177 -0
  205. package/dist/core/src/reporting/architectureScoreBadge.js.map +1 -0
  206. package/dist/core/src/reporting/architectureSupplementalReporters.js +124 -0
  207. package/dist/core/src/reporting/architectureSupplementalReporters.js.map +1 -0
  208. package/dist/core/src/reporting/changeRiskAssessment.js +6 -0
  209. package/dist/core/src/reporting/changeRiskAssessment.js.map +1 -0
  210. package/dist/core/src/reporting/changeRiskTypes.js +3 -0
  211. package/dist/core/src/reporting/changeRiskTypes.js.map +1 -0
  212. package/dist/core/src/reporting/impactAnalysisReporter.js +111 -0
  213. package/dist/core/src/reporting/impactAnalysisReporter.js.map +1 -0
  214. package/dist/core/src/reporting/onboardingDocsReporter.js +113 -0
  215. package/dist/core/src/reporting/onboardingDocsReporter.js.map +1 -0
  216. package/dist/core/src/reporting/rulePackReporter.js +61 -0
  217. package/dist/core/src/reporting/rulePackReporter.js.map +1 -0
  218. package/dist/core/src/reporting/safetyControlsDetection.js +343 -0
  219. package/dist/core/src/reporting/safetyControlsDetection.js.map +1 -0
  220. package/dist/core/src/resolveRuleAdrs.js +31 -0
  221. package/dist/core/src/resolveRuleAdrs.js.map +1 -0
  222. package/dist/core/src/reviewGenerationWorkflow.js +220 -0
  223. package/dist/core/src/reviewGenerationWorkflow.js.map +1 -0
  224. package/dist/core/src/rulePacks/index.js +17 -0
  225. package/dist/core/src/rulePacks/index.js.map +1 -0
  226. package/dist/core/src/rulePacks/layeredMonolithRulePack.js +45 -0
  227. package/dist/core/src/rulePacks/layeredMonolithRulePack.js.map +1 -0
  228. package/dist/core/src/rulePacks/modularMonolithRulePack.js +41 -0
  229. package/dist/core/src/rulePacks/modularMonolithRulePack.js.map +1 -0
  230. package/dist/core/src/rulePacks/types.js +3 -0
  231. package/dist/core/src/rulePacks/types.js.map +1 -0
  232. package/dist/core/src/setupNextSteps.js +939 -0
  233. package/dist/core/src/setupNextSteps.js.map +1 -0
  234. package/dist/core/src/setupRefresh.js +152 -0
  235. package/dist/core/src/setupRefresh.js.map +1 -0
  236. package/dist/core/src/smartInit/apiDbHintDetection.js +836 -0
  237. package/dist/core/src/smartInit/apiDbHintDetection.js.map +1 -0
  238. package/dist/core/src/smartInit/architectureProposalBuilder.js +1215 -0
  239. package/dist/core/src/smartInit/architectureProposalBuilder.js.map +1 -0
  240. package/dist/core/src/smartInit/architectureStyleDetection.js +472 -0
  241. package/dist/core/src/smartInit/architectureStyleDetection.js.map +1 -0
  242. package/dist/core/src/smartInit/archpilotIgnore.js +139 -0
  243. package/dist/core/src/smartInit/archpilotIgnore.js.map +1 -0
  244. package/dist/core/src/smartInit/componentDetection.js +1084 -0
  245. package/dist/core/src/smartInit/componentDetection.js.map +1 -0
  246. package/dist/core/src/smartInit/implementationProfileResolution.js +53 -0
  247. package/dist/core/src/smartInit/implementationProfileResolution.js.map +1 -0
  248. package/dist/core/src/smartInit/index.js +31 -0
  249. package/dist/core/src/smartInit/index.js.map +1 -0
  250. package/dist/core/src/smartInit/moduleDetection.js +982 -0
  251. package/dist/core/src/smartInit/moduleDetection.js.map +1 -0
  252. package/dist/core/src/smartInit/projectKindDetection.js +437 -0
  253. package/dist/core/src/smartInit/projectKindDetection.js.map +1 -0
  254. package/dist/core/src/smartInit/repoTopologyDetection.js +470 -0
  255. package/dist/core/src/smartInit/repoTopologyDetection.js.map +1 -0
  256. package/dist/core/src/smartInit/runContext.js +112 -0
  257. package/dist/core/src/smartInit/runContext.js.map +1 -0
  258. package/dist/core/src/smartInit/smartInitEngine.js +94 -0
  259. package/dist/core/src/smartInit/smartInitEngine.js.map +1 -0
  260. package/dist/core/src/smartInit/stackDetection.js +503 -0
  261. package/dist/core/src/smartInit/stackDetection.js.map +1 -0
  262. package/dist/core/src/smartInit/toolingHintDetection.js +345 -0
  263. package/dist/core/src/smartInit/toolingHintDetection.js.map +1 -0
  264. package/dist/core/src/sourceScopeClassification.js +83 -0
  265. package/dist/core/src/sourceScopeClassification.js.map +1 -0
  266. package/dist/core/src/stackAdapters.js +2475 -0
  267. package/dist/core/src/stackAdapters.js.map +1 -0
  268. package/dist/core/src/stackMetadata.js +157 -0
  269. package/dist/core/src/stackMetadata.js.map +1 -0
  270. package/dist/core/src/suppressions/index.js +3 -0
  271. package/dist/core/src/suppressions/index.js.map +1 -0
  272. package/dist/core/src/suppressions/suppressionReporter.js +38 -0
  273. package/dist/core/src/suppressions/suppressionReporter.js.map +1 -0
  274. package/dist/core/src/suppressions/suppressionTypes.js +3 -0
  275. package/dist/core/src/suppressions/suppressionTypes.js.map +1 -0
  276. package/dist/core/src/suppressions/suppressionValidator.js +119 -0
  277. package/dist/core/src/suppressions/suppressionValidator.js.map +1 -0
  278. package/dist/core/src/transactionDomainAnalysis.js +1416 -0
  279. package/dist/core/src/transactionDomainAnalysis.js.map +1 -0
  280. package/dist/core/src/validation/changedFilesResolver.js +165 -0
  281. package/dist/core/src/validation/changedFilesResolver.js.map +1 -0
  282. package/dist/core/src/validationProfiling.js +33 -0
  283. package/dist/core/src/validationProfiling.js.map +1 -0
  284. package/dist/core/src/validationRuleExplanations.js +69 -0
  285. package/dist/core/src/validationRuleExplanations.js.map +1 -0
  286. package/dist/core/src/validationSourceInventory.js +200 -0
  287. package/dist/core/src/validationSourceInventory.js.map +1 -0
  288. package/dist/core/src/validationSuppressions.js +231 -0
  289. package/dist/core/src/validationSuppressions.js.map +1 -0
  290. package/dist/core/src/validationTypeScriptAstCache.js +82 -0
  291. package/dist/core/src/validationTypeScriptAstCache.js.map +1 -0
  292. package/dist/core/src/validationWorkflow.js +222 -0
  293. package/dist/core/src/validationWorkflow.js.map +1 -0
  294. package/dist/core/src/workspaceRoot.js +68 -0
  295. package/dist/core/src/workspaceRoot.js.map +1 -0
  296. package/package.json +1 -1
@@ -0,0 +1,920 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.detectApplicationLayeringFindings = detectApplicationLayeringFindings;
37
+ const path = __importStar(require("node:path"));
38
+ const node_fs_1 = require("node:fs");
39
+ const ts = __importStar(require("typescript"));
40
+ const moduleDiscovery_1 = require("./moduleDiscovery");
41
+ const archpilotIgnore_1 = require("./smartInit/archpilotIgnore");
42
+ const validationProfiling_1 = require("./validationProfiling");
43
+ const sourceScopeClassification_1 = require("./sourceScopeClassification");
44
+ const ApplicationLayeringRuleIds = {
45
+ CONTROLLER_BUSINESS_LOGIC: 'AP-APP-001',
46
+ REPOSITORY_BUSINESS_LOGIC: 'AP-APP-002',
47
+ SERVICE_BYPASSES_REPOSITORY: 'AP-APP-003',
48
+ PACKAGE_RESPONSIBILITY_MISMATCH: 'AP-APP-004',
49
+ SERVICE_GOD_CLASS: 'AP-APP-005',
50
+ };
51
+ const maxFileSizeBytes = 384 * 1024;
52
+ const supportedExtensions = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.java', '.cs', '.py', '.php', '.go']);
53
+ const ignoredDirectoryNames = new Set([
54
+ '.git',
55
+ '.archpilot',
56
+ '.next',
57
+ '.vscode-test',
58
+ 'node_modules',
59
+ 'dist',
60
+ 'build',
61
+ 'out',
62
+ 'coverage',
63
+ 'test',
64
+ 'tests',
65
+ '__tests__',
66
+ 'fixtures',
67
+ 'smoke',
68
+ 'examples',
69
+ 'docs',
70
+ 'reports',
71
+ 'generated',
72
+ ]);
73
+ function normalizePath(value) {
74
+ return value.replace(/\\/g, '/');
75
+ }
76
+ function toPosixRelative(workspaceRoot, absolutePath) {
77
+ return normalizePath(path.relative(workspaceRoot, absolutePath));
78
+ }
79
+ async function readTextFileIfReasonable(filePath, sourceInventory) {
80
+ if (sourceInventory) {
81
+ return sourceInventory.readText(filePath, { maxFileSizeBytes });
82
+ }
83
+ try {
84
+ const stats = await node_fs_1.promises.stat(filePath);
85
+ if (stats.size > maxFileSizeBytes) {
86
+ return undefined;
87
+ }
88
+ return await node_fs_1.promises.readFile(filePath, { encoding: 'utf8' });
89
+ }
90
+ catch {
91
+ return undefined;
92
+ }
93
+ }
94
+ async function collectSourceFiles(workspaceRoot, sourceInventory) {
95
+ if (sourceInventory) {
96
+ const files = await sourceInventory.getTextFiles({
97
+ extensions: [...supportedExtensions],
98
+ ignoredDirectoryNames: [...ignoredDirectoryNames],
99
+ maxFileSizeBytes,
100
+ });
101
+ return files.map((file) => ({
102
+ relativePath: file.relativePath,
103
+ content: file.content,
104
+ extension: file.extension,
105
+ }));
106
+ }
107
+ const ignoreMatcher = (0, archpilotIgnore_1.loadArchpilotIgnoreMatcher)(workspaceRoot);
108
+ const collected = [];
109
+ const stack = [workspaceRoot];
110
+ while (stack.length > 0) {
111
+ const current = stack.pop();
112
+ if (!current) {
113
+ continue;
114
+ }
115
+ let entries;
116
+ try {
117
+ entries = await node_fs_1.promises.readdir(current, { withFileTypes: true });
118
+ }
119
+ catch {
120
+ continue;
121
+ }
122
+ for (const entry of entries) {
123
+ const absoluteEntryPath = path.join(current, entry.name);
124
+ const relativeEntryPath = toPosixRelative(workspaceRoot, absoluteEntryPath);
125
+ if (ignoreMatcher.isIgnored(relativeEntryPath)) {
126
+ continue;
127
+ }
128
+ if (entry.isDirectory()) {
129
+ if (entry.name.startsWith('.') || ignoredDirectoryNames.has(entry.name)) {
130
+ continue;
131
+ }
132
+ stack.push(absoluteEntryPath);
133
+ continue;
134
+ }
135
+ const extension = path.extname(entry.name).toLowerCase();
136
+ if (!supportedExtensions.has(extension)) {
137
+ continue;
138
+ }
139
+ const content = await readTextFileIfReasonable(absoluteEntryPath, sourceInventory);
140
+ if (content === undefined) {
141
+ continue;
142
+ }
143
+ collected.push({
144
+ relativePath: relativeEntryPath,
145
+ content,
146
+ extension,
147
+ });
148
+ }
149
+ }
150
+ return collected.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
151
+ }
152
+ function lineNumberForOffset(content, offset) {
153
+ let line = 1;
154
+ for (let index = 0; index < offset && index < content.length; index += 1) {
155
+ if (content[index] === '\n') {
156
+ line += 1;
157
+ }
158
+ }
159
+ return line;
160
+ }
161
+ function findLine(content, pattern) {
162
+ const match = pattern.exec(content);
163
+ return match ? lineNumberForOffset(content, match.index) : undefined;
164
+ }
165
+ function hasAnyPattern(content, patterns) {
166
+ return patterns.some((pattern) => pattern.test(content));
167
+ }
168
+ function maskNonCodeEvidence(value) {
169
+ let masked = '';
170
+ let index = 0;
171
+ let previousSignificant = '';
172
+ const pushMasked = (count) => {
173
+ masked += ' '.repeat(count);
174
+ };
175
+ const pushCode = (character) => {
176
+ masked += character;
177
+ if (!/\s/u.test(character)) {
178
+ previousSignificant = character;
179
+ }
180
+ };
181
+ while (index < value.length) {
182
+ const character = value[index] ?? '';
183
+ const next = value[index + 1] ?? '';
184
+ if (character === '/' && next === '/') {
185
+ const end = value.indexOf('\n', index + 2);
186
+ const length = end === -1 ? value.length - index : end - index;
187
+ pushMasked(length);
188
+ index += length;
189
+ continue;
190
+ }
191
+ if (character === '/' && next === '*') {
192
+ const end = value.indexOf('*/', index + 2);
193
+ const length = end === -1 ? value.length - index : end + 2 - index;
194
+ pushMasked(length);
195
+ index += length;
196
+ continue;
197
+ }
198
+ if (character === '\'' || character === '"' || character === '`') {
199
+ const quote = character;
200
+ let cursor = index + 1;
201
+ while (cursor < value.length) {
202
+ const current = value[cursor] ?? '';
203
+ if (current === '\\') {
204
+ cursor += 2;
205
+ continue;
206
+ }
207
+ if (current === quote) {
208
+ cursor += 1;
209
+ break;
210
+ }
211
+ cursor += 1;
212
+ }
213
+ pushMasked(cursor - index);
214
+ index = cursor;
215
+ continue;
216
+ }
217
+ if (character === '/' &&
218
+ (previousSignificant === '' ||
219
+ /[([{:;,=!?&|]/u.test(previousSignificant) ||
220
+ /\b(?:return|case|throw|yield)\s*$/u.test(value.slice(Math.max(0, index - 24), index)))) {
221
+ let cursor = index + 1;
222
+ let inCharacterClass = false;
223
+ while (cursor < value.length) {
224
+ const current = value[cursor] ?? '';
225
+ if (current === '\\') {
226
+ cursor += 2;
227
+ continue;
228
+ }
229
+ if (current === '[') {
230
+ inCharacterClass = true;
231
+ }
232
+ else if (current === ']') {
233
+ inCharacterClass = false;
234
+ }
235
+ else if (current === '/' && !inCharacterClass) {
236
+ cursor += 1;
237
+ while (/[a-z]/iu.test(value[cursor] ?? '')) {
238
+ cursor += 1;
239
+ }
240
+ break;
241
+ }
242
+ cursor += 1;
243
+ }
244
+ pushMasked(cursor - index);
245
+ index = cursor;
246
+ continue;
247
+ }
248
+ pushCode(character);
249
+ index += 1;
250
+ }
251
+ return masked;
252
+ }
253
+ function stripJavaCommentsAndStrings(content) {
254
+ return content
255
+ .replace(/\/\*[\s\S]*?\*\//g, ' ')
256
+ .replace(/\/\/.*$/gm, ' ')
257
+ .replace(/"(?:\\.|[^"\\])*"/g, '""')
258
+ .replace(/'(?:\\.|[^'\\])*'/g, "''");
259
+ }
260
+ function getJavaInterfaceBody(content) {
261
+ const interfaceMatch = /\binterface\s+\w+\s+(?:extends\s+[^{]+)?\{/m.exec(content);
262
+ if (!interfaceMatch) {
263
+ return undefined;
264
+ }
265
+ let depth = 0;
266
+ for (let index = interfaceMatch.index; index < content.length; index += 1) {
267
+ const character = content[index];
268
+ if (character === '{') {
269
+ depth += 1;
270
+ continue;
271
+ }
272
+ if (character === '}') {
273
+ depth -= 1;
274
+ if (depth === 0) {
275
+ return content.slice(interfaceMatch.index + interfaceMatch[0].length, index);
276
+ }
277
+ }
278
+ }
279
+ return undefined;
280
+ }
281
+ function isSpringDataRepositoryInterface(content) {
282
+ const normalized = stripJavaCommentsAndStrings(content);
283
+ return /\binterface\s+\w+\s+extends\s+(?:[\w.]+\s*,\s*)*(?:JpaRepository|CrudRepository|PagingAndSortingRepository|MongoRepository|Repository)\s*<[^>{}]+>/m.test(normalized);
284
+ }
285
+ function isPureSpringDataRepositoryInterface(content) {
286
+ if (!isSpringDataRepositoryInterface(content)) {
287
+ return false;
288
+ }
289
+ const body = getJavaInterfaceBody(stripJavaCommentsAndStrings(content));
290
+ if (!body) {
291
+ return false;
292
+ }
293
+ return !/\)\s*\{|\b(?:default|private|static)\s+[\w<>, ?\[\].]+\s+\w+\s*\(/m.test(body);
294
+ }
295
+ function findMatchingBrace(content, openBraceIndex) {
296
+ let depth = 0;
297
+ for (let index = openBraceIndex; index < content.length; index += 1) {
298
+ const char = content[index];
299
+ if (char === '{') {
300
+ depth += 1;
301
+ }
302
+ else if (char === '}') {
303
+ depth -= 1;
304
+ if (depth === 0) {
305
+ return index;
306
+ }
307
+ }
308
+ }
309
+ return Math.min(content.length - 1, openBraceIndex + 5000);
310
+ }
311
+ function extractMethodBodies(entry) {
312
+ if (entry.extension === '.py') {
313
+ return extractPythonMethodBodies(entry);
314
+ }
315
+ const methods = [];
316
+ const pattern = braceMethodPatternForExtension(entry.extension);
317
+ for (const match of entry.content.matchAll(pattern)) {
318
+ const openBrace = (match.index ?? 0) + match[0].lastIndexOf('{');
319
+ const closeBrace = findMatchingBrace(entry.content, openBrace);
320
+ methods.push({
321
+ name: match[1] ?? 'method',
322
+ body: entry.content.slice(openBrace, closeBrace + 1),
323
+ line: lineNumberForOffset(entry.content, match.index ?? 0),
324
+ });
325
+ }
326
+ return methods;
327
+ }
328
+ function braceMethodPatternForExtension(extension) {
329
+ if (extension === '.java') {
330
+ return /(?:public|private|protected)\s+[\w<>, ?\[\]]+\s+(\w+)\s*\([^)]*\)\s*\{/gu;
331
+ }
332
+ if (extension === '.cs') {
333
+ return /(?:public|private|protected|internal)\s+(?:async\s+)?[\w<>, ?\[\]]+\s+(\w+)\s*\([^)]*\)\s*\{/gu;
334
+ }
335
+ if (extension === '.php') {
336
+ return /(?:(?:public|private|protected|static|final)\s+)*function\s+(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\s*\{/gu;
337
+ }
338
+ if (extension === '.go') {
339
+ return /func\s+(?:\([^)]*\)\s*)?([A-Za-z_]\w*)\s*\([^)]*\)\s*(?:\([^)]*\)|[\w*.[\]]+)?\s*\{/gu;
340
+ }
341
+ return /(?:export\s+)?(?:public\s+|private\s+|protected\s+)?(?:async\s+)?(?:function\s+)?(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\s*\{/gu;
342
+ }
343
+ function leadingWhitespaceLength(value) {
344
+ return value.length - value.trimStart().length;
345
+ }
346
+ function extractPythonMethodBodies(entry) {
347
+ const methods = [];
348
+ const lineStarts = [0];
349
+ for (let index = 0; index < entry.content.length; index += 1) {
350
+ if (entry.content[index] === '\n') {
351
+ lineStarts.push(index + 1);
352
+ }
353
+ }
354
+ for (let lineIndex = 0; lineIndex < lineStarts.length; lineIndex += 1) {
355
+ const lineStart = lineStarts[lineIndex] ?? 0;
356
+ const lineEnd = entry.content.indexOf('\n', lineStart);
357
+ const line = entry.content.slice(lineStart, lineEnd === -1 ? entry.content.length : lineEnd);
358
+ const match = /^(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\([^)]*\)\s*:/u.exec(line.trimStart());
359
+ if (!match?.[1]) {
360
+ continue;
361
+ }
362
+ const definitionIndent = leadingWhitespaceLength(line);
363
+ let bodyEnd = entry.content.length;
364
+ for (let cursor = lineIndex + 1; cursor < lineStarts.length; cursor += 1) {
365
+ const cursorStart = lineStarts[cursor] ?? 0;
366
+ const cursorLineEnd = entry.content.indexOf('\n', cursorStart);
367
+ const cursorLine = entry.content.slice(cursorStart, cursorLineEnd === -1 ? entry.content.length : cursorLineEnd);
368
+ if (cursorLine.trim().length === 0) {
369
+ continue;
370
+ }
371
+ if (leadingWhitespaceLength(cursorLine) <= definitionIndent) {
372
+ bodyEnd = cursorStart;
373
+ break;
374
+ }
375
+ }
376
+ methods.push({
377
+ name: match[1],
378
+ body: entry.content.slice(lineStart, bodyEnd),
379
+ line: lineNumberForOffset(entry.content, lineStart),
380
+ });
381
+ }
382
+ return methods;
383
+ }
384
+ function getModulePathForName(contract, moduleName) {
385
+ if (!moduleName) {
386
+ return undefined;
387
+ }
388
+ const modulesRoot = (0, moduleDiscovery_1.resolveModulesRootFromContract)(contract);
389
+ const reference = contract.modules?.[moduleName];
390
+ return normalizePath(reference?.path ?? `${modulesRoot}/${moduleName}`);
391
+ }
392
+ function getPathSegmentsInsideModule(relativePath, modulePath) {
393
+ const normalized = normalizePath(relativePath).toLowerCase();
394
+ if (!modulePath) {
395
+ return normalized.split('/');
396
+ }
397
+ const normalizedModulePath = normalizePath(modulePath).toLowerCase();
398
+ if (normalized === normalizedModulePath) {
399
+ return [];
400
+ }
401
+ if (normalized.startsWith(`${normalizedModulePath}/`)) {
402
+ return normalized.slice(normalizedModulePath.length + 1).split('/');
403
+ }
404
+ return normalized.split('/');
405
+ }
406
+ function getPathPackageRole(relativePath, modulePath, scope) {
407
+ if (!(0, sourceScopeClassification_1.isProductionBackendGovernanceScope)(scope)) {
408
+ return undefined;
409
+ }
410
+ const segments = getPathSegmentsInsideModule(relativePath, modulePath);
411
+ const parentSegments = segments.slice(0, -1);
412
+ if (parentSegments.some((segment) => /^(controllers?|web|rest)$/.test(segment))) {
413
+ return 'controller';
414
+ }
415
+ if (parentSegments.some((segment) => /^(services?|application)$/.test(segment))) {
416
+ return 'service';
417
+ }
418
+ if (parentSegments.some((segment) => /^(repositories?|repository|persistence|dao|data|data-access)$/.test(segment)) ||
419
+ segments.some((segment, index) => segment === 'infrastructure' &&
420
+ /^(repositories?|repository)$/.test(segments[index + 1] ?? '')) ||
421
+ segments.some((segment, index) => segment === 'adapters' &&
422
+ segments[index + 1] === 'persistence')) {
423
+ return 'repository';
424
+ }
425
+ return undefined;
426
+ }
427
+ function getTypeScriptDeclaredRoles(entry, astCache) {
428
+ const sourceFile = astCache
429
+ ? astCache.parseSourceFile({
430
+ filePath: entry.relativePath,
431
+ sourceText: entry.content,
432
+ scriptTarget: ts.ScriptTarget.Latest,
433
+ setParentNodes: true,
434
+ })
435
+ : ts.createSourceFile(entry.relativePath, entry.content, ts.ScriptTarget.Latest, true);
436
+ const roles = new Set();
437
+ const visit = (node) => {
438
+ if ((ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.name) {
439
+ const name = node.name.text;
440
+ if (/Controller$/u.test(name)) {
441
+ roles.add('controller');
442
+ }
443
+ if (/Service$/u.test(name)) {
444
+ roles.add('service');
445
+ }
446
+ if (/(Repository|Dao)$/u.test(name)) {
447
+ roles.add('repository');
448
+ }
449
+ }
450
+ ts.forEachChild(node, visit);
451
+ };
452
+ visit(sourceFile);
453
+ return [...roles];
454
+ }
455
+ function getJavaDeclaredRoles(content) {
456
+ const code = maskNonCodeEvidence(content);
457
+ const roles = new Set();
458
+ if (/(class|interface)\s+\w*Controller\b/.test(code) || /@(?:Controller|RestController)\b|org\.springframework\.web\.bind\.annotation/u.test(code)) {
459
+ roles.add('controller');
460
+ }
461
+ if (/(class|interface)\s+\w*Service\b/.test(code) || /@Service\b/.test(code)) {
462
+ roles.add('service');
463
+ }
464
+ if (/(class|interface)\s+\w*(?:Repository|Dao)\b/.test(code) || /@Repository\b/.test(code)) {
465
+ roles.add('repository');
466
+ }
467
+ return [...roles];
468
+ }
469
+ function getTextDeclaredRoles(content, extension) {
470
+ const code = maskNonCodeEvidence(content);
471
+ const roles = new Set();
472
+ if (extension === '.java') {
473
+ return getJavaDeclaredRoles(content);
474
+ }
475
+ if (/@Controller\b|\b(?:router|app)\.(?:get|post|put|patch|delete)\s*\(|\bAPIRouter\s*\(|@(?:app|router)\.(?:get|post|put|patch|delete)\b|\[ApiController\]|\bControllerBase\b|Illuminate\\Routing\\Controller|extends\s+Controller\b|\bRoute::(?:get|post|put|patch|delete)\s*\(|\bhttp\.(?:HandleFunc|HandlerFunc)\b|\b(?:gin|mux|chi)\.\w+/u.test(code)) {
476
+ roles.add('controller');
477
+ }
478
+ if (/@Injectable\b|@Service\b|\bclass\s+\w*Service\b/u.test(code)) {
479
+ roles.add('service');
480
+ }
481
+ if (/@Repository\b|\bclass\s+\w*(?:Repository|Repo|Dao)\b|\binterface\s+\w*(?:Repository|Dao)\b/u.test(code)) {
482
+ roles.add('repository');
483
+ }
484
+ return [...roles];
485
+ }
486
+ function classifySourceFile(entry, modulePath, astCache) {
487
+ const lowerPath = entry.relativePath.toLowerCase();
488
+ const scope = (0, sourceScopeClassification_1.classifyValidationSourceScope)(entry.relativePath);
489
+ const effectiveDeclaredRoles = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(entry.extension)
490
+ ? [...new Set([...getTypeScriptDeclaredRoles(entry, astCache), ...getTextDeclaredRoles(entry.content, entry.extension)])]
491
+ : getTextDeclaredRoles(entry.content, entry.extension);
492
+ const isController = /(^|[./_-])controller\.(ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/i.test(lowerPath) ||
493
+ effectiveDeclaredRoles.includes('controller');
494
+ const isService = /(^|[./_-])service\.(ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/i.test(lowerPath) ||
495
+ effectiveDeclaredRoles.includes('service');
496
+ const isRepository = /(^|[./_-])(?:repository|repo|dao)\.(ts|tsx|js|jsx|mjs|cjs|java|cs|py|php|go)$/i.test(lowerPath) ||
497
+ effectiveDeclaredRoles.includes('repository');
498
+ return {
499
+ isController,
500
+ isService,
501
+ isRepository,
502
+ packageRole: getPathPackageRole(entry.relativePath, modulePath, scope),
503
+ declaredRoles: effectiveDeclaredRoles,
504
+ scope,
505
+ };
506
+ }
507
+ function inferModuleForPath(contract, relativePath) {
508
+ const normalized = normalizePath(relativePath);
509
+ const modulesRoot = (0, moduleDiscovery_1.resolveModulesRootFromContract)(contract);
510
+ for (const [moduleName, reference] of Object.entries(contract.modules ?? {})) {
511
+ const modulePath = normalizePath(reference.path ?? `${modulesRoot}/${moduleName}`);
512
+ if (normalized === modulePath || normalized.startsWith(`${modulePath}/`)) {
513
+ return moduleName;
514
+ }
515
+ }
516
+ const rootPrefix = `${normalizePath(modulesRoot)}/`;
517
+ if (normalized.startsWith(rootPrefix)) {
518
+ const [moduleName] = normalized.slice(rootPrefix.length).split('/');
519
+ return moduleName || undefined;
520
+ }
521
+ return undefined;
522
+ }
523
+ function createFinding(input) {
524
+ return {
525
+ id: input.id,
526
+ severity: 'warning',
527
+ passed: false,
528
+ message: input.message,
529
+ findingType: 'file-scope',
530
+ filePath: input.file.relativePath,
531
+ sourceFile: input.file.relativePath,
532
+ ...(input.line ? { sourceLine: input.line } : {}),
533
+ ...(input.module ? { module: input.module } : {}),
534
+ ...(input.target ? { target: input.target } : {}),
535
+ };
536
+ }
537
+ function hasRepositoryLayer(files, contract) {
538
+ return files.some((file) => {
539
+ const moduleName = inferModuleForPath(contract, file.relativePath);
540
+ return classifySourceFile(file, getModulePathForName(contract, moduleName)).isRepository;
541
+ });
542
+ }
543
+ function hasServiceLayer(files) {
544
+ return files.some((file) => classifySourceFile(file).isService);
545
+ }
546
+ function hasDirectDatabaseAccess(value) {
547
+ const code = maskNonCodeEvidence(value);
548
+ return [
549
+ /\b(?:this\.)?prisma\.[a-z]\w*\.(?:find|create|update|upsert|delete|count|aggregate|groupBy|createMany|updateMany|deleteMany)\w*\s*\(/iu,
550
+ /\b(?:this\.)?prisma\.\$transaction\s*\(/u,
551
+ /\b(?:PrismaClient|DataSource|EntityManager|JdbcTemplate|QueryRunner|DbContext|DbSet|TransactionScope|sql\.DB|sqlx\.DB|gorm\.DB)\b/u,
552
+ /\b(?:this\.)?(?:entityManager|dataSource|jdbcTemplate|queryRunner)\.(?:createQuery|query|execute|save|persist|merge|remove|find)\w*\s*\(/iu,
553
+ /\b(?:db|session)\.(?:query|execute|add|delete|commit|rollback)\s*\(/iu,
554
+ /\b(?:DB::table|DB::select|DB::insert|DB::update|DB::delete|DB::transaction)\s*\(/u,
555
+ /\b[A-Z]\w*::(?:query|where|find|findOrFail|create|update|delete)\s*\(/u,
556
+ /\b(?:db|tx)\.(?:Query|QueryContext|QueryRow|QueryRowContext|Exec|ExecContext|Begin|BeginTx)\s*\(/u,
557
+ /\bknex\s*\(/iu,
558
+ /\b(?:knex|sequelize|typeorm|dataSource|repository)\.(?:transaction|query|createQueryBuilder|getRepository)\s*\(/iu,
559
+ /\b(?:this\.)?db\.[A-Z]\w*\.(?:Where|Find|First|FirstOrDefault|SingleOrDefault|Add|Update|Remove|ExecuteDelete|ExecuteUpdate)\s*\(/u,
560
+ /\bcreateQueryBuilder\s*\(/u,
561
+ /\bquery\s*\(\s*(?:`|'|")\s*(?:select|insert|update|delete)\b/iu,
562
+ ].some((pattern) => pattern.test(code));
563
+ }
564
+ function hasRepositoryPersistenceCall(value) {
565
+ return /\b(?:this\.)?\w*(?:Repository|Repo|Dao)\.(?:save|create|insert|update|delete|remove|persist|merge|upsert|deleteMany|updateMany|createMany)\w*\s*\(/u.test(value);
566
+ }
567
+ function hasTransactionHandling(value) {
568
+ return /\b(?:\$transaction|@Transactional|transactional\s*\(|startTransaction|beginTransaction|commitTransaction|rollbackTransaction|QueryRunner|TransactionTemplate|TransactionScope|BeginTransaction|BeginTransactionAsync|DB::transaction|session\.begin|BeginTx|db\.Transaction)\b/iu.test(maskNonCodeEvidence(value));
569
+ }
570
+ function hasWebFrameworkEvidence(value) {
571
+ return /@(?:Controller|RestController|RequestMapping|GetMapping|PostMapping)\b|@Controller\b|@(?:Get|Post|Put|Patch|Delete)\b|\b(?:express|Request|Response|APIRouter|FastAPI|ControllerBase|IActionResult|HttpContext|Illuminate\\Http|Illuminate\\Routing|Route::|http\.ResponseWriter|http\.Request|gin\.Context)\b|\b(?:router|app)\.(?:get|post|put|patch|delete)\s*\(|@(?:app|router)\.(?:get|post|put|patch|delete)\b|\[(?:ApiController|HttpGet|HttpPost|HttpPut|HttpPatch|HttpDelete)\b/u.test(maskNonCodeEvidence(value));
572
+ }
573
+ function hasControllerWorkflowEvidence(methods) {
574
+ return methods.some((method) => {
575
+ const nonInfrastructureCalls = [...method.body.matchAll(/\bthis\.(\w+)\.(\w+)\s*\(/gu)]
576
+ .filter((match) => !/auth|guard|validator|validation|mapper|dto|parser/iu.test(match[1] ?? ''))
577
+ .filter((match) => !/^require|^authorize|^authenticate|^validate|^parse|^map|^to/iu.test(match[2] ?? ''));
578
+ return (nonInfrastructureCalls.length >= 3 &&
579
+ /\b(?:approve|reject|create|update|delete|remove|invite|checkout|sync|provision|transition|settle)\b/iu.test(method.body) &&
580
+ /\bif\s*\(|\bswitch\s*\(|\bthrow\s+new\b/u.test(method.body));
581
+ });
582
+ }
583
+ function detectControllerBusinessLogic(entry, classification, moduleName, context) {
584
+ if (!classification.isController || !(0, sourceScopeClassification_1.isProductionBackendGovernanceScope)(classification.scope)) {
585
+ return undefined;
586
+ }
587
+ const methods = extractMethodBodies(entry);
588
+ const directDatabaseMethod = methods.find((method) => hasDirectDatabaseAccess(method.body));
589
+ const repositoryPersistenceMethod = context.serviceLayerPresent && context.repositoryLayerPresent
590
+ ? methods.find((method) => hasRepositoryPersistenceCall(method.body))
591
+ : undefined;
592
+ const transactionMethod = methods.find((method) => hasTransactionHandling(method.body));
593
+ const hasWorkflowEvidence = hasControllerWorkflowEvidence(methods);
594
+ if (!directDatabaseMethod && !repositoryPersistenceMethod && !transactionMethod && !hasWorkflowEvidence) {
595
+ return undefined;
596
+ }
597
+ const evidence = [
598
+ directDatabaseMethod ? 'directDatabase=true' : undefined,
599
+ repositoryPersistenceMethod ? 'repositoryPersistence=true' : undefined,
600
+ transactionMethod ? 'transaction=true' : undefined,
601
+ hasWorkflowEvidence ? 'workflow=true' : undefined,
602
+ ].filter((value) => Boolean(value));
603
+ return createFinding({
604
+ id: ApplicationLayeringRuleIds.CONTROLLER_BUSINESS_LOGIC,
605
+ message: `Controller appears to contain persistence or business workflow logic instead of delegating to an application service (${evidence.join(', ')}).`,
606
+ file: entry,
607
+ line: directDatabaseMethod?.line ?? repositoryPersistenceMethod?.line ?? transactionMethod?.line ?? methods[0]?.line,
608
+ module: moduleName,
609
+ target: 'controller',
610
+ });
611
+ }
612
+ function detectRepositoryBusinessLogic(entry, classification, moduleName) {
613
+ if (!classification.isRepository) {
614
+ return undefined;
615
+ }
616
+ if (entry.extension === '.java' && isPureSpringDataRepositoryInterface(entry.content)) {
617
+ return undefined;
618
+ }
619
+ const businessWorkflowPatterns = [
620
+ /\b(?:HttpService|RestTemplate|WebClient|axios|fetch)\b/,
621
+ /\b(?:EventEmitter|ApplicationEventPublisher|CommandBus|QueryBus)\b/,
622
+ /\b(?:Mailer|Email|Sms|Queue|Kafka|Rabbit|Sqs)\b/i,
623
+ /\b(?:Controller|Service)\b/,
624
+ ];
625
+ const code = maskNonCodeEvidence(entry.content);
626
+ if (!hasAnyPattern(code, businessWorkflowPatterns) && !hasWebFrameworkEvidence(entry.content)) {
627
+ return undefined;
628
+ }
629
+ return createFinding({
630
+ id: ApplicationLayeringRuleIds.REPOSITORY_BUSINESS_LOGIC,
631
+ message: 'Repository appears to contain workflow or integration logic that belongs in an application service.',
632
+ file: entry,
633
+ line: findLine(code, /\b(?:HttpService|RestTemplate|WebClient|axios|fetch|EventEmitter|ApplicationEventPublisher|CommandBus|QueryBus|Mailer|Email|Sms|Queue|Kafka|Rabbit|Sqs|Controller|Service|APIRouter|ControllerBase|Illuminate\\Http|http\.Request)\b/i),
634
+ module: moduleName,
635
+ target: 'repository',
636
+ });
637
+ }
638
+ function detectServiceBypassesRepository(input) {
639
+ if (!input.classification.isService ||
640
+ !(0, sourceScopeClassification_1.isProductionBackendGovernanceScope)(input.classification.scope) ||
641
+ input.classification.scope.isInfrastructure ||
642
+ !input.repositoryLayerPresent) {
643
+ return undefined;
644
+ }
645
+ const directDatabasePatterns = [
646
+ /\b(?:DataSource|EntityManager|JdbcTemplate|PrismaClient|DbContext|DbSet|sql\.DB|sqlx\.DB|gorm\.DB)\b/,
647
+ /\bcreateQueryBuilder\s*\(/,
648
+ /\bquery\s*\(\s*(?:`|'|")\s*(?:select|insert|update|delete)\b/i,
649
+ /\b(?:db|session)\.(?:query|execute|add|delete|commit|rollback)\s*\(/i,
650
+ /\b(?:DB::table|DB::select|DB::insert|DB::update|DB::delete|DB::transaction)\s*\(/,
651
+ /\b[A-Z]\w*::(?:query|where|find|findOrFail|create|update|delete)\s*\(/,
652
+ /\b(?:db|tx)\.(?:Query|QueryContext|QueryRow|QueryRowContext|Exec|ExecContext|Begin|BeginTx)\s*\(/,
653
+ /\bknex\s*\(/i,
654
+ /\b(?:knex|sequelize|typeorm|dataSource|repository)\.(?:transaction|query|createQueryBuilder|getRepository)\s*\(/i,
655
+ /\b(?:this\.)?db\.[A-Z]\w*\.(?:Where|Find|First|FirstOrDefault|SingleOrDefault|Add|Update|Remove|ExecuteDelete|ExecuteUpdate)\s*\(/,
656
+ ];
657
+ const prismaPatterns = [/\b(?:PrismaClient|prisma)\b/i];
658
+ const code = maskNonCodeEvidence(input.entry.content);
659
+ const hasDirectDatabase = hasAnyPattern(code, directDatabasePatterns);
660
+ const hasPrismaBypass = hasAnyPattern(code, prismaPatterns);
661
+ if (!hasDirectDatabase && !hasPrismaBypass) {
662
+ return undefined;
663
+ }
664
+ return createFinding({
665
+ id: ApplicationLayeringRuleIds.SERVICE_BYPASSES_REPOSITORY,
666
+ message: 'Service appears to access the database directly instead of using the repository/persistence layer.',
667
+ file: input.entry,
668
+ line: findLine(input.entry.content, /\b(?:DataSource|EntityManager|JdbcTemplate|createQueryBuilder|query|PrismaClient|prisma)\b/i),
669
+ module: input.moduleName,
670
+ target: 'service',
671
+ });
672
+ }
673
+ function detectPackageResponsibilityMismatch(entry, classification, moduleName) {
674
+ if (!(0, sourceScopeClassification_1.isProductionBackendGovernanceScope)(classification.scope) ||
675
+ !classification.packageRole ||
676
+ classification.declaredRoles.length === 0) {
677
+ return undefined;
678
+ }
679
+ const mismatchedRole = classification.declaredRoles.find((role) => role !== classification.packageRole);
680
+ if (!mismatchedRole) {
681
+ return undefined;
682
+ }
683
+ return createFinding({
684
+ id: ApplicationLayeringRuleIds.PACKAGE_RESPONSIBILITY_MISMATCH,
685
+ message: `File is located in a ${classification.packageRole} package but declares ${mismatchedRole} responsibility.`,
686
+ file: entry,
687
+ line: findLine(entry.content, /\b(?:class|interface)\s+\w*(?:Controller|Service|Repository|Dao)\b|@(?:Controller|RestController|Injectable|Service|Repository)\b/),
688
+ module: moduleName,
689
+ target: classification.packageRole,
690
+ });
691
+ }
692
+ function countTypeScriptClassMethods(sourceFile) {
693
+ let count = 0;
694
+ const visit = (node) => {
695
+ if (ts.isClassDeclaration(node)) {
696
+ for (const member of node.members) {
697
+ if (ts.isMethodDeclaration(member)) {
698
+ count += 1;
699
+ }
700
+ }
701
+ }
702
+ ts.forEachChild(node, visit);
703
+ };
704
+ visit(sourceFile);
705
+ return count;
706
+ }
707
+ function countConstructorParameters(sourceFile) {
708
+ let count = 0;
709
+ const visit = (node) => {
710
+ if (ts.isConstructorDeclaration(node)) {
711
+ count += node.parameters.length;
712
+ }
713
+ ts.forEachChild(node, visit);
714
+ };
715
+ visit(sourceFile);
716
+ return count;
717
+ }
718
+ function countJavaMethods(content) {
719
+ return [...content.matchAll(/\b(?:public|private|protected)\s+(?!class\b)[\w<>, ?\[\]]+\s+\w+\s*\([^)]*\)\s*\{/g)].length;
720
+ }
721
+ function countJavaInjectedFields(content) {
722
+ return [...content.matchAll(/@(Autowired|Inject)\b|private\s+final\s+\w+(?:<[^>]+>)?\s+\w+\s*;/g)].length;
723
+ }
724
+ function sortUnique(values) {
725
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
726
+ }
727
+ function isDbModelEvidenceToken(value) {
728
+ const normalized = value.trim();
729
+ if (normalized.length <= 1) {
730
+ return false;
731
+ }
732
+ if (!/^[A-Za-z][A-Za-z0-9_]*$/u.test(normalized)) {
733
+ return false;
734
+ }
735
+ const lower = normalized.toLowerCase();
736
+ const excluded = new Set([
737
+ 'a',
738
+ 'all',
739
+ 'an',
740
+ 'doing',
741
+ 'first',
742
+ 'is',
743
+ 'outside',
744
+ 'resend',
745
+ 'scratch',
746
+ 'swagger',
747
+ 'the',
748
+ ]);
749
+ if (excluded.has(lower)) {
750
+ return false;
751
+ }
752
+ return !/(?:client|provider|service|controller|guard|swagger|openapi)$/iu.test(normalized);
753
+ }
754
+ function isStructuredSqlTableEvidence(value, keyword, quote, following = '') {
755
+ const normalized = value.trim();
756
+ const hasStructuralEvidence = /^(?:from|update|into)$/iu.test(keyword) ||
757
+ quote !== undefined && quote.length > 0 ||
758
+ /[_.]/u.test(normalized) ||
759
+ (/^join$/iu.test(keyword) && /\bon\b/iu.test(following));
760
+ return hasStructuralEvidence && isDbModelEvidenceToken(normalized);
761
+ }
762
+ function extractSqlLikeLiterals(content) {
763
+ return [...content.matchAll(/(['"`])([\s\S]{0,1200}?)\1/gu)]
764
+ .map((match) => match[2] ?? '')
765
+ .filter((literal) => /\b(?:select|update|delete|insert)\b[\s\S]{0,400}\b(?:from|join|into|update)\b/iu.test(literal));
766
+ }
767
+ function extractDbModelsTouched(content) {
768
+ const models = new Set();
769
+ for (const match of content.matchAll(/\b(?:this\.)?prisma\.([a-z]\w*)\./giu)) {
770
+ if (match[1] && isDbModelEvidenceToken(match[1])) {
771
+ models.add(match[1]);
772
+ }
773
+ }
774
+ for (const sqlLiteral of extractSqlLikeLiterals(content)) {
775
+ for (const match of sqlLiteral.matchAll(/\b(?:from|join|update|into)\s+(["`]?)([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)?)\1/giu)) {
776
+ const keyword = /\b(from|join|update|into)\b/iu.exec(match[0])?.[1] ?? '';
777
+ const following = sqlLiteral.slice((match.index ?? 0) + match[0].length, (match.index ?? 0) + match[0].length + 120);
778
+ if (match[2] && isStructuredSqlTableEvidence(match[2], keyword, match[1], following)) {
779
+ models.add(match[2]);
780
+ }
781
+ }
782
+ }
783
+ return sortUnique(models).slice(0, 6);
784
+ }
785
+ function extractExternalIntegrations(content) {
786
+ const integrations = new Set();
787
+ const patterns = [
788
+ [/\b(?:HttpService|httpClient|RestTemplate|WebClient|axios|fetch)\b/iu, 'http'],
789
+ [/\b(?:Mailer|mailClient|emailClient|sendEmail|send\w*Email)\b/iu, 'email'],
790
+ [/\b(?:Kafka|Rabbit|Sqs|Queue|EventEmitter|ApplicationEventPublisher)\b/iu, 'messaging'],
791
+ [/\b(?:Paddle|Stripe|Checkout|PortalSession)\b/iu, 'billing-provider'],
792
+ [/\b(?:S3|putObject|upload)\b/iu, 'object-storage'],
793
+ ];
794
+ for (const [pattern, label] of patterns) {
795
+ if (pattern.test(content)) {
796
+ integrations.add(label);
797
+ }
798
+ }
799
+ return sortUnique(integrations);
800
+ }
801
+ function countPersistenceCollaborators(content) {
802
+ const collaborators = new Set();
803
+ for (const match of content.matchAll(/\b(?:private\s+readonly\s+|private\s+|readonly\s+)?(\w*(?:Repository|Repo|Dao|Prisma|DataSource|EntityManager|JdbcTemplate))\b/gu)) {
804
+ if (match[1]) {
805
+ collaborators.add(match[1]);
806
+ }
807
+ }
808
+ return collaborators.size;
809
+ }
810
+ function summarizeServiceEvidence(entry, methodCount, dependencyCount) {
811
+ return {
812
+ lines: entry.content.split(/\r?\n/u).length,
813
+ publicMethods: methodCount,
814
+ injectedCollaborators: dependencyCount,
815
+ persistenceCollaborators: countPersistenceCollaborators(entry.content),
816
+ dbModelsTouched: extractDbModelsTouched(entry.content),
817
+ externalIntegrations: extractExternalIntegrations(entry.content),
818
+ };
819
+ }
820
+ function formatServiceEvidence(evidence) {
821
+ const parts = [
822
+ `loc=${evidence.lines}`,
823
+ `methods=${evidence.publicMethods}`,
824
+ `collaborators=${evidence.injectedCollaborators}`,
825
+ `persistence=${evidence.persistenceCollaborators}`,
826
+ ];
827
+ if (evidence.dbModelsTouched.length > 0) {
828
+ parts.push(`db=${evidence.dbModelsTouched.join('|')}`);
829
+ }
830
+ if (evidence.externalIntegrations.length > 0) {
831
+ parts.push(`external=${evidence.externalIntegrations.join('|')}`);
832
+ }
833
+ return parts.join(', ');
834
+ }
835
+ function detectServiceGodClass(entry, classification, moduleName, astCache) {
836
+ if (!classification.isService || !(0, sourceScopeClassification_1.isProductionBackendGovernanceScope)(classification.scope)) {
837
+ return undefined;
838
+ }
839
+ const lineCount = entry.content.split(/\r?\n/u).length;
840
+ const sourceFile = entry.extension === '.ts' || entry.extension === '.tsx'
841
+ ? astCache
842
+ ? astCache.parseSourceFile({
843
+ filePath: entry.relativePath,
844
+ sourceText: entry.content,
845
+ scriptTarget: ts.ScriptTarget.Latest,
846
+ setParentNodes: true,
847
+ })
848
+ : ts.createSourceFile(entry.relativePath, entry.content, ts.ScriptTarget.Latest, true)
849
+ : undefined;
850
+ const methodCount = sourceFile
851
+ ? countTypeScriptClassMethods(sourceFile)
852
+ : countJavaMethods(entry.content);
853
+ const dependencyCount = sourceFile
854
+ ? countConstructorParameters(sourceFile)
855
+ : countJavaInjectedFields(entry.content);
856
+ const oversized = lineCount >= 450 ||
857
+ (methodCount >= 25 && dependencyCount >= 5) ||
858
+ (methodCount >= 12 && dependencyCount >= 8);
859
+ if (!oversized) {
860
+ return undefined;
861
+ }
862
+ const evidence = summarizeServiceEvidence(entry, methodCount, dependencyCount);
863
+ return createFinding({
864
+ id: ApplicationLayeringRuleIds.SERVICE_GOD_CLASS,
865
+ message: `Service is large or highly coupled enough to indicate multiple application responsibilities in one class (${formatServiceEvidence(evidence)}).`,
866
+ file: entry,
867
+ line: 1,
868
+ module: moduleName,
869
+ target: 'service',
870
+ });
871
+ }
872
+ async function detectApplicationLayeringFindings(input) {
873
+ const disabled = input.disabledRuleIds ?? new Set();
874
+ const started = Date.now();
875
+ const files = await collectSourceFiles(input.workspaceRoot, input.sourceInventory);
876
+ (0, validationProfiling_1.emitValidationProfile)('AP-APP analyzer file scan', Date.now() - started, [
877
+ { name: 'files', value: files.length },
878
+ ]);
879
+ const repositoryLayerPresent = hasRepositoryLayer(files, input.contract);
880
+ const serviceLayerPresent = hasServiceLayer(files);
881
+ const findings = [];
882
+ for (const file of files) {
883
+ const moduleName = inferModuleForPath(input.contract, file.relativePath);
884
+ const classification = classifySourceFile(file, getModulePathForName(input.contract, moduleName), input.astCache);
885
+ const candidates = [
886
+ disabled.has(ApplicationLayeringRuleIds.CONTROLLER_BUSINESS_LOGIC)
887
+ ? undefined
888
+ : detectControllerBusinessLogic(file, classification, moduleName, {
889
+ serviceLayerPresent,
890
+ repositoryLayerPresent,
891
+ }),
892
+ disabled.has(ApplicationLayeringRuleIds.REPOSITORY_BUSINESS_LOGIC)
893
+ ? undefined
894
+ : detectRepositoryBusinessLogic(file, classification, moduleName),
895
+ disabled.has(ApplicationLayeringRuleIds.SERVICE_BYPASSES_REPOSITORY)
896
+ ? undefined
897
+ : detectServiceBypassesRepository({
898
+ entry: file,
899
+ classification,
900
+ moduleName,
901
+ repositoryLayerPresent,
902
+ }),
903
+ disabled.has(ApplicationLayeringRuleIds.PACKAGE_RESPONSIBILITY_MISMATCH)
904
+ ? undefined
905
+ : detectPackageResponsibilityMismatch(file, classification, moduleName),
906
+ disabled.has(ApplicationLayeringRuleIds.SERVICE_GOD_CLASS)
907
+ ? undefined
908
+ : detectServiceGodClass(file, classification, moduleName, input.astCache),
909
+ ];
910
+ findings.push(...candidates.filter((candidate) => !!candidate));
911
+ }
912
+ return findings.sort((left, right) => {
913
+ const fileCompare = (left.sourceFile ?? '').localeCompare(right.sourceFile ?? '');
914
+ if (fileCompare !== 0) {
915
+ return fileCompare;
916
+ }
917
+ return left.id.localeCompare(right.id);
918
+ });
919
+ }
920
+ //# sourceMappingURL=applicationLayeringAnalysis.js.map