Draft PRs: open-as-draft / mark-ready transitions (fixes #613) #616
No reviewers
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub!616
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/issue-613"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the binding option-a decision: draft PRs creatable/flippable via API+UI with tests.
API: POST ../pulls accepts draft (omitted = ready); PUT ../pulls/{num} {draft: bool} flips ready<>draft for author-or-triage (same roles as state transitions), 409 on merged. Flips append draft_changed thread events (from/to draft/ready labels, mirroring state_changed) with ready_for_review/converted_to_draft notify + stream fan-out; no-op flips write nothing. Merge task refuses drafts alongside the other step-1 gates (narrated 409, no publish).
UI: PullNew open-as-draft checkbox (ReleaseNew idiom; key rides only when true so plain opens stay byte-identical); header Draft badge on open drafts + mark-ready/convert-to-draft toggle beside it (pullDraftVisibility, the pullCloseVisibility precedent); list draft chips; draft_changed timeline text; the previously dead MergeBox draft arm is live. SDK pulls.open takes draft (undefined omits it), update passes through.
Docs: features/03 (new section 3.1 + route rows + SSE actions + Decisions entry) and go/12_web_ui (law 12, same commit).
Verification: go test ./internal/pulls/... -race green (incl. new draft613_test.go: open default/draft, flip both ways + events/fan-out + roles, merged-refused, merge-refused, mark-ready-then-merge, HTTP wire); make cover gate holds (pulls 96.1%, all packages >=95%); web unit full-minus-smoke 1590/1590 (new draft-613.test.js, 11 tests); vite build + esbuild SDK bundle green; gofmt/vet clean. Notes: one rare TestGetPRHeadDrift flake seen once (stamp-without-stream assertion; passes solo and 10/11 suite runs; untouched code path, per-service/per-env isolation); web/dist was unbuilt in the worktree (rebuilt; .keep restored).
Per the binding user decision, draft PRs are creatable/flippable via API+UI: POST ../pulls accepts draft (omitted = ready), PUT ../pulls/{num} {draft: bool} flips for author-or-triage with draft_changed events and ready_for_review/converted_to_draft fan-out, 409 on merged; the merge task refuses drafts alongside the other step-1 gates. UI: PullNew open-as-draft checkbox, header Draft badge + mark-ready/convert-to-draft toggle, live MergeBox draft arm. Docs: features/03 (section 3.1 + routes + Decisions) and go/12_web_ui (law 12, same change).Independent review (option-a draft PRs,
ddf92c3): APPROVE.Verified each acceptance point against the code, not just the description:
Test runs on the worktree: go test ./internal/pulls/ -race green; -cover 96.1%; gofmt/vet clean; node --test unit files minus smoke green (1590 pass; the single smoke failure 'built SPA shell /setup 403' reproduces identically on clean main — sandbox environmental, unrelated).
Two non-blocking observations: (a) a merge landing in the µs between UpdatePR's second merged-check and savePR would persist draft=true on a merged doc via reapplyPR plus a draft_changed event — functionally inert (Merged wins in every reader; merge gate checks Merged first) and the same residual race the state flips already carry (they do not even re-check); acceptable. (b) MergeBox mergeState draft arm is covered by source pins rather than a direct mergeState({pr:{draft:true}}) call — consistent with the #592 pattern used throughout; fine.
No fix commits needed — worktree clean at
ddf92c3. Verdict: APPROVE.