Rename tier1_authority / retire "Tier 1"/"Tier 2" merge-authority prose — reopens design 009's Non-goal nf-lwxv ← Beads

closed priority 2 task unassigned activesession:tier1-rename

Twinned from https://github.com/cfsh/ninefold/issues/1093 by tools/beads/import_github.py's reconcile pass.

Aedan's ask, verbatim (PR #1092 inline thread, 2026-08-18, on .claude/commands/prototype.md's tier1_authority mention): "where does tier1_authority come from? We are trying to kill all references to tier xyz"

Context

tier1_authority() (tools/nflib/authority.py:226) is the function that answers "may this PR merge WITHOUT a human approval?" — what the reviewer verdicts and PR labels now call approval:auto/approval:human. It was introduced in #704 ("merge authority as a required status check, and one implementation of the question"), part of the original Tier-1 merge-authority work.

Two rounds of "tier" cleanup have already shipped:

- #971 (design 009 T3, closed/shipped): the reviewer's advisory tier:1/2/3 labels → risk:{routine,infra,feel}. - #1077 (closed/shipped, just landed as of this issue): "Tier 0" wording describing the reviewer bot's own comment-only stage, dropped across CHARTER.md, DESIGN.md, README.md, notes/reviewer.md, DEVEL.md, CLAUDE.md, notes/merging.md.

**Both explicitly carved out tier1_authority and "Tier 1"/"Tier 2" prose as a Non-goal.** #1077's Non-goals section, verbatim:

> The perimeter's "Tier 1"/"Tier 2" merge-authority naming > (tools/nflib/authority.py's tier1_authority(), "ordinary Tier 1" in > CLAUDE.md and notes/merging.md, design 009's own "Tier 2 > (tools/nflib/)" reference to the philosophy's hardened tier). Design 009 > deliberately kept this vocabulary — it isn't the leftover this issue is > about, and renaming it would reopen a decision design 009 already made. A > future round can revisit it if it ever causes real confusion; this issue > doesn't argue that case.

That's design_docs/009-the-games-audit-lane.md §5's own ruling: "The word tier is freed to mean only NINEFOLD_PHILOSOPHY.md's hacky vs hardened — prose vocabulary, never a label" — but 009 chose to keep "Tier 1"/"Tier 2" itself as the perimeter's own name for the two merge-authority paths, alongside that same freed sense. **This issue is Aedan reopening that decision** — the coexistence is exactly the confusion #1077 fixed for "Tier 0", now recurring for "Tier 1".

Live (non-historical) references, grep -n "tier1_authority\|[Tt]ier[ -]1\b\|[Tt]ier[ -]2\b":

- tools/nflib/authority.py — the function itself (:226, exported at :69) and ~15 docstring/comment mentions of "Tier 1" (`:18, 242, 245, 282, 292, 345, 352, 401, 445, 474, 629, 636, 675`). - tools/nflib/perimeter.py — module docstring title (:1: "The Tier-1 merge perimeter…"), and ~7 more prose mentions (`:100-101, 105, 190, 298, 431-432, 634`). - tools/pr/merge_pr.py — ~20 mentions across the module docstring and inline comments (`:28, 32, 34, 51, 132, 602, 627, 702-703, 769-770, 808, 830, 833, 1102, 1106, 1131-1132, 1147, 1216, 1235`). - notes/merging.md:29 — "tier1_authority". - tools/reviewer/CHARTER.md:226 — "Tier-1 authority".

Prescription

Rename tier1_authority() to a name built from the live vocabulary (approval:auto/approval:human) rather than a tier number — e.g. approval_auto_authority() or unattended_merge_authority() (pick one; § Open questions). Update every call site (tools/pr/merge_pr.py:132,808,1147) and every docstring/comment above to match, same "drop the number, keep the sense" pattern #1077 used for "Tier 0" — most sites already gloss "Tier 1" as "no human approval"/"approval:auto" right next to the tier wording, so this is mostly deletion, not new prose. notes/merging.md and tools/reviewer/CHARTER.md get the same treatment at their one site each.

Follow #1077's own Non-goals precedent for what NOT to touch:

- design_docs/009-the-games-audit-lane.md and other accepted design docs — frozen prose, amendments only, never rewritten after acceptance. - notes/history.md — case law, quotes real history verbatim. - Any tier=N/tier:N legacy-grammar parsing or its test fixtures (tools/nflib/verdict.py, tools/nflib/test_data/pr_sample.json, engine_test.py's LEGACY_TIER_LABELS cases) — unrelated to this function, must keep parsing old verdicts forever per design 009 T3. - NINEFOLD_PHILOSOPHY.md's own "tier" usage (hacky-vs-hardened) — the sense every prior round has explicitly preserved.

Test plan

Pure rename — no behavior change. grep -n "tier1_authority" tools/ notes/ returns nothing outside test files exercising the renamed symbol under its new name; ./presubmit.py --all green (particularly tools/nflib/authority_test.py, tools/pr/merge_pr_test.py, tools/pr/perimeter_check_test.py, tools/pr/review_now_test.py, tools/pr/digest_test.py — all currently reference tier1_authority by name or assert on "Tier 1" strings per the grep above).

PR shape

One PR — mechanical rename at one cognitive level (E3), same shape as #1077. Touches tools/nflib/* (governed) so it waits for Aedan's approval regardless of how it's split; no benefit to splitting further.

Non-goals

Everything under "Follow #1077's own Non-goals precedent" above.

Open questions

1. Replacement name for tier1_authority(). Candidates: approval_auto_authority(), unattended_merge_authority(), no_human_needed(). Default: approval_auto_authority() — matches the label it decides (approval:auto) most directly. Not worth a review cycle to pre-negotiate; ships with the dev's best call if unanswered. 2. Whether the module docstring title of perimeter.py ("The Tier-1 merge perimeter…") should also drop "Tier-1" or keep it as a proper noun now that #1077 established the pattern of dropping tier numbers entirely. Default: drop it, same as every other site — "The approval:auto merge perimeter" or equivalent.

Dependencies

None.

Comments

No comments.

Add a comment