supercov 0.0.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.
package/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # supercov
2
+
3
+ Zero-edit, runner-aware coverage-completeness command for JavaScript test
4
+ suites.
5
+
6
+ ```sh
7
+ npx supercov -- npm test
8
+ ```
9
+
10
+ For local development before publication, a Supercov contributor can expose
11
+ the checkout globally. Consumer repositories still remain untouched:
12
+
13
+ ```sh
14
+ # In the supercov repository.
15
+ npm install
16
+ npm link
17
+ ```
18
+
19
+ ## Verifying the instrumenter
20
+
21
+ The coverage engine has three independent test layers:
22
+
23
+ - semantic differential fixtures execute original and instrumented programs
24
+ in isolated scopes and compare return values, thrown errors, and observable
25
+ side-effect order;
26
+ - a deterministic generated corpus exercises 160 nested combinations of
27
+ short-circuiting, ternaries, coercion, and thrown expressions on every run;
28
+ - coverage oracles assert exact decision vectors, MC/DC witnesses, and branch
29
+ alternatives independently of program behavior.
30
+
31
+ ```sh
32
+ npm test
33
+ ```
34
+
35
+ The differential suite includes getters, proxies, optional calls and `this`,
36
+ computed logical assignments, defaults, `try`/`catch`/`finally`, iterator
37
+ closing, switch fallthrough, labeled loops, async functions, and generators.
38
+ Every generated failure prints its reproducible seed and expression.
39
+
40
+ ## Agent query workflow
41
+
42
+ Each run is stored locally as a compressed, immutable report under
43
+ `.supercov/runs/<run-id>/`. Its `report.json.gz`, `run.json`, and
44
+ `report.html` keep the machine report, run metadata, and human report together.
45
+ Agents should use bounded CLI queries instead of loading the complete report
46
+ into context.
47
+
48
+ ```sh
49
+ # Orient using only a few lines.
50
+ npx supercov runs --limit 5
51
+ npx supercov runs latest coverage
52
+ npx supercov runs latest coverage --filter passed
53
+ npx supercov runs latest coverage --filter failed
54
+ npx supercov runs latest coverage kinds
55
+ npx supercov runs latest coverage runners
56
+ npx supercov runs latest coverage --kind e2e
57
+ npx supercov runs latest coverage files
58
+ npx supercov runs latest coverage gaps --limit 10
59
+ npx supercov runs latest coverage gaps --kind e2e --limit 10
60
+
61
+ # Drill into one target selected from the gap list.
62
+ npx supercov runs latest coverage file app/routes/example.ts
63
+ npx supercov runs latest coverage decision app/routes/example.ts:42
64
+ npx supercov runs latest coverage covers app/routes/example.ts:57
65
+
66
+ # Understand redundancy/contribution and validate a newly written test. Replace
67
+ # "latest" with the immutable run ID when an agent continues work later.
68
+ npx supercov runs latest coverage test "test title fragment"
69
+ npx supercov diff <older-run> <newer-run>
70
+ ```
71
+
72
+ Coverage queries use `--filter all` by default, matching conventional coverage
73
+ tools: every executed attempt contributes, including attempts that later fail.
74
+ Use `--filter passed` for verified coverage from successful attempts of
75
+ ultimately passing tests, or `--filter failed` to inspect only execution from
76
+ failed attempts (including failed retries of flaky tests). Reports record
77
+ attempt status and classify each test as passed, failed, flaky, skipped, timed
78
+ out, interrupted, or unknown. The HTML equivalents are `report.html`,
79
+ `report-passed.html`, and `report-failed.html`.
80
+
81
+ The run ID is positional because all coverage queries operate on one immutable
82
+ run. `latest` is a convenience selector for interactive use. Every query
83
+ accepts `--json` and—where the result can be long—`--limit` and `--offset`.
84
+ Every collection is paginated at 20 items by default and prints its range plus
85
+ a copyable next-page command; generated commands omit the default limit.
86
+ Text output is concise for an interactive agent; JSON is the stable machine
87
+ interface that can later back hosted coverage tools without changing the
88
+ stored schema.
89
+
90
+ For a conventional Vite project, the CLI:
91
+
92
+ 1. creates ignored Vite, Vitest, and Playwright overlays under
93
+ `.supercov/`;
94
+ 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 `--`;
101
+ 5. attributes every source hit and decision vector to its individual test,
102
+ automatically wraps Playwright actions and assertions, and records the
103
+ action/assertion phase responsible for each correlated hit; then merges
104
+ server and browser evidence into HTML and JSON reports; and
105
+ 6. restores an ordinary application build even after a failed test command.
106
+
107
+ 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.
115
+
116
+ Each test carries two independent provenance fields:
117
+
118
+ - `runner`: the process that executed it, such as `playwright` or `vitest`;
119
+ - `kind`: its semantic level, such as `e2e`, `integration`, `component`, or
120
+ `unit`.
121
+
122
+ Kind is resolved in descending confidence from an explicit
123
+ `SUPERCOV_TEST_KIND`, Playwright project name, test path, then runner
124
+ default (Playwright is E2E; Vitest is unit). The report preserves how the label
125
+ was established, so an inferred kind is never presented as user-declared.
126
+ Vitest module-import/setup execution is retained as a separate setup scope,
127
+ not mislabeled as a test case.
128
+
129
+ Filtered queries recompute every obligation from the selected tests. MC/DC is
130
+ especially important: the command recomputes independence witness pairs rather
131
+ than filtering an already-computed percentage. Therefore a witness assembled
132
+ from one unit vector and one E2E vector counts for the combined suite but not
133
+ for either filtered subset. With `--kind e2e`, gap and file queries also
134
+ distinguish obligations covered only by other test levels from obligations
135
+ uncovered everywhere.
136
+
137
+ The JSON report contains both per-test and per-test-file coverage data. MC/DC
138
+ stores vector-level provenance rather than only a decision-level test list, so
139
+ a later suite minimizer can recompute valid independence pairs for any proposed
140
+ subset. This matters because the two vectors in a witness pair may come from
141
+ different tests.
142
+
143
+ The same report also contains an action/assertion trace without requiring spec
144
+ changes. Calls such as `page.goto()`, `locator.click()`, and `locator.fill()`
145
+ open action phases; Playwright `expect()` matchers open assertion phases. The
146
+ phase travels on browser requests into automatically wrapped Remix loaders,
147
+ actions, and the server document renderer. Node async context preserves that
148
+ ID through awaited helpers. An assertion also retains the preceding action ID,
149
+ making chains such as “click -> application lines/decisions -> visible
150
+ assertion” queryable in JSON and visible in HTML.
151
+
152
+ Server evidence is safe when Playwright uses multiple workers against one
153
+ application server. Every routed request carries a run/worker/test/retry scope;
154
+ Node async context retains that scope and its current phase across awaited
155
+ work. The server writes to a distinct attempt path, and the collecting fixture
156
+ accepts only records bearing that attempt ID. No worker deletes, reads, or
157
+ attributes another worker's live evidence file.
158
+
159
+ Detached work is never silently dropped or guessed onto the currently active
160
+ test. HTTP callbacks inherit the carrier automatically; child processes inherit
161
+ it through their environment; and exported queue helpers support BullMQ,
162
+ Bee-Queue, pg-boss, Agenda, and in-process schedulers. Evidence that arrives
163
+ without a carrier is persisted under a first-class `background/unattributed`
164
+ scope. It is visible in the all-attempt report and excluded from passed-only
165
+ per-test coverage.
166
+
167
+ The Playwright adapter covers the page and request fixtures, API request
168
+ contexts, user-created browser contexts/pages, popups and all their frames,
169
+ dedicated/service workers, WebSocket handshake headers, and test-spawned child
170
+ processes. A two-worker generic fixture exercises these surfaces without
171
+ changing its test imports or Playwright config.
172
+
173
+ Every run stores SHA-256 fingerprints for source, tests, dependency lockfiles,
174
+ test/build configuration, and the instrumenter, plus its report schema and Git
175
+ revision/dirty state. Queries compare the stored fingerprint with the current
176
+ workspace, visibly mark stale runs, and reject evidence carrying a different
177
+ run scope.
178
+
179
+ For Chromium documents exposed through the page target, a pre-document probe
180
+ also installs the phase before application JavaScript starts. Chromium may run
181
+ a newly created cross-origin iframe in a separate target that cannot be safely
182
+ paused and attached during navigation; its earliest browser probes use the
183
+ timing fallback until the frame is live. This affects only action-level causal
184
+ precision, not structural coverage or exact test-case provenance.
185
+
186
+ Code reached outside a recognized Playwright action, such as setup work or a
187
+ project-specific helper that performs HTTP requests directly, still has exact
188
+ test-case attribution but may not have an explicit action-phase ID. The report
189
+ labels explicit browser/server events separately from events assigned by the
190
+ isolated VM's timing fallback. Only explicit phases can raise confidence to
191
+ `asserted`; a timing-correlated event remains execution-only. Each line, point,
192
+ branch alternative, vector, and MC/DC condition therefore distinguishes
193
+ unexecuted, executed, action-linked, and assertion-linked evidence, as well as
194
+ unit-only versus E2E coverage.
195
+
196
+ The v2 denominator additionally measures optional-chain short-circuiting,
197
+ logical assignments, parameter/destructuring defaults, try versus catch,
198
+ zero versus entered `for-in`/`for-of`, and implicit switch no-match. Direct
199
+ `eval`/`Function` source cannot receive a stable pre-run denominator; when such
200
+ code is discovered the report records its exact location as a completeness
201
+ blocker instead of allowing a misleading 100% verdict.
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawn } from "node:child_process";
4
+ import { createRequire } from "node:module";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const cli = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
8
+ const require = createRequire(import.meta.url);
9
+ const tsx = require.resolve("tsx");
10
+ const child = spawn(
11
+ process.execPath,
12
+ ["--import", tsx, cli, ...process.argv.slice(2)],
13
+ {
14
+ stdio: "inherit",
15
+ env: process.env,
16
+ },
17
+ );
18
+
19
+ child.on("error", (error) => {
20
+ console.error("[supercov] failed to start", error);
21
+ process.exitCode = 1;
22
+ });
23
+ child.on("exit", (code, signal) => {
24
+ if (signal) process.kill(process.pid, signal);
25
+ else process.exitCode = code ?? 1;
26
+ });
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "supercov",
3
+ "version": "0.0.0",
4
+ "description": "Zero-edit, runner-aware coverage completeness for JavaScript test suites",
5
+ "type": "module",
6
+ "files": [
7
+ "bin",
8
+ "src",
9
+ "README.md"
10
+ ],
11
+ "engines": {
12
+ "node": ">=22"
13
+ },
14
+ "bin": {
15
+ "supercov": "bin/supercov.js"
16
+ },
17
+ "exports": {
18
+ "./playwright": "./src/playwright.ts",
19
+ "./register": "./src/register.mjs",
20
+ "./vite": "./src/vitePlugin.ts",
21
+ "./vitest": "./src/vitest.ts"
22
+ },
23
+ "scripts": {
24
+ "test": "vitest run tests/unit",
25
+ "test:types": "tsc --noEmit",
26
+ "test:fixture": "npm --prefix tests/fixtures/generic-playwright run test:coverage",
27
+ "check": "npm run test && npm run test:types",
28
+ "prepublishOnly": "npm run check"
29
+ },
30
+ "dependencies": {
31
+ "@babel/generator": "^8.0.0",
32
+ "@babel/parser": "^8.0.4",
33
+ "@babel/traverse": "^8.0.4",
34
+ "@babel/types": "^8.0.4",
35
+ "tsx": "^4.20.6"
36
+ },
37
+ "peerDependencies": {
38
+ "@playwright/test": ">=1.50.0",
39
+ "vite": ">=5.0.0",
40
+ "vitest": ">=2.0.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "@playwright/test": {
44
+ "optional": true
45
+ },
46
+ "vitest": {
47
+ "optional": true
48
+ }
49
+ },
50
+ "devDependencies": {
51
+ "@playwright/test": "1.62.1",
52
+ "@types/node": "^24.0.0",
53
+ "typescript": "7.0.2",
54
+ "vite": "8.2.2",
55
+ "vitest": "4.1.11"
56
+ }
57
+ }