supercov 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -20
  3. package/bin/supercov.js +10 -0
  4. package/dist/atomic.d.ts +6 -0
  5. package/dist/atomic.d.ts.map +1 -0
  6. package/dist/atomic.js +47 -0
  7. package/dist/atomic.js.map +1 -0
  8. package/dist/cli.js +431 -214
  9. package/dist/cli.js.map +1 -1
  10. package/dist/directInstrumenter.d.ts +8 -0
  11. package/dist/directInstrumenter.d.ts.map +1 -0
  12. package/dist/directInstrumenter.js +70 -0
  13. package/dist/directInstrumenter.js.map +1 -0
  14. package/dist/instrumenter.d.ts.map +1 -1
  15. package/dist/instrumenter.js +251 -41
  16. package/dist/instrumenter.js.map +1 -1
  17. package/dist/integrity.d.ts.map +1 -1
  18. package/dist/integrity.js +27 -0
  19. package/dist/integrity.js.map +1 -1
  20. package/dist/launchSupervisor.d.ts +24 -0
  21. package/dist/launchSupervisor.d.ts.map +1 -0
  22. package/dist/launchSupervisor.js +397 -0
  23. package/dist/launchSupervisor.js.map +1 -0
  24. package/dist/playwright.d.ts +0 -4
  25. package/dist/playwright.d.ts.map +1 -1
  26. package/dist/playwright.js +33 -17
  27. package/dist/playwright.js.map +1 -1
  28. package/dist/playwrightReporter.d.ts.map +1 -1
  29. package/dist/playwrightReporter.js +3 -2
  30. package/dist/playwrightReporter.js.map +1 -1
  31. package/dist/project.d.ts +5 -2
  32. package/dist/project.d.ts.map +1 -1
  33. package/dist/project.js +192 -27
  34. package/dist/project.js.map +1 -1
  35. package/dist/query.d.ts.map +1 -1
  36. package/dist/query.js +1 -0
  37. package/dist/query.js.map +1 -1
  38. package/dist/register.mjs +18 -13
  39. package/dist/register.mjs.map +1 -1
  40. package/dist/reporter.d.ts +4 -1
  41. package/dist/reporter.d.ts.map +1 -1
  42. package/dist/reporter.js +13 -11
  43. package/dist/reporter.js.map +1 -1
  44. package/dist/resolve-loader.d.mts.map +1 -1
  45. package/dist/resolve-loader.mjs +11 -3
  46. package/dist/resolve-loader.mjs.map +1 -1
  47. package/dist/runtime.d.ts +2 -2
  48. package/dist/runtime.d.ts.map +1 -1
  49. package/dist/runtime.js +35 -7
  50. package/dist/runtime.js.map +1 -1
  51. package/dist/transport.d.ts +2 -0
  52. package/dist/transport.d.ts.map +1 -1
  53. package/dist/transport.js +2 -0
  54. package/dist/transport.js.map +1 -1
  55. package/dist/types.d.ts +2 -1
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/vitePlugin.d.ts.map +1 -1
  58. package/dist/vitePlugin.js +4 -3
  59. package/dist/vitePlugin.js.map +1 -1
  60. package/dist/vitest.js +3 -2
  61. package/dist/vitest.js.map +1 -1
  62. package/dist/vitestReporter.d.ts +17 -2
  63. package/dist/vitestReporter.d.ts.map +1 -1
  64. package/dist/vitestReporter.js +51 -2
  65. package/dist/vitestReporter.js.map +1 -1
  66. package/dist/workspace.d.ts +46 -0
  67. package/dist/workspace.d.ts.map +1 -0
  68. package/dist/workspace.js +284 -0
  69. package/dist/workspace.js.map +1 -0
  70. package/package.json +30 -5
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Supercov contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -18,24 +18,51 @@ npm link
18
18
 
19
19
  ## Verifying the instrumenter
20
20
 
21
- The coverage engine has three independent test layers:
21
+ The coverage engine has seven independent release gates:
22
22
 
23
23
  - semantic differential fixtures execute original and instrumented programs
24
24
  in isolated scopes and compare return values, thrown errors, and observable
25
25
  side-effect order;
26
26
  - a deterministic generated corpus exercises 160 nested combinations of
27
27
  short-circuiting, ternaries, coercion, and thrown expressions on every run;
