Skip to content

Add plan_resume MCP tool for mid-pipeline recovery - #217

Merged
neoneye merged 22 commits into
mainfrom
feature/plan-resume-tool
Mar 10, 2026
Merged

Add plan_resume MCP tool for mid-pipeline recovery#217
neoneye merged 22 commits into
mainfrom
feature/plan-resume-tool

Conversation

@neoneye

@neoneyeneoneye commented Mar 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Add plan_resume MCP tool that resumes a failed plan without discarding completed intermediary files — plan generation restarts from the first incomplete step, skipping all steps that already produced output files
  • Add PIPELINE_VERSION integer constant stamped into plan parameters on create, retry, and resume — on resume, the MCP layer rejects with PIPELINE_VERSION_MISMATCH if the stored version differs from the current version
  • Write 001-3-planexe_metadata.json (containing pipeline_version) to the output dir at start, persisting it in the zip snapshot
  • Worker-side defense-in-depth: after restoring the zip snapshot, verify pipeline_version from the metadata file before proceeding — sets plan back to failed with a descriptive progress_message on mismatch
  • Replace internal terminology ("run", "task", "mid-pipeline") with user-facing language ("plan generation", "step", "before completing all steps", "intermediary files") across tool descriptions, server instructions, and docs
  • Add naming migration notes to worker_plan_database/app.py header: new code should use plan_id (not task_id) and plan (not run)
  • Rename restore_run_dir_from_zip_snapshot to restore_output_dir_from_zip_snapshot
  • Document the plan_resume tool, compatibility caveat, and version check in the MCP interface spec (sections 6.6, 9.3, 9.4)
  • Add end-to-end test plan proposal (docs/proposals/112-end-to-end-test-plan.md) with 9 scenarios covering plan_resume, pipeline version mismatch, and full happy path — split into no-LLM and LLM-required groups
  • Fix llama_index import compatibility (core.llms.typescore.base.llms.types fallback)
  • Fix token metrics session corruption: remove nested app.app_context() from _handle_task_completion — nested contexts tear down the scoped session, corrupting the connection for subsequent db operations like token metrics recording
  • Add missing column migrations (thinking_tokens, duration_seconds, success, error_message, raw_usage_data) to ensure_token_metrics_columns so tables created by older model versions get the columns the ORM expects

Test plan

  • pytest mcp_cloud/tests/test_plan_resume_tool.py — covers structured content, SSE URL, PLAN_NOT_FOUND, PLAN_NOT_RESUMABLE, PIPELINE_VERSION_MISMATCH, and default model_profile (requires Docker/CI)
  • pytest mcp_cloud/tests/test_tool_surface_consistency.py — verifies plan_resume is listed in tool definitions
  • pytest mcp_local/ — proxy tests
  • pytest worker_plan/worker_plan_api/tests/ — unit tests for shared utilities (passes locally)
  • Run a plan end-to-end and verify 001-3-planexe_metadata.json appears in the output zip
  • Verify token metrics are recorded without psycopg2 errors during plan generation

🤖 Generated with Claude Code

