From 3eff28e6240367c7467b16666896ac7b35bcc761 Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <304681515+codex-bot-andresmgsl@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:27:29 +0000 Subject: [PATCH 1/2] docs: explain sweep cadence and manual dispatch --- .github/workflows/self-labels.yml | 20 +++++++++------- LABELS.md | 3 ++- changelog.d/203.md | 5 ++++ docs/CONSUMERS.md | 39 ++++++++++++++++++++----------- 4 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 changelog.d/203.md diff --git a/.github/workflows/self-labels.yml b/.github/workflows/self-labels.yml index e955e52..1b4d0df 100644 --- a/.github/workflows/self-labels.yml +++ b/.github/workflows/self-labels.yml @@ -5,17 +5,19 @@ name: labels # unpinned — correct only for the repo that IS the source). Consumers write: # uses: heavy-duty/ceremony/.github/workflows/labels.yml@ on: - # Hourly, not */15 (#199): the cron is the sweep's ONLY wake for the four - # transition classes no subscribed event carries — a review verdict landing - # (there is no pull_request_review trigger here), blocker:ci-red set or cleared - # (no check_suite/check_run/workflow_run), a blocker:conflict when ANOTHER PR + # The consumer owns this cadence (#203). Hourly is the recommended default + # when no other engine drives board state: the cron is then the sweep's ONLY + # wake for four transition classes — a review verdict landing (there is no + # pull_request_review trigger here), blocker:ci-red set or cleared (no + # check_suite/check_run/workflow_run), a blocker:conflict when ANOTHER PR # merges under this one, and the time-based stale / 48h claim-reclaim. The - # events below carry the rest in seconds. So hourly trades ≤1h of latency on - # those four for dropping */15's four full-board sweeps an hour at GitHub's - # 1-minute billing floor — 52% of one private consumer's runs. Do NOT delete - # this cron — it is the discovery path for those four, not a forgotten-handoff net. + # events below carry the rest in seconds. Hourly trades ≤1h of latency on + # those four for one full-board sweep at GitHub's 1-minute billing floor. If + # another engine writes some of those transitions, only the classes with no + # other writer bound the cadence; relax it only as that list shrinks. schedule: [{cron: "0 * * * *"}] - workflow_dispatch: # bootstraps missing labels on a fresh repo + # A manual full-board sweep, including taxonomy bootstrap on a fresh repo. + workflow_dispatch: # Narrowed (#199) to the actions that carry a queue-state change the hourly # cron cannot wait one cadence for — dropping only labeled/unlabeled/assigned/ # unassigned, which feed validation and the 48h claim clock (caught within one diff --git a/LABELS.md b/LABELS.md index b8eaf55..5421484 100644 --- a/LABELS.md +++ b/LABELS.md @@ -3,7 +3,8 @@ The taxonomy shared across the heavy-duty repos. Only the `scope:` set differs per repo (each repo's `.github/labels.conf` names its actual surfaces); everything else below is core and identical everywhere, created by -the labels workflow's bootstrap dispatch (issue #10). +the labels workflow's dispatch (which is also the operator's manual +full-board reconcile sweep; issue #10). Two state machines share the taxonomy: the **PR machine** (proven in box/rig/cast, reconciled by machinery) and the **issue flow** (the diff --git a/changelog.d/203.md b/changelog.d/203.md new file mode 100644 index 0000000..da1b8b6 --- /dev/null +++ b/changelog.d/203.md @@ -0,0 +1,5 @@ +### Changed + +- Labels automation docs now make sweep cadence a consumer-owned tradeoff, + retain hourly as the engine-less default, and document manual dispatch as + the operator's immediate full-board sweep (#203). diff --git a/docs/CONSUMERS.md b/docs/CONSUMERS.md index 5a4a4c9..ad1abf0 100644 --- a/docs/CONSUMERS.md +++ b/docs/CONSUMERS.md @@ -122,7 +122,8 @@ the machinery at all: [Labels automation](#labels-automation), plus `.github/labels.conf` (panel + the repo's `scope:*` rows) and `.github/labeler.yml` (the path→scope globs). Run `workflow_dispatch` once — **this bootstraps - the taxonomy, `release` label included**. + the taxonomy, `release` label included** — and use it again whenever an + operator needs a full-board sweep immediately. 7. **The artifact hook** (optional): `.github/actions/release-artifact/` per [The artifact hook](#the-artifact-hook). No hook → the source tarball is the package. @@ -296,15 +297,18 @@ The complete caller is: ```yaml name: labels on: - # Hourly, not */15 (#199): the cron is the sweep's only wake for the - # transitions no subscribed event carries — a review verdict landing (no - # pull_request_review trigger), blocker:ci-red set/cleared, a blocker:conflict - # when another PR merges under this one, and the time-based stale / 48h + # The consumer owns this cadence (#203). Hourly is the recommended default + # when no other engine drives board state: the cron is then the sweep's only + # wake for four transition classes — a review verdict landing (no + # pull_request_review trigger), blocker:ci-red set/cleared, blocker:conflict + # when another PR merges under this one, and time-based stale / 48h # claim-reclaim. Events below carry the rest in seconds. Hourly trades ≤1h of - # latency on those four for dropping */15's four sweeps an hour at GitHub's - # 1-minute floor. Keep the cron — it is the discovery path, not a safety net. + # latency on those four for one full-board sweep at GitHub's 1-minute floor. + # If another engine writes some of those transitions, only the classes with + # no other writer bound the cadence; relax it only as that list shrinks. schedule: [{cron: "0 * * * *"}] - workflow_dispatch: # bootstraps missing labels on a fresh repo + # A manual full-board sweep, including taxonomy bootstrap on a fresh repo. + workflow_dispatch: pull_request_target: # Fork PRs; these carry the head/draft/review facts state:* derives from. # labeled/unlabeled are the handoff wake (state:needs-human confirmed here); @@ -398,11 +402,20 @@ Core state, blocker, work-queue, and release labels come from ceremony. Scope rows remain consumer-owned because paths and surfaces differ by repository. After adding the caller and configuration, run `workflow_dispatch` once to -bootstrap labels on a fresh repository. Scheduled and PR-triggered runs only -reconcile; they do not repeatedly upsert the taxonomy. When a ceremony pin -bump adds a core label, bump the pin first and then re-dispatch -`workflow_dispatch`; the scheduled sweep warns when the pinned taxonomy -declares a core label the repository lacks. +bootstrap labels on a fresh repository. It is also the operator's general +manual full-board sweep — the answer when the board looks wrong now rather +than after the next scheduled cadence: + +```sh +gh workflow run labels.yml -R / +``` + +Ceremony dogfoods the caller under the filename `self-labels.yml`, so the +equivalent command in this repository substitutes that filename. Scheduled +and PR-triggered runs only reconcile; they do not repeatedly upsert the +taxonomy. When a ceremony pin bump adds a core label, bump the pin first and +then re-dispatch `workflow_dispatch`; the scheduled sweep warns when the +pinned taxonomy declares a core label the repository lacks. ## Doctrine mirror From 4198597834ca7babaab2dcb3a95f602494fbe218 Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <304681515+codex-bot-andresmgsl@users.noreply.github.com> Date: Wed, 29 Jul 2026 10:37:03 +0000 Subject: [PATCH 2/2] docs: correct labels maintenance cadence --- .github/workflows/self-labels.yml | 8 +++++--- LABELS.md | 11 +++++++---- docs/CONSUMERS.md | 8 +++++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/self-labels.yml b/.github/workflows/self-labels.yml index 1b4d0df..272f429 100644 --- a/.github/workflows/self-labels.yml +++ b/.github/workflows/self-labels.yml @@ -12,9 +12,11 @@ on: # check_suite/check_run/workflow_run), a blocker:conflict when ANOTHER PR # merges under this one, and the time-based stale / 48h claim-reclaim. The # events below carry the rest in seconds. Hourly trades ≤1h of latency on - # those four for one full-board sweep at GitHub's 1-minute billing floor. If - # another engine writes some of those transitions, only the classes with no - # other writer bound the cadence; relax it only as that list shrinks. + # those four while cutting nominal scheduled sweeps from four an hour to one + # at GitHub's 1-minute billing floor. Do not delete the cron: it is their + # discovery path. If another engine writes some of those transitions, only + # the classes with no other writer bound the cadence; relax it only as that + # list shrinks. schedule: [{cron: "0 * * * *"}] # A manual full-board sweep, including taxonomy bootstrap on a fresh repo. workflow_dispatch: diff --git a/LABELS.md b/LABELS.md index 5421484..8eba639 100644 --- a/LABELS.md +++ b/LABELS.md @@ -212,10 +212,13 @@ on a PR would say the same thing twice and drift. ## Maintenance -The labels workflow (issue #10) recomputes PR state statelessly on PR events -plus a 15-minute advisory cron, and bootstraps this taxonomy idempotently on -manual dispatch. The sweep warns when the core taxonomy declares a label the -repository lacks. The same workflow reconciles issue-flow labels on issue +The labels workflow (issue #10) recomputes PR state statelessly on subscribed +events plus a consumer-owned scheduled discovery sweep. Hourly is the +recommended default when no other engine drives board state; relax it only as +the transition classes with no other writer shrink. Manual dispatch both +bootstraps this taxonomy idempotently and runs the operator's on-demand +full-board reconcile. The sweep warns when the core taxonomy declares a label +the repository lacks. The same workflow reconciles issue-flow labels on issue events and during the scheduled sweep. Default GitHub labels (`duplicate`, `invalid`, `question`, `wontfix`, `help wanted`, `good first issue`) are deleted at bootstrap — a `question` is a discussion, not an issue. diff --git a/docs/CONSUMERS.md b/docs/CONSUMERS.md index ad1abf0..eaac5c1 100644 --- a/docs/CONSUMERS.md +++ b/docs/CONSUMERS.md @@ -303,9 +303,11 @@ on: # pull_request_review trigger), blocker:ci-red set/cleared, blocker:conflict # when another PR merges under this one, and time-based stale / 48h # claim-reclaim. Events below carry the rest in seconds. Hourly trades ≤1h of - # latency on those four for one full-board sweep at GitHub's 1-minute floor. - # If another engine writes some of those transitions, only the classes with - # no other writer bound the cadence; relax it only as that list shrinks. + # latency on those four while cutting nominal scheduled sweeps from four an + # hour to one at GitHub's 1-minute floor. Do not delete the cron: it is their + # discovery path. If another engine writes some of those transitions, only + # the classes with no other writer bound the cadence; relax it only as that + # list shrinks. schedule: [{cron: "0 * * * *"}] # A manual full-board sweep, including taxonomy bootstrap on a fresh repo. workflow_dispatch: