Skip to content

feat(web): show draft pull requests as drafts in the sidebar - #219

Merged
incognitojam merged 2 commits into
mainfrom
t3code/gray-draft-pr-number
Aug 20, 2026
Merged

feat(web): show draft pull requests as drafts in the sidebar#219
incognitojam merged 2 commits into
mainfrom
t3code/gray-draft-pr-number

Conversation

@incognitojam

@incognitojam incognitojam commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Note

A draft pull request looked identical to one ready for review in the sidebar — emerald #123, tooltip reading "Open". It now reads muted with a "Draft" tooltip, using the same resolver the pull request panel already used. Web only; mobile needs a different answer.

The problem

prStatusIndicator branched on pr.state alone, so a draft rendered exactly like a pull request that was ready for review. The tooltip said PR #123 - Open, and that string is also the link's aria-label.

The pull request panel already got this right — resolvePullRequestState mutes drafts and its comment says the tones are shared "so one pull request cannot look like two different things in two places". The sidebar was the exception.

The fix

isDraft now travels with the change request. It is optional on both ChangeRequest and the VCS-status contract, so an old server or a provider that does not report it reads as "not known to be a draft" rather than silently claiming ready-for-review.

All four source control adapters decode their own spelling: GitHub isDraft, GitLab draft with the pre-14.0 work_in_progress fallback, Bitbucket draft, Azure isDraft. Only GitHub needed new request fields, and they ride along on --json calls it already makes — no extra round trip. GitLab, Bitbucket and Azure were already returning the field in payloads that were being discarded.

On the client, the sidebar now takes its state word and tone from resolvePullRequestState, which removes the parallel colour switch and leaves one place to change a tone. Merged and closed still outrank the flag: a draft that lands reads Merged.

Two supporting changes that are easy to miss:

  • threadChangeRequestSnapshotsEqual compares isDraft. Without it, "Ready for review" would not repaint the row.
  • settledPrHoverColorClass takes the pull request rather than just its state, so hovering a settled draft no longer restores emerald and announces it as ready.

Scope

Mobile is deliberately untouched. text-zinc-500 already means closed in thread-pr-presentation.ts, so painting drafts gray there would make the two indistinguishable on the surface with the smallest tap target. It needs a glyph rather than a tone, which is its own change. isDraft reaches mobile on the wire and is ignored.

Before / after

The same real draft pull request (this one), on the same seeded sidebar. Before, it is emerald and its tooltip reads PR #219 - Open; after, it is muted and reads PR #219 - Draft.

Before After
Sidebar thread row showing #219 in emerald Sidebar thread row showing #219 in muted gray

Verification

ThreadStatusIndicators and the full sourceControl suite pass (204 tests), GitManager passes (89). Typecheck is clean on web, server, contracts, client-runtime, desktop and mobile.

New tests cover a draft round trip per provider adapter, a GitManager status test asserting a draft arrives as isDraft: true, and on the web side the muted tone, the Draft tooltip, merged-outranks-draft, the hover tone, and both snapshot-equality cases.


Written by an agent (Claude Code, claude-opus-5).

A draft pull request rendered in the sidebar exactly like one that is ready
for review: emerald `#123`, and a tooltip reading "PR #123 - Open". The pull
request panel already muted drafts, so the same pull request looked like two
different things in two places.

`isDraft` now travels with the change request: optional on the `ChangeRequest`
and VCS-status contracts, decoded by all four source control adapters in their
own spelling, and carried through `GitManager` into thread status. GitHub is
the only provider that needed new request fields, and they ride along on calls
it already makes.

The sidebar takes its state and tone from `resolvePullRequestState`, the
resolver the pull request panel uses, which replaces a parallel colour switch.
Drafts read muted zinc with a "Draft" tooltip; merged and closed still outrank
the flag.

Mobile is unchanged: gray already means "closed" there, so it needs a
different answer than tone.

Written by an agent (Claude Code, claude-opus-5).
@incognitojam
incognitojam marked this pull request as ready for review August 20, 2026 09:56
@incognitojam
incognitojam merged commit 9fd1793 into main Aug 20, 2026
8 of 9 checks passed
@incognitojam
incognitojam deleted the t3code/gray-draft-pr-number branch August 20, 2026 10:45
incognitojam added a commit that referenced this pull request Aug 20, 2026
> [!NOTE]
> TL;DR: Add ledger coverage for the seven substantive fork capabilities
merged after the latest nightly promotion, so the next upstream rebase
reports their semantic overlap before release.

The fork feature ledger did not yet cover draft pull request status,
missing-workspace startup guards, attention-state sidebar prominence,
provider subscription limits, active-terminal close confirmation, fork
analytics identity, or arbitrary file attachments. This records the
behavioral invariants, implementation and upstream watch paths, focused
test evidence, and retirement criteria for PRs #219, #222, #224, #225,
#226, #227, and #228.