neoneyeand others added 22 commits March 9, 2026 03:32
… progress
Unlike plan_retry which clears all artifacts and restarts from scratch,
plan_resume preserves completed pipeline outputs and restores the run
directory from the stored zip snapshot. Luigi then skips completed tasks
and picks up where the pipeline left off.
This is the #1 blocker for autonomous agent workflows (Proposal 87) and
a prerequisite for the autonomous prompt optimization loop (Proposals
94/59), which needs fast re-runs that skip completed tasks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ing options
Resuming a plan after pipeline changes (renamed filenames, new tasks, changed
schemas) can produce errors or inconsistent output. Added guidance on when
resume is safe vs when plan_retry is preferred, plus a comparison of future
mitigation approaches (version integer, content hash, manifest JSON).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ive re-run
The MCP tool restricts resume to failed plans, but the underlying Luigi
mechanism is more general — deleting output files triggers re-execution
of those tasks and their downstream dependents. Documented that this
capability is available locally via run_plan_pipeline.py.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…shots
Store a PIPELINE_VERSION integer constant (initially 1) that gets stamped
into plan parameters on create, retry, and resume. On resume, reject with
PIPELINE_VERSION_MISMATCH if the stored version differs from the current
version, directing callers to use plan_retry instead. Legacy plans with
no stored version are treated as incompatible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* main:
fix: correct PLANEXE_OUTPUTS_DIR docs - accurate incident description
fix: address PR #230 review - add docs, remove gitignore change
fix: decouple planexe-outputs from git repo
docs: explain why ThinkingAwareOpenAILike exists vs LMStudio class
docs: Add thinking tokens section to LM Studio provider guide
Add ThinkingAwareOpenAILike class for LM Studio thinking token handling
docs(proposal-103): extend with llama_index silent truncation findings from local model runs
Add PLANEXE_METADATA (001-3-planexe_metadata.json) to FilenameEnum and
write it in ExecutePipeline.run() before luigi.build() starts. This
persists the pipeline version in the zip snapshot for future inspection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After restoring the zip snapshot in the worker, read pipeline_version
from 001-3-planexe_metadata.json and reject the resume if it differs
from the current PIPELINE_VERSION. Sets the plan back to failed so the
caller can use plan_retry instead. Handles missing/corrupt metadata
files by defaulting to None (incompatible).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…plan_resume descriptions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…acing text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nstructions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…facing descriptions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… server instructions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…date log messages
Replace 'task' with 'plan', 'run directory' with 'output directory' in
the resume block of worker_plan_database/app.py.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the in-progress migration from task_id to plan_id and from
run to plan for new code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ip_snapshot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…line_version.py
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Catalogs 9 test scenarios covering plan_resume, pipeline version
mismatch, retry vs resume, and full happy path. Split into no-LLM
(deterministic, cheap) and LLM-required (slow, costly) groups.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Handle both old (llama_index.core.llms.types) and new
(llama_index.core.base.llms.types) module locations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove nested app.app_context() blocks from _handle_task_completion —
the callback already runs inside the outer context opened by
execute_pipeline_for_job(). Nested contexts cause Flask-SQLAlchemy to
tear down the scoped session on exit, corrupting the connection and
triggering psycopg2 DatabaseError / ResourceClosedError in subsequent
db operations like token metrics recording.
Also add missing column migrations (thinking_tokens, duration_seconds,
success, error_message, raw_usage_data) to ensure_token_metrics_columns
so tables created by older model versions get the columns the ORM now
expects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@neoneye
neoneye merged commit 72f0e9b into mainMar 10, 2026
3 checks passed
@neoneye
neoneye deleted the feature/plan-resume-tool branch March 10, 2026 00:48
neoneye added a commit that referenced this pull request Mar 10, 2026
The plan_resume MCP tool (PR #217) supports resuming failed plans
without discarding completed intermediary files. This adds a Resume
button next to Retry in the multi-user frontend so users can access
this functionality from the UI.
- Add /plan/resume POST endpoint with pipeline version check
- Use formaction to share a single form with model_profile dropdown
- Resume is enabled only in failed state; Retry also works in stop_requested
- Tooltips explain the difference between the two actions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@neoneyeneoneye mentioned this pull request Mar 10, 2026
7 tasks
neoneye added a commit that referenced this pull request Mar 10, 2026
The plan_resume MCP tool (PR #217) supports resuming failed plans
without discarding completed intermediary files. This adds a Resume
button next to Retry in the multi-user frontend so users can access
this functionality from the UI.
Frontend endpoint (/plan/resume):
- Validates owner/admin auth, rejects non-failed state
- Checks pipeline_version compatibility; redirects with error banner
on mismatch instead of showing raw JSON
- Preserves all artifacts (key difference from retry)
- Sets resume=True, increments resume_count, archives billing entries
- Adds EventItem audit trail
Template (plan_iframe.html):
- Shared form with formaction for Retry and Resume buttons
- Resume only enabled in failed state (not stop_requested)
- Tooltips explain the difference between the two actions
- Inline error banner when resume is rejected due to version mismatch
Worker fix (worker_plan_database/app.py):
- Truncate progress_message to fit varchar(128) column, fixing a
StringDataRightTruncation crash on pipeline version mismatch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
neoneye added a commit that referenced this pull request Mar 10, 2026
The plan_resume MCP tool (PR #217) supports resuming failed plans
without discarding completed intermediary files. This adds a Resume
button next to Retry in the multi-user frontend so users can access
this functionality from the UI.
Frontend endpoint (/plan/resume):
- Validates owner/admin auth, rejects non-failed state
- Checks pipeline_version compatibility; redirects with error banner
on mismatch instead of showing raw JSON
- Preserves all artifacts (key difference from retry)
- Sets resume=True, increments resume_count, archives billing entries
- Does NOT stamp pipeline_version — leaves that to the worker after
successful artifact validation
- Adds EventItem audit trail
Template (plan_iframe.html):
- Shared form with formaction for Retry and Resume buttons
- Resume only enabled in failed state (not stop_requested)
- Tooltips explain the difference between the two actions
- Inline error banner when resume is rejected due to version mismatch
Worker fix (worker_plan_database/app.py):
- Truncate progress_message to fit varchar(128) column, fixing a
StringDataRightTruncation crash on pipeline version mismatch
- Clear pipeline_version from parameters on mismatch rejection so
subsequent frontend resume attempts are correctly blocked
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
neoneye added a commit that referenced this pull request Mar 10, 2026
The plan_resume MCP tool (PR #217) supports resuming failed plans
without discarding completed intermediary files. This adds a Resume
button next to Retry in the multi-user frontend so users can access
this functionality from the UI.
Frontend endpoint (/plan/resume):
- Validates owner/admin auth, rejects non-failed state
- Checks pipeline_version compatibility; redirects with error banner
on mismatch instead of showing raw JSON
- Preserves all artifacts (key difference from retry)
- Sets resume=True, increments resume_count, archives billing entries
- Does NOT stamp pipeline_version — leaves that to the worker after
successful artifact validation
- Adds EventItem audit trail
Template (plan_iframe.html):
- Shared form with formaction for Retry and Resume buttons
- Resume only enabled in failed state (not stop_requested)
- Tooltips explain the difference between the two actions
- Inline error banner when resume is rejected due to version mismatch
Worker fix (worker_plan_database/app.py):
- Truncate progress_message to fit varchar(128) column, fixing a
StringDataRightTruncation crash on pipeline version mismatch
- Clear pipeline_version from parameters on mismatch rejection so
subsequent frontend resume attempts are correctly blocked
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
neoneye added a commit that referenced this pull request Mar 10, 2026
The plan_resume MCP tool (PR #217) supports resuming failed plans
without discarding completed intermediary files. This adds a Resume
button next to Retry in the multi-user frontend so users can access
this functionality from the UI.
Frontend endpoint (/plan/resume):
- Validates owner/admin auth, rejects non-failed state
- Checks pipeline_version compatibility; redirects with error banner
on mismatch instead of showing raw JSON
- Preserves all artifacts (key difference from retry)
- Sets resume=True, increments resume_count, archives billing entries
- Does NOT stamp pipeline_version — leaves that to the worker after
successful artifact validation
- Adds EventItem audit trail
Template (plan_iframe.html):
- Shared form with formaction for Retry and Resume buttons
- Resume only enabled in failed state (not stop_requested)
- Tooltips explain the difference between the two actions
- Inline error banner when resume is rejected due to version mismatch
Worker fix (worker_plan_database/app.py):
- Truncate progress_message to fit varchar(128) column, fixing a
StringDataRightTruncation crash on pipeline version mismatch
- Clear pipeline_version from parameters on mismatch rejection so
subsequent frontend resume attempts are correctly blocked
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for freeto 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

@neoneye