projscan 4.6.0 → 4.8.0
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/README.md +25 -12
- package/dist/cli/_shared.js +12 -44
- package/dist/cli/_shared.js.map +1 -1
- package/dist/cli/changedOnly.d.ts +16 -0
- package/dist/cli/changedOnly.js +28 -0
- package/dist/cli/changedOnly.js.map +1 -0
- package/dist/cli/commands/start.js +5 -28
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/startOptionsRegistration.d.ts +2 -0
- package/dist/cli/commands/startOptionsRegistration.js +29 -0
- package/dist/cli/commands/startOptionsRegistration.js.map +1 -0
- package/dist/cli/formatOptions.d.ts +4 -0
- package/dist/cli/formatOptions.js +30 -0
- package/dist/cli/formatOptions.js.map +1 -0
- package/dist/core/agentBrief.js +6 -1
- package/dist/core/agentBrief.js.map +1 -1
- package/dist/core/ast.d.ts +2 -17
- package/dist/core/ast.js +4 -33
- package/dist/core/ast.js.map +1 -1
- package/dist/core/astBodySignals.js +2 -3
- package/dist/core/astBodySignals.js.map +1 -1
- package/dist/core/astMembers.d.ts +1 -0
- package/dist/core/astMembers.js +38 -9
- package/dist/core/astMembers.js.map +1 -1
- package/dist/core/astResult.d.ts +20 -0
- package/dist/core/astResult.js +39 -0
- package/dist/core/astResult.js.map +1 -0
- package/dist/core/bugHunt.js +2 -142
- package/dist/core/bugHunt.js.map +1 -1
- package/dist/core/bugHuntHotspotFindings.d.ts +2 -0
- package/dist/core/bugHuntHotspotFindings.js +68 -0
- package/dist/core/bugHuntHotspotFindings.js.map +1 -0
- package/dist/core/bugHuntPreflightFindings.d.ts +3 -0
- package/dist/core/bugHuntPreflightFindings.js +115 -0
- package/dist/core/bugHuntPreflightFindings.js.map +1 -0
- package/dist/core/codeGraph.d.ts +2 -24
- package/dist/core/codeGraph.js +8 -119
- package/dist/core/codeGraph.js.map +1 -1
- package/dist/core/codeGraphAdapterContexts.d.ts +8 -0
- package/dist/core/codeGraphAdapterContexts.js +14 -0
- package/dist/core/codeGraphAdapterContexts.js.map +1 -0
- package/dist/core/codeGraphFileSelection.d.ts +7 -0
- package/dist/core/codeGraphFileSelection.js +19 -0
- package/dist/core/codeGraphFileSelection.js.map +1 -0
- package/dist/core/codeGraphIncremental.d.ts +17 -0
- package/dist/core/codeGraphIncremental.js +64 -0
- package/dist/core/codeGraphIncremental.js.map +1 -0
- package/dist/core/codeGraphQueries.d.ts +9 -0
- package/dist/core/codeGraphQueries.js +25 -0
- package/dist/core/codeGraphQueries.js.map +1 -0
- package/dist/core/collisionDetector.d.ts +1 -0
- package/dist/core/collisionDetector.js +3 -0
- package/dist/core/collisionDetector.js.map +1 -1
- package/dist/core/coordination.js +23 -5
- package/dist/core/coordination.js.map +1 -1
- package/dist/core/coordinationEvidence.d.ts +1 -0
- package/dist/core/coordinationEvidence.js.map +1 -1
- package/dist/core/dataflow.js +3 -338
- package/dist/core/dataflow.js.map +1 -1
- package/dist/core/dataflowDatabaseSinks.d.ts +8 -0
- package/dist/core/dataflowDatabaseSinks.js +78 -0
- package/dist/core/dataflowDatabaseSinks.js.map +1 -0
- package/dist/core/dataflowRiskAssembly.d.ts +11 -0
- package/dist/core/dataflowRiskAssembly.js +117 -0
- package/dist/core/dataflowRiskAssembly.js.map +1 -0
- package/dist/core/dataflowTraversal.d.ts +25 -0
- package/dist/core/dataflowTraversal.js +200 -0
- package/dist/core/dataflowTraversal.js.map +1 -0
- package/dist/core/fileInspectionReport.d.ts +13 -0
- package/dist/core/fileInspectionReport.js +49 -0
- package/dist/core/fileInspectionReport.js.map +1 -0
- package/dist/core/fileInspector.d.ts +3 -11
- package/dist/core/fileInspector.js +2 -46
- package/dist/core/fileInspector.js.map +1 -1
- package/dist/core/fixSuggest.d.ts +1 -9
- package/dist/core/fixSuggest.js +2 -58
- package/dist/core/fixSuggest.js.map +1 -1
- package/dist/core/fixSuggestDependencyNames.d.ts +1 -0
- package/dist/core/fixSuggestDependencyNames.js +9 -0
- package/dist/core/fixSuggestDependencyNames.js.map +1 -0
- package/dist/core/fixSuggestPreview.d.ts +10 -0
- package/dist/core/fixSuggestPreview.js +87 -0
- package/dist/core/fixSuggestPreview.js.map +1 -0
- package/dist/core/frameworkExpressSources.js +6 -31
- package/dist/core/frameworkExpressSources.js.map +1 -1
- package/dist/core/frameworkFastifySources.js +5 -22
- package/dist/core/frameworkFastifySources.js.map +1 -1
- package/dist/core/frameworkHonoSources.js +12 -24
- package/dist/core/frameworkHonoSources.js.map +1 -1
- package/dist/core/frameworkKoaSources.js +5 -24
- package/dist/core/frameworkKoaSources.js.map +1 -1
- package/dist/core/frameworkNextRouteSources.d.ts +6 -1
- package/dist/core/frameworkNextRouteSources.js +31 -1
- package/dist/core/frameworkNextRouteSources.js.map +1 -1
- package/dist/core/frameworkRemixSources.d.ts +2 -0
- package/dist/core/frameworkRemixSources.js +63 -0
- package/dist/core/frameworkRemixSources.js.map +1 -0
- package/dist/core/frameworkSourceContext.d.ts +15 -0
- package/dist/core/frameworkSourceContext.js +2 -0
- package/dist/core/frameworkSourceContext.js.map +1 -0
- package/dist/core/frameworkSourceMatching.d.ts +6 -0
- package/dist/core/frameworkSourceMatching.js +29 -0
- package/dist/core/frameworkSourceMatching.js.map +1 -0
- package/dist/core/frameworkSourceResolvers.d.ts +2 -0
- package/dist/core/frameworkSourceResolvers.js +45 -0
- package/dist/core/frameworkSourceResolvers.js.map +1 -0
- package/dist/core/frameworkSources.d.ts +3 -3
- package/dist/core/frameworkSources.js +17 -15
- package/dist/core/frameworkSources.js.map +1 -1
- package/dist/core/frameworkSvelteKitSources.d.ts +2 -0
- package/dist/core/frameworkSvelteKitSources.js +118 -0
- package/dist/core/frameworkSvelteKitSources.js.map +1 -0
- package/dist/core/intentRouter.d.ts +4 -14
- package/dist/core/intentRouter.js +2 -33
- package/dist/core/intentRouter.js.map +1 -1
- package/dist/core/intentRouterCatalog.js +49 -0
- package/dist/core/intentRouterCatalog.js.map +1 -1
- package/dist/core/intentRouterKeywordToolGuards.js +5 -0
- package/dist/core/intentRouterKeywordToolGuards.js.map +1 -1
- package/dist/core/intentRouterKeywordWeights.js +36 -0
- package/dist/core/intentRouterKeywordWeights.js.map +1 -1
- package/dist/core/intentRouterReleaseSignals.js +104 -39
- package/dist/core/intentRouterReleaseSignals.js.map +1 -1
- package/dist/core/intentRouterResolution.d.ts +3 -0
- package/dist/core/intentRouterResolution.js +11 -0
- package/dist/core/intentRouterResolution.js.map +1 -0
- package/dist/core/intentRouterResult.d.ts +16 -0
- package/dist/core/intentRouterResult.js +34 -0
- package/dist/core/intentRouterResult.js.map +1 -0
- package/dist/core/intentRouterWorkSignals.js +18 -0
- package/dist/core/intentRouterWorkSignals.js.map +1 -1
- package/dist/core/languages/pythonLockfiles.d.ts +4 -0
- package/dist/core/languages/pythonLockfiles.js +6 -2
- package/dist/core/languages/pythonLockfiles.js.map +1 -1
- package/dist/core/languages/pythonManifests.js +11 -24
- package/dist/core/languages/pythonManifests.js.map +1 -1
- package/dist/core/languages/pythonPep508.js +1 -1
- package/dist/core/languages/pythonPep508.js.map +1 -1
- package/dist/core/languages/pythonProjectEvidence.js +4 -4
- package/dist/core/languages/pythonProjectEvidence.js.map +1 -1
- package/dist/core/languages/pythonPyproject.js +1 -1
- package/dist/core/languages/pythonPyproject.js.map +1 -1
- package/dist/core/languages/pythonPyprojectEvidence.d.ts +7 -0
- package/dist/core/languages/pythonPyprojectEvidence.js +23 -0
- package/dist/core/languages/pythonPyprojectEvidence.js.map +1 -0
- package/dist/core/languages/pythonRequirements.d.ts +2 -0
- package/dist/core/languages/pythonRequirements.js +215 -24
- package/dist/core/languages/pythonRequirements.js.map +1 -1
- package/dist/core/pluginAnalyzerLoading.d.ts +3 -0
- package/dist/core/pluginAnalyzerLoading.js +55 -0
- package/dist/core/pluginAnalyzerLoading.js.map +1 -0
- package/dist/core/pluginAnalyzerRunning.d.ts +10 -0
- package/dist/core/pluginAnalyzerRunning.js +32 -0
- package/dist/core/pluginAnalyzerRunning.js.map +1 -0
- package/dist/core/pluginIssueValidation.d.ts +2 -0
- package/dist/core/pluginIssueValidation.js +22 -0
- package/dist/core/pluginIssueValidation.js.map +1 -0
- package/dist/core/pluginManifestDiscovery.d.ts +25 -0
- package/dist/core/pluginManifestDiscovery.js +80 -0
- package/dist/core/pluginManifestDiscovery.js.map +1 -0
- package/dist/core/pluginManifestValidation.d.ts +41 -0
- package/dist/core/pluginManifestValidation.js +179 -0
- package/dist/core/pluginManifestValidation.js.map +1 -0
- package/dist/core/pluginModuleLoading.d.ts +8 -0
- package/dist/core/pluginModuleLoading.js +91 -0
- package/dist/core/pluginModuleLoading.js.map +1 -0
- package/dist/core/pluginReporterLoading.d.ts +41 -0
- package/dist/core/pluginReporterLoading.js +105 -0
- package/dist/core/pluginReporterLoading.js.map +1 -0
- package/dist/core/pluginRuntimeTypes.d.ts +20 -0
- package/dist/core/pluginRuntimeTypes.js +2 -0
- package/dist/core/pluginRuntimeTypes.js.map +1 -0
- package/dist/core/plugins.d.ts +11 -126
- package/dist/core/plugins.js +13 -478
- package/dist/core/plugins.js.map +1 -1
- package/dist/core/preflight.d.ts +1 -2
- package/dist/core/preflight.js +4 -91
- package/dist/core/preflight.js.map +1 -1
- package/dist/core/preflightEvidence.js +11 -0
- package/dist/core/preflightEvidence.js.map +1 -1
- package/dist/core/preflightInputs.d.ts +1 -0
- package/dist/core/preflightInputs.js.map +1 -1
- package/dist/core/preflightReasons.d.ts +21 -0
- package/dist/core/preflightReasons.js +28 -0
- package/dist/core/preflightReasons.js.map +1 -0
- package/dist/core/preflightReport.d.ts +9 -0
- package/dist/core/preflightReport.js +67 -0
- package/dist/core/preflightReport.js.map +1 -0
- package/dist/core/regressionPlan.d.ts +2 -1
- package/dist/core/regressionPlan.js +7 -1
- package/dist/core/regressionPlan.js.map +1 -1
- package/dist/core/releaseEvidence.js +6 -120
- package/dist/core/releaseEvidence.js.map +1 -1
- package/dist/core/releaseEvidenceArtifacts.d.ts +3 -0
- package/dist/core/releaseEvidenceArtifacts.js +65 -0
- package/dist/core/releaseEvidenceArtifacts.js.map +1 -0
- package/dist/core/releaseEvidenceVerdict.d.ts +6 -0
- package/dist/core/releaseEvidenceVerdict.js +54 -0
- package/dist/core/releaseEvidenceVerdict.js.map +1 -0
- package/dist/core/reportPathRedaction.d.ts +4 -0
- package/dist/core/reportPathRedaction.js +64 -0
- package/dist/core/reportPathRedaction.js.map +1 -0
- package/dist/core/reportScope.js +2 -163
- package/dist/core/reportScope.js.map +1 -1
- package/dist/core/reportScopeFiltering.d.ts +9 -0
- package/dist/core/reportScopeFiltering.js +102 -0
- package/dist/core/reportScopeFiltering.js.map +1 -0
- package/dist/core/review.js +2 -47
- package/dist/core/review.js.map +1 -1
- package/dist/core/reviewChangedReport.d.ts +13 -0
- package/dist/core/reviewChangedReport.js +38 -0
- package/dist/core/reviewChangedReport.js.map +1 -0
- package/dist/core/reviewComputation.d.ts +9 -0
- package/dist/core/reviewComputation.js +14 -0
- package/dist/core/reviewComputation.js.map +1 -0
- package/dist/core/reviewContractChanges.js +22 -8
- package/dist/core/reviewContractChanges.js.map +1 -1
- package/dist/core/reviewDataflow.js +18 -0
- package/dist/core/reviewDataflow.js.map +1 -1
- package/dist/core/roadmapCatalog.js +7 -203
- package/dist/core/roadmapCatalog.js.map +1 -1
- package/dist/core/roadmapCatalogPost44.d.ts +2 -0
- package/dist/core/roadmapCatalogPost44.js +205 -0
- package/dist/core/roadmapCatalogPost44.js.map +1 -0
- package/dist/core/roadmapCatalogTypes.d.ts +6 -0
- package/dist/core/roadmapCatalogTypes.js +2 -0
- package/dist/core/roadmapCatalogTypes.js.map +1 -0
- package/dist/core/searchIndex.d.ts +2 -14
- package/dist/core/searchIndex.js +4 -227
- package/dist/core/searchIndex.js.map +1 -1
- package/dist/core/searchIndexFiles.d.ts +1 -0
- package/dist/core/searchIndexFiles.js +26 -0
- package/dist/core/searchIndexFiles.js.map +1 -0
- package/dist/core/searchIndexText.d.ts +15 -0
- package/dist/core/searchIndexText.js +204 -0
- package/dist/core/searchIndexText.js.map +1 -0
- package/dist/core/start.js +5 -46
- package/dist/core/start.js.map +1 -1
- package/dist/core/startClaimRouteCriteria.d.ts +7 -0
- package/dist/core/startClaimRouteCriteria.js +16 -0
- package/dist/core/startClaimRouteCriteria.js.map +1 -0
- package/dist/core/startCouplingRouteCriteria.d.ts +2 -0
- package/dist/core/startCouplingRouteCriteria.js +13 -0
- package/dist/core/startCouplingRouteCriteria.js.map +1 -0
- package/dist/core/startDependencyRouteCriteria.d.ts +2 -0
- package/dist/core/startDependencyRouteCriteria.js +43 -0
- package/dist/core/startDependencyRouteCriteria.js.map +1 -0
- package/dist/core/startEvidence.d.ts +1 -1
- package/dist/core/startEvidence.js +16 -1
- package/dist/core/startEvidence.js.map +1 -1
- package/dist/core/startFileRouteCriteria.d.ts +2 -0
- package/dist/core/startFileRouteCriteria.js +56 -0
- package/dist/core/startFileRouteCriteria.js.map +1 -0
- package/dist/core/startFixedRouteCriteria.d.ts +1 -0
- package/dist/core/startFixedRouteCriteria.js +90 -0
- package/dist/core/startFixedRouteCriteria.js.map +1 -0
- package/dist/core/startImpactRouteCriteria.d.ts +7 -0
- package/dist/core/startImpactRouteCriteria.js +14 -0
- package/dist/core/startImpactRouteCriteria.js.map +1 -0
- package/dist/core/startInputs.d.ts +1 -0
- package/dist/core/startInputs.js +4 -1
- package/dist/core/startInputs.js.map +1 -1
- package/dist/core/startIntentTargets.d.ts +1 -0
- package/dist/core/startIntentTargets.js +28 -0
- package/dist/core/startIntentTargets.js.map +1 -1
- package/dist/core/startMissionControl.js +8 -2
- package/dist/core/startMissionControl.js.map +1 -1
- package/dist/core/startMissionPolicy.js +12 -0
- package/dist/core/startMissionPolicy.js.map +1 -1
- package/dist/core/startMode.d.ts +1 -0
- package/dist/core/startMode.js +10 -2
- package/dist/core/startMode.js.map +1 -1
- package/dist/core/startPreflightRouteCriteria.d.ts +11 -0
- package/dist/core/startPreflightRouteCriteria.js +29 -0
- package/dist/core/startPreflightRouteCriteria.js.map +1 -0
- package/dist/core/startProductPlanningRouteCriteria.d.ts +8 -0
- package/dist/core/startProductPlanningRouteCriteria.js +29 -0
- package/dist/core/startProductPlanningRouteCriteria.js.map +1 -0
- package/dist/core/startRegressionRouteCriteria.d.ts +3 -0
- package/dist/core/startRegressionRouteCriteria.js +62 -0
- package/dist/core/startRegressionRouteCriteria.js.map +1 -0
- package/dist/core/startReportBuilder.d.ts +1 -0
- package/dist/core/startReportBuilder.js +1 -0
- package/dist/core/startReportBuilder.js.map +1 -1
- package/dist/core/startReportContext.d.ts +23 -0
- package/dist/core/startReportContext.js +51 -0
- package/dist/core/startReportContext.js.map +1 -0
- package/dist/core/startRoadmapPreview.d.ts +2 -0
- package/dist/core/startRoadmapPreview.js +31 -0
- package/dist/core/startRoadmapPreview.js.map +1 -0
- package/dist/core/startRouteActions.js +39 -1
- package/dist/core/startRouteActions.js.map +1 -1
- package/dist/core/startSuccessCriteria.d.ts +2 -3
- package/dist/core/startSuccessCriteria.js +15 -419
- package/dist/core/startSuccessCriteria.js.map +1 -1
- package/dist/core/startUnderstandRouteCriteria.d.ts +3 -0
- package/dist/core/startUnderstandRouteCriteria.js +97 -0
- package/dist/core/startUnderstandRouteCriteria.js.map +1 -0
- package/dist/core/taint.d.ts +2 -67
- package/dist/core/taint.js +41 -164
- package/dist/core/taint.js.map +1 -1
- package/dist/core/taintIndex.d.ts +20 -0
- package/dist/core/taintIndex.js +81 -0
- package/dist/core/taintIndex.js.map +1 -0
- package/dist/core/taintTraversal.d.ts +8 -0
- package/dist/core/taintTraversal.js +113 -0
- package/dist/core/taintTraversal.js.map +1 -0
- package/dist/core/taintTypes.d.ts +67 -0
- package/dist/core/taintTypes.js +2 -0
- package/dist/core/taintTypes.js.map +1 -0
- package/dist/core/telemetry.d.ts +9 -89
- package/dist/core/telemetry.js +35 -387
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/telemetryConfig.d.ts +58 -0
- package/dist/core/telemetryConfig.js +171 -0
- package/dist/core/telemetryConfig.js.map +1 -0
- package/dist/core/telemetryEvents.d.ts +57 -0
- package/dist/core/telemetryEvents.js +143 -0
- package/dist/core/telemetryEvents.js.map +1 -0
- package/dist/core/telemetryFlushing.d.ts +10 -0
- package/dist/core/telemetryFlushing.js +42 -0
- package/dist/core/telemetryFlushing.js.map +1 -0
- package/dist/core/telemetryRecording.d.ts +26 -0
- package/dist/core/telemetryRecording.js +38 -0
- package/dist/core/telemetryRecording.js.map +1 -0
- package/dist/core/telemetrySender.d.ts +9 -0
- package/dist/core/telemetrySender.js +22 -0
- package/dist/core/telemetrySender.js.map +1 -0
- package/dist/core/upgradePreviewPython.js +1 -1
- package/dist/core/upgradePreviewPython.js.map +1 -1
- package/dist/index.d.ts +4 -60
- package/dist/index.js +4 -60
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/serverMessageHandling.d.ts +3 -0
- package/dist/mcp/serverMessageHandling.js +16 -0
- package/dist/mcp/serverMessageHandling.js.map +1 -0
- package/dist/mcp/toolDefinitions.d.ts +3 -0
- package/dist/mcp/toolDefinitions.js +15 -0
- package/dist/mcp/toolDefinitions.js.map +1 -0
- package/dist/mcp/tools.js +2 -13
- package/dist/mcp/tools.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/publicAgent.d.ts +22 -0
- package/dist/publicAgent.js +23 -0
- package/dist/publicAgent.js.map +1 -0
- package/dist/publicCore.d.ts +29 -0
- package/dist/publicCore.js +30 -0
- package/dist/publicCore.js.map +1 -0
- package/dist/publicLanguages.d.ts +1 -0
- package/dist/publicLanguages.js +2 -0
- package/dist/publicLanguages.js.map +1 -0
- package/dist/publicMcp.d.ts +8 -0
- package/dist/publicMcp.js +9 -0
- package/dist/publicMcp.js.map +1 -0
- package/dist/reporters/consoleFixReporter.d.ts +3 -0
- package/dist/reporters/consoleFixReporter.js +41 -0
- package/dist/reporters/consoleFixReporter.js.map +1 -0
- package/dist/reporters/consoleReporter.d.ts +1 -3
- package/dist/reporters/consoleReporter.js +1 -42
- package/dist/reporters/consoleReporter.js.map +1 -1
- package/dist/reporters/htmlAnalysisReporter.d.ts +3 -0
- package/dist/reporters/htmlAnalysisReporter.js +98 -0
- package/dist/reporters/htmlAnalysisReporter.js.map +1 -0
- package/dist/reporters/htmlCoverageReporter.d.ts +2 -0
- package/dist/reporters/htmlCoverageReporter.js +52 -0
- package/dist/reporters/htmlCoverageReporter.js.map +1 -0
- package/dist/reporters/htmlImpactReporter.d.ts +2 -0
- package/dist/reporters/htmlImpactReporter.js +41 -0
- package/dist/reporters/htmlImpactReporter.js.map +1 -0
- package/dist/reporters/htmlPrDiffReporter.d.ts +2 -0
- package/dist/reporters/htmlPrDiffReporter.js +84 -0
- package/dist/reporters/htmlPrDiffReporter.js.map +1 -0
- package/dist/reporters/htmlReporter.d.ts +20 -9
- package/dist/reporters/htmlReporter.js +7 -365
- package/dist/reporters/htmlReporter.js.map +1 -1
- package/dist/reporters/htmlReviewReporter.d.ts +2 -0
- package/dist/reporters/htmlReviewReporter.js +94 -0
- package/dist/reporters/htmlReviewReporter.js.map +1 -0
- package/dist/reporters/htmlShared.d.ts +7 -0
- package/dist/reporters/htmlShared.js +106 -0
- package/dist/reporters/htmlShared.js.map +1 -0
- package/dist/tool-manifest.json +2 -2
- package/dist/types/preflight.d.ts +19 -0
- package/dist/types/start.d.ts +7 -437
- package/dist/types/startCommon.d.ts +79 -0
- package/dist/types/startCommon.js +2 -0
- package/dist/types/startCommon.js.map +1 -0
- package/dist/types/startExecution.d.ts +44 -0
- package/dist/types/startExecution.js +2 -0
- package/dist/types/startExecution.js.map +1 -0
- package/dist/types/startMissionControl.d.ts +91 -0
- package/dist/types/startMissionControl.js +2 -0
- package/dist/types/startMissionControl.js.map +1 -0
- package/dist/types/startMissionProof.d.ts +91 -0
- package/dist/types/startMissionProof.js +2 -0
- package/dist/types/startMissionProof.js.map +1 -0
- package/dist/types/startMissionResume.d.ts +100 -0
- package/dist/types/startMissionResume.js +2 -0
- package/dist/types/startMissionResume.js.map +1 -0
- package/dist/types/startMissionReview.d.ts +45 -0
- package/dist/types/startMissionReview.js +2 -0
- package/dist/types/startMissionReview.js.map +1 -0
- package/dist/types/startMissionTooling.d.ts +16 -0
- package/dist/types/startMissionTooling.js +2 -0
- package/dist/types/startMissionTooling.js.map +1 -0
- package/dist/utils/changedFiles.d.ts +1 -0
- package/dist/utils/changedFiles.js +7 -4
- package/dist/utils/changedFiles.js.map +1 -1
- package/docs/GUIDE.md +9 -7
- package/docs/ROADMAP.md +18 -7
- package/docs/examples/adoption-workflows.md +12 -1
- package/docs/examples/swarm-coordination.md +11 -2
- package/package.json +1 -1
package/dist/core/plugins.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { PluginReporterResolveResult } from './pluginReporterLoading.js';
|
|
2
|
+
import type { LoadedPlugin } from './pluginRuntimeTypes.js';
|
|
3
|
+
import type { PluginReporterCommand } from './pluginManifestValidation.js';
|
|
3
4
|
/**
|
|
4
5
|
* Stable local plugin API (2.0+).
|
|
5
6
|
*
|
|
@@ -15,105 +16,15 @@ import type { FileEntry, Issue, DataflowReport, SemanticGraphReport } from '../t
|
|
|
15
16
|
* discipline as the rest of projscan.
|
|
16
17
|
*/
|
|
17
18
|
export declare const PLUGIN_PREVIEW_FLAG = "PROJSCAN_PLUGINS_PREVIEW";
|
|
18
|
-
export
|
|
19
|
-
export
|
|
20
|
-
export
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
name: string;
|
|
27
|
-
kind: PluginKind;
|
|
28
|
-
/** Module entry point, relative to the manifest file. */
|
|
29
|
-
module: string;
|
|
30
|
-
/** Optional human-readable summary. */
|
|
31
|
-
description?: string;
|
|
32
|
-
}
|
|
33
|
-
export interface PluginAnalyzerManifest extends PluginManifestBase {
|
|
34
|
-
kind: 'analyzer';
|
|
35
|
-
/** Issue category emitted by this plugin (`Issue.category`). */
|
|
36
|
-
category: string;
|
|
37
|
-
}
|
|
38
|
-
export interface PluginReporterManifest extends PluginManifestBase {
|
|
39
|
-
kind: 'reporter';
|
|
40
|
-
/** CLI commands this reporter can render. */
|
|
41
|
-
commands: PluginReporterCommand[];
|
|
42
|
-
}
|
|
43
|
-
export type PluginManifest = PluginAnalyzerManifest | PluginReporterManifest;
|
|
44
|
-
export interface PluginAnalyzerContext {
|
|
45
|
-
schemaVersion: 1;
|
|
46
|
-
getCodeGraph: () => Promise<CodeGraph>;
|
|
47
|
-
getSemanticGraph: () => Promise<SemanticGraphReport>;
|
|
48
|
-
getDataflow: () => Promise<DataflowReport>;
|
|
49
|
-
}
|
|
50
|
-
export interface PluginAnalyzerExports {
|
|
51
|
-
check: (rootPath: string, files: FileEntry[], context?: PluginAnalyzerContext) => Promise<Issue[]> | Issue[];
|
|
52
|
-
}
|
|
53
|
-
export interface PluginReporterContext<TPayload = unknown> {
|
|
54
|
-
command: PluginReporterCommand;
|
|
55
|
-
rootPath: string;
|
|
56
|
-
manifest: PluginReporterManifest;
|
|
57
|
-
payload: TPayload;
|
|
58
|
-
}
|
|
59
|
-
export interface PluginReporterExports {
|
|
60
|
-
render: (context: PluginReporterContext) => Promise<string> | string;
|
|
61
|
-
}
|
|
62
|
-
export interface LoadedPlugin {
|
|
63
|
-
manifest: PluginAnalyzerManifest;
|
|
64
|
-
/** Absolute path to the manifest file on disk. */
|
|
65
|
-
manifestPath: string;
|
|
66
|
-
/** Absolute path to the resolved module entry point. */
|
|
67
|
-
modulePath: string;
|
|
68
|
-
exports: PluginAnalyzerExports;
|
|
69
|
-
}
|
|
70
|
-
export interface LoadedReporterPlugin {
|
|
71
|
-
manifest: PluginReporterManifest;
|
|
72
|
-
/** Absolute path to the manifest file on disk. */
|
|
73
|
-
manifestPath: string;
|
|
74
|
-
/** Absolute path to the resolved module entry point. */
|
|
75
|
-
modulePath: string;
|
|
76
|
-
exports: PluginReporterExports;
|
|
77
|
-
}
|
|
78
|
-
export interface PluginDiscoveryEntry {
|
|
79
|
-
manifestPath: string;
|
|
80
|
-
manifest: PluginManifest | null;
|
|
81
|
-
/** Set when the manifest failed to parse or validate. */
|
|
82
|
-
error?: string;
|
|
83
|
-
diagnostic?: PluginDiagnostic;
|
|
84
|
-
}
|
|
85
|
-
export type PluginManifestFileResult = {
|
|
86
|
-
ok: true;
|
|
87
|
-
manifest: PluginManifest;
|
|
88
|
-
} | {
|
|
89
|
-
ok: false;
|
|
90
|
-
reason: string;
|
|
91
|
-
diagnostic: PluginDiagnostic;
|
|
92
|
-
};
|
|
93
|
-
export type PluginReporterResolveResult = {
|
|
94
|
-
ok: true;
|
|
95
|
-
plugin: LoadedReporterPlugin;
|
|
96
|
-
} | {
|
|
97
|
-
ok: false;
|
|
98
|
-
reason: string;
|
|
99
|
-
diagnostic: PluginDiagnostic;
|
|
100
|
-
};
|
|
101
|
-
export type PluginReporterRenderResult = {
|
|
102
|
-
ok: true;
|
|
103
|
-
output: string;
|
|
104
|
-
} | {
|
|
105
|
-
ok: false;
|
|
106
|
-
reason: string;
|
|
107
|
-
diagnostic: PluginDiagnostic;
|
|
108
|
-
};
|
|
19
|
+
export { PLUGIN_DIR, PLUGIN_MANIFEST_EXT, discoverPluginManifests, readPluginManifestFile, } from './pluginManifestDiscovery.js';
|
|
20
|
+
export type { PluginDiscoveryEntry, PluginManifestFileResult } from './pluginManifestDiscovery.js';
|
|
21
|
+
export type { LoadedPlugin, PluginAnalyzerContext, PluginAnalyzerExports, } from './pluginRuntimeTypes.js';
|
|
22
|
+
export { runAnalyzerPlugins } from './pluginAnalyzerRunning.js';
|
|
23
|
+
export { PLUGIN_REPORTER_COMMANDS, PLUGIN_SCHEMA_VERSION, validateManifest, } from './pluginManifestValidation.js';
|
|
24
|
+
export type { PluginAnalyzerManifest, PluginDiagnostic, PluginKind, PluginManifest, PluginReporterCommand, PluginReporterManifest, } from './pluginManifestValidation.js';
|
|
25
|
+
export { renderReporterPlugin } from './pluginReporterLoading.js';
|
|
26
|
+
export type { LoadedReporterPlugin, PluginReporterContext, PluginReporterExports, PluginReporterRenderResult, PluginReporterResolveResult, } from './pluginReporterLoading.js';
|
|
109
27
|
export declare function pluginsEnabled(): boolean;
|
|
110
|
-
export declare function readPluginManifestFile(manifestPath: string): Promise<PluginManifestFileResult>;
|
|
111
|
-
/**
|
|
112
|
-
* Discover every plugin manifest under `<root>/.projscan-plugins/`. Manifests
|
|
113
|
-
* that fail to parse or validate are returned with `manifest: null` and an
|
|
114
|
-
* `error` so the CLI / MCP tool can surface them without throwing.
|
|
115
|
-
*/
|
|
116
|
-
export declare function discoverPluginManifests(rootPath: string): Promise<PluginDiscoveryEntry[]>;
|
|
117
28
|
/**
|
|
118
29
|
* Discover, validate, and dynamically import every plugin under the
|
|
119
30
|
* project. Returns [] when the preview flag is off.
|
|
@@ -124,29 +35,3 @@ export declare function discoverPluginManifests(rootPath: string): Promise<Plugi
|
|
|
124
35
|
*/
|
|
125
36
|
export declare function loadPlugins(rootPath: string): Promise<LoadedPlugin[]>;
|
|
126
37
|
export declare function resolveReporterPlugin(rootPath: string, reporterName: string, command: PluginReporterCommand): Promise<PluginReporterResolveResult>;
|
|
127
|
-
export declare function renderReporterPlugin(plugin: LoadedReporterPlugin, context: PluginReporterContext): Promise<PluginReporterRenderResult>;
|
|
128
|
-
/**
|
|
129
|
-
* Run every loaded analyzer plugin against `files`. Issues that don't pass
|
|
130
|
-
* a tight shape check are dropped so a malformed plugin can't poison the
|
|
131
|
-
* issue stream. Each plugin's output is also re-stamped with `id` prefixed
|
|
132
|
-
* by the plugin name (so two plugins emitting the same local rule id can't
|
|
133
|
-
* collide).
|
|
134
|
-
*/
|
|
135
|
-
export declare function runAnalyzerPlugins(plugins: LoadedPlugin[], rootPath: string, files: FileEntry[], context?: PluginAnalyzerContext): Promise<Issue[]>;
|
|
136
|
-
export interface PluginDiagnostic {
|
|
137
|
-
code: 'invalid-manifest' | 'unsupported-schema-version' | 'invalid-name' | 'unsupported-kind' | 'invalid-module' | 'invalid-category' | 'invalid-commands' | 'invalid-description' | 'invalid-manifest-path' | 'invalid-json' | 'read-error' | 'plugins-disabled' | 'reporter-not-found' | 'reporter-unsupported-command' | 'invalid-reporter-export' | 'reporter-load-error' | 'reporter-render-error' | 'plugin-untrusted';
|
|
138
|
-
message: string;
|
|
139
|
-
field?: string;
|
|
140
|
-
hint?: string;
|
|
141
|
-
}
|
|
142
|
-
interface ValidationOk {
|
|
143
|
-
ok: true;
|
|
144
|
-
manifest: PluginManifest;
|
|
145
|
-
}
|
|
146
|
-
interface ValidationFail {
|
|
147
|
-
ok: false;
|
|
148
|
-
reason: string;
|
|
149
|
-
diagnostic: PluginDiagnostic;
|
|
150
|
-
}
|
|
151
|
-
export declare function validateManifest(input: unknown): ValidationOk | ValidationFail;
|
|
152
|
-
export {};
|
package/dist/core/plugins.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { getPluginTrustStatus } from './pluginTrust.js';
|
|
1
|
+
import { loadAnalyzerPluginEntry } from './pluginAnalyzerLoading.js';
|
|
2
|
+
import { discoverPluginManifests } from './pluginManifestDiscovery.js';
|
|
3
|
+
import { resolveReporterPlugin as resolveReporterPluginEntry } from './pluginReporterLoading.js';
|
|
5
4
|
/**
|
|
6
5
|
* Stable local plugin API (2.0+).
|
|
7
6
|
*
|
|
@@ -17,87 +16,14 @@ import { getPluginTrustStatus } from './pluginTrust.js';
|
|
|
17
16
|
* discipline as the rest of projscan.
|
|
18
17
|
*/
|
|
19
18
|
export const PLUGIN_PREVIEW_FLAG = 'PROJSCAN_PLUGINS_PREVIEW';
|
|
20
|
-
export
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
25
|
-
export const PLUGIN_REPORTER_COMMANDS = ['doctor', 'analyze', 'ci'];
|
|
19
|
+
export { PLUGIN_DIR, PLUGIN_MANIFEST_EXT, discoverPluginManifests, readPluginManifestFile, } from './pluginManifestDiscovery.js';
|
|
20
|
+
export { runAnalyzerPlugins } from './pluginAnalyzerRunning.js';
|
|
21
|
+
export { PLUGIN_REPORTER_COMMANDS, PLUGIN_SCHEMA_VERSION, validateManifest, } from './pluginManifestValidation.js';
|
|
22
|
+
export { renderReporterPlugin } from './pluginReporterLoading.js';
|
|
26
23
|
export function pluginsEnabled() {
|
|
27
24
|
const v = process.env[PLUGIN_PREVIEW_FLAG];
|
|
28
25
|
return v === '1' || v === 'true';
|
|
29
26
|
}
|
|
30
|
-
export async function readPluginManifestFile(manifestPath) {
|
|
31
|
-
let raw;
|
|
32
|
-
try {
|
|
33
|
-
raw = await fs.readFile(manifestPath, 'utf-8');
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
const message = `unable to read manifest: ${err instanceof Error ? err.message : String(err)}`;
|
|
37
|
-
return {
|
|
38
|
-
ok: false,
|
|
39
|
-
reason: message,
|
|
40
|
-
diagnostic: {
|
|
41
|
-
code: 'read-error',
|
|
42
|
-
message,
|
|
43
|
-
hint: 'Check file permissions and try again.',
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
let parsed;
|
|
48
|
-
try {
|
|
49
|
-
parsed = JSON.parse(raw);
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
const message = `invalid JSON: ${err instanceof Error ? err.message : String(err)}`;
|
|
53
|
-
return {
|
|
54
|
-
ok: false,
|
|
55
|
-
reason: message,
|
|
56
|
-
diagnostic: {
|
|
57
|
-
code: 'invalid-json',
|
|
58
|
-
message,
|
|
59
|
-
hint: 'Fix the manifest so it is valid JSON.',
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
const validation = validateManifest(parsed);
|
|
64
|
-
return validation.ok
|
|
65
|
-
? { ok: true, manifest: validation.manifest }
|
|
66
|
-
: { ok: false, reason: validation.reason, diagnostic: validation.diagnostic };
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Discover every plugin manifest under `<root>/.projscan-plugins/`. Manifests
|
|
70
|
-
* that fail to parse or validate are returned with `manifest: null` and an
|
|
71
|
-
* `error` so the CLI / MCP tool can surface them without throwing.
|
|
72
|
-
*/
|
|
73
|
-
export async function discoverPluginManifests(rootPath) {
|
|
74
|
-
const dir = path.join(rootPath, PLUGIN_DIR);
|
|
75
|
-
let entries;
|
|
76
|
-
try {
|
|
77
|
-
entries = await fs.readdir(dir);
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
return [];
|
|
81
|
-
}
|
|
82
|
-
const out = [];
|
|
83
|
-
for (const name of entries.sort()) {
|
|
84
|
-
if (!name.endsWith(PLUGIN_MANIFEST_EXT))
|
|
85
|
-
continue;
|
|
86
|
-
const manifestPath = path.join(dir, name);
|
|
87
|
-
const result = await readPluginManifestFile(manifestPath);
|
|
88
|
-
if (!result.ok) {
|
|
89
|
-
out.push({
|
|
90
|
-
manifestPath,
|
|
91
|
-
manifest: null,
|
|
92
|
-
error: result.reason,
|
|
93
|
-
diagnostic: result.diagnostic,
|
|
94
|
-
});
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
out.push({ manifestPath, manifest: result.manifest });
|
|
98
|
-
}
|
|
99
|
-
return out;
|
|
100
|
-
}
|
|
101
27
|
/**
|
|
102
28
|
* Discover, validate, and dynamically import every plugin under the
|
|
103
29
|
* project. Returns [] when the preview flag is off.
|
|
@@ -112,407 +38,16 @@ export async function loadPlugins(rootPath) {
|
|
|
112
38
|
const discovered = await discoverPluginManifests(rootPath);
|
|
113
39
|
const loaded = [];
|
|
114
40
|
for (const entry of discovered) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
continue;
|
|
119
|
-
const modulePath = path.resolve(path.dirname(entry.manifestPath), entry.manifest.module);
|
|
120
|
-
try {
|
|
121
|
-
await assertPluginModuleReadable(entry.manifest.module, modulePath);
|
|
122
|
-
// Trust-on-first-use gate: never import (execute) a module the user
|
|
123
|
-
// hasn't explicitly approved. The preview flag opts a user into the
|
|
124
|
-
// plugin *system*; trust opts them into each specific module's bytes.
|
|
125
|
-
const trust = await getPluginTrustStatus(modulePath);
|
|
126
|
-
if (trust.status !== 'trusted') {
|
|
127
|
-
process.stderr.write(untrustedAnalyzerWarning(entry.manifest.name, trust.status));
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
const mod = await importPluginModule(modulePath);
|
|
131
|
-
const exportsObj = (mod.default ?? mod);
|
|
132
|
-
if (typeof exportsObj.check !== 'function') {
|
|
133
|
-
process.stderr.write(`[projscan] plugin "${entry.manifest.name}" missing required export "check"; export default { check(rootPath, files) { ... } } or export a named check function. skipped.\n`);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
loaded.push({
|
|
137
|
-
manifest: entry.manifest,
|
|
138
|
-
manifestPath: entry.manifestPath,
|
|
139
|
-
modulePath,
|
|
140
|
-
exports: { check: exportsObj.check },
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
catch (err) {
|
|
144
|
-
const detail = describePluginModuleLoadError(err, entry.manifest.module, modulePath, 'manifest');
|
|
145
|
-
process.stderr.write(`[projscan] plugin "${entry.manifest.name}" failed to load: ${detail.message}${detail.hint ? ` ${detail.hint}` : ''}. skipped.\n`);
|
|
146
|
-
}
|
|
41
|
+
const plugin = await loadAnalyzerPluginEntry(entry);
|
|
42
|
+
if (plugin)
|
|
43
|
+
loaded.push(plugin);
|
|
147
44
|
}
|
|
148
45
|
return loaded;
|
|
149
46
|
}
|
|
150
47
|
export async function resolveReporterPlugin(rootPath, reporterName, command) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
message: `reporter plugins require ${PLUGIN_PREVIEW_FLAG}=1`,
|
|
155
|
-
hint: `Set ${PLUGIN_PREVIEW_FLAG}=1 in the environment to enable plugin reporters.`,
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
const entries = await discoverPluginManifests(rootPath);
|
|
159
|
-
const reporters = entries.filter((entry) => entry.manifest?.kind === 'reporter');
|
|
160
|
-
const entry = reporters.find((candidate) => candidate.manifest.name === reporterName);
|
|
161
|
-
if (!entry) {
|
|
162
|
-
return pluginRuntimeFail({
|
|
163
|
-
code: 'reporter-not-found',
|
|
164
|
-
message: `reporter plugin "${reporterName}" was not found`,
|
|
165
|
-
hint: 'Run `projscan plugin list` to see discovered reporter plugins.',
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
if (!entry.manifest.commands.includes(command)) {
|
|
169
|
-
return pluginRuntimeFail({
|
|
170
|
-
code: 'reporter-unsupported-command',
|
|
171
|
-
message: `reporter plugin "${reporterName}" does not support command "${command}"`,
|
|
172
|
-
hint: `Add "${command}" to the reporter manifest's commands array or choose a different reporter.`,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
return loadReporterPlugin(entry.manifest, entry.manifestPath);
|
|
176
|
-
}
|
|
177
|
-
export async function renderReporterPlugin(plugin, context) {
|
|
178
|
-
try {
|
|
179
|
-
const output = await plugin.exports.render(context);
|
|
180
|
-
if (typeof output !== 'string') {
|
|
181
|
-
return pluginRuntimeFail({
|
|
182
|
-
code: 'reporter-render-error',
|
|
183
|
-
message: `reporter plugin "${plugin.manifest.name}" returned ${typeof output}; expected string`,
|
|
184
|
-
hint: 'Reporter render(context) must return text for stdout.',
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
return { ok: true, output };
|
|
188
|
-
}
|
|
189
|
-
catch (err) {
|
|
190
|
-
return pluginRuntimeFail({
|
|
191
|
-
code: 'reporter-render-error',
|
|
192
|
-
message: `reporter plugin "${plugin.manifest.name}" failed during render: ${formatError(err)}`,
|
|
193
|
-
hint: 'Fix the reporter render(context) implementation and try again.',
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
async function loadReporterPlugin(manifest, manifestPath) {
|
|
198
|
-
const modulePath = path.resolve(path.dirname(manifestPath), manifest.module);
|
|
199
|
-
try {
|
|
200
|
-
await assertPluginModuleReadable(manifest.module, modulePath);
|
|
201
|
-
// Trust-on-first-use gate — see loadPlugins. Reporters render to stdout,
|
|
202
|
-
// but importing the module still runs its top-level code, so the same
|
|
203
|
-
// approval requirement applies.
|
|
204
|
-
const trust = await getPluginTrustStatus(modulePath);
|
|
205
|
-
if (trust.status !== 'trusted') {
|
|
206
|
-
return pluginRuntimeFail(untrustedReporterDiagnostic(manifest.name, trust.status));
|
|
207
|
-
}
|
|
208
|
-
const mod = await importPluginModule(modulePath);
|
|
209
|
-
const exportsObj = (mod.default ?? mod);
|
|
210
|
-
if (typeof exportsObj.render !== 'function') {
|
|
211
|
-
return pluginRuntimeFail({
|
|
212
|
-
code: 'invalid-reporter-export',
|
|
213
|
-
message: `reporter plugin "${manifest.name}" missing required export "render"`,
|
|
214
|
-
hint: 'Use export default { render(context) { ... } } or export a named render function.',
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
return {
|
|
218
|
-
ok: true,
|
|
219
|
-
plugin: {
|
|
220
|
-
manifest,
|
|
221
|
-
manifestPath,
|
|
222
|
-
modulePath,
|
|
223
|
-
exports: { render: exportsObj.render },
|
|
224
|
-
},
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
catch (err) {
|
|
228
|
-
const detail = describePluginModuleLoadError(err, manifest.module, modulePath, 'reporter manifest');
|
|
229
|
-
return pluginRuntimeFail({
|
|
230
|
-
code: 'reporter-load-error',
|
|
231
|
-
message: `reporter plugin "${manifest.name}" failed to load: ${detail.message}`,
|
|
232
|
-
hint: detail.hint ?? 'Check the reporter module path and module syntax.',
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
class PluginModuleMissingError extends Error {
|
|
237
|
-
manifestModule;
|
|
238
|
-
modulePath;
|
|
239
|
-
constructor(manifestModule, modulePath) {
|
|
240
|
-
super(`module "${manifestModule}" was not found at ${modulePath}`);
|
|
241
|
-
this.manifestModule = manifestModule;
|
|
242
|
-
this.modulePath = modulePath;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
class PluginModuleReadError extends Error {
|
|
246
|
-
manifestModule;
|
|
247
|
-
modulePath;
|
|
248
|
-
constructor(manifestModule, modulePath, err) {
|
|
249
|
-
super(`module "${manifestModule}" could not be read at ${modulePath}: ${formatError(err)}`);
|
|
250
|
-
this.manifestModule = manifestModule;
|
|
251
|
-
this.modulePath = modulePath;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
async function assertPluginModuleReadable(manifestModule, modulePath) {
|
|
255
|
-
try {
|
|
256
|
-
await fs.access(modulePath);
|
|
257
|
-
}
|
|
258
|
-
catch (err) {
|
|
259
|
-
const code = typeof err === 'object' && err !== null && 'code' in err
|
|
260
|
-
? String(err.code)
|
|
261
|
-
: '';
|
|
262
|
-
if (code === 'ENOENT')
|
|
263
|
-
throw new PluginModuleMissingError(manifestModule, modulePath);
|
|
264
|
-
throw new PluginModuleReadError(manifestModule, modulePath, err);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
function describePluginModuleLoadError(err, manifestModule, modulePath, manifestLabel) {
|
|
268
|
-
if (err instanceof PluginModuleMissingError) {
|
|
269
|
-
return {
|
|
270
|
-
message: err.message,
|
|
271
|
-
hint: `Check the ${manifestLabel} "module" path.`,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
if (err instanceof PluginModuleReadError) {
|
|
275
|
-
return {
|
|
276
|
-
message: err.message,
|
|
277
|
-
hint: `Check file permissions for the ${manifestLabel} "module" path.`,
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
if (err instanceof SyntaxError) {
|
|
281
|
-
return {
|
|
282
|
-
message: `syntax error in module "${manifestModule}": ${formatError(err)}`,
|
|
283
|
-
hint: `Run node "${modulePath}" to reproduce the syntax error.`,
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
return { message: formatError(err) };
|
|
287
|
-
}
|
|
288
|
-
function untrustedAnalyzerWarning(name, status) {
|
|
289
|
-
const reason = status === 'changed' ? 'module changed since it was trusted' : 'module is not trusted';
|
|
290
|
-
const verb = status === 'changed' ? 'Re-run' : 'Run';
|
|
291
|
-
return `[projscan] plugin "${name}" ${reason}; skipped (not executed). ${verb} \`projscan plugin trust ${name}\` to approve this module.\n`;
|
|
292
|
-
}
|
|
293
|
-
function untrustedReporterDiagnostic(name, status) {
|
|
294
|
-
const changed = status === 'changed';
|
|
295
|
-
return {
|
|
296
|
-
code: 'plugin-untrusted',
|
|
297
|
-
message: changed
|
|
298
|
-
? `reporter plugin "${name}" changed since it was trusted; not executed`
|
|
299
|
-
: `reporter plugin "${name}" is not trusted; not executed`,
|
|
300
|
-
hint: `${changed ? 'Re-run' : 'Run'} \`projscan plugin trust ${name}\` to approve this reporter.`,
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
function importPluginModule(modulePath) {
|
|
304
|
-
return dynamicImport(pathToFileURL(modulePath).href).catch(async (err) => {
|
|
305
|
-
if (!isMissingDynamicImportCallback(err))
|
|
306
|
-
throw err;
|
|
307
|
-
return importPluginModuleFromSource(modulePath);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
function isMissingDynamicImportCallback(err) {
|
|
311
|
-
return (err instanceof TypeError && err.message.includes('dynamic import callback was not specified'));
|
|
312
|
-
}
|
|
313
|
-
async function importPluginModuleFromSource(modulePath) {
|
|
314
|
-
const source = await fs.readFile(modulePath, 'utf-8');
|
|
315
|
-
const defaultMatch = source.match(/^\s*export\s+default\s+([\s\S]*?)\s*;?\s*$/);
|
|
316
|
-
if (defaultMatch) {
|
|
317
|
-
const expression = defaultMatch[1].trim().replace(/;$/, '');
|
|
318
|
-
return { default: new Function(`return (${expression});`)() };
|
|
319
|
-
}
|
|
320
|
-
const names = [];
|
|
321
|
-
let transformed = source.replace(/\bexport\s+(async\s+function|function)\s+([A-Za-z_$][\w$]*)/g, (_m, kind, name) => {
|
|
322
|
-
names.push(String(name));
|
|
323
|
-
return `${kind} ${name}`;
|
|
324
|
-
});
|
|
325
|
-
transformed = transformed.replace(/\bexport\s+const\s+([A-Za-z_$][\w$]*)\s*=/g, (_m, name) => {
|
|
326
|
-
names.push(String(name));
|
|
327
|
-
return `const ${name} =`;
|
|
48
|
+
return resolveReporterPluginEntry(rootPath, reporterName, command, {
|
|
49
|
+
pluginsEnabled: pluginsEnabled(),
|
|
50
|
+
previewFlag: PLUGIN_PREVIEW_FLAG,
|
|
328
51
|
});
|
|
329
|
-
if (names.length === 0) {
|
|
330
|
-
throw new Error('unsupported module syntax in Vitest VM fallback');
|
|
331
|
-
}
|
|
332
|
-
return new Function(`${transformed}\nreturn { ${names.join(', ')} };`)();
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Run every loaded analyzer plugin against `files`. Issues that don't pass
|
|
336
|
-
* a tight shape check are dropped so a malformed plugin can't poison the
|
|
337
|
-
* issue stream. Each plugin's output is also re-stamped with `id` prefixed
|
|
338
|
-
* by the plugin name (so two plugins emitting the same local rule id can't
|
|
339
|
-
* collide).
|
|
340
|
-
*/
|
|
341
|
-
export async function runAnalyzerPlugins(plugins, rootPath, files, context) {
|
|
342
|
-
const out = [];
|
|
343
|
-
for (const p of plugins) {
|
|
344
|
-
let raw;
|
|
345
|
-
try {
|
|
346
|
-
raw = (await p.exports.check(rootPath, files, context)) ?? [];
|
|
347
|
-
}
|
|
348
|
-
catch (err) {
|
|
349
|
-
process.stderr.write(`[projscan] plugin "${p.manifest.name}" threw during check: ${err instanceof Error ? err.message : String(err)}. ignored for this run.\n`);
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
for (const issue of raw) {
|
|
353
|
-
if (!isWellShapedIssue(issue))
|
|
354
|
-
continue;
|
|
355
|
-
out.push({
|
|
356
|
-
...issue,
|
|
357
|
-
id: `plugin:${p.manifest.name}:${issue.id}`,
|
|
358
|
-
category: issue.category || p.manifest.category,
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return out;
|
|
363
|
-
}
|
|
364
|
-
function failValidation(diagnostic) {
|
|
365
|
-
return { ok: false, reason: diagnostic.message, diagnostic };
|
|
366
|
-
}
|
|
367
|
-
function pluginRuntimeFail(diagnostic) {
|
|
368
|
-
return { ok: false, reason: diagnostic.message, diagnostic };
|
|
369
|
-
}
|
|
370
|
-
function formatError(err) {
|
|
371
|
-
return err instanceof Error ? err.message : String(err);
|
|
372
|
-
}
|
|
373
|
-
export function validateManifest(input) {
|
|
374
|
-
if (!input || typeof input !== 'object') {
|
|
375
|
-
return failValidation({
|
|
376
|
-
code: 'invalid-manifest',
|
|
377
|
-
message: 'manifest must be a JSON object',
|
|
378
|
-
hint: 'Use an object with schemaVersion, name, kind, module, and category fields.',
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
const obj = input;
|
|
382
|
-
if (obj.schemaVersion !== PLUGIN_SCHEMA_VERSION) {
|
|
383
|
-
return failValidation({
|
|
384
|
-
code: 'unsupported-schema-version',
|
|
385
|
-
field: 'schemaVersion',
|
|
386
|
-
message: `unsupported schemaVersion ${String(obj.schemaVersion)}; expected ${PLUGIN_SCHEMA_VERSION}`,
|
|
387
|
-
hint: `Set "schemaVersion": ${PLUGIN_SCHEMA_VERSION}.`,
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
if (typeof obj.name !== 'string' || !/^[a-z0-9][a-z0-9._/-]{0,64}$/i.test(obj.name)) {
|
|
391
|
-
return failValidation({
|
|
392
|
-
code: 'invalid-name',
|
|
393
|
-
field: 'name',
|
|
394
|
-
message: 'name is required and must be 1-65 chars of [a-z0-9._/-]',
|
|
395
|
-
hint: 'Use a stable 1-65 character plugin id such as "team/no-console" or "my-plugin".',
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
if (obj.kind !== 'analyzer' && obj.kind !== 'reporter') {
|
|
399
|
-
return failValidation({
|
|
400
|
-
code: 'unsupported-kind',
|
|
401
|
-
field: 'kind',
|
|
402
|
-
message: 'kind must be "analyzer" or "reporter"',
|
|
403
|
-
hint: 'Set "kind": "analyzer" for issue-producing plugins or "kind": "reporter" for CLI output plugins.',
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
if (typeof obj.module !== 'string' || obj.module.length === 0) {
|
|
407
|
-
return failValidation({
|
|
408
|
-
code: 'invalid-module',
|
|
409
|
-
field: 'module',
|
|
410
|
-
message: 'module is required and must be a relative path',
|
|
411
|
-
hint: 'Point to a local module inside the same plugin directory, for example "./check.mjs".',
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
// Path-traversal guard. Modules must resolve under the manifest's own dir.
|
|
415
|
-
if (path.isAbsolute(obj.module) || obj.module.split(/[/\\]/).some((seg) => seg === '..')) {
|
|
416
|
-
return failValidation({
|
|
417
|
-
code: 'invalid-module',
|
|
418
|
-
field: 'module',
|
|
419
|
-
message: 'module must be a relative path inside the plugin dir',
|
|
420
|
-
hint: 'Do not use absolute paths or any ".." path segment.',
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
if (obj.description !== undefined && typeof obj.description !== 'string') {
|
|
424
|
-
return failValidation({
|
|
425
|
-
code: 'invalid-description',
|
|
426
|
-
field: 'description',
|
|
427
|
-
message: 'description must be a string when provided',
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
if (obj.kind === 'analyzer') {
|
|
431
|
-
if (typeof obj.category !== 'string' || obj.category.length === 0) {
|
|
432
|
-
return failValidation({
|
|
433
|
-
code: 'invalid-category',
|
|
434
|
-
field: 'category',
|
|
435
|
-
message: 'category is required for analyzer plugins',
|
|
436
|
-
hint: 'Use the fallback Issue.category for this plugin, for example "custom" or "security".',
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
return {
|
|
440
|
-
ok: true,
|
|
441
|
-
manifest: {
|
|
442
|
-
schemaVersion: obj.schemaVersion,
|
|
443
|
-
name: obj.name,
|
|
444
|
-
kind: obj.kind,
|
|
445
|
-
module: obj.module,
|
|
446
|
-
category: obj.category,
|
|
447
|
-
...(typeof obj.description === 'string' ? { description: obj.description } : {}),
|
|
448
|
-
},
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
const commandValidation = validateReporterCommands(obj.commands);
|
|
452
|
-
if (!commandValidation.ok)
|
|
453
|
-
return commandValidation;
|
|
454
|
-
return {
|
|
455
|
-
ok: true,
|
|
456
|
-
manifest: {
|
|
457
|
-
schemaVersion: obj.schemaVersion,
|
|
458
|
-
name: obj.name,
|
|
459
|
-
kind: obj.kind,
|
|
460
|
-
module: obj.module,
|
|
461
|
-
commands: commandValidation.commands,
|
|
462
|
-
...(typeof obj.description === 'string' ? { description: obj.description } : {}),
|
|
463
|
-
},
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
function validateReporterCommands(input) {
|
|
467
|
-
if (!Array.isArray(input) || input.length === 0) {
|
|
468
|
-
return failValidation({
|
|
469
|
-
code: 'invalid-commands',
|
|
470
|
-
field: 'commands',
|
|
471
|
-
message: 'commands must be a non-empty array for reporter plugins',
|
|
472
|
-
hint: 'Use one or more supported commands: doctor, analyze, ci.',
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
const seen = new Set();
|
|
476
|
-
const invalid = [];
|
|
477
|
-
for (const value of input) {
|
|
478
|
-
if (typeof value !== 'string' || !isReporterCommand(value)) {
|
|
479
|
-
invalid.push(String(value));
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
seen.add(value);
|
|
483
|
-
}
|
|
484
|
-
if (invalid.length > 0) {
|
|
485
|
-
return failValidation({
|
|
486
|
-
code: 'invalid-commands',
|
|
487
|
-
field: 'commands',
|
|
488
|
-
message: `unsupported reporter command(s): ${invalid.join(', ')}`,
|
|
489
|
-
hint: 'Supported reporter commands are: doctor, analyze, ci.',
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
return { ok: true, commands: [...seen] };
|
|
493
|
-
}
|
|
494
|
-
function isReporterCommand(value) {
|
|
495
|
-
return PLUGIN_REPORTER_COMMANDS.includes(value);
|
|
496
|
-
}
|
|
497
|
-
function isWellShapedIssue(x) {
|
|
498
|
-
if (!x || typeof x !== 'object')
|
|
499
|
-
return false;
|
|
500
|
-
const obj = x;
|
|
501
|
-
if (typeof obj.id !== 'string' || obj.id.length === 0)
|
|
502
|
-
return false;
|
|
503
|
-
if (typeof obj.title !== 'string')
|
|
504
|
-
return false;
|
|
505
|
-
if (typeof obj.description !== 'string')
|
|
506
|
-
return false;
|
|
507
|
-
if (!isSeverity(obj.severity))
|
|
508
|
-
return false;
|
|
509
|
-
if (typeof obj.category !== 'string')
|
|
510
|
-
return false;
|
|
511
|
-
if (typeof obj.fixAvailable !== 'boolean')
|
|
512
|
-
return false;
|
|
513
|
-
return true;
|
|
514
|
-
}
|
|
515
|
-
function isSeverity(x) {
|
|
516
|
-
return x === 'error' || x === 'warning' || x === 'info';
|
|
517
52
|
}
|
|
518
53
|
//# sourceMappingURL=plugins.js.map
|