@mknrt/autotests-overkill 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +117 -0
  2. package/assets/overkill-logo.svg +8 -0
  3. package/assets/overkill-small.svg +8 -0
  4. package/dist/connectors/index.d.ts +4 -0
  5. package/dist/connectors/index.js +4 -0
  6. package/dist/indexer/index.d.ts +4 -0
  7. package/dist/indexer/index.js +4 -0
  8. package/dist/mcp/index.d.ts +2 -0
  9. package/dist/mcp/index.js +2 -0
  10. package/dist/src/appContext.d.ts +21 -0
  11. package/dist/src/appContext.js +40 -0
  12. package/dist/src/cli/indexKnowledge.d.ts +1 -0
  13. package/dist/src/cli/indexKnowledge.js +11 -0
  14. package/dist/src/cli/main.d.ts +19 -0
  15. package/dist/src/cli/main.js +59 -0
  16. package/dist/src/cli/runAcceptance.d.ts +21 -0
  17. package/dist/src/cli/runAcceptance.js +131 -0
  18. package/dist/src/cli/runMcpServer.d.ts +1 -0
  19. package/dist/src/cli/runMcpServer.js +10 -0
  20. package/dist/src/cli/shared.d.ts +1 -0
  21. package/dist/src/cli/shared.js +7 -0
  22. package/dist/src/config/consumerConfig.d.ts +126 -0
  23. package/dist/src/config/consumerConfig.js +63 -0
  24. package/dist/src/connectors/autotests2Connector.d.ts +41 -0
  25. package/dist/src/connectors/autotests2Connector.js +94 -0
  26. package/dist/src/connectors/caseplatformConnector.d.ts +35 -0
  27. package/dist/src/connectors/caseplatformConnector.js +251 -0
  28. package/dist/src/connectors/ciArtifactsConnector.d.ts +23 -0
  29. package/dist/src/connectors/ciArtifactsConnector.js +14 -0
  30. package/dist/src/connectors/diffConnector.d.ts +1 -0
  31. package/dist/src/connectors/diffConnector.js +4 -0
  32. package/dist/src/connectors/filesystemConnector.d.ts +4 -0
  33. package/dist/src/connectors/filesystemConnector.js +15 -0
  34. package/dist/src/connectors/gitlabConnector.d.ts +14 -0
  35. package/dist/src/connectors/gitlabConnector.js +64 -0
  36. package/dist/src/connectors/reportPortalConnector.d.ts +14 -0
  37. package/dist/src/connectors/reportPortalConnector.js +84 -0
  38. package/dist/src/contracts/confidence.d.ts +8 -0
  39. package/dist/src/contracts/confidence.js +33 -0
  40. package/dist/src/contracts/errors.d.ts +6 -0
  41. package/dist/src/contracts/errors.js +18 -0
  42. package/dist/src/contracts/toolOutput.d.ts +113 -0
  43. package/dist/src/contracts/toolOutput.js +35 -0
  44. package/dist/src/domain/analyzeDiffImpact.d.ts +22 -0
  45. package/dist/src/domain/analyzeDiffImpact.js +52 -0
  46. package/dist/src/domain/analyzeTestGaps.d.ts +22 -0
  47. package/dist/src/domain/analyzeTestGaps.js +41 -0
  48. package/dist/src/domain/buildRerunScope.d.ts +23 -0
  49. package/dist/src/domain/buildRerunScope.js +17 -0
  50. package/dist/src/domain/buildSetupTeardownPlan.d.ts +23 -0
  51. package/dist/src/domain/buildSetupTeardownPlan.js +13 -0
  52. package/dist/src/domain/findExistingTestAssets.d.ts +22 -0
  53. package/dist/src/domain/findExistingTestAssets.js +50 -0
  54. package/dist/src/domain/findFrontendContract.d.ts +22 -0
  55. package/dist/src/domain/findFrontendContract.js +13 -0
  56. package/dist/src/domain/findFrontendRuntimeLogic.d.ts +22 -0
  57. package/dist/src/domain/findFrontendRuntimeLogic.js +28 -0
  58. package/dist/src/domain/findTestAreaContext.d.ts +23 -0
  59. package/dist/src/domain/findTestAreaContext.js +30 -0
  60. package/dist/src/domain/generateSpecBlueprint.d.ts +23 -0
  61. package/dist/src/domain/generateSpecBlueprint.js +213 -0
  62. package/dist/src/domain/mapFeatureToExistingCoverage.d.ts +22 -0
  63. package/dist/src/domain/mapFeatureToExistingCoverage.js +56 -0
  64. package/dist/src/domain/recommendSelectorStrategy.d.ts +22 -0
  65. package/dist/src/domain/recommendSelectorStrategy.js +13 -0
  66. package/dist/src/domain/shared.d.ts +5 -0
  67. package/dist/src/domain/shared.js +36 -0
  68. package/dist/src/domain/summarizeCiContext.d.ts +22 -0
  69. package/dist/src/domain/summarizeCiContext.js +35 -0
  70. package/dist/src/domain/triageFailedRun.d.ts +25 -0
  71. package/dist/src/domain/triageFailedRun.js +46 -0
  72. package/dist/src/index.d.ts +4 -0
  73. package/dist/src/index.js +4 -0
  74. package/dist/src/indexer/extractors/frontendContractExtractor.d.ts +17 -0
  75. package/dist/src/indexer/extractors/frontendContractExtractor.js +109 -0
  76. package/dist/src/indexer/extractors/frontendRuntimeExtractor.d.ts +14 -0
  77. package/dist/src/indexer/extractors/frontendRuntimeExtractor.js +110 -0
  78. package/dist/src/indexer/extractors/testAssetExtractor.d.ts +13 -0
  79. package/dist/src/indexer/extractors/testAssetExtractor.js +17 -0
  80. package/dist/src/indexer/refreshPipeline.d.ts +12 -0
  81. package/dist/src/indexer/refreshPipeline.js +156 -0
  82. package/dist/src/indexer/snapshotStore.d.ts +10 -0
  83. package/dist/src/indexer/snapshotStore.js +45 -0
  84. package/dist/src/knowledge/database.d.ts +3 -0
  85. package/dist/src/knowledge/database.js +8 -0
  86. package/dist/src/knowledge/migrations.d.ts +1 -0
  87. package/dist/src/knowledge/migrations.js +28 -0
  88. package/dist/src/knowledge/repositories.d.ts +28 -0
  89. package/dist/src/knowledge/repositories.js +78 -0
  90. package/dist/src/mcp/registerTools.d.ts +11 -0
  91. package/dist/src/mcp/registerTools.js +118 -0
  92. package/dist/src/mcp/server.d.ts +4 -0
  93. package/dist/src/mcp/server.js +29 -0
  94. package/dist/src/utils/fileUtils.d.ts +4 -0
  95. package/dist/src/utils/fileUtils.js +16 -0
  96. package/dist/src/utils/pathUtils.d.ts +7 -0
  97. package/dist/src/utils/pathUtils.js +59 -0
  98. package/dist/src/utils/textUtils.d.ts +3 -0
  99. package/dist/src/utils/textUtils.js +26 -0
  100. package/docs/architecture/overview.md +31 -0
  101. package/docs/consumer-integration.md +64 -0
  102. package/docs/operator-cookbook.md +39 -0
  103. package/docs/plugin-packaging.md +33 -0
  104. package/docs/superpowers/plans/2026-04-19-autotests-overkill-v1.md +600 -0
  105. package/docs/tool-catalog.md +34 -0
  106. package/overkill.config.example.json +16 -0
  107. package/package.json +73 -0
  108. package/skills/overkill-debug-failure/SKILL.md +13 -0
  109. package/skills/overkill-find-gaps/SKILL.md +13 -0
  110. package/skills/overkill-generate-setup/SKILL.md +12 -0
  111. package/skills/overkill-generate-test/SKILL.md +15 -0
  112. package/skills/overkill-impact-analysis/SKILL.md +12 -0
  113. package/skills/overkill-onboard/SKILL.md +16 -0
  114. package/skills/overkill-prompt-builder/SKILL.md +13 -0
  115. package/skills/overkill-reuse-project-patterns/SKILL.md +13 -0
  116. package/skills/overkill-review-test-draft/SKILL.md +10 -0
  117. package/templates/prompts/debug-failure.md +3 -0
  118. package/templates/prompts/find-gaps.md +3 -0
  119. package/templates/prompts/generate-test.md +3 -0
  120. package/templates/prompts/impact-analysis.md +3 -0
  121. package/templates/spec-blueprints/default.md +39 -0
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # Autotests Overkill
2
+
3
+ `Autotests Overkill` is a standalone AI-assisted testing platform for `autotests2`, `caseplatform-web`, and CI artifacts. It is designed for Codex-style work: inspect existing coverage, extract frontend contracts and runtime logic, generate draft specs, triage failures, and narrow rerun scope without silently mutating consumer repositories.
4
+
5
+ ## What v1.1 adds
6
+
7
+ - Legacy widget contract extraction for files such as `dateRangeInput_control.js` and `dateRangeInput_singleton.js`
8
+ - Stronger spec blueprints that reuse real `autotests2` setup, commands, helpers, and selector patterns
9
+ - Acceptance coverage for both modern and legacy widgets
10
+ - Knowledge-store-backed retrieval for asset search, area context, impact analysis, and blueprint support
11
+ - Optional ReportPortal and GitLab adapters with graceful artifacts-first fallback
12
+ - Codex plugin packaging via `.codex-plugin/plugin.json` and `.mcp.json`
13
+
14
+ ## Repository layout
15
+
16
+ - `src/` implementation code
17
+ - `mcp/` MCP entrypoint notes
18
+ - `skills/` Codex skills for end-to-end workflows
19
+ - `indexer/` indexing entrypoint notes
20
+ - `connectors/` connector notes
21
+ - `templates/` prompt and blueprint templates
22
+ - `docs/` operator and integration documentation
23
+ - `tests/` unit, integration, and acceptance checks
24
+
25
+ ## Install
26
+
27
+ Published npm package install:
28
+
29
+ 1. Run `npm install -D @mknrt/autotests-overkill`.
30
+ 2. Copy `node_modules/@mknrt/autotests-overkill/overkill.config.example.json` to `overkill.config.json`.
31
+ 3. Set `repos.autotests2`, `repos.caseplatformWeb`, and `ci.artifactsRoot`.
32
+ 4. Run `npx autotests-overkill index`.
33
+
34
+ Repository-local development:
35
+
36
+ 1. Run `npm install`.
37
+ 2. Copy `overkill.config.example.json` to `overkill.config.json`.
38
+ 3. Set `repos.autotests2`, `repos.caseplatformWeb`, and `ci.artifactsRoot`.
39
+ 4. Run `npm run build`.
40
+ 5. Run `npm run index`.
41
+
42
+ ## Daily workflow
43
+
44
+ 1. Refresh local knowledge with `npm run index`.
45
+ 2. Start the MCP server through the checked-in MCP manifest or by running `npx autotests-overkill mcp`.
46
+ 3. Use `find_frontend_contract`, `find_existing_test_assets`, and `generate_spec_blueprint` for a new feature draft.
47
+ 4. Use `summarize_ci_context`, `triage_failed_run`, and `analyze_diff_impact` for failure or change triage.
48
+ 5. Review generated output manually before editing `autotests2`.
49
+
50
+ CLI commands:
51
+
52
+ - `npx autotests-overkill index`
53
+ - `npx autotests-overkill mcp`
54
+ - `npx autotests-overkill acceptance coverage caption`
55
+ - `npx autotests-overkill acceptance blueprint dateRangeField`
56
+
57
+ ## Verification commands
58
+
59
+ - `npm run verify`
60
+ - `npm run mcp:smoke`
61
+ - `npm run acceptance:coverage`
62
+ - `npm run acceptance:coverage:legacy`
63
+ - `npm run acceptance:blueprint`
64
+ - `npm run acceptance:failure`
65
+ - `npm run acceptance:impact`
66
+
67
+ ## Consumer config
68
+
69
+ The platform reads `overkill.config.json` with these keys:
70
+
71
+ - `repos.autotests2`
72
+ - `repos.caseplatformWeb`
73
+ - `ci.artifactsRoot`
74
+ - `ci.reportPortal.endpoint`
75
+ - `ci.reportPortal.project`
76
+ - `ci.reportPortal.token`
77
+ - `ci.gitlab.baseUrl`
78
+ - `ci.gitlab.projectId`
79
+ - `ci.gitlab.token`
80
+ - `cacheDir`
81
+
82
+ The default path is local and artifacts-first. Missing ReportPortal or GitLab credentials do not break tools; the platform keeps using local stats, screenshots, videos, and captured API payloads.
83
+
84
+ ## MCP tools
85
+
86
+ - `find_existing_test_assets`
87
+ - `find_test_area_context`
88
+ - `find_frontend_contract`
89
+ - `find_frontend_runtime_logic`
90
+ - `map_feature_to_existing_coverage`
91
+ - `analyze_test_gaps`
92
+ - `generate_spec_blueprint`
93
+ - `recommend_selector_strategy`
94
+ - `build_setup_teardown_plan`
95
+ - `analyze_diff_impact`
96
+ - `triage_failed_run`
97
+ - `build_rerun_scope`
98
+ - `summarize_ci_context`
99
+
100
+ Every tool returns the same normalized shape:
101
+
102
+ - `summary`
103
+ - `evidence`
104
+ - `recommended_actions`
105
+ - `repo_paths`
106
+ - `confidence`
107
+ - `warnings`
108
+
109
+ ## Codex plugin packaging
110
+
111
+ This repository can be consumed either from a Git checkout or as a published npm package:
112
+
113
+ - `.codex-plugin/plugin.json` exposes the plugin metadata
114
+ - `.mcp.json` registers the local MCP server command for checkout-based usage
115
+ - `skills/` is auto-discovered as the bundled skill set
116
+
117
+ See [consumer-integration.md](/C:/gitrep/autotests-overkill/docs/consumer-integration.md), [operator-cookbook.md](/C:/gitrep/autotests-overkill/docs/operator-cookbook.md), and [plugin-packaging.md](/C:/gitrep/autotests-overkill/docs/plugin-packaging.md) for setup details.
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="none">
2
+ <rect width="256" height="256" rx="40" fill="#0F4C81"/>
3
+ <path d="M58 176 92 90l29 61 35-81" stroke="#F4F7FB" stroke-linecap="round" stroke-linejoin="round" stroke-width="18"/>
4
+ <circle cx="58" cy="176" r="12" fill="#FFD166"/>
5
+ <circle cx="92" cy="90" r="12" fill="#FFD166"/>
6
+ <circle cx="121" cy="151" r="12" fill="#FFD166"/>
7
+ <circle cx="156" cy="70" r="12" fill="#FFD166"/>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <rect width="64" height="64" rx="14" fill="#0F4C81"/>
3
+ <path d="M18 45 28 20l8 18 10-22" stroke="#F4F7FB" stroke-linecap="round" stroke-linejoin="round" stroke-width="5"/>
4
+ <circle cx="18" cy="45" r="4" fill="#FFD166"/>
5
+ <circle cx="28" cy="20" r="4" fill="#FFD166"/>
6
+ <circle cx="36" cy="38" r="4" fill="#FFD166"/>
7
+ <circle cx="46" cy="16" r="4" fill="#FFD166"/>
8
+ </svg>
@@ -0,0 +1,4 @@
1
+ export * from '../src/connectors/autotests2Connector.js';
2
+ export * from '../src/connectors/caseplatformConnector.js';
3
+ export * from '../src/connectors/ciArtifactsConnector.js';
4
+ export * from '../src/connectors/diffConnector.js';
@@ -0,0 +1,4 @@
1
+ export * from '../src/connectors/autotests2Connector.js';
2
+ export * from '../src/connectors/caseplatformConnector.js';
3
+ export * from '../src/connectors/ciArtifactsConnector.js';
4
+ export * from '../src/connectors/diffConnector.js';
@@ -0,0 +1,4 @@
1
+ export * from '../src/indexer/refreshPipeline.js';
2
+ export * from '../src/indexer/extractors/frontendContractExtractor.js';
3
+ export * from '../src/indexer/extractors/frontendRuntimeExtractor.js';
4
+ export * from '../src/indexer/extractors/testAssetExtractor.js';
@@ -0,0 +1,4 @@
1
+ export * from '../src/indexer/refreshPipeline.js';
2
+ export * from '../src/indexer/extractors/frontendContractExtractor.js';
3
+ export * from '../src/indexer/extractors/frontendRuntimeExtractor.js';
4
+ export * from '../src/indexer/extractors/testAssetExtractor.js';
@@ -0,0 +1,2 @@
1
+ export * from '../src/mcp/server.js';
2
+ export * from '../src/mcp/registerTools.js';
@@ -0,0 +1,2 @@
1
+ export * from '../src/mcp/server.js';
2
+ export * from '../src/mcp/registerTools.js';
@@ -0,0 +1,21 @@
1
+ import { Autotests2Connector } from './connectors/autotests2Connector.js';
2
+ import { CaseplatformConnector } from './connectors/caseplatformConnector.js';
3
+ import { CiArtifactsConnector } from './connectors/ciArtifactsConnector.js';
4
+ import { GitLabConnector } from './connectors/gitlabConnector.js';
5
+ import { ReportPortalConnector } from './connectors/reportPortalConnector.js';
6
+ import { type ConsumerConfig, type ConsumerConfigInput } from './config/consumerConfig.js';
7
+ import { createKnowledgeDatabase } from './knowledge/database.js';
8
+ export type AppContext = {
9
+ config: ConsumerConfig;
10
+ database: ReturnType<typeof createKnowledgeDatabase>;
11
+ autotests2: Autotests2Connector;
12
+ caseplatform: CaseplatformConnector;
13
+ ciArtifacts: CiArtifactsConnector;
14
+ gitlab: GitLabConnector;
15
+ reportPortal: ReportPortalConnector;
16
+ };
17
+ export declare function createAppContext(input?: {
18
+ config?: ConsumerConfig | ConsumerConfigInput;
19
+ }): Promise<AppContext>;
20
+ export declare function resolveRuntimeConfigPath(): string;
21
+ export declare function createRuntimeAppContext(): Promise<AppContext>;
@@ -0,0 +1,40 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { Autotests2Connector } from './connectors/autotests2Connector.js';
4
+ import { CaseplatformConnector } from './connectors/caseplatformConnector.js';
5
+ import { CiArtifactsConnector } from './connectors/ciArtifactsConnector.js';
6
+ import { GitLabConnector } from './connectors/gitlabConnector.js';
7
+ import { ReportPortalConnector } from './connectors/reportPortalConnector.js';
8
+ import { createDefaultConsumerConfig, loadConsumerConfig, parseConsumerConfig } from './config/consumerConfig.js';
9
+ import { createKnowledgeDatabase } from './knowledge/database.js';
10
+ import { ensureDirectory } from './utils/fileUtils.js';
11
+ export async function createAppContext(input) {
12
+ const config = input?.config
13
+ ? ('cacheDir' in input.config ? input.config : parseConsumerConfig(input.config))
14
+ : createDefaultConsumerConfig();
15
+ ensureDirectory(config.cacheDir);
16
+ const database = createKnowledgeDatabase(path.join(config.cacheDir, 'knowledge.db'));
17
+ return {
18
+ config,
19
+ database,
20
+ autotests2: new Autotests2Connector(config.repos.autotests2),
21
+ caseplatform: new CaseplatformConnector(config.repos.caseplatformWeb),
22
+ ciArtifacts: new CiArtifactsConnector(),
23
+ gitlab: new GitLabConnector(config.ci.gitlab),
24
+ reportPortal: new ReportPortalConnector(config.ci.reportPortal),
25
+ };
26
+ }
27
+ export function resolveRuntimeConfigPath() {
28
+ const explicitPath = process.env.OVERKILL_CONFIG_PATH;
29
+ if (explicitPath) {
30
+ return path.resolve(process.cwd(), explicitPath);
31
+ }
32
+ return path.resolve(process.cwd(), 'overkill.config.json');
33
+ }
34
+ export async function createRuntimeAppContext() {
35
+ const configPath = resolveRuntimeConfigPath();
36
+ const config = fs.existsSync(configPath)
37
+ ? loadConsumerConfig(configPath)
38
+ : createDefaultConsumerConfig();
39
+ return createAppContext({ config });
40
+ }
@@ -0,0 +1 @@
1
+ export declare function runIndexKnowledge(): Promise<void>;
@@ -0,0 +1,11 @@
1
+ import { createRuntimeAppContext } from '../appContext.js';
2
+ import { refreshKnowledge } from '../indexer/refreshPipeline.js';
3
+ import { isDirectExecution } from './shared.js';
4
+ export async function runIndexKnowledge() {
5
+ const context = await createRuntimeAppContext();
6
+ const result = await refreshKnowledge(context);
7
+ console.log(JSON.stringify(result, null, 2));
8
+ }
9
+ if (isDirectExecution(import.meta.url)) {
10
+ await runIndexKnowledge();
11
+ }
@@ -0,0 +1,19 @@
1
+ export type ParsedCliArgs = {
2
+ command: 'index';
3
+ args: string[];
4
+ } | {
5
+ command: 'mcp';
6
+ args: string[];
7
+ } | {
8
+ command: 'acceptance';
9
+ args: string[];
10
+ } | {
11
+ command: 'help';
12
+ args: [];
13
+ } | {
14
+ command: 'invalid';
15
+ args: string[];
16
+ };
17
+ export declare function parseCliArgs(argv: string[]): ParsedCliArgs;
18
+ export declare function formatCliHelp(): string;
19
+ export declare function runCli(argv?: string[]): Promise<void>;
@@ -0,0 +1,59 @@
1
+ import { runIndexKnowledge } from './indexKnowledge.js';
2
+ import { runAcceptanceCli } from './runAcceptance.js';
3
+ import { startMcpServer } from './runMcpServer.js';
4
+ import { isDirectExecution } from './shared.js';
5
+ export function parseCliArgs(argv) {
6
+ const [command, ...args] = argv;
7
+ if (!command || command === '--help' || command === '-h' || command === 'help') {
8
+ return { command: 'help', args: [] };
9
+ }
10
+ if (command === 'index') {
11
+ return { command, args };
12
+ }
13
+ if (command === 'mcp') {
14
+ return { command, args };
15
+ }
16
+ if (command === 'acceptance') {
17
+ return { command, args };
18
+ }
19
+ return { command: 'invalid', args: [command, ...args] };
20
+ }
21
+ export function formatCliHelp() {
22
+ return [
23
+ 'autotests-overkill <command>',
24
+ '',
25
+ 'Commands:',
26
+ ' index Refresh the local knowledge cache.',
27
+ ' mcp Start the MCP server.',
28
+ ' acceptance <mode> [args...] Run acceptance checks.',
29
+ '',
30
+ 'Examples:',
31
+ ' npx @mknrt/autotests-overkill index',
32
+ ' npx @mknrt/autotests-overkill mcp',
33
+ ' npx @mknrt/autotests-overkill acceptance coverage caption',
34
+ ].join('\n');
35
+ }
36
+ export async function runCli(argv = process.argv.slice(2)) {
37
+ const parsed = parseCliArgs(argv);
38
+ if (parsed.command === 'help') {
39
+ console.log(formatCliHelp());
40
+ return;
41
+ }
42
+ if (parsed.command === 'invalid') {
43
+ console.error(`Unknown command '${parsed.args[0]}'.\n\n${formatCliHelp()}`);
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ if (parsed.command === 'index') {
48
+ await runIndexKnowledge();
49
+ return;
50
+ }
51
+ if (parsed.command === 'mcp') {
52
+ await startMcpServer();
53
+ return;
54
+ }
55
+ await runAcceptanceCli(parsed.args);
56
+ }
57
+ if (isDirectExecution(import.meta.url)) {
58
+ await runCli();
59
+ }
@@ -0,0 +1,21 @@
1
+ import { type AppContext } from '../appContext.js';
2
+ import type { NormalizedToolOutput } from '../contracts/toolOutput.js';
3
+ export type AcceptanceMode = 'coverage' | 'failure' | 'impact' | 'blueprint';
4
+ export type AcceptanceCheck = {
5
+ name: string;
6
+ passed: boolean;
7
+ detail: string;
8
+ };
9
+ export type AcceptanceReport = {
10
+ mode: AcceptanceMode;
11
+ target: string;
12
+ checks: AcceptanceCheck[];
13
+ output: Record<string, unknown>;
14
+ };
15
+ export declare function evaluateAcceptanceMode(mode: AcceptanceMode, args: string[], context: AppContext): Promise<AcceptanceReport>;
16
+ export declare function evaluateCoverageAcceptance(contract: NormalizedToolOutput, gaps: NormalizedToolOutput, widget: string): AcceptanceCheck[];
17
+ export declare function evaluateFailureAcceptance(triage: NormalizedToolOutput): AcceptanceCheck[];
18
+ export declare function evaluateImpactAcceptance(impact: NormalizedToolOutput, changedFile: string): AcceptanceCheck[];
19
+ export declare function evaluateBlueprintAcceptance(blueprint: NormalizedToolOutput, feature: string): AcceptanceCheck[];
20
+ export declare function assertPassingChecks(report: AcceptanceReport): void;
21
+ export declare function runAcceptanceCli(argv?: string[]): Promise<void>;
@@ -0,0 +1,131 @@
1
+ import { createRuntimeAppContext } from '../appContext.js';
2
+ import { analyzeDiffImpact } from '../domain/analyzeDiffImpact.js';
3
+ import { analyzeTestGaps } from '../domain/analyzeTestGaps.js';
4
+ import { findFrontendContract } from '../domain/findFrontendContract.js';
5
+ import { generateSpecBlueprint } from '../domain/generateSpecBlueprint.js';
6
+ import { triageFailedRun } from '../domain/triageFailedRun.js';
7
+ import { isDirectExecution } from './shared.js';
8
+ export async function evaluateAcceptanceMode(mode, args, context) {
9
+ if (mode === 'coverage') {
10
+ const widget = args[0] ?? 'caption';
11
+ const [contract, gaps] = await Promise.all([
12
+ findFrontendContract({ widget }, context),
13
+ analyzeTestGaps({ widget }, context),
14
+ ]);
15
+ return {
16
+ mode,
17
+ target: widget,
18
+ checks: evaluateCoverageAcceptance(contract, gaps, widget),
19
+ output: { contract, gaps },
20
+ };
21
+ }
22
+ if (mode === 'failure') {
23
+ const triage = await triageFailedRun({
24
+ statsFile: `${context.config.repos.autotests2}/cypress/reports/test-stats.json`,
25
+ screenshotsRoot: `${context.config.repos.autotests2}/cypress/screenshots`,
26
+ videosRoot: `${context.config.repos.autotests2}/cypress/videos`,
27
+ apiCaptureRoot: `${context.config.repos.autotests2}/cypress/reports/api-capture`,
28
+ }, context);
29
+ return {
30
+ mode,
31
+ target: 'latest-failure-artifacts',
32
+ checks: evaluateFailureAcceptance(triage),
33
+ output: { triage },
34
+ };
35
+ }
36
+ if (mode === 'impact') {
37
+ const changedFile = args[0] ?? 'C:/gitrep/caseplatform-web/vcm/jqVCM/widget/caption/CaptionSingleton.ts';
38
+ const impact = await analyzeDiffImpact({ changedFiles: [changedFile] }, context);
39
+ return {
40
+ mode,
41
+ target: changedFile,
42
+ checks: evaluateImpactAcceptance(impact, changedFile),
43
+ output: { impact },
44
+ };
45
+ }
46
+ const feature = args[0] ?? 'caption';
47
+ const area = args[1];
48
+ const blueprint = await generateSpecBlueprint({ feature, area }, context);
49
+ return {
50
+ mode,
51
+ target: feature,
52
+ checks: evaluateBlueprintAcceptance(blueprint, feature),
53
+ output: { blueprint },
54
+ };
55
+ }
56
+ export function evaluateCoverageAcceptance(contract, gaps, widget) {
57
+ const hasNonEmptyContract = !/0 properties, 0 events, and 0 methods/.test(contract.summary);
58
+ return [
59
+ check('contract evidence', contract.evidence.length > 0, `Frontend contract for '${widget}' must contain evidence-backed files/snippets.`, `Collected ${contract.evidence.length} contract evidence item(s).`),
60
+ check('contract usefulness', hasNonEmptyContract, `Frontend contract for '${widget}' is empty, so coverage acceptance must fail instead of silently passing.`, contract.summary),
61
+ check('gap evidence', gaps.evidence.length > 0, `Gap analysis for '${widget}' must contain evidence and likely gap signals.`, `Collected ${gaps.evidence.length} gap evidence item(s).`),
62
+ ];
63
+ }
64
+ export function evaluateFailureAcceptance(triage) {
65
+ const hasStats = triage.evidence.some((item) => item.label === 'stats report');
66
+ const hasArtifacts = triage.evidence.some((item) => /failure screenshot|failure video|failed spec/.test(item.label));
67
+ return [
68
+ check('failure evidence', triage.evidence.length > 0, 'Failure acceptance requires evidence-backed triage output.', `Collected ${triage.evidence.length} evidence item(s).`),
69
+ check('stats report', hasStats, 'Failure acceptance requires the stats report evidence entry.', 'Stats report evidence is present.'),
70
+ check('artifact context', hasArtifacts, 'Failure acceptance requires at least one screenshot, video, or failed-spec evidence item.', 'Artifact context is present in the triage output.'),
71
+ ];
72
+ }
73
+ export function evaluateImpactAcceptance(impact, changedFile) {
74
+ const impactedSpecs = impact.evidence.filter((item) => item.label === 'impacted spec');
75
+ return [
76
+ check('impacted specs', impactedSpecs.length > 0, `Impact acceptance for '${changedFile}' must not pass when no impacted specs are found.`, `Mapped ${impactedSpecs.length} impacted spec(s).`),
77
+ check('spec repo paths', impact.repo_paths.some((repoPath) => repoPath.endsWith('.cy.js')), `Impact acceptance for '${changedFile}' must include Cypress spec paths, not just the changed file.`, `Spec paths: ${impact.repo_paths.filter((repoPath) => repoPath.endsWith('.cy.js')).length}`),
78
+ ];
79
+ }
80
+ export function evaluateBlueprintAcceptance(blueprint, feature) {
81
+ const draft = blueprint.evidence.find((item) => item.label === 'blueprint')?.snippet ?? '';
82
+ const hasReferenceSpecs = blueprint.evidence.some((item) => item.label === 'reference spec');
83
+ const hasImportTarget = /support\/base(?:Conf)?/.test(draft);
84
+ const hasSetupShape = draft.includes('before(() => {') && draft.includes('beforeEach(() => {');
85
+ const hasSelectorGuidance = blueprint.recommended_actions.some((action) => action.toLowerCase().includes('selector'));
86
+ const hasReuseGuidance = blueprint.recommended_actions.some((action) => action.toLowerCase().includes('reuse') || action.toLowerCase().includes('borrow'));
87
+ return [
88
+ check('reference specs', hasReferenceSpecs, `Blueprint acceptance for '${feature}' requires real reference specs from autotests2.`, 'Reference specs are attached as evidence.'),
89
+ check('non-placeholder import', draft.length > 0 && !draft.includes("from '...'") && hasImportTarget, `Blueprint acceptance for '${feature}' requires a real import target instead of demo-level placeholders.`, 'Blueprint contains a concrete support import target.'),
90
+ check('setup guidance', hasSetupShape && draft.includes('cy.getWidget('), `Blueprint acceptance for '${feature}' requires usable before/beforeEach structure and widget access guidance.`, 'Blueprint contains before/beforeEach hooks and widget access patterns.'),
91
+ check('selector and reuse guidance', hasSelectorGuidance && hasReuseGuidance, `Blueprint acceptance for '${feature}' requires explicit selector and reuse guidance.`, 'Recommended actions include selector and reuse guidance.'),
92
+ ];
93
+ }
94
+ export function assertPassingChecks(report) {
95
+ const failedChecks = report.checks.filter((checkResult) => !checkResult.passed);
96
+ if (failedChecks.length === 0) {
97
+ return;
98
+ }
99
+ const details = failedChecks.map((checkResult) => `${checkResult.name}: ${checkResult.detail}`).join(' | ');
100
+ throw new Error(`${report.mode} acceptance failed for '${report.target}'. ${details}`);
101
+ }
102
+ function check(name, passed, failedDetail, passedDetail) {
103
+ return {
104
+ name,
105
+ passed,
106
+ detail: passed ? passedDetail : failedDetail,
107
+ };
108
+ }
109
+ export async function runAcceptanceCli(argv = process.argv.slice(2)) {
110
+ const [rawMode, ...args] = argv;
111
+ if (!isAcceptanceMode(rawMode)) {
112
+ console.error(`Unknown acceptance mode '${rawMode}'. Use coverage, failure, impact, or blueprint.`);
113
+ process.exit(1);
114
+ }
115
+ const context = await createRuntimeAppContext();
116
+ const report = await evaluateAcceptanceMode(rawMode, args, context);
117
+ try {
118
+ assertPassingChecks(report);
119
+ console.log(JSON.stringify(report, null, 2));
120
+ }
121
+ catch (error) {
122
+ console.error(JSON.stringify(report, null, 2));
123
+ throw error;
124
+ }
125
+ }
126
+ function isAcceptanceMode(value) {
127
+ return value === 'coverage' || value === 'failure' || value === 'impact' || value === 'blueprint';
128
+ }
129
+ if (isDirectExecution(import.meta.url)) {
130
+ await runAcceptanceCli();
131
+ }
@@ -0,0 +1 @@
1
+ export declare function startMcpServer(): Promise<void>;
@@ -0,0 +1,10 @@
1
+ import { createRuntimeAppContext } from '../appContext.js';
2
+ import { runMcpServer } from '../mcp/server.js';
3
+ import { isDirectExecution } from './shared.js';
4
+ export async function startMcpServer() {
5
+ const context = await createRuntimeAppContext();
6
+ await runMcpServer(context);
7
+ }
8
+ if (isDirectExecution(import.meta.url)) {
9
+ await startMcpServer();
10
+ }
@@ -0,0 +1 @@
1
+ export declare function isDirectExecution(moduleUrl: string): boolean;
@@ -0,0 +1,7 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ export function isDirectExecution(moduleUrl) {
4
+ const currentFile = fileURLToPath(moduleUrl);
5
+ const entryFile = process.argv[1] ? path.resolve(process.argv[1]) : '';
6
+ return currentFile === entryFile;
7
+ }
@@ -0,0 +1,126 @@
1
+ import { z } from 'zod';
2
+ export declare const consumerConfigSchema: z.ZodObject<{
3
+ repos: z.ZodObject<{
4
+ autotests2: z.ZodString;
5
+ caseplatformWeb: z.ZodString;
6
+ }, "strict", z.ZodTypeAny, {
7
+ autotests2: string;
8
+ caseplatformWeb: string;
9
+ }, {
10
+ autotests2: string;
11
+ caseplatformWeb: string;
12
+ }>;
13
+ ci: z.ZodObject<{
14
+ artifactsRoot: z.ZodString;
15
+ reportPortal: z.ZodOptional<z.ZodObject<{
16
+ endpoint: z.ZodString;
17
+ project: z.ZodOptional<z.ZodString>;
18
+ token: z.ZodOptional<z.ZodString>;
19
+ }, "strict", z.ZodTypeAny, {
20
+ endpoint: string;
21
+ project?: string | undefined;
22
+ token?: string | undefined;
23
+ }, {
24
+ endpoint: string;
25
+ project?: string | undefined;
26
+ token?: string | undefined;
27
+ }>>;
28
+ gitlab: z.ZodOptional<z.ZodObject<{
29
+ baseUrl: z.ZodString;
30
+ projectId: z.ZodOptional<z.ZodString>;
31
+ token: z.ZodOptional<z.ZodString>;
32
+ }, "strict", z.ZodTypeAny, {
33
+ baseUrl: string;
34
+ token?: string | undefined;
35
+ projectId?: string | undefined;
36
+ }, {
37
+ baseUrl: string;
38
+ token?: string | undefined;
39
+ projectId?: string | undefined;
40
+ }>>;
41
+ }, "strict", z.ZodTypeAny, {
42
+ artifactsRoot: string;
43
+ reportPortal?: {
44
+ endpoint: string;
45
+ project?: string | undefined;
46
+ token?: string | undefined;
47
+ } | undefined;
48
+ gitlab?: {
49
+ baseUrl: string;
50
+ token?: string | undefined;
51
+ projectId?: string | undefined;
52
+ } | undefined;
53
+ }, {
54
+ artifactsRoot: string;
55
+ reportPortal?: {
56
+ endpoint: string;
57
+ project?: string | undefined;
58
+ token?: string | undefined;
59
+ } | undefined;
60
+ gitlab?: {
61
+ baseUrl: string;
62
+ token?: string | undefined;
63
+ projectId?: string | undefined;
64
+ } | undefined;
65
+ }>;
66
+ cacheDir: z.ZodOptional<z.ZodString>;
67
+ projectHints: z.ZodOptional<z.ZodObject<{
68
+ defaultWidget: z.ZodOptional<z.ZodString>;
69
+ }, "strict", z.ZodTypeAny, {
70
+ defaultWidget?: string | undefined;
71
+ }, {
72
+ defaultWidget?: string | undefined;
73
+ }>>;
74
+ }, "strict", z.ZodTypeAny, {
75
+ repos: {
76
+ autotests2: string;
77
+ caseplatformWeb: string;
78
+ };
79
+ ci: {
80
+ artifactsRoot: string;
81
+ reportPortal?: {
82
+ endpoint: string;
83
+ project?: string | undefined;
84
+ token?: string | undefined;
85
+ } | undefined;
86
+ gitlab?: {
87
+ baseUrl: string;
88
+ token?: string | undefined;
89
+ projectId?: string | undefined;
90
+ } | undefined;
91
+ };
92
+ cacheDir?: string | undefined;
93
+ projectHints?: {
94
+ defaultWidget?: string | undefined;
95
+ } | undefined;
96
+ }, {
97
+ repos: {
98
+ autotests2: string;
99
+ caseplatformWeb: string;
100
+ };
101
+ ci: {
102
+ artifactsRoot: string;
103
+ reportPortal?: {
104
+ endpoint: string;
105
+ project?: string | undefined;
106
+ token?: string | undefined;
107
+ } | undefined;
108
+ gitlab?: {
109
+ baseUrl: string;
110
+ token?: string | undefined;
111
+ projectId?: string | undefined;
112
+ } | undefined;
113
+ };
114
+ cacheDir?: string | undefined;
115
+ projectHints?: {
116
+ defaultWidget?: string | undefined;
117
+ } | undefined;
118
+ }>;
119
+ export type ConsumerConfigInput = z.input<typeof consumerConfigSchema>;
120
+ export type ConsumerConfig = z.output<typeof consumerConfigSchema> & {
121
+ cacheDir: string;
122
+ };
123
+ export declare function resolveRepoPath(value: string, baseDir?: string): string;
124
+ export declare function parseConsumerConfig(input: ConsumerConfigInput, baseDir?: string): ConsumerConfig;
125
+ export declare function loadConsumerConfig(configPath?: string): ConsumerConfig;
126
+ export declare function createDefaultConsumerConfig(baseDir?: string): ConsumerConfig;