Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .claude/skills/github-project-triage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
name: github-project-triage
description: >-
Triage GitHub issues and PRs into maintainer-facing item cards and sort them
into autonomous / needs-owner / defer buckets. Use when asked to "triage" a
repo or the backlog, or as the first step of the maintainer-orchestrator loop.
Defaults to the current repo; only goes org-wide when explicitly told ("all",
"broad", "org-wide").
---

# GitHub Project Triage

Turn an open queue into decisions. Triage produces **item cards** a maintainer
can act on, then sorts them so the orchestrator knows what to do.

## Scope

- If invoked inside a Git repo with a GitHub remote (or a Routine cloned a
specific repo), triage **only that repo**.
- Only broaden to multiple repos / the whole `ITSEZMONEY` org when the prompt
explicitly says `all`, `broad`, `org-wide`, or `everything`.
Comment on lines +20 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The reference to the ITSEZMONEY organization is copied from the gate-slip repository. It should be updated to the current organization/user (adityash8) to ensure the AI agent scopes its triage correctly.

Suggested change
- Only broaden to multiple repos / the whole `ITSEZMONEY` org when the prompt
explicitly says `all`, `broad`, `org-wide`, or `everything`.
- Only broaden to multiple repos / the whole `adityash8` org when the prompt
explicitly says `all`, `broad`, `org-wide`, or `everything`.

Comment on lines +20 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the hard-coded source organization

When the routine is invoked with all/org-wide, this scope rule directs triage at the hard-coded ITSEZMONEY org even though this repository's metadata points to github.com/adityash8/exit-zero. That makes an org-wide ExitZero maintenance run inspect and potentially mutate the wrong organization while missing the intended owner/repo set; derive the org from the selected repositories instead of the copied source repo.

Useful? React with 👍 / 👎.


## Discover the queue

Use the **GitHub MCP connector** (preferred) or `gh`:
- Open PRs (with CI status, requested reviewers, draft state, mergeability).
- Open issues (with labels, age, last activity).
- For each, the last few comments and the CI job summary.

There is no `repobar` dependency — query GitHub directly. Batch reads where the
connector allows it; don't fetch full logs until an item needs them.

## Item card

For every open issue/PR, produce:

| Field | What to capture |
| --- | --- |
| **URL / #** | Direct link. |
| **What** | One line: what this issue/PR is. |
| **Why it matters** | Impact / who it affects. |
| **Author trust** | Per the auto-merge allowlist: `adityash8` = **trusted**; everyone else — other org members, returning/first-time/external contributors, forks, and bots (Dependabot/Renovate) — = **untrusted**. State the factual signal, not a vibe. |
| **Type** | bug · feature · dependency · security · docs · chore |
| **Fit** | good / mixed / poor + one-line reason (does it match the product?). |
| **Risk** | low / medium / high + blast radius (what breaks if wrong). |
| **Proof** | CI state · local repro · test coverage · manual/E2E validation. |
| **Blockers** | Missing repro, failing CI, needs decision, needs creds, merge conflict. |
| **Next action** | The single concrete next step. |

Trust here is an **explicit allowlist for auto-merge**, not a vibe: only
`adityash8` is trusted. Untrusted authorship doesn't mean a bad patch — it means
the item cannot auto-merge and routes to **needs-owner** (draft PR), even with
green CI. The sole exception is a **bot dependency bump**, which may auto-merge
if it meets every low-risk gate. Trust never substitutes for green CI and a sane
diff; cite factual signals (account, prior merged PRs) when noting it.

## Risk heuristics (ITSEZMONEY / gate-slip context)

Treat as **high risk** anything touching: auth/Passport/OAuth, payments/Stripe,
`certificates/` or any key/secret, DB schema or migrations (`shared/schema.ts`),
the parsing pipeline's output shape (`flightDataSchema`, the dual-AI parsers),
or CI/release/`.env`/infra/deployment config. Treat docs, copy, tests,
lockfile/dep bumps, and formatting as **low risk**.

## Buckets

Sort every card into exactly one:

1. **Autonomous** — fixable without product input. Note a confidence level and
why it's safe. (The orchestrator's autonomy policy decides land-vs-draft.)
2. **Needs owner** — blocked on a decision, direction, missing credentials, or
high-risk surface. State the exact decision required and the options.
3. **Defer / close** — stale, duplicate, superseded, or out of scope. Give the
reason and the canonical item if it's a duplicate.

## Output

