Skip to content

refactor(mcp): split item_inner's dispatch arms into src/mcp_server/item.rs - #187

Merged
getappz merged 1 commit into
masterfrom
refactor/split-item-inner-dispatch
Jul 14, 2026
Merged

refactor(mcp): split item_inner's dispatch arms into src/mcp_server/item.rs#187
getappz merged 1 commit into
masterfrom
refactor/split-item-inner-dispatch

Conversation

@getappz

@getappz getappz commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • item_inner was a single 411-line function (the file's largest, and its top complexity hotspot per both ast-grep line-span scanning and lean-ctx's own health scoring) dispatching all 13 item actions inline.
  • Moved each arm's body verbatim into its own item_<action> method in a new src/mcp_server/item.rs submodule; item_inner is now just the match dispatch. No behavior change.

Test plan

  • cargo test --bin agentflare — 437 passed
  • cargo fmt --check
  • cargo clippy --bin agentflare — no new warnings

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation for item requests, including required fields and pagination values.
    • Improved reliability of item claiming, completion, and release workflows to prevent race conditions.
    • Standardized error handling and response formatting across item actions.
  • New Features

    • Added support for attaching and removing labels from items, with clear operation results.

…tem.rs

item_inner was a single 411-line function (the file's largest, and its top
complexity hotspot per both ast-grep line-span scanning and lean-ctx's own
health scoring) dispatching all 13 item actions inline. Moved each arm's
body verbatim into its own item_<action> method in a new submodule;
item_inner is now just the match dispatch. No behavior change.
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Item MCP handling is extracted from item_inner into src/mcp_server/item.rs. Dedicated methods now cover CRUD, claims, completion, cancellation, and label operations while preserving validation, backend access, worktree workflows, and JSON responses.

Changes

Item MCP handlers

Layer / File(s) Summary
Core item handlers
src/mcp_server.rs, src/mcp_server/item.rs
The server declares the item submodule, delegates ItemRequest actions to dedicated methods, and implements CRUD validation, backend operations, pagination, state updates, deletion, and JSON serialization.
Claim and completion workflows
src/mcp_server/item.rs
Claim, heartbeat, release, and done handlers coordinate backend locking with worktree creation and pull-request publication.
Cancellation and label actions
src/mcp_server/item.rs
Cancellation updates item state and releases the caller’s claim, while label handlers add or remove associations and return operation status.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the refactor of moving item_inner dispatch arms into src/mcp_server/item.rs.
Description check ✅ Passed The description includes the required Summary and Test plan sections and is mostly complete, with only the Notes for reviewers section omitted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/split-item-inner-dispatch

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/mcp_server/item.rs (3)

188-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Progress-sender fallback duplicated with item_done.

The PROGRESS_SENDER.try_with(|ps| f(item, &repo_root, target, ps.as_ref())).unwrap_or_else(|_| f(item, &repo_root, target, None)) fallback (lines 218-226) is repeated almost verbatim in item_done below (lines 313-321), only swapping create_worktree for push_and_open_pr. Worth factoring into a shared helper that takes the worktree fn as a parameter.

🤖 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 `@src/mcp_server/item.rs` around lines 188 - 245, Factor the repeated
PROGRESS_SENDER.try_with fallback pattern from item_claim and item_done into a
shared helper that accepts the worktree operation as a parameter. Update
item_claim’s create_worktree call and item_done’s push_and_open_pr call to use
the helper while preserving their existing arguments and fallback behavior.

278-348: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mirrors the same progress-sender fallback in item_claim.

Lines 313-321 duplicate the PROGRESS_SENDER.try_with(...).unwrap_or_else(...) fallback already flagged in item_claim above, just calling push_and_open_pr instead of create_worktree. Same extraction opportunity applies here.

🤖 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 `@src/mcp_server/item.rs` around lines 278 - 348, Extract the duplicated
PROGRESS_SENDER.try_with(...).unwrap_or_else(...) fallback in item_done into the
shared helper introduced for item_claim, preserving the existing
push_and_open_pr invocation and fallback behavior. Update item_done to call that
helper while keeping the surrounding PR URL handling unchanged.

10-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider a shared "required field" helper.

The ok_or_else(...)? + .trim().is_empty() pattern here (name, lines 11-16) repeats near-identically for every required field across all 13 handlers in this file (id in item_get/item_delete/item_claim/etc., label_id in item_add_label/item_remove_label, state_id in item_update_state). A small generic helper would cut this boilerplate significantly.

♻️ Example helper
fn require_field(value: Option<String>, field: &str, action: &str) -> Result<String, ErrorData> {
    let v = value
        .ok_or_else(|| ErrorData::invalid_params(format!("{field} is required for {action}"), None))?;
    if v.trim().is_empty() {
        return Err(ErrorData::invalid_params(format!("{field} is required"), None));
    }
    Ok(v)
}
🤖 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 `@src/mcp_server/item.rs` around lines 10 - 51, Introduce a shared
required-field helper near the item handlers that validates an optional string
for both presence and non-blank content, using the field and action to produce
the existing error messages. Replace the repeated validation patterns across
handlers including item_create, item_get/item_delete/item_claim,
item_add_label/item_remove_label, and item_update_state, while preserving each
handler’s current required-field semantics and error behavior.
🤖 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.