Draft status and terminal close confirmation cite their partial upstream
counterparts in [upstream
pingdotgg#7148](pingdotgg#7148) and [upstream
pingdotgg#7592](pingdotgg#7592). The smaller #220,
#221, and #223 fixes intentionally remain patch-stack-only under the
ledger's incremental coverage policy.

The ledger mutation tests now select fixtures by the property they need
instead of assuming the alphabetically first capability has multiple PRs
and an unassessed upstream status.

Verification:

- `vp run --filter @t3tools/scripts ledger:check`
- `vp test run scripts/fork-feature-ledger.test.ts
scripts/generate-fork-features-summary.test.ts` — 34 tests passed
- `vp check .github/fork-features.yml
scripts/fork-feature-ledger.test.ts`

---
Written by an agent (T3 Code, gpt-5.6-sol).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 20, 2026
> [!NOTE]
> A draft pull request looked identical to one ready for review in the
sidebar — emerald `#123`, tooltip reading "Open". It now reads muted
with a "Draft" tooltip, using the same resolver the pull request panel
already used. Web only; mobile needs a different answer.

## The problem

`prStatusIndicator` branched on `pr.state` alone, so a draft rendered
exactly like a pull request that was ready for review. The tooltip said
`PR #123 - Open`, and that string is also the link's `aria-label`.

The pull request panel already got this right —
`resolvePullRequestState` mutes drafts and its comment says the tones
are shared "so one pull request cannot look like two different things in
two places". The sidebar was the exception.

## The fix

`isDraft` now travels with the change request. It is optional on both
`ChangeRequest` and the VCS-status contract, so an old server or a
provider that does not report it reads as "not known to be a draft"
rather than silently claiming ready-for-review.

All four source control adapters decode their own spelling: GitHub
`isDraft`, GitLab `draft` with the pre-14.0 `work_in_progress` fallback,
Bitbucket `draft`, Azure `isDraft`. Only GitHub needed new request
fields, and they ride along on `--json` calls it already makes — no
extra round trip. GitLab, Bitbucket and Azure were already returning the
field in payloads that were being discarded.

On the client, the sidebar now takes its state word and tone from
`resolvePullRequestState`, which removes the parallel colour switch and
leaves one place to change a tone. Merged and closed still outrank the
flag: a draft that lands reads Merged.

Two supporting changes that are easy to miss:

- `threadChangeRequestSnapshotsEqual` compares `isDraft`. Without it,
"Ready for review" would not repaint the row.
- `settledPrHoverColorClass` takes the pull request rather than just its
state, so hovering a settled draft no longer restores emerald and
announces it as ready.

## Scope

Mobile is deliberately untouched. `text-zinc-500` already means
**closed** in `thread-pr-presentation.ts`, so painting drafts gray there
would make the two indistinguishable on the surface with the smallest
tap target. It needs a glyph rather than a tone, which is its own
change. `isDraft` reaches mobile on the wire and is ignored.

## Before / after

The same real draft pull request (this one), on the same seeded sidebar.
Before, it is emerald and its tooltip reads `PR #219 - Open`; after, it
is muted and reads `PR #219 - Draft`.

| Before | After |
| --- | --- |
| <img
src="https://raw.githubusercontent.com/yngatech/t3code/assets/pr-219-draft-pr-number/before.png"
width="420" alt="Sidebar thread row showing #219 in emerald"> | <img
src="https://raw.githubusercontent.com/yngatech/t3code/assets/pr-219-draft-pr-number/after.png"
width="420" alt="Sidebar thread row showing #219 in muted gray"> |

## Verification

`ThreadStatusIndicators` and the full `sourceControl` suite pass (204
tests), `GitManager` passes (89). Typecheck is clean on web, server,
contracts, client-runtime, desktop and mobile.

New tests cover a draft round trip per provider adapter, a `GitManager`
status test asserting a draft arrives as `isDraft: true`, and on the web
side the muted tone, the `Draft` tooltip, merged-outranks-draft, the
hover tone, and both snapshot-equality cases.

---
Written by an agent (Claude Code, claude-opus-5).
yngatech-nightly Bot pushed a commit that referenced this pull request Aug 20, 2026
> [!NOTE]
> TL;DR: Add ledger coverage for the seven substantive fork capabilities
merged after the latest nightly promotion, so the next upstream rebase
reports their semantic overlap before release.

The fork feature ledger did not yet cover draft pull request status,
missing-workspace startup guards, attention-state sidebar prominence,
provider subscription limits, active-terminal close confirmation, fork
analytics identity, or arbitrary file attachments. This records the
behavioral invariants, implementation and upstream watch paths, focused
test evidence, and retirement criteria for PRs #219, #222, #224, #225,
#226, #227, and #228.

Draft status and terminal close confirmation cite their partial upstream
counterparts in [upstream
pingdotgg#7148](pingdotgg#7148) and [upstream
pingdotgg#7592](pingdotgg#7592). The smaller #220,
#221, and #223 fixes intentionally remain patch-stack-only under the
ledger's incremental coverage policy.

The ledger mutation tests now select fixtures by the property they need
instead of assuming the alphabetically first capability has multiple PRs
and an unassessed upstream status.

Verification:

- `vp run --filter @t3tools/scripts ledger:check`
- `vp test run scripts/fork-feature-ledger.test.ts
scripts/generate-fork-features-summary.test.ts` — 34 tests passed
- `vp check .github/fork-features.yml
scripts/fork-feature-ledger.test.ts`

---
Written by an agent (T3 Code, gpt-5.6-sol).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant