Repository navigation
Nightly triage: sweep unboarded issues onto the board and run the board audit #2463
Description
Problem
New issues reach the board only when a maintainer runs /issue-triage by hand, currently every day or two. Until then, a user-submitted issue has no card. It is invisible to the board, to its priority ordering and to every Status-filtered view, whether or not it is urgent. The same gap delays the dependabot and SDK-watch issues, which leave boarding to triage.
Goal
A nightly workflow that runs /issue-triage's pass 1 and its board audit, so that every open issue has a card by morning. Pass 2 (assigning a milestone, which is the approval) stays human, as the skill requires: "Pass 2 is a human judgment call and is never done unprompted."
Blocked on
#2462's credential. Board writes need org Projects write access, which GITHUB_TOKEN cannot hold. The GitHub App described there (Projects read & write, Issues read & write) covers this workflow too.
Design
The work splits into a deterministic half and a judgment half. That split, together with AGENTS.md's rule that no model runs in a write-capable job, gives the workflow the same three-job shape as sdk-watch.yml.
1. sweep — deterministic, holds the credential, no model.
- Find open issues with no card on either board, using the recipe in
/issue-triage(the union of Add tab and approval flow for server -> client sampling #28 and get tools working #11, filtered to this repo). It must check that the listing is complete (.items | length == .totalCount), because Add tab and approval flow for server -> client sampling #28 already has more items than the default--limitreturns. - Apply the labels deterministically where the form already determines them:
- A Feature request already carries
enhancement+v2. - A Bug report carries
bug, and its version label comes from the form'sversion-linedropdown, parsed from the issue body. - An issue whose type or version cannot be determined mechanically is left for the model (below), or flagged. It is never guessed.
- A Feature request already carries
- Board it:
v2→ Add tab and approval flow for server -> client sampling #28,v1→ get tools working #11, with StatusIncoming. Leave the milestone unset.- The one exception is an issue that already has a milestone, which goes to
Todo, as the skill describes.
- The one exception is an issue that already has a milestone, which goes to
- Hand the new card list to
analyze.
2. analyze — the model, contents: read only.
- Score each new v2 issue with the priority rubric (two axes plus the listed bonuses), and suggest a type label where the form did not determine one.
- Return structured output only (
--json-schema). Restrict the available tools (--tools, not only--allowedTools), give it noBashand noWebFetch, and let it post nothing. These are the rulesAGENTS.mdlays down forsdk-watch's analysis job. ⚠️ Issue bodies are untrusted, third-party input. Unlikesdk-watch, whose upstreams are first-party, anyone with a GitHub account can write the text this model reads. That is the caseAGENTS.mdsays would change the trade-off: "Point the analysis at an upstream outside this org, or feed it third-party content, and the trade changes." So this job must not haveANTHROPIC_API_KEYreadable through a tool it needs. Use workload identity federation, or a dedicated CI-scoped key with a spend cap, asAGENTS.mdnames for exactly this case. Decide which before building it.
3. apply — holds the credential, no model.
- Validate every value
analyzereturned before writing it:- the Priority must be one of the four options
- the type must be one of the five labels
- each axis must be an integer from 1 to 5
- the total must match its parts, recomputed here rather than trusted
- Then set Priority and post the score comment in the format
/issue-triagespecifies. - A value that fails validation is left unset and reported, never coerced.
4. The board audit — report only.
- Run the audit query from
/issue-triageand fail the job when any check is non-zero, so drift becomes a red run instead of something the next manual pass has to notice. ⚠️ Actions logs on this public repo are public, and the boards are private. The audit output (issue numbers per defect class, Status, Priority) and anything else read from the board must go only to a place with the board's own audience. Print counts only to the log, or write the detail somewhere private. The same applies to the sweep's own logging.
Out of scope
- Pass 2: milestones and moving cards out of
Incoming. - Fixing audit findings automatically. Report them; a person fixes them.
- GHSA drafts, which are GHSA draft cards: place on the board for the affected line, and include affected versions + reporter #2462.
Acceptance
- Scheduled workflow with
sweep→analyze→apply(+ audit), permissions scoped per job as above, with tests pinning:analyze's permissions and tool whitelist- that
analyzecontains no write step - that
applyvalidates before it writes
- Deterministic label/board classification in a
scripts/*.mjshelper, with a sibling*.test.mjs, covering:- both forms
- both boards
- the already-milestoned →
Todoexception - the incomplete-listing guard
- Credential decision for the model key recorded (federation, or a dedicated capped key).
- Nothing read from the private boards reaches a public log beyond counts.
-
/issue-triageandAGENTS.mdupdated to say the sweep runs nightly, and what is still manual (pass 2).
Activity
cliffhall commentedon Sep 23, 2026
Triage: Priority Medium (total 6)
/issue-triageby hand every day or two) works but is a choreBoard: #28, Status
Todo, milestone v2.10.0.cliffhall commentedon Sep 23, 2026
Milestone moved to v2.9.0 (the milestone due dates were corrected). The priority is unchanged; the milestone bonus applies either way.
cliffhall commentedon Sep 30, 2026
Blocked on #2544 (the GitHub App), which now has its own card. This issue is a sub-issue of tracker #2543, milestoned v2.10.0. Its separate open decision is unchanged:
analyzereads third-party issue text, so the model's key must not be readable through a tool it needs (workload identity federation, or a CI-scoped key with a spend cap).