From 647a305226bb46aeb820ffccd8af2aff62417c68 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Sat, 23 May 2026 15:57:24 -0400 Subject: [PATCH 1/2] rules(pr-triage-tiers): codify five-class PR-triage disposition framework + deferred-to-human label workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Carves the empirical Tier 1-5 framework evolved during Otto-CLI's 2026-05-23 PR-cleanup session (27 closes from the 125 → 90 open queue) into a canonical .claude/rules/ rule. Composes with the just-created GitHub label deferred-to-human (color #FBCA04, created 2026-05-23) which lets agent unfinished-PR scans skip the rare-by-design Tier 5 cases. Per Aaron 2026-05-23: 'lirs background service is what's leaving prs sometime so we are updateing to check for unfinsihed prs first when it starts, maybe yours should do the same'. This rule provides the disposition framework that the unfinished-PR check applies. The companion edit to docs/AUTONOMOUS-LOOP-PER-TICK.md Step 1 (unfinished-PR check sub-step) is intentionally deferred to a follow-up PR — peer Otto-CLI is actively editing that file; coordinating the canonical change avoids clobbering peer work. Five tiers: Tier 1: fully redundant (all files byte-identical on main) → close as substrate-redundant Tier 2: substrate-recoverable (missing files regeneratable via existing tooling) → close with regenerate path named Tier 3: substrate-superseded (substrate landed under alt-ID / alt-filename / alt-scheme on main) → close with cross-reference Tier 4: substrate-re-derivable (operational lesson already encoded in canonical rule form OR reconstructible from observable evidence) → close with discipline-already- encoded note Tier 5: deferred-to-human (substantive + unique + NOT regeneratable from observable evidence — e.g., external-AI conversation transcripts) → tag and leave for maintainer Each tier has a substrate-honest comment template + empirical anchor from the 27 closes that evolved the framework. Lane discipline: agent applies tiers ONLY to PRs in own surface's branch lane (otto-cli/* / otto-desktop/* / otto-vscode/* / otto/* per agent-roster-reference-card.md). Do NOT triage Lior/Vera/ Riven/Alexa branches. Co-Authored-By: Claude --- .claude/rules/pr-triage-tiers.md | 193 +++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 .claude/rules/pr-triage-tiers.md diff --git a/.claude/rules/pr-triage-tiers.md b/.claude/rules/pr-triage-tiers.md new file mode 100644 index 0000000000..a4a487b6e3 --- /dev/null +++ b/.claude/rules/pr-triage-tiers.md @@ -0,0 +1,193 @@ +# PR triage tiers — five-class disposition framework for unfinished-PR cleanup + +Carved sentence: + +> Every stale unfinished PR fits one of five disposition classes; +> close with substrate-honest comment when the substrate is +> recovered/redundant/superseded/re-derivable, park only when +> unique substantive substrate is at risk. Tag `deferred-to-human` +> on the rare cases that genuinely need maintainer attention so +> agent unfinished-PR scans can skip them. + +## Operational content + +When triaging an unfinished/stale/abandoned PR (especially during +the agent-start unfinished-PR-check per +[`docs/AUTONOMOUS-LOOP-PER-TICK.md`](../../docs/AUTONOMOUS-LOOP-PER-TICK.md) +Step 1 + per [`holding-without-named-dependency-is-standing-by-failure.md`](holding-without-named-dependency-is-standing-by-failure.md)), +classify into one of five tiers and apply the standard disposition. + +### Tier 1 — Fully redundant (close as substrate-redundant) + +**Signal**: every file the PR touches is byte-identical on `origin/main`. + +**Reason it's safe to close**: substrate is already on main; PR adds nothing. + +**Disposition template**: + +```text +Closing as fully substrate-redundant: +byte-identical on origin/main. days stale, . +Per `.claude/rules/blocked-green-ci-investigate-threads.md` +stale-armed-PR Pattern A. +``` + +### Tier 2 — Substrate-recoverable (close with regenerate path named) + +**Signal**: some files missing on main, but those files are +**regeneratable via existing tooling** (e.g., PR-discussion +archives via `tools/pr-preservation/archive-pr.ts`; tick shards +that fall in a generated range). + +**Disposition template**: + +```text +Closing as substrate-recoverable: of files on main; + missing () are for +already-merged source PRs and recoverable via fresh +``. Per `.claude/rules/blocked-green-ci-investigate-threads.md` +stale-armed-PR Pattern A. +``` + +### Tier 3 — Substrate-superseded (close with alt-landing cross-reference) + +**Signal**: missing files' intent landed on main under a +different ID, filename, or scheme (e.g., new top-level row → +subdecimal scheme; ID-collision with reassigned row; +filename-convention re-ordering). + +**Disposition template**: + +```text +Closing as substrate-superseded: shipped via +. would now create + with current main. Per `.claude/rules/blocked-green-ci-investigate-threads.md` +stale-armed-PR Pattern A. +``` + +### Tier 4 — Substrate-re-derivable (close with discipline-already-encoded note) + +**Signal**: missing substrate is a small observation +(shadow-lesson, brief drift report) whose **operational lesson +is already encoded in canonical rule form** OR re-derivable from +observable evidence (commit history, broadcast bus archives, +adjacent shadow logs). + +**Disposition template**: + +```text +Closing as substrate-re-derivable: is a brief + whose operational discipline is already +encoded at `.claude/rules/.md`. Branch HEAD preserved for +optional cherry-pick if specific phrasing matters. Per +`.claude/rules/blocked-green-ci-investigate-threads.md` +stale-armed-PR Pattern A. +``` + +### Tier 5 — Park for human (tag `deferred-to-human`, do not close) + +**Signal**: missing substrate is **substantive AND unique AND +NOT regeneratable from observable evidence**. Examples: external-AI +conversation transcripts (one-time event), human-Aaron research +exchanges, novel cross-substrate synthesis, persona NOTEBOOK with +real content. + +**Disposition**: do NOT close. Apply the `deferred-to-human` +label so future agent unfinished-PR scans skip the PR (per the +`deferred-to-human` label semantics: agents leave these alone). +Post a comment naming the substantive substrate at risk so the +maintainer can pick disposition (re-land via cherry-pick, close ++ archive elsewhere, or restart fresh). + +**Comment template**: + +```text +Substrate at risk — pending maintainer disposition: + + files in this PR contain substantive unique substrate NOT +recoverable from observable evidence: +- : +- : + +Options: +- (a) cherry-pick the substantive files into a fresh small PR +- (b) close + archive the substantive files elsewhere +- (c) restart the work fresh + +Tagging `deferred-to-human` so agent unfinished-PR scans skip +this PR. Per `.claude/rules/pr-triage-tiers.md` Tier 5. +``` + +Then: `gh pr edit --add-label "deferred-to-human"`. + +## The `deferred-to-human` GitHub label + +Created 2026-05-23 (color `#FBCA04`). Semantics: + +- Agent applies it when classifying a PR as Tier 5 +- Agent unfinished-PR scans filter `-label:"deferred-to-human"` + to skip these +- Maintainer removes the label after disposition +- Empirically expected to be rare (most stale PRs are Tier 1-4); + if `deferred-to-human` accumulates, the threshold for Tier 5 + has drifted and needs re-calibration + +## When to apply this framework + +Per [`docs/AUTONOMOUS-LOOP-PER-TICK.md`](../../docs/AUTONOMOUS-LOOP-PER-TICK.md) +Step 1 (unfinished-PR check sub-step): on every cold-boot AND on +each cron tick, scan unfinished PRs authored by this agent's +surface (`otto-cli/*`, `otto-desktop/*`, `otto-vscode/*`, `otto/*` +branch prefixes per [`.claude/rules/agent-roster-reference-card.md`](agent-roster-reference-card.md)), +filter out `deferred-to-human` labels, and triage in priority +order (oldest first per the established discipline). + +## Empirical anchor — 2026-05-23 cleanup session + +This rule codifies the framework evolved across 27 PR closes +during Otto-CLI's 2026-05-23 session (PR landing as part of QoL +bundle): + +- Tier 1 closes: e.g., #3326, #3346, #3351, #3352, #3357, #3532, + #3610 (single-file or all-files-on-main cases) +- Tier 2 closes: e.g., #3317, #3318, #3344, #3347, #3354, #3669, + #3481 (PR-discussion preservation files for merged source PRs) +- Tier 3 closes: e.g., #3323, #3355, #3360, #3374, #3520, #3534 + (subdecimal-vs-top-level convergence; ID-collision) +- Tier 4 closes: e.g., #3353, #3543, #3599, #3341 (re-derivable + shadow lessons; discipline-already-encoded) +- Tier 5 parks: #3340 (Aaron-Ani-Grok research conversations + unique substrate); peer Otto picked up for cherry-pick + +## Composes with + +- [`.claude/rules/blocked-green-ci-investigate-threads.md`](blocked-green-ci-investigate-threads.md) + (Pattern A/B/C reference; this rule is the per-tier extension) +- [`.claude/rules/holding-without-named-dependency-is-standing-by-failure.md`](holding-without-named-dependency-is-standing-by-failure.md) + (PR-triage IS counter-reset decomposition work per condition #3) +- [`.claude/rules/agent-roster-reference-card.md`](agent-roster-reference-card.md) + (lane discipline — only triage PRs in your surface's lane) +- [`.claude/rules/claim-acquire-before-worktree-work.md`](claim-acquire-before-worktree-work.md) + (when re-land via cherry-pick is chosen for Tier 5) +- [`docs/AUTONOMOUS-LOOP-PER-TICK.md`](../../docs/AUTONOMOUS-LOOP-PER-TICK.md) + Step 1 (unfinished-PR-check sub-step) +- [`.claude/rules/refresh-world-model-poll-pr-gate.md`](refresh-world-model-poll-pr-gate.md) + (rate-limit tiers affect how aggressively to scan) + +## Full reasoning + +The framework emerged empirically during a 2026-05-23 Otto-CLI +session cleaning up 125 → 90 open PRs. Tier 1-4 closes were +unambiguous via per-PR file inspection (substrate-on-main check ++ alt-filename search + content sampling). Tier 5 surfaced when +PR #3340 had 2 Aaron-Ani-Grok research conversations and PR #3543 +had what looked like persona substrate (later content-inspected +to actually be re-derivable, so down-classified to Tier 4 after +inspection). + +The `deferred-to-human` label is the Aaron 2026-05-23 design +extension: "yes we can add that tag in github deferred-to-human +also i should not have to see those often but yes some humans will +like this mode of operation". Tagging rather than closing +preserves substrate-at-risk while letting agent unfinished-PR +scans filter cleanly. From b83b8fb83c7dc7fd1dca0504fde6265df040ee1b Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Sat, 23 May 2026 16:10:40 -0400 Subject: [PATCH 2/2] =?UTF-8?q?fix(rules/pr-triage-tiers):=20MD032=20?= =?UTF-8?q?=E2=80=94=20replace=20line-leading=20'+'=20with=20prose=20conne?= =?UTF-8?q?ctors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Markdownlint MD032 violations at lines 100 and 182: line-leading '+' characters interpreted as start-of-list markers requiring blank lines before. Rewrite the two affected continuations: line 100: 'close\n+ archive elsewhere' → 'close-and-archive elsewhere' line 182: 'check\n+ alt-filename + content' → 'check\nplus alt-filename and content' Per .github/workflows/gate.yml lint(markdownlint) failure on PR #4761. Co-Authored-By: Claude --- .claude/rules/pr-triage-tiers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/rules/pr-triage-tiers.md b/.claude/rules/pr-triage-tiers.md index a4a487b6e3..65edbbf7d7 100644 --- a/.claude/rules/pr-triage-tiers.md +++ b/.claude/rules/pr-triage-tiers.md @@ -96,8 +96,8 @@ real content. label so future agent unfinished-PR scans skip the PR (per the `deferred-to-human` label semantics: agents leave these alone). Post a comment naming the substantive substrate at risk so the -maintainer can pick disposition (re-land via cherry-pick, close -+ archive elsewhere, or restart fresh). +maintainer can pick disposition (re-land via cherry-pick, +close-and-archive elsewhere, or restart fresh). **Comment template**: @@ -179,7 +179,7 @@ bundle): The framework emerged empirically during a 2026-05-23 Otto-CLI session cleaning up 125 → 90 open PRs. Tier 1-4 closes were unambiguous via per-PR file inspection (substrate-on-main check -+ alt-filename search + content sampling). Tier 5 surfaced when +plus alt-filename search and content sampling). Tier 5 surfaced when PR #3340 had 2 Aaron-Ani-Grok research conversations and PR #3543 had what looked like persona substrate (later content-inspected to actually be re-derivable, so down-classified to Tier 4 after