@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.
- package/CHANGELOG.md +538 -0
- package/README.md +1 -0
- package/dist/archpilot-cli.js +850 -159
- package/dist/cli/src/archpilot-cli.js +5523 -0
- package/dist/cli/src/archpilot-cli.js.map +1 -0
- package/dist/core/src/adr/adrLoader.js +97 -0
- package/dist/core/src/adr/adrLoader.js.map +1 -0
- package/dist/core/src/adr/adrParser.js +77 -0
- package/dist/core/src/adr/adrParser.js.map +1 -0
- package/dist/core/src/adr/adrTemplate.js +45 -0
- package/dist/core/src/adr/adrTemplate.js.map +1 -0
- package/dist/core/src/adr/adrTypes.js +3 -0
- package/dist/core/src/adr/adrTypes.js.map +1 -0
- package/dist/core/src/adr/adrValidation.js +160 -0
- package/dist/core/src/adr/adrValidation.js.map +1 -0
- package/dist/core/src/adr/index.js +9 -0
- package/dist/core/src/adr/index.js.map +1 -0
- package/dist/core/src/adrManagement.js +174 -0
- package/dist/core/src/adrManagement.js.map +1 -0
- package/dist/core/src/adrRequirementStatus.js +62 -0
- package/dist/core/src/adrRequirementStatus.js.map +1 -0
- package/dist/core/src/adrScaffoldGeneration.js +325 -0
- package/dist/core/src/adrScaffoldGeneration.js.map +1 -0
- package/dist/core/src/apiDesignAnalysis.js +869 -0
- package/dist/core/src/apiDesignAnalysis.js.map +1 -0
- package/dist/core/src/applicationLayeringAnalysis.js +920 -0
- package/dist/core/src/applicationLayeringAnalysis.js.map +1 -0
- package/dist/core/src/applyRulePack.js +117 -0
- package/dist/core/src/applyRulePack.js.map +1 -0
- package/dist/core/src/architectureBaseline.js +271 -0
- package/dist/core/src/architectureBaseline.js.map +1 -0
- package/dist/core/src/architectureComponentDiscoveryDefaults.js +139 -0
- package/dist/core/src/architectureComponentDiscoveryDefaults.js.map +1 -0
- package/dist/core/src/architectureDependencyContext.js +316 -0
- package/dist/core/src/architectureDependencyContext.js.map +1 -0
- package/dist/core/src/architectureDriftDetection.js +96 -0
- package/dist/core/src/architectureDriftDetection.js.map +1 -0
- package/dist/core/src/architectureDriftTimeline.js +221 -0
- package/dist/core/src/architectureDriftTimeline.js.map +1 -0
- package/dist/core/src/architectureGovernanceBaseline.js +469 -0
- package/dist/core/src/architectureGovernanceBaseline.js.map +1 -0
- package/dist/core/src/architectureHealthHistory.js +208 -0
- package/dist/core/src/architectureHealthHistory.js.map +1 -0
- package/dist/core/src/architectureHealthScore.js +657 -0
- package/dist/core/src/architectureHealthScore.js.map +1 -0
- package/dist/core/src/architectureInit.js +826 -0
- package/dist/core/src/architectureInit.js.map +1 -0
- package/dist/core/src/architectureMap.js +727 -0
- package/dist/core/src/architectureMap.js.map +1 -0
- package/dist/core/src/architectureMigrationPreview.js +467 -0
- package/dist/core/src/architectureMigrationPreview.js.map +1 -0
- package/dist/core/src/architectureModelRefresh.js +209 -0
- package/dist/core/src/architectureModelRefresh.js.map +1 -0
- package/dist/core/src/architectureReportWorkflow.js +139 -0
- package/dist/core/src/architectureReportWorkflow.js.map +1 -0
- package/dist/core/src/architectureValidation.js +3879 -0
- package/dist/core/src/architectureValidation.js.map +1 -0
- package/dist/core/src/architectureWorkspaceModel.js +166 -0
- package/dist/core/src/architectureWorkspaceModel.js.map +1 -0
- package/dist/core/src/authorizationTenantAnalysis.js +652 -0
- package/dist/core/src/authorizationTenantAnalysis.js.map +1 -0
- package/dist/core/src/bootstrapArchitectureConfig.js +150 -0
- package/dist/core/src/bootstrapArchitectureConfig.js.map +1 -0
- package/dist/core/src/changeRisk/changeRiskAssessment.js +251 -0
- package/dist/core/src/changeRisk/changeRiskAssessment.js.map +1 -0
- package/dist/core/src/changeRisk/changeRiskTypes.js +3 -0
- package/dist/core/src/changeRisk/changeRiskTypes.js.map +1 -0
- package/dist/core/src/changeRisk/index.js +6 -0
- package/dist/core/src/changeRisk/index.js.map +1 -0
- package/dist/core/src/ci/githubInlineAnnotations.js +245 -0
- package/dist/core/src/ci/githubInlineAnnotations.js.map +1 -0
- package/dist/core/src/ci/githubPrCommentAdapter.js +232 -0
- package/dist/core/src/ci/githubPrCommentAdapter.js.map +1 -0
- package/dist/core/src/ciWorkflowTemplates.js +1042 -0
- package/dist/core/src/ciWorkflowTemplates.js.map +1 -0
- package/dist/core/src/compliance/complianceExportBuilder.js +122 -0
- package/dist/core/src/compliance/complianceExportBuilder.js.map +1 -0
- package/dist/core/src/compliance/complianceExportTypes.js +3 -0
- package/dist/core/src/compliance/complianceExportTypes.js.map +1 -0
- package/dist/core/src/compliance/complianceExportWriter.js +48 -0
- package/dist/core/src/compliance/complianceExportWriter.js.map +1 -0
- package/dist/core/src/compliance/complianceRulePackResolver.js +62 -0
- package/dist/core/src/compliance/complianceRulePackResolver.js.map +1 -0
- package/dist/core/src/config/index.js +17 -0
- package/dist/core/src/config/index.js.map +1 -0
- package/dist/core/src/config/projectConfig.js +224 -0
- package/dist/core/src/config/projectConfig.js.map +1 -0
- package/dist/core/src/config/projectIdentity.js +160 -0
- package/dist/core/src/config/projectIdentity.js.map +1 -0
- package/dist/core/src/dataQueryRiskDetection.js +1203 -0
- package/dist/core/src/dataQueryRiskDetection.js.map +1 -0
- package/dist/core/src/dependencyValidation.js +2557 -0
- package/dist/core/src/dependencyValidation.js.map +1 -0
- package/dist/core/src/discoverAdrs.js +15 -0
- package/dist/core/src/discoverAdrs.js.map +1 -0
- package/dist/core/src/drift/driftComparator.js +49 -0
- package/dist/core/src/drift/driftComparator.js.map +1 -0
- package/dist/core/src/drift/driftSnapshotLoader.js +136 -0
- package/dist/core/src/drift/driftSnapshotLoader.js.map +1 -0
- package/dist/core/src/drift/driftSnapshotTypes.js +3 -0
- package/dist/core/src/drift/driftSnapshotTypes.js.map +1 -0
- package/dist/core/src/drift/driftSnapshotWriter.js +48 -0
- package/dist/core/src/drift/driftSnapshotWriter.js.map +1 -0
- package/dist/core/src/drift/index.js +6 -0
- package/dist/core/src/drift/index.js.map +1 -0
- package/dist/core/src/eventArchitectureAnalysis.js +925 -0
- package/dist/core/src/eventArchitectureAnalysis.js.map +1 -0
- package/dist/core/src/findingTargetResolution.js +117 -0
- package/dist/core/src/findingTargetResolution.js.map +1 -0
- package/dist/core/src/generateArchitectureDiagrams.js +57 -0
- package/dist/core/src/generateArchitectureDiagrams.js.map +1 -0
- package/dist/core/src/generateImpactAnalysis.js +366 -0
- package/dist/core/src/generateImpactAnalysis.js.map +1 -0
- package/dist/core/src/generateOnboardingDocs.js +262 -0
- package/dist/core/src/generateOnboardingDocs.js.map +1 -0
- package/dist/core/src/governance/cloudConnection.js +203 -0
- package/dist/core/src/governance/cloudConnection.js.map +1 -0
- package/dist/core/src/governance/governanceContracts.js +129 -0
- package/dist/core/src/governance/governanceContracts.js.map +1 -0
- package/dist/core/src/governance/governanceGitMetadata.js +78 -0
- package/dist/core/src/governance/governanceGitMetadata.js.map +1 -0
- package/dist/core/src/governance/governanceUploadClient.js +119 -0
- package/dist/core/src/governance/governanceUploadClient.js.map +1 -0
- package/dist/core/src/governance/governanceUploadLimitErrorFormatting.js +155 -0
- package/dist/core/src/governance/governanceUploadLimitErrorFormatting.js.map +1 -0
- package/dist/core/src/governance/governanceUploadPayload.js +439 -0
- package/dist/core/src/governance/governanceUploadPayload.js.map +1 -0
- package/dist/core/src/governance/runGovernanceUpload.js +103 -0
- package/dist/core/src/governance/runGovernanceUpload.js.map +1 -0
- package/dist/core/src/impactAnalysisEngine.js +376 -0
- package/dist/core/src/impactAnalysisEngine.js.map +1 -0
- package/dist/core/src/initializationState.js +99 -0
- package/dist/core/src/initializationState.js.map +1 -0
- package/dist/core/src/managedArtifacts.js +151 -0
- package/dist/core/src/managedArtifacts.js.map +1 -0
- package/dist/core/src/moduleContractValidation.js +266 -0
- package/dist/core/src/moduleContractValidation.js.map +1 -0
- package/dist/core/src/moduleContractsGenerator.js +337 -0
- package/dist/core/src/moduleContractsGenerator.js.map +1 -0
- package/dist/core/src/moduleDiscovery.js +416 -0
- package/dist/core/src/moduleDiscovery.js.map +1 -0
- package/dist/core/src/moduleScope.js +426 -0
- package/dist/core/src/moduleScope.js.map +1 -0
- package/dist/core/src/onboardingGuidance.js +74 -0
- package/dist/core/src/onboardingGuidance.js.map +1 -0
- package/dist/core/src/operationalLogging.js +7 -0
- package/dist/core/src/operationalLogging.js.map +1 -0
- package/dist/core/src/packageVersion.js +52 -0
- package/dist/core/src/packageVersion.js.map +1 -0
- package/dist/core/src/policy/effectivePolicyResolver.js +91 -0
- package/dist/core/src/policy/effectivePolicyResolver.js.map +1 -0
- package/dist/core/src/policy/exceptionLoader.js +285 -0
- package/dist/core/src/policy/exceptionLoader.js.map +1 -0
- package/dist/core/src/policy/remotePolicyLoader.js +227 -0
- package/dist/core/src/policy/remotePolicyLoader.js.map +1 -0
- package/dist/core/src/policy/remotePolicyTypes.js +3 -0
- package/dist/core/src/policy/remotePolicyTypes.js.map +1 -0
- package/dist/core/src/policy/riskPolicyConfig.js +206 -0
- package/dist/core/src/policy/riskPolicyConfig.js.map +1 -0
- package/dist/core/src/policy/riskPolicyEnforcement.js +203 -0
- package/dist/core/src/policy/riskPolicyEnforcement.js.map +1 -0
- package/dist/core/src/policy/riskPolicyExitCode.js +16 -0
- package/dist/core/src/policy/riskPolicyExitCode.js.map +1 -0
- package/dist/core/src/policy/riskPolicyInitializer.js +90 -0
- package/dist/core/src/policy/riskPolicyInitializer.js.map +1 -0
- package/dist/core/src/quickFix/quickFixEngine.js +132 -0
- package/dist/core/src/quickFix/quickFixEngine.js.map +1 -0
- package/dist/core/src/quickFix/quickFixMessaging.js +15 -0
- package/dist/core/src/quickFix/quickFixMessaging.js.map +1 -0
- package/dist/core/src/quickFix/quickFixProviders.js +87 -0
- package/dist/core/src/quickFix/quickFixProviders.js.map +1 -0
- package/dist/core/src/quickFix/quickFixTypes.js +3 -0
- package/dist/core/src/quickFix/quickFixTypes.js.map +1 -0
- package/dist/core/src/remediation/fileHelpers.js +86 -0
- package/dist/core/src/remediation/fileHelpers.js.map +1 -0
- package/dist/core/src/remediation/fixRegistry.js +645 -0
- package/dist/core/src/remediation/fixRegistry.js.map +1 -0
- package/dist/core/src/remediation/index.js +8 -0
- package/dist/core/src/remediation/index.js.map +1 -0
- package/dist/core/src/remediation/remediationEngine.js +207 -0
- package/dist/core/src/remediation/remediationEngine.js.map +1 -0
- package/dist/core/src/reporting/adrReporter.js +59 -0
- package/dist/core/src/reporting/adrReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureBaselineReporter.js +64 -0
- package/dist/core/src/reporting/architectureBaselineReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureDiagramReporter.js +148 -0
- package/dist/core/src/reporting/architectureDiagramReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureDriftTimelineReporter.js +44 -0
- package/dist/core/src/reporting/architectureDriftTimelineReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureHealthHistoryReporter.js +51 -0
- package/dist/core/src/reporting/architectureHealthHistoryReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureMapReporter.js +228 -0
- package/dist/core/src/reporting/architectureMapReporter.js.map +1 -0
- package/dist/core/src/reporting/architecturePrCommentReporter.js +324 -0
- package/dist/core/src/reporting/architecturePrCommentReporter.js.map +1 -0
- package/dist/core/src/reporting/architecturePrReviewReporter.js +389 -0
- package/dist/core/src/reporting/architecturePrReviewReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureReportArtifacts.js +166 -0
- package/dist/core/src/reporting/architectureReportArtifacts.js.map +1 -0
- package/dist/core/src/reporting/architectureReviewReportGenerator.js +382 -0
- package/dist/core/src/reporting/architectureReviewReportGenerator.js.map +1 -0
- package/dist/core/src/reporting/architectureReviewReporter.js +1633 -0
- package/dist/core/src/reporting/architectureReviewReporter.js.map +1 -0
- package/dist/core/src/reporting/architectureRiskAssessment.js +101 -0
- package/dist/core/src/reporting/architectureRiskAssessment.js.map +1 -0
- package/dist/core/src/reporting/architectureScoreBadge.js +177 -0
- package/dist/core/src/reporting/architectureScoreBadge.js.map +1 -0
- package/dist/core/src/reporting/architectureSupplementalReporters.js +124 -0
- package/dist/core/src/reporting/architectureSupplementalReporters.js.map +1 -0
- package/dist/core/src/reporting/changeRiskAssessment.js +6 -0
- package/dist/core/src/reporting/changeRiskAssessment.js.map +1 -0
- package/dist/core/src/reporting/changeRiskTypes.js +3 -0
- package/dist/core/src/reporting/changeRiskTypes.js.map +1 -0
- package/dist/core/src/reporting/impactAnalysisReporter.js +111 -0
- package/dist/core/src/reporting/impactAnalysisReporter.js.map +1 -0
- package/dist/core/src/reporting/onboardingDocsReporter.js +113 -0
- package/dist/core/src/reporting/onboardingDocsReporter.js.map +1 -0
- package/dist/core/src/reporting/rulePackReporter.js +61 -0
- package/dist/core/src/reporting/rulePackReporter.js.map +1 -0
- package/dist/core/src/reporting/safetyControlsDetection.js +343 -0
- package/dist/core/src/reporting/safetyControlsDetection.js.map +1 -0
- package/dist/core/src/resolveRuleAdrs.js +31 -0
- package/dist/core/src/resolveRuleAdrs.js.map +1 -0
- package/dist/core/src/reviewGenerationWorkflow.js +220 -0
- package/dist/core/src/reviewGenerationWorkflow.js.map +1 -0
- package/dist/core/src/rulePacks/index.js +17 -0
- package/dist/core/src/rulePacks/index.js.map +1 -0
- package/dist/core/src/rulePacks/layeredMonolithRulePack.js +45 -0
- package/dist/core/src/rulePacks/layeredMonolithRulePack.js.map +1 -0
- package/dist/core/src/rulePacks/modularMonolithRulePack.js +41 -0
- package/dist/core/src/rulePacks/modularMonolithRulePack.js.map +1 -0
- package/dist/core/src/rulePacks/types.js +3 -0
- package/dist/core/src/rulePacks/types.js.map +1 -0
- package/dist/core/src/setupNextSteps.js +939 -0
- package/dist/core/src/setupNextSteps.js.map +1 -0
- package/dist/core/src/setupRefresh.js +152 -0
- package/dist/core/src/setupRefresh.js.map +1 -0
- package/dist/core/src/smartInit/apiDbHintDetection.js +836 -0
- package/dist/core/src/smartInit/apiDbHintDetection.js.map +1 -0
- package/dist/core/src/smartInit/architectureProposalBuilder.js +1215 -0
- package/dist/core/src/smartInit/architectureProposalBuilder.js.map +1 -0
- package/dist/core/src/smartInit/architectureStyleDetection.js +472 -0
- package/dist/core/src/smartInit/architectureStyleDetection.js.map +1 -0
- package/dist/core/src/smartInit/archpilotIgnore.js +139 -0
- package/dist/core/src/smartInit/archpilotIgnore.js.map +1 -0
- package/dist/core/src/smartInit/componentDetection.js +1084 -0
- package/dist/core/src/smartInit/componentDetection.js.map +1 -0
- package/dist/core/src/smartInit/implementationProfileResolution.js +53 -0
- package/dist/core/src/smartInit/implementationProfileResolution.js.map +1 -0
- package/dist/core/src/smartInit/index.js +31 -0
- package/dist/core/src/smartInit/index.js.map +1 -0
- package/dist/core/src/smartInit/moduleDetection.js +982 -0
- package/dist/core/src/smartInit/moduleDetection.js.map +1 -0
- package/dist/core/src/smartInit/projectKindDetection.js +437 -0
- package/dist/core/src/smartInit/projectKindDetection.js.map +1 -0
- package/dist/core/src/smartInit/repoTopologyDetection.js +470 -0
- package/dist/core/src/smartInit/repoTopologyDetection.js.map +1 -0
- package/dist/core/src/smartInit/runContext.js +112 -0
- package/dist/core/src/smartInit/runContext.js.map +1 -0
- package/dist/core/src/smartInit/smartInitEngine.js +94 -0
- package/dist/core/src/smartInit/smartInitEngine.js.map +1 -0
- package/dist/core/src/smartInit/stackDetection.js +503 -0
- package/dist/core/src/smartInit/stackDetection.js.map +1 -0
- package/dist/core/src/smartInit/toolingHintDetection.js +345 -0
- package/dist/core/src/smartInit/toolingHintDetection.js.map +1 -0
- package/dist/core/src/sourceScopeClassification.js +83 -0
- package/dist/core/src/sourceScopeClassification.js.map +1 -0
- package/dist/core/src/stackAdapters.js +2475 -0
- package/dist/core/src/stackAdapters.js.map +1 -0
- package/dist/core/src/stackMetadata.js +157 -0
- package/dist/core/src/stackMetadata.js.map +1 -0
- package/dist/core/src/suppressions/index.js +3 -0
- package/dist/core/src/suppressions/index.js.map +1 -0
- package/dist/core/src/suppressions/suppressionReporter.js +38 -0
- package/dist/core/src/suppressions/suppressionReporter.js.map +1 -0
- package/dist/core/src/suppressions/suppressionTypes.js +3 -0
- package/dist/core/src/suppressions/suppressionTypes.js.map +1 -0
- package/dist/core/src/suppressions/suppressionValidator.js +119 -0
- package/dist/core/src/suppressions/suppressionValidator.js.map +1 -0
- package/dist/core/src/transactionDomainAnalysis.js +1416 -0
- package/dist/core/src/transactionDomainAnalysis.js.map +1 -0
- package/dist/core/src/validation/changedFilesResolver.js +165 -0
- package/dist/core/src/validation/changedFilesResolver.js.map +1 -0
- package/dist/core/src/validationProfiling.js +33 -0
- package/dist/core/src/validationProfiling.js.map +1 -0
- package/dist/core/src/validationRuleExplanations.js +69 -0
- package/dist/core/src/validationRuleExplanations.js.map +1 -0
- package/dist/core/src/validationSourceInventory.js +200 -0
- package/dist/core/src/validationSourceInventory.js.map +1 -0
- package/dist/core/src/validationSuppressions.js +231 -0
- package/dist/core/src/validationSuppressions.js.map +1 -0
- package/dist/core/src/validationTypeScriptAstCache.js +82 -0
- package/dist/core/src/validationTypeScriptAstCache.js.map +1 -0
- package/dist/core/src/validationWorkflow.js +222 -0
- package/dist/core/src/validationWorkflow.js.map +1 -0
- package/dist/core/src/workspaceRoot.js +68 -0
- package/dist/core/src/workspaceRoot.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,727 @@
|
|
|
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.generateArchitectureMap = generateArchitectureMap;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const node_fs_1 = require("node:fs");
|
|
39
|
+
const architectureInit_1 = require("./architectureInit");
|
|
40
|
+
const dependencyValidation_1 = require("./dependencyValidation");
|
|
41
|
+
const moduleDiscovery_1 = require("./moduleDiscovery");
|
|
42
|
+
const moduleScope_1 = require("./moduleScope");
|
|
43
|
+
const moduleDetection_1 = require("./smartInit/moduleDetection");
|
|
44
|
+
function normalizePath(value) {
|
|
45
|
+
return value.replace(/\\/g, '/');
|
|
46
|
+
}
|
|
47
|
+
async function pathExists(targetPath) {
|
|
48
|
+
try {
|
|
49
|
+
await node_fs_1.promises.access(targetPath);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function readTextFileIfExists(filePath) {
|
|
57
|
+
try {
|
|
58
|
+
return await node_fs_1.promises.readFile(filePath, { encoding: 'utf8' });
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const sourceFileExtensions = new Set([
|
|
65
|
+
'.ts',
|
|
66
|
+
'.tsx',
|
|
67
|
+
'.js',
|
|
68
|
+
'.jsx',
|
|
69
|
+
'.mjs',
|
|
70
|
+
'.cjs',
|
|
71
|
+
'.mts',
|
|
72
|
+
'.cts',
|
|
73
|
+
'.py',
|
|
74
|
+
'.go',
|
|
75
|
+
'.java',
|
|
76
|
+
'.kt',
|
|
77
|
+
'.kts',
|
|
78
|
+
'.cs',
|
|
79
|
+
'.php',
|
|
80
|
+
'.rb',
|
|
81
|
+
'.vue',
|
|
82
|
+
'.svelte',
|
|
83
|
+
]);
|
|
84
|
+
const configuredRootIgnoredModuleNames = new Set([
|
|
85
|
+
'components',
|
|
86
|
+
'hooks',
|
|
87
|
+
'utils',
|
|
88
|
+
'util',
|
|
89
|
+
'lib',
|
|
90
|
+
'common',
|
|
91
|
+
'shared',
|
|
92
|
+
'shared-ui',
|
|
93
|
+
'types',
|
|
94
|
+
'constants',
|
|
95
|
+
'config',
|
|
96
|
+
'test',
|
|
97
|
+
'tests',
|
|
98
|
+
'__tests__',
|
|
99
|
+
'fixtures',
|
|
100
|
+
'mocks',
|
|
101
|
+
'__mocks__',
|
|
102
|
+
'generated',
|
|
103
|
+
'dist',
|
|
104
|
+
'build',
|
|
105
|
+
'out',
|
|
106
|
+
'node_modules',
|
|
107
|
+
]);
|
|
108
|
+
function sortUnique(values) {
|
|
109
|
+
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
110
|
+
}
|
|
111
|
+
function toSafeContractModuleFileStem(moduleName) {
|
|
112
|
+
return normalizePath(moduleName)
|
|
113
|
+
.split('/')
|
|
114
|
+
.map((segment) => segment.trim())
|
|
115
|
+
.filter((segment) => segment.length > 0)
|
|
116
|
+
.join('.');
|
|
117
|
+
}
|
|
118
|
+
function getModuleRegistry(contract) {
|
|
119
|
+
const modules = contract?.modules;
|
|
120
|
+
if (!modules || typeof modules !== 'object' || Array.isArray(modules)) {
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
return modules;
|
|
124
|
+
}
|
|
125
|
+
async function readArchitectureConfigRecord(workspaceRoot) {
|
|
126
|
+
const content = await readTextFileIfExists(path.join(workspaceRoot, '.archpilot', 'architecture.json'));
|
|
127
|
+
if (!content) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const parsed = JSON.parse(content);
|
|
132
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
133
|
+
? parsed
|
|
134
|
+
: undefined;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function hasExplicitModuleRootConfig(config) {
|
|
141
|
+
if (!config) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (typeof config.modulesRootRelativePath === 'string' ||
|
|
145
|
+
typeof config.modulesRoot === 'string') {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
const structure = config.structure && typeof config.structure === 'object' && !Array.isArray(config.structure)
|
|
149
|
+
? config.structure
|
|
150
|
+
: undefined;
|
|
151
|
+
return Boolean(typeof structure?.modulesRootRelativePath === 'string' ||
|
|
152
|
+
typeof structure?.modulesRoot === 'string');
|
|
153
|
+
}
|
|
154
|
+
function hasConfiguredModuleRegistryEntries(config) {
|
|
155
|
+
if (!config || !config.modules || typeof config.modules !== 'object' || Array.isArray(config.modules)) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return Object.keys(config.modules).length > 0;
|
|
159
|
+
}
|
|
160
|
+
function hasExplicitModuleRegistry(config) {
|
|
161
|
+
return Boolean(config &&
|
|
162
|
+
Object.prototype.hasOwnProperty.call(config, 'modules') &&
|
|
163
|
+
config.modules &&
|
|
164
|
+
typeof config.modules === 'object' &&
|
|
165
|
+
!Array.isArray(config.modules));
|
|
166
|
+
}
|
|
167
|
+
function normalizePublicEntrypointList(entries) {
|
|
168
|
+
return sortUnique(entries.map((entry) => normalizePath(entry.trim())).filter((entry) => entry.length > 0));
|
|
169
|
+
}
|
|
170
|
+
function hasConfiguredPublicEntrypoint(registryEntry) {
|
|
171
|
+
return (Array.isArray(registryEntry?.publicEntrypoints) &&
|
|
172
|
+
registryEntry.publicEntrypoints.some((entry) => typeof entry === 'string' && entry.trim().length > 0));
|
|
173
|
+
}
|
|
174
|
+
async function readPackageJsonIfExists(moduleDirectoryPath) {
|
|
175
|
+
const content = await readTextFileIfExists(path.join(moduleDirectoryPath, 'package.json'));
|
|
176
|
+
if (!content) {
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const parsed = JSON.parse(content);
|
|
181
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
182
|
+
? parsed
|
|
183
|
+
: undefined;
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function collectModuleSourceEvidence(directoryPath) {
|
|
190
|
+
let entries;
|
|
191
|
+
try {
|
|
192
|
+
entries = await node_fs_1.promises.readdir(directoryPath, { withFileTypes: true });
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return { sourceFileCount: 0, hasReadme: false, hasEntrypointFile: false };
|
|
196
|
+
}
|
|
197
|
+
let sourceFileCount = 0;
|
|
198
|
+
let hasReadme = false;
|
|
199
|
+
let hasEntrypointFile = false;
|
|
200
|
+
for (const entry of entries) {
|
|
201
|
+
const fullPath = path.join(directoryPath, entry.name);
|
|
202
|
+
if (entry.isDirectory()) {
|
|
203
|
+
if (['node_modules', 'dist', 'out', 'build', 'coverage', '.git'].includes(entry.name)) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const nested = await collectModuleSourceEvidence(fullPath);
|
|
207
|
+
sourceFileCount += nested.sourceFileCount;
|
|
208
|
+
hasReadme ||= nested.hasReadme;
|
|
209
|
+
hasEntrypointFile ||= nested.hasEntrypointFile;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (!entry.isFile()) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
const lowerName = entry.name.toLowerCase();
|
|
216
|
+
if (lowerName === 'readme.md' || lowerName === 'readme.mdx') {
|
|
217
|
+
hasReadme = true;
|
|
218
|
+
}
|
|
219
|
+
if (/^(index|main|app|extension|cli)\.[cm]?[jt]sx?$/iu.test(entry.name)) {
|
|
220
|
+
hasEntrypointFile = true;
|
|
221
|
+
}
|
|
222
|
+
if (sourceFileExtensions.has(path.extname(entry.name).toLowerCase())) {
|
|
223
|
+
sourceFileCount += 1;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return { sourceFileCount, hasReadme, hasEntrypointFile };
|
|
227
|
+
}
|
|
228
|
+
function hasKnownBoundaryRole(moduleName) {
|
|
229
|
+
const normalized = moduleName.toLowerCase();
|
|
230
|
+
const compact = normalized.replace(/[-_/]/gu, '');
|
|
231
|
+
const segments = normalized.split(/[/-]/u);
|
|
232
|
+
return ['adr', 'ci', 'compliance', 'config', 'governance', 'policy', 'validation', 'smartinit'].some((role) => compact.includes(role) || segments.includes(role));
|
|
233
|
+
}
|
|
234
|
+
async function hasPackageEntrypoint(moduleDirectoryPath) {
|
|
235
|
+
const packageJson = await readPackageJsonIfExists(moduleDirectoryPath);
|
|
236
|
+
if (!packageJson) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
return ['main', 'module', 'browser', 'types', 'bin', 'exports'].some((field) => packageJson[field] !== undefined);
|
|
240
|
+
}
|
|
241
|
+
async function hasIntentionalIndependentEvidence(args) {
|
|
242
|
+
const moduleDirectoryPath = path.join(args.workspaceRoot, ...args.moduleEntry.sourcePath.split('/'));
|
|
243
|
+
const evidence = await collectModuleSourceEvidence(moduleDirectoryPath);
|
|
244
|
+
return (args.moduleEntry.contractExists ||
|
|
245
|
+
args.moduleEntry.hasPublicEntrypoint === true ||
|
|
246
|
+
evidence.hasReadme ||
|
|
247
|
+
evidence.hasEntrypointFile ||
|
|
248
|
+
(await hasPackageEntrypoint(moduleDirectoryPath)) ||
|
|
249
|
+
args.hasChildren ||
|
|
250
|
+
(args.isLeafChild && evidence.sourceFileCount > 0) ||
|
|
251
|
+
hasKnownBoundaryRole(args.moduleEntry.moduleName) ||
|
|
252
|
+
evidence.sourceFileCount >= 2);
|
|
253
|
+
}
|
|
254
|
+
async function loadModuleContractPublicEntrypoints(workspaceRoot, contractPath) {
|
|
255
|
+
const fullContractPath = path.join(workspaceRoot, ...contractPath.split('/'));
|
|
256
|
+
const content = await readTextFileIfExists(fullContractPath);
|
|
257
|
+
if (!content) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const parsed = JSON.parse(content);
|
|
262
|
+
if (!Array.isArray(parsed.publicEntrypoints)) {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
const validEntries = parsed.publicEntrypoints.filter((entry) => typeof entry === 'string');
|
|
266
|
+
if (validEntries.length !== parsed.publicEntrypoints.length) {
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
return normalizePublicEntrypointList(validEntries);
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function parseCycleString(cycle) {
|
|
276
|
+
const nodes = cycle.split('->').filter((entry) => entry.length > 0);
|
|
277
|
+
if (nodes.length >= 2 && nodes[0] === nodes[nodes.length - 1]) {
|
|
278
|
+
return nodes.slice(0, -1);
|
|
279
|
+
}
|
|
280
|
+
return nodes;
|
|
281
|
+
}
|
|
282
|
+
async function discoverModulesFromArchitectureContract(workspaceRoot, contract, modulesRoot) {
|
|
283
|
+
const moduleRegistry = getModuleRegistry(contract);
|
|
284
|
+
const normalizedModulesRoot = normalizePath(modulesRoot);
|
|
285
|
+
const contractsRoot = normalizePath(contract.structure.contractsRoot ?? '.archpilot/contracts');
|
|
286
|
+
const discovered = [];
|
|
287
|
+
const toContractPath = (moduleName, registryEntry) => normalizePath(typeof registryEntry?.contract === 'string'
|
|
288
|
+
? registryEntry.contract
|
|
289
|
+
: `${contractsRoot}/${toSafeContractModuleFileStem(moduleName)}.contract.json`);
|
|
290
|
+
const resolveMissingPublicEntrypointAlignment = async (registryEntry, contractPath) => {
|
|
291
|
+
if (!Array.isArray(registryEntry?.publicEntrypoints)) {
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
const registryPublicEntrypoints = normalizePublicEntrypointList(registryEntry.publicEntrypoints.filter((entry) => typeof entry === 'string'));
|
|
295
|
+
const contractPublicEntrypoints = await loadModuleContractPublicEntrypoints(workspaceRoot, contractPath);
|
|
296
|
+
if (!contractPublicEntrypoints) {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
return (registryPublicEntrypoints.length !== contractPublicEntrypoints.length ||
|
|
300
|
+
registryPublicEntrypoints.some((entry, index) => entry !== contractPublicEntrypoints[index]));
|
|
301
|
+
};
|
|
302
|
+
const registryEntries = Object.entries(moduleRegistry).sort(([left], [right]) => left.localeCompare(right));
|
|
303
|
+
for (const [moduleName, registryEntry] of registryEntries) {
|
|
304
|
+
if (!registryEntry.path || typeof registryEntry.path !== 'string') {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
const normalizedSourcePath = normalizePath(registryEntry.path);
|
|
308
|
+
const absoluteSourcePath = path.join(workspaceRoot, ...normalizedSourcePath.split('/'));
|
|
309
|
+
let sourcePathExists = false;
|
|
310
|
+
let sourceIsDirectory = false;
|
|
311
|
+
let sourceIsFile = false;
|
|
312
|
+
try {
|
|
313
|
+
const sourceStats = await node_fs_1.promises.stat(absoluteSourcePath);
|
|
314
|
+
sourcePathExists = true;
|
|
315
|
+
sourceIsDirectory = sourceStats.isDirectory();
|
|
316
|
+
sourceIsFile = sourceStats.isFile();
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
sourcePathExists = false;
|
|
320
|
+
}
|
|
321
|
+
if (!sourceIsDirectory && !sourceIsFile) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
const contractPath = normalizePath(typeof registryEntry.contract === 'string'
|
|
325
|
+
? registryEntry.contract
|
|
326
|
+
: `${contractsRoot}/${toSafeContractModuleFileStem(moduleName)}.contract.json`);
|
|
327
|
+
const contractExists = await pathExists(path.join(workspaceRoot, ...contractPath.split('/')));
|
|
328
|
+
const missingPublicEntrypointAlignment = await resolveMissingPublicEntrypointAlignment(registryEntry, contractPath);
|
|
329
|
+
discovered.push({
|
|
330
|
+
moduleName,
|
|
331
|
+
sourcePath: normalizedSourcePath,
|
|
332
|
+
discoverySource: 'architecture.json',
|
|
333
|
+
sourcePathExists,
|
|
334
|
+
...(resolveModuleScopeForPath(workspaceRoot, normalizedSourcePath, contract)
|
|
335
|
+
? { scope: resolveModuleScopeForPath(workspaceRoot, normalizedSourcePath, contract) }
|
|
336
|
+
: {}),
|
|
337
|
+
contractPath,
|
|
338
|
+
contractExists,
|
|
339
|
+
hasPublicEntrypoint: hasConfiguredPublicEntrypoint(registryEntry),
|
|
340
|
+
...(missingPublicEntrypointAlignment !== undefined
|
|
341
|
+
? { missingPublicEntrypointAlignment }
|
|
342
|
+
: {}),
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return discovered.sort((left, right) => left.moduleName.localeCompare(right.moduleName));
|
|
346
|
+
}
|
|
347
|
+
async function discoverModulesFromFallbackScan(workspaceRoot, modulesRoot = 'src/modules', contractsRoot = '.archpilot/contracts', options) {
|
|
348
|
+
const topLevelWorkspaceModules = async () => {
|
|
349
|
+
const modules = [];
|
|
350
|
+
for (const container of ['packages', 'apps', 'services']) {
|
|
351
|
+
for (const moduleName of await (0, moduleDiscovery_1.listModuleDirectoryNames)(workspaceRoot, container)) {
|
|
352
|
+
if (configuredRootIgnoredModuleNames.has(moduleName.toLowerCase())) {
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
modules.push({ moduleId: moduleName, sourcePath: `${container}/${moduleName}` });
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return modules.sort((left, right) => left.moduleId.localeCompare(right.moduleId));
|
|
359
|
+
};
|
|
360
|
+
const hierarchicalModules = options?.topLevelWorkspaceOnly
|
|
361
|
+
? await topLevelWorkspaceModules()
|
|
362
|
+
: options?.configuredRootOnly
|
|
363
|
+
? (0, moduleDetection_1.detectModuleCandidatesForRoot)(workspaceRoot, modulesRoot)
|
|
364
|
+
.filter((candidate) => candidate.classification === 'architecture-module' &&
|
|
365
|
+
!configuredRootIgnoredModuleNames.has(candidate.name.toLowerCase()))
|
|
366
|
+
.map((candidate) => ({
|
|
367
|
+
moduleId: candidate.name,
|
|
368
|
+
sourcePath: candidate.path,
|
|
369
|
+
}))
|
|
370
|
+
: await (0, moduleDiscovery_1.discoverHierarchicalModuleRoots)(workspaceRoot, modulesRoot);
|
|
371
|
+
const moduleNames = hierarchicalModules.length > 0 ? [] : await (0, moduleDiscovery_1.listModuleDirectoryNames)(workspaceRoot, modulesRoot);
|
|
372
|
+
const discovered = [];
|
|
373
|
+
for (const moduleRoot of hierarchicalModules) {
|
|
374
|
+
const contractPath = `${contractsRoot}/${toSafeContractModuleFileStem(moduleRoot.moduleId)}.contract.json`;
|
|
375
|
+
discovered.push({
|
|
376
|
+
moduleName: moduleRoot.moduleId,
|
|
377
|
+
sourcePath: moduleRoot.sourcePath,
|
|
378
|
+
discoverySource: 'inferred-scan',
|
|
379
|
+
sourcePathExists: true,
|
|
380
|
+
...(resolveModuleScopeForPath(workspaceRoot, moduleRoot.sourcePath)
|
|
381
|
+
? { scope: resolveModuleScopeForPath(workspaceRoot, moduleRoot.sourcePath) }
|
|
382
|
+
: {}),
|
|
383
|
+
contractPath,
|
|
384
|
+
contractExists: await pathExists(path.join(workspaceRoot, ...contractPath.split('/'))),
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
for (const moduleName of moduleNames) {
|
|
388
|
+
const sourcePath = `${modulesRoot}/${moduleName}`;
|
|
389
|
+
const contractPath = `${contractsRoot}/${toSafeContractModuleFileStem(moduleName)}.contract.json`;
|
|
390
|
+
discovered.push({
|
|
391
|
+
moduleName,
|
|
392
|
+
sourcePath,
|
|
393
|
+
discoverySource: 'inferred-scan',
|
|
394
|
+
sourcePathExists: true,
|
|
395
|
+
...(resolveModuleScopeForPath(workspaceRoot, sourcePath)
|
|
396
|
+
? { scope: resolveModuleScopeForPath(workspaceRoot, sourcePath) }
|
|
397
|
+
: {}),
|
|
398
|
+
contractPath,
|
|
399
|
+
contractExists: await pathExists(path.join(workspaceRoot, ...contractPath.split('/'))),
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
return discovered;
|
|
403
|
+
}
|
|
404
|
+
function getComponentEntries(contract) {
|
|
405
|
+
const components = contract?.components;
|
|
406
|
+
if (!components) {
|
|
407
|
+
return [];
|
|
408
|
+
}
|
|
409
|
+
const rawEntries = Array.isArray(components)
|
|
410
|
+
? components.map((entry) => {
|
|
411
|
+
const typed = entry;
|
|
412
|
+
return [typed.id, entry];
|
|
413
|
+
})
|
|
414
|
+
: Object.entries(components);
|
|
415
|
+
const entries = [];
|
|
416
|
+
for (const [key, value] of rawEntries) {
|
|
417
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
const typed = value;
|
|
421
|
+
const componentId = typeof typed.id === 'string' && typed.id.trim().length > 0
|
|
422
|
+
? typed.id.trim()
|
|
423
|
+
: typeof key === 'string' && key.trim().length > 0
|
|
424
|
+
? key.trim()
|
|
425
|
+
: undefined;
|
|
426
|
+
const sourcePath = typeof typed.path === 'string' && typed.path.trim().length > 0
|
|
427
|
+
? normalizePath(typed.path.trim())
|
|
428
|
+
: undefined;
|
|
429
|
+
if (!componentId || !sourcePath || sourcePath === '.') {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
entries.push({ componentId, sourcePath });
|
|
433
|
+
}
|
|
434
|
+
return entries.sort((left, right) => left.componentId.localeCompare(right.componentId));
|
|
435
|
+
}
|
|
436
|
+
async function discoverModulesFromComponents(workspaceRoot, contract, contractsRoot = '.archpilot/contracts') {
|
|
437
|
+
const discovered = [];
|
|
438
|
+
for (const component of getComponentEntries(contract)) {
|
|
439
|
+
const absoluteSourcePath = path.join(workspaceRoot, ...component.sourcePath.split('/'));
|
|
440
|
+
let sourcePathExists = false;
|
|
441
|
+
let sourceIsDirectory = false;
|
|
442
|
+
try {
|
|
443
|
+
const sourceStats = await node_fs_1.promises.stat(absoluteSourcePath);
|
|
444
|
+
sourcePathExists = true;
|
|
445
|
+
sourceIsDirectory = sourceStats.isDirectory();
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
sourcePathExists = false;
|
|
449
|
+
}
|
|
450
|
+
if (!sourceIsDirectory) {
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
const contractPath = `${contractsRoot}/${toSafeContractModuleFileStem(component.componentId)}.contract.json`;
|
|
454
|
+
discovered.push({
|
|
455
|
+
moduleName: component.componentId,
|
|
456
|
+
sourcePath: component.sourcePath,
|
|
457
|
+
discoverySource: 'inferred-scan',
|
|
458
|
+
sourcePathExists,
|
|
459
|
+
...(resolveModuleScopeForPath(workspaceRoot, component.sourcePath, contract)
|
|
460
|
+
? { scope: resolveModuleScopeForPath(workspaceRoot, component.sourcePath, contract) }
|
|
461
|
+
: {}),
|
|
462
|
+
contractPath,
|
|
463
|
+
contractExists: await pathExists(path.join(workspaceRoot, ...contractPath.split('/'))),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
return discovered;
|
|
467
|
+
}
|
|
468
|
+
function toArchitectureMapEdge(edge) {
|
|
469
|
+
return {
|
|
470
|
+
source: edge.sourceModule,
|
|
471
|
+
target: edge.targetModule,
|
|
472
|
+
importCount: edge.importCount,
|
|
473
|
+
publicImportCount: edge.publicImportCount,
|
|
474
|
+
nonPublicImportCount: edge.nonPublicImportCount,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
function buildIncomingMap(modules, edges) {
|
|
478
|
+
const incoming = new Map();
|
|
479
|
+
for (const moduleEntry of modules) {
|
|
480
|
+
incoming.set(moduleEntry.moduleName, new Set());
|
|
481
|
+
}
|
|
482
|
+
for (const edge of edges) {
|
|
483
|
+
incoming.get(edge.target)?.add(edge.source);
|
|
484
|
+
}
|
|
485
|
+
return new Map([...incoming.entries()]
|
|
486
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
487
|
+
.map(([moduleName, sources]) => [
|
|
488
|
+
moduleName,
|
|
489
|
+
[...sources].sort((left, right) => left.localeCompare(right)),
|
|
490
|
+
]));
|
|
491
|
+
}
|
|
492
|
+
function buildOutgoingMap(modules, edges) {
|
|
493
|
+
const outgoing = new Map();
|
|
494
|
+
for (const moduleEntry of modules) {
|
|
495
|
+
outgoing.set(moduleEntry.moduleName, new Set());
|
|
496
|
+
}
|
|
497
|
+
for (const edge of edges) {
|
|
498
|
+
outgoing.get(edge.source)?.add(edge.target);
|
|
499
|
+
}
|
|
500
|
+
return new Map([...outgoing.entries()]
|
|
501
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
502
|
+
.map(([moduleName, targets]) => [
|
|
503
|
+
moduleName,
|
|
504
|
+
[...targets].sort((left, right) => left.localeCompare(right)),
|
|
505
|
+
]));
|
|
506
|
+
}
|
|
507
|
+
function sortRankedCounts(values) {
|
|
508
|
+
return [...values].sort((left, right) => {
|
|
509
|
+
const countCompare = right.count - left.count;
|
|
510
|
+
if (countCompare !== 0) {
|
|
511
|
+
return countCompare;
|
|
512
|
+
}
|
|
513
|
+
return left.moduleName.localeCompare(right.moduleName);
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
function resolveProjectName(workspaceRoot, contract) {
|
|
517
|
+
const fromContract = contract?.projectName?.trim();
|
|
518
|
+
if (fromContract) {
|
|
519
|
+
return fromContract;
|
|
520
|
+
}
|
|
521
|
+
return path.basename(workspaceRoot);
|
|
522
|
+
}
|
|
523
|
+
function resolveModuleScopeForPath(workspaceRoot, modulePath, contract) {
|
|
524
|
+
return (0, moduleScope_1.classifyModuleScope)({
|
|
525
|
+
modulePath,
|
|
526
|
+
workspaceRoot,
|
|
527
|
+
projectKinds: contract?.projectKinds,
|
|
528
|
+
stacks: contract?.stacks,
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
async function generateArchitectureMap(workspaceRoot, options) {
|
|
532
|
+
const measure = async (phase, run) => {
|
|
533
|
+
const started = Date.now();
|
|
534
|
+
try {
|
|
535
|
+
return await run();
|
|
536
|
+
}
|
|
537
|
+
finally {
|
|
538
|
+
options?.onTiming?.({ phase, durationMs: Date.now() - started });
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
const contract = await measure('architecture-map.contract-load', () => (0, architectureInit_1.loadArchitectureContract)(workspaceRoot));
|
|
542
|
+
const rawArchitectureConfig = await measure('architecture-map.config-read', () => readArchitectureConfigRecord(workspaceRoot));
|
|
543
|
+
const moduleRegistry = getModuleRegistry(contract);
|
|
544
|
+
const hasArchitectureJson = Boolean(contract);
|
|
545
|
+
const contractHasConfiguredModules = Object.keys(moduleRegistry).length > 0 ||
|
|
546
|
+
hasConfiguredModuleRegistryEntries(rawArchitectureConfig);
|
|
547
|
+
const hasComponentEntries = getComponentEntries(contract).length > 0;
|
|
548
|
+
const hasExplicitEmptyModuleRegistry = hasArchitectureJson &&
|
|
549
|
+
!contractHasConfiguredModules &&
|
|
550
|
+
hasExplicitModuleRegistry(rawArchitectureConfig) &&
|
|
551
|
+
!hasComponentEntries;
|
|
552
|
+
const shouldUseConfiguredRootInference = hasArchitectureJson &&
|
|
553
|
+
!contractHasConfiguredModules &&
|
|
554
|
+
!hasExplicitEmptyModuleRegistry &&
|
|
555
|
+
hasExplicitModuleRootConfig(rawArchitectureConfig);
|
|
556
|
+
const shouldUseTopLevelWorkspaceInference = hasArchitectureJson &&
|
|
557
|
+
!contractHasConfiguredModules &&
|
|
558
|
+
!hasExplicitEmptyModuleRegistry &&
|
|
559
|
+
!shouldUseConfiguredRootInference;
|
|
560
|
+
const discoveryMode = hasArchitectureJson
|
|
561
|
+
? 'architecture-json'
|
|
562
|
+
: 'inferred-src-modules';
|
|
563
|
+
const modulesRoot = normalizePath(await (0, moduleDiscovery_1.resolveConfiguredModulesRoot)(workspaceRoot, (0, moduleDiscovery_1.resolveModulesRootFromContract)(contract)));
|
|
564
|
+
const modules = await measure('architecture-map.discovery', () => {
|
|
565
|
+
if (hasExplicitEmptyModuleRegistry) {
|
|
566
|
+
return Promise.resolve([]);
|
|
567
|
+
}
|
|
568
|
+
if (hasArchitectureJson &&
|
|
569
|
+
!shouldUseConfiguredRootInference &&
|
|
570
|
+
!shouldUseTopLevelWorkspaceInference) {
|
|
571
|
+
return discoverModulesFromArchitectureContract(workspaceRoot, contract, modulesRoot);
|
|
572
|
+
}
|
|
573
|
+
if (hasArchitectureJson && hasComponentEntries) {
|
|
574
|
+
return discoverModulesFromComponents(workspaceRoot, contract, (0, moduleDiscovery_1.resolveContractsRootFromContract)(contract));
|
|
575
|
+
}
|
|
576
|
+
return discoverModulesFromFallbackScan(workspaceRoot, modulesRoot, (0, moduleDiscovery_1.resolveContractsRootFromContract)(contract), shouldUseConfiguredRootInference
|
|
577
|
+
? { configuredRootOnly: true }
|
|
578
|
+
: shouldUseTopLevelWorkspaceInference
|
|
579
|
+
? { topLevelWorkspaceOnly: true }
|
|
580
|
+
: undefined);
|
|
581
|
+
});
|
|
582
|
+
const moduleIds = modules.map((moduleEntry) => moduleEntry.moduleName);
|
|
583
|
+
const dependencySnapshot = await measure('architecture-map.dependency-graph', () => (0, dependencyValidation_1.buildModuleDependencyGraphSnapshot)(workspaceRoot, {
|
|
584
|
+
modulesRootRelativePath: modulesRoot,
|
|
585
|
+
moduleFilter: moduleIds,
|
|
586
|
+
}));
|
|
587
|
+
const edges = dependencySnapshot.edges.map((edge) => toArchitectureMapEdge(edge));
|
|
588
|
+
const hierarchyEdges = dependencySnapshot.hierarchyEdges;
|
|
589
|
+
const parsedCycles = dependencySnapshot.cycles
|
|
590
|
+
.map((cycle) => parseCycleString(cycle))
|
|
591
|
+
.filter((cycle) => cycle.length > 1)
|
|
592
|
+
.sort((left, right) => left.join('->').localeCompare(right.join('->')));
|
|
593
|
+
const incomingMap = buildIncomingMap(modules, edges);
|
|
594
|
+
const outgoingMap = buildOutgoingMap(modules, edges);
|
|
595
|
+
const cycleMembership = new Set(parsedCycles.flatMap((cycle) => cycle));
|
|
596
|
+
const hierarchyParentByChild = new Map(hierarchyEdges.map((edge) => [edge.childModule, edge.parentModule]));
|
|
597
|
+
const childModulesByParent = new Map();
|
|
598
|
+
for (const edge of hierarchyEdges) {
|
|
599
|
+
const children = childModulesByParent.get(edge.parentModule) ?? [];
|
|
600
|
+
children.push(edge.childModule);
|
|
601
|
+
childModulesByParent.set(edge.parentModule, children);
|
|
602
|
+
}
|
|
603
|
+
const independentModuleNames = [];
|
|
604
|
+
const potentialOrphanModuleNames = [];
|
|
605
|
+
const hotspotSummary = await measure('architecture-map.hotspots', () => Promise.all(modules.map(async (moduleEntry) => {
|
|
606
|
+
const incomingDependencyCount = incomingMap.get(moduleEntry.moduleName)?.length ?? 0;
|
|
607
|
+
const outgoingDependencyCount = outgoingMap.get(moduleEntry.moduleName)?.length ?? 0;
|
|
608
|
+
const hasNoPeerUsage = incomingDependencyCount === 0 && outgoingDependencyCount === 0;
|
|
609
|
+
const hasIntentionalEvidence = hasNoPeerUsage
|
|
610
|
+
? await hasIntentionalIndependentEvidence({
|
|
611
|
+
workspaceRoot,
|
|
612
|
+
moduleEntry,
|
|
613
|
+
hasChildren: (childModulesByParent.get(moduleEntry.moduleName)?.length ?? 0) > 0,
|
|
614
|
+
isLeafChild: hierarchyParentByChild.has(moduleEntry.moduleName) &&
|
|
615
|
+
(childModulesByParent.get(moduleEntry.moduleName)?.length ?? 0) === 0,
|
|
616
|
+
})
|
|
617
|
+
: false;
|
|
618
|
+
const orphan = hasNoPeerUsage && !hasIntentionalEvidence;
|
|
619
|
+
if (hasNoPeerUsage && hasIntentionalEvidence) {
|
|
620
|
+
independentModuleNames.push(moduleEntry.moduleName);
|
|
621
|
+
}
|
|
622
|
+
if (orphan) {
|
|
623
|
+
potentialOrphanModuleNames.push(moduleEntry.moduleName);
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
moduleName: moduleEntry.moduleName,
|
|
627
|
+
incomingDependencyCount,
|
|
628
|
+
outgoingDependencyCount,
|
|
629
|
+
participatesInCycle: cycleMembership.has(moduleEntry.moduleName),
|
|
630
|
+
orphan,
|
|
631
|
+
missingContract: !moduleEntry.contractExists,
|
|
632
|
+
...(moduleEntry.missingPublicEntrypointAlignment !== undefined
|
|
633
|
+
? {
|
|
634
|
+
missingPublicEntrypointAlignment: moduleEntry.missingPublicEntrypointAlignment,
|
|
635
|
+
}
|
|
636
|
+
: {}),
|
|
637
|
+
};
|
|
638
|
+
})));
|
|
639
|
+
const mostDependedOnModules = sortRankedCounts(hotspotSummary
|
|
640
|
+
.filter((entry) => entry.incomingDependencyCount > 0)
|
|
641
|
+
.map((entry) => ({
|
|
642
|
+
moduleName: entry.moduleName,
|
|
643
|
+
count: entry.incomingDependencyCount,
|
|
644
|
+
})));
|
|
645
|
+
const highestOutgoingFanOutModules = sortRankedCounts(hotspotSummary
|
|
646
|
+
.filter((entry) => entry.outgoingDependencyCount > 0)
|
|
647
|
+
.map((entry) => ({
|
|
648
|
+
moduleName: entry.moduleName,
|
|
649
|
+
count: entry.outgoingDependencyCount,
|
|
650
|
+
})));
|
|
651
|
+
const modulesInCircularDependencies = sortUnique(hotspotSummary
|
|
652
|
+
.filter((entry) => entry.participatesInCycle)
|
|
653
|
+
.map((entry) => entry.moduleName));
|
|
654
|
+
const independentModules = sortUnique(independentModuleNames);
|
|
655
|
+
const potentialOrphanModules = sortUnique(potentialOrphanModuleNames);
|
|
656
|
+
const orphanModules = potentialOrphanModules;
|
|
657
|
+
const missingContracts = sortUnique(hotspotSummary
|
|
658
|
+
.filter((entry) => entry.missingContract)
|
|
659
|
+
.map((entry) => entry.moduleName));
|
|
660
|
+
const missingPublicEntrypointAlignment = sortUnique(hotspotSummary
|
|
661
|
+
.filter((entry) => entry.missingPublicEntrypointAlignment === true)
|
|
662
|
+
.map((entry) => entry.moduleName));
|
|
663
|
+
const connectivityThreshold = contract?.governance.validation?.highInboundDependencyWarningThreshold ?? 3;
|
|
664
|
+
const highlyConnectedModules = sortRankedCounts(hotspotSummary
|
|
665
|
+
.map((entry) => ({
|
|
666
|
+
moduleName: entry.moduleName,
|
|
667
|
+
count: entry.incomingDependencyCount + entry.outgoingDependencyCount,
|
|
668
|
+
}))
|
|
669
|
+
.filter((entry) => entry.count >= connectivityThreshold));
|
|
670
|
+
return {
|
|
671
|
+
...(options?.metadata ? { xArchPilot: options.metadata } : {}),
|
|
672
|
+
reportVersion: 1,
|
|
673
|
+
projectName: resolveProjectName(workspaceRoot, contract),
|
|
674
|
+
generatedAtUtc: options?.generatedAtUtc ?? new Date().toISOString(),
|
|
675
|
+
discoveryMode,
|
|
676
|
+
modulesRoot,
|
|
677
|
+
modules,
|
|
678
|
+
moduleHotspotSummary: hotspotSummary,
|
|
679
|
+
edges,
|
|
680
|
+
hierarchyEdges,
|
|
681
|
+
cycles: parsedCycles,
|
|
682
|
+
hotspots: {
|
|
683
|
+
mostDependedOnModules,
|
|
684
|
+
highestOutgoingFanOutModules,
|
|
685
|
+
modulesInCircularDependencies,
|
|
686
|
+
independentModules,
|
|
687
|
+
potentialOrphanModules,
|
|
688
|
+
orphanModules,
|
|
689
|
+
missingContracts,
|
|
690
|
+
highlyConnectedModules,
|
|
691
|
+
missingPublicEntrypointAlignment,
|
|
692
|
+
},
|
|
693
|
+
summaryCounts: {
|
|
694
|
+
moduleCount: modules.length,
|
|
695
|
+
edgeCount: edges.length,
|
|
696
|
+
cycleCount: parsedCycles.length,
|
|
697
|
+
independentCount: independentModules.length,
|
|
698
|
+
potentialOrphanCount: potentialOrphanModules.length,
|
|
699
|
+
orphanCount: orphanModules.length,
|
|
700
|
+
highlyConnectedCount: highlyConnectedModules.length,
|
|
701
|
+
missingContractCount: missingContracts.length,
|
|
702
|
+
},
|
|
703
|
+
graph: {
|
|
704
|
+
nodes: modules.map((moduleEntry) => ({
|
|
705
|
+
id: moduleEntry.moduleName,
|
|
706
|
+
label: moduleEntry.moduleName,
|
|
707
|
+
})),
|
|
708
|
+
edges: edges.map((edge) => ({
|
|
709
|
+
source: edge.source,
|
|
710
|
+
target: edge.target,
|
|
711
|
+
importCount: edge.importCount,
|
|
712
|
+
publicImportCount: edge.publicImportCount,
|
|
713
|
+
nonPublicImportCount: edge.nonPublicImportCount,
|
|
714
|
+
})),
|
|
715
|
+
hierarchyEdges: hierarchyEdges.map((edge) => ({
|
|
716
|
+
source: edge.parentModule,
|
|
717
|
+
target: edge.childModule,
|
|
718
|
+
relationship: 'contains',
|
|
719
|
+
})),
|
|
720
|
+
},
|
|
721
|
+
notes: {
|
|
722
|
+
usedArchitectureJson: discoveryMode === 'architecture-json',
|
|
723
|
+
usedFallbackInference: discoveryMode !== 'architecture-json',
|
|
724
|
+
},
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
//# sourceMappingURL=architectureMap.js.map
|