Troubleshoot spec engine
Before you start
The spec engine coordinates plan parsing, task execution, quality gates, and state persistence. Failures usually fall into one of three areas: a plan file that can't be read or parsed, a SpecState that is missing or corrupt, or a TaskResult that signals a quality-gate failure. Identify which area is affected before diving into code.
Symptom table
| If you observe | Check |
|---|---|
FileNotFoundError: Plan file not found |
Verify the path passed to read_spec(plan_path) or PipelineOrchestrator(spec_path) exists and is non-empty. |
ValueError: plan_path must be a non-empty string |
You passed an empty string or None as spec_path/plan_path. Confirm the calling code resolves the path before passing it. |
PipelineResult.success is False |
Iterate PipelineResult.tasks and check each TaskResult.error, TaskResult.quality_gate_passed, and TaskResult.tests_passed to find which task failed and why. |
| A task never appears in the output | Call read_spec(plan_path) directly and inspect the returned list. If the task is missing, the XML task block in the plan file is malformed or absent. |
| Execution resumes from the wrong task | Call load_state(plan_path) and inspect SpecState.completed and SpecState.current. If stale, call clear_state(plan_path) to reset. |
get_pending_tasks returns an empty list unexpectedly |
SpecState.completed already contains all task IDs. Either the state is stale or the plan was previously finished. Call clear_state(plan_path) to start fresh. |
| Quality gate always passes when it shouldn't | Check whether skip_gates=True was passed to PipelineOrchestrator or execute_with_approval. Remove that flag to re-enable gates. |
TaskResult.severity returns an unexpected level |
Inspect TaskResult.gate_score and TaskResult.gate_details to see the raw values driving the classification. |
| No resumable plans found | Call find_resumable_plans() (default search path: .claude/plans). If it returns an empty list, no .state.json files exist in that directory. |
Step-by-step diagnosis
Follow these steps in order — earlier steps are cheaper and resolve most issues without deeper investigation.
-
Reproduce the failure with a minimal call. Strip the invocation to its required arguments and confirm the failure is repeatable:
from pipeline import read_spec tasks = read_spec("path/to/your-plan.md") print(tasks)If
read_specraises, the problem is in the plan file or the path. If it returns an unexpected list, the XML task blocks in the file need inspection. -
Inspect the state file. Before running the pipeline, check what state is persisted:
from spec import load_state state = load_state("path/to/your-plan.md") print(state) # None means no state exists if state: print(state.to_dict())Look at
state.completed,state.current, andstate.schema_version. A mismatchedschema_versionor acompletedlist that includes tasks you expect to re-run indicates stale state. -
Clear stale state and retry. If step 2 reveals stale or corrupt state, reset it:
from spec import clear_state clear_state("path/to/your-plan.md")Then re-run the pipeline. This is the fix for most "wrong task order" and "pending tasks list is empty" issues.
-
Run the pipeline with gates disabled to isolate gate failures. If tasks execute but quality gates block progress unexpectedly, run with
skip_gates=Trueto confirm the task logic itself works:from pipeline import PipelineOrchestrator orch = PipelineOrchestrator("path/to/your-plan.md", skip_gates=True) result = orch.run_all() print(result.summary())If
result.successisTruewith gates skipped butFalsewith gates enabled, the gate thresholds or thegate_scorevalues on failing tasks are the root cause. Re-enable gates and inspectTaskResult.gate_detailsfor each failing task. -
Examine per-task results. Iterate the
PipelineResult.taskslist and print eachTaskResultto pinpoint which task failed:for task_result in result.tasks: if not task_result.quality_gate_passed or task_result.error: print(task_result.task_id, task_result.task_name) print("error:", task_result.error) print("score:", task_result.gate_score) print("details:", task_result.gate_details) print("tests_passed:", task_result.tests_passed) -
Run related tests. Confirm which test cases pass against your current code:
pytest -k "spec" -vA failing test that exercises the broken path gives you a reproducible harness and can confirm when your fix is correct.
Common fixes
-
Missing or mistyped plan path.
read_specraisesFileNotFoundErrororValueErrorwhenplan_pathis wrong. Always resolve the path before passing it:import os plan_path = os.path.abspath("path/to/your-plan.md") tasks = read_spec(plan_path) -
Stale
SpecStateblocking re-execution. If a plan was previously completed or interrupted mid-run, the state file records those task IDs inSpecState.completed. Reset with:from spec import clear_state clear_state("path/to/your-plan.md")This removes the embedded state comment from the plan file. The next run starts from the first task.
-
Quality gates skipped unintentionally. If
skip_gates=Truewas passed toPipelineOrchestratororexecute_with_approvalduring development and left in, gate failures will never surface. Remove the flag:# Before (gates disabled): orch = PipelineOrchestrator(spec_path, skip_gates=True) # After (gates enabled): orch = PipelineOrchestrator(spec_path) -
Skipping specific tasks unintentionally. If
run_allwas called with a non-emptyskip_task_idsset, those tasks are silently omitted from the run. Confirm the set is correct or passNoneto run all tasks:result = orch.run_all(skip_task_ids=None) -
XML task blocks missing from the plan file.
read_specreturns an empty list if the plan file contains no parseable XML task blocks. Open the plan file and confirm the task blocks are present and well-formed. The plan file lives at the path under.claude/plans/recorded inSpecState.plan_path. -
Dependency version drift. If behavior changed without a code edit, confirm your environment matches expectations:
pip show attuneNote that this check requires access to your local environment and is outside the spec engine itself.
Source files
src/attune/spec/**src/attune/pipeline/**
Tags: spec, planning