Release v0.4.7
What's Changed
PR #24: fix: treat non-zero exit codes as failures when Claude produces no usable output
Author: @moneypennyrasener
Problem
fastflow list was showing failed Claude Code runs as active because Invoke() in internal/runner/claude.go captured non-zero exit codes in result.ExitCode but always returned (result, nil). Since the runner only calls SetStatus(failed) when executeStage returns an error, failures were silently swallowed.
Fixes #23
Changes
internal/runner/claude.go
- Add
ErrRateLimitedsentinel error andisRateLimited()helper that detects "you've hit your limit" / "rate limit" patterns in Claude output (mirrors existingisNotLoggedIn()) - After auth-failure detection, check for rate limiting and return
ErrRateLimitedwhen detected - If Claude exits with a non-zero code and produced no usable output (
result.Output == ""), return an error containing the exit code and a tail ofRawOutputfor context. Runs that exit non-zero but still produced a valid result stream are left unaffected (key constraint from the issue)
internal/runner/claude_test.go
- Add
TestIsRateLimitedcovering positive cases (case-insensitive) and a negative case - Add
TestIsMaxTurnsErrorcovering positive and negative cases
How to verify
-
go test ./internal/runner/...— all tests pass, including the newTestIsRateLimitedandTestIsMaxTurnsError
Full Changelog: v0.4.6...v0.4.7
What's Changed
- fix: treat non-zero exit codes as failures when Claude produces no usable output by @moneypennyrasener in #24
Full Changelog: v0.4.6...v0.4.7