Skip to content

Commit 51a65a3

Browse files
committed
ci(pm): retire the half-state patrol's schedule — on demand only
The patrol is report-only, and the dispatch charter made its anchor rows a precondition for opening a dispatch, so a row misreading a now-legal state cost every executive seat a handling step four times a day until a dev repaired the row. Ruling 208 (batch letter 2, part R3) retires the schedule and keeps the instrument: no line of the sweeper is edited, the workflow stays runnable, and the triage seat dispatches it for its reconciliation. - `on:` drops the `schedule:` block; `workflow_dispatch: {}` and the `pull_request:` paths trigger stay exactly as they were. - The header prose that promised a four-times-a-day cadence, the `:37` offset, the `Swept` heartbeat reading, the concurrency note, the anchor fallback note and the citation census's cost note are rewritten for on-demand use, and carry the ⛔ against re-scheduling it silently. - The generator's own cadence constants are untouched by ruling, so the anchor body will keep stamping a deadline against a schedule nobody fires; the header records that as a known, unread reading. Claude-Session: https://claude.ai/code/session_012GcsUbuqFGBibkEDMRC1eE Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2cac363 commit 51a65a3

1 file changed

Lines changed: 80 additions & 41 deletions

File tree

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

Lines changed: 80 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ name: Half-State Patrol
88
# NOT repo-agnostic — when it runs, what it may touch, the board's own anchor,
99
# and the one step that writes to this repo's cards.
1010
#
11-
# ## Why a workflow, and not "a seat should run it"
11+
# ## Why a workflow at all — the transport, not the calendar
12+
#
13+
# ⚠️ HALF SUPERSEDED (ruling #208 on objectstack#19491, executed by
14+
# objectstack#19497): this file declares NO schedule. The argument below is kept
15+
# as the history that put the patrol on a runner, not as a promise that anything
16+
# fires it. What survives is the transport reason in the next paragraph; what the
17+
# ruling retired is the calendar.
1218
#
1319
# The sweeper carries thirteen predicates over the dispatch protocol's
1420
# label/assignee/PR invariants, and for most of its life its documented consumer
@@ -17,6 +23,10 @@ name: Half-State Patrol
1723
# claims (H2) and an unenumerated backlog sat on the board. Not one predicate had
1824
# fired. A healing mechanism with no scheduled caller heals only in the
1925
# counterfactual, and an alarm added to a script nobody runs is still silence.
26+
# That reading bought the schedule in #9844 and was true of its day. Ruling #208
27+
# re-measured the same instrument and found the standing caller charging more
28+
# than it healed — see the `on:` block below, which carries the reading and the
29+
# ⛔ that goes with it.
2030
#
2131
# "Some seat should run it" also kept not happening for a MEASURED reason, not a
2232
# discipline one: in every container class measured at the time, the live sweep
@@ -37,12 +47,13 @@ name: Half-State Patrol
3747
# `HTTPS_PROXY`, so the sweeper sent the proxy's placeholder token straight to
3848
# GitHub, earned a 401, and reported that refusal as the container's verdict.
3949
#
40-
# ⛔ That does NOT retire this workflow, and the fix deliberately did not touch
41-
# it. The #9844 reason stands on its own and is not a transport reason: an alarm
42-
# whose only caller is "a seat should remember" is silence, whoever CAN run it.
43-
# The on-demand path is restored BESIDE the schedule — a lane that needs the
44-
# board read right now (the 4x/day body trims its own rows, and says so) can now
45-
# get it — never instead of the schedule.
50+
# ⛔ That did NOT retire this workflow either, and the fix deliberately did not
51+
# touch it: a correction about WHO CAN run the sweep is not a ruling about
52+
# WHETHER it should run by the clock, and this file stayed exactly as it was.
53+
# What the correction bought is the path this workflow now runs on ALONE — a lane
54+
# that needs the board read right now (the body trims its own rows, and says so)
55+
# gets it from its own container or from a `workflow_dispatch` here. Since ruling
56+
# #208 that on-demand read is the only read there is.
4657
#
4758
# ## What lands where
4859
#
@@ -52,11 +63,21 @@ name: Half-State Patrol
5263
# archive this needs. The body is owned end-to-end by the generator, so no run can
5364
# leave half of it stale.
5465
#
55-
# The `Swept` timestamp in that body is the patrol's heartbeat and is deliberately
56-
# refreshed even when the findings are unchanged: a timestamp that stops advancing
57-
# is how a reader learns the standing caller died. That is the whole defect class
58-
# this workflow exists to close, so the run must not "optimize away" the no-op
59-
# edit that proves it is alive.
66+
# The `Swept` timestamp in that body is refreshed even when the findings are
67+
# unchanged, and the run must still not "optimize away" that no-op edit — but
68+
# read it for what it now is. With no schedule behind it, the stamp dates the
69+
# last time a seat ASKED for a reconciliation; it is no longer a heartbeat, and a
70+
# `Swept` that stopped advancing means nobody has dispatched the patrol since,
71+
# ⛔ not that a standing caller died.
72+
#
73+
# ⚠️ KNOWN STALE READING, deliberately not repaired here (objectstack#19497): the
74+
# generator stamps a cadence deadline beside `Swept` from its own `PATROL_CRON` /
75+
# `PATROL_CADENCE_HOURS` constants, so the anchor body will keep stamping an
76+
# "expected every 6h · next by …" deadline computed from the schedule string
77+
# those constants still hold — a deadline against a schedule this file no longer
78+
# declares, and nothing on this board fires. The ruling forbids editing the
79+
# sweeper for it (⛔ not one of its 36,717 lines); the repair is filed as its own
80+
# finding instead.
6081
#
6182
# ## Report-only, and the one thing that is NOT report-only
6283
#
@@ -119,23 +140,39 @@ name: Half-State Patrol
119140
# a healthy block.
120141

