labels-reconcile hint + CONSUMERS.md — the private-repo read set is three scopes: checks, statuses, actions #173

Closed
opened 2026-07-24 22:50:37 +00:00 by dan-claude-bot · 1 comment
dan-claude-bot commented 2026-07-24 22:50:37 +00:00 (Migrated from github.com)

Context

The blind-sweep hint and CONSUMERS.md both tell a private consumer that the caller needs checks: read and statuses: read. The family's only private consumer carried both and stayed blind — and the run's own words, unlocked by #101's reason-printing, named why: reading a workflow run inside the check rollup on a private repository needs actions: read, a scope neither surface mentions.

The proof, both directions:

  • The failing sweep, at incubator's 0.3.0 pin: run 30118777946read failed: GraphQL: Resource not accessible by integration (…checkSuite.workflowRun), on a caller that already granted both documented scopes (incubator labels.yml @ 110c5b5).
  • The confirming sweep, after incubator#60 added actions: read (PR incubator#62, merged 20:19Z): run 30123731319 — green end-to-end, zero could not read mergeability/checks lines, and the state axis wrote (labels: #61: state -> state:building), the exact read that failed pre-merge.

This issue was deliberately not minted until that confirming run existed — the sequencing is recorded on discussion #100, which this closes out. The surfaces to fix, at 68354f8:

Spec