28
+ - seeded `fast-check` properties exercise another 500 generated nested
29
+ expressions and 300 generated control-flow executions, with shrinking and a
30
+ reproducible seed on failure;
28
31
  - coverage oracles assert exact decision vectors, MC/DC witnesses, and branch
29
- alternatives independently of program behavior.
32
+ alternatives independently of program behavior;
33
+ - the same three-condition masking-MC/DC golden cases must report 100% for a
34
+ complete witness set and 33.33% for an incomplete one under both Supercov
35
+ and Clang/LLVM source-based MC/DC;
36
+ - release CI shards the pinned TC39 Test262 corpus across 16 workers, runs the
37
+ official Test262 harness on original and instrumented sources, and rejects
38
+ any scenario that passes originally but fails after transformation; and
39
+ - checked performance budgets cover transform latency, output expansion, and
40
+ runtime probe overhead.
30
41
 
31
42
  ```sh
32
43
  npm test
44
+ npm run test:clang-mcdc
45
+ npm run benchmark:check
46
+ TEST262_DIR=/path/to/test262 npm run test:test262
33
47
  ```
34
48
 
35
49
  The differential suite includes getters, proxies, optional calls and `this`,
36
50
  computed logical assignments, defaults, `try`/`catch`/`finally`, iterator
37
51
  closing, switch fallthrough, labeled loops, async functions, and generators.
38
- Every generated failure prints its reproducible seed and expression.
52
+ The compatibility workflow additionally runs Node 22/24/25, Playwright
53
+ 1.55/current, Vite 5/current, Vitest 2/current, Chromium, Firefox, WebKit, and
54
+ modern JavaScript/JSX/TypeScript/TSX syntax fixtures. Test262's module, async,
55
+ raw, parse/resolution-negative, Annex B sloppy-script extension, and explicit
56
+ `Function.prototype.toString`/function-source-coercion tests are intentionally
57
+ excluded from the source-rewrite comparison, with reason counts printed for
58
+ every shard. Annex B does not apply to the Vite application modules Supercov
59
+ instruments; exact source reflection necessarily observes a source transform.
60
+ When application code directly coerces or observes a function's source,
61
+ Supercov leaves that function body uninstrumented and records a visible
62
+ `semantic-safety` completeness blocker. The release corpus covers every other eligible synchronous
63
+ script and runtime-negative scenario, while dedicated differential fixtures
64
+ cover async functions and generators. Every semantic-equivalence failure
65
+ blocks the trusted-publishing workflow.
39
66
 
40
67
  ## Agent query workflow
41
68
 
@@ -87,31 +114,99 @@ Text output is concise for an interactive agent; JSON is the stable machine
87
114
  interface that can later back hosted coverage tools without changing the
88
115
  stored schema.
89
116
 
90
- For a conventional Vite project, the CLI:
117
+ For a conventional Vite project, or a Node project with no build step, the
118
+ CLI:
91
119
 
92
- 1. creates ignored Vite, Vitest, and Playwright overlays under
93
- `.supercov/`;
120
+ 1. refreshes a stable isolated source namespace under
121
+ `.supercov/cache/instrumented-workspace/<project>/`, links the existing
122
+ dependency tree, and creates all Vite, Vitest, Playwright, and build output
123
+ only there; the stable path lets VM/container snapshot systems reuse a
124
+ coverage build without touching the application's ordinary build;
94
125
  2. inventories every `app/**/*.ts(x)` and `src/**/*.ts(x)` file for the
95
- denominator, then
96
- instruments modules loaded by Vite without changing the project's config;
97
- 3. redirects existing `@playwright/test` imports at module-load time and injects
98
- a Vitest setup through the child runner's generated config, without changing
99
- specs, imports, package scripts, or checked-in configs;
100
- 4. runs the exact command following `--`;
126
+ denominator, then instruments modules loaded by Vite without changing the
127
+ project's config; when no build script exists, it instruments only the
128
+ disposable source copy and supplies a module-format-neutral runtime through
129
+ the inherited Node preload;
130
+ 3. discovers the Playwright-compatible fixture provider, test export, and
131
+ additional named exports from the suite's existing imports, then redirects
132
+ that provider at module-load time; Vitest setup is injected through the
133
+ child runner's generated config;
134
+ 4. runs the exact command following `--`, propagating coverage through every
135
+ Node child process it launches;
101
136
  5. attributes every source hit and decision vector to its individual test,
102
137
  automatically wraps Playwright actions and assertions, and records the
103
138
  action/assertion phase responsible for each correlated hit; then merges
104
139
  server and browser evidence into HTML and JSON reports; and
105
- 6. restores an ordinary application build even after a failed test command.
140
+ 6. atomically publishes the evidence/report into `.supercov/` and retains only
141
+ the disposable isolated build namespace as a provider snapshot cache. The
142
+ ordinary application build is never read as an input, overwritten, or
143
+ rebuilt afterward.
144
+
145
+ Only `.supercov/` is modified in the user's checkout. A per-project lock
146
+ rejects overlapping runs before either can build. Run state is durably written
147
+ through preparing/building/testing/reporting/terminal phases; SIGINT, SIGTERM,
148
+ and SIGHUP are forwarded to the entire child process group. If the process is
149
+ killed without a cleanup opportunity, the next invocation marks the dead PID's
150
+ run abandoned and refreshes the isolated namespace before using it. Report,
151
+ evidence, and state writes use sibling-temp files, fsync, and atomic rename;
152
+ lock acquisition uses exclusive creation and fsync.
153
+
154
+ Retention is deterministic because UTC run IDs sort chronologically:
155
+
156
+ ```sh
157
+ npx supercov clean --keep 20
158
+ npx supercov clean --keep 20 --dry-run
159
+ ```
160
+
161
+ The cleanup command never removes an active workspace and never touches files
162
+ outside `.supercov/`.
106
163
 
107
164
  The automatic adapters currently support standard Playwright suites (ESM and
108
- CommonJS specs in arbitrary project directories), Vitest, and the Essential
109
- Apps isolated Playwright VM runner. A single command such as
110
- `supercov -- npm test` can collect Vitest and Playwright evidence into
111
- the same run. The application build must currently be Vite-based. Jest,
112
- `node:test`, non-Vite build systems, browser component runners, and distributed
113
- multi-host merging still require adapters; they are not silently reported as
114
- covered.
165
+ CommonJS specs in arbitrary project directories), project-owned Playwright
166
+ fixture packages, Vitest, no-build Node commands, and Node coordinators that
167
+ launch tests inside a mounted VM/container workspace. A single command such as
168
+ `supercov -- npm test` can collect Vitest and Playwright evidence into the same
169
+ run. No-build Node execution is retained as background/unattributed evidence
170
+ until a recognized test-runner adapter supplies exact test boundaries. Jest,
171
+ exact `node:test` attribution, non-Vite application builds, browser component
172
+ runners, and distributed multi-host merging still require adapters; they are
173
+ not silently reported as per-test coverage.
174
+
175
+ Remote execution discovery is structural rather than provider-specific. The
176
+ preload observes CommonJS exports for a static `build(options)` capability,
177
+ activates only when those options contain a host-to-guest mount that includes
178
+ the isolated project, scopes an existing cache/snapshot identity to the run's
179
+ source fingerprint, and follows the opaque returned object graph. A method
180
+ whose options contain `argv`, `cmd`, or `command` receives guest-translated
181
+ Supercov paths and a guest-valid Node preload. The execution log records this
182
+ process/capability graph but hashes long or multiline arguments so embedded
183
+ shell bodies and credentials are never persisted.
184
+
185
+ This first zero-edit mechanism has explicit boundaries. It follows Node child
186
+ processes, not arbitrary non-Node supervisors or a remote control plane that
187
+ never exposes launches to the local process. The remote SDK must currently be
188
+ visible through CommonJS loading, its build options must expose the workspace
189
+ mount, and its execution call must accept an environment. Pure-ESM executor
190
+ SDKs, positional-only remote exec APIs, and providers that hide all launch
191
+ state behind an RPC need additional interception layers. Supercov reports
192
+ missing evidence rather than claiming those paths are covered.
193
+
194
+ The public regression suite includes a provider-neutral opaque executor. Its
195
+ CommonJS SDK exposes only a static build capability, a host-to-guest mount,
196
+ an existing snapshot key, an opaque image/pool/machine chain, and an
197
+ argv-shaped execution method. CI requires Supercov to discover that structure,
198
+ scope the cache identity, translate paths and the Node preload into the guest,
199
+ run nested Vitest and Playwright commands, parse every concurrent trace shard,
200
+ and produce 100% fixture coverage. A separate clean-room gate packs the npm
201
+ tarball and invokes it through `npx` in a project with no build step, asserting
202
+ that no source or configuration file changes.
203
+
204
+ Before the isolated build, Supercov also compares the invoked npm/pnpm/yarn/bun
205
+ script with explicit string-valued `process.env` mode checks in the project's
206
+ build config. A semantic match such as `test:preview` and
207
+ `process.env.TEST_PREVIEW === "true"` activates that build-only flag and is
208
+ printed before the build. It never guesses values for unrelated environment
209
+ variables.
115
210
 