121142
on:
122-
schedule:
123-
# Four times a day, six hours apart, at :37 past the hour.
124-
#
125-
# The minute is offset ON PURPOSE. The triage Routine that heals these same
126-
# states fires hourly near the top of the hour, and a patrol landing at the
127-
# same minute would keep reading the board mid-heal — reporting half-states
128-
# the healer is in the middle of pairing, i.e. manufacturing findings that
129-
# clear themselves. :37 puts this sweep in the quiet part of the healer's
130-
# cycle in both directions. Four runs/day rather than hourly: H13's own
131-
# threshold is 2h and the incident it comes from sat ~26h, so six-hourly
132-
# detection is two orders of magnitude better than the status quo (never)
133-
# while staying cheap on the core quota this sweep shares with the loop's
134-
# hot path.
135-
#
136-
# The cadence is per-board and stays in the caller: a sibling with a
137-
# different healer cycle picks its own minute here, not in the action.
138-
- cron: '37 1,7,13,19 * * *'
143+
# ⛔ ON DEMAND ONLY — this workflow declares NO schedule, and re-adding one
144+
# takes the maintainer's sentence, not a reading of the history above.
145+
# Ruling #208 on objectstack#19491, executed by objectstack#19497, maintainer
146+
# 「19491 接受你的建议,并立刻派发处理相关任务。」 The triage seat dispatches this
147+
# workflow when it wants the board reconciled; nothing fires it by the clock.
148+
#
149+
# WHAT THE RETIRED SCHEDULE WAS: `37 1,7,13,19 * * *` — four runs a day, six
150+
# hours apart, the minute deliberately off the top of the hour so the sweep
151+
# never read the board mid-heal while the hourly triage Routine was pairing
152+
# states, and four runs rather than hourly because H13's own threshold is 2h.
153+
# None of that was what the ruling found wrong.
154+
#
155+
# WHY IT WENT: the patrol is REPORT-ONLY (see the section above) while the
156+
# dispatch charter made its anchor rows a precondition for opening a dispatch.
157+
# A row misreading a now-legal state therefore cost every executive seat a
158+
# handling step — four times a day, until a dev repaired the row — and the
159+
# sweeper was taking eight such repairs a day in the fortnight before the
160+
# ruling. On the maintainer's question 「巡查仪留着却不继续开发,会不会反而不停的报
161+
# 错误的信息」 the answer measured yes. The ruling stops the clock, ⛔ not the
162+
# instrument: the script keeps every one of its 36,717 lines and stays runnable
163+
# from here, and the charter's precondition is deleted on the sibling card.
164+
#
165+
# ⛔ Do not re-add a `schedule:` block on the argument the history above makes
166+
# ("an alarm nobody runs is silence"). That argument is answered, not
167+
# forgotten: it was weighed against what the standing caller was charging every
168+
# seat, and it lost. If a month passes with nobody dispatching this, the ruling
169+
# is that the sweeper is deleted whole on its own card — ⛔ never quietly
170+
# re-scheduled.
171+
#
172+
# The cadence was always per-board and stays in the caller: a sibling repo that
173+
# wants a scheduled sweep of ITS board declares `schedule:` in its own copy of
174+
# this caller and picks its own minute against its own healer — never in the
175+
# action, and never by reading a cadence out of this file.
139176
workflow_dispatch: {}
140177
# Changes to the patrol itself get exercised before they merge — the same
141178
# posture as engine-split-metric.yml. On a pull_request run the sweep still
@@ -191,9 +228,10 @@ permissions:
191228
issues: write
192229
pull-requests: read
193230