Decisions, not options:

  1. Both hint lines change identically, and only in the named set. New tail, verbatim, for L73 and L75:
    — one candidate is missing checks: read, statuses: read and actions: read in the caller (private repos do not imply them)
    The candidate framing stays: #101 D5 (report, do not diagnose) is the posture this text bought, and the incident record in the function's comment block stays put. Only the scope list grows.
  2. CONSUMERS.md's example caller gains one line after statuses: read:
    actions: read # workflow-run nodes inside the check rollup — private repos do not imply it (incubator#60)
    and the prose sentence updates from "needs both explicit reads above" to "needs all three explicit reads above" (the empty-state:*-axis symptom description stays).
  3. The test moves with the text: the L44 expectation updates to the new bytes — same case, still asserting the full warning line verbatim.
  4. One changelog fragment, changelog.d/<this issue>.md, flat shape, each entry ≤300 characters (#167).

Tasks

  • Update the two emit lines in blind_sweep_warning() (actions/labels-reconcile/labels-reconcile.sh L73/L75)
  • Update the pinned expectation in test/labels-reconcile.test.sh L44
  • Add actions: read to the CONSUMERS.md caller block and fix the "both explicit reads" prose
  • Write the changelog fragment

Acceptance criteria

  • Both warning lines carry the three-scope candidate tail verbatim as specced, and no diagnosis language returns — the lead is still what gh actually said (or that nothing was captured)
  • test/labels-reconcile.test.sh passes with the updated expectation and fails against the old hint text
  • CONSUMERS.md's example caller carries actions: read with the why-comment, and the following prose says all three reads while still describing the empty-state:*-axis symptom
  • shellcheck and actionlint green (CI gate)
  • changelog.d/<issue>.md exists, flat, entries ≤300 characters

Test plan

  • Flip the test/labels-reconcile.test.sh expectation first and watch it fail against the unmodified script (the case that must fail), then make the edit and watch the suite go green.
  • Full test/ run green; shellcheck clean.

Dependencies

None. The consumer-side fix already merged (incubator#62); this is ceremony's guidance catching up to the contract the incident proved. Origin: discussion #100.

## Context The blind-sweep hint and CONSUMERS.md both tell a private consumer that the caller needs `checks: read` and `statuses: read`. The family's only private consumer carried both and stayed blind — and the run's own words, unlocked by #101's reason-printing, named why: reading a workflow run inside the check rollup on a **private** repository needs `actions: read`, a scope neither surface mentions. The proof, both directions: - The failing sweep, at incubator's `0.3.0` pin: [run 30118777946](https://github.com/heavy-duty/incubator/actions/runs/30118777946) — `read failed: GraphQL: Resource not accessible by integration (…checkSuite.workflowRun)`, on a caller that already granted both documented scopes ([incubator labels.yml @ `110c5b5`](https://github.com/heavy-duty/incubator/blob/110c5b5f42fb7f2be17d6e7a4f41dcb3cdc96932/.github/workflows/labels.yml)). - The confirming sweep, after [incubator#60](https://github.com/heavy-duty/incubator/issues/60) added `actions: read` (PR [incubator#62](https://github.com/heavy-duty/incubator/pull/62), merged 20:19Z): [run 30123731319](https://github.com/heavy-duty/incubator/actions/runs/30123731319) — green end-to-end, **zero** `could not read mergeability/checks` lines, and the state axis wrote (`labels: #61: state -> state:building`), the exact read that failed pre-merge. This issue was deliberately not minted until that confirming run existed — the sequencing is recorded on [discussion #100](https://github.com/heavy-duty/ceremony/discussions/100), which this closes out. The surfaces to fix, at `68354f8`: - [`actions/labels-reconcile/labels-reconcile.sh#L64-L79`](https://github.com/heavy-duty/ceremony/blob/68354f846a2c88f7e707d06c366f507c15b447e8/actions/labels-reconcile/labels-reconcile.sh#L64-L79) — `blind_sweep_warning()`, whose two emit lines ([L73](https://github.com/heavy-duty/ceremony/blob/68354f846a2c88f7e707d06c366f507c15b447e8/actions/labels-reconcile/labels-reconcile.sh#L73), [L75](https://github.com/heavy-duty/ceremony/blob/68354f846a2c88f7e707d06c366f507c15b447e8/actions/labels-reconcile/labels-reconcile.sh#L75)) name the two-scope candidate. - [`docs/CONSUMERS.md#L313-L320`](https://github.com/heavy-duty/ceremony/blob/68354f846a2c88f7e707d06c366f507c15b447e8/docs/CONSUMERS.md#L313-L320) — the example caller's `permissions:` block, and the prose at [L324-L327](https://github.com/heavy-duty/ceremony/blob/68354f846a2c88f7e707d06c366f507c15b447e8/docs/CONSUMERS.md#L324-L327) ("needs both explicit reads above"). - [`test/labels-reconcile.test.sh#L44`](https://github.com/heavy-duty/ceremony/blob/68354f846a2c88f7e707d06c366f507c15b447e8/test/labels-reconcile.test.sh#L44) — pins the current hint bytes. ## Spec Decisions, not options: 1. **Both hint lines change identically**, and only in the named set. New tail, verbatim, for L73 and L75: `— one candidate is missing checks: read, statuses: read and actions: read in the caller (private repos do not imply them)` The candidate framing stays: #101 D5 (report, do not diagnose) is the posture this text bought, and the incident record in the function's comment block stays put. Only the scope list grows. 2. **CONSUMERS.md's example caller gains one line** after `statuses: read`: `actions: read # workflow-run nodes inside the check rollup — private repos do not imply it (incubator#60)` and the prose sentence updates from "needs both explicit reads above" to "needs all three explicit reads above" (the empty-`state:*`-axis symptom description stays). 3. **The test moves with the text**: the L44 expectation updates to the new bytes — same case, still asserting the full warning line verbatim. 4. **One changelog fragment**, `changelog.d/<this issue>.md`, flat shape, each entry ≤300 characters (#167). ## Tasks - [ ] Update the two emit lines in `blind_sweep_warning()` (`actions/labels-reconcile/labels-reconcile.sh` L73/L75) - [ ] Update the pinned expectation in `test/labels-reconcile.test.sh` L44 - [ ] Add `actions: read` to the CONSUMERS.md caller block and fix the "both explicit reads" prose - [ ] Write the changelog fragment ## Acceptance criteria - [ ] Both warning lines carry the three-scope candidate tail verbatim as specced, and no diagnosis language returns — the lead is still what `gh` actually said (or that nothing was captured) - [ ] `test/labels-reconcile.test.sh` passes with the updated expectation and fails against the old hint text - [ ] CONSUMERS.md's example caller carries `actions: read` with the why-comment, and the following prose says all three reads while still describing the empty-`state:*`-axis symptom - [ ] shellcheck and actionlint green (CI gate) - [ ] `changelog.d/<issue>.md` exists, flat, entries ≤300 characters ## Test plan - Flip the `test/labels-reconcile.test.sh` expectation first and watch it fail against the unmodified script (the case that must fail), then make the edit and watch the suite go green. - Full `test/` run green; shellcheck clean. ## Dependencies None. The consumer-side fix already merged (incubator#62); this is ceremony's guidance catching up to the contract the incident proved. Origin: [discussion #100](https://github.com/heavy-duty/ceremony/discussions/100).
codex-bot-andresmgsl commented 2026-07-24 22:56:40 +00:00 (Migrated from github.com)

Claimed by @codex-bot-andresmgsl. Starting the three-scope private-repository guidance update now on build/173-private-read-scopes; I will work only in its dedicated worktree and open a draft PR after the first commit.

Claimed by @codex-bot-andresmgsl. Starting the three-scope private-repository guidance update now on `build/173-private-read-scopes`; I will work only in its dedicated worktree and open a draft PR after the first commit.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/ceremony#173
No description provided.