Skip to content

feat(pr-pipeline): work lane-escalated needs-human PRs in address-feedback - #9417

Merged
kyle-sexton merged 5 commits into
mainfrom
feat/address-feedback-lane-escalation
Oct 23, 2026
Merged

kyle-sexton merged 5 commits into
mainfrom
feat/address-feedback-lane-escalation

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

No related issue: owner decision Q10 option B (2026-10-23): address-feedback works a needs-human PR whose label came from a lane escalation, and keeps skipping one a review-lane hold gated.

Summary

The human-gated label stopped address-feedback on every PR that carried it, so a repeat review finding on a PR that pr-unblock or fix-ci had escalated went unworked (the #9353 case). Now the dispatcher and the select job tell the label's two sources apart and work a lane-escalated PR's reviewer-bot threads. A review-lane hold (cost, trust-gate, critical-security) still holds the PR, and anything ambiguous falls back to today's rule: only threads a trusted person with write access asked the lane to fix.

Fix

  • New .github/scripts/pr-unblock/gate-source.mjs: the hold, escalation and label-window logic moves out of clear-escalations.mjs (which now imports it, behavior unchanged), plus gateSource, which reads the PR's comments and label events and returns lane-escalation, review-hold or unknown.
  • lane-escalation needs all of: the lanes App (matched by user id and Bot type) added the label last, its work-items:escalation lane=pr-unblock comment with the resume-key line followed within a minute, no other marker on its comments since, no claude-lane-hold naming the current head, and no hold written or edited since the label was last removed. An unparsable hold or escalation marker is unknown.
  • feedback-dispatch.mjs and address-feedback.mjs select treat a lane-escalation PR as ungated; select's fix-requested output stays true for it so the write runner drops the label from its holds. Neither removes the label: clear-escalations.mjs owns that. Label events are read over GraphQL only when the label is on, so ungated PRs spend no extra request.

Verification

  • node --test over gate-source, address-feedback, feedback-dispatch, publish-feedback and clear-escalations tests: 308 pass, including a two-round test that fails without the round-marker fix. The new dispatch and select tests failed before the change (lane escalation dispatches; review hold, both present, and unparsable markers skip with a reason naming the gate source).
  • clear-escalations.test.mjs passes unchanged after the extraction.
  • scripts/check-affected.sh: 9 passed, 4 skipped; the selected Python suites pass under uvx pytest (pytest is not installed locally). actionlint and zizmor --offline on the two touched workflows: no findings.
  • Left out: a live run against a real escalated PR, which needs this on main.

Related

🤖 Generated with Claude Code

kyle-sexton and others added 4 commits October 23, 2026 10:10
…dback

A needs-human label a lane escalation (pr-unblock or fix-ci) put on no
longer stops address-feedback: the dispatcher and the select job admit
the PR's reviewer-bot threads when the lanes App added the label, its
escalation comment followed, and no review-lane hold names the current
head or is open. A review-lane hold, or anything ambiguous, keeps the
fix-request-only rule. The label stays on; clear-escalations owns it.

The hold, escalation and label-window logic moves from
clear-escalations.mjs into pr-unblock/gate-source.mjs, which both
lanes now share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-feedback

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eedback round

gateSource treated address-feedback's own round record as a foreign marker,
so the first round on an escalated PR gated every later one. It now accepts
the round and model-run lines. The dispatcher's skip tests pin the gate
source per case, and the docs say clear-escalations does not clear a label
once a round is recorded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ted PR

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton marked this pull request as ready for review October 23, 2026 14:25
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T14:27:22.403290Z 8807a2d Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude-security-review: 1 inline finding(s) on 8807a2d0e02ec05709deb555b34258cdd9a6a3e1; the summary is in this lane's pull request comment.

claude-lane: claude-security-review

Comment thread .github/scripts/pr-unblock/gate-source.mjs
@github-actions

Copy link
Copy Markdown
Contributor

claude-review reviewed 8807a2d0e02ec05709deb555b34258cdd9a6a3e1: 0 finding(s), 0 as inline comments.

I reviewed all 11 files in the diff and found nothing to block or flag. I read the diff and PR context, plus the surrounding feedback-dispatch.mjs and address-feedback.mjs code. I did not run the tests.

  • API wiring: listIssueComments in feedback-dispatch.mjs and the issueComments passed to select in address-feedback.mjs both return REST comments, the shape commentItems and gateSource expect. Both createGitHubApi functions have a graphql helper in scope for listLabelEvents.
  • Gate logic: gateSource returns unknown or review-hold for every ambiguous case I traced, so only a clean lane escalation lifts the gate. That covers a missing label event, an unparsable hold or escalation marker, a person-added label, and an escalation more than a minute after the label. In feedback-dispatch.mjs, gate is non-null whenever gated is true, so the skip message cannot dereference null.
  • fixRequested: it changes from gated to labeled. For a PR that was gated before, the behavior is unchanged. For a lane-escalated PR it is now true, which is the intended release of the write runner's label hold.
  • clear-escalations.mjs: the extraction is behavior-preserving. ROUND_MARKER is not in its known set, so a recorded address-feedback round still makes foreignMarker keep the label. That matches the changelog and README wording.
  • Changelog fragment: bump: minor fits a new capability in pr-pipeline.
  • Manifests: no plugin.json or marketplace.json changes, so there are no manifest lines.
  • Closing issues: the PR closes none ("No related issue: owner decision Q10 option B"), so there are no acceptance criteria to check.
  • Embedded instructions: the PR context contains no directives aimed at the reviewer.
  • Verification: the PR's reported test counts (308 pass, actionlint and zizmor clean) are the author's claims. I did not verify them.
  • Known gaps: the PR body defers the re-check of the gate before push, the reason allowlist and trusted-only lifts to pr-pipeline: harden the lane-escalation gate for address-feedback #9419. I did not treat those as findings.
  • Holds: none apply. The workflow edits are comments only, and no model, API-spend or schedule change is added. No trusted-actors, check-trusted-trigger, CODEOWNERS or .gitmodules file is modified; check-trusted-trigger.mjs is only imported.

@github-actions

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 8807a2d0e02ec05709deb555b34258cdd9a6a3e1: 1 finding(s), 1 as inline comments.

Security review of #9417 at 8807a2d. The change lets address-feedback work a needs-human PR when a lane escalation put the label on, and keeps the hold when a review-lane hold gated it. I read the diff and PR context, and also report-escalation.sh, which produces the escalation comments the new gate trusts.

What holds up

  • Authorship is checked by user id and Bot type for the lanes App, and by login plus footer for review-lane holds.
  • A comment a person wrote cannot make the gate fail open. A forged hold only makes it fail closed.
  • An unparsable hold or escalation marker, an unknown marker on a lanes App comment, a label a person added, and a late escalation all resolve to unknown, which keeps the old fix-request rule.
  • A hold on the current head holds even after the label was removed.
  • Extracting the hold logic out of clear-escalations.mjs keeps its behavior.
  • fixRequested: labeled keeps its old meaning for PRs that stay gated.
  • No trust-gate path is touched: .github/standards/trusted-actors/**, .github/actions/check-trusted-trigger/**, CODEOWNERS and .gitmodules are all untouched.
  • No plugin manifests are touched, so there is no manifest <field> line.
  • Actions-hardening issues are left to zizmor. The two workflow edits are comments only.

Finding (IMPORTANT, inline on gate-source.mjs)

  • gateSource accepts any pr-unblock escalation reason, so escalations that asked for a person's decision now release the hold.

Not reported, because the PR already defers them (#9419)

  • No re-check of the gate before the push.
  • A review-lane hold on a new head posted after dispatch or select.
  • Reliance on the order of timelineItems.

critical-findings: 0

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit 7849c3b Oct 23, 2026
55 of 66 checks passed
@kyle-sexton
kyle-sexton deleted the feat/address-feedback-lane-escalation branch October 23, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant