Code review r2 (M1): the cancelled-run filter in merge-candidate's
waitValidate had no test or mutant — every test replaced ops.waitValidate
with a fake. realOps now takes an injectable `exec` (default: the same
spawnSync wrapper) so the real implementation runs against scripted
`gh run list` answers: a cancelled dispatch is skipped and its
replacement followed; a lone cancelled run ends in `missing`, never red.
Mutant: merge-trusts-cancelled-dispatch.
Issue: #510
User-Visible: no
Code review r1 (M1): validate-gate.mjs and merge-candidate's waitValidate
read a `cancelled` dispatch run on the material as red, so a dispatch
replaced by the next one in the `validate-dispatch-<ref>` concurrency
group would have returned the task S7→S6 for nothing — the same class
#511 fixed in release-gate.mjs. Cancelled runs are now ignored: the gate
follows the replacement dispatch, or starts its own when there is none.
Mutant: review-returns-task-on-cancelled-dispatch.
Issue: #510
User-Visible: no
Validate ran the three "Мутанты по диффу" shards on every push of every
branch: 48 of 56 job-hours on 08–09.09, most of them cancelled by the
next push. Mutants now run when asked — pull requests, the nightly
schedule, a push carrying a `Release:` trailer, or a dispatch with
`mutants=true` (classify-changes.mjs → `mutants_requested`); an ordinary
push runs the light checks only.
The proof moves to where it is consumed. process.yml gets a gate after
the #499 reuse step: on the code stage it looks for a dispatch Validate
run on the exact material SHA whose mutant jobs executed and passed
(scripts/validate-gate.mjs); none → it dispatches one and waits; red or
missing → the task goes back S7→S6 with the run link and the review
cycle is not spent. Spec stage and the reuse fast-path skip the gate
(`proceed=true`); all later steps branch on `proceed` in place of the
old conflict conjunct only. merge-candidate.mjs dispatches Validate on
the pushed candidate and waits for that dispatch run.
PROCESS.md/AGENTS.md: review does not start on red code; one handoff —
one push.
Mutants: mutants-run-on-every-push, review-starts-on-red-validate,
review-trusts-push-run-without-mutants, merge-waits-push-run-without-mutants.
Issue: #510
User-Visible: no
Windows portability (the three red tests on the owner's machine at green CI):
- scripts/spawn-portable.mjs: isMainModule via pathToFileURL (the
`file://${argv[1]}` form gives file:///C:/C:/... and the CLI stays silent);
portableCommand — a shell only for npm/npx/.cmd, node and git run directly
(spawn via shell dropped the quotes of `node -e "…"`). Applied to
classify-changes, mutation-gate-report, review-doc-guard, check-inputs,
merge-candidate, gate-small, rebase-on-dev.
- the rebase-on-dev test pins core.autocrlf=false / core.eol=lf through
GIT_CONFIG_* for its temp repository instead of touching the user's git
config; test/windows-portability.test.mjs forbids both anti-patterns.
Pins: scripts/toolchain-pins.mjs reads Node/Python from validate.yml, the HA
stack from tests_backend/requirements.txt, Playwright/Chromium from the
lockfile — no second dictionary; `npm run toolchain:check` compares the
machine; .nvmrc/.python-version are derived and tested equal;
scripts/wsl-setup.sh provisions WSL/Linux with those pins.
scripts/task-packet.mjs: one derived view of an issue (status, rights, owner
decisions, branch vs dev, Validate on the tip, previous verdict with recorded
tree, AC → evidence, unwitnessed). scripts/wait-verdict.mjs: polls labels,
pipeline comments and optionally Validate, prints only on state change, exit
0/3/4, writes nothing.
gate:small --smokes: after build the browser phase runs bundle-sync and then
the directly matched and registered smokes, two at a time; broad matches stay
with the reviewer. package.json changed, so the bundle is rebuilt here.
Issue: #496
User-Visible: no
scripts/merge-candidate.mjs owns the review pipeline's merge: when dev
moved during review, the rebased candidate is pushed to the issue branch,
its diff is compared to the reviewed one by patch-id, Validate on that SHA
is awaited, and only then dev is advanced with --force-with-lease on the
base the candidate was built on — a rejected lease restarts, at most three
times. Every non-merge outcome moves the label with a comment, so the
"label always changes" invariant holds. nightly.yml now finds the Validate
run it dispatched and inherits its conclusion. Three mutants guard this.
Issue: #492
User-Visible: no