super super/docs/app/PROPOSAL_TEST_RUNNER_2026_09_08.md
tools/proposal-test-runner.mjs REPOSITORY REVIEW_ATTEMPT_JSON EXISTING_RUN_DIRECTORY runs the initial super-javascript-behavior@1 profile. Invoke it with Node. This is a local h…

Proposal test executor foundation — 2026-09-08

tools/proposal-test-runner.mjs REPOSITORY REVIEW_ATTEMPT_JSON EXISTING_RUN_DIRECTORY runs the initial super-javascript-behavior@1 profile. Invoke it with Node. This is a local human-operated command, not a cockpit action, runtime validation job, signed attestation, or acceptance operation. No agent-facing authority was added.

The runner verifies a selected-file review's content digests, basis identity, committed HEAD and current disk identity. It captures regular files listed by Git (tracked plus untracked, honoring ignores for untracked files), detects changes with a second capture, then overlays the proposed text in a separate directory. The manifest identifies every captured path, mode, byte length and digest; its digest identifies the tested result tree. HEAD is context, not a claim that the dirty working tree equals that commit. Ignored/unlisted files are outside the snapshot. Deleted tracked files, symlinks and submodules currently refuse. Capture is not a filesystem-atomic snapshot.

The initial profile invokes the copied Node executable directly with --test --test-reporter=tap on captured tools/*-test.mjs files. There is no shell command interpolation, dependency installation or network access. Bubblewrap provides a read-only source mount, isolated process/network namespaces, empty environment, temporary scratch space and no host home directory. System /usr is read-only but shared; the Node executable is hashed and copied, while system libraries are not content-pinned. This Linux profile needs /usr/bin/bwrap, /usr/bin/git, Node, and working user namespaces. It never falls back to an unisolated run.

Limits: 1–1024 source files, 2 MiB per file, 32 MiB total, 64 test files, 100–120000 ms execution timeout (default 30 seconds), 128 KiB combined output. Timeout kills the process group. Output is truncated explicitly; when the terminal test summary is unavailable the result is an execution failure, not an inferred pass. These are source/output/time limits, not hard process-memory or CPU quotas.

started.json is saved before launch. outcome.json separates completed pass/fail from timeout, launch/termination and runner failures. The local record includes exact proposed-file and full-snapshot identities, test paths, Node identity, output and timestamps. A start without outcome remains unfinished history after a host crash. These records have not been admitted into Ampd's authority-managed validation ledger.

The source snapshot and manifest remain in the run directory for review; the copied Node executable is removed. The tested mount is read-only during execution, and file digests/modes are checked afterwards. Retained files are user-owned local artifacts: a future consumer must verify the manifest again before trusting or reusing them. The source repository and its Git objects are never written.

Integration tests: SUPER_RUNNER_TEST_ROOT=/existing/disposable/directory node --test tools/proposal-test-runner-spec.mjs. The filename deliberately does not match the child profile, preventing recursive runner tests. Tests cover real passing/failing assertions, changed result identities, retained material and records, filesystem/environment/network isolation, timeout, bounded output, stale input, symlinks and output-directory placement. Tests require host user-namespace support; they refuse within environments that block Bubblewrap.

Next integration: native-held repository selection and source verification; durable runtime admission/start/result association; human Run/Cancel/reopen UI with screenshots; then acceptance tied to exact result and validation. A UI must not treat these local JSON records as trusted runtime receipts merely because their shapes match. No new UI was added in this pass.

Open in the interactive atlas