Group the cards by bucket, most actionable first. Keep each card to a few lines.
End with a one-line tally (`N autonomous · M needs-owner · K defer`). When run as
the orchestrator's first step, hand this structured result back rather than
printing a wall of text.
174 changes: 174 additions & 0 deletions .claude/skills/maintainer-orchestrator/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
name: maintainer-orchestrator
description: >-
Control-plane loop for maintaining ITSEZMONEY repositories. Use when asked to

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The reference to the ITSEZMONEY organization should be updated to adityash8 to match the current repository's context.

Suggested change
Control-plane loop for maintaining ITSEZMONEY repositories. Use when asked to
Control-plane loop for maintaining adityash8 repositories. Use when asked to

"maintain the repos", "run the maintainer loop", "triage and act on the
backlog", or when invoked by a scheduled/API/GitHub-event cloud Routine. It
inspects issues/PRs/CI across one or more repos, classifies each item as
autonomous / needs-owner / defer, lands low-risk work autonomously, escalates
the rest, and records state in a durable ledger issue.
---

# Maintainer Orchestrator

A **control-plane** skill: inspect, classify, act, monitor, and report. It does
not invent product direction — it moves the existing backlog toward a clean,
green, reviewed state and escalates anything that needs a human decision.

This skill is designed to run **autonomously inside a Claude Code Routine**
(`claude.ai/code/routines`) — a cloud session with no permission prompts — but
also works when invoked by hand in an interactive session.

## The loop (one run)

Each run is one pass. Do these in order, then stop.

1. **Scope (owner-guarded).** Determine the target repositories.
- If the Routine cloned multiple repos, act on all of them; if invoked in a
single repo with a GitHub remote, act on that repo only.
- **Owner allowlist:** only operate on repos whose owner is `adityash8` or
`ITSEZMONEY`. Skip any cloned repo outside those owners entirely — no
triage, no PR, no merge — and record the skip in the **run summary**, never
in the skipped repo (you have no business writing to it).
- Do **not** broaden beyond the cloned/selected repos unless the prompt says
`all` / `org-wide`.
2. **Triage.** Invoke the `github-project-triage` skill to build item cards for
every open issue and PR (URL, what/why, author trust, fit, risk, proof/test
state, blockers, next action) and sort them into three buckets:
**autonomous · needs-owner · defer/close**.
Comment on lines +35 to +38

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude the ledger issue from triage

After the first run creates the open ledger issue, this instruction still sends every open issue through triage on the next run, with no exception for the maintainer-ledger item. That means the durable ledger itself can be classified as backlog work and then deferred or closed by the later defer/close step, removing the state the loop relies on; filter the ledger issue out of the queue before building item cards.

Useful? React with 👍 / 👎.

3. **Read the ledger (single, race-safe).** Locate the repo's ledger by the
`maintainer-ledger` label (canonical), falling back to the exact title
`🤖 Maintainer Loop — Ledger`. **Exactly one must stay open.** If several are
open — two runs can race and each create one — keep the **lowest-numbered**
open ledger, close the rest as duplicates (`state_reason: duplicate` with
`duplicate_of` set to the survivor), and continue on the survivor. If none exists, create it, ensure the
`maintainer-ledger` label exists, and apply it. Never open a second ledger
when one is already open. The ledger is the durable memory across runs (cloud
sessions are ephemeral); skip anything it marks resolved or `wontfix`.
4. **Act on autonomous items**, one at a time, verifying each before moving on
(see *Autonomy policy* below). Stop touching an item the moment it stops
meeting the bar and reclassify it as needs-owner.
5. **Escalate needs-owner items.** Don't guess at product/direction/secret
decisions. Label `needs-owner`, leave a one-paragraph comment stating the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ensure the needs-owner label before applying it

When a needs-owner item is encountered in a repo that has not already created this custom label, this step can fail or leave the escalation unlabeled: the loop only ensures maintainer-ledger exists before applying it, and the repo does not include any label setup for needs-owner. Since this runbook is meant to bootstrap new repos, create/ensure the label before using it so owner-blocked items stay discoverable.

Useful? React with 👍 / 👎.

decision required and the options, and record it in the ledger.
6. **Defer/close** stale, duplicate, or superseded items with a short reason.
7. **Report.** Update the ledger issue with what changed this run (landed,
escalated, deferred, still-in-flight) and the timestamp. Keep it skimmable.

Then end the run. The next trigger starts the next pass.

## Autonomy policy

The owner has authorized **auto-merge for low-risk work**. Be conservative:
when in doubt, downgrade to a draft PR and escalate.

### Low-risk → may land autonomously (open PR, get CI green, then merge)

