Skip to content

fix(pr-pipeline): end a workflow-stale issue run green and re-fire it - #9537

Merged
kyle-sexton merged 3 commits into
mainfrom
agent-a910bd2b34d6554d6
Oct 24, 2026
Merged

kyle-sexton merged 3 commits into
mainfrom
agent-a910bd2b34d6554d6

Conversation

@kyle-sexton

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

Copy link
Copy Markdown
Member

Refs: #9498

Summary

An issue-lane run that waits in its concurrency slot while a lane workflow change merges failed red at the read runner's workflow-current step, before any model turn. That red run was noise in lane telemetry, and work-unblock's sweep re-fired it only because it failed. This PR ends that run green and keeps the re-fire.

Fix

  • pr-run-activity-read.yml: on a blob difference, workflow-current writes stale=true, prints a ::warning::workflow-stale line and exits 0. A new Stop on stale workflow files step runs only then. issue-prior is skipped and go is false, so issue-run-started is false and reuse-branch is empty. Every caller job keyed on those (apply-issue-patch, run-checks, report-statuses, report-outcome) skips. No outcome marker is posted, so the issue is never read as done. The run concludes success, so morning-brief's lane section, which counts only failure, timed_out and startup_failure, does not count it.
  • label-unblocked.mjs: stoppedStale matches that step at conclusion: success in a resolve-issue job of a green run. The sweep then re-fires the run like a failed one: once per version of the two lane workflow files, recorded in the existing marker comment. Each run's job listing is now read once per sweep, through jobLister, and shared by didNoWork, cancelledBeforeWork and stoppedStale, so the new check makes no extra API call.
  • Docs: the comments in the workflow, the work-unblock.yml header, pr-run-activity.md and a pr-pipeline changelog fragment are updated.

Exposure 2 (a lane workflow merge during the model run, which refuses the apply-issue-patch mint) is handled in the companion broker PR in melodic-software/azure-iac. That PR is not deployed yet.

Verification

  • node --test .github/scripts/work-unblock/label-unblocked.test.mjs: 127 pass, 0 fail. New tests: a green stale-stopped run is re-fired, is not re-fired again on the same workflow files, and is re-fired once more on new files. A green run whose stop step was skipped, or whose stop step sits in another job, is not re-fired, and neither is a held issue's. Removing the stoppedStale call makes the re-fire test fail (126 pass, 1 fail).
  • node --test .github/actions/resolve-config/callers.test.mjs: 161 pass, 0 fail. The stale cases now assert exit 0 with stale=true written to GITHUB_OUTPUT, and the fresh cases assert that nothing is written. The test also covers the stop step's and issue-prior's conditions, and go returning run=false on STALE=true.
  • nice bash scripts/check-affected.sh --uncommitted: 9 passed, 4 skipped, over 7 changed files.
  • actionlint on both edited workflows: clean.

Related

  • melodic-software/azure-iac#88 (draft, not deployed): lets apply-issue-patch mint under the same superseded-workflow conditions as report-outcome.

🤖 Generated with Claude Code

kyle-sexton and others added 3 commits October 23, 2026 21:34
An issue-lane run that waited in its slot past a lane workflow merge
failed red at the read runner's workflow-current step before any model
turn. That step now sets stale=true and ends green: a dedicated
`Stop on stale workflow files` step runs, go is false, so no model turn,
outcome marker or caller job follows, and the run counts as no failure.

work-unblock's sweep finds that step in the run's job listing and
re-fires the issue once per version of the lane workflow files, as it
does a failed run. Each run's job listing is read once and shared.

Refs: #9498

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

Assert the stale re-fire reads a run's job listing once, word the script
header to match work-unblock.yml, remove the held case that returned
before any job read, and drop an issue reference from a test comment.

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

chatgpt-codex-connector Bot commented Oct 24, 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-24T01:49:36.550278Z 18e6d3c 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

Copy link
Copy Markdown
Contributor

