Repository navigation
Retiring draft left no "complete, do not merge yet" hold the arming lane respects #405
Description
#398 → #400 made ready the default and kept pr-draft as an explicit escape hatch ("set true only where a human is expected to mark it ready"). That covers the case where a person will flip it. It does not cover the case that showed up within hours: work that is complete and green and must not merge until something outside the PR exists.
desk#92 is the instance. Two workflow files, all checks green, and a body that says plainly it must not merge before a broker grant and a NOTIFY_WORKFLOW_REFS entry exist — because merging first ships a door whose mint cannot resolve, which claim-boundary.md P4 forbids. The session held it as draft, then wrote out the conflict rather than deciding alone:
- the convention says a branch that is not ready is not a PR yet;
- the property says do not ship a door that cannot mint;
- draft satisfies the second by breaking the first, and there is no third state.
It resolved fine there (draft is sanctioned for that PR, and dependency order is the real answer), but the general gap is real and will recur wherever a change is correct and its precondition is external — a broker door before its grant, a caller before its callee, a ruleset before the check that produces its context. Tonight's pr-arm re-pin was exactly that shape, and it only avoided the problem because the ordering happened to run inside one session.
What the hold has to do
- Visible to the factory. The whole point of retiring draft was that the arming lane never touches a draft, so held work is invisible to it. A replacement must be a PR the lane can see and decline, not one it cannot see.
- Refuse merge mechanically. Not a convention, not a body paragraph. The org's own rule is that review is not the gate — the enforceable predicate is a check.
- Say why, in the PR. A hold with no stated reason is indistinguishable from an abandoned PR after a week.
- Clear without a deploy. Removing the hold must be cheap, or it becomes its own bottleneck.
Shape I would build
A do-not-merge label plus one always-run reusable check that fails while the label is present and passes when it is not, added to the required set the same way pr-claim / pr-claim is. Roughly:
_hold.ymlin this repo,workflow_call, one job keyedhold,permissions: { pull-requests: read }, red iff the label is on the PR, with the label's reason echoed into the check output.- The context joins
required-baselineso it applies org-wide, the way the claim does. - Removing the label re-runs the check and the arming lane picks the PR up on its own.
That satisfies all four: the PR is ready and visible, the lane declines it because a required check is red, the reason is in the check output, and clearing it is one label.
The cost, stated rather than discovered: it is a new org-wide required context, which is the same class of change as the claim, and a required check with no producer bricks a repo (.github-private#243's lesson). It has to roll before it is required, exactly like pr-claim did.
The alternative worth weighing first
Do nothing, and treat "complete but blocked on an external precondition" as evidence the work is in the wrong order — land the precondition first, as desk#92 concluded and as the door re-pin did. That is cheaper and it is often right. It fails when the precondition is a manual [org]/[settings] toggle that a keyholder can only do at some later hour, which is common here: the PR then either sits ready and mergeable-by-machine, or sits draft and invisible.
I lean toward building it, because the dark factory makes the window between "green" and "merged" arbitrarily short, and that is precisely when an unmechanised hold stops working. But it is a new required context, so it is a keyholder's call and not a session's.
Refs #398, #400, .github-private#938 (the convention), desk#92 (the instance), .github-private#243 (a required check with no producer).
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity