Skip to content
This text was generated by an LLM (how cgwalters uses LLMs). cgwalters has not reviewed it yet.

Pruning the backlog

agent-board prune --config FILE lists the open issues of the pass configuration's workRepositories that are candidates to close, each with its reasons and the links that show them (agent-board#280). It is read-only: it comments on, labels and closes nothing. Closing, a cap for it and a schedule are a later change; this list is what the operator looks at first.

The configuration is the pass's, from a trusted default-branch checkout. Prune reads its workRepositories, its board (for each issue's Priority, from the board's Priority field, which must exist and be single-select: otherwise the read is refused rather than every issue taken as unprioritized) and its bot. GH_TOKEN reads; it needs read access to the repositories' issues and to the project.

Reasons

An issue labelled keep (in any case) is skipped whole and only counted. Pull requests are left out. Any other open issue is listed with each reason that applies:

  • overtaken: a merged pull request of one of the workRepositories is among those GitHub takes as closing the issue (its closing references, as a closing keyword or the Development sidebar make them). The evidence is that pull request. A cross-reference alone does not count, as its text may say anything ("this does not fix …"), nor does an issue closed as completed, a pull request closed without a merge, or one from another repository.
  • duplicate: an older open issue of the same repository has the same title stem: its letters and digits as lowercase words, so App: crash matches App crash. The oldest of them stays and is the evidence. A title with no letters or digits, such as an emoji alone, matches nothing.
  • stale: its board Priority is neither P0 nor P1 (or it has none), it has no open sub-issue and blocks no issue, and nothing happened for --stale-days (21 by default). Idle time starts at the issue's creation, at any timeline event by a person (a comment, a label, a reference; not mentioned or subscribed, whose actor is the person named, even by the bot), or at a cross-reference from a pull request, whoever opened it, as that is run activity. The bot's own comments and labels, and those of apps, never count, so board passes and status comments do not make an issue look active. An issue whose sub-issue or dependency summary GitHub did not return is never called stale. The evidence is the newest activity that counted.
  • triage-done: the newest triage verdict the bot posted on the issue (a schedule-triage block, as in the supervisor's close) is done, and no person commented after it. A verdict posted by anyone but the configured bot is ignored. This is a candidate for a person to look at, not the supervisor's checked closure.

Candidates are sorted by repository and number. The default output is text, a link and title per candidate with a line per reason and its evidence; --format json prints the same report as one object: now, stale_days, repositories, open (issues read), kept, requests, not_modified and candidates, each with repository, number, url, title, priority and reasons (reason, detail, evidence).

Reads

Each repository's open issues are listed (a request per hundred), then each issue's timeline (a request per hundred events) except those kept; the board's open issues are one GraphQL request per hundred, and an issue a merged pull request cross-referenced costs one GraphQL request for its closing references. Every read, conditional or not, is spent from a budget of 1,000; running out refuses the whole read rather than list part of the backlog. A read refused under a rate limit is retried by the transport, at most three times, and counts once: the budget bounds reads, and the HTTP requests are at most four times as many.

The REST reads are conditional, as the poll's are. With --cache FILE, the responses of the last read are revalidated with If-None-Match (or If-Modified-Since where GitHub sent no ETag), and an unchanged page answers 304, which costs no rate limit. After a whole read the file is replaced by the responses it used, slimmed to the facts prune reads. It is only a cache: deleting it costs requests, not correctness. GraphQL cannot be revalidated, so the board's pages and closing references are read every time.

Not yet

Prune does not yet read a newer issue that supersedes an older one, title or body matches on the same files, issues outside the dispatch bounds, or whether a linked pull request is still being worked on beyond its cross-reference. A duplicate keeps the oldest issue, not the one with a pull request.