@skyramp/mcp 0.3.2-rc.pom-4 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/adapters/jestAdapter.d.ts +14 -0
- package/build/adapters/jestAdapter.js +113 -0
- package/build/adapters/mochaAdapter.d.ts +13 -0
- package/build/adapters/mochaAdapter.js +87 -0
- package/build/adapters/playwrightAdapter.d.ts +17 -0
- package/build/adapters/playwrightAdapter.js +182 -0
- package/build/adapters/pytestAdapter.d.ts +15 -0
- package/build/adapters/pytestAdapter.js +108 -0
- 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 +129 -8
- package/build/playwright/PlaywrightTraceService.d.ts +8 -0
- package/build/playwright/PlaywrightTraceService.js +1 -0
- 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 +17 -8
- 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 +70 -7
- package/build/prompts/sut-setup/modes/dockerComposePrompt.js +1 -1
- package/build/prompts/sut-setup/shared.js +19 -17
- package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +10 -1
- package/build/prompts/test-maintenance/drift-analysis-prompt.js +54 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +5 -2
- package/build/prompts/test-recommendation/scopeAssessment.js +78 -6
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
- package/build/prompts/testbot/testbot-prompts.d.ts +2 -17
- package/build/prompts/testbot/testbot-prompts.js +63 -60
- package/build/recommendation/planRanker.d.ts +15 -2
- package/build/recommendation/planRanker.js +76 -5
- package/build/resources/testbotResource.js +23 -5
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +15 -9
- package/build/services/TestExecutionService.js +56 -28
- package/build/services/TestGenerationService.d.ts +2 -2
- package/build/services/TestGenerationService.js +39 -21
- package/build/services/containerEnv.js +27 -1
- package/build/tool-phases.js +7 -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 +521 -0
- package/build/tools/runExistingTestsTool.d.ts +138 -0
- package/build/tools/runExistingTestsTool.js +644 -0
- package/build/tools/submitReportTool.js +40 -2
- package/build/tools/test-management/actionsTool.js +12 -2
- package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
- package/build/tools/test-management/analyzeChangesTool.js +63 -40
- package/build/tools/test-management/analyzeTestHealthTool.d.ts +11 -0
- package/build/tools/test-management/analyzeTestHealthTool.js +63 -1
- package/build/tools/test-management/registerTestPlanTool.js +55 -7
- package/build/tools/trace/startTraceCollectionTool.js +3 -3
- package/build/types/ExternalTestExecution.d.ts +67 -0
- package/build/types/ExternalTestExecution.js +8 -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/TestAnalysis.d.ts +7 -3
- package/build/types/TestExecution.d.ts +1 -0
- package/build/types/TestTypes.d.ts +25 -7
- package/build/types/TestTypes.js +25 -7
- package/build/types/TestbotPromptOptions.d.ts +35 -0
- package/build/types/TestbotPromptOptions.js +1 -0
- package/build/types/TestbotReport.d.ts +7 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/index.js +1 -0
- package/build/utils/AnalysisStateManager.d.ts +33 -0
- package/build/utils/AnalysisStateManager.js +36 -2
- 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/frontendSelectors.js +0 -1
- package/build/utils/gitStaging.d.ts +5 -0
- package/build/utils/gitStaging.js +1 -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-catalog.d.ts +23 -0
- package/build/utils/pom-catalog.js +30 -0
- package/build/utils/pom-scope/pom-files.d.ts +14 -0
- package/build/utils/pom-scope/pom-files.js +32 -6
- package/build/utils/pom-scope/testIdDiscovery.d.ts +40 -0
- package/build/utils/pom-scope/testIdDiscovery.js +104 -0
- package/build/utils/pom-verify/verify.d.ts +5 -0
- package/build/utils/pom-verify/verify.js +1 -0
- package/build/utils/progress.js +10 -5
- package/build/utils/proxy-terminal.js +3 -3
- package/build/utils/reportVerification.d.ts +7 -2
- package/build/utils/reportVerification.js +9 -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/frameworks.d.ts +11 -0
- package/build/workspace/frameworks.js +22 -0
- package/build/workspace/testSuites.d.ts +20 -0
- package/build/workspace/testSuites.js +17 -0
- package/build/workspace/workspace.d.ts +206 -24
- package/build/workspace/workspace.js +52 -2
- package/node_modules/playwright/ThirdPartyNotices.txt +319 -266
- package/node_modules/playwright/lib/dom-analyzer/blueprint.js +154 -27
- package/node_modules/playwright/lib/dom-analyzer/crawler.js +2 -2
- package/node_modules/playwright/lib/mcp/browser/tools/pageBlueprint.js +1 -1
- package/node_modules/playwright/lib/mcp/browser/tools/sitemap.js +6 -2
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +3 -2
- package/node_modules/playwright/lib/mcp/skyramp/resultCode.js +4 -3
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +15 -3
- package/node_modules/playwright/lib/mcp/skyramp/specImport.js +781 -0
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +14 -3
- package/node_modules/playwright/lib/mcp/test/resultCode.test.js +2 -1
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +1 -1
- package/node_modules/playwright/lib/mcp/test/skyRampExport.test.js +30 -0
- package/node_modules/playwright/lib/transform/babelBundleImpl.js +200 -199
- package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +3 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.package-lock.json +3 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/adapter/aws-lambda/handler.js +16 -25
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/adapter/bun/websocket.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/adapter/lambda-edge/handler.js +20 -4
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +16 -25
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/adapter/bun/websocket.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/adapter/lambda-edge/handler.js +20 -4
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/client.js +10 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/utils.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/css/common.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/css/index.js +9 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/base.js +8 -14
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/components.js +41 -21
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/context.js +131 -5
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/streaming.js +9 -7
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/compress/index.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cors/index.js +2 -5
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/index.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/language/language.js +10 -32
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/method-override/index.js +5 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/serve-static/index.js +2 -2
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/timing/timing.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/node.js +9 -0
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/body.js +12 -4
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/buffer.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/ipaddr.js +6 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/validator/validator.js +3 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/client.js +10 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/utils.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/css/common.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/css/index.js +9 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/base.js +15 -15
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/components.js +42 -22
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/context.js +129 -5
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/streaming.js +10 -8
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/bearer-auth/index.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cache/index.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/compress/index.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cors/index.js +2 -5
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/index.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/language/language.js +10 -32
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/method-override/index.js +5 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/serve-static/index.js +2 -2
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/timing/timing.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/node.js +9 -0
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/aws-lambda/handler.d.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/lambda-edge/handler.d.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/helper/websocket/index.d.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/base.d.ts +1 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/context.d.ts +39 -0
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/context-storage/index.d.ts +2 -2
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/language/language.d.ts +18 -0
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/body.d.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/types.d.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/body.js +12 -4
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/buffer.js +2 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/ipaddr.js +6 -1
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/validator/validator.js +3 -3
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/package.json +29 -22
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/package-lock.json +3 -3
- package/node_modules/playwright/node_modules/playwright-core/lib/generated/pollingRecorderSource.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +5 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/specReader.js +781 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderApp.js +25 -6
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/replayEngine.js +3 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/utils.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/htmlReport/index.html +253 -27
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-D0BjbCb7.js → codeMirrorModule-DtudTj_v.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-BpDwp16L.js +422 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-Bzd72-bG.js → codeMirrorModule-FNMuBzX1.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Co9upU5h.js +1035 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.DXNIQ_dx.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CIKB3XSv.js +5 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/generated/pollingRecorderSource.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +4 -0
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/specReader.ts +1028 -0
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderApp.ts +31 -8
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/replayEngine.ts +1 -0
- package/node_modules/playwright/node_modules/playwright-core/src/utils.ts +1 -0
- package/node_modules/playwright/package.json +1 -1
- package/package.json +12 -6
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/tsconfig.build.tsbuildinfo +0 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-lvTRGFx-.js +0 -193
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-DzxTioTK.js +0 -809
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.BGc30U3S.js +0 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.IaDrb29A.js +0 -5
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { VerifyResult } from "../../utils/pom-verify/index.js";
|
|
2
|
+
import { ReuseVerificationOutcome, type ReuseSkippedEntry } from "../../types/ReuseOutcome.js";
|
|
3
|
+
export { ReuseDeclinedBy, ReuseVerificationOutcome, type ReuseOutcome, type ReuseSkippedEntry, } from "../../types/ReuseOutcome.js";
|
|
4
|
+
/** A member the verifier flagged at some point in this run. NOT the same as "a
|
|
5
|
+
* member that was demoted": the workflow allows one remap attempt, so a flagged
|
|
6
|
+
* member may have been fixed rather than restored to raw inline. Only a
|
|
7
|
+
* `// kept inline:` marker proves a decline; this list can at most say which
|
|
8
|
+
* member a decline was about. */
|
|
9
|
+
export interface FlaggedMember {
|
|
10
|
+
pageObject: string;
|
|
11
|
+
member: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* What run state holds between the verify pass and the report step.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately NOT an extension of {@link ReuseOutcome}: it is a disjoint type
|
|
17
|
+
* holding only what cannot be recomputed from the delivered spec. Two reasons.
|
|
18
|
+
*
|
|
19
|
+
* Anything recomputable must not be stored, because storing it makes it stale the
|
|
20
|
+
* moment the spec changes — and it does change: the execution fix-up may restore
|
|
21
|
+
* `<testFile>.raw.bak` over the spec by plain `cp`, invisible to this tool. The
|
|
22
|
+
* counts and the decline list are therefore derived at report time (see
|
|
23
|
+
* `rederiveReuseOutcome`), never read back from here.
|
|
24
|
+
*
|
|
25
|
+
* And keeping the two types disjoint makes the report boundary opt-IN. When the
|
|
26
|
+
* record extended the wire type, every field added here shipped to the
|
|
27
|
+
* customer-facing report unless someone remembered to widen a destructure — a
|
|
28
|
+
* default that quietly asserts something, which is the same shape as the
|
|
29
|
+
* file-level attribution bug this module already had once. Now adding a field is
|
|
30
|
+
* a type error at the construction site instead.
|
|
31
|
+
*/
|
|
32
|
+
export interface ReuseRecord {
|
|
33
|
+
/** Tier-1 POM candidate FILES detection found. Not recoverable from the spec:
|
|
34
|
+
* it describes what was available to reuse, not what was reused. */
|
|
35
|
+
candidatesDetected?: number;
|
|
36
|
+
/** Needs `gateFired`, which only the verify call knows. */
|
|
37
|
+
verification?: ReuseVerificationOutcome;
|
|
38
|
+
/** Members the verifier flagged, accumulated across this run's verify passes —
|
|
39
|
+
* by the time verification PASSES the violations are gone, so a member that was
|
|
40
|
+
* substituted and then restored survives only as a `// kept inline:` comment,
|
|
41
|
+
* indistinguishable from one the mapper never promoted.
|
|
42
|
+
*
|
|
43
|
+
* Named for what it holds, not for what it is used to infer: FLAGGED is weaker
|
|
44
|
+
* than "demoted" (see {@link FlaggedMember}). Calling it `demoted` is what
|
|
45
|
+
* licensed attributing a whole file's declines to one member — do not rename it
|
|
46
|
+
* back. */
|
|
47
|
+
flagged?: FlaggedMember[];
|
|
48
|
+
/** Identity of the spec to re-derive from, and the language to parse it as. */
|
|
49
|
+
testFilePath?: string;
|
|
50
|
+
language?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Every well-formed `// kept inline: <basename> — <reason>` marker in a spec.
|
|
54
|
+
*
|
|
55
|
+
* Deliberately separate from `isKeptInlineDocumented` (verify-gates.ts) rather
|
|
56
|
+
* than replacing it: that one asks "is THIS known basename documented", so it can
|
|
57
|
+
* anchor on the basename and never has to guess where the name ends. Loosening the
|
|
58
|
+
* gate's predicate to share this regex would change when the zero-reuse escape
|
|
59
|
+
* hatch fires, which is not a side effect worth taking for deduplication — but see
|
|
60
|
+
* `findUnparsableKeptInline` for how the gap between them is kept visible.
|
|
61
|
+
*/
|
|
62
|
+
export declare function parseKeptInline(specContent: string): {
|
|
63
|
+
pageObject: string;
|
|
64
|
+
reason: string;
|
|
65
|
+
}[];
|
|
66
|
+
/**
|
|
67
|
+
* Lines that announce a kept-inline decline but that `parseKeptInline` cannot
|
|
68
|
+
* read — a missing reason clause, or a bare unspaced hyphen the zero-reuse gate's
|
|
69
|
+
* looser predicate would still accept.
|
|
70
|
+
*
|
|
71
|
+
* Such a marker satisfies the escape hatch (no gate failure, the agent proceeds)
|
|
72
|
+
* while the decline never reaches the report: silent signal loss, which is exactly
|
|
73
|
+
* the failure class this feature exists to close. Callers log these rather than
|
|
74
|
+
* dropping them quietly.
|
|
75
|
+
*/
|
|
76
|
+
export declare function findUnparsableKeptInline(specContent: string): string[];
|
|
77
|
+
/** Members the verifier flagged in one pass, keyed to the file a decline comment
|
|
78
|
+
* would name. */
|
|
79
|
+
export declare function flaggedFrom(r: VerifyResult): FlaggedMember[];
|
|
80
|
+
/** Union two flagged-member lists, deduplicated. */
|
|
81
|
+
export declare function mergeFlagged(prior: FlaggedMember[] | undefined, next: FlaggedMember[]): FlaggedMember[];
|
|
82
|
+
/**
|
|
83
|
+
* Build the `skipped` list for a spec: one entry per documented kept-inline
|
|
84
|
+
* marker — markers are the only ground truth for "this was actually left inline".
|
|
85
|
+
*
|
|
86
|
+
* Attribution is deliberately conservative, and only labels a decline when the
|
|
87
|
+
* correspondence is exact — one marker for that file and one flagged member for
|
|
88
|
+
* it:
|
|
89
|
+
*
|
|
90
|
+
* - No member of the file was ever flagged → the mapper never promoted it,
|
|
91
|
+
* `not-mapped`. Unambiguous: a flagged member implies it had been substituted.
|
|
92
|
+
* - Exactly one marker and one flagged member → that marker is that member,
|
|
93
|
+
* `demoted-by-verify`.
|
|
94
|
+
* - Anything else → the entry keeps its reason but carries no `member` and no
|
|
95
|
+
* `declinedBy`. Several markers on one file (S-01b's shape: a demote and an
|
|
96
|
+
* abstention on the same class) give no way to say which marker is which
|
|
97
|
+
* member, and a flagged member may have been remapped successfully rather than
|
|
98
|
+
* demoted, so a count mismatch is not even reliably a mixed-cause file.
|
|
99
|
+
*
|
|
100
|
+
* Guessing here is worse than omitting: a wrong member under a confident
|
|
101
|
+
* "demoted by verification" label sends a reviewer chasing a decline that never
|
|
102
|
+
* happened, which is the multi-hour log dig this field exists to end.
|
|
103
|
+
*/
|
|
104
|
+
export declare function buildSkipped(specContent: string, flagged: FlaggedMember[] | undefined): ReuseSkippedEntry[];
|
|
105
|
+
/** The verdict for a verify pass. A fired compliance gate is a failure regardless
|
|
106
|
+
* of the raw result; otherwise `r.ok` decides. `skipped-no-pom` is not reachable
|
|
107
|
+
* here — it is recorded on the prompt-generation call, where "no reusable POM
|
|
108
|
+
* layer detected" is determined. */
|
|
109
|
+
export declare function verificationFrom(gateFired: boolean, r: VerifyResult): ReuseVerificationOutcome;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { stripStrings } from "../../utils/pom-scope/strip.js";
|
|
3
|
+
import { ReuseDeclinedBy, ReuseVerificationOutcome, } from "../../types/ReuseOutcome.js";
|
|
4
|
+
/**
|
|
5
|
+
* Server-side derivation of a UI test's POM code-reuse outcome.
|
|
6
|
+
*
|
|
7
|
+
* The counts and verdicts here are all computed in-process by `skyramp_reuse_code`
|
|
8
|
+
* already — tier-1 detection by `selectScopedPoms`, the call counts and violations
|
|
9
|
+
* by `verifyReuse`, the demote/abstain record by the `// kept inline:` comments in
|
|
10
|
+
* the spec the tool just read. Routing them through the agent (read four integers
|
|
11
|
+
* out of tool text, hold them across the rest of the run, retype them into a later
|
|
12
|
+
* call) is still prose-mediated and still droppable, which is the failure this
|
|
13
|
+
* whole feature exists to fix. So they are persisted to run state and merged into
|
|
14
|
+
* the report server-side, exactly as `beforeStatus`/`afterStatus` are.
|
|
15
|
+
*
|
|
16
|
+
* The agent supplies nothing here.
|
|
17
|
+
*/
|
|
18
|
+
/** Separator between composite-key parts. `\0` cannot occur in a file name or a
|
|
19
|
+
* reason clause, so it cannot collide — written as an escape, never as a literal
|
|
20
|
+
* control byte, or git classifies this source file as binary. */
|
|
21
|
+
const KEY_SEP = "\0";
|
|
22
|
+
// The wire shape lives in types/ (and is re-exported from types/index.ts for
|
|
23
|
+
// consumers). Re-exported here so this module stays the one place to look when
|
|
24
|
+
// working on the derivation.
|
|
25
|
+
export { ReuseDeclinedBy, ReuseVerificationOutcome, } from "../../types/ReuseOutcome.js";
|
|
26
|
+
/** Matches a well-formed `// kept inline: <basename> <sep> <reason>` marker.
|
|
27
|
+
*
|
|
28
|
+
* The separator must be an em/en dash or a *spaced* hyphen. Discovery has no
|
|
29
|
+
* anchor to tell where the file name ends, and a bare hyphen is ambiguous with
|
|
30
|
+
* hyphens inside file names (`alert-destinations.page.ts-reason`), so requiring
|
|
31
|
+
* whitespace is what makes the split decidable. `findUnparsableKeptInline` below
|
|
32
|
+
* reports anything that looks like a marker but does not match, so a malformed
|
|
33
|
+
* one is never silently lost. */
|
|
34
|
+
const KEPT_INLINE_RE = /\/\/\s*kept inline:\s*(\S.*?)\s*(?:[—–]+|\s+-+\s+)\s*(\S.*?)\s*$/;
|
|
35
|
+
/** Lines that look like a kept-inline marker. Deliberately looser than
|
|
36
|
+
* KEPT_INLINE_RE so the difference between the two is detectable. */
|
|
37
|
+
const KEPT_INLINE_LOOSE_RE = /\/\/\s*kept inline:/;
|
|
38
|
+
/** Comment lines only — a marker quoted inside a string literal is not a real
|
|
39
|
+
* marker, the same reasoning as the zero-reuse gate's predicate. */
|
|
40
|
+
function commentLines(specContent) {
|
|
41
|
+
return stripStrings(specContent).split("\n");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Every well-formed `// kept inline: <basename> — <reason>` marker in a spec.
|
|
45
|
+
*
|
|
46
|
+
* Deliberately separate from `isKeptInlineDocumented` (verify-gates.ts) rather
|
|
47
|
+
* than replacing it: that one asks "is THIS known basename documented", so it can
|
|
48
|
+
* anchor on the basename and never has to guess where the name ends. Loosening the
|
|
49
|
+
* gate's predicate to share this regex would change when the zero-reuse escape
|
|
50
|
+
* hatch fires, which is not a side effect worth taking for deduplication — but see
|
|
51
|
+
* `findUnparsableKeptInline` for how the gap between them is kept visible.
|
|
52
|
+
*/
|
|
53
|
+
export function parseKeptInline(specContent) {
|
|
54
|
+
const out = [];
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
for (const line of commentLines(specContent)) {
|
|
57
|
+
const m = KEPT_INLINE_RE.exec(line);
|
|
58
|
+
if (!m)
|
|
59
|
+
continue;
|
|
60
|
+
const pageObject = path.basename(m[1].trim());
|
|
61
|
+
const reason = m[2].trim();
|
|
62
|
+
const key = `${pageObject}${KEY_SEP}${reason}`;
|
|
63
|
+
if (seen.has(key))
|
|
64
|
+
continue;
|
|
65
|
+
seen.add(key);
|
|
66
|
+
out.push({ pageObject, reason });
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Lines that announce a kept-inline decline but that `parseKeptInline` cannot
|
|
72
|
+
* read — a missing reason clause, or a bare unspaced hyphen the zero-reuse gate's
|
|
73
|
+
* looser predicate would still accept.
|
|
74
|
+
*
|
|
75
|
+
* Such a marker satisfies the escape hatch (no gate failure, the agent proceeds)
|
|
76
|
+
* while the decline never reaches the report: silent signal loss, which is exactly
|
|
77
|
+
* the failure class this feature exists to close. Callers log these rather than
|
|
78
|
+
* dropping them quietly.
|
|
79
|
+
*/
|
|
80
|
+
export function findUnparsableKeptInline(specContent) {
|
|
81
|
+
return commentLines(specContent)
|
|
82
|
+
.filter((line) => KEPT_INLINE_LOOSE_RE.test(line) && !KEPT_INLINE_RE.test(line))
|
|
83
|
+
.map((line) => line.trim());
|
|
84
|
+
}
|
|
85
|
+
/** Members the verifier flagged in one pass, keyed to the file a decline comment
|
|
86
|
+
* would name. */
|
|
87
|
+
export function flaggedFrom(r) {
|
|
88
|
+
const out = [];
|
|
89
|
+
for (const v of r.violations) {
|
|
90
|
+
const file = v.searched[0];
|
|
91
|
+
if (file)
|
|
92
|
+
out.push({ pageObject: path.basename(file), member: `${v.binding}.${v.member}` });
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
/** Union two flagged-member lists, deduplicated. */
|
|
97
|
+
export function mergeFlagged(prior, next) {
|
|
98
|
+
const byKey = new Map();
|
|
99
|
+
for (const d of [...(prior ?? []), ...next]) {
|
|
100
|
+
byKey.set(`${d.pageObject}${KEY_SEP}${d.member}`, d);
|
|
101
|
+
}
|
|
102
|
+
return [...byKey.values()];
|
|
103
|
+
}
|
|
104
|
+
function countByFile(items) {
|
|
105
|
+
const counts = new Map();
|
|
106
|
+
for (const i of items)
|
|
107
|
+
counts.set(i.pageObject, (counts.get(i.pageObject) ?? 0) + 1);
|
|
108
|
+
return counts;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Build the `skipped` list for a spec: one entry per documented kept-inline
|
|
112
|
+
* marker — markers are the only ground truth for "this was actually left inline".
|
|
113
|
+
*
|
|
114
|
+
* Attribution is deliberately conservative, and only labels a decline when the
|
|
115
|
+
* correspondence is exact — one marker for that file and one flagged member for
|
|
116
|
+
* it:
|
|
117
|
+
*
|
|
118
|
+
* - No member of the file was ever flagged → the mapper never promoted it,
|
|
119
|
+
* `not-mapped`. Unambiguous: a flagged member implies it had been substituted.
|
|
120
|
+
* - Exactly one marker and one flagged member → that marker is that member,
|
|
121
|
+
* `demoted-by-verify`.
|
|
122
|
+
* - Anything else → the entry keeps its reason but carries no `member` and no
|
|
123
|
+
* `declinedBy`. Several markers on one file (S-01b's shape: a demote and an
|
|
124
|
+
* abstention on the same class) give no way to say which marker is which
|
|
125
|
+
* member, and a flagged member may have been remapped successfully rather than
|
|
126
|
+
* demoted, so a count mismatch is not even reliably a mixed-cause file.
|
|
127
|
+
*
|
|
128
|
+
* Guessing here is worse than omitting: a wrong member under a confident
|
|
129
|
+
* "demoted by verification" label sends a reviewer chasing a decline that never
|
|
130
|
+
* happened, which is the multi-hour log dig this field exists to end.
|
|
131
|
+
*/
|
|
132
|
+
export function buildSkipped(specContent, flagged) {
|
|
133
|
+
const markers = parseKeptInline(specContent);
|
|
134
|
+
const markerCounts = countByFile(markers);
|
|
135
|
+
const flaggedByFile = new Map();
|
|
136
|
+
for (const f of flagged ?? []) {
|
|
137
|
+
const members = flaggedByFile.get(f.pageObject) ?? [];
|
|
138
|
+
members.push(f.member);
|
|
139
|
+
flaggedByFile.set(f.pageObject, members);
|
|
140
|
+
}
|
|
141
|
+
return markers.map(({ pageObject, reason }) => {
|
|
142
|
+
const members = flaggedByFile.get(pageObject) ?? [];
|
|
143
|
+
if (members.length === 0) {
|
|
144
|
+
return { pageObject, declinedBy: ReuseDeclinedBy.NotMapped, reason };
|
|
145
|
+
}
|
|
146
|
+
if (members.length === 1 && markerCounts.get(pageObject) === 1) {
|
|
147
|
+
return { pageObject, member: members[0], declinedBy: ReuseDeclinedBy.DemotedByVerify, reason };
|
|
148
|
+
}
|
|
149
|
+
return { pageObject, reason };
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** The verdict for a verify pass. A fired compliance gate is a failure regardless
|
|
153
|
+
* of the raw result; otherwise `r.ok` decides. `skipped-no-pom` is not reachable
|
|
154
|
+
* here — it is recorded on the prompt-generation call, where "no reusable POM
|
|
155
|
+
* layer detected" is determined. */
|
|
156
|
+
export function verificationFrom(gateFired, r) {
|
|
157
|
+
return !gateFired && r.ok ? ReuseVerificationOutcome.Passed : ReuseVerificationOutcome.Failed;
|
|
158
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type VerifyResult } from "../../utils/pom-verify/index.js";
|
|
2
|
+
import { type ReuseOutcome, type ReuseRecord } from "./reuse-outcome.js";
|
|
3
|
+
/** Record the tier-1 candidate count STEP 1 detected. */
|
|
4
|
+
export declare function recordCandidates(testFile: string, candidatesDetected: number, explicitStateFile?: string): Promise<void>;
|
|
5
|
+
/** The prompt-generation call found no reusable POM layer at all. No candidate
|
|
6
|
+
* count is recorded: "0 candidates" adds nothing to "no POM layer was found",
|
|
7
|
+
* and rendering both produces a redundant zero in the summary. */
|
|
8
|
+
export declare function recordNoPomLayer(testFile: string, explicitStateFile?: string): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Record what one verify pass established: the call counts, the verdict, and the
|
|
11
|
+
* declines read out of the spec the verifier just parsed.
|
|
12
|
+
*
|
|
13
|
+
* `flagged` accumulates across passes because a PASSED verdict has no violations
|
|
14
|
+
* left to inspect — a member that was substituted and then restored survives only
|
|
15
|
+
* as a `// kept inline:` comment, indistinguishable from one the mapper never
|
|
16
|
+
* promoted. Accumulating is what keeps that distinction recoverable at all; it does
|
|
17
|
+
* not by itself establish it, since a flagged member may have been remapped rather
|
|
18
|
+
* than restored (see buildSkipped for how narrowly it is trusted).
|
|
19
|
+
*/
|
|
20
|
+
export declare function recordVerifyOutcome(testFile: string, r: VerifyResult, gateFired: boolean, language: string, explicitStateFile?: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Re-derive a recorded outcome from the spec as it stands NOW, so the report
|
|
23
|
+
* describes the delivered artifact rather than the state at verify time.
|
|
24
|
+
*
|
|
25
|
+
* The two can differ: the execution fix-up may restore `<testFile>.raw.bak` over
|
|
26
|
+
* the spec after verification, reverting every substitution with a plain `cp` that
|
|
27
|
+
* this tool never sees. Trusting the recorded counts there would publish
|
|
28
|
+
* `callsReused: 5, verification: "passed"` for a spec containing no POM calls —
|
|
29
|
+
* a confident false claim, strictly worse than the silence this feature replaced.
|
|
30
|
+
* Re-deriving here rather than requiring a final `verify: true` pass is deliberate:
|
|
31
|
+
* the report step always runs, so the agent cannot skip it.
|
|
32
|
+
*
|
|
33
|
+
* `candidatesDetected` is kept as recorded — it counts POM FILES that detection
|
|
34
|
+
* found, which a restore does not change. Everything else comes from the file.
|
|
35
|
+
*
|
|
36
|
+
* `verification` is dropped when the delivered spec reuses nothing: a PASSED
|
|
37
|
+
* verdict describes a spec that no longer exists, and pairing it with a zero count
|
|
38
|
+
* reads as though the empty result had been blessed.
|
|
39
|
+
*
|
|
40
|
+
* Returns the recorded outcome minus internals when re-derivation is impossible
|
|
41
|
+
* (no path recorded — e.g. only the candidate count was ever written), and
|
|
42
|
+
* `undefined` when it fails outright. Failing closed matters: falling back to the
|
|
43
|
+
* recorded counts is exactly the false claim this exists to prevent.
|
|
44
|
+
*/
|
|
45
|
+
export declare function rederiveReuseOutcome(record: ReuseRecord): Promise<ReuseOutcome | undefined>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { logger } from "../../utils/logger.js";
|
|
4
|
+
import { resolveRunStatePath, StateManager, } from "../../utils/AnalysisStateManager.js";
|
|
5
|
+
import { verifyReuse } from "../../utils/pom-verify/index.js";
|
|
6
|
+
import { buildSkipped, findUnparsableKeptInline, flaggedFrom, mergeFlagged, verificationFrom, ReuseVerificationOutcome, } from "./reuse-outcome.js";
|
|
7
|
+
/**
|
|
8
|
+
* Persistence for the server-derived POM-reuse outcome, keyed by test-file
|
|
9
|
+
* basename (what `newTestsCreated[].fileName` carries, so
|
|
10
|
+
* `skyramp_submit_report` can match without path normalization).
|
|
11
|
+
*
|
|
12
|
+
* Every write is best-effort. Reuse observability must never be able to fail a
|
|
13
|
+
* refactor that otherwise succeeded, so a missing/unreadable/unwritable state
|
|
14
|
+
* file degrades to "no reuse summary in the report" — the same outcome as running
|
|
15
|
+
* outside a Testbot run, where there is no run state to record into.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Read-modify-write one spec's outcome. `patch` receives the entry recorded so
|
|
19
|
+
* far, so a caller that needs prior state (the verify pass, which accumulates
|
|
20
|
+
* flagged members) uses the same path as one that does not.
|
|
21
|
+
*
|
|
22
|
+
* Fields the patch omits are preserved: the prompt-generation call knows the
|
|
23
|
+
* candidate count, each verify pass knows the counts and verdict.
|
|
24
|
+
*/
|
|
25
|
+
async function updateReuseOutcome(testFile, patch, explicitStateFile) {
|
|
26
|
+
const stateFile = resolveRunStatePath(explicitStateFile);
|
|
27
|
+
if (!stateFile)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
const manager = StateManager.fromStatePath(stateFile);
|
|
31
|
+
const data = await manager.readData();
|
|
32
|
+
if (!data)
|
|
33
|
+
return;
|
|
34
|
+
const key = path.basename(testFile);
|
|
35
|
+
const existing = data.reuseOutcomes?.[key] ?? {};
|
|
36
|
+
await manager.writeData({
|
|
37
|
+
...data,
|
|
38
|
+
reuseOutcomes: { ...data.reuseOutcomes, [key]: { ...existing, ...patch(existing) } },
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
logger.warning("Could not record POM-reuse outcome — report will omit the reuse summary", {
|
|
43
|
+
testFile,
|
|
44
|
+
error: String(err),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Record the tier-1 candidate count STEP 1 detected. */
|
|
49
|
+
export async function recordCandidates(testFile, candidatesDetected, explicitStateFile) {
|
|
50
|
+
await updateReuseOutcome(testFile, () => ({ candidatesDetected }), explicitStateFile);
|
|
51
|
+
}
|
|
52
|
+
/** The prompt-generation call found no reusable POM layer at all. No candidate
|
|
53
|
+
* count is recorded: "0 candidates" adds nothing to "no POM layer was found",
|
|
54
|
+
* and rendering both produces a redundant zero in the summary. */
|
|
55
|
+
export async function recordNoPomLayer(testFile, explicitStateFile) {
|
|
56
|
+
await updateReuseOutcome(testFile, () => ({ verification: ReuseVerificationOutcome.SkippedNoPom }), explicitStateFile);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Record what one verify pass established: the call counts, the verdict, and the
|
|
60
|
+
* declines read out of the spec the verifier just parsed.
|
|
61
|
+
*
|
|
62
|
+
* `flagged` accumulates across passes because a PASSED verdict has no violations
|
|
63
|
+
* left to inspect — a member that was substituted and then restored survives only
|
|
64
|
+
* as a `// kept inline:` comment, indistinguishable from one the mapper never
|
|
65
|
+
* promoted. Accumulating is what keeps that distinction recoverable at all; it does
|
|
66
|
+
* not by itself establish it, since a flagged member may have been remapped rather
|
|
67
|
+
* than restored (see buildSkipped for how narrowly it is trusted).
|
|
68
|
+
*/
|
|
69
|
+
export async function recordVerifyOutcome(testFile, r, gateFired, language, explicitStateFile) {
|
|
70
|
+
if (!resolveRunStatePath(explicitStateFile))
|
|
71
|
+
return;
|
|
72
|
+
await updateReuseOutcome(testFile, (existing) => {
|
|
73
|
+
const flagged = mergeFlagged(existing.flagged, flaggedFrom(r));
|
|
74
|
+
return {
|
|
75
|
+
testFilePath: testFile,
|
|
76
|
+
language,
|
|
77
|
+
verification: verificationFrom(gateFired, r),
|
|
78
|
+
...(flagged.length > 0 ? { flagged } : {}),
|
|
79
|
+
};
|
|
80
|
+
}, explicitStateFile);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Re-derive a recorded outcome from the spec as it stands NOW, so the report
|
|
84
|
+
* describes the delivered artifact rather than the state at verify time.
|
|
85
|
+
*
|
|
86
|
+
* The two can differ: the execution fix-up may restore `<testFile>.raw.bak` over
|
|
87
|
+
* the spec after verification, reverting every substitution with a plain `cp` that
|
|
88
|
+
* this tool never sees. Trusting the recorded counts there would publish
|
|
89
|
+
* `callsReused: 5, verification: "passed"` for a spec containing no POM calls —
|
|
90
|
+
* a confident false claim, strictly worse than the silence this feature replaced.
|
|
91
|
+
* Re-deriving here rather than requiring a final `verify: true` pass is deliberate:
|
|
92
|
+
* the report step always runs, so the agent cannot skip it.
|
|
93
|
+
*
|
|
94
|
+
* `candidatesDetected` is kept as recorded — it counts POM FILES that detection
|
|
95
|
+
* found, which a restore does not change. Everything else comes from the file.
|
|
96
|
+
*
|
|
97
|
+
* `verification` is dropped when the delivered spec reuses nothing: a PASSED
|
|
98
|
+
* verdict describes a spec that no longer exists, and pairing it with a zero count
|
|
99
|
+
* reads as though the empty result had been blessed.
|
|
100
|
+
*
|
|
101
|
+
* Returns the recorded outcome minus internals when re-derivation is impossible
|
|
102
|
+
* (no path recorded — e.g. only the candidate count was ever written), and
|
|
103
|
+
* `undefined` when it fails outright. Failing closed matters: falling back to the
|
|
104
|
+
* recorded counts is exactly the false claim this exists to prevent.
|
|
105
|
+
*/
|
|
106
|
+
export async function rederiveReuseOutcome(record) {
|
|
107
|
+
const { candidatesDetected, verification, flagged, testFilePath, language } = record;
|
|
108
|
+
// No verify pass ran for this spec, so there are no counts to derive — only the
|
|
109
|
+
// detection-time facts, which no spec change can invalidate.
|
|
110
|
+
if (!testFilePath || !language)
|
|
111
|
+
return { candidatesDetected, verification };
|
|
112
|
+
try {
|
|
113
|
+
const r = await verifyReuse(testFilePath, language);
|
|
114
|
+
const specContent = await readFile(testFilePath, "utf8");
|
|
115
|
+
// Diagnose the file the report is actually built from. A marker the zero-reuse
|
|
116
|
+
// gate accepts but this cannot parse satisfies the escape hatch while its
|
|
117
|
+
// decline never reaches the report — silent signal loss is the failure class
|
|
118
|
+
// this feature exists to close.
|
|
119
|
+
const unparsable = findUnparsableKeptInline(specContent);
|
|
120
|
+
if (unparsable.length > 0) {
|
|
121
|
+
logger.warning("Malformed `// kept inline:` marker(s) in the delivered spec — these declines will be missing from the PR report. " +
|
|
122
|
+
"Use `// kept inline: <file basename> — <reason>` (em dash, or a hyphen with spaces around it).", { testFile: testFilePath, markers: unparsable });
|
|
123
|
+
}
|
|
124
|
+
const skipped = buildSkipped(specContent, flagged);
|
|
125
|
+
return {
|
|
126
|
+
candidatesDetected,
|
|
127
|
+
callsReused: r.reusedCalls,
|
|
128
|
+
callsVerified: r.checkedCalls,
|
|
129
|
+
// A PASSED verdict describes a spec that no longer exists once reuse is gone,
|
|
130
|
+
// and pairing it with a zero count reads as though the empty result had been
|
|
131
|
+
// blessed.
|
|
132
|
+
verification: r.reusedCalls > 0 ? verification : undefined,
|
|
133
|
+
skipped: skipped.length > 0 ? skipped : undefined,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
logger.warning("Could not re-derive the POM-reuse outcome from the delivered spec — omitting the reuse summary rather than reporting counts that may no longer hold", { testFile: testFilePath, error: String(err) });
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { ProgrammingLanguage, MockProtocol } from "../types/TestTypes.js";
|
|
3
|
+
/**
|
|
4
|
+
* skyramp_enrich_test_with_mocks
|
|
5
|
+
*
|
|
6
|
+
* Injects mock imports and apply_mock() calls into a generated test file.
|
|
7
|
+
* The mock files are generated by skyramp_mock_generation — this tool wires
|
|
8
|
+
* them into the test so the mocks are applied before the test runs.
|
|
9
|
+
*
|
|
10
|
+
* No data duplication — the test imports from the generated mock files.
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerEnrichTestWithMocksTool(server: McpServer): void;
|
|
13
|
+
declare function injectMockImports(original: string, testFile: string, scenarioName: string, mockFiles: string[], traceComments?: string[], language?: ProgrammingLanguage): string;
|
|
14
|
+
declare function isSupportedMockEnrichmentLanguage(language: ProgrammingLanguage | string): language is ProgrammingLanguage;
|
|
15
|
+
type MockEntry = {
|
|
16
|
+
serviceName: string;
|
|
17
|
+
moduleName: string;
|
|
18
|
+
relativePath: string;
|
|
19
|
+
importPath: string;
|
|
20
|
+
importLabel: string;
|
|
21
|
+
mockFile: string;
|
|
22
|
+
className: string;
|
|
23
|
+
classReference: string;
|
|
24
|
+
targetUrl?: string;
|
|
25
|
+
protocol: MockProtocol;
|
|
26
|
+
};
|
|
27
|
+
declare function buildMockImportBlock(testFile: string, scenarioName: string, mockFiles: string[], traceComments?: string[], language?: ProgrammingLanguage, mockEntries?: MockEntry[]): string;
|
|
28
|
+
export { injectMockImports, buildMockImportBlock, isSupportedMockEnrichmentLanguage };
|