fix: when errors happen, put ai-rework, and do not automatically call again (#30) - #34
Merged
Conversation
A failed run was retried unattended, forever. classifyCause marked usage/rate limits, turn/budget ceilings and network errors "resumable", so ResumeParked re-ran Rework on them every poll cycle (5m backoff doubling to 60m) — one issue that kept failing kept re-running the whole pipeline and burning tokens with nobody watching. Now a failure is terminal: the issue is parked as ai-rework with the error commented, and nothing touches it until a human removes the label, which re-queues it (reusing the preserved worktree and branch, per the continue-don't-reset rule). The only resume left is interruptedCause — the deliberate hand-off written by SweepOrphans after a daemon restart and by the dashboard's Continue — which is not a failure. The backoff still covers a resume that fails before it re-parks (e.g. GitHub unreachable), so its resumable cause survives on disk. The park comment now carries the real error instead of a generic snippet: - Errors are clipped, not tail-truncated: 6000 chars keeping BOTH ends, so the head (which step failed) and the tail (the API's own message) both survive, inside a collapsed fenced block. - A claude transport/parse failure reports stderr AND stdout, each labelled and explicitly "(empty)" when blank — claude often writes its diagnostics to stdout, and the old "(stderr: )" said nothing. - failureSummary adds turns, cost and wall time, so the comment shows how far the session got before it died. - Every park comments, including a re-park: the silent-repark rule only existed to keep the backoff loop from spamming the issue, and that loop is gone. Judgment calls made headlessly: - The tooling-failure path (abort) also parks now. It used to strip ai-wip and leave the issue eligible, which re-triaged and re-attempted it every cycle — the same unattended retry loop, paid for in triage tokens. gh/git calls are already retried in-band, so reaching abort means the failure is persistent. It no longer deletes the worktree or branch either. - The park comment stopped advertising `loop -rework <N>` (that flag does not exist) and does not offer Continue (the dashboard shows it only for ai-stopped tickets). It names the one action that works: remove the label. Docs (operations, how-it-works, configuration, README) updated to match. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # ai/prompts/comments.md.tmpl
Nothing retries an issue automatically any more. The resume stage (ResumeParked, shouldResume, per-issue exponential backoff, `loop -rework` and rework.go) re-ran the whole pipeline every cycle for a parked issue, so one broken ticket burned tokens indefinitely on work nobody watched. A parked issue now waits for a human, who removes the rework label to queue another attempt; the preserved worktree, branch, logs and session are reused by the next run per the continue-not-reset rule. classifyCause keeps recognizing causes purely to explain the park in the comment, and park-cause on disk is now a diagnostic nothing reads back. Continue drops its session-resume branch: it clears the stopped label and local state so the normal cycle re-picks the issue in the same worktree. preflight stops asking repos to create ai-failed (recognized, never applied) and starts asking for ai-stopped, which the dashboard does apply. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
It was already deprecated — recognized but never applied. Drop the labelFailed const, the StateLabels.Failed field and its "failed" JSON key, the hasStateLabel and stateKind cases, the "failed" sidebar rank tier, the dashboard badge branch, and every mention across docs and the example config. Behavior change: an issue still carrying a literal ai-failed label from an older version is no longer recognized as being in a state, so it becomes eligible again and the loop will pick it up. Remove the label, or relabel those issues ai-rework, before upgrading if that is not what you want. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
abort() now delegates to park(), so a failure in wt.Create parks the issue before any worktree or branch exists. The park comment told the human unconditionally that "the preserved worktree, branch and logs are reused", which on that one path names work that was never created. Reword it to cover whatever the failed run actually produced, and align the same claim in docs/operations.md. Also document why readParkCause has no caller in the daemon: it is a test/inspection accessor, kept so the read goes through the same path logic as the write. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
stripeClass had a "failed" branch that stateKind can no longer return, and readParkCause lost its only production caller when the resume scan went away. The park-cause marker is still written and cleared as an operator diagnostic, so the reader moves to a test helper to keep the existing assertions honest. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
readSession lost its last production caller when the auto-resume path was removed, while scanIssueDir kept its own inlined ReadFile + Unmarshal of the same file — dead code sitting next to a duplicate of itself. Point scanIssueDir at readSession so SessionInfo parsing has one implementation, and pull the "session" filename into a sessionFile const alongside stateFile/titleFile/ parkCauseFile so the writer and reader can't drift. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
rework.md.tmpl and guidance-interrupted were deleted earlier on this branch, but their entries lingered in the map. The test only errors on templates missing an entry, never on extra ones, so nothing failed — they were just dead weight. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #30
Automated by loope (bug flow). Spec and plan, if any, are committed in this branch under docs/.