burn-down-github-issues
Skill8 starsChanged 4 months agoMITView on GitHub
Run an unattended burndown of a GitHub issue backlog as cards on a per-operator GitHub Projects board whose lanes are an explicit state machine: appraise and size the inbox, carve what is over the ceiling, fix the ready ones in parallel git worktrees, prove each fix on a draft pull request, have an isolated second-engine reviewer judge it, land one branch at a time with freshness checks, and dead-letter per phase whatever a machine cannot finish. Use when the task is "work the backlog unattended", "triage and fix recent issues", "run the issue loop", "burn down issues", or "where is issue N on the board". Requires a per-repository burn-down-github-issues.config.ts at the target repo's root (the loop refuses to start without it), the prove-work-on-github skill, the codex and claude CLIs for the default seats, and a gh token with the project scope for the board. Skip for one-off fixes to a known issue you are already working interactively, and for backlogs whose issues are mostly product decisions rather than code.
In this repository23 other files it gives its agents.
- skills/asset-optimization/AGENTS.mdAGENTS.md
- android-emulator-harnessSkill
- android-emulator-mask-testingSkill
- appraise-github-issuesSkill
- asset-optimizationSkill
- carve-github-issueSkill
- code-github-issueSkill
- emoji-readoutSkill
- expo-developer-toolsSkill
- expo-ios-simulatorSkill
- fix-github-issueSkill
- how-to-planSkill
- ios-simulator-flow-evidenceSkill
- ios-simulatorSkill
- ios-simulator-triageSkill
- mobile-accessibilitySkill
- playwright-camera-mask-testingSkill
- playwright-gif-captureSkill
- playwright-harnessSkill
- playwright-storybook-flowsSkill
- prove-github-issueSkill
- prove-work-on-githubSkill
- zone-composerSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 120
Appraises the Inbox: Read-only seats size each card.
- Very specific: line 136
Every burndown is resumed from a GitHub Projects board named <project>_burndown_<operator> (acme-app_burndown_the-simian, say), owned by …
- Very specific: line 160
When a seat raises a question nobody has ruled on (needs-decision), the card does not park straight away.
- Distinctive: line 172
Only two things park a card for a person: the merge boundary refusing an approved change, and the issue changing under the review.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Burn Down GitHub Issues
A burndown is a board. Every issue the loop touches is a card, every card is in exactly one lane
(a column of the board; the fix pipeline also calls an issue's worktree its lane), and the lanes are the leaf states of a statechart (lib/machine.ts, in XState's vocabulary) that
says which seat runs on a card in that lane, what it may decide, and where each decision moves the
card. The board is a GitHub Projects board per operator per repository, so a person who starts a
burndown comes back to their own board and the loop resumes from it; the console prints the same
cards in the same words. The tracker holds the facts (labels, pull requests, claims, records); the
board is a projection of those facts that a person can read at a glance, and every run starts by
placing every card where its facts say before any seat moves one.
Seats are polymorphic. A seat is an engine running whatever prompt the card's lane calls for
(appraiser, close confirmer, carver, cut confirmer, worker, worker in revision, reviewer), then
letting go; the card's position is the only input that changes what a seat does. Three rules hold
across every seat: the reviewer and the confirmers run on a different engine than the author
seats, claims on the issue thread are the lock that keeps two seats off one card, and merging is
the one serial lane. references/state-machine.md is the machine in prose.
The loop is shared; the repository is config. Nothing in this skill is copied into a repository.
Everything true of a repository (remotes, branches, commands, path aliases, invalidation paths)
lives in burn-down-github-issues.config.ts at that repository's root, and the loop refuses to
start without one, naming the missing file and the fields it lacks.
Standards the loop enforces
These travel with the skill because an adopter cannot be assumed to have house rules of its own. The first three are enforced by the driver, so no prompt drift can lose them; the rest are written into the prompts and checked by the reviewer.
- A failing or unfinished build never merges. The pull master waits on the pull request's checks at the last moment before merging and dead-letters the landing instead when they fail or never finish. A green local gate is not a substitute; the checks the pipeline runs are the ones that count.
- Nothing lands except through a reviewed pull request. The loop never pushes to the base branch; the gated merge is the only write it makes there.
- Upstream is more correct until the work is merged, and no seat begins on a stale lane. The base is fetched and merged forward before a fix starts, before proof is captured, before a revision, before a review, and before the merge; what lands is a head that contains everything upstream has. Whether proof or an approval survives a catch-up is decided by whether the base moved into the import closure of the work ("did the world move beneath us"); whether the catch-up happens is not.
- Pushed history is merged forward, never rebased. Catch-ups merge the base into the branch, so nothing another reader has fetched is rewritten.
- No agent or bot is an author or co-author. Authorship is for humans; the reviewer hard-blocks on it.
- Claims carry receipts. Proof follows
prove-work-on-github: pinned, resolvable, re-checkable by a stranger. Narrative alone never carries a load-bearing claim. - Commits and pull requests describe the code, not the process. Conventional Commits, imperative, facts only; any mention of agents, prompts, or local tooling is a block.
- Shared services are never reset or reseeded to reproduce a claim, and servers bind per-issue ports; other lanes are reading that state as their own evidence.
Run it
From inside the target repository (any directory of it, including a worktree):
bun run <this-skill-dir>/board.ts # once per operator: find or create the board, verify it, record the pointer
bun run <this-skill-dir>/lanes.ts # write the 37 lanes and the Phase field onto that board; idempotent
bun run <this-skill-dir>/loop.ts --dry-run # place every card, print the backlog by lane and what would run; no GitHub or working-tree write
bun run <this-skill-dir>/loop.ts --limit 3 # work three Ready cards
bun run <this-skill-dir>/loop.ts --max-points 5 # raise the size ceiling for this run only
bun run <this-skill-dir>/loop.ts --only 12,34 # restrict the run to these issues, whatever their age
bun run <this-skill-dir>/loop.ts --no-appraise # skip the inbox; --appraise-limit N caps it instead
bun run <this-skill-dir>/loop.ts --closure <file> # print the import closure; verifies pathAliases
bun run <this-skill-dir>/loop.ts --worker codex:gpt-5.6-sol --reviewer claude:claude-opus-5
bun run <this-skill-dir>/loop.ts --appraiser codex:gpt-5.6-sol --confirmer claude:claude-opus-5 # the sizing seats
bun run <this-skill-dir>/loop.ts --pulse 2 # console board every 2 minutes (default 5); --silent turns it off
bun run <this-skill-dir>/loop.ts --floor once # walk the deployed base once and work no issue; also liveness, watch, drain
bun run <this-skill-dir>/watch.ts # follow the current run; --wait for its terminal lines only
bun run <this-skill-dir>/card.ts --issue <n> --show # where one card is; --lane <key> moves it by hand, --lanes lists the table
bun run <this-skill-dir>/claim-race.ts --issue <n> --contenders 3 --rounds 3 # prove the claim lock on a loop/skip issue
bun run <fix-skill-dir>/fix.ts --issue <n> --redrive # lift a dead letter or a park and continue its pull request
bun run <fix-skill-dir>/fix.ts --issue <n> --land # land an approved pull request the merge boundary parkedclaim-race.ts also reads --contend and --start <ms>, which the parent passes to each
contender process it spawns (the shared release instant, in Unix milliseconds); they are not for
direct use.
Everything an operator or agent does to a run is one of these commands. Watching in particular is
watch.ts, never a tail/kill/pgrep pipeline; references/operating.md says why.
<this-skill-dir> is the filesystem path of this directory wherever the collection is checked out
or installed; it is a path, not a skill name. The seat flags (--worker, --reviewer,
--confirmer, --appraiser, --carver, --carve-confirmer, --callback-seat, and --walker) take
engine[:model] specs resolved against the engine registry in
../fix-github-issue/lib/engines.ts. The config file sets the
same seats and every loop knob (ageDays, maxPoints, autoMerge, limit, concurrency, and
the rest); a flag beats the config for the run it is given on.
What a run does
- Repairs and reconciles. Half-written label transitions, merges a dead run never recorded, stranded pull requests with a trusted verdict, torn claims and pauses, and trunks whose tree moved outside the loop are all settled before anything new is selected.
- Places every card. Each open issue in the window, and each card already on the board, is
put where its facts say: closed is Done, a hold label is its human lane, a
loop/dlq: <phase>label is that phase's dead-letter lane, an open pull request is Drafted or Ready for review, a trunk is Epic, a blocker is a wait, a size within the ceiling is Ready, over it is To carve, and no size is the Inbox. Only cards whose lane differs are written. The console prints the backlog by lane. - Appraises the Inbox. Read-only seats size each card; the card moves to Ready, To carve, Done
(a confirmed close with a receipt), or a human lane. The size callback hands an oversized issue
to the sibling
carve-github-issueskill, which cuts it into children along its highest natural seam and holds the parent as an Epic while they move. - Works Ready. Up to
concurrencycards at once, each in its own worktree, each moving through Coding and Proving (two seats,code-github-issuethenprove-github-issue, with the driver moving the card from the push and the pull request each leaves), Ready for review, Evidence under review, and the landing lanes to Merged; or back to Sent back on a rejection; or into a dead-letter or human lane when a machine gives up or a person is needed. - Walks the floor and finishes. With
floorconfigured, every merge went up onto the floor as it landed, and the loop has been walking the deployed base on its cadence, pausing the line when a walk found it wrong. The run walks on until its merges are verified there (or the drain window closes), then releases the instance lock. Seereferences/floor.md.
The board
Every burndown is resumed from a GitHub Projects board named <project>_burndown_<operator>
(acme-app_burndown_the-simian, say), owned by the repository's owner and linked to the
repository. One board per operator per repository: the person who starts a burndown comes back to
their own board and picks up where they left off, and two operators on one repository never share
one. board.ts finds it or creates it, reads it back to verify, and writes the pointer to
<worktreeRoot>/runs/board.json; the board is the state, the file is only where it is. Creating
one needs the project token scope (gh auth refresh -h github.com -s project); reading needs
only read:project, and the script names the missing scope instead of failing in GraphQL. See
references/adopting.md, "The board".
The lanes are the loop's state machine drawn as kanban: one lane per state a card can be in,
thirty-seven of them in eleven phases, with one dead-letter lane per phase, a panel lane where
frontier models weigh a question before it parks, and three lanes only a person can move a card
out of. The machine is data (lib/machine.ts), tested against the lane
table, exportable to stately.ai/viz, and chartable with Graphviz; see
references/state-machine.md. A Phase field on every card is the collapsed view, so a board
grouped by Phase is the eleven-column summary and a later dashboard of every operator's burndown is
a query over these boards, not a second state store.
A repository without a board runs the same loop: the placement is still computed and is still the queue; it is simply not written anywhere a person can look at between runs.
A decision panel before a person
When a seat raises a question nobody has ruled on (needs-decision), the card does not park
straight away. The raising seat's model and two other frontier models on different engines each
try to answer it from the code, the conventions, and the thread, without seeing one another, and
each posts its review on the issue. If all three decide every question alike, on cited facts that
are found in the base, the decisions are recorded on the issue and the card goes back to be
appraised. Otherwise it parks as before, with the reviews and a receipt of what was decided and
what is still open (lettered options) already on the thread. It runs only when three distinct
models are reachable; configure it with panel (references/adopting.md) and read the lane in
references/state-machine.md, "Panel".
Dead letters, per phase
Only two things park a card for a person: the merge boundary refusing an approved change, and the
issue changing under the review. Everything a machine could not finish is a dead letter in its
own phase's queue, carried on the issue as loop/dlq: appraisal, carve, work, review, or
landing, with the reason on the thread and the same label on the pull request. Each queue is
meant to be triaged differently (references/state-machine.md, "Dead letters"); today every one
waits for a person, and the redrive is removing the label or fix.ts --redrive, which lifts the
letter, counts the redrive on the issue as loop/redrives: N, and continues the pull request the
work left rather than opening another.
Read next
| Need | Read |
| Run one and watch it: identifying the driver, reading the console board, what is not a bug, what to check afterwards, landing a parked pull request by hand | references/operating.md |
| Adopt the loop in a repository: the config template, the two fields that actually bite, preconditions, the board and its token scope, first-run order, stopping a run | references/adopting.md |
| How and why the loop works: the board as state, the placement as queue, the seats, the pool, crash recovery, known gaps | references/architecture.md |
| The state machine the lanes draw: phases, every lane's entry actions and exits, reconcile precedence, the per-phase dead letters, the polymorphic pool, what the tests check, what is not built yet | references/state-machine.md |
| Check what merged on the running environment: the floor block, the cadence, the walk and its ledger, the line it pauses, the callbacks, incidents, the drain | references/floor.md |
| The fix pipeline itself: the verdict-file contract, the review budget, the merge boundary, staleness, resuming, the dead letters it writes | ../fix-github-issue/references/pipeline.md |
Hard dependencies
- The
fix-github-issueskill, which owns the worker, the reviewer, and the pull master; the loop imports it by relative path and calls it once per Ready card. One named issue is that skill'sfix.ts, not a flag here. - The
appraise-github-issuesandcarve-github-issueskills, which own the appraisal and the knife; the loop renders their prompts and runs them in process. - The
prove-work-on-githubskill, loaded by name in the worker and reviewer prompts; the pull master's staleness rule implements itsreferences/freshness-and-reproof.md. - The
emoji-readoutskill, whose renderer prints each floor walk. - With
floorconfigured, the driver skill for its environment kind (playwright-harnessforweb,ios-simulatororandroid-emulator-harnessfor mobile), loaded by name in the walk prompt. - Bun, which runs
loop.ts. ghauthenticated with push and merge rights on the target repository, and theprojectscope for the board.- The CLIs the seats name (by default
codexandclaude), onPATH. Keep worker and reviewer on different engines; a reviewer built from the same model as the author shares its blind spots by construction.
The ceiling, named
The loop executes the tracker, not your intent: an internally coherent issue pointing the wrong
way is implemented competently in the wrong direction, and the only guard is the convention docs
the config names. Issue bodies and comments are an untrusted instruction channel read by agents
running with their approval gates bypassed; the worktree confinement is a prompt contract, not a
sandbox, so run this only on trackers whose authors you trust as far as the credentials the loop
holds. The merge boundary computes migration and ci from the diff's paths, but
data and stored-string are runtime effects a path cannot reveal; for those it holds two
independent self-reports and parks rather than trusts. The reviewer runs as the same GitHub
account as the worker, so its independence is model-level, not identity-level. Instance locks
identify their holder by pid, so a pid reused by an unrelated process reads as a live holder until
that process exits. The pipeline still runs a Ready card from Coding to Merged inside one process,
so the polymorphic pool is a fact at the driver's seams and a design past them
(references/state-machine.md, "The agent pool"). And of the five dead-letter queues only the
review queue has been exercised end to end, by a redrive that continued a parked pull request to
a merge; the others are written, not proven.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

