@diffci.com/diffci 0.1.11 → 0.2.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 (76) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +295 -229
  3. package/action.yml +154 -154
  4. package/dist-client/src/client/cli.js +213 -95
  5. package/dist-client/src/client/economics.js +31 -0
  6. package/dist-client/src/client/full-command.js +46 -0
  7. package/dist-client/src/client/mcp.js +196 -0
  8. package/dist-client/src/client/observe.js +40 -9
  9. package/dist-client/src/client/verify-savings.js +8 -2
  10. package/docs/agent-adoption-kit.md +96 -0
  11. package/docs/agent-adoption-targets.md +52 -0
  12. package/docs/ai-agents.md +27 -3
  13. package/docs/claude-code.md +3 -2
  14. package/docs/codex.md +3 -2
  15. package/docs/copilot.md +4 -4
  16. package/docs/cursor.md +4 -4
  17. package/docs/grok.md +3 -2
  18. package/docs/language-support.md +118 -70
  19. package/docs/mcp.md +21 -0
  20. package/docs/npm-adoption.md +6 -0
  21. package/llms.txt +3 -0
  22. package/node_modules/@babel/parser/bin/babel-parser.js +0 -0
  23. package/node_modules/@diffci.com/core/README.md +9 -1
  24. package/node_modules/@diffci.com/core/dist/cache/economics-context.d.ts +2 -0
  25. package/node_modules/@diffci.com/core/dist/cache/economics-context.js +21 -0
  26. package/node_modules/@diffci.com/core/dist/cache/economics-context.js.map +1 -0
  27. package/node_modules/@diffci.com/core/dist/cache/vue-analysis-cache.d.ts +5 -0
  28. package/node_modules/@diffci.com/core/dist/cache/vue-analysis-cache.js +100 -0
  29. package/node_modules/@diffci.com/core/dist/cache/vue-analysis-cache.js.map +1 -0
  30. package/node_modules/@diffci.com/core/dist/planner/test-command.js +32 -0
  31. package/node_modules/@diffci.com/core/dist/planner/test-command.js.map +1 -1
  32. package/node_modules/@diffci.com/core/dist/repo/adapters/go.d.ts +3 -0
  33. package/node_modules/@diffci.com/core/dist/repo/adapters/go.js +24 -6
  34. package/node_modules/@diffci.com/core/dist/repo/adapters/go.js.map +1 -1
  35. package/node_modules/@diffci.com/core/dist/repo/adapters/index.js +2 -1
  36. package/node_modules/@diffci.com/core/dist/repo/adapters/index.js.map +1 -1
  37. package/node_modules/@diffci.com/core/dist/repo/adapters/maven.d.ts +3 -0
  38. package/node_modules/@diffci.com/core/dist/repo/adapters/maven.js +65 -0
  39. package/node_modules/@diffci.com/core/dist/repo/adapters/maven.js.map +1 -0
  40. package/node_modules/@diffci.com/core/dist/repo/adapters/types.d.ts +11 -0
  41. package/node_modules/@diffci.com/core/dist/repo/adapters/types.js.map +1 -1
  42. package/node_modules/@diffci.com/core/dist/repo/adapters/vue.js +142 -14
  43. package/node_modules/@diffci.com/core/dist/repo/adapters/vue.js.map +1 -1
  44. package/node_modules/@diffci.com/core/dist/repo/graph.d.ts +4 -0
  45. package/node_modules/@diffci.com/core/dist/repo/graph.js +169 -19
  46. package/node_modules/@diffci.com/core/dist/repo/graph.js.map +1 -1
  47. package/node_modules/@diffci.com/core/dist/repo/impact.js +22 -5
  48. package/node_modules/@diffci.com/core/dist/repo/impact.js.map +1 -1
  49. package/node_modules/@diffci.com/core/dist/repo/repo-config.d.ts +15 -0
  50. package/node_modules/@diffci.com/core/dist/repo/repo-config.js +13 -2
  51. package/node_modules/@diffci.com/core/dist/repo/repo-config.js.map +1 -1
  52. package/node_modules/@diffci.com/core/dist/repo/test-discovery.js +2 -0
  53. package/node_modules/@diffci.com/core/dist/repo/test-discovery.js.map +1 -1
  54. package/node_modules/@diffci.com/core/dist/repo/types.d.ts +17 -0
  55. package/node_modules/@diffci.com/core/dist/repo/vue-scope.d.ts +4 -0
  56. package/node_modules/@diffci.com/core/dist/repo/vue-scope.js +157 -0
  57. package/node_modules/@diffci.com/core/dist/repo/vue-scope.js.map +1 -0
  58. package/node_modules/@diffci.com/core/src/cache/economics-context.ts +19 -0
  59. package/node_modules/@diffci.com/core/src/cache/vue-analysis-cache.ts +80 -0
  60. package/node_modules/@diffci.com/core/src/planner/test-command.ts +28 -0
  61. package/node_modules/@diffci.com/core/src/repo/adapters/go.ts +24 -5
  62. package/node_modules/@diffci.com/core/src/repo/adapters/index.ts +2 -1
  63. package/node_modules/@diffci.com/core/src/repo/adapters/maven.ts +38 -0
  64. package/node_modules/@diffci.com/core/src/repo/adapters/types.ts +5 -0
  65. package/node_modules/@diffci.com/core/src/repo/adapters/vue.ts +120 -15
  66. package/node_modules/@diffci.com/core/src/repo/graph.ts +146 -20
  67. package/node_modules/@diffci.com/core/src/repo/impact.ts +20 -4
  68. package/node_modules/@diffci.com/core/src/repo/repo-config.ts +20 -2
  69. package/node_modules/@diffci.com/core/src/repo/test-discovery.ts +2 -0
  70. package/node_modules/@diffci.com/core/src/repo/types.ts +11 -0
  71. package/node_modules/@diffci.com/core/src/repo/vue-scope.ts +122 -0
  72. package/node_modules/nanoid/bin/nanoid.cjs +0 -0
  73. package/node_modules/typescript/bin/tsc +0 -0
  74. package/node_modules/typescript/bin/tsserver +0 -0
  75. package/node_modules/yaml/bin.mjs +0 -0
  76. package/package.json +155 -138
