@codyswann/lisa 4.81.9 → 4.82.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 (87) hide show
  1. package/dist/cli/lisa-test-run-jest-merge.d.ts +11 -0
  2. package/dist/cli/lisa-test-run-jest-merge.d.ts.map +1 -0
  3. package/dist/cli/lisa-test-run-jest-merge.js +152 -0
  4. package/dist/cli/lisa-test-run-jest-merge.js.map +1 -0
  5. package/dist/cli/lisa-test-run-shard.d.ts +123 -0
  6. package/dist/cli/lisa-test-run-shard.d.ts.map +1 -0
  7. package/dist/cli/lisa-test-run-shard.js +333 -0
  8. package/dist/cli/lisa-test-run-shard.js.map +1 -0
  9. package/dist/cli/lisa-test-run.d.ts.map +1 -1
  10. package/dist/cli/lisa-test-run.js +38 -1
  11. package/dist/cli/lisa-test-run.js.map +1 -1
  12. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  13. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  14. package/dist/core/upstream-evidence-manifest.js +11 -1
  15. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  16. package/package.json +4 -4
  17. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-agy/plugin.json +1 -1
  20. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  23. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
  27. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
  31. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-expo-agy/plugin.json +1 -1
  34. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  48. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  55. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  62. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa-rails-agy/plugin.json +1 -1
  69. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
  73. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  75. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  76. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
  80. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  82. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  83. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
  87. package/scripts/two-channel-couplings.json +1 -1
@@ -0,0 +1,11 @@
1
+ import { type ShardReceipt } from "./lisa-test-run-shard.js";
2
+ /**
3
+ * Merge every shard's Jest coverage, write the configured reports, and check
4
+ * the project's `coverageThreshold` once over the merged map.
5
+ * @param argv - Payload argv the gate task handed `lisa-test-run`
6
+ * @param receipts - Every shard's receipt, complete and consistent
7
+ * @param cwd - Project directory
8
+ * @returns Process exit code: 0 when every floor holds
9
+ */
10
+ export declare function mergeJestShards(argv: readonly [string, ...string[]], receipts: readonly ShardReceipt[], cwd?: string): number;
11
+ //# sourceMappingURL=lisa-test-run-jest-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-jest-merge.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-jest-merge.ts"],"names":[],"mappings":"AAuBA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AA2IlC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACpC,QAAQ,EAAE,SAAS,YAAY,EAAE,EACjC,GAAG,GAAE,MAAsB,GAC1B,MAAM,CA4CR"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Merge Jest shard coverage and enforce the project floor once (#4479).
3
+ *
4
+ * Jest has no counterpart to `vitest --merge-reports`, so the merge is done
5
+ * here with the istanbul libraries Jest itself reports through. They are
6
+ * resolved from the project's own Jest install, not bundled with Lisa, so the
7
+ * coverage maps are read and written by the same library versions that
8
+ * produced them.
9
+ *
10
+ * Nothing about the project's coverage configuration is restated. `jest
11
+ * --showConfig` over the very argv the gate task ran resolves
12
+ * `coverageThreshold`, `coverageReporters` and `coverageDirectory` under the
13
+ * same environment — so `LISA_COVERAGE_SCOPE=unit` still selects the unit
14
+ * floor — and the merge writes the reporters the project configured, into the
15
+ * directory it configured, which is where the SonarCloud hand-off looks.
16
+ * @module cli/lisa-test-run-jest-merge
17
+ */
18
+ import { spawnSync } from "node:child_process";
19
+ import * as fs from "node:fs";
20
+ import { createRequire } from "node:module";
21
+ import * as path from "node:path";
22
+ import { env } from "node:process";
23
+ import { checkJestThresholds, runnerEntry, } from "./lisa-test-run-shard.js";
24
+ /** Largest `--showConfig` document accepted, in bytes. */
25
+ const SHOW_CONFIG_LIMIT = 64 * 1024 * 1024;
26
+ /**
27
+ * Resolve Jest's global coverage configuration for this exact command.
28
+ * @param argv - Payload argv the gate task handed `lisa-test-run`
29
+ * @param cwd - Project directory
30
+ * @returns Resolved coverage configuration
31
+ */
32
+ function showJestConfig(argv, cwd) {
33
+ const [command, ...args] = argv;
34
+ const shown = spawnSync(command, [...args, "--showConfig"], {
35
+ cwd,
36
+ encoding: "utf8",
37
+ maxBuffer: SHOW_CONFIG_LIMIT,
38
+ });
39
+ if (shown.status !== 0) {
40
+ throw new Error(`jest --showConfig exited ${shown.status ?? shown.signal}: ${shown.stderr}`);
41
+ }
42
+ return JSON.parse(shown.stdout)
43
+ .globalConfig;
44
+ }
45
+ /**
46
+ * The file a bare command name runs, found on PATH.
47
+ * @param command - Executable name or path
48
+ * @returns Real path of the executable, or undefined
49
+ */
50
+ function executablePath(command) {
51
+ const candidates = command.includes(path.sep)
52
+ ? [command]
53
+ : (env.PATH ?? "")
54
+ .split(path.delimiter)
55
+ .map(directory => path.join(directory, command));
56
+ const found = candidates.find(candidate => fs.existsSync(candidate));
57
+ return found === undefined ? undefined : fs.realpathSync(found);
58
+ }
59
+ /**
60
+ * Resolve one istanbul library from the project, falling back to the copy
61
+ * reachable from the Jest executable the gate task actually runs.
62
+ * @param name - Package name
63
+ * @param bases - Files to resolve from, in order
64
+ * @returns The loaded module
65
+ */
66
+ function load(name, bases) {
67
+ for (const base of bases) {
68
+ try {
69
+ return createRequire(base)(name);
70
+ }
71
+ catch {
72
+ // Next base: package managers that isolate dependencies hoist none.
73
+ }
74
+ }
75
+ throw new Error(`${name} is not resolvable from the project or its jest install; the shard merge needs the istanbul libraries jest reports with.`);
76
+ }
77
+ /**
78
+ * Every file the istanbul libraries may be resolved from.
79
+ * @param argv - Payload argv
80
+ * @param cwd - Project directory
81
+ * @returns Resolution bases in the order they are tried: the project, then
82
+ * `@jest/reporters` (which depends on istanbul directly) back up to Jest
83
+ */
84
+ function resolutionBases(argv, cwd) {
85
+ const entry = runnerEntry(argv);
86
+ const jest = entry === undefined ? undefined : executablePath(entry);
87
+ const chain = ["@jest/core", "@jest/reporters"].reduce((resolved, dependency) => {
88
+ const from = resolved.at(-1);
89
+ const next = from === undefined ? undefined : manifestFrom(from, dependency);
90
+ return next === undefined ? resolved : [...resolved, next];
91
+ }, jest === undefined ? [] : [jest]);
92
+ return [path.join(cwd, "package.json"), ...[...chain].reverse()];
93
+ }
94
+ /**
95
+ * Resolve one package's manifest from a file, or undefined when unreachable.
96
+ * @param from - File to resolve from
97
+ * @param dependency - Package name
98
+ * @returns The manifest path, or undefined
99
+ */
100
+ function manifestFrom(from, dependency) {
101
+ try {
102
+ return createRequire(from).resolve(`${dependency}/package.json`);
103
+ }
104
+ catch {
105
+ return undefined;
106
+ }
107
+ }
108
+ /**
109
+ * Merge every shard's Jest coverage, write the configured reports, and check
110
+ * the project's `coverageThreshold` once over the merged map.
111
+ * @param argv - Payload argv the gate task handed `lisa-test-run`
112
+ * @param receipts - Every shard's receipt, complete and consistent
113
+ * @param cwd - Project directory
114
+ * @returns Process exit code: 0 when every floor holds
115
+ */
116
+ export function mergeJestShards(argv, receipts, cwd = process.cwd()) {
117
+ // Decided from the RESOLVED config, not the receipts' command-line flag: a
118
+ // project with `collectCoverage: true` collects in every shard without
119
+ // passing --coverage, and its floor must still be enforced here.
120
+ const config = showJestConfig(argv, cwd);
121
+ if (!config.collectCoverage) {
122
+ process.stdout.write("lisa-test-run: the test command collects no coverage, so there is nothing to merge.\n");
123
+ return 0;
124
+ }
125
+ const bases = resolutionBases(argv, cwd);
126
+ const istanbul = {
127
+ coverage: load("istanbul-lib-coverage", bases),
128
+ report: load("istanbul-lib-report", bases),
129
+ reports: load("istanbul-reports", bases),
130
+ };
131
+ const map = istanbul.coverage.createCoverageMap({});
132
+ for (const receipt of receipts) {
133
+ const file = path.join(receipt.directory, "coverage", "coverage-final.json");
134
+ if (!fs.existsSync(file))
135
+ throw new Error(`shard ${receipt.index} left no coverage (${file}).`);
136
+ map.merge(JSON.parse(fs.readFileSync(file, "utf8")));
137
+ }
138
+ const context = istanbul.report.createContext({
139
+ dir: config.coverageDirectory,
140
+ coverageMap: map,
141
+ defaultSummarizer: "nested",
142
+ });
143
+ for (const reporter of config.coverageReporters) {
144
+ const [name, options] = typeof reporter === "string" ? [reporter, {}] : reporter;
145
+ istanbul.reports.create(name, options).execute(context);
146
+ }
147
+ const failures = checkJestThresholds(config.coverageThreshold, map.getCoverageSummary().toJSON());
148
+ for (const failure of failures)
149
+ process.stderr.write(`${failure}\n`);
150
+ return failures.length === 0 ? 0 : 1;
151
+ }
152
+ //# sourceMappingURL=lisa-test-run-jest-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-jest-merge.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-jest-merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /** `<index>/<total>` for one shard leg, e.g. `2/4`. */
2
+ export declare const SHARD_ENV = "LISA_TEST_SHARD";
3
+ /** Directory a shard leg writes its receipt and results into. */
4
+ export declare const SHARD_OUTPUT_ENV = "LISA_TEST_SHARD_OUTPUT";
5
+ /** Directory the merge leg downloaded every shard's results into. */
6
+ export declare const SHARD_MERGE_ENV = "LISA_TEST_SHARD_MERGE";
7
+ /** How many shards the merge leg must find. */
8
+ export declare const SHARD_TOTAL_ENV = "LISA_TEST_SHARD_TOTAL";
9
+ /** Every variable above, for stripping before the payload starts. */
10
+ export declare const SHARD_ENV_NAMES: readonly ["LISA_TEST_SHARD", "LISA_TEST_SHARD_OUTPUT", "LISA_TEST_SHARD_MERGE", "LISA_TEST_SHARD_TOTAL"];
11
+ /** File a shard leg leaves in its output directory. */
12
+ export declare const SHARD_RECEIPT = "lisa-shard-receipt.json";
13
+ /** The test runners this wrapper knows how to shard. */
14
+ export type ShardRunner = "jest" | "vitest";
15
+ /** One shard leg. */
16
+ export interface ShardLeg {
17
+ readonly kind: "shard";
18
+ readonly index: number;
19
+ readonly total: number;
20
+ readonly output: string;
21
+ }
22
+ /** The merge leg. */
23
+ export interface ShardMerge {
24
+ readonly kind: "merge";
25
+ readonly directory: string;
26
+ readonly total: number;
27
+ }
28
+ /** What this process was asked to be. */
29
+ export type ShardPlan = {
30
+ readonly kind: "none";
31
+ } | ShardLeg | ShardMerge;
32
+ /** One shard's receipt as read back by the merge. */
33
+ export interface ShardReceipt {
34
+ readonly index: number;
35
+ readonly total: number;
36
+ readonly runner: ShardRunner;
37
+ readonly coverage: boolean;
38
+ /** Directory the receipt was found in — the shard's own results. */
39
+ readonly directory: string;
40
+ }
41
+ /**
42
+ * Decide whether this process is a shard leg, the merge, or neither.
43
+ * @param env - Process environment
44
+ * @returns The plan; `none` when no shard variable is set
45
+ */
46
+ export declare function shardPlanFrom(env: Readonly<Record<string, string | undefined>>): ShardPlan;
47
+ /**
48
+ * The file a payload argv actually starts: the command itself, or — when the
49
+ * command is `node` — the first argument that is not a Node flag, so
50
+ * `node --max-old-space-size=6144 node_modules/jest/bin/jest.js` names Jest.
51
+ * A flag that takes its value as a separate argument is not special-cased;
52
+ * its value is taken for the entry, names no runner, and is refused loudly.
53
+ * @param argv - Payload argv
54
+ * @returns The entry, or undefined when `node` is given no script
55
+ */
56
+ export declare function runnerEntry(argv: readonly string[]): string | undefined;
57
+ /**
58
+ * Name the runner a payload argv starts, refusing anything else.
59
+ * @param argv - Payload argv
60
+ * @returns The runner
61
+ */
62
+ export declare function shardRunnerOf(argv: readonly string[]): ShardRunner;
63
+ /**
64
+ * Rewrite one payload argv into a single shard of itself.
65
+ * @param argv - Payload argv
66
+ * @param runner - Runner the argv starts
67
+ * @param leg - This shard leg
68
+ * @returns The shard's argv
69
+ */
70
+ export declare function shardArgv(argv: readonly [string, ...string[]], runner: ShardRunner, leg: ShardLeg): [string, ...string[]];
71
+ /**
72
+ * Leave the receipt that proves this leg ran only its slice.
73
+ * @param leg - This shard leg
74
+ * @param runner - Runner the leg starts
75
+ * @param argv - The payload argv before sharding
76
+ */
77
+ export declare function writeShardReceipt(leg: ShardLeg, runner: ShardRunner, argv: readonly string[]): void;
78
+ /**
79
+ * Read every shard's receipt, refusing an incomplete or inconsistent set.
80
+ * @param directory - Merge directory
81
+ * @param total - Expected shard count
82
+ * @returns Receipts in shard order
83
+ */
84
+ export declare function readShardReceipts(directory: string, total: number): readonly ShardReceipt[];
85
+ /**
86
+ * Turn the payload argv into Vitest's report merge over the gathered blobs.
87
+ * @param argv - Payload argv
88
+ * @param blobs - Directory holding every shard's blob
89
+ * @returns Merge argv
90
+ */
91
+ export declare function vitestMergeArgv(argv: readonly [string, ...string[]], blobs: string): [string, ...string[]];
92
+ /**
93
+ * Copy every shard's blob into one flat directory, which is the only layout
94
+ * `vitest --merge-reports` reads.
95
+ * @param receipts - Every shard's receipt
96
+ * @param into - Destination directory
97
+ */
98
+ export declare function gatherVitestBlobs(receipts: readonly ShardReceipt[], into: string): void;
99
+ /** One coverage metric's totals, as istanbul summarises it. */
100
+ export interface CoverageMetric {
101
+ readonly total: number;
102
+ readonly covered: number;
103
+ readonly pct: number;
104
+ }
105
+ /** Istanbul's summary of a coverage map. */
106
+ export type CoverageSummary = Readonly<Record<"lines" | "statements" | "functions" | "branches", CoverageMetric>>;
107
+ /** A Jest `coverageThreshold` object. */
108
+ export type JestThresholds = Readonly<Record<string, Readonly<Record<string, number>>>>;
109
+ /**
110
+ * Check merged coverage against the project's Jest `coverageThreshold`, with
111
+ * Jest's own semantics and wording: a positive number is a percentage floor, a
112
+ * negative one a ceiling on uncovered entities.
113
+ *
114
+ * Only the `global` key is supported. Path and glob keys select files by
115
+ * Jest's own matching, and reimplementing that here would be a second
116
+ * definition free to drift from the first, so a sharded run refuses them by
117
+ * name instead of approximating them.
118
+ * @param thresholds - Resolved `coverageThreshold`, or undefined
119
+ * @param summary - Merged coverage summary
120
+ * @returns Jest-worded failures; empty when every floor holds
121
+ */
122
+ export declare function checkJestThresholds(thresholds: JestThresholds | undefined, summary: CoverageSummary): readonly string[];
123
+ //# sourceMappingURL=lisa-test-run-shard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-shard.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-shard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Shard and merge planning for `lisa-test-run` (CodySwannGT/lisa#4479).
3
+ *
4
+ * `quality.yml` shards the unit suite by ENVIRONMENT, never by appending
5
+ * arguments to the project's gate task. The task is a package script whose
6
+ * shape Lisa does not know — `bun run test:cov` may reach the runner through
7
+ * two `$npm_execpath run` hops, and npm, yarn and bun each forward trailing
8
+ * arguments differently. The playwright workflow hit exactly that wall and
9
+ * stopped sharding declared tasks altogether. An environment variable survives
10
+ * every hop, and this wrapper is the one place that knows which runner it is
11
+ * about to start, so the runner-specific spelling lives here.
12
+ *
13
+ * A shard leg writes a receipt BEFORE its runner starts. The workflow refuses a
14
+ * leg that left none: a consumer still on a Lisa without this module, or a
15
+ * gate task that bypasses `lisa-test-run`, would otherwise run the WHOLE suite
16
+ * in every leg and report green N times — the sharded run would look healthy
17
+ * while proving nothing about the speed-up it was adopted for.
18
+ *
19
+ * Per-shard coverage floors are switched off, because a shard measures a slice
20
+ * of the suite against the whole source and fails any project-wide floor. The
21
+ * floor is enforced once, by the merge, over the union of every shard. Vitest
22
+ * enforces every threshold form its config declares at that merge; the Jest
23
+ * merge supports the `global` key only and refuses the rest by name.
24
+ * @module cli/lisa-test-run-shard
25
+ */
26
+ import * as fs from "node:fs";
27
+ import * as path from "node:path";
28
+ /** `<index>/<total>` for one shard leg, e.g. `2/4`. */
29
+ export const SHARD_ENV = "LISA_TEST_SHARD";
30
+ /** Directory a shard leg writes its receipt and results into. */
31
+ export const SHARD_OUTPUT_ENV = "LISA_TEST_SHARD_OUTPUT";
32
+ /** Directory the merge leg downloaded every shard's results into. */
33
+ export const SHARD_MERGE_ENV = "LISA_TEST_SHARD_MERGE";
34
+ /** How many shards the merge leg must find. */
35
+ export const SHARD_TOTAL_ENV = "LISA_TEST_SHARD_TOTAL";
36
+ /** Every variable above, for stripping before the payload starts. */
37
+ export const SHARD_ENV_NAMES = [
38
+ SHARD_ENV,
39
+ SHARD_OUTPUT_ENV,
40
+ SHARD_MERGE_ENV,
41
+ SHARD_TOTAL_ENV,
42
+ ];
43
+ /** File a shard leg leaves in its output directory. */
44
+ export const SHARD_RECEIPT = "lisa-shard-receipt.json";
45
+ const WHOLE_NUMBER = /^[1-9]\d*$/;
46
+ /**
47
+ * Read a variable, treating an empty value as unset.
48
+ * @param env - Process environment
49
+ * @param name - Variable name
50
+ * @returns The value, or undefined when unset or empty
51
+ */
52
+ function setting(env, name) {
53
+ const value = env[name];
54
+ return value === undefined || value === "" ? undefined : value;
55
+ }
56
+ /**
57
+ * Parse one shard leg's `<index>/<total>`.
58
+ * @param value - Raw `LISA_TEST_SHARD`
59
+ * @param output - Raw `LISA_TEST_SHARD_OUTPUT`
60
+ * @returns The shard leg
61
+ */
62
+ function shardLeg(value, output) {
63
+ const [index, total, ...rest] = value.split("/");
64
+ if (rest.length > 0 ||
65
+ index === undefined ||
66
+ total === undefined ||
67
+ !WHOLE_NUMBER.test(index) ||
68
+ !WHOLE_NUMBER.test(total) ||
69
+ Number(index) > Number(total)) {
70
+ throw new Error(`${SHARD_ENV} is ${JSON.stringify(value)}; it must be <index>/<total> with 1 <= index <= total.`);
71
+ }
72
+ if (output === undefined) {
73
+ throw new Error(`${SHARD_ENV} is set but ${SHARD_OUTPUT_ENV} is not, so this shard has nowhere to leave its receipt.`);
74
+ }
75
+ return { kind: "shard", index: Number(index), total: Number(total), output };
76
+ }
77
+ /**
78
+ * Decide whether this process is a shard leg, the merge, or neither.
79
+ * @param env - Process environment
80
+ * @returns The plan; `none` when no shard variable is set
81
+ */
82
+ export function shardPlanFrom(env) {
83
+ const shard = setting(env, SHARD_ENV);
84
+ const merge = setting(env, SHARD_MERGE_ENV);
85
+ if (shard !== undefined && merge !== undefined) {
86
+ throw new Error(`${SHARD_ENV} and ${SHARD_MERGE_ENV} are both set; a run is one shard or the merge, never both.`);
87
+ }
88
+ if (shard !== undefined)
89
+ return shardLeg(shard, setting(env, SHARD_OUTPUT_ENV));
90
+ if (merge === undefined)
91
+ return { kind: "none" };
92
+ const total = env[SHARD_TOTAL_ENV] ?? "";
93
+ if (!WHOLE_NUMBER.test(total)) {
94
+ throw new Error(`${SHARD_TOTAL_ENV} is ${JSON.stringify(total)}; the merge must be told how many shards to expect.`);
95
+ }
96
+ return { kind: "merge", directory: merge, total: Number(total) };
97
+ }
98
+ /**
99
+ * Whether one argv entry names a runner's executable or entry script.
100
+ * @param entry - argv entry
101
+ * @param runner - Runner name
102
+ * @returns True when the entry starts that runner
103
+ */
104
+ function names(entry, runner) {
105
+ if (entry === undefined)
106
+ return false;
107
+ const base = path.basename(entry);
108
+ return (base === runner ||
109
+ base === `${runner}.js` ||
110
+ base === `${runner}.mjs` ||
111
+ entry.includes(`node_modules/${runner}/`));
112
+ }
113
+ /**
114
+ * The file a payload argv actually starts: the command itself, or — when the
115
+ * command is `node` — the first argument that is not a Node flag, so
116
+ * `node --max-old-space-size=6144 node_modules/jest/bin/jest.js` names Jest.
117
+ * A flag that takes its value as a separate argument is not special-cased;
118
+ * its value is taken for the entry, names no runner, and is refused loudly.
119
+ * @param argv - Payload argv
120
+ * @returns The entry, or undefined when `node` is given no script
121
+ */
122
+ export function runnerEntry(argv) {
123
+ if (path.basename(argv[0] ?? "") !== "node")
124
+ return argv[0];
125
+ return argv.slice(1).find(arg => !arg.startsWith("-"));
126
+ }
127
+ /**
128
+ * Name the runner a payload argv starts, refusing anything else.
129
+ * @param argv - Payload argv
130
+ * @returns The runner
131
+ */
132
+ export function shardRunnerOf(argv) {
133
+ const entry = runnerEntry(argv);
134
+ const runner = ["jest", "vitest"].find(candidate => names(entry, candidate));
135
+ if (runner === undefined) {
136
+ throw new Error(`lisa-test-run cannot shard "${argv.join(" ")}": only jest and vitest commands can be sharded.`);
137
+ }
138
+ return runner;
139
+ }
140
+ /**
141
+ * Whether the payload collects coverage at all.
142
+ * @param argv - Payload argv
143
+ * @returns True when a coverage flag is present
144
+ */
145
+ function collectsCoverage(argv) {
146
+ return argv.some(arg => arg === "--coverage" ||
147
+ arg === "--coverage=true" ||
148
+ arg === "--collectCoverage" ||
149
+ arg === "--collectCoverage=true");
150
+ }
151
+ /**
152
+ * Rewrite one payload argv into a single shard of itself.
153
+ * @param argv - Payload argv
154
+ * @param runner - Runner the argv starts
155
+ * @param leg - This shard leg
156
+ * @returns The shard's argv
157
+ */
158
+ export function shardArgv(argv, runner, leg) {
159
+ const shard = `--shard=${leg.index}/${leg.total}`;
160
+ if (runner === "jest") {
161
+ return [
162
+ ...argv,
163
+ shard,
164
+ "--coverageReporters=json",
165
+ "--coverageThreshold={}",
166
+ `--coverageDirectory=${path.join(leg.output, "coverage")}`,
167
+ ];
168
+ }
169
+ return [
170
+ ...argv,
171
+ shard,
172
+ "--reporter=blob",
173
+ `--outputFile.blob=${path.join(leg.output, `blob-${leg.index}-${leg.total}.json`)}`,
174
+ // Every threshold off, not four zeroed metrics: glob, `perFile` and
175
+ // `100: true` thresholds survive zeroes and fail a partial shard. The
176
+ // merge (`--merge-reports`) still enforces the config's thresholds.
177
+ "--coverage.thresholds=false",
178
+ ];
179
+ }
180
+ /**
181
+ * Leave the receipt that proves this leg ran only its slice.
182
+ * @param leg - This shard leg
183
+ * @param runner - Runner the leg starts
184
+ * @param argv - The payload argv before sharding
185
+ */
186
+ export function writeShardReceipt(leg, runner, argv) {
187
+ fs.mkdirSync(leg.output, { recursive: true });
188
+ fs.writeFileSync(path.join(leg.output, SHARD_RECEIPT), `${JSON.stringify({
189
+ schema: 1,
190
+ index: leg.index,
191
+ total: leg.total,
192
+ runner,
193
+ coverage: collectsCoverage(argv),
194
+ })}\n`);
195
+ }
196
+ /**
197
+ * Find every receipt directly in, or one level under, the merge directory —
198
+ * which is where `download-artifact` puts one artifact per subdirectory.
199
+ * @param directory - Merge directory
200
+ * @returns Receipt paths
201
+ */
202
+ function receiptPaths(directory) {
203
+ const candidates = [
204
+ directory,
205
+ ...fs
206
+ .readdirSync(directory, { withFileTypes: true })
207
+ .filter(entry => entry.isDirectory())
208
+ .map(entry => path.join(directory, entry.name)),
209
+ ].map(candidate => path.join(candidate, SHARD_RECEIPT));
210
+ return candidates.filter(candidate => fs.existsSync(candidate));
211
+ }
212
+ /**
213
+ * Read one receipt file.
214
+ * @param file - Receipt path
215
+ * @returns The receipt
216
+ */
217
+ function readReceipt(file) {
218
+ const raw = JSON.parse(fs.readFileSync(file, "utf8"));
219
+ if (typeof raw.index !== "number" ||
220
+ typeof raw.total !== "number" ||
221
+ (raw.runner !== "jest" && raw.runner !== "vitest") ||
222
+ typeof raw.coverage !== "boolean") {
223
+ throw new Error(`${file} is not a unit-test shard receipt.`);
224
+ }
225
+ return {
226
+ index: raw.index,
227
+ total: raw.total,
228
+ runner: raw.runner,
229
+ coverage: raw.coverage,
230
+ directory: path.dirname(file),
231
+ };
232
+ }
233
+ /**
234
+ * Refuse a set of receipts that is not exactly shards 1..total of one run.
235
+ * @param receipts - Every receipt found
236
+ * @param total - Expected shard count
237
+ */
238
+ function assertCompleteShardSet(receipts, total) {
239
+ const foreign = receipts.find(receipt => receipt.total !== total);
240
+ if (foreign !== undefined) {
241
+ throw new Error(`shard ${foreign.index}/${foreign.total} belongs to a different layout; expected ${total} shards.`);
242
+ }
243
+ const indices = receipts.map(receipt => receipt.index);
244
+ const repeated = indices.find((index, position) => indices.indexOf(index) !== position);
245
+ if (repeated !== undefined)
246
+ throw new Error(`shard ${repeated} reported twice.`);
247
+ const seen = new Set(indices);
248
+ const missing = Array.from({ length: total }, (_, i) => i + 1).filter(index => !seen.has(index));
249
+ if (missing.length > 0) {
250
+ throw new Error(`expected ${total} unit-test shards but found ${seen.size}: missing shard ${missing.join(", ")}.`);
251
+ }
252
+ const runners = [...new Set(receipts.map(receipt => receipt.runner))];
253
+ if (runners.length > 1) {
254
+ throw new Error(`the shards ran different test runners (${runners.join(", ")}); they cannot be merged.`);
255
+ }
256
+ }
257
+ /**
258
+ * Read every shard's receipt, refusing an incomplete or inconsistent set.
259
+ * @param directory - Merge directory
260
+ * @param total - Expected shard count
261
+ * @returns Receipts in shard order
262
+ */
263
+ export function readShardReceipts(directory, total) {
264
+ const receipts = receiptPaths(directory).map(readReceipt);
265
+ assertCompleteShardSet(receipts, total);
266
+ return [...receipts].sort((left, right) => left.index - right.index);
267
+ }
268
+ /**
269
+ * Turn the payload argv into Vitest's report merge over the gathered blobs.
270
+ * @param argv - Payload argv
271
+ * @param blobs - Directory holding every shard's blob
272
+ * @returns Merge argv
273
+ */
274
+ export function vitestMergeArgv(argv, blobs) {
275
+ return [...argv, `--merge-reports=${blobs}`];
276
+ }
277
+ /**
278
+ * Copy every shard's blob into one flat directory, which is the only layout
279
+ * `vitest --merge-reports` reads.
280
+ * @param receipts - Every shard's receipt
281
+ * @param into - Destination directory
282
+ */
283
+ export function gatherVitestBlobs(receipts, into) {
284
+ fs.mkdirSync(into, { recursive: true });
285
+ for (const receipt of receipts) {
286
+ const blob = `blob-${receipt.index}-${receipt.total}.json`;
287
+ const source = path.join(receipt.directory, blob);
288
+ if (!fs.existsSync(source))
289
+ throw new Error(`shard ${receipt.index} left no vitest blob (${blob}).`);
290
+ fs.copyFileSync(source, path.join(into, blob));
291
+ }
292
+ }
293
+ /**
294
+ * Check merged coverage against the project's Jest `coverageThreshold`, with
295
+ * Jest's own semantics and wording: a positive number is a percentage floor, a
296
+ * negative one a ceiling on uncovered entities.
297
+ *
298
+ * Only the `global` key is supported. Path and glob keys select files by
299
+ * Jest's own matching, and reimplementing that here would be a second
300
+ * definition free to drift from the first, so a sharded run refuses them by
301
+ * name instead of approximating them.
302
+ * @param thresholds - Resolved `coverageThreshold`, or undefined
303
+ * @param summary - Merged coverage summary
304
+ * @returns Jest-worded failures; empty when every floor holds
305
+ */
306
+ export function checkJestThresholds(thresholds, summary) {
307
+ const keys = Object.keys(thresholds ?? {});
308
+ const unsupported = keys.find(key => key !== "global");
309
+ if (unsupported !== undefined) {
310
+ throw new Error(`coverageThreshold key ${JSON.stringify(unsupported)} cannot be checked across shards; only "global" thresholds are supported when unit_test_shards > 1.`);
311
+ }
312
+ const global = thresholds?.global ?? {};
313
+ return ["statements", "branches", "lines", "functions"].flatMap(metric => {
314
+ const threshold = global[metric];
315
+ if (threshold === undefined)
316
+ return [];
317
+ const actual = summary[metric];
318
+ if (threshold < 0) {
319
+ const uncovered = actual.total - actual.covered;
320
+ return -threshold < uncovered
321
+ ? [
322
+ `Jest: Uncovered count for ${metric} (${uncovered}) exceeds global threshold (${-threshold})`,
323
+ ]
324
+ : [];
325
+ }
326
+ return actual.pct < threshold
327
+ ? [
328
+ `Jest: "global" coverage threshold for ${metric} (${threshold}%) not met: ${actual.pct}%`,
329
+ ]
330
+ : [];
331
+ });
332
+ }
333
+ //# sourceMappingURL=lisa-test-run-shard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-shard.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-shard.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lisa-test-run.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run.ts"],"names":[],"mappings":";AAeA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC"}
1
+ {"version":3,"file":"lisa-test-run.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run.ts"],"names":[],"mappings":";AA6BA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC"}