feat(setbuilder): replace_slot agent tool — atomic track swap#472
Conversation
Add a single Family-2 mutation tool `replace_slot` to the WrzDJSet pass-2 agent: swap the track in a slot in place, keeping its position, instead of remove+insert (which passes through a transient invalid state and shifts positions). `_tool_replace_slot` resolves the slot via `_slot_or_error`, refuses locked slots (mirroring `_tool_remove_slot`), resolves the replacement via `_pool_track_or_error`, and writes ONLY the slot's `track_id` using the same namespaced id derivation the insert tools use (`_pass1_track_meta(track).slot_track_id`). It never touches the `requests` table. Owner-scoped (both slot and pool track resolved against `set_obj.id`), rationale-required via `MUTATION_TOOLS`, and dispatched only through `apply_tool_call`'s closed allowlist. Closes #467 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 1 hour, 44 minutes, and 26 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?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 credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. 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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds Changesreplace_slot Mutation Tool
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
# Conflicts: # server/app/services/setbuilder/pass2_agent.py # server/tests/test_setbuilder_pass2.py
Why
Part of #442 (Family 2 — safe mutations). Swapping the track in a slot today means remove + insert: two ops with a transient invalid state and shifting positions.
replace_slotdoes it atomically — same position, new track.What
Adds a single mutation tool
replace_slotto the WrzDJSet pass-2 agent (server/app/services/setbuilder/pass2_agent.py):_tool_replace_slot(db, set_obj, payload)resolves the slot via_slot_or_error, refuses locked slots (AgentToolError, mirroring_tool_remove_slot), resolves the replacement via_pool_track_or_error, then writes only the slot'strack_id— keeping itsposition.db.flush(); returns({"slot_id", "pool_track_id"}, {slot.position}).MUTATION_TOOLS, thehandlersallowlist inapply_tool_call, the_agent_tools()schema (_tool("replace_slot", {"slot_id": "integer", "pool_track_id": "integer"})— auto-addsrationale), and a one-sentencereplace_slotclause in_tool_display_summary.Slot ↔ pool-track id derivation (design decision)
The new
track_idis derived with_pass1_track_meta(track).slot_track_id, the exact helper the insert tools route through. It resolves totrack.track_id or f"pool:{track.id}"(pass1_deterministic.py), identical to what_insert_track_atbuilds inline — so the namespacing rule stays in one place rather than being re-derived.Security invariants (from #442)
set_obj.id.locked: a locked slot cannot be replaced.rationale(enforced byMUTATION_TOOLS).apply_tool_call's closed allowlist.track_id; never therequeststable (regression test asserts unchanged).Testing
server/tests/test_setbuilder_pass2.py: replace happy path (position preserved, other slot untouched), locked rejection, foreign pool track, foreign slot, missing-rationale,requests-untouched regression, display-summary.🤖 Co-authored by Claude Opus 4.8. Closes #467.
Summary by CodeRabbit