labels: relax self caller cron to hourly, narrow issues triggers (#199)

The advisory */15 cron fired a full-board sweep four times an hour at
GitHub's 1-minute billing floor; events carry real state changes in
seconds, so the cron only backstops a forgotten handoff. Relax it to
hourly and narrow the issues: trigger to [opened, closed] — the two
actions with promptness-critical reconcile behavior — dropping the
labeled/unlabeled churn source. Per-trigger why-comments added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude-bot-andresmgsl 2026-07-28 18:10:23 +00:00
parent 0a9316f7e1
commit dfafeedeec
2 changed files with 20 additions and 2 deletions

View file

@ -5,11 +5,28 @@ name: labels
# unpinned — correct only for the repo that IS the source). Consumers write: # unpinned — correct only for the repo that IS the source). Consumers write:
# uses: heavy-duty/ceremony/.github/workflows/labels.yml@<pinned-tag> # uses: heavy-duty/ceremony/.github/workflows/labels.yml@<pinned-tag>
on: on:
schedule: [{cron: "*/15 * * * *"}] # advisory; the handoff label is the real wake # Hourly, not */15 (#199): the cron is a BACKSTOP, not the wake. Events below
# carry every real state change in seconds; the cron only catches a FORGOTTEN
# handoff, so a quiet repo loses at most the forgotten case, and only by ≤1h —
# while */15 fired a full-board sweep four times an hour at GitHub's 1-minute
# billing floor, 52% of one private consumer's runs for near-zero real work.
schedule: [{cron: "0 * * * *"}]
workflow_dispatch: # bootstraps missing labels on a fresh repo workflow_dispatch: # bootstraps missing labels on a fresh repo
# Narrowed to the two actions with promptness-critical reconcile behavior
# (#199): `opened` drives the mint→needs-triage check (issueflow's opened-only
# path), `closed` drives the blocker-closes→ready self-heal (crew#96/#98). The
# dropped actions — labeled/unlabeled/assigned/unassigned/edited/reopened —
# only feed validation and the 48h claim clock, which the hourly cron catches
# within one cadence; labeled/unlabeled were also the dominant issues-churn
# source. The PR handoff wake is pull_request_target:labeled, NOT issues, so
# this does not touch the handoff.
issues: issues:
types: [opened, edited, assigned, unassigned, labeled, unlabeled, closed, reopened] types: [opened, closed]
pull_request_target: pull_request_target:
# Every PR arrives from a fork, so these carry the head/draft/review facts
# the sweep derives state:* from. labeled/unlabeled are the handoff wake —
# the author's optimistic state:needs-human write, confirmed or corrected
# here in seconds (#11); synchronize re-derives on every push;
# review_requested/review_request_removed wake the sweep that clears (or # review_requested/review_request_removed wake the sweep that clears (or
# restores) blocker:unrequested — without them the one event that makes # restores) blocker:unrequested — without them the one event that makes
# the label false could not clear it, and a quiet repo wore the red flag # the label false could not clear it, and a quiet repo wore the red flag

1
changelog.d/199.md Normal file
View file

@ -0,0 +1 @@
- `labels` caller — the advisory sweep cron relaxes from `*/15` to hourly and the `issues:` trigger narrows to `[opened, closed]`, cutting how often a full-board reconcile is billed without changing what a sweep does or delaying any real state change past one cadence (#199). Events still carry every transition in seconds; the cron only backstops a forgotten handoff. Each caller trigger now carries a comment saying why it is subscribed, and the reconcile concurrency stays `cancel-in-progress: false` — cancelling a sweep mid-board is the race that guard exists to prevent.