Skip to content

docs: add Incoming to both boards, adopt the v2 Priority field, and document the triage rubric - #1892

Merged
cliffhall merged 7 commits into
v2/mainfrom
v2/docs/board-incoming-status-and-issue-priority
Aug 1, 2026
Merged

docs: add Incoming to both boards, adopt the v2 Priority field, and document the triage rubric#1892
cliffhall merged 7 commits into
v2/mainfrom
v2/docs/board-incoming-status-and-issue-priority

Conversation

@cliffhall

@cliffhall cliffhall commented Aug 1, 2026

Copy link
Copy Markdown
Member

Closes #1891

Docs-only, plus board-configuration changes that are already applied and verified.

Why

Triaging the 154 unlabeled open issues in #1872 surfaced two gaps.

No board state for "filed but not yet triaged." AGENTS.md described Todo as "approved-but-not-started work," so a newly filed issue had nowhere to sit that distinguished nobody has looked at this from a maintainer approved it. During the sweep this was concrete: 36 issues ended up awaiting review, and Todo would have falsely asserted sign-off on all of them.

The Priority field existed but was unused and undocumented. Board #28 carried a Priority single-select from the project template. Zero of its 264 items had it set, AGENTS.md never mentioned it, and its P0/P1/P2 options matched no vocabulary used anywhere in the repo. There was also no written rule for how to decide something is urgent.

What changed on the board

  • Status gained an Incoming option, ordered ahead of Todo.
  • Priority was re-optioned from P0/P1/P2 to Urgent / High / Medium / Low.

Each mutation echoed back every existing option's id, and the Status change was verified by diffing a full item-list snapshot before and after: all 264 cards kept their Status, all four prior option IDs survived.

All 51 open v2 issues have since been scored and boarded — 36 into Incoming, plus Priority set on the 15 existing Todo cards.

The Done column incident

While this PR was open, the Done Status option was deleted from the board, blanking the Status of all 247 cards that held it. Restored from the pre-change snapshot: the orphaned set was confirmed to be exactly the 247 cards that held Done, the option was recreated, and each card re-set. Verified afterward — same 247 cards in Done, no other card disturbed.

Two consequences land in this PR:

  1. Done is now 259d6aab, not 248a3910. A recreated option never regains its old id. Updated in the option table and in the merge step that cites it.
  2. The hazard callout was wrong in a way that mattered. It recommended the web UI as the safe alternative to the GraphQL mutation. That holds for adding and renaming, but deleting an option blanks its cards in the UI exactly as it does via the API — no undo, no warning. Corrected, plus a snapshot-first rule and the recovery recipe used here (including the grouping check that proves the orphaned set matches the deleted option before re-applying).

That recipe is the difference between the two incidents this board has now had: the first, via API, required reconstructing ~197 statuses by inference; this one took about two minutes because a snapshot existed.

What changed in AGENTS.md

  • Completes the priority rubric already drafted in the working tree: fills in the score bands, expands both axes into scored 1-5 tables, and repairs the truncated signal-indicator line (Labeled , urgent, bug, or security).
  • Documents Incoming with the Incoming/Todo distinction spelled out, since that boundary is the point of the new column.
  • Adds the Priority field ID and option IDs beside the Status ones, plus a two-call recipe (each item-edit sets one field; there is no combined form).
  • Widens and corrects the updateProjectV2Field hazard callout as described above, and records that ProjectV2SingleSelectFieldOptionInput.id is an optional String — which is what makes the safe "echo every existing id, omit only the new one" pattern work.
  • Refreshes the --limit guidance (~200 → ~265 items) and the last-verified dates.
  • Drops the V2 Go Live Status reference. That option is not in the field's option list — verified against the live field, so the instruction was unfollowable as written.

Deliberately not changed

.github/copilot-instructions.md. Per its own scoping rule, board recipes and IDs are excluded from the mirror — they aren't things a reviewer cites against a diff. Confirmed the file has no board, status, or priority references today.

Scoring note

Across all 51 scored issues: 11 High, 23 Medium, 17 Low, and no Urgent. The closest was #1852 (Inspector won't launch at all on Windows) at 11/15 — both axes maxed, one corroborating signal short. That may mean the Urgent band sits a notch high, or simply that nothing currently qualifies; worth watching before the thresholds are treated as settled.

Testing

npm run ci passes from the root (462 tests), run on both commits. Docs-only, so no behaviour is exercised by it; the gate was run because it is unconditional. No screenshots — nothing in the web UI or TUI changed.