claude-review reviewed 18e6d3c96f908196238c76f6e59387c4d79cb3a7: 0 finding(s), 0 as inline comments.

No findings on PR #9537 at 18e6d3c.

I read the full diff and .claude-lane/pr-context.md. I also read label-unblocked.mjs and pr-run-activity-read.yml around the changed code. I ran no tests or commands, because this lane has no shell. The test counts in the PR description are author-claimed and unverified by me.

What I checked:

  • Stale-run stop (pr-run-activity-read.yml). workflow-current writes stale=true and exits 0. The new Stop on stale workflow files step runs only when stale == 'true'. issue-prior is skipped, and go sets run=false. Every later step I could find that touches the activity keys on steps.go.outputs.run == 'true', and the job outputs issue-run-started and go derive from go. With no issue-prior output, reuse-branch, resume-branch and resume-tip are empty.
  • Sweep (label-unblocked.mjs). jobLister memoises each run's job listing, so didNoWork, cancelledBeforeWork and stoppedStale share one read per run. stoppedStale requires a green run and a successful Stop on stale workflow files step inside a resolve-issue job. A skipped stop step or one in another job does not count, and the tests cover both. The re-fire reuses the existing once-per-workflow-key guard through workflowKey() and the refire markers.
  • Test and doc changes. The tests follow the behavior change, and callers.test.mjs now checks the stop step's and issue-prior's conditions and the go script's STALE handling. The comments, the work-unblock.yml header, pr-run-activity.md and the changelog fragment (bump: patch, a bug fix) all describe the new behavior.
  • Closing issue. The PR says Refs: #9498 and closes no issue, so there are no acceptance criteria to check. No hold class applies: there is no new model call, schedule, trusted-actors, CODEOWNERS or .gitmodules change, and no plugin manifest is touched.

@github-actions

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 18e6d3c96f908196238c76f6e59387c4d79cb3a7: 0 finding(s), 0 as inline comments.

No security findings. critical-findings: 0

I read the full diff and PR context, then the read runner's job outputs and work-resolve-issue.yml's caller-job conditions. Embedded text in the PR context: none that tries to steer the review. No manifest or trust-gate paths are touched, so there are no manifest <field> lines and no hold.

What I checked

  • Stale run stops before any model turn or write. Before this change, a stale run failed red and stopped there. The new path is workflow-current writing stale=true, then exit 0, then issue-prior skipped, then go=false. Every later step in the run job keys on steps.go.outputs.run == 'true', including the always() ones around lines 1841–2045. issue-run-started is false and reuse-branch is empty (issue-prior is skipped). Every caller job that mints or writes (apply-issue-patch, run-checks, report-statuses, report-outcome) requires one of those, so none runs. The control that the stale-workflow check protects is not weakened. The broker still refuses the mint on stale files, and the model never runs.
  • Failure and uncertainty paths still fail closed. "Cannot read the run's workflow commit" still exits 0 with no stale output, so the broker decides, as before. STALE is compared as a literal string in go, and none of these values reach a command or path unquoted.
  • Re-fire sweep. stoppedStale requires a green run, a valid numeric run id, and a resolve-issue job whose Stop on stale workflow files step concluded success. The re-fire key, the once-per-workflow-version limit, the labeler trust check and the refusal checks run unchanged afterwards. A green run cannot loop the sweep: the tests cover no second re-fire on the same files. The jobLister cache is keyed by run id and only removes duplicate reads, so it widens nothing.
  • Instruction-surface deletions. None. The doc and comment edits restate the same behaviour. The register file was not consulted, because no standing rule is removed or softened.

A green stale run is now invisible to failure telemetry (the PR calls this out). That is an observability trade-off, not a security issue.

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 24, 2026
Merged via the queue into main with commit 537e70b Oct 24, 2026
56 of 67 checks passed
@kyle-sexton
kyle-sexton deleted the agent-a910bd2b34d6554d6 branch October 24, 2026 01:58
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