@@ -1,70 +1,118 @@
1
- # Language and framework support
2
-
3
- DiffCI now has an extensible repository-adapter boundary and initial Vue and Go support.
4
- These additions propose selections in the existing observer; they do not enable production CI skipping.
5
-
6
- | Surface | Implemented scope | Boundaries |
7
- | --- | --- | --- |
8
- | JavaScript / TypeScript | Existing dependency analysis and ten existing test-runner command mappings | Runner recognition is not a guarantee of complete framework semantics |
9
- | Vue | SFC parsing with `@vue/compiler-sfc`; script imports, nested components, compiled template asset imports; propagation into importing JS/TS tests | Runtime component/directive resolution, preprocessors, external/custom SFC blocks, style URLs/imports, Nuxt conventions and glob imports require full validation |
10
- | Go | One root module; native `go list` metadata; package-level transitive test selection, external test packages, embedded files; `go test -json` commands and result parsing | Workspaces/nested modules, inactive Go files, cgo/native objects, runtime plugins, generation/linkname, external local replacements and incomplete metadata require full validation |
11
- | Mixed Go and JS/TS | Detected | Full validation until cross-language relationships are declared and modeled |
12
- | Python, Svelte, Astro, Java/Kotlin, C#, Rust | No new semantic support in this release | Require additional adapters and qualification |
13
-
14
- ## Using the observer
15
-
16
- Use the existing `observe` command and commit range options. The observer now admits a root
17
- `go.mod` or Vue SFCs as well as a TypeScript project. Vue projects without a tsconfig have their
18
- JS/TS files parsed alongside their components. Existing TS-only corpus eligibility remains separate:
19
- this release does not silently enroll Go repositories in historical JS/TS research cohorts.
20
-
21
- For Go, install a compatible Go toolchain on the **same host and build environment** used for analysis
22
- and testing, and prepare the repository's dependencies first using its normal setup procedure.
23
- DiffCI invokes `go list -mod=readonly -deps -test -json ./...` with `GOTOOLCHAIN=local`, `GOPROXY=off`,
24
- `GOSUMDB=off`, and `GOWORK=off`. Missing toolchains or dependencies produce refusal/full fallback.
25
- Go may populate its own build cache but must not modify the checkout. It does not run `go generate`.
26
- Custom `GOFLAGS` currently require full validation. Discovered GOOS, GOARCH and CGO_ENABLED settings
27
- are carried into the structured test command.
28
-
29
- A selection such as `lib/value_test.go` becomes:
30
-
31
- ```sh
32
- go test -mod=readonly -json -count=1 ./lib
33
- ```
34
-
35
- It runs the entire package. Consumers must honor the emitted `CommandSpec.env`, preserve the build
36
- context, and check fallback/command-synthesis status before execution. Commands are not portable
37
- between different GOOS/GOARCH/GOFLAGS contexts. The controlled runner command policies accept `go`;
38
- hosted images still need a Go installation before Go workloads can run. No deployment is performed
39
- by these code changes.
40
-
41
- Go result parsing counts failing **packages**, records failing test names, and rejects incomplete
42
- JSON streams. It does not invent test-file counts from package counts, so file-based economics
43
- qualification may still report an unsupported denominator for Go.
44
-
45
- ## Extension points
46
-
47
- - `src/repo/adapters/types.ts`: adapter context and graph contribution contract.
48
- - `src/repo/adapters/index.ts`: framework/language adapter registry and bounded file inventory.
49
- - `src/repo/adapters/vue.ts`: Vue compiler integration.
50
- - `src/repo/adapters/go.ts`: native Go package metadata and conservative dependency model.
51
- - `src/repo/adapters/go-test.ts`: structured Go outcome parsing.
52
- - `src/planner/test-command.ts`: runner command routing, including verified Go package targets.
53
-
54
- Adapters contribute source and asset nodes, dependency edges, virtual JS/TS source, runnable test
55
- identities and explicit blockers. Blockers persist into the profile and graph result and cannot be
56
- removed by delta-specific reachability refinement. Go graphs bypass the disk cache until every cache
57
- caller provides a complete toolchain/build-context identity. The cache schema was bumped to prevent
58
- reuse of graphs created before adapter support.
59
-
60
- ## Validation and qualification
61
-
62
- `tests/repo/language-adapters.test.ts` covers transitive Vue selection, unsupported-feature fallbacks,
63
- Go package imports and embeds, metadata failures, command routing, and incomplete output.
64
- When Go is on PATH, its native integration test runs the observer against a real Git fixture,
65
- compares successful full/subset test runs, and verifies the subset catches an introduced fault.
66
- Without Go, that native test is explicitly skipped.
67
-
68
- These are implementation checks, not prospective customer safety or savings evidence. Each new
69
- ecosystem still needs real repository shadow observations and economic qualification before broader
70
- support or savings claims are made.
1
+ # Language and framework support
2
+
3
+ DiffCI now has an extensible repository-adapter boundary and initial Vue, Go, and Maven support.
4
+ These additions propose selections in the existing observer; they do not enable production CI skipping.
5
+
6
+ | Surface | Implemented scope | Boundaries |
7
+ | --- | --- | --- |
8
+ | JavaScript / TypeScript | Existing dependency analysis and ten existing test-runner command mappings | Runner recognition is not a guarantee of complete framework semantics |
9
+ | Vue | SFC parsing with `@vue/compiler-sfc`; script imports, literal Options API component registrations, empty script fixtures, compiled template asset imports; propagation into importing JS/TS tests; protected runtime-dependent tests in verified isolated scopes | Runtime uncertainty requires full validation unless protected by the isolated-suite policy below; preprocessors, external/custom SFC blocks, style URLs/imports, Nuxt conventions and glob imports require full validation |
10
+ | Go | One root module; optional explicit root-module scope in a repository containing nested modules; native metadata, package-level transitive selection, embeds and Go test commands | Workspaces, changes inside excluded modules, inactive Go files, cgo/native objects, plugins, generation/linkname and incomplete metadata require full validation; root scoping rejects local replacements |
11
+ | Maven / Java / Kotlin | Conventional multi-module reactors with `src/main/{java,kotlin}` and `src/test/{java,kotlin}`; module dependency propagation; Surefire-style test names; proposed reactor commands | Nonstandard layouts, generated sources, integration-test conventions, and POM changes may require full validation. Maven commands are observations and must match the repository's CI lifecycle and profiles. |
12
+ | Mixed Go and JS/TS | Detected | Full validation until cross-language relationships are declared and modeled |
13
+ | Python, Svelte, Astro, C#, Rust | No new semantic support in this release | Require additional adapters and qualification |
14
+
15
+ ## Using the observer
16
+
17
+ Use the existing `observe` command and commit range options. The observer now admits a root
18
+ `go.mod`, Vue SFCs, or a conventional Maven reactor as well as a TypeScript project. Vue projects without a tsconfig have their
19
+ JS/TS files parsed alongside their components. Existing TS-only corpus eligibility remains separate:
20
+ this release does not silently enroll Go repositories in historical JS/TS research cohorts.
21
+
22
+ For Maven, DiffCI proposes module-level commands but does not run them or change CI. The default
23
+ goal is `test`. If the repository's CI runs `verify` with profiles, declare that command shape in
24
+ `diffci.json` (or the `diffci` key in `package.json`):
25
+
26
+ ```json
27
+ { "maven": { "goal": "verify", "profiles": ["run-its"] } }
28
+ ```
29
+
30
+ This produces a command such as `mvn -pl tools -am verify -P run-its`. The `-am` option can also run
31
+ tests in upstream modules. Check the proposed command against the actual CI workflow before using
32
+ it for execution. A single Cloudflare Resolver run showed a candidate saving of 8.6% with a
33
+ CI-aligned `verify -P run-its` command; it does not establish repeatable savings across repositories.
34
+
35
+ For Go, install a compatible Go toolchain on the **same host and build environment** used for analysis
36
+ and testing, and prepare the repository's dependencies first using its normal setup procedure.
37
+ DiffCI invokes `go list -mod=readonly -deps -test -json ./...` with `GOTOOLCHAIN=local`, `GOPROXY=off`,
38
+ `GOSUMDB=off`, and `GOWORK=off`. Missing toolchains or dependencies produce refusal/full fallback.
39
+ Go may populate its own build cache but must not modify the checkout. It does not run `go generate`.
40
+ Custom `GOFLAGS` currently require full validation. Discovered GOOS, GOARCH and CGO_ENABLED settings
41
+ are carried into the structured test command.
42
+
43
+ For CI that runs only the root module's `go test ./...`, a repository containing nested
44
+ modules can explicitly declare that scope in a committed root `diffci.json`:
45
+
46
+ ```json
47
+ { "go": { "scope": "root-module" } }
48
+ ```
49
+
50
+ This does not cover nested-module CI jobs. Keep their validation unchanged. Without the
51
+ declaration, nested modules still block selection. With it, nested module trees are
52
+ excluded from the root test universe, but any change there (including a rename out of
53
+ the tree) forces full validation. Scope/configuration changes also force full validation.
54
+ Go workspaces and local replacements still block scoped selection. Reports identify the
55
+ declared `goScope`; the structured commands continue to run root-relative packages.
56
+
57
+ Empty-graph refusals now include the adapter's reason. Vue recognizes only direct imported
58
+ component identifiers in literal `components` registrations. Unresolved runtime dependencies
59
+ retain full execution unless the isolated-suite protection described below applies.
60
+
61
+ The Reka selection candidate also resolves imported Vue macro types through TypeScript aliases,
62
+ extended configurations and directory index files, and recognizes leading `./` in test globs.
63
+ For an explicitly scoped Vue suite, a component-specific blocker can be excluded only when every
64
+ test/setup/configuration root has been parsed and none can reach that component. This is not a
65
+ directory-name exclusion: imported story fixtures retain their blockers. Unresolved dependencies
66
+ and global configuration blockers still force full validation. Compiler-assisted components that
67
+ probe JSON configuration are rebuilt instead of persistently cached until every compiler input can
68
+ be tracked. See the [Reka experiment](research/2026-09-13-reka-selection.md) for qualification evidence.
69
+
70
+ The runtime-protection candidate can always run every test file reaching an unresolved runtime
71
+ component or directive, while selecting other tests normally. This requires a verified scoped
72
+ Vitest suite and isolated execution. Shared setup reaching a runtime blocker, disabled or ambiguous
73
+ isolation, custom runners/environments and unmodeled configuration keep full-suite fallback.
74
+ This policy protects tests despite unknown runtime edges; it does not resolve those edges or claim
75
+ support for non-isolated or order-dependent jobs. See the [runtime protection experiment](research/2026-09-13-vue-runtime-partition.md).
76
+
77
+ A selection such as `lib/value_test.go` becomes:
78
+
79
+ ```sh
80
+ go test -mod=readonly -json -count=1 ./lib
81
+ ```
82
+
83
+ It runs the entire package. Consumers must honor the emitted `CommandSpec.env`, preserve the build
84
+ context, and check fallback/command-synthesis status before execution. Commands are not portable
85
+ between different GOOS/GOARCH/GOFLAGS contexts. The controlled runner command policies accept `go`;
86
+ hosted images still need a Go installation before Go workloads can run. No deployment is performed
87
+ by these code changes.
88
+
89
+ Go result parsing counts failing **packages**, records failing test names, and rejects incomplete
90
+ JSON streams. It does not invent test-file counts from package counts, so file-based economics
91
+ qualification may still report an unsupported denominator for Go.
92
+
93
+ ## Extension points
94
+
95
+ - `src/repo/adapters/types.ts`: adapter context and graph contribution contract.
96
+ - `src/repo/adapters/index.ts`: framework/language adapter registry and bounded file inventory.
97
+ - `src/repo/adapters/vue.ts`: Vue compiler integration.
98
+ - `src/repo/adapters/go.ts`: native Go package metadata and conservative dependency model.
99
+ - `src/repo/adapters/go-test.ts`: structured Go outcome parsing.
100
+ - `src/planner/test-command.ts`: runner command routing, including verified Go package targets.
101
+
102
+ Adapters contribute source and asset nodes, dependency edges, virtual JS/TS source, runnable test
103
+ identities and explicit blockers. Effective suite blockers persist into the profile and graph result
104
+ and cannot be removed by delta-specific reachability refinement. Go graphs bypass the disk cache until every cache
105
+ caller provides a complete toolchain/build-context identity. The cache schema was bumped to prevent
106
+ reuse of graphs created before adapter support.
107
+
108
+ ## Validation and qualification
109
+
110
+ `tests/repo/language-adapters.test.ts` covers transitive Vue selection, unsupported-feature fallbacks,
111
+ Go package imports and embeds, metadata failures, command routing, and incomplete output.
112
+ When Go is on PATH, its native integration test runs the observer against a real Git fixture,
113
+ compares successful full/subset test runs, and verifies the subset catches an introduced fault.
114
+ Without Go, that native test is explicitly skipped.
115
+
116
+ These are implementation checks, not prospective customer safety or savings evidence. Each new
117
+ ecosystem still needs real repository shadow observations and economic qualification before broader
118
+ support or savings claims are made.
package/docs/mcp.md ADDED
@@ -0,0 +1,21 @@
1
+ # DiffCI MCP Server
2
+
3
+ DiffCI ships a small stdio MCP server for coding agents that prefer native tools over shell commands.
4
+
5
+ Run it with:
6
+
7
+ ```bash
8
+ npx -p @diffci.com/diffci@latest diffci-mcp
9
+ ```
10
+
11
+ Available tools:
12
+
13
+ - `diffci_check` - runs `diffci check`, including inferred full and selected test commands.
14
+ - `diffci_init` - runs `diffci init` to seed agent instruction files.
15
+ - `diffci_verify_workflow` - runs `diffci verify-workflow` to check non-interference.
16
+
17
+ The MCP server delegates to the same open-source CLI. `diffci_check` sends nothing to DiffCI Cloud,
18
+ but it runs test commands when it can infer them. Use the CLI's `observe --no-send` for analysis only.
19
+
20
+ Keep required project CI authoritative. DiffCI output is a validation lens, not permission to skip
21
+ required checks.
@@ -59,6 +59,12 @@ Ask maintainers for a small, reversible experiment:
59
59
  Use this when a maintainer asks whether selecting fewer tests would actually make their CI faster.
60
60
  This is a paired local measurement, not a production-savings claim.
61
61
 
62
+ For one command that infers the full test command and prints the measured percentage when both runs
63
+ pass, use `npx @diffci.com/diffci@latest check` from the repository root. For Maven, `check` reads
64
+ the goal and profiles from `diffci.json` when present; otherwise it uses `mvn test` and says that
65
+ the default may differ from CI. Run it on the intended CI runner: timings from another machine are
66
+ not CI savings. A full-validation fallback runs the full command once and reports 0% reduction.
67
+
62
68
  Step 1: create an observation report without sending it anywhere.
63
69
 
64
70
  ```bash
package/llms.txt CHANGED
@@ -30,5 +30,8 @@ Useful docs:
30
30
  - Cursor: https://diffci.com/docs/cursor.html
31
31
  - GitHub Copilot: https://diffci.com/docs/copilot.html
32
32
  - Grok: https://diffci.com/docs/grok.html
33
+ - Adoption kit: https://github.com/DiffCI/DiffCI.com/blob/main/docs/agent-adoption-kit.md
34
+ - Adoption targets: https://github.com/DiffCI/DiffCI.com/blob/main/docs/agent-adoption-targets.md
35
+ - MCP server: https://github.com/DiffCI/DiffCI.com/blob/main/docs/mcp.md
33
36
  - Distribution: https://github.com/DiffCI/DiffCI.com/blob/main/docs/distribution.md
34
37
  - Language support: https://github.com/DiffCI/DiffCI.com/blob/main/docs/language-support.md
File without changes
@@ -2,7 +2,7 @@
2
2
 
3
3
  **An open-source engine for understanding changes and planning less CI work conservatively.** Licensed under AGPL-3.0-only.
4
4
 
5
- This is the standalone Core engine. It analyzes local JavaScript/TypeScript repositories, supported Vue components and root Go modules, traces dependency impact, infers GitHub Actions structure and proposes test selections with evidence and full-run fallbacks. It works without a DiffCI account, hosted service or API key. See [the release boundary](docs/release-boundary.md) for support limits.
5
+ This is the standalone Core engine. It analyzes local JavaScript/TypeScript repositories, supported Vue components, root Go modules and conventional Maven reactors, traces dependency impact, infers GitHub Actions structure and proposes test selections with evidence and full-run fallbacks. It works without a DiffCI account, hosted service or API key. See [the release boundary](docs/release-boundary.md) for support limits.
6
6
 
7
7
  ## Run locally
8
8
 
@@ -21,6 +21,14 @@ The target must be a clean Git repository root checked out at `--head`. Fetch th
21
21
 
22
22
  **Plans are advisory.** This release does not execute, skip or cancel CI jobs. `SKIP_CANDIDATE` is a candidate, not permission to bypass a check. Keep full CI authoritative while evaluating Core. Missing command synthesis, unsupported configuration and incomplete evidence must not be treated as an empty test suite. Static analysis is not proof that a test can safely be omitted.
23
23
 
24
+ For Maven jobs whose CI runs a lifecycle goal or profiles other than `test`, declare them in `diffci.json` (or the `diffci` key in `package.json`):
25
+
26
+ ```json
27
+ { "maven": { "goal": "verify", "profiles": ["run-its"] } }
28
+ ```
29
+
30
+ This changes the proposed command, such as `mvn -pl tools -am verify -P run-its`; Core still does not run it. Confirm the command against the repository's CI workflow before using it for execution.
31
+
24
32
  ## What is included
25
33
 
26
34
  | Area | Implementation |
@@ -0,0 +1,2 @@
1
+ /** Files that determine whether a cached Vue analysis still matches the checkout configuration. */
2
+ export declare function economicsContext(repoPath: string): string;
@@ -0,0 +1,21 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { readRepositoryConfig } from "../repo/repo-config.js";
5
+ /** Files that determine whether a cached Vue analysis still matches the checkout configuration. */
6
+ export function economicsContext(repoPath) {
7
+ const scope = readRepositoryConfig(repoPath).vue;
8
+ const paths = new Set(["diffci.json", "package.json", "tsconfig.json", "go.mod", "go.sum", "go.work", "go.work.sum", "pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock", "bun.lockb", ...["ts", "js", "mts", "mjs", "cts", "cjs"].map(ext => `vitest.config.${ext}`)]);
9
+ if (scope)
10
+ for (const path of ["package.json", "tsconfig.json", scope.testConfig])
11
+ paths.add(`${scope.packageRoot}/${path}`);
12
+ const hash = createHash("sha256").update(JSON.stringify([process.platform, process.arch, process.version]));
13
+ for (const path of [...paths].sort()) {
14
+ hash.update(JSON.stringify(path));
15
+ const file = join(repoPath, path);
16
+ hash.update(existsSync(file) ? readFileSync(file) : "<absent>");
17
+ hash.update("\0");
18
+ }
19
+ return hash.digest("hex");
20
+ }
21
+ //# sourceMappingURL=economics-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"economics-context.js","sourceRoot":"","sources":["../../src/cache/economics-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,mGAAmG;AACnG,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACnR,IAAI,KAAK;QAAE,KAAK,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,eAAe,EAAE,KAAK,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC,CAAC;IAC7H,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5G,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type AdapterContext, type AdapterContribution } from "../repo/adapters/types.js";
2
+ /** Trusted runner-local cache, optional and never a source of test-selection authority.
3
+ * Every hit validates source, context and all compiler filesystem probes. Graph resolution
4
+ * and selection are rebuilt. Any unreadable/corrupt cache is an ordinary analysis miss. */
5
+ export declare function analyzeVueCached(context: AdapterContext, directory: string, version: string): AdapterContribution;
@@ -0,0 +1,100 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, writeFileSync } from "node:fs";
3
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+ import { economicsContext } from "./economics-context.js";
5
+ import { vueAdapter } from "../repo/adapters/vue.js";
6
+ import { contribution } from "../repo/adapters/types.js";
7
+ const digest = (value) => createHash("sha256").update(value).digest("hex");
8
+ function physical(path) {
9
+ if (existsSync(path))
10
+ return realpathSync(path);
11
+ return resolve(physical(dirname(path)), relative(dirname(path), path));
12
+ }
13
+ function fingerprint(path) {
14
+ if (!existsSync(path))
15
+ return "absent";
16
+ return JSON.stringify([realpathSync(path), statSync(path).isFile() ? digest(readFileSync(path)) : "directory"]);
17
+ }
18
+ /** Trusted runner-local cache, optional and never a source of test-selection authority.
19
+ * Every hit validates source, context and all compiler filesystem probes. Graph resolution
20
+ * and selection are rebuilt. Any unreadable/corrupt cache is an ordinary analysis miss. */
21
+ export function analyzeVueCached(context, directory, version) {
22
+ let cacheDir;
23
+ let namespace;
24
+ try {
25
+ cacheDir = physical(resolve(directory));
26
+ const rel = relative(realpathSync(context.repoPath), cacheDir);
27
+ if (!rel || (!(rel === ".." || rel.startsWith("../") || rel.startsWith("..\\")) && !isAbsolute(rel)))
28
+ return vueAdapter.analyze(context);
29
+ namespace = digest(JSON.stringify(["vue-analysis-v1", version, vueAdapter.version, realpathSync(context.repoPath), economicsContext(context.repoPath), context.files]));
30
+ }
31
+ catch {
32
+ return vueAdapter.analyze(context);
33
+ }
34
+ const result = contribution(vueAdapter);
35
+ const phasesMs = {};
36
+ const counts = { cacheHits: 0, cacheMisses: 0, cacheWriteFailures: 0 };
37
+ result.performance = { phasesMs, counts };
38
+ for (const path of context.files.filter(file => file.endsWith(".vue"))) {
39
+ const started = performance.now();
40
+ const file = join(cacheDir, `${digest(path)}.json`);
41
+ let key = "";
42
+ let item;
43
+ try {
44
+ key = digest(JSON.stringify([namespace, path, fingerprint(join(context.repoPath, path))]));
45
+ const envelope = JSON.parse(readFileSync(file, "utf8"));
46
+ if (envelope.key === key && typeof envelope.payload === "string" && digest(envelope.payload) === envelope.sha256) {
47
+ const data = JSON.parse(envelope.payload);
48
+ if (Array.isArray(data.probes) && data.probes.every((probe) => Array.isArray(probe) && probe.length === 2 && typeof probe[0] === "string" && fingerprint(probe[0]) === probe[1]))
49
+ item = data.result;
50
+ }
51
+ }
52
+ catch { /* unreadable or stale entry: rebuild */ }
53
+ phasesMs.cacheReadValidate = (phasesMs.cacheReadValidate ?? 0) + performance.now() - started;
54
+ if (item)
55
+ counts.cacheHits++;
56
+ else {
57
+ counts.cacheMisses++;
58
+ const probes = new Map();
59
+ let cacheable = true;
60
+ item = vueAdapter.analyze({ ...context, vueComponentPaths: [path], recordVueRead(file) {
61
+ // TS config expansion can read extended configs through its own system host.
62
+ // Until every such input is recorded, rebuild compiler-assisted components.
63
+ if (file.endsWith(".json"))
64
+ cacheable = false;
65
+ try {
66
+ probes.set(resolve(file), fingerprint(file));
67
+ }
68
+ catch {
69
+ cacheable = false;
70
+ }
71
+ } });
72
+ if (key && cacheable) {
73
+ const writeStart = performance.now();
74
+ try {
75
+ const { performance: _performance, ...cachedResult } = item;
76
+ const payload = JSON.stringify({ probes: [...probes], result: cachedResult });
77
+ mkdirSync(cacheDir, { recursive: true });
78
+ const temporary = `${file}.${randomUUID()}.tmp`;
79
+ writeFileSync(temporary, JSON.stringify({ key, payload, sha256: digest(payload) }));
80
+ renameSync(temporary, file);
81
+ }
82
+ catch {
83
+ counts.cacheWriteFailures++;
84
+ }
85
+ phasesMs.cacheWrite = (phasesMs.cacheWrite ?? 0) + performance.now() - writeStart;
86
+ }
87
+ }
88
+ for (const field of ["sourcePaths", "assetPaths", "edges", "virtualSources", "testFiles"])
89
+ result[field].push(...item[field]);
90
+ result.blockers.push(...item.blockers.filter(blocker => !result.blockers.includes(blocker)));
91
+ (result.fileBlockers ??= []).push(...(item.fileBlockers ?? []));
92
+ Object.assign(result.testPackages, item.testPackages);
93
+ for (const [name, value] of Object.entries(item.performance?.phasesMs ?? {}))
94
+ phasesMs[name] = (phasesMs[name] ?? 0) + value;
95
+ for (const [name, value] of Object.entries(item.performance?.counts ?? {}))
96
+ counts[name] = (counts[name] ?? 0) + value;
97
+ }
98
+ return result;
99
+ }
100
+ //# sourceMappingURL=vue-analysis-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue-analysis-cache.js","sourceRoot":"","sources":["../../src/cache/vue-analysis-cache.ts"],"names":[],"mappings":"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"}
@@ -61,6 +61,19 @@ export function planSelectiveTestCommands(profile, selectedPaths) {
61
61
  const blockers = profile.adapterBlockers ?? profile.adapters?.flatMap((adapter) => adapter.blockers) ?? [];
62
62
  if (blockers.length)
63
63
  return { commands: [], groups: [], unroutedPaths: [...selectedPaths], refusalReason: blockers.join("; ") };
64
+ if (profile.vueScope) {
65
+ const scope = profile.vueScope;
66
+ const known = new Set(profile.testFilePaths);
67
+ const unclaimed = selectedPaths.filter(path => !known.has(path));
68
+ if (unclaimed.length || profile.packageManager !== "pnpm")
69
+ return { commands: [], groups: [], unroutedPaths: [...unclaimed], refusalReason: "Scoped Vitest execution requires pnpm and verified package test paths" };
70
+ if (!selectedPaths.length)
71
+ return { commands: [], groups: [], unroutedPaths: [] };
72
+ const paths = [...selectedPaths].sort();
73
+ const local = paths.map(path => scope.packageRoot === "." ? path : path.slice(scope.packageRoot.length + 1));
74
+ const commandSpec = { executable: "pnpm", args: ["--dir", scope.packageRoot, "exec", "vitest", "run", "--config", scope.testConfig, ...local] };
75
+ return { commands: [commandSpec], groups: [{ runnerId: `vitest:${scope.packageRoot}/${scope.testConfig}`, label: "Declared Vue package suite", paths, commandSpec }], unroutedPaths: [] };
76
+ }
64
77
  const goPaths = selectedPaths.filter((path) => path.endsWith(".go"));
65
78
  if (goPaths.length) {
66
79
  const packages = profile.goTestPackages ?? {};
@@ -81,6 +94,25 @@ export function planSelectiveTestCommands(profile, selectedPaths) {
81
94
  const group = { runnerId: "go:test", label: "Go package tests", paths: [...goPaths].sort(), commandSpec };
82
95
  return { commands: [...jsPlan.commands, commandSpec], groups: [...jsPlan.groups, group], unroutedPaths: [] };
83
96
  }
97
+ const javaPaths = selectedPaths.filter((path) => path.endsWith(".java") || path.endsWith(".kt"));
98
+ if (javaPaths.length) {
99
+ const modules = profile.mavenTestModules ?? {};
100
+ const unclaimed = javaPaths.filter((path) => !Object.hasOwn(modules, path));
101
+ if (unclaimed.length)
102
+ return { commands: [], groups: [], unroutedPaths: unclaimed, refusalReason: "Maven test files require verified reactor module metadata" };
103
+ if (selectedPaths.some((path) => !path.endsWith(".java") && !path.endsWith(".kt")))
104
+ return { commands: [], groups: [], unroutedPaths: [...selectedPaths], refusalReason: "Mixed Maven/JavaScript selective execution requires separate CI jobs" };
105
+ const targets = [...new Set(javaPaths.map((path) => modules[path]))].sort();
106
+ if (targets.some((target) => target !== "." && (target.startsWith("/") || target.split("/").includes("..") || /[\\\r\n]/.test(target)))) {
107
+ return { commands: [], groups: [], unroutedPaths: javaPaths, refusalReason: "Invalid Maven reactor module target" };
108
+ }
109
+ const maven = profile.diffciConfig?.maven;
110
+ const goal = maven?.goal ?? "test";
111
+ const args = [...(targets.length === 1 && targets[0] === "." ? [] : ["-pl", targets.join(","), "-am"]), goal, ...(maven?.profiles?.length ? ["-P", maven.profiles.join(",")] : [])];
112
+ const commandSpec = { executable: "mvn", args };
113
+ const group = { runnerId: "maven:surefire", label: "Maven reactor tests", paths: [...javaPaths].sort(), commandSpec };
114
+ return { commands: [commandSpec], groups: [group], unroutedPaths: [] };
115
+ }
84
116
  const paths = [...selectedPaths].sort();
85
117
  if (paths.length === 0)
86
118
  return { commands: [], groups: [], unroutedPaths: [] };
@@ -1 +1 @@
1
- {"version":3,"file":"test-command.js","sourceRoot":"","sources":["../../src/planner/test-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-command.js","sourceRoot":"","sources":["../../src/planner/test-command.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ interface GoPackage {
14
14
  DepsErrors?: unknown[];
15
15
  Incomplete?: boolean;
16
16
  GoFiles?: string[];
17
+ IgnoredGoFiles?: string[];
17
18
  CgoFiles?: string[];
18
19
  TestGoFiles?: string[];
19
20
  XTestGoFiles?: string[];
@@ -28,6 +29,8 @@ interface GoPackage {
28
29
  }
29
30
  /** go list emits adjacent JSON objects, not a JSON array or JSONL. */
30
31
  export declare function parseGoList(output: string): GoPackage[];
32
+ /** go ./... excludes these names; edits still require full CI (for example testdata reads). */
33
+ export declare function isGoDiscoveryIgnoredPath(path: string): boolean;
31
34
  export declare function analyzeGoMetadata(context: AdapterContext, output: string): AdapterContribution;
32
35
  export declare const goAdapter: RepositoryAdapter;
33
36
  export {};
@@ -44,6 +44,10 @@ function internalPath(root, path) {
44
44
  const rel = relative(root, resolve(path)).replace(/\\/g, "/");
45
45
  return rel === ".." || rel.startsWith("../") || isAbsolute(rel) ? undefined : rel;
46
46
  }
47
+ /** go ./... excludes these names; edits still require full CI (for example testdata reads). */
48
+ export function isGoDiscoveryIgnoredPath(path) {
49
+ return path.split("/").some(part => part === "testdata" || part.startsWith("_") || part.startsWith("."));
50
+ }
47
51
  export function analyzeGoMetadata(context, output) {
48
52
  const result = contribution(goAdapter);
49
53
  const all = parseGoList(output);
@@ -55,7 +59,10 @@ export function analyzeGoMetadata(context, output) {
55
59
  const anchors = new Map();
56
60
  const members = new Map();
57
61
  for (const pkg of packages) {
58
- const files = [...(pkg.GoFiles ?? []), ...(pkg.CgoFiles ?? []), ...(pkg.TestGoFiles ?? []), ...(pkg.XTestGoFiles ?? [])];
62
+ // Associate inactive files with their package conservatively. They are not runnable
63
+ // tests, but edits (including build constraints) must still select that package and
64
+ // its dependents. Unaccounted files remain a global blocker below.
65
+ const files = [...(pkg.GoFiles ?? []), ...(pkg.CgoFiles ?? []), ...(pkg.TestGoFiles ?? []), ...(pkg.XTestGoFiles ?? []), ...(pkg.IgnoredGoFiles ?? [])];
59
66
  const paths = files.map((file) => internalPath(context.repoPath, resolve(pkg.Dir, file)));
60
67
  if (paths.some((p) => p === undefined)) {
61
68
  result.blockers.push("Go package contains files outside the repository");
@@ -112,16 +119,19 @@ export function analyzeGoMetadata(context, output) {
112
119
  result.blockers.push("Go analysis found no local packages");
113
120
  // Ignored files/build tags, generation and testdata can change the runnable universe.
114
121
  const modeled = new Set([...result.sourcePaths, ...result.assetPaths]);
115
- if (context.files.some((file) => file.endsWith(".go") && !modeled.has(file)))
116
- result.blockers.push("Go files outside the active build context require full validation");
122
+ const unmodeled = context.files.filter(file => file.endsWith(".go") && !modeled.has(file) && !isGoDiscoveryIgnoredPath(file));
123
+ if (unmodeled.length)
124
+ result.blockers.push(`Go files outside the active build context require full validation: ${unmodeled.slice(0, 20).join(", ")}`);
117
125
  return result;
118
126
  }
119
127
  export const goAdapter = {
120
- id: "go", version: "1", kind: "language",
128
+ id: "go", version: "3", kind: "language",
121
129
  detect: ({ files }) => files.some((file) => file === "go.mod" || file.endsWith(".go")),
122
130
  analyze(context) {
123
131
  const failure = contribution(this);
124
- if (!context.files.includes("go.mod") || context.files.some((f) => f === "go.work" || f.endsWith("/go.mod"))) {
132
+ const nestedRoots = context.files.filter(f => f.endsWith("/go.mod")).map(f => f.slice(0, -"go.mod".length));
133
+ const scoped = context.profile.diffciConfig?.go?.scope === "root-module";
134
+ if (!context.files.includes("go.mod") || context.files.includes("go.work") || (nestedRoots.length && !scoped)) {
125
135
  failure.blockers.push("Go support requires one root go.mod; workspaces and nested modules require full validation");
126
136
  return failure;
127
137
  }
@@ -142,7 +152,15 @@ export const goAdapter = {
142
152
  env,
143
153
  stdio: ["ignore", "pipe", "pipe"],
144
154
  });
145
- const result = analyzeGoMetadata(context, output);
155
+ const excluded = (file) => nestedRoots.some(root => file.startsWith(root));
156
+ const scopedContext = scoped ? { ...context, files: context.files.filter(file => !excluded(file)) } : context;
157
+ const result = analyzeGoMetadata(scopedContext, output);
158
+ if (scoped) {
159
+ context.profile.goExcludedModuleRoots = nestedRoots;
160
+ // A local replacement can make an excluded module part of the root module's build.
161
+ if (parseGoList(output).some(pkg => pkg.Module?.Replace?.Dir))
162
+ result.blockers.push("Go root-module scope with local replacements requires full validation");
163
+ }
146
164
  result.executionEnv = { GOOS: buildEnv.GOOS, GOARCH: buildEnv.GOARCH, CGO_ENABLED: buildEnv.CGO_ENABLED, GOFLAGS: "" };
147
165
  return result;
148
166
  }