⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
src/queue/processors.ts pushes onto failedOutputs when a check_run (line 10995), comment
(line 11487), or label (line 11549) publish fails. The structurally identical gate_check_run
publish path does not: its permission_missing branch (lines 10760-10807) and its outer catch
(lines 10808-10857) only write an audit-log entry and attempt a fallback publish — if that fallback
also fails, nothing is ever pushed onto failedOutputs.
Consequence: for a gate-only repo (one with no comment/label surface configured), a revoked
Checks:write permission or a transient GitHub 5xx during the gate_check_run publish leaves both
publishedOutputs and failedOutputs empty. finishPublicSurfacePublication (lines 9144-9176)
checks failedOutputs to decide whether to fire the loud pr_public_surface_failed audit event,
escalate via capturePostHogReviewFailure, and throw RetryablePublicSurfacePublishFailedError for
transient-retry — with failedOutputs empty, all three are skipped, so the review is silently never
posted with no operator-visible signal at all.
Requirements
- Push a
gate_check_run entry onto failedOutputs when both the primary publish and its fallback
fail, matching the pattern already used for check_run/comment/label.
- Do not change the fallback-publish attempt itself — only ensure a genuine, final failure is
recorded the same way the other three output types already are.
Deliverables
All three Deliverables are required in the same PR.
Test Coverage Requirements
src/** is measured by codecov/patch (99%+ target, branch-counted). The new tests must exercise
the previously-silent double-failure path directly.
Expected Outcome
A gate-only repo whose gate_check_run publish fails entirely gets the same operator-visible
failure signal (audit event, PostHog escalation, transient retry) that every other output type
already gets, closing a silent-failure gap specific to gate-only repos.
Links & Resources
src/queue/processors.ts:10760-10857 (gate_check_run publish path, the fix target), :10995,
:11487, :11549 (already-correct sibling failedOutputs.push calls)
src/queue/processors.ts:9144-9176 (finishPublicSurfacePublication, the downstream consumer of
failedOutputs)
Context
src/queue/processors.tspushes ontofailedOutputswhen acheck_run(line 10995),comment(line 11487), or
label(line 11549) publish fails. The structurally identicalgate_check_runpublish path does not: its
permission_missingbranch (lines 10760-10807) and its outercatch(lines 10808-10857) only write an audit-log entry and attempt a fallback publish — if that fallback
also fails, nothing is ever pushed onto
failedOutputs.Consequence: for a gate-only repo (one with no comment/label surface configured), a revoked
Checks:write permission or a transient GitHub 5xx during the
gate_check_runpublish leaves bothpublishedOutputsandfailedOutputsempty.finishPublicSurfacePublication(lines 9144-9176)checks
failedOutputsto decide whether to fire the loudpr_public_surface_failedaudit event,escalate via
capturePostHogReviewFailure, and throwRetryablePublicSurfacePublishFailedErrorfortransient-retry — with
failedOutputsempty, all three are skipped, so the review is silently neverposted with no operator-visible signal at all.
Requirements
gate_check_runentry ontofailedOutputswhen both the primary publish and its fallbackfail, matching the pattern already used for
check_run/comment/label.recorded the same way the other three output types already are.
Deliverables
gate_check_runpublish (both primary and fallback attempts failing) results in agate_check_runentry infailedOutputs.createOrUpdateGateCheckRunto fail withpermission_missingandcreateOrUpdateErroredGateCheckRun(the fallback) to also fail, and assertsfailedOutputscontains a
gate_check_runentry.finishPublicSurfacePublication's downstream effects (thepr_public_surface_failedaudit event,capturePostHogReviewFailureescalation, andRetryablePublicSurfacePublishFailedError) now fire for this case, matching what alreadyhappens for an equivalent
check_runfailure.All three Deliverables are required in the same PR.
Test Coverage Requirements
src/**is measured bycodecov/patch(99%+ target, branch-counted). The new tests must exercisethe previously-silent double-failure path directly.
Expected Outcome
A gate-only repo whose
gate_check_runpublish fails entirely gets the same operator-visiblefailure signal (audit event, PostHog escalation, transient retry) that every other output type
already gets, closing a silent-failure gap specific to gate-only repos.
Links & Resources
src/queue/processors.ts:10760-10857(gate_check_runpublish path, the fix target),:10995,:11487,:11549(already-correct siblingfailedOutputs.pushcalls)src/queue/processors.ts:9144-9176(finishPublicSurfacePublication, the downstream consumer offailedOutputs)