feat: auto-resume on provider usage limit reset + /code-review command - #46
feat: auto-resume on provider usage limit reset + /code-review command#46gr3enarr0w wants to merge 4 commits into
Conversation
|
Thanks — the auto-resume work is the valuable part here, but this PR is doing three separate things and I can't take it as one:
Could you rebase this down to just auto-resume + /code-review, drop the isolation files (they'll come from #43), and add coverage for parseResetHintMs, the backoff/cap in scheduleAutoResume, and the recoverStaleRuns re-arm? Happy to merge once it's scoped to its own change. |
feat(workflow-manager): schedule automatic resume after usage-limit pause (QuintinShaw#27) - ExecOptions.autoResume (default true) controls per-run opt-out - Parses resetHint for h/min patterns; falls back to 60 min - Exponential backoff per runId, capped at 5 attempts - Re-arms timer on cold start in recoverStaleRuns() for persisted paused runs - cancelAutoResume() called in stop() and deleteRun() to prevent ghost resumes feat(code-review): add /code-review built-in workflow command (QuintinShaw#32) - New src/code-review.ts: generateCodeReviewWorkflow() - Phase 1: 7 parallel finder agents (A-G) with tier routing: A/B/C (correctness) → medium, D/E/F (cleanup) → small, G (altitude) → big - Phase 2: parallel verify pass per candidate, drops REFUTED findings - Phase 3: big-tier synthesis, ranked by angle priority, capped at 10 - Registered in builtin-commands.ts with 4 input modes: /code-review → git diff HEAD /code-review HEAD~3.. → git range /code-review src/foo → specific file /code-review 42 → gh pr diff 42 - Exported from index.ts as generateCodeReviewWorkflow Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- workflow-manager.test.ts: unit-test parseResetHintMs (2h / 30min / 1h30min / garbage fallback), scheduleAutoResume exponential backoff + MAX_AUTO_RESUME_ATTEMPTS (5) cap, and recoverStaleRuns re-arming timers for usage-limit paused runs - builtin-commands.test.ts: update count 4→5 and sorted names to include "code-review"; fix idempotent and missing-commands assertions - builtin-workflows.test.ts: add generateCodeReviewWorkflow test asserting meta.name, Find/Verify/Report phases, parallel + candidateSchema - src/index.ts: move code-review.js export to correct alphabetical position (after builtin-commands.js) to satisfy biome sort check Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1aa292b to
7fb49fc
Compare
|
Thanks for the quick turnaround — the split is clean (no more #43 overlap, rebases onto main with zero conflicts) and the new tests are real. Two things before merge, both in the new code:
A regression test asserting both stop() and deleteRun() call cancelAutoResume would pin #1 (that gap is exactly why it slipped through). Optional: clamp the backoff with Math.max(delay, 60_000) so a hint that parses to ~0 doesn't fire five instant retries. |
…with execFile Move cancelAutoResume() and autoResumeAttempts.delete() above the !managed guard in stop() so timers armed by recoverStaleRuns() for persistence-only runs are always cancelled, even when the run has no in-memory ManagedRun. Replace promisify(exec) with promisify(execFile) + array args in the /code-review diff-source invocation to eliminate the shell-injection vector from user-supplied branch/range/path inputs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PR Reviewer Guide 🔍(Review updated until commit 2347f1a)Here are some key observations to aid the review process:
|
autoResumeAttempts was in-memory only. On cold start, recoverStaleRuns() re-armed timers with the count reset to 0, so a run that hit the 5-attempt cap could receive another 5 attempts after restart. Fix: add autoResumeAttempts to PersistedRunState (optional field, zero-safe for existing records). recoverStaleRuns() restores the count before scheduling. persistRun() writes the current count on every usage-limit pause. The timer callback persists the incremented count before calling resume() so a crash mid-attempt doesn't reset the cap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Persistent review updated to latest commit 2347f1a |
|
This bundles two unrelated features with very different risk profiles, and they're blocking each other: /code-review is close to mergeable, while auto-resume needs another iteration. Please split it — /code-review can land quickly. Auto-resume (#27), the things that need rework:
/code-review (#32), minor: raise |
|
Hey @gr3enarr0w — no rush at all, just checking in since it's been a couple weeks. Are you planning to pick up the review notes here? The |
Extracts the /code-review half of #46 onto current main, leaving the auto-resume half (run-persistence.ts / workflow-manager.ts) for a later PR. - src/code-review.ts: generateCodeReviewWorkflow() — 7 parallel finder agents (correctness x3, cleanup x3, altitude x1) -> per-candidate verify pass -> ranked markdown report. - src/builtin-commands.ts: register /code-review alongside the other bundled commands; gather the diff via execFile (no shell) so branch/range/path input can't break out into a shell command. - src/index.ts: export generateCodeReviewWorkflow + MAX_DIFF_CHARS. - tests/builtin-commands.test.ts, tests/builtin-workflows.test.ts: /code-review coverage. - README.md: document /code-review's input modes and behavior. Addresses the maintainer's earlier review nits on this half: - maxBuffer on the diff-gathering exec raised from Node's 1MB default to 64MB, with a clear notify (not a raw ERR_CHILD_PROCESS_STDOUT_MAXBUFFER) when even that's exceeded. - Diffs over 200k chars (MAX_DIFF_CHARS) are truncated with a visible notice at both the command layer and, defensively, inside the generated workflow script itself (which also stamps diffTruncated on the result). - Verify phase deliberately keeps its hand-rolled 3-way CONFIRMED / PLAUSIBLE / REFUTED agent() call instead of the verify() stdlib, which only returns a boolean and would collapse that signal for no behavioral gain (only REFUTED is filtered) — documented inline in code-review.ts. Co-authored-by: Clark Everson <clark@everson.dev>
|
Heads up — I've split the This PR stays open for the auto-resume half, which still needs the rework from my earlier review (the |
|
Hi @gr3enarr0w — an update on this one. The I want to be straight that your PR directly informed that work — reviewing it is what surfaced the exact edge cases the rewrite had to get right (the swallowed I think this can be closed now that both halves are covered (#62 + #78), but I'll leave that to you in case you'd rather repurpose it. Really appreciate the contributions — hope to see more. |
Summary
Closes #27
Closes #32
feat(workflow-manager): auto-resume after usage-limit pause (#27)
When a workflow hits a provider quota/usage limit, it's now checkpointed as
paused(already in place via #26). This PR adds the automatic resume layer on top.How it works
ExecOptions.autoResume(defaulttrue) — opt out per-execution by passingautoResume: falseexecuteRuncatches aPROVIDER_USAGE_LIMITerror, it callsscheduleAutoResume(runId, resetHint)parseResetHintMs()extracts hours/minutes from the verbatimresetHintstring (e.g."~3h","45 min"), falls back to 60 minutesMAX_AUTO_RESUME_ATTEMPTS = 5then gives uprecoverStaleRuns()now re-arms timers on cold start for any persistedpaused + pauseReason === "usage_limit"runsstop()anddeleteRun()cancel pending timers so stopped runs don't ghost-resume"autoResuming"event before each attempt for observabilityfeat(code-review): /code-review built-in command (#32)
New
src/code-review.tsimplementinggenerateCodeReviewWorkflow(), registered as/code-review.Phases
Phase 1 — Find (7 parallel agents)
Phase 2 — Verify — parallel verifier per candidate, drops REFUTED
Phase 3 — Report — big-tier synthesis, ranked A/B/C > D/E/F > G, capped at 10
Input modes