Files
iptvnator/docs/superpowers/plans/2026-07-25-coverage-integrity-runtime-boundaries.md
T
4gray 08b868d6c1 test(electron): harden runtime boundary coverage (#1267)
Adds contract-focused regression coverage for the Electron HTTP server,
remote-control events, settings events, and managed download paths, and makes
Tier A coverage fail closed when instrumentation fails or a runtime-owning
production file disappears from a project or from the merged Istanbul report.

The old `coverage:ci` exited 0 despite a `Failed to collect coverage`
diagnostic: libs/m3u-state/src/lib/effects.ts was simply absent from the merged
map. All 30 Tier A reports are now required, the merged map covers 710 files,
and effects.ts is reported as 0/159 instead of silently disappearing.

Also fixes remote static-file path containment for encoded, malformed, NUL,
POSIX and Win32-style traversal inputs, with behavior-preserving testability
seams.

Statements 69.27% -> 69.54%; http-server.ts 0% -> 90.21%,
remote-control.events.ts 0% -> 96.55%, settings.events.ts 59.25% -> 96.29%.
2026-07-26 22:27:50 +02:00

2004 lines
59 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Coverage Integrity And Electron Runtime Boundaries Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Make Tier A coverage fail closed and add meaningful regression coverage for the HTTP server, remote control, settings, and download-file Electron boundaries.
**Architecture:** A shared pure Node module classifies runtime-owning TypeScript, validates per-project Istanbul reports, scans child output for collection failures, and evaluates aggregate/per-file ratchets. Existing Electron contracts stay unchanged except for the TDD-backed rejection of a discovered static-path traversal escape; tests use real loopback/filesystem behavior where practical and mock only process, persistence, or native-shell boundaries.
**Tech Stack:** Node.js ESM and `node:test`, TypeScript compiler API, Istanbul coverage maps, Jest/ts-jest, Electron main-process IPC, Node HTTP streams, Angular Jest configuration, Nx, Playwright.
**Execution note (2026-07-26):** The branch was rebased onto
`origin/master` commit `7e8c2ccce16b71d72a64c45f1d96dd090dc8e077`
before the final ratchet run. A real-loopback HTTP regression exposed a Windows
double-leading-slash traversal escape; the implementation adds a tested pure
resolver and a user-facing Electron fix note. A final integrity follow-up also
validates the merged Istanbul map itself before evaluating its recomputed
summary and ratchets.
---
## Scope And File Map
Create:
- `tools/coverage/coverage-integrity.mjs` — shared source classification,
report validation, output scanning, and ratchet evaluation.
- `tools/coverage/coverage-integrity.test.mjs` — deterministic Node tests using
temporary source/report fixtures.
- `apps/electron-backend/src/app/server/http-server.spec.ts` — real loopback
and temporary-directory HTTP server contracts.
- `apps/electron-backend/src/app/events/remote-control.events.spec.ts` —
registered HTTP handler, IPC, status, validation, and size-limit contracts.
Modify:
- `tools/coverage/run-tier-a-coverage.mjs` — stream child output, detect
collection failures, require complete project reports.
- `tools/coverage/merge-coverage.mjs` — reject missing/invalid Tier A inputs
before touching merged output.
- `tools/coverage/coverage-health.mjs` — independently validate completeness
and ratchets.
- `tools/coverage/coverage-policy.json` — store achieved aggregate and
critical-file ratchets.
- `package.json` — run coverage-tool unit tests inside `coverage:ci`.
- `libs/m3u-state/tsconfig.spec.json` — use bundler resolution and include the
shared Electron window declaration so `effects.ts` instruments.
- `apps/electron-backend/src/app/server/http-server.ts` — optional static-root
and server-factory seam, port `0` support for loopback tests, and a tested
static-root containment resolver.
- `apps/electron-backend/src/app/events/remote-control.events.ts` — export the
class for isolated instances while preserving the default singleton.
- `apps/electron-backend/src/app/events/settings.events.spec.ts` — persistence,
normalization, remote-control reconciliation, and redaction contracts.
- `apps/electron-backend/src/app/events/database/downloads.events.spec.ts` —
managed-path checks before native shell access.
- `docs/architecture/validation-map.md` — canonical fail-closed and ratchet
maintenance workflow.
- `docs/superpowers/specs/2026-07-25-coverage-integrity-runtime-boundaries-design.md`
— retain the corrected Istanbul-rounded baseline values.
Do not modify:
- `apps/electron-backend/src/app/workers/database.worker.ts`;
- workspace dashboard or Stalker search production code;
- type-only/shared-interface source for percentage gain;
- `AGENTS.md` or `CLAUDE.md`, unless execution discovers that the implemented
commands contradict text already present there.
### Task 0: Rebase And Bootstrap Immediately Before Implementation
**Files:**
- Verify only: `package.json`
- Verify only: `pnpm-lock.yaml`
- Verify only: `tools/coverage/coverage-policy.json`
- [ ] **Step 1: Load the execution skills**
Read completely before code changes:
```text
using-superpowers
executing-plans
test-driven-development
electron-pro
typescript
angular-testing
iptvnator-nx-architecture
```
Use `systematic-debugging` before changing code in response to any unexpected
failure, and `verification-before-completion`, `release-notes`, and
`github-pr` during the final tasks.
- [ ] **Step 2: Confirm a clean branch and rebase onto fresh master**
Run:
```bash
git status --short --branch
git fetch origin master --prune
git rebase origin/master
git status --short --branch
git log -2 --oneline --decorate
```
Expected: the branch is `agent/coverage-integrity-runtime-boundaries`, the
rebase exits 0, and only the committed design/plan are ahead of the latest
`origin/master`. If master changed a scoped source, spec, Jest config, or
coverage tool, re-run the baseline checks below and update this plan's numeric
seed before implementation rather than resolving by assumption.
- [ ] **Step 3: Refresh locked dependencies and Nx discovery**
Run:
```bash
pnpm install --frozen-lockfile
pnpm nx show projects
pnpm nx show projects --withTarget test
```
Expected: all commands exit 0; the project list contains
`electron-backend`, `electron-backend-e2e`, and `m3u-state`; the lockfile stays
unchanged.
- [ ] **Step 4: Reconfirm the fresh baseline**
Run even when Step 2 reports no new master commits:
```bash
NX_SKIP_NX_CACHE=true pnpm run coverage:ci
```
Expected on unchanged
`7e8c2ccce16b71d72a64c45f1d96dd090dc8e077`: the command exits 0 while printing
`Failed to collect coverage` for `libs/m3u-state/src/lib/effects.ts`, and the
30 project reports merge 709 files while omitting that runtime-owning source.
The aggregate remains 69.27/58.92/67.44/69.57, with HTTP and remote control at
0%, settings at 16 / 27 (59.25%), and downloads at 69 / 147 (46.93%). Record
the fresh aggregate and selected-file values. If master changed them, replace
the numeric ratchet seed in Task 3; do not lower a baseline already present on
newer master.
### Task 1: Build And Unit-Test The Shared Coverage Integrity Module
**Files:**
- Create: `tools/coverage/coverage-integrity.test.mjs`
- Create: `tools/coverage/coverage-integrity.mjs`
- [ ] **Step 1: Write the failing source-classification and output-scanner tests**
Create `tools/coverage/coverage-integrity.test.mjs` with Node built-ins and
these contracts:
```javascript
import assert from 'node:assert/strict';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { afterEach, describe, it } from 'node:test';
import {
createCoverageOutputScanner,
evaluateCoverageRatchets,
hasRuntimeOwnedStatement,
validateProjectCoverage,
validateRequiredProjectReports,
} from './coverage-integrity.mjs';
const temporaryRoots = [];
afterEach(() => {
for (const root of temporaryRoots.splice(0)) {
rmSync(root, { recursive: true, force: true });
}
});
describe('hasRuntimeOwnedStatement', () => {
it('excludes type-only, import-only, and pure re-export source', () => {
assert.equal(
hasRuntimeOwnedStatement(
'import type { Settings } from "./settings";'
),
false
);
assert.equal(
hasRuntimeOwnedStatement('interface Settings { enabled: boolean }'),
false
);
assert.equal(
hasRuntimeOwnedStatement('export type Mode = "live" | "vod";'),
false
);
assert.equal(
hasRuntimeOwnedStatement('export { value } from "./value";'),
false
);
assert.equal(
hasRuntimeOwnedStatement('declare const injected: string;'),
false
);
});
it('includes emitted declarations and executable statements', () => {
assert.equal(
hasRuntimeOwnedStatement('export const enabled = true;'),
true
);
assert.equal(
hasRuntimeOwnedStatement(
'export class RuntimeBoundary { start() {} }'
),
true
);
assert.equal(hasRuntimeOwnedStatement('console.log("runtime");'), true);
});
});
describe('createCoverageOutputScanner', () => {
it('detects an ANSI-colored marker split across chunks', () => {
const scanner = createCoverageOutputScanner(128);
scanner.push('\u001b[31mFailed to collect');
scanner.push(' coverage from /workspace/effects.ts\u001b[39m');
assert.equal(scanner.collectionFailed, true);
});
it('keeps only a bounded rolling tail', () => {
const scanner = createCoverageOutputScanner(32);
scanner.push('x'.repeat(256));
assert.equal(scanner.tail.length, 32);
assert.equal(scanner.collectionFailed, false);
});
});
```
- [ ] **Step 2: Add failing temporary-report tests**
In the same file, add helpers that write one runtime source plus a synthetic
Istanbul entry:
```javascript
function makeProjectFixture() {
const workspaceRoot = mkdtempSync(
path.join(tmpdir(), 'iptvnator-coverage-integrity-')
);
temporaryRoots.push(workspaceRoot);
const sourceRoot = 'libs/example/src';
const projectRoot = 'libs/example';
const sourcePath = path.join(workspaceRoot, sourceRoot, 'runtime.ts');
const reportPath = path.join(
workspaceRoot,
'coverage',
projectRoot,
'coverage-final.json'
);
mkdirSync(path.dirname(sourcePath), { recursive: true });
mkdirSync(path.dirname(reportPath), { recursive: true });
writeFileSync(sourcePath, 'export const runtime = true;\n');
const project = {
name: 'example',
root: projectRoot,
sourceRoot,
};
return { project, reportPath, sourcePath, workspaceRoot };
}
function coverageEntry(filePath, hits = [0]) {
const statementMap = Object.fromEntries(
hits.map((_, index) => [
index,
{
start: { line: index + 1, column: 0 },
end: { line: index + 1, column: 28 },
},
])
);
const statementHits = Object.fromEntries(
hits.map((hit, index) => [index, hit])
);
return {
path: filePath,
statementMap,
fnMap: {},
branchMap: {},
s: statementHits,
f: {},
b: {},
};
}
describe('validateProjectCoverage', () => {
it('accepts a report containing every runtime-owning file', () => {
const fixture = makeProjectFixture();
writeFileSync(
fixture.reportPath,
JSON.stringify({
[fixture.sourcePath]: coverageEntry(fixture.sourcePath),
})
);
const result = validateProjectCoverage(fixture);
assert.deepEqual(result.errors, []);
assert.equal(result.report?.project.name, 'example');
});
it('reports a runtime-owning source omitted from a valid report', () => {
const fixture = makeProjectFixture();
writeFileSync(fixture.reportPath, '{}');
const result = validateProjectCoverage(fixture);
assert.equal(result.errors.length, 1);
assert.match(result.errors[0], /runtime\.ts/);
});
it('reports missing and invalid project reports', () => {
const missing = makeProjectFixture();
const invalid = makeProjectFixture();
writeFileSync(invalid.reportPath, '{ invalid json');
assert.match(
validateProjectCoverage(missing).errors[0],
/did not produce/
);
assert.match(
validateProjectCoverage(invalid).errors[0],
/invalid JSON/
);
});
it('requires every configured Tier A report', () => {
const fixture = makeProjectFixture();
const result = validateRequiredProjectReports({
projects: [fixture.project],
workspaceRoot: fixture.workspaceRoot,
});
assert.equal(result.reports.length, 0);
assert.match(result.errors[0], /example/);
});
});
```
- [ ] **Step 3: Add failing aggregate and critical-file ratchet tests**
Add:
```javascript
describe('evaluateCoverageRatchets', () => {
it('reports aggregate percentage regression', () => {
const errors = evaluateCoverageRatchets({
coverageData: {},
mergedSummary: {
statements: { covered: 68, total: 100, pct: 68 },
branches: { covered: 57, total: 100, pct: 57 },
functions: { covered: 67, total: 100, pct: 67 },
lines: { covered: 69, total: 100, pct: 69 },
},
ratchet: {
merged: {
statements: 68.86,
branches: 58.66,
functions: 67.19,
lines: 69.2,
},
criticalFiles: [],
},
workspaceRoot: '/workspace',
});
assert.equal(errors.length, 4);
assert.match(errors[0], /statements.*68.*68\.86/);
});
it('requires both covered statements and percentage for a critical file', () => {
const workspaceRoot = '/workspace';
const filePath = path.join(workspaceRoot, 'apps/runtime.ts');
const errors = evaluateCoverageRatchets({
coverageData: {
[filePath]: coverageEntry(filePath, [1, 0]),
},
mergedSummary: {
statements: { covered: 1, total: 1, pct: 100 },
branches: { covered: 0, total: 0, pct: 100 },
functions: { covered: 0, total: 0, pct: 100 },
lines: { covered: 1, total: 1, pct: 100 },
},
ratchet: {
merged: {
statements: 0,
branches: 0,
functions: 0,
lines: 0,
},
criticalFiles: [
{
path: 'apps/runtime.ts',
statements: {
minimumCovered: 2,
minimumPercent: 75,
},
},
],
},
workspaceRoot,
});
assert.equal(errors.length, 2);
assert.match(errors[0], /apps\/runtime\.ts/);
});
it('reports a critical file missing from merged coverage', () => {
const errors = evaluateCoverageRatchets({
coverageData: {},
mergedSummary: {
statements: { covered: 0, total: 0, pct: 100 },
branches: { covered: 0, total: 0, pct: 100 },
functions: { covered: 0, total: 0, pct: 100 },
lines: { covered: 0, total: 0, pct: 100 },
},
ratchet: {
merged: {
statements: 0,
branches: 0,
functions: 0,
lines: 0,
},
criticalFiles: [
{
path: 'apps/missing.ts',
statements: {
minimumCovered: 1,
minimumPercent: 0,
},
},
],
},
workspaceRoot: '/workspace',
});
assert.match(errors[0], /missing from merged coverage/);
});
});
```
- [ ] **Step 4: Run the Node tests to verify RED**
Run:
```bash
node --test tools/coverage/coverage-integrity.test.mjs
```
Expected: FAIL with `ERR_MODULE_NOT_FOUND` for
`tools/coverage/coverage-integrity.mjs`.
- [ ] **Step 5: Implement source classification and the bounded scanner**
Create `tools/coverage/coverage-integrity.mjs`. Use `unknown`-equivalent
runtime validation rather than trusting parsed JSON shapes. The core
classification and scanner must follow:
```javascript
import { createRequire } from 'node:module';
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
import path from 'node:path';
import ts from 'typescript';
const require = createRequire(import.meta.url);
const { createCoverageMap } = require('istanbul-lib-coverage');
export const COVERAGE_COLLECTION_FAILURE = 'Failed to collect coverage';
const ANSI_ESCAPE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
function toPosix(filePath) {
return filePath.split(path.sep).join('/');
}
function hasDeclareModifier(statement) {
const modifiers = ts.canHaveModifiers(statement)
? (ts.getModifiers(statement) ?? [])
: [];
return modifiers.some(
(modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword
);
}
export function hasRuntimeOwnedStatement(sourceText, fileName = 'source.ts') {
const source = ts.createSourceFile(
fileName,
sourceText,
ts.ScriptTarget.Latest,
true
);
return source.statements.some((statement) => {
if (hasDeclareModifier(statement)) {
return false;
}
return !(
ts.isImportDeclaration(statement) ||
ts.isImportEqualsDeclaration(statement) ||
ts.isInterfaceDeclaration(statement) ||
ts.isTypeAliasDeclaration(statement) ||
ts.isExportDeclaration(statement) ||
ts.isEmptyStatement(statement)
);
});
}
export function createCoverageOutputScanner(maxCharacters = 4096) {
let tail = '';
let collectionFailed = false;
return {
get collectionFailed() {
return collectionFailed;
},
get tail() {
return tail;
},
push(chunk) {
tail = `${tail}${String(chunk).replace(ANSI_ESCAPE, '')}`.slice(
-maxCharacters
);
if (tail.includes(COVERAGE_COLLECTION_FAILURE)) {
collectionFailed = true;
}
},
};
}
```
Add recursive enumeration with exactly these exclusions:
```javascript
function isExcludedSource(filePath) {
const file = toPosix(filePath);
return (
/\.(spec|test)\.ts$/.test(file) ||
file.endsWith('.d.ts') ||
file.endsWith('/test-setup.ts') ||
file.includes('/test-stubs/') ||
/\.generated\./.test(file) ||
file.includes('/environments/') ||
file.endsWith('/index.ts')
);
}
```
`runtimeOwningSourceFiles(workspaceRoot, sourceRoot)` must recursively read
only `.ts` files, apply `isExcludedSource`, parse the file, and return sorted
absolute paths whose source has a runtime-owned statement.
- [ ] **Step 6: Implement report validation**
Implement these stable return shapes:
```javascript
// validateProjectCoverage(...)
{
errors: string[],
report: undefined | {
data: Record<string, object>,
path: string,
project: object,
},
}
// validateRequiredProjectReports(...)
{
errors: string[],
reports: Array<{
data: Record<string, object>,
path: string,
project: object,
}>,
}
```
`validateProjectCoverage({ workspaceRoot, project })` must:
1. resolve `coverage/<project.root>/coverage-final.json`;
2. report a missing file using the project name and relative report path;
3. parse JSON and reject arrays, `null`, and invalid JSON;
4. normalize report keys with `path.resolve`;
5. compare them to `runtimeOwningSourceFiles`; and
6. emit one diagnostic per missing source, including project and relative
source path.
`validateRequiredProjectReports` must call it for every project and preserve
policy order in `reports`.
- [ ] **Step 7: Implement ratchet evaluation**
`evaluateCoverageRatchets` must:
- compare each merged metric with its numeric minimum;
- build an Istanbul map from `coverageData`;
- require every critical path to exist;
- obtain `fileCoverage.toSummary().toJSON().statements`;
- compare both `covered` and `pct`; and
- return diagnostics rather than exiting.
Use messages of the form:
```text
Merged statements coverage regressed: observed 68%, required at least 68.86%.
Critical coverage apps/runtime.ts statements covered regressed: observed 1, required at least 2.
Critical coverage apps/runtime.ts statements percent regressed: observed 50%, required at least 75%.
```
- [ ] **Step 8: Run the module tests to verify GREEN**
Run:
```bash
node --test tools/coverage/coverage-integrity.test.mjs
```
Expected: all classification, marker, report, and ratchet tests pass.
- [ ] **Step 9: Commit the pure integrity module**
Run:
```bash
git add \
tools/coverage/coverage-integrity.mjs \
tools/coverage/coverage-integrity.test.mjs
git commit -m "test(coverage): add integrity primitives"
```
Expected: one commit containing only the pure module and its Node tests.
### Task 2: Wire The Gate And Fix The Real `m3u-state` Instrumentation Failure
**Files:**
- Modify: `tools/coverage/run-tier-a-coverage.mjs`
- Modify: `tools/coverage/merge-coverage.mjs`
- Modify: `tools/coverage/coverage-health.mjs`
- Modify: `package.json`
- Modify: `libs/m3u-state/tsconfig.spec.json`
- [ ] **Step 1: Replace synchronous inherited child output with streamed scanning**
In `run-tier-a-coverage.mjs`, replace `spawnSync` with `spawn`, import
`createCoverageOutputScanner` and `validateProjectCoverage`, and add:
```javascript
async function runCoverageProject(project) {
const args = buildNxArgs(project);
console.log(`\n==> Collecting coverage for ${project.name}`);
console.log(`pnpm ${args.join(' ')}`);
const scanner = createCoverageOutputScanner();
const child = spawn('pnpm', args, {
cwd: workspaceRoot,
env: {
...process.env,
CI: process.env.CI ?? 'true',
NX_TASKS_RUNNER_DYNAMIC_OUTPUT: 'false',
},
stdio: ['inherit', 'pipe', 'pipe'],
});
for (const [stream, destination] of [
[child.stdout, process.stdout],
[child.stderr, process.stderr],
]) {
stream.on('data', (chunk) => {
scanner.push(chunk);
destination.write(chunk);
});
}
const result = await new Promise((resolve, reject) => {
child.once('error', reject);
child.once('close', (code, signal) => resolve({ code, signal }));
});
if (result.code !== 0 || result.signal) {
return result.code ?? 1;
}
if (scanner.collectionFailed) {
console.error(
`Coverage collection failed while testing ${project.name}.`
);
return 1;
}
const validation = validateProjectCoverage({
project,
workspaceRoot,
});
for (const error of validation.errors) {
console.error(`Error: ${error}`);
}
return validation.errors.length === 0 ? 0 : 1;
}
```
Replace the final `spawnSync` loop with top-level awaited sequential calls.
Exit immediately after a nonzero project result so later projects cannot hide
the failed owner.
- [ ] **Step 2: Make merge input fail closed before output mutation**
In `merge-coverage.mjs`, remove the `.filter(existsSync)` construction. Call:
```javascript
const validation = validateRequiredProjectReports({
projects: policy.unitCoverage.tierA,
workspaceRoot,
});
if (validation.errors.length > 0) {
for (const error of validation.errors) {
console.error(`Error: ${error}`);
}
process.exit(1);
}
const coverageInputs = validation.reports;
```
Perform this before `rmSync(outputDir, ...)`. Merge each `input.data` instead
of reopening its path. Log `coverageInputs.length`, which must be exactly 30
on the current policy.
- [ ] **Step 3: Add independent health validation**
In `coverage-health.mjs`:
- import `evaluateCoverageRatchets`, `validateMergedCoverage`,
`validateProjectCoverage`, and `validateRequiredProjectReports`;
- under `--require-report`, validate every Tier A report and append all
diagnostics to `errors`;
- without `--require-report`, validate only report files that actually exist,
treating invalid JSON or missing runtime source in a present report as an
error rather than printing 30 missing-report warnings;
- after loading merged `coverage-summary.json`, load and independently validate
merged `coverage-final.json` for every runtime-owning Tier A file;
- recompute the aggregate summary from the validated merged map, compare it
with the serialized summary, and evaluate
`policy.reporting.coverageRatchet` when the policy has one.
Do not change existing source-root/spec ownership checks, E2E tag warnings, or
changed-file warnings.
- [ ] **Step 4: Run targeted `m3u-state` coverage to verify the real RED**
Run:
```bash
node --test tools/coverage/coverage-integrity.test.mjs
pnpm run coverage:unit:ci -- --projects=m3u-state
```
Expected:
- Node tests PASS.
- Targeted coverage exits nonzero after relaying the existing TypeScript
diagnostics and reports `Coverage collection failed while testing
m3u-state`.
This is the real regression proof: before the runner wiring, the same Jest
failure exited 0.
- [ ] **Step 5: Align the `m3u-state` spec compiler configuration**
Replace `libs/m3u-state/tsconfig.spec.json` with:
```json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "preserve",
"target": "es2016",
"types": ["jest", "node"],
"moduleResolution": "bundler"
},
"files": ["src/test-setup.ts", "../../global.d.ts"],
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
```
This matches the working Angular services test compiler mode, lets TypeScript
honor Angular Material package exports, and includes the shared
`Window.electron` contract. Do not add a local fake Material declaration to
`m3u-state`.
- [ ] **Step 6: Add coverage-tool tests to `coverage:ci`**
In `package.json`, add:
```json
"coverage:tools:test": "node --test tools/coverage/coverage-integrity.test.mjs"
```
Change `coverage:ci` so it starts with:
```json
"coverage:ci": "pnpm run coverage:tools:test && pnpm run coverage:policy:check && pnpm run coverage:unit:ci && pnpm run coverage:merge && node tools/coverage/coverage-health.mjs --require-report"
```
- [ ] **Step 7: Verify targeted instrumentation is GREEN and complete**
Run:
```bash
pnpm run coverage:tools:test
pnpm nx test m3u-state --skip-nx-cache --runInBand
pnpm run coverage:unit:ci -- --projects=m3u-state
node --input-type=module -e 'import fs from "node:fs"; import path from "node:path"; const report=JSON.parse(fs.readFileSync("coverage/libs/m3u-state/coverage-final.json","utf8")); const target=path.resolve("libs/m3u-state/src/lib/effects.ts"); if (!report[target]) throw new Error(`${target} missing`); console.log("effects.ts present");'
```
Expected: all commands exit 0, no `Failed to collect coverage` appears, and
the final command prints `effects.ts present`.
- [ ] **Step 8: Commit the fail-closed runner and instrumentation fix**
Run:
```bash
git add \
package.json \
tools/coverage/run-tier-a-coverage.mjs \
tools/coverage/merge-coverage.mjs \
tools/coverage/coverage-health.mjs \
libs/m3u-state/tsconfig.spec.json
git commit -m "fix(coverage): fail on incomplete instrumentation"
```
Expected: one commit with the gate wiring and the real `effects.ts` fix.
### Task 3: Establish A Real Failing Critical-File Ratchet
**Files:**
- Modify but do not yet commit:
`tools/coverage/coverage-policy.json`
- [ ] **Step 1: Add the provisional ratchet**
Under `reporting`, add:
```json
"coverageRatchet": {
"merged": {
"statements": 68.86,
"branches": 58.66,
"functions": 67.19,
"lines": 69.2
},
"criticalFiles": [
{
"path": "apps/electron-backend/src/app/server/http-server.ts",
"statements": {
"minimumCovered": 1,
"minimumPercent": 0
}
},
{
"path": "apps/electron-backend/src/app/events/remote-control.events.ts",
"statements": {
"minimumCovered": 1,
"minimumPercent": 0
}
},
{
"path": "apps/electron-backend/src/app/events/settings.events.ts",
"statements": {
"minimumCovered": 17,
"minimumPercent": 59.25
}
},
{
"path": "apps/electron-backend/src/app/events/database/downloads.events.ts",
"statements": {
"minimumCovered": 70,
"minimumPercent": 46.93
}
}
]
}
```
The existing files use their fresh master percentage and require one
additional covered statement. The two 0% files require one covered statement.
These are minimal progress probes, not final thresholds.
- [ ] **Step 2: Verify the critical acceptance test is RED**
Use the fresh baseline reports from Task 0:
```bash
pnpm run coverage:merge
node tools/coverage/coverage-health.mjs --require-report
```
Expected: merge succeeds with exactly 30 reports; health exits nonzero and
names all selected files still below the provisional ratchet. In particular,
`http-server.ts` and `remote-control.events.ts` report zero covered
statements.
- [ ] **Step 3: Keep the provisional policy change unstaged**
Run:
```bash
git status --short
```
Expected: only `tools/coverage/coverage-policy.json` is intentionally dirty.
Do not stage it in Tasks 4–7; it remains the real red acceptance test until
the behavioral suites raise the observed values.
### Task 4: Cover The HTTP Server Through Real Loopback And Filesystem Contracts
**Files:**
- Create: `apps/electron-backend/src/app/server/http-server.spec.ts`
- Modify: `apps/electron-backend/src/app/server/http-server.ts`
- [ ] **Step 1: Write the complete HTTP contract suite before the seam exists**
The spec must:
- create a temporary static directory with `index.html`, `app.js`,
`styles.css`, `data.json`, and an unknown-extension asset;
- inject a real `http.createServer` wrapper that captures the Node server;
- call `start(0)`, await `listening`, and request
`127.0.0.1:<assigned-port>`;
- stop and remove the temporary tree in `afterEach`.
Use these test helpers:
```typescript
interface HttpResponseSnapshot {
body: Buffer;
contentType: string | undefined;
statusCode: number;
}
function request(
port: number,
requestPath: string,
method = 'GET'
): Promise<HttpResponseSnapshot> {
return new Promise((resolve, reject) => {
const req = http.request(
{
host: '127.0.0.1',
method,
path: requestPath,
port,
},
(res) => {
const chunks: Buffer[] = [];
res.on('data', (chunk: Buffer) => chunks.push(chunk));
res.on('end', () =>
resolve({
body: Buffer.concat(chunks),
contentType: res.headers['content-type'],
statusCode: res.statusCode ?? 0,
})
);
}
);
req.once('error', reject);
req.end();
});
}
```
Add assertions for:
1. `/` returns the exact index body as `text/html`;
2. `.js`, `.css`, `.json`, and an unknown extension return the expected MIME;
3. a client route falls back to the exact index body;
4. missing index returns plain-text 404;
5. a registered API handler receives the request and bypasses static serving;
6. unknown `/api/remote-control/...` returns JSON 404;
7. `/../../outside-secret.txt` never returns an outside file;
8. duplicate `start` creates/listens once;
9. disable stops the server; and
10. an enabled port change stops then starts once with the new port.
- [ ] **Step 2: Run the focused spec to verify RED**
Run:
```bash
pnpm nx test electron-backend \
--testPathPattern=http-server.spec.ts \
--runInBand
```
Expected: FAIL at TypeScript compilation because `HttpServer` does not yet
accept the injected `distPath` and `createServer` options, and `start(0)`
currently ignores port zero.
- [ ] **Step 3: Add the minimal constructor seam**
In `http-server.ts`, add flat types:
```typescript
type HttpServerFactory = (requestListener: http.RequestListener) => http.Server;
interface HttpServerOptions {
createServer?: HttpServerFactory;
distPath?: string;
}
```
Add a factory field and constructor:
```typescript
private readonly createServer: HttpServerFactory;
constructor(options: HttpServerOptions = {}) {
this.createServer =
options.createServer ??
((requestListener) => http.createServer(requestListener));
this.distPath = options.distPath ?? null;
}
```
Replace:
```typescript
if (port) {
```
with:
```typescript
if (port !== undefined) {
```
and replace the direct `http.createServer` call with `this.createServer`.
Leave the production singleton as:
```typescript
export const httpServer = new HttpServer();
```
No production caller passes port zero or constructor options, so normal
runtime behavior stays unchanged.
- [ ] **Step 4: Run HTTP tests and Electron coverage**
Run:
```bash
pnpm nx test electron-backend \
--testPathPattern=http-server.spec.ts \
--runInBand
pnpm run coverage:unit:ci -- --projects=electron-backend
pnpm run coverage:merge
node tools/coverage/coverage-health.mjs --require-report
```
Expected:
- the focused suite PASSes;
- `http-server.ts` is nonzero;
- health remains RED only for the not-yet-expanded selected boundaries and any
aggregate dip caused by adding `effects.ts`.
- [ ] **Step 5: Commit only the HTTP slice**
Run:
```bash
git add \
apps/electron-backend/src/app/server/http-server.ts \
apps/electron-backend/src/app/server/http-server.spec.ts
git commit -m "test(electron): cover remote HTTP server"
```
Expected: the provisional policy remains unstaged.
### Task 5: Cover Remote-Control HTTP, IPC, And Renderer Dispatch
**Files:**
- Create:
`apps/electron-backend/src/app/events/remote-control.events.spec.ts`
- Modify:
`apps/electron-backend/src/app/events/remote-control.events.ts`
- [ ] **Step 1: Write the isolated remote-control suite**
Mock only:
- `BrowserWindow.getAllWindows`;
- `ipcMain.handle` and `ipcMain.on`;
- `httpServer.registerRemoteControlHandler` and `httpServer.start`; and
- `store.get`.
Import a named `RemoteControlEvents` class and instantiate it in each test.
Capture registered handlers in maps. Use a `PassThrough` request for JSON body
tests and a response recorder with typed `writeHead`/`end` methods.
Use this complete exchange helper:
```typescript
interface ResponseSnapshot {
body: string;
headers: Record<string, string>;
statusCode: number;
}
function createExchange(method: string) {
const requestStream = new PassThrough();
Object.defineProperty(requestStream, 'method', { value: method });
let resolveResponse!: (snapshot: ResponseSnapshot) => void;
const snapshot: ResponseSnapshot = {
body: '',
headers: {},
statusCode: 0,
};
const completed = new Promise<ResponseSnapshot>((resolve) => {
resolveResponse = resolve;
});
const response = {
writeHead(statusCode: number, headers: Record<string, string>) {
snapshot.statusCode = statusCode;
snapshot.headers = headers;
return response;
},
end(body?: string) {
snapshot.body = body ?? '';
resolveResponse(snapshot);
return response;
},
};
return {
completed,
request: requestStream as unknown as http.IncomingMessage,
requestStream,
response: response as unknown as http.ServerResponse,
};
}
function getHttpHandler(path: string) {
const handler = mockRegisteredHttpHandlers.get(path);
if (!handler) {
throw new Error(`Expected remote-control HTTP handler for ${path}`);
}
return handler;
}
```
Add exact contract cases:
```typescript
it.each([
['/api/remote-control/channel/up', 'CHANNEL_CHANGE', { direction: 'up' }],
[
'/api/remote-control/channel/down',
'CHANNEL_CHANGE',
{ direction: 'down' },
],
[
'/api/remote-control/volume/up',
'REMOTE_CONTROL_COMMAND',
{ type: 'volume-up' },
],
[
'/api/remote-control/volume/down',
'REMOTE_CONTROL_COMMAND',
{ type: 'volume-down' },
],
[
'/api/remote-control/volume/toggle-mute',
'REMOTE_CONTROL_COMMAND',
{ type: 'volume-toggle-mute' },
],
] as const)(
'dispatches POST %s to the first renderer',
async (path, channel, payload) => {
const exchange = createExchange('POST');
getHttpHandler(path)(exchange.request, exchange.response);
exchange.requestStream.end();
const response = await exchange.completed;
expect(response.statusCode).toBe(200);
expect(response.body).toBe(JSON.stringify({ success: true }));
expect(mockWebContentsSend).toHaveBeenCalledWith(channel, payload);
}
);
```
Also test:
- all seven endpoint paths are registered;
- stored enabled/port starts HTTP once; disabled does not;
- GET on POST-only handlers and POST on status return 405 without dispatch;
- select-number accepts `7.9` and sends integer `7`;
- missing, zero, negative, `Infinity`, and nonnumeric values return 400;
- malformed JSON returns 400 and sends nothing;
- a 10,241-byte body returns 413, destroys the request, and sends nothing;
- partial status IPC updates merge with previous state and refresh
`updatedAt`;
- GET status returns that merged state; and
- no BrowserWindow logs a warning but does not throw.
- [ ] **Step 2: Run the focused spec to verify RED**
Run:
```bash
pnpm nx test electron-backend \
--testPathPattern=remote-control.events.spec.ts \
--runInBand
```
Expected: FAIL because `RemoteControlEvents` is not exported as a named class.
- [ ] **Step 3: Export the existing class without changing its singleton**
Change:
```typescript
class RemoteControlEvents {
```
to:
```typescript
export class RemoteControlEvents {
```
Keep:
```typescript
export default new RemoteControlEvents();
```
Do not change endpoint names, methods, payloads, body limit, stored defaults,
or renderer channels unless a correct regression assertion exposes an actual
defect. If that happens, invoke `systematic-debugging`, keep the failing test,
and document the separately justified behavior fix.
- [ ] **Step 4: Verify remote-control behavior and coverage**
Run:
```bash
pnpm nx test electron-backend \
--testPathPattern=remote-control.events.spec.ts \
--runInBand
pnpm run coverage:unit:ci -- --projects=electron-backend
pnpm run coverage:merge
node tools/coverage/coverage-health.mjs --require-report
```
Expected: the focused suite PASSes, `remote-control.events.ts` is nonzero, and
health no longer reports either formerly 0% selected file.
- [ ] **Step 5: Commit only the remote-control slice**
Run:
```bash
git add \
apps/electron-backend/src/app/events/remote-control.events.ts \
apps/electron-backend/src/app/events/remote-control.events.spec.ts
git commit -m "test(electron): cover remote control events"
```
Expected: the provisional policy remains unstaged.
### Task 6: Expand Settings Runtime Reconciliation Coverage
**Files:**
- Modify:
`apps/electron-backend/src/app/events/settings.events.spec.ts`
- Verify only:
`apps/electron-backend/src/app/events/settings.events.ts`
- [ ] **Step 1: Make the existing test harness deterministic**
Keep real `normalizeExternalPlayerArguments`. Add stable mocks:
```typescript
type SettingsUpdateHandler = (
event: unknown,
settings: Record<string, unknown>
) => void;
const mockStoreGet = jest.fn();
const mockStoreSet = jest.fn();
const mockUpdateSettings = jest.fn();
let handler: SettingsUpdateHandler;
```
Include every imported key in the store mock:
```typescript
EMBEDDED_MPV_FRAME_COPY: 'embeddedMpvFrameCopy',
MPV_PLAYER_ARGUMENTS: 'mpvPlayerArguments',
MPV_REUSE_INSTANCE: 'mpvReuseInstance',
VLC_PLAYER_ARGUMENTS: 'vlcPlayerArguments',
VLC_REUSE_INSTANCE: 'vlcReuseInstance',
store: {
get: mockStoreGet,
set: mockStoreSet,
},
```
In `beforeEach`, clear the handler map, reset modules and mocks, silence
`console.log`, import `./settings.events`, and retrieve the registered
`SETTINGS_UPDATE` handler. Preserve both existing credential-redaction tests.
- [ ] **Step 2: Confirm the provisional settings ratchet is RED before new cases**
Run:
```bash
node tools/coverage/coverage-health.mjs --require-report
```
Expected: settings reports fewer than the provisional 17 covered statements or
less than its retained 59.25% floor.
- [ ] **Step 3: Add normalization and defined-only persistence assertions**
Add:
```typescript
it('normalizes player arguments and preserves explicit false reuse flags', () => {
handler(
{},
{
mpvPlayerArguments: [' --screen=1 ', '', ' --hwdec=auto-safe '],
mpvReuseInstance: false,
vlcPlayerArguments: ' --fullscreen \n\n --no-video-title-show ',
vlcReuseInstance: false,
}
);
expect(mockStoreSet).toHaveBeenCalledWith(
'mpvPlayerArguments',
'--screen=1\n--hwdec=auto-safe'
);
expect(mockStoreSet).toHaveBeenCalledWith('mpvReuseInstance', false);
expect(mockStoreSet).toHaveBeenCalledWith(
'vlcPlayerArguments',
'--fullscreen\n--no-video-title-show'
);
expect(mockStoreSet).toHaveBeenCalledWith('vlcReuseInstance', false);
});
it('does not persist undefined settings', () => {
handler({}, {});
expect(mockStoreSet).not.toHaveBeenCalled();
expect(mockUpdateSettings).not.toHaveBeenCalled();
});
it('coerces the frame-copy startup preference to boolean', () => {
handler({}, { embeddedMpvFrameCopy: 1 });
expect(mockStoreSet).toHaveBeenCalledWith('embeddedMpvFrameCopy', true);
});
```
- [ ] **Step 4: Add partial remote-control reconciliation assertions**
Add two tests:
```typescript
it('uses the stored port when only remote-control enabled changes', () => {
mockStoreGet.mockImplementation((key: string) =>
key === 'remoteControlPort' ? 9988 : undefined
);
handler({}, { remoteControl: true });
expect(mockStoreSet).toHaveBeenCalledWith('remoteControl', true);
expect(mockStoreSet).not.toHaveBeenCalledWith(
'remoteControlPort',
expect.anything()
);
expect(mockUpdateSettings).toHaveBeenCalledWith(true, 9988);
});
it('uses stored enabled state when only the remote-control port changes', () => {
mockStoreGet.mockImplementation((key: string) =>
key === 'remoteControl' ? true : undefined
);
handler({}, { remoteControlPort: 9123 });
expect(mockStoreSet).toHaveBeenCalledWith('remoteControlPort', 9123);
expect(mockStoreSet).not.toHaveBeenCalledWith(
'remoteControl',
expect.anything()
);
expect(mockUpdateSettings).toHaveBeenCalledWith(true, 9123);
});
```
- [ ] **Step 5: Run settings tests and refresh Electron coverage**
Run:
```bash
pnpm nx test electron-backend \
--testPathPattern=settings.events.spec.ts \
--runInBand
pnpm run coverage:unit:ci -- --projects=electron-backend
pnpm run coverage:merge
node tools/coverage/coverage-health.mjs --require-report
```
Expected: all settings tests PASS; settings covered statements and percentage
are above the fresh master baseline. These are characterization tests for
unchanged behavior, so no production edit is expected.
- [ ] **Step 6: Commit only the settings spec**
Run:
```bash
git add apps/electron-backend/src/app/events/settings.events.spec.ts
git commit -m "test(electron): cover settings runtime updates"
```
Expected: the provisional policy remains unstaged.
### Task 7: Expand Download Managed-Path Security Coverage
**Files:**
- Modify:
`apps/electron-backend/src/app/events/database/downloads.events.spec.ts`
- Verify only:
`apps/electron-backend/src/app/events/database/downloads.events.ts`
- [ ] **Step 1: Add filesystem and shell spies to the existing harness**
Add:
```typescript
const mockExistsSync = jest.fn();
const mockOpenPath = jest.fn();
const mockShowItemInFolder = jest.fn();
```
Return the two shell spies from the existing Electron mock. Reset them in
`beforeEach`; make `mockOpenPath` resolve an empty string by default.
Before importing `downloads.events`, register:
```typescript
jest.doMock('node:fs', () => ({
existsSync: mockExistsSync,
}));
```
Add a database helper whose `limit(1)` returns either `[{ id: 42 }]`, `[]`, or
rejects:
```typescript
function mockManagedPath(result: 'managed' | 'unmanaged' | 'error') {
const limit =
result === 'error'
? jest.fn().mockRejectedValue(new Error('database unavailable'))
: jest
.fn()
.mockResolvedValue(result === 'managed' ? [{ id: 42 }] : []);
mockGetDatabase.mockResolvedValue({
select: jest.fn(() => ({
from: jest.fn(() => ({
where: jest.fn(() => ({ limit })),
})),
})),
});
}
```
- [ ] **Step 2: Confirm the provisional downloads ratchet is RED**
Run:
```bash
node tools/coverage/coverage-health.mjs --require-report
```
Expected: downloads is below the provisional 70-covered-statement target or
its retained 46.93% floor.
- [ ] **Step 3: Add the managed-path rejection cases**
For both `DOWNLOADS_REVEAL_FILE` and `DOWNLOADS_PLAY_FILE`, assert:
```typescript
it.each(['DOWNLOADS_REVEAL_FILE', 'DOWNLOADS_PLAY_FILE'])(
'%s rejects a path not owned by a download row',
async (channel) => {
mockManagedPath('unmanaged');
mockExistsSync.mockReturnValue(true);
await expect(
getHandler(channel)(null, '/tmp/unmanaged.mp4')
).resolves.toEqual({
error: 'File not found',
success: false,
});
expect(mockShowItemInFolder).not.toHaveBeenCalled();
expect(mockOpenPath).not.toHaveBeenCalled();
}
);
it.each(['DOWNLOADS_REVEAL_FILE', 'DOWNLOADS_PLAY_FILE'])(
'%s rejects a managed path missing on disk',
async (channel) => {
mockManagedPath('managed');
mockExistsSync.mockReturnValue(false);
await expect(
getHandler(channel)(null, '/downloads/missing.mp4')
).resolves.toEqual({
error: 'File not found',
success: false,
});
expect(mockShowItemInFolder).not.toHaveBeenCalled();
expect(mockOpenPath).not.toHaveBeenCalled();
}
);
```
- [ ] **Step 4: Add the authorized shell and database-failure cases**
Add one reveal success, one play success, and a parameterized database failure:
```typescript
it('reveals only a managed file that exists', async () => {
mockManagedPath('managed');
mockExistsSync.mockReturnValue(true);
await expect(
getHandler('DOWNLOADS_REVEAL_FILE')(null, '/downloads/movie.mp4')
).resolves.toEqual({ success: true });
expect(mockShowItemInFolder).toHaveBeenCalledWith('/downloads/movie.mp4');
});
it('opens only a managed file that exists', async () => {
mockManagedPath('managed');
mockExistsSync.mockReturnValue(true);
await expect(
getHandler('DOWNLOADS_PLAY_FILE')(null, '/downloads/movie.mp4')
).resolves.toEqual({ success: true });
expect(mockOpenPath).toHaveBeenCalledWith('/downloads/movie.mp4');
});
```
For the database-error cases, silence `console.error`, use
`mockManagedPath('error')`, expect the existing structured not-found response,
and assert neither shell spy ran.
- [ ] **Step 5: Run download tests and refresh Electron coverage**
Run:
```bash
pnpm nx test electron-backend \
--testPathPattern=downloads.events.spec.ts \
--runInBand
pnpm run coverage:unit:ci -- --projects=electron-backend
pnpm run coverage:merge
node tools/coverage/coverage-health.mjs --require-report
```
Expected: all existing destructive cleanup/pause/resume tests and all new
managed-path tests PASS. Downloads covered statements and percentage exceed
the fresh master values.
- [ ] **Step 6: Commit only the downloads spec**
Run:
```bash
git add \
apps/electron-backend/src/app/events/database/downloads.events.spec.ts
git commit -m "test(electron): cover managed download paths"
```
Expected: the provisional policy remains the only unstaged source change.
### Task 8: Record Achieved Ratchets And Document The Integrity Contract
**Files:**
- Modify:
`tools/coverage/coverage-policy.json`
- Modify:
`docs/architecture/validation-map.md`
- Modify:
`docs/superpowers/specs/2026-07-25-coverage-integrity-runtime-boundaries-design.md`
- Modify:
`docs/superpowers/plans/2026-07-25-coverage-integrity-runtime-boundaries.md`
- Create:
`.changes/electron-remote-static-paths.md`
- [ ] **Step 1: Generate a complete fresh candidate report**
Run:
```bash
NX_SKIP_NX_CACHE=true pnpm run coverage:ci
```
Expected: 30 Tier A reports, no `Failed to collect coverage`, no missing
runtime-owning files, and all four aggregate metrics at or above the fresh
master baseline. If any metric is lower, do not lower the baseline. Inspect
the approved boundary cases for a missing meaningful assertion, add that
failing assertion, and rerun the directly affected suite before repeating this
command.
- [ ] **Step 2: Print exact achieved aggregate and per-file values**
Run:
```bash
node --input-type=module <<'NODE'
import { createRequire } from 'node:module';
import fs from 'node:fs';
import path from 'node:path';
const require = createRequire(import.meta.url);
const { createCoverageMap } = require('istanbul-lib-coverage');
const data = JSON.parse(
fs.readFileSync('coverage/merged/coverage-final.json', 'utf8')
);
const map = createCoverageMap(data);
const targets = [
'apps/electron-backend/src/app/server/http-server.ts',
'apps/electron-backend/src/app/events/remote-control.events.ts',
'apps/electron-backend/src/app/events/settings.events.ts',
'apps/electron-backend/src/app/events/database/downloads.events.ts',
];
const criticalFiles = targets.map((file) => {
const statements = map
.fileCoverageFor(path.resolve(file))
.toSummary()
.toJSON().statements;
return {
path: file,
statements: {
minimumCovered: statements.covered,
minimumPercent: statements.pct,
},
};
});
const summary = map.getCoverageSummary().toJSON();
console.log(
JSON.stringify(
{
merged: {
statements: summary.statements.pct,
branches: summary.branches.pct,
functions: summary.functions.pct,
lines: summary.lines.pct,
},
criticalFiles,
},
null,
4
)
);
NODE
```
Expected: a complete `coverageRatchet` value with nonzero HTTP/remote values
and settings/download values no lower than their baseline. Copy this exact
JSON object over the provisional `reporting.coverageRatchet`; do not round
manually or retain the provisional one-statement probes.
- [ ] **Step 3: Verify the achieved ratchet passes and rejects regressions**
Run:
```bash
pnpm run coverage:health -- --require-report
node --test tools/coverage/coverage-integrity.test.mjs
```
Expected: both exit 0. The synthetic Node tests still prove below-ratchet
metrics, missing critical files, missing reports, and collection markers fail.
- [ ] **Step 4: Update the canonical validation map**
Under `## Coverage Tiers` in `docs/architecture/validation-map.md`, add:
```markdown
Tier A coverage is fail-closed. `coverage:unit:ci` relays Jest output but exits
nonzero on `Failed to collect coverage`, a missing/invalid project report, or
a runtime-owning production TypeScript file absent from that report.
`coverage:merge` requires every configured Tier A report before replacing the
merged output, and `coverage:health --require-report` repeats completeness plus
aggregate and critical-file ratchets.
Runtime-owning files are discovered from the TypeScript AST. Specs, declarations,
test setup/stubs, generated/environment files, `index.ts`, type-only files, and
pure re-export shims do not count as executable coverage inputs.
Ratchets live under `reporting.coverageRatchet` in
`tools/coverage/coverage-policy.json`. Update them only from a fresh full
`coverage:ci` report when every value stays level or rises; never lower a
ratchet to accept a regression. The only exception is a reviewed production
source shrink: `minimumCovered` may follow a lower statement total when the PR
identifies the removed executable statements and fresh coverage proves that
the file percentage, aggregate ratchets, and remaining behavioral coverage do
not decrease.
```
Also include `pnpm run coverage:tools:test` in the local coverage command block.
- [ ] **Step 5: Confirm documentation and release-note decisions**
Because the real-loopback regression exposed and fixed an observable Windows
static-path traversal escape, add `.changes/electron-remote-static-paths.md`:
```markdown
---
type: fix
area: electron
---
The desktop remote-control server now blocks crafted static paths from escaping
bundled web files on Windows.
```
Run:
```bash
pnpm exec prettier --check \
docs/architecture/validation-map.md \
docs/superpowers/specs/2026-07-25-coverage-integrity-runtime-boundaries-design.md \
docs/superpowers/plans/2026-07-25-coverage-integrity-runtime-boundaries.md \
.changes/electron-remote-static-paths.md
pnpm run release:notes:validate
```
Expected: both pass. The release note records the narrow user-visible security
fix; do not apply `no-release-note` in Task 10.
- [ ] **Step 6: Commit ratchets and docs**
Run:
```bash
git add \
tools/coverage/coverage-policy.json \
docs/architecture/validation-map.md \
docs/superpowers/specs/2026-07-25-coverage-integrity-runtime-boundaries-design.md \
docs/superpowers/plans/2026-07-25-coverage-integrity-runtime-boundaries.md \
.changes/electron-remote-static-paths.md
git commit -m "ci(coverage): ratchet runtime boundaries"
```
Expected: the provisional policy is replaced by achieved values, the security
fix has a valid release note, and the worktree becomes clean.
### Task 9: Run Fresh Validation And Audit The Final Diff
**Files:**
- Verify only: all changed files
- Verify only:
`apps/electron-backend-e2e/src/downloads.e2e.ts`
- Verify only:
`apps/electron-backend-e2e/src/remote-control.e2e.ts`
- Verify only:
`apps/electron-backend-e2e/src/settings.e2e.ts`
- [ ] **Step 1: Run targeted unit, lint, and type checks**
Run:
```bash
pnpm run coverage:tools:test
pnpm nx test electron-backend --skip-nx-cache --runInBand
pnpm nx test m3u-state --skip-nx-cache --runInBand
pnpm nx lint electron-backend --skip-nx-cache
pnpm nx lint m3u-state --skip-nx-cache
pnpm run typecheck:backend
```
Expected: every command exits 0; no Jest suite, lint rule, or backend type
check fails.
- [ ] **Step 2: Run the three existing Electron E2E contracts**
Run:
```bash
pnpm nx run electron-backend-e2e:e2e-ci--src/downloads.e2e.ts --skip-nx-cache
pnpm nx run electron-backend-e2e:e2e-ci--src/remote-control.e2e.ts --skip-nx-cache
pnpm nx run electron-backend-e2e:e2e-ci--src/settings.e2e.ts --skip-nx-cache
```
Expected: all targets PASS. These prove the real packaged-style Electron IPC,
native folder/download flow, remote loopback server, renderer command, and
settings persistence contracts beyond unit mocks.
- [ ] **Step 3: Build the production Electron target**
Run:
```bash
pnpm nx build electron-backend \
--configuration=production \
--skip-nx-cache
```
Expected: exit 0, including worker, web, and remote-control-web dependencies.
- [ ] **Step 4: Run final full coverage from scratch**
Run:
```bash
NX_SKIP_NX_CACHE=true pnpm run coverage:ci
```
Expected:
- all coverage-tool tests PASS;
- policy sees 30 Tier A projects;
- all 30 project reports are merged;
- `effects.ts` is present;
- no collection marker or runtime-owning source omission is reported;
- achieved aggregate and critical-file ratchets PASS.
- [ ] **Step 5: Inspect exact metrics and scoped diff**
Run:
```bash
git diff origin/master...HEAD --check
git diff --stat origin/master...HEAD
git diff --name-only origin/master...HEAD
git status --short --branch
```
Expected:
- no whitespace errors;
- only the files in this plan appear;
- no database worker, dashboard, Stalker search, type-only interface, lockfile,
AGENTS, or CLAUDE changes appear;
- the worktree is clean.
- [ ] **Step 6: Apply verification-before-completion**
Read and follow `verification-before-completion`. Record, without paraphrasing
away failures:
- exact unit suite/test counts;
- exact E2E results;
- lint/typecheck/build exit results;
- 30/30 Tier A report integrity;
- aggregate before/after;
- all selected-file before/after values;
- docs and release-note decisions.
Do not claim completion from cached or earlier output.
### Task 10: Recheck Master, Push, And Open The Draft PR
**Files:**
- Verify only: current branch history and GitHub PR metadata
- [ ] **Step 1: Recheck master before publication**
Run:
```bash
git fetch origin master --prune
git log --oneline HEAD..origin/master
```
Expected: no output. If master advanced, rebase, rerun dependency bootstrap and
all of Task 9, then refresh ratchets only upward before publication.
- [ ] **Step 2: Review conventional history**
Run:
```bash
git log --oneline origin/master..HEAD
git status --short --branch
```
Expected: concise conventional commits, including the design and plan docs,
with a clean worktree.
- [ ] **Step 3: Push the agent branch**
Run:
```bash
git push -u origin agent/coverage-integrity-runtime-boundaries
```
Expected: push succeeds and sets the upstream.
- [ ] **Step 4: Create a draft PR**
Read and follow `github-pr`. Create a draft targeting `master` with title:
```text
test(electron): harden runtime coverage integrity
```
The body must contain:
- fresh baseline commit and aggregate metrics;
- exact after metrics;
- selected-file before/after table;
- behavioral contracts for HTTP, remote control, settings, and downloads;
- the two behavior-preserving production seams;
- the `effects.ts` compiler/instrumentation correction;
- runner, merge, health, and ratchet behavior;
- exact validation commands/results;
- docs update;
- the Electron fix release note for Windows static-path containment; and
- deferred `database.worker.ts`, dashboard rails, and Stalker search.
Use:
```bash
gh pr create \
--draft \
--base master \
--head agent/coverage-integrity-runtime-boundaries \
--title "test(electron): harden runtime coverage integrity" \
--body-file -
```
Provide the fully populated body on standard input; do not leave metric or
validation placeholders.
- [ ] **Step 5: Verify release-note metadata**
Run:
```bash
gh pr view --json url,isDraft,headRefName,baseRefName,labels,files,commits,statusCheckRollup
```
Expected: the PR is draft, head/base are correct,
`.changes/electron-remote-static-paths.md` is included, `no-release-note` is
absent, and the command prints the PR URL.
- [ ] **Step 6: Return the exact handoff**
Return:
- draft PR URL;
- branch;
- final commit SHA;
- aggregate and selected-file before/after metrics;
- exact command results and any explicit environment-only skip;
- docs updated (`docs/architecture/validation-map.md`);
- release note added (`.changes/electron-remote-static-paths.md`) with no
`no-release-note` label;
- deferred zero-coverage follow-ups.