ALL must hold:
- CI is **fully green** on the head commit (not pending, not skipped-as-proxy).
- The change is one of: dependency patch/minor bump that is non-breaking,
lockfile sync, docs/comments/typo, formatting or lint autofix, test-only
additions, or a clearly-scoped config tweak.
- Diff is small and bounded (rule of thumb: ≤ ~50 changed lines, single
concern).
- It touches **none** of: auth, payments/Stripe, `certificates/` or any
key/secret, DB schema or migrations (`shared/schema.ts`, drizzle), CI/release
config, infra/deployment config, or anything in `.env*`.
- Author is **trusted** per the allowlist below (or the change was authored by
this loop, which runs as `adityash8`) — **or** it is a bot dependency bump that
independently meets every other gate in this list.
- No unresolved review thread requests changes.
- Branch is up to date with base (or can be safely fast-forward updated).

**Trusted author — explicit allowlist, not "CI is green":**
- An item counts as from a trusted author **only** if the PR author is
`adityash8`. No one else qualifies — other org members, first-time/external
contributors, forks, and bot accounts (including Dependabot/Renovate) are
**not** trusted.
- Bot **dependency** PRs may be auto-merged **only** when they also pass every
low-risk gate above; bot authorship alone never grants trust for anything else.

For these: ensure CI is green, then **merge** (squash by default). If the loop
authored the fix, open the PR first, let CI run, then merge once green.

### Everything else → draft PR + escalate, never auto-merge

Bugs with real logic changes, features, anything touching the protected areas
above, large diffs, untrusted authors, red/uncertain CI, or any ambiguity:
open or leave a **draft** PR with your analysis, label `needs-owner`, and record
it in the ledger. Do not merge.

### Never

- Force-push to or merge into protected/long-lived branches outside the PR flow.
- Touch certificates, private keys, or secrets.
- Close an item a human is actively discussing.
- Make product/pricing/architecture decisions.

## CI babysitting

When you open or own a PR, drive its CI to green: read failing job logs,
reproduce locally when possible, push the fix, re-check. Re-kick on each failure
rather than treating one round as the job. If a failure is real and out of scope
or you've re-kicked several times without progress, escalate with the diagnosis
instead of looping forever.

## Parallelization (worker fan-out)

Within a single run you may fan out read-only investigation across repos/items
using the `Agent` tool (one subagent per repo or per cluster of related items).
Keep **mutations** (commits, merges, comments) on the main orchestrator thread so
there is a single writer. Workers investigate and report; the orchestrator
decides and acts. Workers must not spawn further workers.

## Tools

Use the **GitHub MCP connector** for all GitHub reads/writes (issues, PRs, CI
status, job logs, merges, comments, labels); fall back to `gh` only if the
connector is unavailable. Use `git` for local branch work. The `github-project-triage`
skill provides the queue-discovery and scoring helpers.

Close duplicate ledgers via the connector/REST API so `state_reason: duplicate`
(+ `duplicate_of`) sticks — verified working. Note `gh issue close --reason`
accepts only `completed`/`not_planned`, so if you must use `gh`, close with
`not_planned` and a comment linking the survivor instead.

## The ledger

One ledger issue per repo, marked with the `maintainer-ledger` label (the
canonical identifier) and titled `🤖 Maintainer Loop — Ledger`. **Exactly one
stays open** — if a run finds duplicates it keeps the lowest-numbered open one,
closes the others as duplicates, and rewrites the survivor's body. Locate by
label first (titles can be edited), then by title. Body rewritten each run.
Suggested shape:

```
## Maintainer Loop — last run <UTC timestamp>

### Landed this run
- #123 bump zod 3.x → 3.y (deps, CI green) — merged

### Needs owner
- #130 Stripe webhook retry policy — needs decision: idempotency window? (options A/B)

### In flight
- #128 fix PDF parse crash — draft PR open, CI red, investigating

### Deferred / closed
- #99 closed as duplicate of #128
```

This is the only state that survives between runs — keep it accurate.

> Seeing duplicate ledgers? That means two runs started concurrently — check the
> routine's triggers for overlap (e.g. a manual **Run now** firing alongside a
> scheduled run, or two schedule/event triggers). The dedup above heals it, but
> overlapping triggers also burn double the runs.

## Reporting back to the owner

A Routine run has no human present, so "escalation" means: the `needs-owner`
label, a concise comment on the item, and a ledger entry. Do not block on
`AskUserQuestion` (there is nobody to answer mid-run). If a connector is
configured (Slack/Linear/etc.), a one-line summary of escalations is welcome,
but the ledger is the source of truth.
Loading
Loading