Problem
The #label-close-split-brain guard — which exists to stop ORB branding a PR with an enforcement label
when the paired close did not happen — only inspects the same planned array
(src/services/agent-action-executor.ts:252-257):
for (let i = 0; i < outcomes.length; i++)
if (planned[i]?.actionClass === "close" && planned[i]?.closeKind === closeKind) return outcomes[i]?.outcome;
return undefined; // → guard does not fire
Two paths never carry the pair, so the guard silently no-ops.
1. The approval queue stages one action per row
agent-approval-queue.ts:344 builds plan = [pendingActionToPlanned({ actionClass: pending.actionClass, … })]
— a single action. createPendingAgentActionIfAbsent conflicts on
(repoFullName, pullNumber, actionClass) (src/db/repositories.ts:6355), so the close and its
blacklist / contributor_cap / review_nag / copycat label are two independently accept/rejectable
rows. A maintainer rejecting the close and accepting the label labels an open PR "blacklisted
contributor".
2. After a breaker downgrade the close is gone but the label remains
downgradeCloseToHold's isDowngradableClose requires actionClass === "close"
(src/settings/agent-actions.ts:625-651), so #9115 now drops a copycat/review_nag close while leaving
its closeKind-tagged label in the plan. The executor then finds no close at all → undefined → label
applied.
Trigger
closehold:<repo> engaged plus a block-mode copycat match (agent-actions.ts:939-943); or a maintainer
rejecting a staged close whose companion label row is still pending.
Impact
A PR is publicly branded with a plagiarism / ban / cap enforcement label while remaining open and
unclosed — precisely the outcome the guard's own doc comment says must never happen. Contributor-visible
reputational harm from a decision the system deliberately withheld, and nothing removes the label
afterwards (see #9009 — manual-review is not the only sticky label).
Requirements
- Make the correlation durable rather than batch-local: stage the coupled pair as one pending row
whose params carry both mutations, so accept/reject is atomic over the pair.
- Or have
downgradeCloseToHold and the approval accept path drop any label whose closeKind has no
surviving/accepted close.
- Add an invariant test: no enforcement label is ever applied without its paired close having succeeded,
across all execution entry points.
Test Coverage Requirements
99%+ patch coverage, branch-counted; both paths (approval-queue split, post-breaker downgrade) covered
explicitly.
Links & Resources
maintainer-only — actuation atomicity.
Problem
The
#label-close-split-brainguard — which exists to stop ORB branding a PR with an enforcement labelwhen the paired close did not happen — only inspects the same
plannedarray(
src/services/agent-action-executor.ts:252-257):Two paths never carry the pair, so the guard silently no-ops.
1. The approval queue stages one action per row
agent-approval-queue.ts:344buildsplan = [pendingActionToPlanned({ actionClass: pending.actionClass, … })]— a single action.
createPendingAgentActionIfAbsentconflicts on(repoFullName, pullNumber, actionClass)(src/db/repositories.ts:6355), so the close and itsblacklist/contributor_cap/review_nag/copycatlabel are two independently accept/rejectablerows. A maintainer rejecting the close and accepting the label labels an open PR "blacklisted
contributor".
2. After a breaker downgrade the close is gone but the label remains
downgradeCloseToHold'sisDowngradableCloserequiresactionClass === "close"(
src/settings/agent-actions.ts:625-651), so #9115 now drops acopycat/review_nagclose while leavingits
closeKind-tagged label in the plan. The executor then finds no close at all →undefined→ labelapplied.
Trigger
closehold:<repo>engaged plus a block-mode copycat match (agent-actions.ts:939-943); or a maintainerrejecting a staged
closewhose companionlabelrow is still pending.Impact
A PR is publicly branded with a plagiarism / ban / cap enforcement label while remaining open and
unclosed — precisely the outcome the guard's own doc comment says must never happen. Contributor-visible
reputational harm from a decision the system deliberately withheld, and nothing removes the label
afterwards (see #9009 —
manual-reviewis not the only sticky label).Requirements
whose params carry both mutations, so accept/reject is atomic over the pair.
downgradeCloseToHoldand the approval accept path drop anylabelwhosecloseKindhas nosurviving/accepted close.
across all execution entry points.
Test Coverage Requirements
99%+ patch coverage, branch-counted; both paths (approval-queue split, post-breaker downgrade) covered
explicitly.
Links & Resources
src/services/agent-action-executor.ts~252-257, ~351-358;src/services/agent-approval-queue.ts~344;src/settings/agent-actions.ts~625-651, ~939-943;src/db/repositories.ts~6355maintainer-only — actuation atomicity.