Nitpick comments:
In `@src/mcp_server/item.rs`:
- Around line 188-245: Factor the repeated PROGRESS_SENDER.try_with fallback
pattern from item_claim and item_done into a shared helper that accepts the
worktree operation as a parameter. Update item_claim’s create_worktree call and
item_done’s push_and_open_pr call to use the helper while preserving their
existing arguments and fallback behavior.
- Around line 278-348: Extract the duplicated
PROGRESS_SENDER.try_with(...).unwrap_or_else(...) fallback in item_done into the
shared helper introduced for item_claim, preserving the existing
push_and_open_pr invocation and fallback behavior. Update item_done to call that
helper while keeping the surrounding PR URL handling unchanged.
- Around line 10-51: Introduce a shared required-field helper near the item
handlers that validates an optional string for both presence and non-blank
content, using the field and action to produce the existing error messages.
Replace the repeated validation patterns across handlers including item_create,
item_get/item_delete/item_claim, item_add_label/item_remove_label, and
item_update_state, while preserving each handler’s current required-field
semantics and error behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f18c1ea7-b508-4109-bd4c-cfbf30bf25e1

📥 Commits

Reviewing files that changed from the base of the PR and between 5ece9c3 and 9de87a0.

📒 Files selected for processing (2)
  • src/mcp_server.rs
  • src/mcp_server/item.rs

@getappz
getappz merged commit f7464af into master Jul 14, 2026
14 checks passed
@getappz
getappz deleted the refactor/split-item-inner-dispatch branch July 14, 2026 20:30
getappz pushed a commit that referenced this pull request Aug 25, 2026
Discovery tick dispatches purely on the ready-for-work label, so items
#184/#185/#186/#187 (go/no-go candidates from #166's spec) whose own
description says "Decision pending — not dispatched" got auto-dispatched
and re-dispatched across multiple agents anyway -- the prose was never
actually enforced.

Add a needs-decision label that blocks run_discovery_tick even while
ready-for-work is also present. Stripping ready-for-work alone wouldn't
have been durable: redispatch unconditionally re-attaches it, so the new
label has to keep gating on its own until a human clears it.

Agentflare-Agent: claude-code
Agentflare-Branch: fix/dispatch-failure-ceiling-any-reason
getappz pushed a commit that referenced this pull request Aug 25, 2026
reconcile_orphaned_jobs already tries to release a dead job's claim via
release_and_comment under a with_owner_override scope before calling
restore_ready_for_work, but that release is best-effort (let _ = ...) and
its failure is silent. When it silently doesn't take, restore_ready_for_work
still puts ready-for-work back on the item -- so run_discovery_tick sees it
as dispatchable, but the actual dispatch (and redispatch) both refuse with
"blocked_by_live_claim" until the claim's TTL naturally expires (up to 4h).

Reproduced live on items #185/#187: both sat stuck for the better part of
an hour with no visible error, owner strings confirmed to be their own now-
dead job's claim.

restore_ready_for_work now releases the claim itself too, using the same
owner string reconcile_orphaned_jobs already constructs -- defense in
depth, not a replacement for the earlier release, so it only ever touches
the dead job's own lease.

Agentflare-Agent: claude-code
Agentflare-Branch: fix/dispatch-failure-ceiling-any-reason
getappz added a commit that referenced this pull request Aug 27, 2026
…ent dispatch (#619)

WorkflowEngine::recover() resumes non-terminal sdd_loop runs after a daemon
restart by calling execute_workflow() directly, bypassing execute_work's
run_in_worktree/EXECUTE_WORK_CWD_LOCK entirely (PR #601 only guards fresh
dispatches from the job queue). A resumed run's agent dispatch still went
through the ambient-cwd run_headless, so it silently inherited whatever
worktree another concurrently-running item's chdir happened to have set --
confirmed live on items #186/#187, both binding into task/186's worktree.

Thread the item's own worktree path through StepInvocation.cwd (persisted
on WorkItemData, read at step-execution time so a resumed run still has
it) and dispatch via run_headless_in instead, mirroring the pattern
app_send_hook already uses for App workflows. This removes the dependency
on global process cwd for this call path rather than trying to widen the
lock to cover the recovery path too.

Also splits the execute_work_impl dispatch-fixture tests out of work.rs
into work_dispatch_fixture_tests.rs to stay under the file's LOC gate.

Agentflare-Agent: claude-code
Agentflare-Branch: task/191-opencode-agentflare-work-dispatch-doesn
Agentflare-Item: 191
Agentflare-Session: 0be92ce2-29ad-46d0-9303-597ede893b7b

Co-authored-by: shiva <shiva@gosysinfo.tech>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant