fix(plans): /revise route now dispatches plan_update prompt#75
Merged
Conversation
The HTTP /api/plans/{plan_id}/revise route was still telling the
planner to call plan_propose, which refuses when a pending plan
already exists for the task. Result: clicking Revise in the UI
silently no-op'd while the request returned 200.
Extract a shared request_plan_revision helper in nerve.agent.plan_service
so the HTTP route and MCP plan_revise tool can't drift apart on the
prompt template again. The route now also rejects non-pending plans
with a real 409 and surfaces validation errors with 400/404, letting
the UI display a meaningful message instead of dropping the request.
- new: nerve/agent/plan_service.py (PlanNotFound/TaskNotFound/PlanNotPending)
- HTTP and MCP surfaces become thin wrappers around the helper
- planStore.ts gains actionError state; PlanDetailPage shows it inline
- tests/test_plan_revise.py covers helper + tool + HTTP route paths
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The web UI's Revise button silently no-op'd. The HTTP route
/api/plans/{plan_id}/revisestill instructed the planner to callplan_propose, which now refuses with "Task X already has a pending or implementing plan. Skip it." whenever a pending plan exists for the task — i.e. every revise attempt. The request returned200 {\"status\": \"revision_requested\"}, so the failure was invisible.Fix: dispatch the
plan_updateprompt (mirroring the MCPplan_revisetool) and extract a sharedrequest_plan_revision()helper so the two surfaces can't drift apart again.Changes
nerve/agent/plan_service.py— single source of truth for revision dispatch. Exposesrequest_plan_revision(db, engine, plan_id, feedback)plusPlanNotFound/TaskNotFound/PlanNotPendingexceptions. Prompt template is a module-level constant.nerve/gateway/routes/plans.py— thin wrapper around the helper; maps exceptions to 400 (empty feedback), 404 (plan/task missing), 409 (non-pending). Previously every error path returned 200 with feedback silently stored on the plan.nerve/agent/tools.py::plan_revise— same thin-wrapper treatment.planStore.revisePlannow returnsPromise<boolean>, setsactionErroron failure, and parses FastAPI's{detail: ...}JSON envelope.PlanDetailPagerenders the error inline next to the textarea; the form only collapses on success.Test plan
tests/test_plan_revise.py— 17 new tests covering the helper (prompt content, feedback persistence, session routing, fallback tocron:task-planner, all three exceptions, empty-feedback ValueError), the MCP tool wrapper, and the HTTP route via FastAPITestClient.npm run buildcleanOut of scope
The dead supersede-loop in
_plan_propose_impl(tools.py:1131-1133) is now unreachable from the revise path. Harmless dead code; separate cleanup PR.