Maintainers are penalised by a gate built for contributors
gate.linkedIssue: block exists to stop unlinked contributor work. Applied to a maintainer's own PR it asks them to file an issue against their own repo before touching it, and fails or holds the PR when they don't. The bot's own PRs — release-please, dependency bumps, generated-doc refreshes — hit it constantly for the same reason.
On the production Orb, hold | missing_linked_issue is the second-largest hold bucket: 503 over the last week, behind only the hold | success bug fixed in #10116.
Turning the gate off is not the answer: it should keep full force for contributors, and everything that analyses an issue that is linked should keep working for everyone.
What this needs to preserve
- Contributors unaffected.
block keeps its full force.
- All analysis retained when an issue IS linked —
linkedIssueSatisfaction, settings.linkedIssueHardRules, linkedIssueLabelPropagation.
- The signal stays visible. A maintainer should still see "No linked issue detected"; it just should not be a verdict.
Fix: one clamp
The two halves are already separate concerns, which is what makes this clean:
- the
missing_linked_issue finding is produced on requireLinkedIssue — true for any mode but off
- it blocks only when
resolveConfiguredGateMode resolves block
So clamping block → advisory for maintainer-authored PRs keeps the finding visible while removing exactly its power to fail the gate, hold, or close. Nothing is suppressed and nothing goes silent.
gate:
linkedIssue: block # unchanged — still blocks contributors
linkedIssueMaintainerExempt: true # new
Config-as-code only (global or per-repo .loopover.yml), following hardGuardrailGlobs — no DB column, so no dashboard toggle can silently disagree with the file, and no migration.
Scope of "maintainer"
Exactly the existing protected author set — authorIsOwner || authorIsAdmin || authorIsAutomationBot (processors.ts's protectedAuthor) — reused rather than redefined, so it cannot come to mean one thing here and another on the close path. Bots are included: they already have auto-close protection for the same reason, and they are a large share of the unlinked PRs in practice.
Deliberately not a bypass flag
The clamp is applied to settings before it reaches gateCheckPolicy, not passed as an argument, because both halves that must agree read that object. A bypass flag threaded through the linked-issue paths would have had to be excluded from each one by hand — and the next such path would have been added without the exclusion.
It also must be applied at all four gateCheckPolicy sites (webhook, sweep, two re-gate paths). Wiring only the webhook path would mean the same PR gets one verdict live and a different one when the sweep re-gates it.
Maintainers are penalised by a gate built for contributors
gate.linkedIssue: blockexists to stop unlinked contributor work. Applied to a maintainer's own PR it asks them to file an issue against their own repo before touching it, and fails or holds the PR when they don't. The bot's own PRs — release-please, dependency bumps, generated-doc refreshes — hit it constantly for the same reason.On the production Orb,
hold | missing_linked_issueis the second-largest hold bucket: 503 over the last week, behind only thehold | successbug fixed in #10116.Turning the gate off is not the answer: it should keep full force for contributors, and everything that analyses an issue that is linked should keep working for everyone.
What this needs to preserve
blockkeeps its full force.linkedIssueSatisfaction,settings.linkedIssueHardRules,linkedIssueLabelPropagation.Fix: one clamp
The two halves are already separate concerns, which is what makes this clean:
missing_linked_issuefinding is produced onrequireLinkedIssue— true for any mode butoffresolveConfiguredGateModeresolvesblockSo clamping
block→advisoryfor maintainer-authored PRs keeps the finding visible while removing exactly its power to fail the gate, hold, or close. Nothing is suppressed and nothing goes silent.Config-as-code only (global or per-repo
.loopover.yml), followinghardGuardrailGlobs— no DB column, so no dashboard toggle can silently disagree with the file, and no migration.Scope of "maintainer"
Exactly the existing protected author set —
authorIsOwner || authorIsAdmin || authorIsAutomationBot(processors.ts'sprotectedAuthor) — reused rather than redefined, so it cannot come to mean one thing here and another on the close path. Bots are included: they already have auto-close protection for the same reason, and they are a large share of the unlinked PRs in practice.Deliberately not a bypass flag
The clamp is applied to
settingsbefore it reachesgateCheckPolicy, not passed as an argument, because both halves that must agree read that object. A bypass flag threaded through the linked-issue paths would have had to be excluded from each one by hand — and the next such path would have been added without the exclusion.It also must be applied at all four
gateCheckPolicysites (webhook, sweep, two re-gate paths). Wiring only the webhook path would mean the same PR gets one verdict live and a different one when the sweep re-gates it.