116
211
  Each test carries two independent provenance fields:
117
212
 
package/bin/supercov.js CHANGED
@@ -13,6 +13,16 @@ const child = spawn(
13
13
  },
14
14
  );
15
15
 
16
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
17
+ process.once(signal, () => {
18
+ try {
19
+ child.kill(signal);
20
+ } catch {
21
+ // The child may already have completed.
22
+ }
23
+ });
24
+ }
25
+
16
26
  child.on("error", (error) => {
17
27
  console.error("[supercov] failed to start", error);
18
28
  process.exitCode = 1;
@@ -0,0 +1,6 @@
1
+ import { type WriteFileOptions } from "node:fs";
2
+ /** Write a complete sibling file and atomically replace the destination. */
3
+ export declare function atomicWriteFileSync(path: string, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void;
4
+ /** Atomically publish a fully prepared file or directory and persist its entry. */
5
+ export declare function atomicRenameSync(source: string, destination: string): void;
6
+ //# sourceMappingURL=atomic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,gBAAgB,EACtB,MAAM,SAAS,CAAC;AAiBjB,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,eAAe,EACrC,OAAO,CAAC,EAAE,gBAAgB,GACzB,IAAI,CAmBN;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAI1E"}
package/dist/atomic.js ADDED
@@ -0,0 +1,47 @@
1
+ import { mkdirSync, openSync, closeSync, fsyncSync, renameSync, rmSync, writeFileSync, } from "node:fs";
2
+ import { randomUUID } from "node:crypto";
3
+ import { dirname } from "node:path";
4
+ function fsyncDirectory(path) {
5
+ try {
6
+ const directory = openSync(path, "r");
7
+ try {
8
+ fsyncSync(directory);
9
+ }
10
+ finally {
11
+ closeSync(directory);
12
+ }
13
+ }
14
+ catch {
15
+ // Some platforms (notably Windows) do not permit opening directories.
16
+ }
17
+ }
18
+ /** Write a complete sibling file and atomically replace the destination. */
19
+ export function atomicWriteFileSync(path, data, options) {
20
+ mkdirSync(dirname(path), { recursive: true });
21
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
22
+ let descriptor;
23
+ try {
24
+ descriptor = openSync(temporary, "wx", 0o600);
25
+ writeFileSync(descriptor, data, options);
26
+ fsyncSync(descriptor);
27
+ closeSync(descriptor);
28
+ descriptor = undefined;
29
+ renameSync(temporary, path);
30
+ // Persist the directory entry as well as the file contents on POSIX. Some
31
+ // platforms (notably Windows) do not permit opening directories, so file
32
+ // fsync + atomic rename remains the portable fallback there.
33
+ fsyncDirectory(dirname(path));
34
+ }
35
+ finally {
36
+ if (descriptor !== undefined)
37
+ closeSync(descriptor);
38
+ rmSync(temporary, { force: true });
39
+ }
40
+ }
41
+ /** Atomically publish a fully prepared file or directory and persist its entry. */
42
+ export function atomicRenameSync(source, destination) {
43
+ mkdirSync(dirname(destination), { recursive: true });
44
+ renameSync(source, destination);
45
+ fsyncDirectory(dirname(destination));
46
+ }
47
+ //# sourceMappingURL=atomic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic.js","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,UAAU,EACV,MAAM,EACN,aAAa,GAEd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,SAAS,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,IAAqC,EACrC,OAA0B;IAE1B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IAC/D,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9C,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,UAAU,GAAG,SAAS,CAAC;QACvB,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5B,0EAA0E;QAC1E,yEAAyE;QACzE,6DAA6D;QAC7D,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,IAAI,UAAU,KAAK,SAAS;YAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,WAAmB;IAClE,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAChC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;AACvC,CAAC"}