194-
# One patrol at a time. A scheduled run overlapping a manual dispatch would have
195-
# two runs racing to rewrite the same body, and the loser's findings would vanish
196-
# with no trace but an edit-history entry.
231+
# One patrol at a time. Two dispatches in flight at once — the shape that is left
232+
# now that nothing fires by the clock — would have two runs racing to rewrite the
233+
# same body, and the loser's findings would vanish with no trace but an
234+
# edit-history entry.
197235
concurrency:
198236
group: half-state-patrol
199237
cancel-in-progress: false
@@ -223,8 +261,8 @@ jobs:
223261
# No `pnpm install`: the sweeper imports only `node:` builtins
224262
# (`process`, `child_process`, `fs`, `url`), global `fetch`, and one
225263
# repo-local helper — no npm dependency, so installing the workspace here
226-
# would buy nothing and would give a scheduled patrol a lockfile it could
227-
# fail on.
264+
# would buy nothing and would give this patrol a lockfile it could fail
265+
# on.
228266
#
229267
# `./` — the LOCAL action, deliberately, and this is the one consumer that
230268
# should not pin a sha. A sibling pins one because it wants a reviewed
@@ -246,7 +284,7 @@ jobs:
246284
# travels: the cheapest way to adopt the patrol is still to copy this
247285
# caller, and an unguarded fallback is what would let such a copy
248286
# rewrite some unrelated card in a sibling with this board's findings,
249-
# silently and four times a day. A number is only ever meaningful in
287+
# silently, on every run it is given. A number is only ever meaningful
250288
# the repo it was minted in.
251289
#
252290
# TO ROTATE (here): open a new `tracking`-labeled issue, put its
@@ -418,16 +456,17 @@ jobs:
418456
# `::warning::` carrying the site count. ⛔ NOT the anchor issue — that
419457
# body is owned end-to-end by `check-half-states.mjs`'s generator, and a
420458
# second writer is how half of a generated body goes stale.
421-
# HOW OFTEN: on this workflow's schedule — four times a day, six hours
422-
# apart — plus any `workflow_dispatch`, plus the `pull_request` runs the
423-
# paths filter above admits.
459+
# HOW OFTEN: once per `workflow_dispatch` — this workflow has carried no
460+
# schedule since ruling #208 (objectstack#19497) — plus the
461+
# `pull_request` runs the paths filter above admits.
424462
# WHAT IT COSTS AND WHO PAYS: the census enumerates the whole board once
425463
# (159 requests on this repo at the time of writing, cursor-paginated —
426464
# the alternative is one request per distinct number). It is paid by
427465
# THIS repository's own `secrets.GITHUB_TOKEN` core quota, the same
428-
# 5,000/hour this job already draws the live sweep from: ~636
429-
# requests/day at four runs, under half a percent of a single hour's
430-
# allowance. ⛔ No PAT, no cross-repo credential — the file's own rule.
466+
# 5,000/hour this job already draws the live sweep from: ~159 requests
467+
# per run, ~3% of a single hour's allowance, and no standing daily draw
468+
# at all now that a seat has to ask for each run. ⛔ No PAT, no
469+
# cross-repo credential — the file's own rule.
431470
#
432471
# ⛔ Gated on the repository NAME, for the reason the closed-card sweep
433472
# above states: this script is objectstack-only until a sibling has a

0 commit comments

Comments
 (0)