Files
iptvnator/docs/superpowers/plans/2026-07-25-coverage-integrity-runtime-boundaries.md
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

59 KiB
Raw Permalink Blame History

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

// 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:

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:

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:

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:

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:

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:

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:

{
    "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:

"coverage:tools:test": "node --test tools/coverage/coverage-integrity.test.mjs"

Change coverage:ci so it starts with:

"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:

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:

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:

"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:

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:

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:

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:

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:

type HttpServerFactory = (requestListener: http.RequestListener) => http.Server;

interface HttpServerOptions {
    createServer?: HttpServerFactory;
    distPath?: string;
}

Add a factory field and constructor:

private readonly createServer: HttpServerFactory;

constructor(options: HttpServerOptions = {}) {
    this.createServer =
        options.createServer ??
        ((requestListener) => http.createServer(requestListener));
    this.distPath = options.distPath ?? null;
}

Replace:

if (port) {

with:

if (port !== undefined) {

and replace the direct http.createServer call with this.createServer. Leave the production singleton as:

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:

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:

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:

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:

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:

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:

class RemoteControlEvents {

to:

export class RemoteControlEvents {

Keep:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

jest.doMock('node:fs', () => ({
    existsSync: mockExistsSync,
}));

Add a database helper whose limit(1) returns either [{ id: 42 }], [], or rejects:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

---
type: fix
area: electron
---

The desktop remote-control server now blocks crafted static paths from escaping
bundled web files on Windows.

Run:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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.