feat: flare doctor — claim-worktree health sweep + safe reclaim (#235) - #305
Conversation
Agentflare-Agent: 1 Agentflare-Branch: item-235-flare-doctor
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a public git worktree health scanner with lane flags, summaries, reclamation, and text/JSON/Markdown output. Wires these capabilities into a new ChangesGit Doctor
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant GitDoctorCLI
participant DoctorCore
participant GitWorktrees
Operator->>GitDoctorCLI: Run git doctor
GitDoctorCLI->>DoctorCore: scan(repo_root, staleness_days)
DoctorCore->>GitWorktrees: List and inspect worktrees
GitWorktrees-->>DoctorCore: Worktree health data
opt Reclaim enabled
GitDoctorCLI->>DoctorCore: reclaim(report, force)
DoctorCore->>GitWorktrees: Remove eligible worktrees and prune
end
DoctorCore-->>GitDoctorCLI: DoctorReport
GitDoctorCLI-->>Operator: Render report and exit status
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (1)
crates/flare-git-core/src/doctor.rs (1)
158-166: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider named constants for violation thresholds.
5and3are magic numbers; naming them (e.g.const DIRTY_VIOLATION_THRESHOLD: usize = 5;) would aid future tuning/readability.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/flare-git-core/src/doctor.rs` around lines 158 - 166, Define named constants for the dirty and stale worktree violation thresholds in the doctor logic, then replace the magic values in the dirty_count and stale_count comparisons and messages. Keep the current threshold values and reported behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/flare-git-core/src/doctor.rs`:
- Around line 72-81: Update parse_worktree_list to represent detached HEAD
entries distinctly instead of encoding them as a branch placeholder, then update
scan’s branch_lanes grouping and has_upstream check to run only when
entry.detached is false; preserve normal branch processing for attached
worktrees.
- Around line 94-98: Update the worktree health evaluation around the existing
Dirty and Stale flag pushes to compute each worktree’s actual elapsed time since
its last activity, and only add HealthFlag::Stale when that duration meets or
exceeds staleness_days. Ensure the stale_count violation and reclaim logic
consume only genuinely stale flags, preserving protection for fresh and
non-dirty worktrees.
- Around line 218-221: Update the lane cleanup branch around remove_dir_all to
handle failures explicitly, logging a diagnostic that includes the affected path
and error details. Only run worktree prune and add the lane to reclaimed after
successful removal, preserving the existing success behavior.
- Around line 350-352: Fix is_dirty to detect uncommitted changes from git
status --porcelain output rather than inverting the exit-status-only run_in_ok
result. Ensure it returns true when the worktree has porcelain status output, so
HealthFlag::Dirty and reclaim safety checks behave correctly.
- Around line 16-24: Update doctor::scan() to consume the orphan results from
worktree::audit_orphans() and emit HealthFlag::Orphaned with the detected item
state. Add the required zombie detection in the same scan path and emit
HealthFlag::Zombie for matching worktrees, so the report counts reflect both
states instead of remaining zero.
In `@src/cli/git.rs`:
- Around line 487-489: Update the scan command’s success check around
report.violations so every failing health flag—including MissingWorktree,
MissingUpstream, Orphaned, and Zombie—causes a nonzero exit status. Either
populate report.violations for each failing flag or use an explicit report
predicate that includes all of them, while preserving success for clean reports.
- Around line 472-480: Update the args.reclaim handling around doctor::reclaim
so status messages do not write to machine-readable stdout. Route both the
reclaimed lane messages and the empty-result message to stderr, while preserving
the existing JSON output on stdout.
- Around line 158-160: Update crates/flare-git-core/src/doctor.rs::scan to use
the configured staleness_days threshold when determining whether an existing
worktree is stale, rather than marking every worktree stale. Compare each
worktree’s actual age against the threshold before adding the stale flag,
preserving fresh lanes as non-stale and allowing --reclaim to target only stale
worktrees. Add coverage for both fresh and stale lanes.
- Around line 150-151: Constrain the DoctorArgs.format argument to the
documented text, json, and markdown values using the CLI’s value-enum or
value-parser mechanism instead of accepting arbitrary strings. Ensure invalid
values such as “jso” are rejected during argument parsing, and add coverage
verifying invalid input fails.
---
Nitpick comments:
In `@crates/flare-git-core/src/doctor.rs`:
- Around line 158-166: Define named constants for the dirty and stale worktree
violation thresholds in the doctor logic, then replace the magic values in the
dirty_count and stale_count comparisons and messages. Keep the current threshold
values and reported behavior unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 8cd05cab-1972-42c4-b1cb-de93ce2b19dd
📒 Files selected for processing (3)
crates/flare-git-core/src/doctor.rscrates/flare-git-core/src/lib.rssrc/cli/git.rs
| pub enum HealthFlag { | ||
| Dirty, | ||
| Stale { days: u64 }, | ||
| MissingWorktree, | ||
| DuplicateBranch { other_paths: Vec<String> }, | ||
| MissingUpstream, | ||
| Orphaned { item_state: String }, | ||
| Zombie, | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the relevant file and inspect the implementation around scan/summary/format/reclaim.
git ls-files 'crates/flare-git-core/src/doctor.rs'
wc -l crates/flare-git-core/src/doctor.rs
sed -n '1,260p' crates/flare-git-core/src/doctor.rs
printf '\n--- SECOND CHUNK ---\n'
sed -n '260,420p' crates/flare-git-core/src/doctor.rsRepository: getappz/agentflare
Length of output: 12986
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,260p' crates/flare-git-core/src/doctor.rs
printf '\n---\n'
sed -n '260,420p' crates/flare-git-core/src/doctor.rsRepository: getappz/agentflare
Length of output: 12893
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search the repository for any construction or handling of Orphaned/Zombie states.
rg -n --hidden --glob '!target' 'HealthFlag::(Orphaned|Zombie)|\bOrphaned\b|\bZombie\b|orphaned|zombie' crates
printf '\n--- file list ---\n'
git ls-files 'crates/**/doctor.rs' 'crates/**/claim*' 'crates/**/session*' 'crates/**/worktree*' 'crates/**/snapshot*'Repository: getappz/agentflare
Length of output: 2505
🏁 Script executed:
#!/bin/bash
set -euo pipefail
wc -l crates/flare-git-core/src/worktree.rs
sed -n '430,580p' crates/flare-git-core/src/worktree.rs
printf '\n---\n'
rg -n 'audit|orphaned|zombie|doctor|HealthFlag' crates/flare-git-core/src/worktree.rs crates/flare-git-core/src/doctor.rsRepository: getappz/agentflare
Length of output: 10939
doctor::scan() still doesn’t emit orphaned/zombie flags
crates/flare-git-core/src/worktree.rs::audit_orphans() already detects orphaned worktrees, but crates/flare-git-core/src/doctor.rs::scan() never consumes it, and nothing here constructs HealthFlag::Zombie. The doctor report’s orphaned/zombie counts stay at 0, so those states never surface in this path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/flare-git-core/src/doctor.rs` around lines 16 - 24, Update
doctor::scan() to consume the orphan results from worktree::audit_orphans() and
emit HealthFlag::Orphaned with the detected item state. Add the required zombie
detection in the same scan path and emit HealthFlag::Zombie for matching
worktrees, so the report counts reflect both states instead of remaining zero.
- is_dirty checked run_in_ok's exit status, but `git status --porcelain` always exits 0 -- it was always false, so --reclaim's dirty guard never actually fired. Now checks for non-empty output instead. - Stale was unconditionally pushed for every lane regardless of actual age, making every worktree "stale" and, combined with the dirty bug, making --reclaim eligible to delete every lane in the repo. Now derived from days since the worktree's last commit, compared against the threshold. - Orphaned (item completed/cancelled but worktree remains) was declared in the enum/summary/formatters but never computed. Wired scan() to accept a sequence_id -> state group_name map (built by the CLI layer from the items/states tables, mirroring claimed_sequence_ids) and flag lanes whose item is completed or cancelled. - Zombie (dead claiming-session pid) stays unimplemented -- no existing pid-liveness primitive in this codebase to build on; documented on the enum variant and left for a follow-up rather than rushed in. - Fixed clippy (useless format!, collapsible if) and fmt findings from CI; added coverage for the two correctness fixes. Agentflare-Agent: claude-code_2-1-217_agent Agentflare-Branch: item-235-flare-doctor
- Detached-HEAD worktrees were encoded as a fake branch name ("detached
at <rev>"), which then flowed into has_upstream and duplicate-branch
checks meant for real branches. Split into a separate detached_at
field so detached lanes are excluded from branch-only checks, same as
they should be.
- reclaim() silently dropped a lane when remove_dir_all failed (e.g. a
Windows file lock) with no diagnostic at all -- now logs which lane
and why.
- --format accepted any string and silently fell back to text output on
a typo; now a clap ValueEnum so an invalid value is a parse error.
- reclaim's status lines were printed to stdout, corrupting
`--reclaim --format json` output for a script piping it to `jq`. Moved
to stderr, alongside the JSON/markdown/text report on stdout.
Agentflare-Agent: claude-code_2-1-217_agent
Agentflare-Branch: item-235-flare-doctor
flare doctor— claim-worktree health sweep + safe reclaimItem: #235
Spec:
2026-07-21-worktree-doctor-sweepOne command
agentflare git doctorsweeping all agentflare claim worktrees with health flags:dirtygit status --porcelainnon-emptystalemissing-worktreeduplicate-branchmissing-upstreamorphanedzombieUsage:
agentflare git doctor— text output, exit 1 on violations--format json|markdown— structured output--reclaim— removes clean stale/orphaned/zombie lanes (snapshots first)--force— also reclaim dirty lanes (use with caution)--staleness-days N— custom stale thresholdTouchpoints:
crates/flare-git-core/src/doctor.rs(new) — detection + reclaim + formattingcrates/flare-git-core/src/lib.rs— addedpub mod doctorsrc/cli/git.rs—Doctorvariant onGitCommand+ handlerTests: 4 new + 85 existing = 89 passing
Summary by CodeRabbit
agentflare git doctorto inspect claim worktrees for health issues.