Skip to content

fix(item): release must not erase a reassignment made mid-run - #783

Merged
getappz merged 1 commit into
masterfrom
task/605-item-release-wipes-a-reassignment-made-m
Sep 21, 2026
Merged

getappz merged 1 commit into
masterfrom
task/605-item-release-wipes-a-reassignment-made-m

Conversation

@getappz

@getappz getappz commented Sep 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes "redispatch to a new agent doesn't stick" (seen on agentflare item #604, where a redispatch to claude-code kept reverting to opencode).

Root cause. agentflare_backend::item::release set assignee_agent = NULL whenever it released a claim, whoever the assignee was. If a job for agent A is still running when the operator redispatches to agent B, that job later fails, release_and_comment -> item_release -> item::release wipes B. The queue then retries the same job, apply_fresh_overrides sees a NULL assignee and fails open to the job's frozen payload agent (A), and the claim re-assigns the item to A:<job>.

Evidence from item_assignment_events on #604:

time from to
12:04:20 opencode:job claude-code (redispatch)
12:05:54 None opencode:job (retry's claim)

The NULL between those rows is the wipe.

Fix. item::release now clears assignee_agent only when the item has not been reassigned to a different agent type than the releasing owner (agent_part comparison). Ordinary release still clears it, so item #93's behavior (a released item must not stay pinned to the releasing agent type) is unchanged, and a no-op release is unchanged too. This complements #780, which releases the old claim on redispatch but could not stop a still-running job from wiping the assignee afterwards.

Not changed: apply_fresh_overrides fail-open (a NULL assignee after a normal release legitimately means "use the payload agent"), redispatch, reassignment_releases_claim.

Tracks agentflare item #605 (not GitHub PR/issue #605).

Test plan

  • Both new tests failed before the fix with left: None, right: Some("claude-code"), and pass after
    • release_keeps_an_assignee_reassigned_to_a_different_agent_mid_run (backend)
    • item_release_by_a_superseded_job_keeps_the_redispatched_assignee (MCP layer, replays redispatch then the old job's release)
  • cargo test -p agentflare-backend: 151 passed
  • cargo fmt --all --check clean
  • cargo clippy --locked --workspace --all-targets --all-features -- -D warnings -A unsafe_code -A clippy::pedantic exits 0
  • Full cargo test --workspace: not clean locally, see below; left to CI

Local cargo test --bin agentflare had 5 failures, none caused by this change. Two fail identically on unmodified master (agent_detector_flags_the_claudecode_marker_run_denies_on, which depends on the session env, and claim_self_repair_defers_when_another_workstation_already_holds_a_live_claim); pm_health_matches_item_health_for_the_same_params is a 1-second timing flake; the other two (claim_guard_leaves_the_claim_held_when_disarmed, claim_then_headless_not_found_releases_claim_and_posts_error_comment) pass when run alone.

Known follow-ups (not in this PR)

  • A redispatch does not stop the still-running old job; it keeps executing until it fails.
  • Unconfirmed: pick_implementer_agent may swap claude-code for a fallback when claude_over_threshold() is true. No evidence it fired here.

Summary by CodeRabbit

  • Bug Fixes

    • Preserved the current assignee when a previous agent releases an item after it has been reassigned.
    • Prevented outdated releases from clearing newer assignments.
  • Tests

    • Added coverage for reassignment scenarios across item handling and dispatch workflows.

item::release cleared assignee_agent whenever it released a claim, whoever
the assignee was. A job still running when the operator redispatched to
another agent would, on failing, wipe that reassignment; the queue retry
then saw no assignee and fell back to the job's frozen payload agent, so a
redispatch to a new agent never stuck (seen on item 604).

Only clear the assignee when it is not a different agent type than the
releasing owner. Adds a backend regression test and an MCP-level one that
replays the redispatch-then-old-job-releases sequence.

Agentflare-Agent: claude-code_2-1-278_agent
Agentflare-Branch: task/605-item-release-wipes-a-reassignment-made-m
Agentflare-Item: 605
Agentflare-Session: ca443dbc-124a-49dd-8747-6e32ade55b8e
@getappz

getappz commented Sep 21, 2026

Copy link
Copy Markdown
Owner Author

Tracking this PR for automated review (flared:51bb8de6c33b).

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

Understand this PR’s impact

Explore downstream dependencies and potential security impact with Blast Radius.

View blast radius →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: getappz/agentflare/.coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: e828e2c0-2971-4142-bebd-0328b8b52ad2

📥 Commits

Reviewing files that changed from the base of the PR and between f153897 and 554582a.

📒 Files selected for processing (3)
  • crates/agentflare-backend/src/item/claim.rs
  • crates/agentflare-backend/src/item/tests.rs
  • src/mcp_server/tests/action_tests.rs

Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.


📝 Walkthrough

Walkthrough

release now preserves an assignee when another agent reassigns the item before the original claim releases. Backend and MCP tests cover this behavior.

Changes

Lease release safety

Layer / File(s) Summary
Preserve reassigned ownership and validate release behavior
crates/agentflare-backend/src/item/claim.rs, crates/agentflare-backend/src/item/tests.rs, src/mcp_server/tests/action_tests.rs
release checks for reassignment by canonical agent type before clearing the assignee. Regression tests verify that claude-code remains assigned after an obsolete opencode:1 claim releases.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: preventing item release from erasing a reassignment made during an active run.
Description check ✅ Passed The description follows the required Summary and Test plan sections, explains the root cause and fix, documents regression tests, and reports validation results and known follow-ups. The template's No…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@getappz

getappz commented Sep 21, 2026

Copy link
Copy Markdown
Owner Author

supervisor — CI self-repair dispatched

Failing checks: build (windows-latest), CI Green.

Please investigate and push a fix.

job: 5jRhX0yJWtupNBYK_jS0V

@getappz

getappz commented Sep 21, 2026

Copy link
Copy Markdown
Owner Author

supervisor — CI green

Checks are passing again.

@getappz
getappz merged commit 9a7c762 into master Sep 21, 2026
25 of 27 checks passed
@getappz
getappz deleted the task/605-item-release-wipes-a-reassignment-made-m branch September 21, 2026 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant