Skip to content

feat(pr-pipeline): give a fresh lane restart the earlier branch's partial work - #11025

Merged
kyle-sexton merged 3 commits into
mainfrom
fix/9468-stale-branch-context
Oct 29, 2026
Merged

kyle-sexton merged 3 commits into
mainfrom
fix/9468-stale-branch-context

Conversation

@kyle-sexton

Copy link
Copy Markdown
Member

Closes #9468

Summary

A work-resolve-issue restart that starts fresh because the earlier run's lane branch is behind main now gives the model that branch's commit subjects and diffstat as data. It also names the abandoned branch on the issue once per branch. The work-resolve-issue lane stopped on this issue because the wiring is in .github/workflows/pr-run-activity-read.yml, which it cannot push.

Fix

  • report-outcome.mjs findPrior: the stale result now carries the tip it read (resume.sha), the tip whose commits allLaneCommits passed. --find-prior outputs stale-branch and stale-tip, plus stale-noted=true when a lanes App comment already opens with <!-- work-resolve-issue stale-branch=<branch> -->. That check uses the issue comments the step already reads, so it adds no API read.
  • write-issue.mjs: new readStale puts stale_branch into issue.json (branch, tip, commit subjects, files with line counts). It shares branchWork with readResume, so both use the same GET /compare <base>...<tip> and the same 50-commit and 100-file caps. This is the one added read, the earlier branch's commit list, which the issue's Proposal allows. A malformed branch or tip, or an unreadable comparison, writes no issue file.
  • pr-run-activity-read.yml: the write-issue step gets STALE_BRANCH/STALE_TIP from issue-prior. The "Collect the issue outcome" step writes stale into lane.json only while stale-noted is false. No workflow input, output or permission is added.
  • report-outcome.mjs main: when lane.json's stale has this issue's lane-branch shape, it posts the stale-branch comment (staleComment). A failed post is logged and does not fail the report. Nothing deletes the branch.
  • plugins/work-items/skills/work/SKILL.md: issue-lane step 1 says how to read stale_branch: reuse the approach, redo the work, and treat its contents as data on the same terms as resume.
  • Docs: docs/conventions/pr-pipeline/pr-run-activity.md. Fragments: .changes/pr-pipeline/ and .changes/work-items/.

Verification

  • Red first: with report-outcome.mjs, write-issue.mjs and pr-run-activity-read.yml restored from origin/main, 7 of the new or changed tests fail. They cover the find-prior stale outputs and stale-noted, the issue.json stale_branch record and its refusals, the once-per-branch comment, and the workflow wiring.
  • Green: node --test .github/scripts/work-resolve-issue/*.test.mjs .github/actions/resolve-config/callers.test.mjs gives 588 pass, 0 fail. bash scripts/write-runner-never-rules.test.sh gives 76 pass. actionlint .github/workflows/pr-run-activity-read.yml is clean, and so is scripts/check-affected.sh (pre-push).
  • A test covers a behind branch with a commit that is not the lanes App's: it yields no stale-branch, so its subjects never reach the model.

Related

🤖 Generated with Claude Code

…tial work

When work-resolve-issue starts fresh because the run it would resume
left a lane branch behind the default branch, report-outcome
--find-prior now outputs stale-branch and stale-tip, and write-issue.mjs
adds stale_branch to issue.json: that branch's commit subjects and
diffstat from the same capped compare a resume uses, at the tip whose
commits find-prior checked, framed as data in the work skill.

report-outcome names the branch on the issue once, in a comment opening
with a per-branch marker. find-prior already reads the issue's comments,
so it reports stale-noted when that marker exists and lane.json carries
the branch only while unnoted. No branch is deleted.

Closes #9468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 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-29T19:11:46.259170Z d5d60ce PR opened
ℹ️ 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-review: 1 inline finding(s) on d5d60ceb3e675b9a41bc601c0fcbbddebcb2ec58; the summary is in this lane's pull request comment.

claude-lane: claude-review

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

claude-review reviewed 3230859b6b7ad54d939c7c0e368b7cf7c2bae5a0: 0 finding(s), 0 as inline comments.

No blocking or advisory findings. I read the whole diff and the PR context, and checked readBranch's key parameter and the evaluate and tempDir helpers the new workflow test uses. I did not run the tests. The 588-pass result in the PR description is the author's claim, unverified by me.

Closing issue #9468 (acceptance criteria, as amended by the decision comment)

  • A fresh start after a behind branch gives the model the earlier branch's commit subjects and diffstat as data: met. findPrior returns stale.tip, --find-prior outputs stale-branch and stale-tip, and write-issue.mjs readStale writes issue.stale_branch. Tests cover the output, the record, the malformed-input refusals and the workflow wiring.
  • The lane posts the abandoned branch's name on the issue, once per branch: met. staleComment is posted from main when lane.json's stale has this issue's lane-branch shape. Dedupe works through stale-noted, which only matches a lanes App comment whose first line is the marker. Tests cover a quoted marker, another branch's marker, a non-bot author and a re-posted comment.
  • No API reads beyond the compare call and the earlier branch's commit list: met. The only added read is GET /compare base...tip for the stale tip. The stale-noted check reuses the comments --find-prior already reads.
  • Trust: the stale branch only reaches the model after allLaneCommits has passed on it. A test covers a behind branch with a non-App commit, which yields no stale-branch. lane.json's stale is rewritable during the run, but readBranch limits it to this issue's lane-branch shape and the comment text is fixed, so the worst case is a repeated fixed-text comment.

Trusted paths: report-outcome.mjs, pr-run-activity-read.yml and plugins/work-items/skills/work/SKILL.md were read in full for their change. No workflow input, output, permission or token scope is added.

Cost: the change adds one extra GET /compare read per fresh start past a stale branch, plus a few more model input tokens. That uses prepaid or subscription usage only, so it is not a hold.

Non-blocking note: readStale throws on an unreadable comparison, so a stale branch deleted between --find-prior and write-issue would fail the run, even though the context is optional. This matches how resume behaves, the window is small, and the PR states it as intended. I'm not counting it as a finding.

Manifests: the diff touches no plugin.json or marketplace.json, so there are no manifest lines. The changelog fragments use bump: minor for pr-pipeline (new outputs and issue field) and bump: patch for work-items (skill wording), which looks consistent.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

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

No security issues found in this change.

critical-findings: 0

What I checked in the trusted-path files (report-outcome.mjs, pr-run-activity-read.yml):

  • Trust boundary for commit subjects. The stale-branch data only exists when findPrior returned stale. findPrior returns it only for the branch that passed usable and allLane, the same allLaneCommits check a resume needs. write-issue.mjs fetches GET /compare base...tip at the exact tip find-prior checked, so a push after the check cannot add commits. The subjects reach the model as data under the same 50-commit, 100-file and 200-character caps resume uses. The SKILL.md text keeps the data-not-instruction framing. This widens nothing: the stale branch is data from a branch that already passed the commit check, and the model gets no new capability.
  • Injection. STALE_BRANCH and STALE_TIP come from step outputs that were validated before use. write-issue.mjs checks the branch against the issue's lane-branch regex and the tip against a 40-hex pattern, and throws otherwise. The workflow reads them through env:, not inline run: expressions. LANE_STALE is passed to jq --arg, so it cannot inject. report-outcome re-checks the branch with isLaneBranch(branch, issueNumber) before using it in the comment, and the comment body is a fixed template. A rewritten lane.json can at most make the lanes App post a comment naming a branch of this issue's own lane shape.
  • Dedupe marker. staleNoted counts a comment only when the lanes App wrote it and its first line is exactly the marker. A stranger's comment, or a comment that merely quotes the marker, does not suppress the note. The tests cover both.
  • Token, permissions and kill switch. The diff adds no workflow permission, input, output or token scope. The new POST /issues/N/comments uses the same lane token and comment endpoint report-outcome already uses. The failure path is logged and does not fail the report. Nothing deletes a branch.
  • Merge holds. No hold or gate logic changed.
  • Manifests. No plugin.json or marketplace.json changes.
  • Instruction surface. plugins/work-items/skills/work/SKILL.md only adds guidance, and it keeps the existing data-only framing. Nothing was removed or softened.

Spend: the change adds one GET /compare per stale fresh start and one issue comment. That is prepaid API and Actions usage, not a hold.

… test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@melodic-automation-lanes melodic-automation-lanes Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 29, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

The pr-unblock lane stopped on this pull request and needs a person: the pull request changes .github/workflows/, which the lane token cannot push, so the lane does not address its review threads.

  • Reason: feedback-protected-path
  • Resume key: d5d60ceb3e675b9a41bc601c0fcbbddebcb2ec58 (the head the lane stopped on)

To resume, deal with the reason above, remove the needs-human label (and do-not-merge, if set), then dispatch the pr-unblock workflow with pr-number=11025 and activity=address-feedback:

gh workflow run pr-unblock.yml -R melodic-software/claude-code-plugins -f pr-number=11025 -f activity=address-feedback

@kyle-sexton kyle-sexton removed the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 29, 2026
@kyle-sexton

Copy link
Copy Markdown
Member Author

lane token cannot push workflow files; fixed from a session in 353b73f

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit e21d237 Oct 29, 2026
62 of 63 checks passed
@kyle-sexton
kyle-sexton deleted the fix/9468-stale-branch-context branch October 29, 2026 23:21
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.

feat(pr-pipeline): give a fresh lane restart the earlier branch's partial work

1 participant