…e rubric (#1891)

Board #28 had no state for "filed but not yet triaged" — Todo means
maintainer-approved, so parking unreviewed issues there falsely asserted
sign-off. Adds an Incoming status ahead of Todo.

The board's Priority single-select existed but was unused (0 of 264 cards)
and undocumented, with P0/P1/P2 options matching no vocabulary in the repo.
Re-optioned to Urgent/High/Medium/Low and documented alongside Status.

Completes the priority rubric: fills in the score bands (12+/9-11/6-8/<=5),
expands both axes into scored tables, and fixes the truncated signal-indicator
line. Severity alone tops out at High by design.

Also drops the "V2 Go Live" status reference — that option is not in the
field's option list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Aug 1, 2026
cliffhall and others added 2 commits August 1, 2026 11:46
…ce (#1891)

The Done Status option was deleted from board #28, blanking the Status of
all 247 cards that held it. Restored from a pre-change item-list snapshot;
verified all 247 are Done again and no other card was disturbed.

A recreated option never regains its old id, so Done is now 259d6aab rather
than 248a3910 — updated in the option table and the merge step.

The hazard callout recommended the web UI as the safe path, which is what
made this look safe. It is not: deleting an option blanks its cards in the
UI exactly as it does via the API, with no undo. Corrects that, adds a
snapshot-first rule, and documents the recovery recipe used here — including
the grouping check that proves the orphaned set is exactly the deleted
option's cards before re-applying.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
Board #11 had the same gap as #28 — no state for "filed but not yet
triaged" — so a v1 security-fix issue had nowhere to sit that didn't
assert maintainer approval. Adds Incoming there too.

AGENTS.md carried no v1 board recipes at all, only a link, so anyone
boarding a v1 issue had to discover the project and field ids by hand
and was liable to reach for #28's (which are rejected, but only after
the attempt). Adds a V1 board section with its ids, states that Incoming
is the default status for new items on both boards, and notes that
Priority is v2-only — #11 has no such field.

The Incoming option was added with all four existing option ids echoed
back, and a before/after item-list diff confirms all 74 cards kept their
Status. Three cards on #11 carry no Status; that predates this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
@cliffhall cliffhall changed the title docs: add Incoming board status, adopt the Priority field, and document the triage rubric docs: add Incoming to both boards, adopt the v2 Priority field, and document the triage rubric Aug 1, 2026
@cliffhall

Copy link
Copy Markdown
Member Author

Third commit widens this to the v1 board (#11). Retitled; see #1891 for the rationale.

Board #11 had the same missing-inbox gap as #28, and AGENTS.md carried no v1 board recipes at all — only a link — so boarding a v1 issue meant discovering the ids by hand, with #28's ids the obvious wrong guess.

Board change (applied and verified): Incoming added to #11's Status field as 831820cf, with all four existing option ids echoed back. Before/after item-list diff confirms all 74 cards kept their Status.

Docs: adds a #### V1 board (#11) recipes section with its project/field/option ids, states that Incoming is the default status for new items on both boards, records that Priority is v2-only (#11 has no such field, so don't try), and points the deletion hazard + snapshot + recovery guidance at both boards.

Also worth noting for review: three cards on #11 already carry no Status, which predates this change — confirmed by the diff, not an orphaning event. That's called out in the docs so the next person to look doesn't read it as damage.

npm run ci green on this commit too (462 tests).

cliffhall and others added 2 commits August 1, 2026 13:04
…1891)

An issue page shows two fields named "Priority" and nothing syncs them.
Ours is the project field on board #28. The other is a GitHub issue field
(IFSS_kgDOAdAWeg) defined at the modelcontextprotocol org and shared by
every repo in it, alongside Effort/Start date/Target date. Same name, same
four option names, unrelated storage — #1891 sat at Urgent in Fields and
High on the board simultaneously.

Adds a table naming both, states that no pass-through exists in either
direction, and says to leave the org-level one alone: it is not repo-scoped,
so deleting it would strip Priority from every other org repo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
…#1891)

Both boards are private (public: false, verified), so maintainer-assigned
Status and Priority are invisible to reporters — board priority is a
working queue, not a published commitment.

The org-level Fields -> Priority is the opposite: public on the issue page
and not part of triage. A value there is a reporter's preference, not an
assessment, so it is untrusted input. It now feeds the rubric as a sixth
signal bonus — flat +1 for Urgent or High, identical for both — and never
maps to a band. Urgent needs 12, so nothing a reporter types reaches it
alone; the issue must already sit at 11 on maintainer-assessed axes.

Supersedes the earlier "it is noise" framing: the signal is worth keeping,
it just cannot be allowed to decide the outcome. Also corrects the band
arithmetic (2-15 -> 2-16) now that a sixth bonus exists, and notes that
scores recorded on 2026-08-01 cite the old /15 denominator.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
@cliffhall

Copy link
Copy Markdown
Member Author

Two more commits: the dual-Priority problem and the trust boundary around it.

There are two fields named "Priority" on an issue page, and they don't sync

Where What Ours?
Projects → Inspector V2 → Priority Board #28 project field ✅ yes
Fields → Priority GitHub issue field IFSS_kgDOAdAWeg, defined at the modelcontextprotocol org and shared by typescript-sdk / servers / registry, alongside Effort / Start date / Target date. Created 2026-05-06, ORG_ONLY. ❌ no

Same name, same four option names, unrelated storage. #1891 sat at Urgent in Fields and High on the board simultaneously — that's how this surfaced.

Deleting the org field was considered and rejected. It isn't repo-scoped, so deleteIssueField would strip Priority from every other modelcontextprotocol repo. The docs now say so explicitly, since "delete the duplicate" is the obvious wrong move.

Trust boundary

Both boards are private (public: false, verified on #28 and #11), so maintainer-assigned Status and Priority are invisible to reporters — the board is a working queue, not a published commitment. The org field is the inverse: public on the issue page, and never touched by triage.

So a value there is untrusted — a reporter's preference, not an assessment. It now feeds the rubric as a sixth signal bonus: flat +1 for Urgent or High, identical for both, and never maps to a band. The anti-gaming property is arithmetic rather than assurance: Urgent needs 12 and a reporter contributes at most 1, so an issue must already sit at 11 on maintainer-assessed axes before their input matters — and at 11, they aren't the reason.

This supersedes the "it is noise, leave it alone" wording from the previous commit. The signal is worth keeping; it just can't be allowed to decide the outcome.

Two things reviewers should check

  1. The band range changed, 2–15 → 2–16, because a sixth bonus now exists. The bands themselves are unchanged, but the 51 scores recorded on 2026-08-01 cite /15. Noted in the docs rather than rewriting 51 comments — totals and bands remain correct, only the denominator moved.
  2. Whether an outside reporter can actually set that field is unverified — I'm ADMIN, so viewerCanSetFields says nothing about anyone else. The rule is deliberately written not to depend on the answer: it rests on who assessed the issue, not on who could click, so a future GitHub permission change can't quietly invalidate it.

Also cleared the two stray org-field values on open v2 issues (#1891 Urgent, #1826 Low) — values only, field untouched. #1891's board Priority was overridden High → Urgent by maintainer judgment, with the reasoning recorded on the issue as the rubric requires.

npm run ci green on both commits (462 tests).

…tated (#1891)

The 51 triage comments were rewritten from /15 to /16, so the note saying
they cite the old denominator no longer describes anything. No total moved:
the reporter-set signal only scores for Urgent or High, and the one scored
issue carrying an org-field value (#1826) had Low, which earns nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
@cliffhall

Copy link
Copy Markdown
Member Author

Follow-up: retired the competing label scheme and restated the recorded scores.

p1-high removed from #929 and #932 — the only two open issues carrying it. No open issue now has any p* priority label, so the board field is the sole live priority mechanism.

Scoped to open issues deliberately. The repo carries a full p0-critical/p1-high/p2-medium/p3-low scheme applied to ~52 closed issues; stripping those would erase the record of how work was prioritized under the old scheme without resolving any contradiction, since a closed issue has no queue position to contend for. The four label definitions still exist and can be re-applied — deleting them is the way to genuinely retire the scheme, at the cost of removing them from those closed issues too. Left as a maintainer call.

All 51 triage comments rewritten /15/16, verified by re-fetching every one (51 read /16, 0 read /15). Dry-run first confirmed exactly one occurrence per comment, so nothing else in the bodies changed.

No score moved — only the denominator. The reporter-set signal pays out only for Urgent or High, and the one scored issue that carried an org-field value (#1826) had Low, which earns nothing. Every total and band stands as originally computed; this was a restatement, not a rescore.

Sixth commit drops the now-false AGENTS.md note that said the recorded scores cite /15. npm run ci green (462 tests).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Not ready to approve

A few updated sections still describe board behavior in Status-only terms (and imply generality where the instructions are Status-specific), which can mislead maintainers following these recipes.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

Updates the project’s operational documentation in AGENTS.md to reflect new board workflows: an Incoming status for untriaged issues, adoption of the v2 board Priority field, and a documented scoring rubric for deriving priority consistently.

Changes:

  • Define and document Incoming as the default “filed but not yet triaged” board status (distinct from maintainer-approved Todo).
  • Document the v2 board Priority field (Urgent/High/Medium/Low) and add a rubric for scoring issues.
  • Expand the updateProjectV2Field hazard guidance and add snapshot/recovery procedures for option deletion incidents.
File summaries
File Description
AGENTS.md Documents Incoming, v2 Priority rubric/IDs, and safer board-option mutation + recovery procedures.
Review details

Suppressed comments (2)

AGENTS.md:312

  • The updateProjectV2Field hazard text is written as if it always blanks Status, but this section now applies to both Status and Priority; describe the impact in terms of the field being edited (and which cards lose that field’s value).
> ⚠️ **Never add, rename, or remove an option on a single-select board field (Status or Priority) with the `updateProjectV2Field` GraphQL mutation unless you pass every existing option's `id`.** That mutation does a **full replace** of the option list: if you resend options by name/color/description but omit their `id`s, GitHub **deletes all existing options and mints new ones**, which **orphans the Status of every card on the board** (all items go blank) *and* invalidates every option id in the table above. This has happened once (required reconstructing ~197 items' statuses by inference). Safe alternatives, in order of preference:
> 1. **Add or rename an option in the GitHub web UI** (Project #28 → the field's settings). This preserves ids of untouched options and never orphans the cards on *other* options. ⚠️ **Deleting is different, in the UI as much as in the API: removing an option blanks the Status of every card that held it, with no undo and no warning that says so.** Before deleting any option, snapshot the board (see recovery below).
> 2. If you must script it, first `gh api graphql` the current options **with their `id`s**, then call `updateProjectV2Field` echoing back every existing option **including its `id`**, appending only the new one. `ProjectV2SingleSelectFieldOptionInput.id` is an optional `String`, so a mixed list works: echo the `id` for every option that already exists, omit it only for the one being added. Verify afterward that no card lost its value — snapshot `gh project item-list … --format json` before and after and diff, don't just spot-check.

AGENTS.md:329

  • The recovery section uses .status and the Status field id, so it’s specifically about recovering from a deleted Status option; make that explicit in the heading/intro to avoid implying it also applies unchanged to Priority deletions.
> ### Recovering from a deleted option
>
> This has now happened twice — once via the API (~197 items, reconstructed by inference) and once via the UI (the `Done` column, 247 items, restored from a snapshot in minutes). With a snapshot the recovery is mechanical:
>
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread AGENTS.md Outdated
- `v1` — work targeting `v1/main` (the deprecated line: security fixes only)
- `v2` — work targeting `v2/main` (active development; the default for anything new)

Set the label at **create time** — `gh issue create --label v2 ...`, `gh pr create --label v2 ...` — never by backfilling later, since unlabeled items are exactly the ones missed when filtering by version. **If the target version isn't obvious, it's `v2`**: v2 is where all new work goes, and `v1` is reserved for the narrow case of patching the deprecated line. Only ask when the issue is specifically a fix *for released v1 behavior* and it's unclear whether v2 still has the bug. Note the label is a repo tag and is **not** the board — see the callout above; a `v2` issue also needs a board card with a Status.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — fixed in 5104890, along with the two other locations you pointed at.

  • line 156 — now reads "a v2 issue also needs a board card with a Status and a Priority (a v1 one needs a Status; board get tools working #11 has no Priority field)". The v1 clause matters here: the rest of this section says every issue gets a Priority, which is only true on Add tab and approval flow for server -> client sampling #28.
  • line 310 (the updateProjectV2Field hazard) — reworded from "orphans the Status of every card" to "orphans that field's value on every card", naming which field goes blank based on which one you were editing. Same fix applied to the UI-deletion warning in the numbered list below it. The "~197 items" incident is now explicitly labeled as having happened on Status, so it reads as one instance of the general hazard rather than as its definition.
  • line 326 (the recovery recipe) — you were right that this one is genuinely Status-specific rather than just Status-worded: it reads .status and passes the Status field id. Rather than generalize the code, I labeled it and documented the two substitutions for a Priority deletion — read .priority, and pass PVTSSF_lADOCt2Azc4BJVxtzg5iJE4.

I verified the .priority key exists before documenting it (gh project item-list 28 --format json returns ["assignees","content","id","labels","linked pull requests","milestone","priority","repository","status","title"]) — the field is exposed under its lowercased name, so both keys are present on every item.

)

Copilot review on #1892 flagged three places that still read as
Status-only now that the section covers Priority too:

- the version-label bullet said a v2 issue needs "a board card with a
  Status"; it needs a Status and a Priority (v1 needs only a Status,
  since board #11 has no Priority field)
- the updateProjectV2Field hazard said a bad edit "orphans the Status
  of every card"; it orphans whichever field was edited
- the recovery recipe is genuinely Status-specific (reads .status,
  writes the Status field id), so say so and give the two
  substitutions for a Priority deletion

Verified `gh project item-list --format json` exposes both .status and
.priority before documenting the .priority swap.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Ready to approve

The change is documentation-only and the updates appear internally consistent with the stated board configuration changes and incident notes.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

@cliffhall
cliffhall merged commit 812a115 into v2/main Aug 1, 2026
6 checks passed
@cliffhall
cliffhall deleted the v2/docs/board-incoming-status-and-issue-priority branch August 1, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Boards: add an Incoming status to both boards, adopt the v2 Priority field, and document the triage rubric

2 participants