From 5c85a6426f0f80f7c7561038db533c52e4290ffb Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 16:55:22 +0000 Subject: [PATCH] tooling(pm): name the sweeper's third file in the patrol's adopt list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The half-state patrol's documented sibling install listed two files to copy (`scripts/pm/check-half-states.mjs` and the workflow) while the sweeper has imported `../invoked-as.mjs` since before that list was written. A repo that followed it verbatim installed a patrol that cannot start. Measured on a clean two-file copy of this repo's own files: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../scripts/invoked-as.mjs' imported from '.../scripts/pm/check-half-states.mjs' exit 1 The same copy with `scripts/invoked-as.mjs` added runs the sweeper's `--self-test` to `2062 cases pass`, exit 0. The failure is loud rather than silent — the job's final step turns the run red and the anchor is rewritten with the "THE SWEEP DID NOT RUN" body — but the adopter still gets a dead patrol, and the next two adopters in the fleet would each get one. Three comment/wiring corrections, all in the workflow; the sweeper is not touched, so this repo's sweep behaviour is byte-identical by construction: - the adopt list names three files, with the measurement that decides it; - the "No `pnpm install`" note states the sweeper's real import set (`node:` builtins plus the one repo-local helper) instead of "nothing but `node:process` and global `fetch`" — that sentence is what an adopter checks the copy list against, so a stale one re-creates the defect; - `scripts/invoked-as.mjs` joins the `pull_request` path filter, so a change to it gets the same pre-merge proof the other two files get. The adopted objectui copy has carried that row since its port. Part of #14881 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox --- .github/workflows/half-state-patrol.yml | 33 ++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/.github/workflows/half-state-patrol.yml b/.github/workflows/half-state-patrol.yml index 872f1d4100..46579667e3 100644 --- a/.github/workflows/half-state-patrol.yml +++ b/.github/workflows/half-state-patrol.yml @@ -87,11 +87,24 @@ name: Half-State Patrol # # To adopt, in the sibling repo: # -# 1. copy `scripts/pm/check-half-states.mjs` and this file, unchanged; +# 1. copy THREE files, unchanged: `scripts/pm/check-half-states.mjs`, +# `scripts/invoked-as.mjs` (the sweeper imports it — see below), and this +# file; # 2. open one `tracking`-labeled anchor issue there and set the repository # VARIABLE `HALF_STATE_ANCHOR_ISSUE` to its number # (Settings → Secrets and variables → Actions → Variables). # +# ⚠️ Step 1 said TWO files until 2026-09-03, and the sweeper has imported +# `../invoked-as.mjs` since well before that — so the documented install was a +# patrol that could not start. Measured on a clean two-file copy of this repo's +# own files: `ERR_MODULE_NOT_FOUND … /scripts/invoked-as.mjs`, exit 1, before a +# single predicate runs; the same copy with the helper added passes the +# sweeper's 2,062-case `--self-test`. It fails LOUDLY rather than silently (the +# job's last step turns the run red and the anchor is rewritten with "THE SWEEP +# DID NOT RUN"), which is the one mercy in it — but a repo adopting this file by +# following the list above installed a dead patrol. ⛔ Do not shorten this list +# again from memory: the import is what decides it, not this comment. +# # That is the whole install. The swept repo needs no configuration at all: it is # `github.repository`, so the copy reads the board it lives in — a hardcoded # default was how a copied file could have swept THIS repo and written the @@ -129,6 +142,13 @@ on: pull_request: paths: - 'scripts/pm/check-half-states.mjs' + # The sweeper imports this helper, so a change to it can break the patrol + # without touching either file beside it — and the PR-time proof this + # trigger exists to give would not run. Same reasoning as the adopt list + # above, one layer down: an undeclared dependency is undeclared in every + # place that has to name it. (The adopted objectui copy carries this row + # already; upstream is catching up to its own port.) + - 'scripts/invoked-as.mjs' - '.github/workflows/half-state-patrol.yml' # Least privilege: this job reads the repo and writes exactly one issue BODY. @@ -190,9 +210,14 @@ jobs: with: node-version: '22' - # No `pnpm install`: the sweeper imports nothing but `node:process` and - # global `fetch`. Installing the workspace here would buy nothing and would - # give a scheduled patrol a lockfile it could fail on. + # No `pnpm install`: the sweeper imports only `node:` builtins + # (`process`, `child_process`, `fs`, `url`), global `fetch`, and the one + # repo-local helper `../invoked-as.mjs` — no npm dependency, so installing + # the workspace here would buy nothing and would give a scheduled patrol a + # lockfile it could fail on. ⚠️ That repo-local import is why the adopt + # list above copies THREE files; this sentence read "imports nothing but + # `node:process` and global `fetch`" until 2026-09-03, which is the claim + # an adopter would have checked the copy list against. - name: Run the live sweep id: sweep env: