Skip to content

perf(lanes): configure work-unblock's stranded re-fire backoff per cause and shorten it for transient causes - #12804

Merged
kyle-sexton merged 3 commits into
mainfrom
fix/12644-replacement
Nov 3, 2026
Merged

kyle-sexton merged 3 commits into
mainfrom
fix/12644-replacement

Conversation

@kyle-sexton

Copy link
Copy Markdown
Member

Refs: #12635

Summary

Replaces #12644, the work-resolve-issue lane's per-cause stranded re-fire backoff for
work-unblock (limits.stranded-backoff-hours, with no-run, failed-mint and kill-switch set
to 1 hour and the rest kept at 3). The lane could not finish it: the PR conflicted with main,
pr-unblock's apply-conflict-patch failed, and its branch predates db1cec1 (#12725), which
ci-status needs. This branch merges #12644's head onto current main and finishes the one item
the lane was denied.

Fix

Verification

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vcupom3BKF6QuC5U3sRJPj

melodic-automation-lanes Bot and others added 3 commits November 3, 2026 03:39
Lane-Activity: work-resolve-issue/resolve-issue
The lane branch merged cleanly onto main at 394fe66, which carries
db1cec1 (#12725).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vcupom3BKF6QuC5U3sRJPj
The workflow header still said the stranded re-fire backoff starts at
three hours; it now names limits.stranded-backoff-hours. Comment only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vcupom3BKF6QuC5U3sRJPj
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 3, 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-11-03T09:34:00.986622Z 7e5bb23 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 commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

claude-review reviewed 7e5bb2312c90575b20f28eeda894ef55f0a07144: read 10 of 10 changed file(s); 0 finding(s), 0 as inline comments.

Code review: no findings

I read the whole change in all 10 files. Most of the diff sits on trusted paths (resolve-config/**, work-resolve-issue/limits.mjs, work-unblock.yml, docs/conventions/pr-pipeline.yaml), and I read each of those in full.

Checks

  • Every reader of the old fixed base now reads its cause's hours (label-unblocked.mjs L1687, L1702, L1704, L1741, L1759):
    • no-run, no-report and failed-again go through stranded().
    • kill-switch goes through the breaker backoffDue path.
    • failed-mint goes through the mint backoff path.
    • No reference to STRANDED_HOURS is left anywhere in the repo, I checked with a search.
  • The new backoffDue(since, refires, hours) keeps the old doubling and the 24-hour cap. BACKOFF_CAP_HOURS is now an alias of STRANDED_BACKOFF_MAX, so the cap and the schema maximum share one value.
  • Validation:
    • The schema sets additionalProperties: false and allows integers 1 to 24 for each cause.
    • resolve.mjs merges the configured values over the defaults.
    • resolveStrandedBackoff in limits.mjs checks each value again and falls back to the default. That covers a resolved-config file missing the key or holding a bad value.
  • The new tests look right:
    • resolve.test.mjs covers an override, an unknown cause, 0, 25 and 1.5.
    • The label-unblocked.test.mjs case covers the 1-hour first re-fire and that no-report keeps its 3 hours.
    • It also covers the doubled backoff. I traced the timing by hand: the label is re-added at 08:00:01 with one re-fire, so the next is due at 10:00:01. A sweep at 10:00:00 writes nothing and one at 10:00:02 posts.
    • The test pass counts in the PR description are the author's claim. I did not run them.
  • Docs: the README row, the schema description, the pr-pipeline.yaml comments and the work-unblock.yml header now match the code's per-cause behaviour. The README says failed-again waits at least twice its hours and failed-mint backs off only past limit-stops-per-issue re-fires; both match the code.
  • Changelog fragment: bump: minor fits a new optional config key whose defaults keep today's behaviour.

Closing issue: the PR only says Refs: #12635 and closes no issue, so there were no acceptance criteria to check.

Spend (not a finding, no hold): setting no-run, failed-mint and kill-switch to 1 hour in this repo's pr-pipeline.yaml makes work-unblock re-fire stranded issues sooner and more often. That spends more work-resolve-issue lane runs (subscription and prepaid API usage); it starts no billed charge.

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 7e5bb2312c90575b20f28eeda894ef55f0a07144: read 10 of 10 changed file(s); 0 finding(s), 0 as inline comments.

Security review: PR #12804 (head 7e5bb23)

No security issues found.

The PR adds a limits.stranded-backoff-hours setting with one value per cause. It replaces the fixed 3-hour STRANDED_HOURS that work-unblock waits before re-firing a stranded agent-ready issue. It also sets no-run, failed-mint and kill-switch to 1 hour in docs/conventions/pr-pipeline.yaml. I read every hunk in all 10 changed files, and gave the trusted paths extra scrutiny: resolve-config/resolve.mjs, work-resolve-issue/limits.mjs, work-unblock.yml and pr-pipeline.yaml.

What I checked

  • Token broker / resolve-config (resolve.mjs).
    • The only change adds a stranded-backoff-hours field to the limits block that limitsOf returns. It changes no token scope, lane slot, activity effect or skill allowlist, so the broker grants nothing new.
    • The config is still checked against the schema first (validateSchema with Ajv, resolve.mjs#L87-L99). The new schema node sets "additionalProperties": false and allows only integers from 1 to 24, so the ...limits["stranded-backoff-hours"] spread only ever receives the five known causes. A __proto__ key or any other extra key is rejected before the spread runs.
    • The change adds no imports or code to the signer's load path.
  • limits.mjs. resolveStrandedBackoff keeps a value only if it is an integer from 1 to 24 and otherwise falls back to the default of 3, so it fails closed when the config file can't be read.
  • Kill switch. Only the kill-switch re-fire backoff gets shorter (3 hours to 1, still doubling and capped at 24). The control itself is unchanged:
    • The sweep still runs only while the kill switch is off (label-unblocked.mjs#L1737-L1741).
    • The broker still refuses runs while the switch is on.
    • The switch can still stop every lane.
  • Untrusted input and merge holds.
    • The holds for an untrusted author or untrusted provenance (stoppedUntrusted, L1720), the WIP-cap pause and the limit-stops-per-issue caps are unchanged.
    • hoursFor[cause] is looked up only with fixed cause names in the code, never with text from an issue or PR.
    • The PR touches no merge-hold file.
  • work-unblock.yml. Only a comment changed.

Spend. The 1-hour base for no-run, failed-mint and kill-switch means stranded issues get re-fired, and lane runs spent, more often. That draws on prepaid credit or subscription usage, so it is not a hold.

I found no embedded instructions in the PR context. There are no prior findings, so the round cap did not apply.

critical-findings: 0

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Unattended merge: risk MED at head 7e5bb2312c90575b20f28eeda894ef55f0a07144. Only LOW, or MED on class, size and reported review-finding reasons alone, merges without a human. The lanes clear its holding reasons (a size reason holds nothing); pr-merge judges it again each run.

MED cost-finding: docs/conventions/pr-pipeline.yaml: stranded-backoff-hours:; no-run: 1; no-report: 3; failed-again: 3; failed-mint: 1; kill-switch: 1; subscription or prepaid spend, reported only
MED evidence-unbound:claude-review: not bound: evidence-missing
MED evidence-unbound:claude-security-review: not bound: evidence-missing

@kyle-sexton
kyle-sexton added this pull request to the merge queue Nov 3, 2026
Merged via the queue into main with commit ea71ee1 Nov 3, 2026
119 of 123 checks passed
@kyle-sexton
kyle-sexton deleted the fix/12644-replacement branch November 3, 2026 16:07
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