Skip to content

Commit fb7b746

Browse files
huangyiireneclaude
andauthored
ci(half-state-patrol): state the measured reason the two steps stay in the caller (#19718)
Fixes #19396 Comment-only, in two files. The stated reason for keeping `actions/setup-node` and the closed-card sweep in the CALLING workflow was a census argument, and PR #19284 made it false. Each bullet now carries a constraint that was measured on this tree instead. ## The premise, re-measured on the base (`a251aaa19`) All four censuses reach composite actions. Their own scope lines, exit code captured before any pipe: ``` check-node-version EXIT=0 OK (43 setup-node step(s) across 38 workflow(s) and 2 composite action(s), all on Node 22). check-self-test-wired EXIT=0 scope: 311 file(s) under scripts/, 243 carrying `--self-test` in code ...; 226 of those are run by 38 workflow(s) and 2 composite action(s); ... check-workflow-step-name-quoting EXIT=0 OK (scanned 38 workflow file(s) + 2 composite action file(s), 729 step name(s) -- 9 already quoted, 720 unquoted-and-safe). check-step-collectors EXIT=0 511 `run:` steps across 38 workflow(s) and 2 composite action(s); 5 step(s) run 2+ independent self-tests, all of them through a collector. ``` `premise_still_valid: true` — zero composite actions would have refuted the card; both counts read 2. Two further readings, so the repair rests on measurement rather than on the card's guess: - **`scripts/check-node-version.mjs` builds one list, `[...workflowFiles, ...actionFiles]`, and its own header retires the constraint by name:** *"With both roots read, the constraint is gone: put the step wherever the composition wants it."* - **The consequence the sweep bullet drew is false too, measured with the gate's own exported reader.** Read-only probe, nothing in the tree touched: the closed-card step's real bytes handed to `collectInvocations` twice, once as a workflow and once as a composite action file. ``` workflow named=true selfTested=true attribution=["half-state-patrol.yml"] composite action named=true selfTested=true attribution=[".github/actions/half-state-patrol/action.yml"] ``` So a moved step stays in the population, under the composite action's own name. ## The constraint that IS measurable, per step **`actions/setup-node` — the action holds no Node pin, and a `setup-node` step in it would need one.** The floor asserted in `Locate the patrol sources` is read from the `.nvmrc` that shipped with the action (`action.yml` lines 202-217, already in the file and still true). `check-node-version.mjs` holds every `setup-node` pin in this repo — workflows and composite actions alike — equal to that same `.nvmrc`. So a `setup-node` step inside the composite would install the very version the floor is then compared against: `have` and `floor` derived from one file, equal by construction, the comparison unable to fail, and no longer a reading about the CALLER's runner at all. That holds for a sibling pinning the action too, since both the pin and the `.nvmrc` travel at the same sha. This is *not* the card's guess ("a sibling repository's Node pin has to be the sibling's own"), and the guess is not measurable today: **no sibling calls this action.** `objectui` carries its own `.github/workflows/half-state-patrol.yml` that runs its own copy of the sweeper, holds no `.github/actions/` directory at all, and names this action nowhere. The only caller on either tree is this repo's own `uses: ./.github/actions/half-state-patrol`. No gate requires the pin to be a literal in the caller: `check-node-version` accepts `node-version-file: .nvmrc` as the ideal form, fails an unresolvable expression, and cannot reach a sibling repo at all. **The closed-card sweep — the repair is a deletion, which is the card's second exit.** A true reason already sat in both files, first in the sentence: it is the one step of the old file that was never repo-agnostic, it WRITES to cards under a ruling this repo's board took, and no sibling has taken it. The false half (the `check-self-test-wired` population argument) is deleted rather than rewritten, so what remains is what still holds. ## Proof that this is comment-only Parsed YAML compared against the base blob with the repo's own `yaml@2.9.0`, plus a control leg that must differ so the comparison is not one that cannot fail: ``` IDENTICAL .github/actions/half-state-patrol/action.yml raw bytes before=23411 after=23573 (delta 162) parsed JSON length before=10752 after=10752 sha-equal=true IDENTICAL .github/workflows/half-state-patrol.yml raw bytes before=30837 after=30419 (delta -418) parsed JSON length before=5245 after=5245 sha-equal=true CONTROL LEG (one real YAML byte changed, in memory): identical=false — must be false ``` And every changed line is a comment line: ``` changed lines: 56 NON-comment changed lines: (count: 0) ``` No step moved; no `run:`, `uses:`, `with:`, `if:` or `paths:` byte changed. **Line budget:** `action.yml` block 19 lines to 21 (+2); workflow `setup-node` comment 5 to 5 (0); workflow sweep comment 9 to 3 (-6). Net **-4** across the two files, against the suggested ceiling of +12 / -14. ## Gates Derived with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` (no paths; the script took the change set from the merge base itself), then reconciled with `--ran`. Exit codes captured before any pipe. Readings are quoted in the report comment on #19396; the union was re-run on the final commit. `.github/**` ships in no package, so this carries `skip-changeset`: all 70 non-private packages declare an explicit `files[]` and not one entry names `.github` or the repo root. ## Acceptance notes - **`.github/actions/setup-pnpm` is NOT a stale sibling sentence** — checked because the edited sentence cited it. It was already repaired (lines 50-58): it records the blind spot as CLOSED and says the separation is kept for no constraint at all. That difference is now stated in `action.yml`, so a reader who follows the pointer does not generalise setup-pnpm's retired reason to this action, which has a live one. - **`objectui` has not adopted this composite action, and its copy of the sweeper diverges from the one the action ships** — 13,194 lines against 36,717 at `objectui@0cf2d6644` and `a251aaa19`. That is the copy drift this action exists to delete, one board along. Out of scope here and reported for the filing seat rather than touched. --- _Generated by [Claude Code](https://claude.ai/code/session_01Wnstp2kTth7sGXfr8fXypc)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent ce95164 commit fb7b746

2 files changed

Lines changed: 26 additions & 30 deletions

File tree

‎.github/actions/half-state-patrol/action.yml‎

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,25 @@
4747
#
4848
# ## What deliberately did NOT move into here, and why
4949
#
50-
# Two steps stay in the CALLING workflow, both because a gate in this repo
51-
# derives its population from `.github/workflows/` and only from there:
50+
# Two steps stay in the CALLING workflow, each for its OWN reason -- and ⛔ not
51+
# for the census reason this block used to give. `check-node-version` and
52+
# `check-self-test-wired` read `.github/actions/**` as well as
53+
# `.github/workflows/`; their scope lines say "2 composite action(s)", so a
54+
# step moved in here stays audited, under this file's name, in both.
5255
#
53-
# - `actions/setup-node`. `scripts/check-node-version.mjs` scans
54-
# `.github/workflows/*.yml` and reports how many setup-node steps it
55-
# audited; a step moved in here would drop out of that census and the gate
56-
# would still print OK. `.github/actions/setup-pnpm` records the same
57-
# reasoning for the same gate, and the same answer: callers keep their own
58-
# setup-node step with its literal `node-version` pin.
59-
# - the closed-card sweep. `scripts/check-self-test-wired.mjs` builds its
60-
# population from the scripts a WORKFLOW names, and the only CI invocation
61-
# of `scripts/pm/sweep-closed-cards.mjs --self-test` in this repo is the one
62-
# in that workflow. Moved in here it would leave that gate green while
63-
# auditing one script fewer. It is also the one step in the old file that
64-
# was never repo-agnostic -- it WRITES to cards and was gated on the
65-
# repository name -- so leaving it in the objectstack caller states plainly
66-
# what the `if:` used to state obliquely.
56+
# - `actions/setup-node`. This action holds NO Node pin of its own -- the
57+
# floor in `Locate the patrol sources` is read from the `.nvmrc` that
58+
# shipped with it, and `check-node-version.mjs` holds every setup-node pin
59+
# in this repo equal to that same file. A `setup-node` step in here would
60+
# install the very version that floor is then compared against: equal by
61+
# construction, unable to fail, and no longer a reading about the CALLER's
62+
# runner. The caller picks the Node it runs on; this action only refuses
63+
# one that is too old, by name. (`setup-pnpm` keeps the same separation for
64+
# NO constraint -- there the census was the whole reason, and it is gone.)
65+
# - the closed-card sweep. It is the one step in the old file that was never
66+
# repo-agnostic -- it WRITES to cards and was gated on the repository name
67+
# -- so leaving it in the objectstack caller states plainly what the `if:`
68+
# used to state obliquely.
6769
#
6870
# ## Where this runs, and against which board
6971
#

‎.github/workflows/half-state-patrol.yml‎

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,11 @@ jobs:
248248
- name: Checkout repository
249249
uses: actions/checkout@v7
250250

251-
# Stays in the caller on purpose: `scripts/check-node-version.mjs` scans
252-
# `.github/workflows/*.yml` only and reports how many setup-node steps it
253-
# audited, so a step moved into the composite action would drop out of
254-
# that census while the gate still printed OK. `.github/actions/setup-pnpm`
255-
# records the same reasoning for the same gate.
251+
# Stays in the caller on purpose, and ⛔ NOT for a census reason: the Node
252+
# census reads `.github/actions/**` too. The patrol action holds no Node
253+
# pin of its own and only asserts a floor from the `.nvmrc` it shipped
254+
# with, so the runner's Node has to be the CALLER's choice for that check
255+
# to be a reading about anything. The action's header carries the measure.
256256
- name: Setup Node.js
257257
uses: actions/setup-node@v7
258258
with:
@@ -316,15 +316,9 @@ jobs:
316316
# close-time hygiene rather than the backfill the 2026-08-31 maintainer
317317
# ruling refused.
318318
#
319-
# ⛔ NOT in the composite action, for two reasons that both say the same
320-
# thing. It is the one step of the old file that was never
321-
# repo-agnostic: it WRITES to cards under a ruling this repo's board
322-
# took, and no sibling has taken it. And this workflow is the only place
323-
# in CI that runs `scripts/pm/sweep-closed-cards.mjs --self-test`, which
324-
# is how `scripts/check-self-test-wired.mjs` knows that self-test is
325-
# run at all — that gate builds its population from `.github/workflows/`
326-
# and nowhere else, so moving this step would leave it green while
327-
# auditing one script fewer.
319+
# ⛔ NOT in the composite action. It is the one step of the old file
320+
# that was never repo-agnostic: it WRITES to cards under a ruling this
321+
# repo's board took, and no sibling has taken it.
328322
#
329323
# ⛔ This step never fails the job, whatever the sweep returns; the
330324
# alarm rides an annotation and the run summary instead. Findings are

0 commit comments

Comments
 (0)