Repository navigation
Conversation
… benchmark findings Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
openspec archive applied unit-rung-and-fixture-snapshots' deltas to openspec/specs, but the archive commit (17a1225) staged only openspec/changes and a post-merge git reset --hard discarded the spec edits. Restored: engine-invocation +2 requirements (per-call record store; CLI store parity); suite-certification +2 (fixture snapshots; rung membership by observable) and 3 replaced with the 0.48.0 text. 0.47.0's deltas verified complete. openspec validate --specs --strict: 14/14. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
Support the oldest non-EOL Node major (floor 22); CI matrix from nodejs/Release schedule.json with a committed fallback; per-file test mode (measured ~2x faster than single-process on 22/24/26); forced spec reporter; retire the isolation probe and [ -f ] loop; EOL warning in brief; actions v7; correct every Node 18+ claim; bound child waits (#220). Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…review 4 reviewers (2 Gate 1 lenses, 2 cross-spec lenses) all failed: 7 BLOCKS incl. CI green on a zero-test bucket, an unfalsifiable version-default scenario, 'supported' contradicting between R1/R2 (23/25/27), an over-wide bounded-wait requirement, an unfalsifiable schedule filter (now scripts/test/node-majors.mjs + canned-schedule test); 10 Important; polish. All fixed except one declined with reason. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
End-clause canned entry + mutation (B5); twin-coupling landing order per certification.mjs:173 (1.3→1.2, 1.5→1.4, 2.4c→2.4b); misplaced task lines. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
The pre-commit hook's runner now forces `--test-reporter=spec` with
`FORCE_COLOR=0`, parses `^ℹ` only (the `#` TAP branch is deleted), and
checks in design D5's order: an unreadable summary ABORTs ("the count
could not be read"); `total < declared` is the shortfall ABORT, zero
included; `declared = 0` is the empty-rung ABORT. Previously a
colour-forcing environment made the hook print "tests passing" with the
floor skipped.
- 1.1 RED: functional/conductor-09 runs the hook under FORCE_COLOR=1 and
asserts `2/2 passing`. Failing run: red-1.1.txt (Node v26.9.0).
- 1.2 GREEN: the runner line and the ordered checks; a durable stub-node
fixture for the unreadable-count refusal; assert/conductor-09's
RUNNER_LINE re-pointed, its node --test count widened to see env
prefixes, and a text guard for the refusal and the ℹ-only parse.
Mutations: mutation-1.2.txt.
- 1.3 REGRESSION GUARD: both rungs holding only `.keep` refuse, naming
both rungs, and default discovery is never reached.
- 0.3 baseline-before.md; 0.1/0.2 ticked (verdicts recorded, not stale).
- runHookAgainstFixture gains env / pathPrepend / withFixture / setup.
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
- 2.1 RED: assert-half-has-no-spawn gains a walk over BOTH rungs that refuses, by name, a file installing the run-time git counter neither directly nor through assert-harness/unit-harness, plus a discrimination test (side-effect, named, each harness, a two-line import; a comment- only mention and an unrelated fixture are refused). Failing run, naming exactly the 13 file-rung files of design D3 row 1: red-2.1.txt. - 2.2 GREEN: each of the 13 gains `import "../fixtures/assert-git-shim.mjs";` as its first import. The half is 1271/1271 both per-file and single-process (1269 at 0.3(b) plus the two new tests); none of the 13 went red, so none was reaching the real git undetected. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
- 2.3 RED: new assert/git-shim.test.mjs calls the shim module's exported
removeTempDir() on a scratch tree and asserts it is gone. Failing run:
red-2.3.txt (the module exported no such function).
- 2.4 GREEN: assert-git-shim.mjs exports removeTempDir(); its exit
listener reads the log, then removes shimDir. G-I4 is re-scoped per
design D3 row 2: the per-process exit listener is the mechanism, and
the direct check is that the shim is first on PATH in THIS process.
The shim's prose is rewritten, and the old requirement name ("The
assertion half spawns no process and runs no git") is re-pointed at
every live citation: the shim's printed text, and
assert-half-has-no-spawn's header and unit-rung section (6.2).
verify-2.4.txt: pm-assert-no-git-* count 4705 -> 4705 across one full
run of the half, per-file and single-process.
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…all in any file's process fails the run - 2.4b RED + GREEN: assert/git-shim gains a case asserting the harness's EMPTY_CACHE is scheduled for removal at process exit through the shim's own removal function (failing run: red-2.4b.txt). New fixtures/temp-dir.mjs owns removeTempDir/removeAtExit/ scheduledForRemoval — a separate module because harness.mjs is also imported by the functional half, which must never load the shim; the shim re-exports them. verify-2.4b.txt: pm-empty-cache-* 7804 -> 7804 across one full run, both modes. - 2.4c REGRESSION GUARD: new functional/git-shim.test.mjs runs a fixture file that installs the shim and reaches git through a tolerated library call, under `FORCE_COLOR=0 node --test --test-reporter=spec`, and asserts exit 1, `ℹ fail 1` and the listener naming `git --version`. Twin: assert/git-shim (edited here). mutation-2.4c.txt: the listener's `process.exitCode = 1` removed -> the functional test fails. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
… rationale
2.5 (design D3 rows 4-8, 10, 11): every comment and message that gave
"the assertion half is one process" as its reason now gives the reason
that survives per-file isolation — an in-process caller serving many
invocations, or one file's process:
- scripts/lib/invocation.mjs (three), constants.mjs, command-exit.mjs,
git-gateway.mjs;
- fixtures/helpers.mjs, fixtures/fs-work-counter.mjs, certification.mjs;
- assert/no-inline-exit (rationale + message), assert/per-call-roots,
assert/delivered-obligations;
- assert-half-has-no-spawn's header, walk message and the unit-rung test
TITLE ("...and is a rung of the half" — a renamed test, not a new one).
- functional/conformance's sync-main() rationale, which the 2.5 rg also
caught; its twin assert/conformance gains the one-line rationale so the
coupling check sees a real edit.
verify-2.5.txt classifies every surviving rg line. certify sweeps and
functional ran (constants.mjs is certified).
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…eleted - 1.4 GREEN (design D3, D5): the isolation probe, ISOFLAGFILE, $ISOFLAG and the `[ -f ]` loop are gone. The runner is `FORCE_COLOR=0 node --test --test-reporter=spec scripts/test/unit/*.test.mjs scripts/test/assert/*.test.mjs` under the runner's default per-file isolation. `rm -f` of the old pm-isolation-flag is the inverse of the probe's write. The empty-rung abort is check 3 (`declared = 0`), after the floor. Hook prose and assert/conductor-09's narrative rewritten; its guard re-pointed: the runner line by equality, exactly ONE node --test line, the two rung globs unit first, the zero-count abort after the floor, no --test-isolation, the rm -f line. functional/conductor-09's Node-18 narrative (the one-unmatched-rung test) is history now, assertions kept; a new fixture proves a collapsed run is a shortfall, not an empty rung. verify-1.4.txt: the file on 22.23.3, 24.21.0, 26.10.0, 33/33 each, G-I1 firing on each. mutation-1.4.txt: (i)-(iv) refused. - 1.5 REGRESSION GUARD: a fixture whose git dir holds a stale pm-isolation-flag has none after one hook run. mutation-1.5.txt. - 2.6: verify-2.6.txt records the one-time cleanup (4705 and 7804 leaked directories -> 0); a machine action, no repository change. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…f's one warning line - 3.1: new unit/runtime-support.test.mjs over memoryEngine. RED (no seam, no line): the below-floor line under v20.20.2 names 20.20.2 and 22 and leaves the rest of the brief and the status unchanged; two different below-floor versions in one process each name their own; with no version supplied, a store read observed mid-call sees process.version. Failing run: red-3.1.txt. REGRESSION GUARDS (at/above incl. v25, an unparseable version, uninitialized, render/snapshot), each seen to fail on its mutation: mutation-3.1.txt. - 3.2 GREEN: new scripts/lib/runtime-support.mjs (NODE_FLOOR_MAJOR = 22, supportFloorLine(), the version through escapeControls); invocation.mjs gains PROCESS_CONTEXT.nodeVersion (live) and runtimeVersion(ctx) = ctx.nodeVersion ?? process.version; runInvocation sets nodeVersion: io.nodeVersion ?? process.version; brief() prepends the line (never buildBrief()); fixtures/harness.mjs invokeEngine and fixtures/unit-harness.mjs memoryEngine pass nodeVersion through. New functional/runtime-support.test.mjs spawns `node --import <preload>` with process.version redefined to v20.20.2 and asserts the line, and none without the preload. conductor.mjs's "Node 18+" header corrected. The output-interpolation sweep is green (version escaped, the constant literal). Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
… and HTTP/2 3.3 REGRESSION GUARD, decided: widen. conductor-35's forbidden set named only fetch( and node:http(s); it now also refuses node:net, node:tls, node:dgram and node:http2 (which `node:https?\b` never matched), and their require() forms. mutation-3.3.txt: `import net from "node:net"` added to a scratch runtime-support.mjs is refused, and the pre-3.3 set is shown passing it. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…n clause by clause
- 4.2b RED + GREEN (design D2, Gate 1 B5): new scripts/test/node-majors.mjs
exports supportedMajors(schedule, today) — an lts date present,
start <= today, end > today — and decide({ fetched, body, today,
fallback }) owning every row of D2's table (failed fetch -> fallback +
warning; unreadable body -> error, never the fallback; computed !=
committed -> error naming both; empty -> error), plus the CLI tail CI's
node-majors job runs. New assert/support-floor.test.mjs drives both
against a CANNED schedule where each clause alone decides one entry.
Failing run: red-4.2b.txt (module absent). mutation-4.2b.txt: start,
lts and end clauses removed, and a malformed body routed to the
fallback — each refused. The README/CLAUDE.md support-floor-copy cases
land with 7.2/7.3, which rewrite those lines (per the task).
- 4.1: actions-notes-4.1.md — checkout/setup-node v5, v6, v7 release notes
read; latest tags re-confirmed v7.0.1 / v7.0.0, both node24; no default
this workflow relies on changes, and fetch-depth: 0 keeps its meaning.
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…e, behind one aggregate `test` - 4.2 RED: assert/ci-workflow gains pure functions over ci.yml's text, each with a test: (a)(b) an aggregate `test` job with `if: always()` needing both jobs and failing unless both results are success; (c) the matrix job's fail-fast: false, timeout-minutes and matrix.node from the compute output; (d) curl of the pinned schedule URL and node-majors.mjs given the file or --fetch-failed, `date -u +%F` and $PM_NODE_FALLBACK; (e) min(PM_NODE_FALLBACK) === NODE_FLOOR_MAJOR, naming both on a mismatch; (f)(f2) every bucket step forces the reporter and FORCE_COLOR=0, parses ℹ only and refuses a zero count; (g) v7 actions, no Node 18 pin. runnerLine() allows flags before the globs; the pipeline pattern accepts NAME=value prefixes (Gate 1 I5); the G-C1 fixtures are re-pointed. Failing run against the old ci.yml: red-4.2.txt. - 4.3 GREEN: ci.yml rewritten per design D2 — node-majors (the support floor's Node, curl + node-majors.mjs), test-node (matrix, reported as `test (node N)`), and the `test` aggregate; PM_NODE_FALLBACK "[22,24,26]"; actions @v7; every bucket step one reporter, ℹ parse, an unreadable/short/zero count refused in that order; the stale comment block and its dangling path replaced. security.yml untouched. mutation-4.3.txt: all twelve mutations refused. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…er an unreadable or zero count 4.4 RED + GREEN: certify.mjs exports summaryCount(output, label); new assert/certify-count.test.mjs asserts it reads the spec summary and returns null for a TAP summary (`# tests 3`) and for a coloured one (failing run: red-4.4.txt — no export, and the old regex accepted `#`). runBucket() starts the runner with --test-reporter=spec and FORCE_COLOR=0; a pass whose tests/pass count is null, or whose tests count is 0, records nothing and exits 1. The header comment naming the CI runner's Node 18 is corrected. `certify sweeps` recorded 25/25 through the new path. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…fallback and mismatch runs 4.5: ci-verify-4.5.txt. Through throwaway draft PR #221 (closed unmerged, branch deleted remote and local): the committed workflow computed [22,24,26], ran `test (node 22|24|26)` with `ran 1294, declared 1294` on every leg, and reported the aggregate under `test`; a 404 schedule URL fell back to [22,24,26] with a visible warning; a fallback of [22,24] failed node-majors naming both sets, and the `if: always()` aggregate failed on the skipped legs. Runs 36089089608 / 36089519332 / 36089888678. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…st, not the run (#220) - 5.1 RED: assert/state-file-refuses-to-guess gains a source scan over scripts/test/**/*.mjs: every wait on a child's close/exit event, in all three forms (<child>.on, <child>.once, events once(<child>, …)), must sit in a function that arms setTimeout( and .kill( — process.on("exit") excluded, comments blanked, tokens and samples built from parts. A discrimination test refuses an unbounded sample of each form and accepts a bounded one. Failing run naming functional/state-file-refuses-to-guess.test.mjs:299: red-5.1.txt. - 5.2 GREEN: spawnAll arms a 30 s timer per child (verb-surface's bound) that SIGKILLs it and resolves { timedOut: true }; both callers assert timedOut is false naming the argv and the bound. verify-5.2.txt: the functional file 46/46 on 22.23.3, 24.21.0, 26.10.0. - 5.3 MUTATION: one never-exiting child handed to spawnAll fails 3.1 in 30.2 s naming `node conductor.mjs __hang__ never exits`, and the run continues (45/46): mutation-5.3.txt. Fixes #220. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…the matrix, re-measured quickstart 7.1: the required-check description names the `test` aggregate over the `test (node N)` matrix and the computed supported majors; the hook's command is the forced-reporter, no-colour runner line; the quickstart and watch commands drop --test-isolation=none; "not optional" becomes a note on --test-concurrency for throttling; "one process" wording becomes one runner invocation; the guard section names the per-file shim-install rule. The quickstart was re-run in a fresh clone of a848988: Node v22.23.3 (the support floor) 1296/1296 in 14.0 s, Node v26.9.0 (Homebrew) 1296/1296 in 18.0 s. Every runnable command in the file was run as written in that clone (git config, both node --test forms, --watch for 8 s, --test-concurrency=2, the engine banner); the merge/rebase/tag procedures were not executed. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
… not end-of-life 7.2: README.md's two "Node 18+" claims (the Real Numbers line and Installation's requirements) carry the policy wording. In the same commit 4.2b's documented-support-floor assertion lands in assert/support-floor.test.mjs: every `Node N+` in README.md (at least 2) and CONTRIBUTING.md (at least 1, the copy 7.1 added) must equal NODE_FLOOR_MAJOR, naming the file and both values otherwise, with a discrimination test. The README's "1,116 tests" is left to the release cut's Real Numbers recompute, by design. Documentation currency: YES, user-facing; the pm-plugin.dev pages go to the release cut (7.6). Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…, and no single-process mandate 7.3: CLAUDE.md's hard constraint states Node 22+ with the policy wording and the engine's seven built-ins, re-derived (node:child_process, node:crypto, node:fs, node:os, node:path, node:tty, node:url — it named five). The Tests bullet loses --test-isolation=none and "in ONE process": both rungs run in one runner invocation whose TESTS spawn nothing and run no git. 4.2b's CLAUDE.md support-floor assertion lands here (CLAUDE.md added to assert/support-floor's copies). `rg -n 'isolation|Node 18' CLAUDE.md` returns nothing. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…e on the Real Numbers count, and the support-floor step 7.4: - pr-workflow: the test commands drop --test-isolation=none (one runner invocation); the description and intro say the required `test` check is an aggregate over the `test (node N)` matrix legs. - release-checklist: step 1's command and "one process" wording; the Real Numbers recipe runs `FORCE_COLOR=0 node --test --test-reporter=spec …`, greps `-m1 '^ℹ tests '`, and STOPS without publishing when the line is missing or reads 0 (Gate 1 B1); a new support-floor step at "Engine + tests" computes the supported set via scripts/test/node-majors.mjs against the release date and names NODE_FLOOR_MAJOR, PM_NODE_FALLBACK, the README/CONTRIBUTING/CLAUDE.md copies and the docs-site pages as one unit. Its command was run as written: [22,24,26], exit 0. `rg -n 'isolation' .claude/skills` returns nothing. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…closes the archive lesson 7.8: the release-checklist skill had no archive step at all; step 5 now archives each change after its Gate 2 and says, in these words, "stage openspec/ whole (or everything `git status --short openspec/` lists) — the archive rewrites openspec/specs too". In the same commit the lesson docs/lessons/an-archive-writes-outside-the-change-dir.md's enforced_in and docs/lessons/README.md's enforced-in row name that step. `rg -n 'stage openspec/ whole' .claude/skills/release-checklist/SKILL.md` returns one hit; `rg -n 'until 0.49.0' docs/lessons/` returns nothing. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
7.5: CHANGELOG.md gains `## [Unreleased]` — Changed (the support policy and floor 22; the CI matrix computed from the schedule behind the `test` aggregate; per-file isolation with 0.3's and 8.1's numbers — hook 33.55 s -> 24.0 s here, still not under 15 s, and 14.5 s vs 11.3 s against it on a 4-core runner; one reporter; actions v7), Added (the brief's below-floor line), Fixed (#220; the hook's skipped floor on an unreadable count; the shim and harness temp-dir leaks), Removed (the isolation probe and the Node-18 loop). The release cut folds it into 0.49.0. 7.7: `git diff --stat aa48c88..HEAD -- commands/ agents/ skills/ hooks/ .claude-plugin/` is empty and assert/parity is 9/9 — nothing shipped changed, so the ledger needs no entry; the version bump is the cut's. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…g faster, per-file slower on 4 cores 8.1: the hook end to end at cd093fe, hermetic clone, same method as 0.3: median 24.0 s (runner 15.7 s, 1298 tests) against 33.55 s before. Design D10's outcome: NOT under 15 s, so store-owns-claude-md-managed- block's premise stands (not touched). Leaked temp dirs: 0 / 0 before and after, against 4,043 / 6,879 at 0.3(d). 8.2: from this change's PR run 36089089608, every leg is faster than the Node 18 job in the job and in each bucket step (4m18s / 4m18s / 3m38s against 4m46s). 8.3: on a CI runner (nproc 4, Node 24) per-file is SLOWER — 14.49 s against 11.33 s single-process, median of three interleaved runs each (run 36089977671, throwaway draft PR #221, closed unmerged, branch deleted). Recorded so the trade is known; the decision stands. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…, inverses, commit verification, routed findings - 6.1 call-site-sweep-6.1.txt: every `node --test` count site (hook, ci.yml x3, certify.mjs, the Real Numbers recipe, functional/git-shim) forces the reporter + FORCE_COLOR=0 and refuses an unreadable or zero count; every runtime-version reader/writer (process.version read at three context defaults — one more than design D6 counts, per 3.2's own text); every NODE_FLOOR_MAJOR reader; 141 rung files, 0 without the shim; both awaited child waits bounded, the synchronous class named; D8's sweep line-based (27) and multiline (13), every hit classified. - 6.2/6.3 data-refs-and-inverses-6.2-6.3.txt: PM_NODE_FALLBACK <-> NODE_FLOOR_MAJOR and the documented copies, pm-isolation-flag's writer deleted and removal shipped, the renamed requirement's citations (one left: the main spec header the archive rewrites); every inverse named. - 6.4 commit-verification-6.4.txt: 20 commits, every claimed file in its own commit (git show --name-only), 0 missing. - 6.5 verified: 9.2 carries <!-- pm:lifecycle -->. - 6.9 routed: FRICTION filed as #222 (archive gate vs unsynced main specs) and #223 (attribution nudge on throwaway-branch commits); PROCESS lesson a-guard-installed-by-import-covers-only-its-process; PRACTICE decided not a pm epic; the openspec-validate friction left to the maintainer. 6.6/6.7/6.8 stay open: they bind through Gate 2 and the archive. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…der, and nothing that skips a leg (Gate 2 I1, M3, M6) - I1: reporterRefusals() requires, in every bucket step, the `[ -z "$total" ]` refusal, the `-lt "$declared"` floor and the `-eq 0` refusal — each ending in `exit 1` — in that order. Deleting the -z block used to stay green (`[ "" -lt N ]` errors, `if` reads false, the step exits 0). - M3: actionRefusals() refuses --test-isolation anywhere in ci.yml. - M6: matrixRefusals() refuses `if:` or `continue-on-error:` on the test-node job or any of its steps, and `exclude:`/`include:` under its matrix. mutation-4.3.txt gains (13)-(22), each refused; the pre-fix guard passes (13) 8/8 (control). Also stages the uncommitted attribution of f84fe9d. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…ercised (Gate 2 I2) certify.mjs exports runnerInvocation(files, env) — the argv (`--test --test-reporter=spec …`) and env (FORCE_COLOR forced "0") the bucket runner is started with — and countRefusal(). A function test, not a conductor-09-style text guard: the property is what the runner is handed and what is refused, which a spelling pin would miss after a refactor. assert/certify-count gains two tests: argv/env (colour forced off even under FORCE_COLOR=1), and countRefusal over null, a missing pass, 0, a TAP summary and a coloured one (refused) and a real count (recorded). RED: red-g2-i2.txt (no exports). mutation-g2-i2.txt: the reporter flag, FORCE_COLOR, the null refusal and the zero refusal each removed — each now fails a test. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
… shim's own exit removal is checked (Gate 2 I3, M1)
- I3: assert-half-has-no-spawn gains fixtureInstallsShim(name, read), a
walk through fixture imports (a harness installs when it imports
./assert-git-shim.mjs or another fixture that does — unit-harness
through assert-harness), a test that both trusted harnesses do, and a
discrimination test (direct, transitive, neither, comment). Removing
the shim import and re-export from fixtures/assert-harness.mjs now
fails it, naming both harnesses; the pre-fix walk alone passed that
mutation (control).
- M1: the shim's exit work is exported — drainAndRemove(dir) reads the
log then removes the directory, onExit is the registered listener.
assert/git-shim asserts onExit is in process.listeners("exit") and
drives drainAndRemove on a scratch directory. RED: red-g2-m1.txt.
mutation-g2-i3-m1.txt: I3 and both M1 mutations refused.
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
… header is a checked support-floor copy (Gate 2 M4, M5)
- M5: conductor-35's no-network walk also refuses `from "(node:)?(net|
tls|dgram|http2|https?|dns)"` and dynamic `import("…")` of the same,
and `dns` joins the set. The reviewer's mutation (`import net from
"net"` in runtime-support.mjs) and a dynamic `import("dns")` are both
refused; the pre-fix set matched neither (control).
- M4: support-floor's FLOOR_COPIES adds ["scripts/conductor.mjs", 1] (a
header stating Node 20+ is refused), and the release-checklist's
move-together list names the engine header.
mutation-g2-m4-m5.txt.
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…cess prose left (Gate 2 M2, M7) - M2: runtimeVersion()'s `ctx.nodeVersion ?? process.version` (lib/invocation.mjs) is the ONE default. runInvocation passes io.nodeVersion through unchanged and PROCESS_CONTEXT drops its getter. New assert/conformance "M2" test pins process.version to that single engine code site (comments stripped). RED: red-g2-m2.txt (three sites); mutation-g2-m2.txt: re-adding runInvocation's default is refused. tasks.md 3.2 records the amendment. - M7: conductor.mjs's resetGitCaches note and exit-handler rationale, and functional/conformance's twin rationale, reworded from "the assertion half's ONE shared process" to an in-process caller / one test file's process under per-file isolation. D3's rg sweep widened to scripts/conductor.mjs; the result is appended to verify-2.5.txt. certify sweeps (25/25) and functional (1189/1189) recorded. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…ild holding a pipe cannot hang it (Gate 2 M8)
spawnAll's timer now SIGKILLs the child AND resolves
{ timedOut: true } itself; `close` (which waits for every stdio pipe)
only settles it when the child finishes first. The assert twin gains an
M8 test that the CHILD_BOUND_MS timer kills and resolves timedOut: true
— RED against the previous spawnAll. mutation-g2-m8.txt: with the bound
shortened to 3 s and a child whose backgrounded grandchild holds stdout,
the old helper's test took 20.2 s, the new one fails at 3.05 s.
Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
… 0.50.0 Coordinator's decision at Gate 2 (2026-09-24): a contributor clone can skip releases, and a one-line idempotent `rm -f` costs nothing. The hook comment, design D3, task 6.8's candidate list and the 6.2 data-reference record now say so; there is no deferral to register for it at archive. Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
…o the main specs Claude-Session: https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
pm now supports exactly the Node LTS lines that are not end-of-life. The oldest of them, the support floor, is Node 22. Node 18 (EOL 2025-04-30) and Node 20 (EOL 2026-04-30) are dropped.
What changed
NODE_FLOOR_MAJORinscripts/lib/runtime-support.mjs, and a release-checklist step moves it. The engine still makes no network calls.scripts/test/node-majors.mjscomputes the matrix fromnodejs/Release/schedule.json.testjob keeps branch protection's required check, and it fails on any skipped or failed leg.certify.mjsand the Real Numbers recipe. Each forces--test-reporter=specwithFORCE_COLOR=0.[ -f ]glob loop.Gates
Suite: unit 759 · assert 546 · functional 1189 · sweeps 25. There is no
state.jsonschema change and no migration. Requires/reload-plugins.https://claude.ai/code/session_01BoqzgrFwRC6QTUKuBkw8kM