From 2728f3b41b6cb0b92d56ee6790efd9e5137140ea Mon Sep 17 00:00:00 2001 From: gavinbee <29419542+gavinbee@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:51:57 -0400 Subject: [PATCH 1/2] Document the no-issue PR exception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AGENTS.md said "For every change: open a GitHub issue first", and CONTRIBUTING.md said the same. We stopped meaning it — a one-bullet docs fix now goes straight to a PR labelled no-issue, with a NO-ISSUE trailer saying why. Leaving that undocumented means the next agent either files an issue for a typo or reads a no-issue PR as a rule violation. The exception touches three steps, not one: a no-issue PR also has no number for the branch name, and nothing to put in "Closes #N". All three are amended in both files, with the reasoning in CONTRIBUTING.md, which is where the why belongs. settings.yml gains a labels block naming no-issue, recorded but not applied — apply-settings.py reads only repository, branches and rulesets, so labels are still created per repo by hand. Documenting a key we don't act on yet is this file's stated convention; wiring it up is left to the issue. The exception explicitly does not cover changes to the rules themselves, which is why this one has an issue. Closes #46 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01CgLE8cg9huy2EZnRoXhmwp --- .github/settings.yml | 12 ++++++++++++ AGENTS.md | 7 ++++++- CONTRIBUTING.md | 27 ++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/.github/settings.yml b/.github/settings.yml index bc9fc5e..945e29c 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -24,6 +24,18 @@ repository: delete_branch_on_merge: true allow_update_branch: true +# Labels that should exist in every repo. +# +# NOT YET APPLIED. `apply-settings.py` ignores this block — it acts on `repository`, +# `branches` and `rulesets` only, so these labels still have to be created per repo with +# `gh label create`. Recorded here so the canonical set has one home, per this file's +# convention of documenting keys we don't act on yet. Wiring it up is +# https://github.com/swimblocks/.github/issues/46. +labels: + - name: no-issue + color: ededed + description: Change small enough to skip the issue-first rule; rationale is in the PR body + # Branch protection for public repos is handled via GitHub Rulesets (see `rulesets:` below), # which support bypass actors so org owners and repo admins can force-push without extra steps # — just `git push origin main --force`. GitHub records the bypass in the audit log. diff --git a/AGENTS.md b/AGENTS.md index b8a793e..1bfade8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,7 +47,12 @@ gcloud auth application-default login For **every** change: 1. **Open a GitHub issue first.** Describe the change. This is the unit of work. -2. **Branch** off `main`, named `-`. + - *Exception:* a change small enough to explain itself — a typo, a doc clarification, + recording a decision already made — may go straight to a PR. Label it `no-issue` and + end the description with `NO-ISSUE: `. Use a real issue whenever the + change needs discussion or has acceptance criteria. +2. **Branch** off `main`, named `-` (or a descriptive slug, for a + `no-issue` PR). 3. **Make focused commits.** Coherent, single-purpose. Run `ruff check .` and `pytest -q` locally before pushing. 4. **Hand off for local review — do not open the PR.** Nobody opens a pull request carrying diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 005de91..907cf5e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,10 @@ explicitly overrides it. ## Workflow: issue → branch → PR → squash-merge 1. **Open an issue first.** Describe the problem or feature. This is the unit of work. -2. **Branch** off `main`, named `-` (e.g. `42-fix-date-parsing`). + See [the `no-issue` exception](#the-no-issue-exception) for changes small enough to + skip this. +2. **Branch** off `main`, named `-` (e.g. `42-fix-date-parsing`), + or a descriptive slug when there is no issue. 3. **Do the work.** Keep commits coherent. Run tests + lint locally before pushing. 4. **Read the change before it becomes a PR.** A pull request is a claim that its author stands behind the change, so nobody opens one carrying work the author hasn't actually @@ -43,6 +46,7 @@ explicitly overrides it. PR description. A question written into a PR reads as though the author is asking their reviewers, which sponsors a question they never asked. 5. **Open a PR** whose description includes `Closes #` and explains the *why*. + A `no-issue` PR has no number to close, and carries the `NO-ISSUE:` trailer instead. 6. **CI must be green** (lint + tests) before merge. 7. **Hand off for merge.** Agents do **not** self-merge: after CI is green, post the PR link and stop. @@ -53,6 +57,27 @@ explicitly overrides it. deletes the branch. The squash commit message should carry the meaningful detail, not just the PR title. +### The `no-issue` exception + +A change small enough to explain itself — a typo, a doc clarification, recording a decision +already made — may go straight to a PR. Label it `no-issue` and end the description with a +trailer saying why: + +``` +NO-ISSUE: Clarifying Documentation +``` + +The ceremony in step 1 is worth paying whenever a change needs a decision recorded, argued, +or found again later. It is pure overhead when the change carries its own justification in +one paragraph. The label and the trailer are what keep the exception **visible and +auditable** rather than silent: every PR that skipped the issue says so, in a form you can +search for. + +Use a real issue whenever the change needs discussion, has acceptance criteria, or is +something a future reader would look for in the tracker. Changes to the rules in this file +are always in that category — a policy that nobody can find the reasoning for is a policy +that gets re-litigated. + ### Solo-admin merge path Until a second code owner exists, the author satisfying `require_code_owner_reviews` on their From 801effe2c55dfdc1fcaacec1b066ac7d1f78cc05 Mon Sep 17 00:00:00 2001 From: gavinbee <29419542+gavinbee@users.noreply.github.com> Date: Thu, 3 Sep 2026 23:01:18 -0400 Subject: [PATCH 2/2] Point the labels comment at the work that is actually left MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment said wiring up label reconciliation was tracked by #46 — the issue this PR was closing. That made it a dangling reference: on merge it would have cited a closed issue that never did the wiring, which is the bare-TODO-with-a-link that AGENTS.md section 4 exists to prevent. Label reconciliation is in scope for #46, so the fix is for this PR to stop closing it. The comment now says what remains and that #46 stays open until it lands. Refs #46 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01CgLE8cg9huy2EZnRoXhmwp --- .github/settings.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/settings.yml b/.github/settings.yml index 945e29c..d223212 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -26,11 +26,10 @@ repository: # Labels that should exist in every repo. # -# NOT YET APPLIED. `apply-settings.py` ignores this block — it acts on `repository`, -# `branches` and `rulesets` only, so these labels still have to be created per repo with -# `gh label create`. Recorded here so the canonical set has one home, per this file's -# convention of documenting keys we don't act on yet. Wiring it up is -# https://github.com/swimblocks/.github/issues/46. +# NOT YET APPLIED. `apply-settings.py` acts on `repository`, `branches` and `rulesets` +# only, so these labels are still created per repo by hand with `gh label create`. This +# block is the canonical set; teaching the reconciler to apply it is the remaining work on +# https://github.com/swimblocks/.github/issues/46, which stays open until it lands. labels: - name: no-issue color: ededed