supercov 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -402
- package/docs/agent-loop.md +66 -124
- package/docs/cli.md +74 -87
- package/docs/coverage-model.md +79 -129
- package/docs/evidence.md +60 -91
- package/docs/getting-started.md +71 -97
- package/docs/performance.md +57 -106
- package/docs/supported-suites.md +82 -103
- package/docs/verification.md +49 -83
- package/docs/workspace-isolation.md +67 -115
- package/package.json +7 -7
- package/runtime/javascript/capability.js +19 -0
- package/runtime/javascript/register.mjs +5 -1
|
@@ -1,120 +1,72 @@
|
|
|
1
1
|
# Workspace isolation
|
|
2
2
|
|
|
3
|
-
Supercov
|
|
4
|
-
|
|
5
|
-
not write targets, and cleanup does not depend on a signal handler.
|
|
3
|
+
Supercov measures an instrumented copy of the project. It does not rewrite the
|
|
4
|
+
source tree you edit or the ordinary build output your project already owns.
|
|
6
5
|
|
|
7
|
-
##
|
|
6
|
+
## What Supercov may write
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
is below the project's `.supercov/` directory:
|
|
11
|
-
|
|
12
|
-
| Path | Lifetime |
|
|
8
|
+
| Location | Purpose |
|
|
13
9
|
| --- | --- |
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
| `
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
The intended architecture is capability-based rather than one mechanism for
|
|
78
|
-
every runner:
|
|
79
|
-
|
|
80
|
-
- Node [module customization hooks](https://nodejs.org/api/module.html#customization-hooks)
|
|
81
|
-
can return transformed source for ESM and CommonJS without changing files.
|
|
82
|
-
This is appropriate only when the observed loader chain preserves source
|
|
83
|
-
identity and source maps.
|
|
84
|
-
- Vite/Rollup-compatible tools should transform modules in their native plugin
|
|
85
|
-
graph and relocate every Supercov-added cache/output into `.supercov/`.
|
|
86
|
-
- A Node coordinator that later exposes an opaque VM/container mount can lazily
|
|
87
|
-
materialize the transactional physical fallback and replace only that mount.
|
|
88
|
-
- Native/non-Node compilers and remote control planes that never expose reads or
|
|
89
|
-
mounts need explicit adapters or the physical fallback. Supercov must report
|
|
90
|
-
this boundary instead of silently claiming coverage.
|
|
91
|
-
|
|
92
|
-
The command itself may create files that the same test command normally creates.
|
|
93
|
-
Supercov is responsible for ensuring that instrumentation, generated config,
|
|
94
|
-
manifests, evidence, and additional builds do not add writes outside
|
|
95
|
-
`.supercov/`.
|
|
96
|
-
|
|
97
|
-
## Release blockers for a copy-free mode
|
|
98
|
-
|
|
99
|
-
A copy-free path is not eligible as the default until its regression suite
|
|
100
|
-
proves all of the following:
|
|
101
|
-
|
|
102
|
-
- original and transformed programs remain semantically equivalent;
|
|
103
|
-
- ESM, CommonJS, TypeScript/transpiler, worker, and child-process loader chains
|
|
104
|
-
preserve exact source attribution;
|
|
105
|
-
- test/build configuration and source fingerprints refer to the original tree;
|
|
106
|
-
- output relocation cannot escape `.supercov/`, including plugin-defined
|
|
107
|
-
outputs;
|
|
108
|
-
- an opaque remote mount either receives a complete materialized fallback or is
|
|
109
|
-
rejected clearly;
|
|
110
|
-
- SIGINT, SIGTERM, SIGKILL simulation, concurrent `clean`, ENOSPC, and failed
|
|
111
|
-
rename/copy injection leave no source changes and recover deterministically;
|
|
112
|
-
- retained bytes and startup time are measurably lower than the transactional
|
|
113
|
-
reflink fallback.
|
|
114
|
-
|
|
115
|
-
Until those gates pass, the transactional physical namespace is the conservative
|
|
116
|
-
fallback rather than a temporary-directory mount whose cleanup must succeed.
|
|
117
|
-
|
|
118
|
-
The filesystem gate runs the transaction suite on Linux, macOS, and Windows,
|
|
119
|
-
including reflink/ordinary-copy behavior, internal links or junctions, ENOSPC,
|
|
120
|
-
failed renames, and forced-process-termination recovery.
|
|
10
|
+
| `.supercov/runs/<run-id>/` | Immutable completed runs |
|
|
11
|
+
| `.supercov/work/` | In-progress state and evidence staging |
|
|
12
|
+
| `.supercov/locks/` | Prevents overlapping run and cleanup operations |
|
|
13
|
+
| `supercov/workspace/<project>/` | Marker-protected isolated source and build cache |
|
|
14
|
+
|
|
15
|
+
Supercov owns these locations only when its exact marker is present. If the
|
|
16
|
+
project already contains a user-created `supercov/` directory, Supercov does
|
|
17
|
+
not adopt or delete it; it chooses a deterministic fallback location instead.
|
|
18
|
+
|
|
19
|
+
The managed directories contain their own gitignore rules so run evidence and
|
|
20
|
+
instrumented builds do not become normal repository changes.
|
|
21
|
+
|
|
22
|
+
## What remains untouched
|
|
23
|
+
|
|
24
|
+
Supercov does not intentionally edit:
|
|
25
|
+
|
|
26
|
+
- application source or tests;
|
|
27
|
+
- imports or dependency declarations;
|
|
28
|
+
- test-runner configuration or reporter lists;
|
|
29
|
+
- the project's ordinary build output; or
|
|
30
|
+
- files outside its marker-owned storage.
|
|
31
|
+
|
|
32
|
+
The wrapped test command can still create anything it normally creates. The
|
|
33
|
+
isolation guarantee applies to Supercov's additional instrumentation, evidence,
|
|
34
|
+
and build work—not to side effects authored into the command itself.
|
|
35
|
+
|
|
36
|
+
## Repeated runs
|
|
37
|
+
|
|
38
|
+
When source, configuration, dependencies, toolchain, and build mode match,
|
|
39
|
+
Supercov can reuse the isolated instrumented build. Test-only changes do not
|
|
40
|
+
force an unrelated application rebuild.
|
|
41
|
+
|
|
42
|
+
Workspace updates are prepared separately and published only when complete, so
|
|
43
|
+
a failed refresh does not replace the last complete cache with a partial one.
|
|
44
|
+
|
|
45
|
+
## Crashes and concurrent commands
|
|
46
|
+
|
|
47
|
+
One project can have one coverage or cleanup transaction at a time. A second
|
|
48
|
+
operation fails clearly instead of racing the first.
|
|
49
|
+
|
|
50
|
+
In-progress state records allow the next command to recover after interruption,
|
|
51
|
+
forced termination, or host restart. Unpublished staging data is discarded;
|
|
52
|
+
completed runs are published atomically and remain immutable.
|
|
53
|
+
|
|
54
|
+
## Cleanup
|
|
55
|
+
|
|
56
|
+
Preview cleanup before deleting local Supercov data:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
npx supercov clean --dry-run
|
|
60
|
+
npx supercov clean --keep 20
|
|
61
|
+
npx supercov clean
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Cleanup follows marker ownership and refuses to race an active run. It does not
|
|
65
|
+
scan for similarly named directories or delete paths supplied by run metadata.
|
|
66
|
+
|
|
67
|
+
## Containers and remote workspaces
|
|
68
|
+
|
|
69
|
+
When a suite launches a container or VM from a mounted workspace, Supercov uses
|
|
70
|
+
the isolated workspace as the source presented to that environment. If an
|
|
71
|
+
executor hides its launch or mount boundary, Supercov reports the limitation
|
|
72
|
+
instead of claiming that unseen code was measured.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"description": "Zero-edit, runner-aware coverage completeness for JavaScript test suites",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -68,12 +68,12 @@
|
|
|
68
68
|
"prepublishOnly": "npm run release:check"
|
|
69
69
|
},
|
|
70
70
|
"optionalDependencies": {
|
|
71
|
-
"@supercov/cli-darwin-arm64": "0.0.
|
|
72
|
-
"@supercov/cli-darwin-x64": "0.0.
|
|
73
|
-
"@supercov/cli-linux-arm64-gnu": "0.0.
|
|
74
|
-
"@supercov/cli-linux-arm64-musl": "0.0.
|
|
75
|
-
"@supercov/cli-linux-x64-gnu": "0.0.
|
|
76
|
-
"@supercov/cli-linux-x64-musl": "0.0.
|
|
71
|
+
"@supercov/cli-darwin-arm64": "0.0.23",
|
|
72
|
+
"@supercov/cli-darwin-x64": "0.0.23",
|
|
73
|
+
"@supercov/cli-linux-arm64-gnu": "0.0.23",
|
|
74
|
+
"@supercov/cli-linux-arm64-musl": "0.0.23",
|
|
75
|
+
"@supercov/cli-linux-x64-gnu": "0.0.23",
|
|
76
|
+
"@supercov/cli-linux-x64-musl": "0.0.23"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"@playwright/test": ">=1.55.0",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// The import seam instrumented sources use for capability discovery.
|
|
2
|
+
//
|
|
3
|
+
// Instrumented files import this module instead of the launch supervisor, so
|
|
4
|
+
// a browser bundle of instrumented code carries no Node built-ins -- vite's
|
|
5
|
+
// rollup pass fails hard on `node:fs` inside a browser target, and a Shopify
|
|
6
|
+
// extension build of an instrumented app was the field case. In Node,
|
|
7
|
+
// register.mjs binds the real implementation before any user module
|
|
8
|
+
// evaluates; in a browser there are no processes to supervise and the seam
|
|
9
|
+
// stays a pass-through.
|
|
10
|
+
const passthrough = (value) => value;
|
|
11
|
+
let implementation = passthrough;
|
|
12
|
+
|
|
13
|
+
export function __supercovBindCapabilityWrapper(wrap) {
|
|
14
|
+
implementation = wrap;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function wrapImportedCapability(value) {
|
|
18
|
+
return implementation(value);
|
|
19
|
+
}
|
|
@@ -9,8 +9,12 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
9
9
|
import Module, { register, syncBuiltinESMExports } from "node:module";
|
|
10
10
|
import { closeSync, openSync, unlinkSync } from "node:fs";
|
|
11
11
|
import { resolve } from "node:path";
|
|
12
|
-
import { installLaunchSupervisor } from "./launchSupervisor.js";
|
|
12
|
+
import { installLaunchSupervisor, wrapImportedCapability } from "./launchSupervisor.js";
|
|
13
|
+
import { __supercovBindCapabilityWrapper } from "./capability.js";
|
|
13
14
|
installLaunchSupervisor();
|
|
15
|
+
// Instrumented sources import the browser-safe capability seam; bind the
|
|
16
|
+
// real supervisor implementation before any user module evaluates.
|
|
17
|
+
__supercovBindCapabilityWrapper(wrapImportedCapability);
|
|
14
18
|
// Long-running commands are diagnosed without changing their runner's exit
|
|
15
19
|
// semantics. The first preloaded Node process atomically elects itself for the
|
|
16
20
|
// run and periodically reports public active-resource types. This deliberately
|