@skyramp/mcp 0.3.2-rc.pom-3 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/commandLibrary.d.ts +1 -0
- package/build/commands/commandLibrary.js +19 -13
- package/build/commands/localDevTestChangesCommand.d.ts +15 -0
- package/build/commands/localDevTestChangesCommand.js +201 -0
- package/build/index.js +80 -6
- package/build/prompts/code-reuse.js +3 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
- package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
- package/build/prompts/local-dev/local-dev-plan.js +429 -0
- package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
- package/build/prompts/local-dev/local-dev-prompts.js +190 -0
- package/build/prompts/pom-aware-code-reuse.js +12 -0
- package/build/prompts/prompt-utils.d.ts +8 -0
- package/build/prompts/prompt-utils.js +33 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
- package/build/prompts/sut-setup/shared.js +16 -12
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
- package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
- package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
- package/build/prompts/testbot/testbot-prompts.js +32 -52
- package/build/recommendation/planRanker.d.ts +15 -2
- package/build/recommendation/planRanker.js +76 -5
- package/build/resources/testbotResource.js +2 -1
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +2 -1
- package/build/services/TestExecutionService.js +8 -3
- package/build/services/TestGenerationService.d.ts +2 -2
- package/build/services/TestGenerationService.js +39 -21
- package/build/services/containerEnv.js +3 -1
- package/build/tool-phases.js +6 -0
- package/build/tools/code-refactor/codeReuseTool.js +43 -4
- package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
- package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
- package/build/tools/code-refactor/reuse-outcome.js +158 -0
- package/build/tools/code-refactor/reuse-state.d.ts +45 -0
- package/build/tools/code-refactor/reuse-state.js +140 -0
- package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
- package/build/tools/enrichTestWithMocksTool.js +726 -0
- package/build/tools/executeSkyrampTestTool.d.ts +11 -0
- package/build/tools/executeSkyrampTestTool.js +62 -21
- package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
- package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
- package/build/tools/generate-tests/generateContractRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
- package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
- package/build/tools/generate-tests/generateMockRestTool.js +391 -22
- package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
- package/build/tools/generate-tests/planGuard.js +2 -22
- package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
- package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
- package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
- package/build/tools/localDevWorkerComposeTool.js +264 -0
- package/build/tools/one-click/oneClickTool.d.ts +13 -0
- package/build/tools/one-click/oneClickTool.js +195 -24
- package/build/tools/preflightMockCheckTool.d.ts +2 -0
- package/build/tools/preflightMockCheckTool.js +96 -0
- package/build/tools/queryProxyMocksTool.d.ts +70 -0
- package/build/tools/queryProxyMocksTool.js +522 -0
- package/build/tools/runExistingTestsTool.d.ts +31 -0
- package/build/tools/runExistingTestsTool.js +214 -13
- package/build/tools/submitReportTool.js +38 -3
- package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
- package/build/tools/test-management/analyzeChangesTool.js +63 -40
- package/build/tools/test-management/registerTestPlanTool.js +55 -7
- package/build/tools/trace/startTraceCollectionTool.js +3 -3
- package/build/types/FrontendIntegration.d.ts +3 -0
- package/build/types/FrontendIntegration.js +3 -0
- package/build/types/OneClickCommands.d.ts +1 -1
- package/build/types/Recommendation.d.ts +20 -0
- package/build/types/Recommendation.js +32 -6
- package/build/types/RepositoryAnalysis.d.ts +131 -14
- package/build/types/RepositoryAnalysis.js +16 -2
- package/build/types/ReuseOutcome.d.ts +63 -0
- package/build/types/ReuseOutcome.js +33 -0
- package/build/types/TestExecution.d.ts +1 -0
- package/build/types/TestTypes.d.ts +25 -7
- package/build/types/TestTypes.js +22 -6
- package/build/types/TestbotReport.d.ts +7 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.js +1 -0
- package/build/utils/AnalysisStateManager.d.ts +26 -0
- package/build/utils/AnalysisStateManager.js +31 -1
- package/build/utils/analyze-openapi.js +18 -1
- package/build/utils/branchDiff.d.ts +17 -1
- package/build/utils/branchDiff.js +99 -14
- package/build/utils/featureFlags.d.ts +31 -0
- package/build/utils/featureFlags.js +37 -0
- package/build/utils/frontendIntegration.js +8 -1
- package/build/utils/grpcMockValidation.d.ts +1 -0
- package/build/utils/grpcMockValidation.js +49 -0
- package/build/utils/httpMethodValidation.d.ts +4 -0
- package/build/utils/httpMethodValidation.js +15 -0
- package/build/utils/logger.js +1 -1
- package/build/utils/mockCompatibility.d.ts +49 -0
- package/build/utils/mockCompatibility.js +82 -0
- package/build/utils/pom-scope/pom-files.js +7 -0
- package/build/utils/pom-verify/bindings.js +11 -1
- package/build/utils/pom-verify/re-exports.d.ts +10 -0
- package/build/utils/pom-verify/re-exports.js +61 -0
- package/build/utils/pom-verify/resolve.d.ts +4 -1
- package/build/utils/pom-verify/resolve.js +7 -4
- package/build/utils/pom-verify/verify.d.ts +5 -0
- package/build/utils/pom-verify/verify.js +25 -3
- package/build/utils/progress.js +10 -5
- package/build/utils/proxy-terminal.js +3 -3
- package/build/utils/routeParsers.d.ts +3 -9
- package/build/utils/routeParsers.js +79 -4
- package/build/utils/utils.js +2 -2
- package/build/utils/versions.d.ts +4 -3
- package/build/utils/versions.js +3 -1
- package/build/utils/workspaceAuth.d.ts +46 -0
- package/build/utils/workspaceAuth.js +156 -1
- package/build/workspace/testSuites.d.ts +2 -1
- package/build/workspace/testSuites.js +1 -1
- package/build/workspace/workspace.d.ts +108 -32
- package/build/workspace/workspace.js +32 -4
- package/package.json +5 -2
- package/build/adapters/jestAdapter.test.d.ts +0 -1
- package/build/adapters/jestAdapter.test.js +0 -93
- package/build/adapters/mochaAdapter.test.d.ts +0 -1
- package/build/adapters/mochaAdapter.test.js +0 -63
- package/build/adapters/playwrightAdapter.test.d.ts +0 -1
- package/build/adapters/playwrightAdapter.test.js +0 -169
- package/build/adapters/pytestAdapter.test.d.ts +0 -1
- package/build/adapters/pytestAdapter.test.js +0 -90
- package/build/prompts/code-reuse.test.d.ts +0 -1
- package/build/prompts/code-reuse.test.js +0 -62
- package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
- package/build/prompts/pom-aware-code-reuse.test.js +0 -11
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
- package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
- package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
- package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
- package/build/prompts/testbot/testbot-prompts.test.js +0 -451
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
- package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
- package/build/recommendation/discriminators.test.d.ts +0 -1
- package/build/recommendation/discriminators.test.js +0 -324
- package/build/recommendation/diversity.test.d.ts +0 -1
- package/build/recommendation/diversity.test.js +0 -77
- package/build/recommendation/planRanker.test.d.ts +0 -1
- package/build/recommendation/planRanker.test.js +0 -110
- package/build/resources/testbotResource.test.d.ts +0 -1
- package/build/resources/testbotResource.test.js +0 -44
- package/build/services/AnalyticsService.test.d.ts +0 -1
- package/build/services/AnalyticsService.test.js +0 -86
- package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.integration.test.js +0 -162
- package/build/services/ScenarioGenerationService.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.test.js +0 -414
- package/build/services/TestDiscoveryService.test.d.ts +0 -1
- package/build/services/TestDiscoveryService.test.js +0 -983
- package/build/services/TestExecutionService.test.d.ts +0 -1
- package/build/services/TestExecutionService.test.js +0 -1032
- package/build/services/TestGenerationService.test.d.ts +0 -1
- package/build/services/TestGenerationService.test.js +0 -578
- package/build/tool-phase-coverage.test.d.ts +0 -1
- package/build/tool-phase-coverage.test.js +0 -49
- package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
- package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
- package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
- package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
- package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
- package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
- package/build/tools/generate-tests/planGuard.test.js +0 -185
- package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
- package/build/tools/generate-tests/scenarioLint.test.js +0 -100
- package/build/tools/runExistingTestsTool.test.d.ts +0 -1
- package/build/tools/runExistingTestsTool.test.js +0 -379
- package/build/tools/submitReportTool.test.d.ts +0 -1
- package/build/tools/submitReportTool.test.js +0 -1428
- package/build/tools/test-management/actionsTool.test.d.ts +0 -1
- package/build/tools/test-management/actionsTool.test.js +0 -436
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
- package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
- package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
- package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
- package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
- package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
- package/build/tools/trace/resolveSessionPaths.test.js +0 -104
- package/build/tools/trace/sessionState.test.d.ts +0 -1
- package/build/tools/trace/sessionState.test.js +0 -17
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
- package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
- package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
- package/build/tools/workspace/serviceUpsert.test.js +0 -50
- package/build/utils/AnalysisStateManager.test.d.ts +0 -1
- package/build/utils/AnalysisStateManager.test.js +0 -134
- package/build/utils/dartRouteExtractor.test.d.ts +0 -1
- package/build/utils/dartRouteExtractor.test.js +0 -307
- package/build/utils/docker.test.d.ts +0 -1
- package/build/utils/docker.test.js +0 -114
- package/build/utils/featureFlags.test.d.ts +0 -1
- package/build/utils/featureFlags.test.js +0 -81
- package/build/utils/fileWalk.test.d.ts +0 -1
- package/build/utils/fileWalk.test.js +0 -252
- package/build/utils/frontendIntegration.test.d.ts +0 -1
- package/build/utils/frontendIntegration.test.js +0 -229
- package/build/utils/frontendSelectors.test.d.ts +0 -1
- package/build/utils/frontendSelectors.test.js +0 -118
- package/build/utils/gitStaging.test.d.ts +0 -1
- package/build/utils/gitStaging.test.js +0 -111
- package/build/utils/httpDefaults.test.d.ts +0 -1
- package/build/utils/httpDefaults.test.js +0 -21
- package/build/utils/importerHop.test.d.ts +0 -1
- package/build/utils/importerHop.test.js +0 -469
- package/build/utils/pathAffinityClassification.test.d.ts +0 -1
- package/build/utils/pathAffinityClassification.test.js +0 -208
- package/build/utils/planMatchKeys.test.d.ts +0 -1
- package/build/utils/planMatchKeys.test.js +0 -123
- package/build/utils/pom-scope/index.test.d.ts +0 -1
- package/build/utils/pom-scope/index.test.js +0 -278
- package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
- package/build/utils/pom-scope/pom-files.test.js +0 -29
- package/build/utils/pom-scope/scoring.test.d.ts +0 -1
- package/build/utils/pom-scope/scoring.test.js +0 -39
- package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
- package/build/utils/pom-scope/selector-extractor.test.js +0 -67
- package/build/utils/pom-verify/bindings.test.d.ts +0 -1
- package/build/utils/pom-verify/bindings.test.js +0 -164
- package/build/utils/pom-verify/calls.test.d.ts +0 -1
- package/build/utils/pom-verify/calls.test.js +0 -61
- package/build/utils/pom-verify/resolve.test.d.ts +0 -1
- package/build/utils/pom-verify/resolve.test.js +0 -114
- package/build/utils/pom-verify/verify.test.d.ts +0 -1
- package/build/utils/pom-verify/verify.test.js +0 -374
- package/build/utils/pr-comment-parser.test.d.ts +0 -1
- package/build/utils/pr-comment-parser.test.js +0 -428
- package/build/utils/progress.test.d.ts +0 -1
- package/build/utils/progress.test.js +0 -37
- package/build/utils/projectMetadata.test.d.ts +0 -1
- package/build/utils/projectMetadata.test.js +0 -172
- package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
- package/build/utils/pythonMountPrefixes.test.js +0 -113
- package/build/utils/repoScanner.test.d.ts +0 -1
- package/build/utils/repoScanner.test.js +0 -190
- package/build/utils/reportVerification.test.d.ts +0 -1
- package/build/utils/reportVerification.test.js +0 -185
- package/build/utils/routeParsers.test.d.ts +0 -1
- package/build/utils/routeParsers.test.js +0 -1011
- package/build/utils/scenarioDrafting.test.d.ts +0 -1
- package/build/utils/scenarioDrafting.test.js +0 -876
- package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
- package/build/utils/sourceRouteExtractor.test.js +0 -738
- package/build/utils/telemetry.test.d.ts +0 -1
- package/build/utils/telemetry.test.js +0 -70
- package/build/utils/trace-parser.test.d.ts +0 -6
- package/build/utils/trace-parser.test.js +0 -140
- package/build/utils/uiPageEnumerator.test.d.ts +0 -1
- package/build/utils/uiPageEnumerator.test.js +0 -824
- package/build/utils/utils.test.d.ts +0 -1
- package/build/utils/utils.test.js +0 -103
- package/build/utils/walkerCharacterization.test.d.ts +0 -1
- package/build/utils/walkerCharacterization.test.js +0 -233
- package/build/utils/workspaceAuth.test.d.ts +0 -1
- package/build/utils/workspaceAuth.test.js +0 -260
- package/build/workspace/testSuites.test.d.ts +0 -1
- package/build/workspace/testSuites.test.js +0 -23
- package/build/workspace/workspace.test.d.ts +0 -1
- package/build/workspace/workspace.test.js +0 -264
|
@@ -39,3 +39,40 @@ export function isContractConsumerModeEnabled() {
|
|
|
39
39
|
export function isTestbotEnabled() {
|
|
40
40
|
return process.env.SKYRAMP_FEATURE_TESTBOT === "1";
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns true when the local-dev workflow is enabled
|
|
44
|
+
* (SKYRAMP_FEATURE_LOCAL_DEV=1).
|
|
45
|
+
*
|
|
46
|
+
* The local-dev workflow registers the `skyramp_local_dev` prompt and
|
|
47
|
+
* one-click routing, which diffs from a base commit against the current
|
|
48
|
+
* working state, generates mock configurations and backend tests, executes
|
|
49
|
+
* them locally, and reports results — without requiring a pull request or
|
|
50
|
+
* CI environment.
|
|
51
|
+
*/
|
|
52
|
+
export function isLocalDevEnabled() {
|
|
53
|
+
return process.env.SKYRAMP_FEATURE_LOCAL_DEV === "1";
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns true when general one-click workflows are enabled
|
|
57
|
+
* (SKYRAMP_FEATURE_ONE_CLICK=1).
|
|
58
|
+
*/
|
|
59
|
+
export function isOneClickEnabled() {
|
|
60
|
+
return process.env.SKYRAMP_FEATURE_ONE_CLICK === "1";
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gates the POM-aware path of `skyramp_reuse_code`
|
|
64
|
+
* (SKYRAMP_FEATURE_POM_REUSE=1).
|
|
65
|
+
*
|
|
66
|
+
* When OFF (default), TypeScript/JavaScript + Playwright targets are treated
|
|
67
|
+
* like every other target: `skyramp_reuse_code` returns the SkyrampUtils
|
|
68
|
+
* consolidation prompt, and none of the POM machinery runs — no deterministic
|
|
69
|
+
* POM pre-scoping, no POM catalog / mapping-table workflow, no `verify: true`
|
|
70
|
+
* compliance gates, and consequently no `reuse` summary on the report (nothing
|
|
71
|
+
* records an outcome to re-derive).
|
|
72
|
+
*
|
|
73
|
+
* When ON, the test is refactored against the repo's existing page objects and
|
|
74
|
+
* the verification gates apply.
|
|
75
|
+
*/
|
|
76
|
+
export function isPomReuseEnabled() {
|
|
77
|
+
return process.env.SKYRAMP_FEATURE_POM_REUSE === "1";
|
|
78
|
+
}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
import { execFileSync } from "child_process";
|
|
27
27
|
import * as fs from "fs";
|
|
28
28
|
import * as path from "path";
|
|
29
|
-
import { isTestFile } from "../prompts/test-recommendation/scopeAssessment.js";
|
|
29
|
+
import { isTestFile, isI18nLocaleFile } from "../prompts/test-recommendation/scopeAssessment.js";
|
|
30
30
|
import { logger } from "./logger.js";
|
|
31
31
|
import { walkDir } from "./fileWalk.js";
|
|
32
32
|
import { buildPathSignatures } from "./pathSignatures.js";
|
|
@@ -166,6 +166,13 @@ function checkOneFile(repositoryPath, file) {
|
|
|
166
166
|
if (isRouteOrEntrypoint(file)) {
|
|
167
167
|
return { file, integrated: true, importers: [], reason: IntegrationReason.RouteOrEntrypoint };
|
|
168
168
|
}
|
|
169
|
+
// i18n/locale content is commonly loaded via a runtime-templated path (e.g.
|
|
170
|
+
// i18next-http-backend's `loadPath: '/locales/{{lng}}/{{ns}}.json'`) rather
|
|
171
|
+
// than a static quoted import — the signature grep below would never find
|
|
172
|
+
// that reference and would misreport a real, live locale file as dead code.
|
|
173
|
+
if (isI18nLocaleFile(file)) {
|
|
174
|
+
return { file, integrated: true, importers: [], reason: IntegrationReason.I18nLocaleContent };
|
|
175
|
+
}
|
|
169
176
|
// A missing changed file (e.g. deleted, or an unexpected diff shape) means
|
|
170
177
|
// the classification can't be trusted — fail open rather than risk wrongly
|
|
171
178
|
// suppressing UI test generation.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getGrpcMockResponseValidationError(responseData?: string): string | null;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const GRPC_STATUS_ERROR_NAMES = new Set([
|
|
2
|
+
"CANCELLED",
|
|
3
|
+
"UNKNOWN",
|
|
4
|
+
"INVALID_ARGUMENT",
|
|
5
|
+
"DEADLINE_EXCEEDED",
|
|
6
|
+
"NOT_FOUND",
|
|
7
|
+
"ALREADY_EXISTS",
|
|
8
|
+
"PERMISSION_DENIED",
|
|
9
|
+
"RESOURCE_EXHAUSTED",
|
|
10
|
+
"FAILED_PRECONDITION",
|
|
11
|
+
"ABORTED",
|
|
12
|
+
"OUT_OF_RANGE",
|
|
13
|
+
"UNIMPLEMENTED",
|
|
14
|
+
"INTERNAL",
|
|
15
|
+
"UNAVAILABLE",
|
|
16
|
+
"DATA_LOSS",
|
|
17
|
+
"UNAUTHENTICATED",
|
|
18
|
+
]);
|
|
19
|
+
export function getGrpcMockResponseValidationError(responseData) {
|
|
20
|
+
if (!responseData || responseData.trim().startsWith("@"))
|
|
21
|
+
return null;
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = JSON.parse(responseData);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const record = parsed;
|
|
33
|
+
const candidate = record.error;
|
|
34
|
+
if (typeof candidate !== "string")
|
|
35
|
+
return null;
|
|
36
|
+
const normalized = normalizeGrpcStatusName(candidate);
|
|
37
|
+
if (!GRPC_STATUS_ERROR_NAMES.has(normalized))
|
|
38
|
+
return null;
|
|
39
|
+
return `gRPC mock responseData cannot simulate gRPC status errors such as "${normalized}". Use grpcStatusCode/grpcStatusMessage for gRPC status errors, generate a successful protobuf-shaped response, use a real failing service, or record this scenario as blocked`;
|
|
40
|
+
}
|
|
41
|
+
function normalizeGrpcStatusName(value) {
|
|
42
|
+
return value
|
|
43
|
+
.replace(/^GRPC::Status(?:::|\.)?/i, "")
|
|
44
|
+
.replace(/^GRPC::/i, "")
|
|
45
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
46
|
+
.replace(/[\s.:-]+/g, "_")
|
|
47
|
+
.replace(/^_+|_+$/g, "")
|
|
48
|
+
.toUpperCase();
|
|
49
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { HttpMethod } from "../types/TestTypes.js";
|
|
2
|
+
export declare const REST_MOCK_HTTP_METHODS: HttpMethod[];
|
|
3
|
+
export declare function normalizeRestMockMethod(method?: string): string;
|
|
4
|
+
export declare function getRestMockMethodValidationError(method?: string): string | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HttpMethod } from "../types/TestTypes.js";
|
|
2
|
+
export const REST_MOCK_HTTP_METHODS = Object.values(HttpMethod);
|
|
3
|
+
export function normalizeRestMockMethod(method) {
|
|
4
|
+
return method ? method.trim().toUpperCase() : "";
|
|
5
|
+
}
|
|
6
|
+
export function getRestMockMethodValidationError(method) {
|
|
7
|
+
if (!method)
|
|
8
|
+
return null;
|
|
9
|
+
const normalized = normalizeRestMockMethod(method);
|
|
10
|
+
if (!normalized)
|
|
11
|
+
return null; // whitespace-only → treated as empty (valid)
|
|
12
|
+
if (REST_MOCK_HTTP_METHODS.includes(normalized))
|
|
13
|
+
return null;
|
|
14
|
+
return `REST mock method must be one of ${REST_MOCK_HTTP_METHODS.join(", ")} or empty string (got "${method}")`;
|
|
15
|
+
}
|
package/build/utils/logger.js
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock Compatibility Pre-flight Check
|
|
3
|
+
*
|
|
4
|
+
* Validates mock protocol combinations BEFORE deployment to surface
|
|
5
|
+
* known incompatibilities early rather than at test execution time.
|
|
6
|
+
*/
|
|
7
|
+
import { MockProtocol } from "../types/TestTypes.js";
|
|
8
|
+
export { MockProtocol };
|
|
9
|
+
/** Narrow view of a mock spec used only for protocol compatibility checking. */
|
|
10
|
+
export interface MockCompatibilitySpec {
|
|
11
|
+
protocol: MockProtocol;
|
|
12
|
+
endpointURL: string;
|
|
13
|
+
method?: string;
|
|
14
|
+
grpcServiceName?: string;
|
|
15
|
+
kafkaTopic?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CompatibilityWarning {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
suggestion: string;
|
|
21
|
+
affectedMocks: string[];
|
|
22
|
+
/** When true, the affected mocks cannot intercept traffic and must not be generated or deployed. */
|
|
23
|
+
blocking?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface CompatibilityResult {
|
|
26
|
+
compatible: boolean;
|
|
27
|
+
/** True when at least one warning is blocking — those mocks must be skipped entirely. */
|
|
28
|
+
hasBlockers: boolean;
|
|
29
|
+
warnings: CompatibilityWarning[];
|
|
30
|
+
}
|
|
31
|
+
export interface MockCompatibilityOptions {
|
|
32
|
+
/** Enable Docker local-dev checks that require mocks to intercept service DNS aliases. */
|
|
33
|
+
dockerLocalDev?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validates a set of mock specs for known protocol compatibility issues.
|
|
37
|
+
*
|
|
38
|
+
* Rules:
|
|
39
|
+
* - Any gRPC mock present → GRPC_PERSISTENT_CONN warning (DNS hijacking skips persistent conns)
|
|
40
|
+
* - Docker local-dev REST mock using loopback/host.docker.internal → REST_LOOPBACK_URL blocking warning
|
|
41
|
+
*
|
|
42
|
+
* REST mocks work correctly in Docker local-dev mode only when the mock URL uses
|
|
43
|
+
* the real Docker service hostname (e.g. "billing" from "http://billing:5001").
|
|
44
|
+
* The worker adds that hostname as a Docker network alias so DNS resolves to the mock server.
|
|
45
|
+
*
|
|
46
|
+
* `compatible` is false when any warning is blocking and the mock cannot intercept traffic.
|
|
47
|
+
* `hasBlockers` is true when at least one warning is blocking (mock must not be generated/deployed).
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateMockCompatibility(mocks: MockCompatibilitySpec[], options?: MockCompatibilityOptions): CompatibilityResult;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock Compatibility Pre-flight Check
|
|
3
|
+
*
|
|
4
|
+
* Validates mock protocol combinations BEFORE deployment to surface
|
|
5
|
+
* known incompatibilities early rather than at test execution time.
|
|
6
|
+
*/
|
|
7
|
+
import { MockProtocol } from "../types/TestTypes.js";
|
|
8
|
+
export { MockProtocol };
|
|
9
|
+
function parseRestHostname(endpointURL) {
|
|
10
|
+
try {
|
|
11
|
+
const hostname = new URL(endpointURL).hostname.toLowerCase();
|
|
12
|
+
return hostname.startsWith("[") && hostname.endsWith("]")
|
|
13
|
+
? hostname.slice(1, -1)
|
|
14
|
+
: hostname;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function isLoopbackRestEndpoint(endpointURL) {
|
|
21
|
+
const hostname = parseRestHostname(endpointURL);
|
|
22
|
+
return (hostname === "localhost" ||
|
|
23
|
+
hostname === "127.0.0.1" ||
|
|
24
|
+
hostname === "0.0.0.0" ||
|
|
25
|
+
hostname === "::1" ||
|
|
26
|
+
hostname === "host.docker.internal");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validates a set of mock specs for known protocol compatibility issues.
|
|
30
|
+
*
|
|
31
|
+
* Rules:
|
|
32
|
+
* - Any gRPC mock present → GRPC_PERSISTENT_CONN warning (DNS hijacking skips persistent conns)
|
|
33
|
+
* - Docker local-dev REST mock using loopback/host.docker.internal → REST_LOOPBACK_URL blocking warning
|
|
34
|
+
*
|
|
35
|
+
* REST mocks work correctly in Docker local-dev mode only when the mock URL uses
|
|
36
|
+
* the real Docker service hostname (e.g. "billing" from "http://billing:5001").
|
|
37
|
+
* The worker adds that hostname as a Docker network alias so DNS resolves to the mock server.
|
|
38
|
+
*
|
|
39
|
+
* `compatible` is false when any warning is blocking and the mock cannot intercept traffic.
|
|
40
|
+
* `hasBlockers` is true when at least one warning is blocking (mock must not be generated/deployed).
|
|
41
|
+
*/
|
|
42
|
+
export function validateMockCompatibility(mocks, options = {}) {
|
|
43
|
+
const warnings = [];
|
|
44
|
+
const restMocks = mocks.filter((m) => m.protocol === MockProtocol.Rest);
|
|
45
|
+
const grpcMocks = mocks.filter((m) => m.protocol === MockProtocol.Grpc);
|
|
46
|
+
const loopbackRestMocks = options.dockerLocalDev
|
|
47
|
+
? restMocks.filter((m) => isLoopbackRestEndpoint(m.endpointURL))
|
|
48
|
+
: [];
|
|
49
|
+
if (loopbackRestMocks.length > 0) {
|
|
50
|
+
warnings.push({
|
|
51
|
+
code: "REST_LOOPBACK_URL",
|
|
52
|
+
message: "REST mocks for Docker local-dev must use the original Docker service hostname. " +
|
|
53
|
+
"Loopback hosts such as localhost, 127.0.0.1, 0.0.0.0, ::1, or host.docker.internal " +
|
|
54
|
+
"do not give the Skyramp worker the downstream service DNS alias it needs to intercept traffic.",
|
|
55
|
+
suggestion: "Use the real Docker service origin in endpointURL, for example http://ams:4000 or " +
|
|
56
|
+
"http://billing:5001. Do not use localhost, host.docker.internal, or the Skyramp worker address " +
|
|
57
|
+
"for deployable REST mocks.",
|
|
58
|
+
affectedMocks: loopbackRestMocks.map((m) => m.endpointURL),
|
|
59
|
+
blocking: true,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// Rule: gRPC mocks use DNS hijacking that doesn't intercept persistent connections
|
|
63
|
+
if (grpcMocks.length > 0) {
|
|
64
|
+
warnings.push({
|
|
65
|
+
code: "GRPC_PERSISTENT_CONN",
|
|
66
|
+
message: "gRPC mocks use DNS hijacking which does not intercept persistent connections. " +
|
|
67
|
+
"If the service under test establishes a gRPC connection before mocks are applied, " +
|
|
68
|
+
"the existing connection will bypass the mock.",
|
|
69
|
+
suggestion: "Apply gRPC mocks before the service under test starts, or restart " +
|
|
70
|
+
"the service after applying mocks so it establishes a new connection through the mock DNS. " +
|
|
71
|
+
"For Docker local-dev, also verify the worker has the original downstream hostname alias " +
|
|
72
|
+
"from endpointURL (for example, partner-accounts for partner-accounts:50051).",
|
|
73
|
+
affectedMocks: grpcMocks.map((m) => m.grpcServiceName || m.endpointURL),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const hasBlockers = warnings.some((w) => w.blocking);
|
|
77
|
+
return {
|
|
78
|
+
compatible: !hasBlockers,
|
|
79
|
+
hasBlockers,
|
|
80
|
+
warnings,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -8,6 +8,13 @@ const POM_GLOBS = [
|
|
|
8
8
|
"**/*.page.{ts,js}",
|
|
9
9
|
"**/*Page.{ts,js}",
|
|
10
10
|
"**/pom/**/*.{ts,js}",
|
|
11
|
+
// Selector-owning helper libraries — the free-function convention (e.g. cal.com's
|
|
12
|
+
// playwright/lib/testUtils.ts exporting bookFirstEvent(page)). Bounded to helper
|
|
13
|
+
// modules inside test trees plus the explicit testUtils basename family: candidates
|
|
14
|
+
// are tiered by selector overlap downstream, so a non-owning match costs a scan,
|
|
15
|
+
// never a false substitution target.
|
|
16
|
+
"**/{test,tests,e2e,playwright}/**/{lib,utils,helpers,support}/**/*.{ts,js}",
|
|
17
|
+
"**/{testUtils,test-utils,testHelpers,test-helpers}.{ts,js}",
|
|
11
18
|
];
|
|
12
19
|
const EXCLUDED_BASENAME = /\.(spec|test|cy)\.(ts|js|tsx|jsx|mjs|cjs)$/;
|
|
13
20
|
const ALL_SOURCE_GLOBS = ["**/*.{ts,js,tsx,jsx,mjs,cjs}"];
|
|
@@ -33,7 +33,17 @@ function resolveAgainstPomSet(fromDir, ref, pomSet, aliasMap) {
|
|
|
33
33
|
else {
|
|
34
34
|
return undefined;
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
// Directory imports are how barrels are consumed (`from '../helpers/pages/admin'` where the
|
|
37
|
+
// on-disk target is `admin/index.ts`) — without the index candidates, barrel-bound page objects
|
|
38
|
+
// never bind at all and every call through them degrades to unverifiable.
|
|
39
|
+
for (const cand of [
|
|
40
|
+
base,
|
|
41
|
+
`${base}.ts`,
|
|
42
|
+
`${base}.js`,
|
|
43
|
+
base.replace(/\.js$/, ".ts"),
|
|
44
|
+
path.join(base, "index.ts"),
|
|
45
|
+
path.join(base, "index.js"),
|
|
46
|
+
]) {
|
|
37
47
|
if (pomSet.has(cand))
|
|
38
48
|
return cand;
|
|
39
49
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transitive closure of a file's relative import/re-export refs within the POM set, in BFS
|
|
3
|
+
* order starting from `start` itself. This is the VERIFY-side expansion: a member reached
|
|
4
|
+
* through a barrel-of-barrels (`admin/index.ts` → `export * from './members'` →
|
|
5
|
+
* `members/index.ts` → `members-list-page.ts`) must be searchable from the binding's file, or
|
|
6
|
+
* every such member false-negatives with no way to remap. Distinct from pom-scope's
|
|
7
|
+
* `expandImports`, which stays one-hop by design for scoping (expansion inherits the referrer's
|
|
8
|
+
* score; a transitive walk would over-credit distant files).
|
|
9
|
+
*/
|
|
10
|
+
export declare function expandReExportsTransitive(start: string, pomFiles: string[]): Promise<string[]>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFile } from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
const REF_RE = /(?:from\s+["']([^"']+)["']|require\(\s*["']([^"']+)["']\s*\))/g;
|
|
4
|
+
/** Real-world barrel chains run 2-3 deep (Ghost: admin/index → members/index → members-list-page);
|
|
5
|
+
* the cap only exists to bound a pathological re-export cycle that the visited-set already breaks. */
|
|
6
|
+
const MAX_DEPTH = 6;
|
|
7
|
+
/** Resolves a relative `ref` from `fromFile` to a member of `pomSet`, trying the bare path,
|
|
8
|
+
* .ts/.js extensions, and directory index files — barrels are routinely imported as
|
|
9
|
+
* `from './members'` where the target on disk is `members/index.ts`. */
|
|
10
|
+
function resolveRef(fromFile, ref, pomSet) {
|
|
11
|
+
const base = path.resolve(path.dirname(fromFile), ref);
|
|
12
|
+
const candidates = [
|
|
13
|
+
base,
|
|
14
|
+
`${base}.ts`,
|
|
15
|
+
`${base}.js`,
|
|
16
|
+
base.replace(/\.js$/, ".ts"),
|
|
17
|
+
path.join(base, "index.ts"),
|
|
18
|
+
path.join(base, "index.js"),
|
|
19
|
+
];
|
|
20
|
+
return candidates.find((c) => pomSet.has(c));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Transitive closure of a file's relative import/re-export refs within the POM set, in BFS
|
|
24
|
+
* order starting from `start` itself. This is the VERIFY-side expansion: a member reached
|
|
25
|
+
* through a barrel-of-barrels (`admin/index.ts` → `export * from './members'` →
|
|
26
|
+
* `members/index.ts` → `members-list-page.ts`) must be searchable from the binding's file, or
|
|
27
|
+
* every such member false-negatives with no way to remap. Distinct from pom-scope's
|
|
28
|
+
* `expandImports`, which stays one-hop by design for scoping (expansion inherits the referrer's
|
|
29
|
+
* score; a transitive walk would over-credit distant files).
|
|
30
|
+
*/
|
|
31
|
+
export async function expandReExportsTransitive(start, pomFiles) {
|
|
32
|
+
const pomSet = new Set(pomFiles);
|
|
33
|
+
const visited = new Set([start]);
|
|
34
|
+
const out = [start];
|
|
35
|
+
let frontier = [start];
|
|
36
|
+
for (let depth = 0; depth < MAX_DEPTH && frontier.length > 0; depth++) {
|
|
37
|
+
const next = [];
|
|
38
|
+
for (const file of frontier) {
|
|
39
|
+
let content;
|
|
40
|
+
try {
|
|
41
|
+
content = await readFile(file, "utf8");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
for (const m of content.matchAll(REF_RE)) {
|
|
47
|
+
const ref = m[1] ?? m[2];
|
|
48
|
+
if (!ref || !ref.startsWith("."))
|
|
49
|
+
continue;
|
|
50
|
+
const resolved = resolveRef(file, ref, pomSet);
|
|
51
|
+
if (resolved && !visited.has(resolved)) {
|
|
52
|
+
visited.add(resolved);
|
|
53
|
+
out.push(resolved);
|
|
54
|
+
next.push(resolved);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
frontier = next;
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type PomBinding } from "./bindings.js";
|
|
2
2
|
/** Checks `member` against member-DEFINITION shapes (not a bare `\bmember\b` token match, which
|
|
3
3
|
* would also "find" a local variable or parameter that merely shares the member's name) in the
|
|
4
|
-
* binding's class/source file and its
|
|
4
|
+
* binding's class/source file and the TRANSITIVE closure of its relative imports/re-exports that
|
|
5
|
+
* are themselves POM files. Transitivity matters: repos routinely bind through a barrel-of-barrels
|
|
6
|
+
* (Ghost's `admin/index.ts` → `./members` → `members-list-page.ts`), and stopping at one hop
|
|
7
|
+
* false-negatives every member of every class behind the second barrel. */
|
|
5
8
|
export declare function resolveMemberSource(binding: PomBinding, member: string, pomFiles: string[]): Promise<{
|
|
6
9
|
found: boolean;
|
|
7
10
|
searched: string[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readFile } from "fs/promises";
|
|
2
|
-
import { expandImports } from "../pom-scope/import-expansion.js";
|
|
3
2
|
import { stripCommentsAndStrings } from "../pom-scope/strip.js";
|
|
4
3
|
import { escapeRegExp } from "../regex.js";
|
|
5
4
|
import { primaryFile } from "./bindings.js";
|
|
5
|
+
import { expandReExportsTransitive } from "./re-exports.js";
|
|
6
6
|
// A definition site is either the very start of the file or just past a statement/block
|
|
7
7
|
// delimiter -- this catches indented multi-line source AND single-line/minified class bodies
|
|
8
8
|
// (`export class Foo { ctor(){...} bar(){...} }`) where a real method never lands at column 0.
|
|
@@ -26,12 +26,15 @@ function memberDefinitionRegexes(member) {
|
|
|
26
26
|
}
|
|
27
27
|
/** Checks `member` against member-DEFINITION shapes (not a bare `\bmember\b` token match, which
|
|
28
28
|
* would also "find" a local variable or parameter that merely shares the member's name) in the
|
|
29
|
-
* binding's class/source file and its
|
|
29
|
+
* binding's class/source file and the TRANSITIVE closure of its relative imports/re-exports that
|
|
30
|
+
* are themselves POM files. Transitivity matters: repos routinely bind through a barrel-of-barrels
|
|
31
|
+
* (Ghost's `admin/index.ts` → `./members` → `members-list-page.ts`), and stopping at one hop
|
|
32
|
+
* false-negatives every member of every class behind the second barrel. */
|
|
30
33
|
export async function resolveMemberSource(binding, member, pomFiles) {
|
|
31
|
-
const candidates = await
|
|
34
|
+
const candidates = await expandReExportsTransitive(primaryFile(binding), pomFiles);
|
|
32
35
|
const memberRes = memberDefinitionRegexes(member);
|
|
33
36
|
const searched = [];
|
|
34
|
-
for (const
|
|
37
|
+
for (const file of candidates) {
|
|
35
38
|
searched.push(file);
|
|
36
39
|
let content;
|
|
37
40
|
try {
|
|
@@ -10,5 +10,10 @@ export type VerifyResult = {
|
|
|
10
10
|
unverifiable: string[];
|
|
11
11
|
parseError?: string;
|
|
12
12
|
checkedCalls: number;
|
|
13
|
+
/** Every POM call found in the spec, verifiable or not. NOT checkedCalls +
|
|
14
|
+
* unverifiable.length: `unverifiable` also absorbs `unrecognized` bindings,
|
|
15
|
+
* which are not calls at all, so that sum overcounts. This is the count of
|
|
16
|
+
* POM members the delivered spec actually reuses. */
|
|
17
|
+
reusedCalls: number;
|
|
13
18
|
};
|
|
14
19
|
export declare function verifyReuse(testFile: string, language: string): Promise<VerifyResult>;
|
|
@@ -4,7 +4,7 @@ import * as path from "path";
|
|
|
4
4
|
import { promisify } from "util";
|
|
5
5
|
import { findRoot } from "../pom-scope/index.js";
|
|
6
6
|
import { globPomFiles, globAllSourceFiles } from "../pom-scope/pom-files.js";
|
|
7
|
-
import { extractPomBindings
|
|
7
|
+
import { extractPomBindings } from "./bindings.js";
|
|
8
8
|
import { extractPomCalls } from "./calls.js";
|
|
9
9
|
import { resolveMemberSource } from "./resolve.js";
|
|
10
10
|
import { stripComments, stripCommentsAndStrings } from "../pom-scope/strip.js";
|
|
@@ -34,7 +34,14 @@ async function listMembers(file) {
|
|
|
34
34
|
return [];
|
|
35
35
|
}
|
|
36
36
|
const members = new Set();
|
|
37
|
-
for (const re of [
|
|
37
|
+
for (const re of [
|
|
38
|
+
/^\s*(?:async\s+)?(\w+)\s*\(/gm,
|
|
39
|
+
/this\.(\w+)\s*=/g,
|
|
40
|
+
/get\s+(\w+)\s*\(/g,
|
|
41
|
+
// free-function helper modules: declarations and exported const arrows are members too
|
|
42
|
+
/\bfunction\s+(\w+)\s*\(/g,
|
|
43
|
+
/\bexport\s+const\s+(\w+)\s*=/g,
|
|
44
|
+
]) {
|
|
38
45
|
for (const m of content.matchAll(re)) {
|
|
39
46
|
const name = m[1];
|
|
40
47
|
if (name === "constructor" || NON_MEMBER_KEYWORDS.has(name))
|
|
@@ -139,7 +146,21 @@ export async function verifyReuse(testFile, language) {
|
|
|
139
146
|
const member = call.chain[0] ?? binding.name;
|
|
140
147
|
const { found, searched } = await resolveMemberSource(binding, member, pomFiles);
|
|
141
148
|
if (!found) {
|
|
142
|
-
|
|
149
|
+
// Candidates come from the whole searched closure, not just the binding's file: a
|
|
150
|
+
// binding through a barrel has a member-less primary file, and the members the agent
|
|
151
|
+
// could remap to live in the leaf classes the barrel re-exports.
|
|
152
|
+
const availableMembers = [...new Set((await Promise.all(searched.map(listMembers))).flat())];
|
|
153
|
+
if (availableMembers.length === 0) {
|
|
154
|
+
// "Not found, and I can enumerate nothing to remap to" is evidence about the
|
|
155
|
+
// VERIFIER's reach, not the member's existence. Emitting a violation here starts a
|
|
156
|
+
// remap/demote loop the agent cannot win (no candidates to remap to → forced demote
|
|
157
|
+
// of possibly-correct reuse). Degrade to unverifiable — the fail-open contract at
|
|
158
|
+
// the reachability level, matching resolve.ts's permissive stance on shapes.
|
|
159
|
+
unverifiable.push([call.binding, ...call.chain].join("."));
|
|
160
|
+
checkedCalls--;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
violations.push({ binding: call.binding, member, searched, availableMembers });
|
|
143
164
|
}
|
|
144
165
|
}
|
|
145
166
|
for (const u of unrecognized)
|
|
@@ -161,5 +182,6 @@ export async function verifyReuse(testFile, language) {
|
|
|
161
182
|
unverifiable,
|
|
162
183
|
parseError,
|
|
163
184
|
checkedCalls,
|
|
185
|
+
reusedCalls: calls.length,
|
|
164
186
|
};
|
|
165
187
|
}
|
package/build/utils/progress.js
CHANGED
|
@@ -10,11 +10,16 @@ export function makeProgressReporter(extra) {
|
|
|
10
10
|
return async (progress, total, message) => {
|
|
11
11
|
const progressToken = extra._meta?.progressToken;
|
|
12
12
|
if (progressToken !== undefined) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
try {
|
|
14
|
+
const notification = {
|
|
15
|
+
method: "notifications/progress",
|
|
16
|
+
params: { progressToken, progress, total, message },
|
|
17
|
+
};
|
|
18
|
+
await extra.sendNotification(notification);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Progress is best-effort; a disconnected client should not fail the tool.
|
|
22
|
+
}
|
|
18
23
|
}
|
|
19
24
|
};
|
|
20
25
|
}
|
|
@@ -334,7 +334,7 @@ export async function closeProxyTerminal() {
|
|
|
334
334
|
terminalPID,
|
|
335
335
|
});
|
|
336
336
|
}
|
|
337
|
-
catch (
|
|
337
|
+
catch (_killErr) {
|
|
338
338
|
// Process is already dead, which is what we want
|
|
339
339
|
logger.debug("Terminal process already terminated", {
|
|
340
340
|
terminalPID,
|
|
@@ -384,14 +384,14 @@ export async function closeProxyTerminal() {
|
|
|
384
384
|
terminalPID,
|
|
385
385
|
});
|
|
386
386
|
}
|
|
387
|
-
catch (
|
|
387
|
+
catch (_killErr) {
|
|
388
388
|
// Process is already dead, which is what we want
|
|
389
389
|
logger.debug("Terminal process already terminated", {
|
|
390
390
|
terminalPID,
|
|
391
391
|
});
|
|
392
392
|
}
|
|
393
393
|
}
|
|
394
|
-
catch (
|
|
394
|
+
catch (_pidErr) {
|
|
395
395
|
// Fallback to regular process kill
|
|
396
396
|
try {
|
|
397
397
|
process.kill(terminalPID, "SIGTERM");
|
|
@@ -59,15 +59,9 @@ export declare function isRouteLikeFile(filePath: string): boolean;
|
|
|
59
59
|
* route that existed in the base branch.
|
|
60
60
|
*/
|
|
61
61
|
export declare function selectRemovalCandidateFiles(diffData: BranchDiffData): string[];
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* `git show base:<file>`); files that throw are skipped. Returns every endpoint
|
|
66
|
-
* found in the base versions — callers pass the result to
|
|
67
|
-
* `classifyEndpointsByChangedFiles`, whose moved/still-present filter drops any
|
|
68
|
-
* endpoint that survives in the current catalog, leaving only genuine removals.
|
|
69
|
-
*/
|
|
70
|
-
export declare function recoverRemovedEndpointsFromBase(candidateFiles: string[], fetchBaseContent: (file: string) => Promise<string>): Promise<ScannedEndpoint[]>;
|
|
62
|
+
export declare function recoverRemovedEndpointsFromBase(candidateFiles: string[], fetchBaseContent: (file: string) => Promise<string>, repositoryPath?: string, baseBranch?: string): Promise<ScannedEndpoint[]>;
|
|
63
|
+
/** Strip git's `a/` / `b/` diff-path prefix and normalize separators. */
|
|
64
|
+
export declare function normalizeDiffPath(spec: string): string;
|
|
71
65
|
/**
|
|
72
66
|
* Parse a unified diff into the set of new-side (post-change) line numbers that
|
|
73
67
|
* were touched, keyed by normalized file path.
|