How to Diagnose Workflow Terminal-State Failures¶
Use this guide when default-workflow or smart-orchestrator exits nonzero
with FAILED_MISSING_TERMINAL_EVIDENCE, FAILED_INVALID_EVIDENCE, or another
terminal-state error.
Before you start¶
- Run from a Git checkout for development workflows.
- Use the same
repo_path,branch_name,pr_number, andpr_urlvalues that the failing workflow used. - Preserve Node memory settings when checks include Node tooling:
Read the Failure¶
Run with JSON output so the failing step and terminal evidence are visible:
amplihack recipe run smart-orchestrator \
-c task_description="Fix cache invalidation bug" \
-c repo_path=. \
--format json > result.json
If the shell exits nonzero, inspect the terminal-state failure:
jq '(.failure_context // empty),
(.step_results[]? | select((.step_id // "") | test("terminal-state|workflow-finalize|default-workflow")))' result.json
Look for these fields:
| Field | What to check |
|---|---|
terminal_state |
Stable failure state such as FAILED_MISSING_TERMINAL_EVIDENCE. |
terminal_reason |
Human-readable explanation and next action. |
required_next_action |
The action the finalizer expects before the workflow can close. |
hollow_success_detected |
Whether the run appeared successful but lacked real completion evidence. |
evidence_used |
Typed evidence keys used by the deterministic classifier. |
reporting_failure |
Whether a reporting step failed after successful implementation (produces FAILED_REPORTING, durable evidence preserved). |
observed_phases |
Last workflow phases that produced evidence. |
missing_evidence |
Required proof that was absent. |
Fix FAILED_MISSING_TERMINAL_EVIDENCE¶
This means the workflow was classified as a code-change workflow but stopped before it proved completion.
Common causes:
| Observed phases | Meaning | Fix |
|---|---|---|
workflow-prep only |
Requirements or issue setup ran, then execution stopped. | Re-run or resume so worktree, design, implementation, verification, and publish phases execute. |
workflow-prep,workflow-worktree |
Branch/worktree setup completed, but no implementation evidence exists. | Continue into workflow-design and workflow-tdd; do not treat worktree prep as completion. |
workflow-prep,workflow-worktree,workflow-design |
Design exists, but code and verification did not run. | Continue into implementation and verification, or emit an explicit no-op state if no changes are required. |
workflow-tdd without verification |
Implementation ran but checks did not prove success. | Run pre-commit, targeted tests, or the workflow verification phase. |
Example recovery:
amplihack recipe run default-workflow \
-c task_description="Fix cache invalidation bug" \
-c repo_path=. \
-c branch_name=feat/cache-invalidation \
-c existing_branch=feat/cache-invalidation
The rerun must either continue into implementation/verification/publish or end with an explicit terminal no-op/failure state.
Fix FAILED_INVALID_EVIDENCE¶
This means the workflow produced terminal markers, but they were not trustworthy.
Check for:
- unknown
terminal_state - empty
terminal_reason - boolean markers with non-boolean values
terminal_no_op=truewithout a no-op stateimplementation_completed=trueandterminal_failure=truein the same result- PR URL or PR number that does not match the repository
terminal_success=truewithfinalizer_confidence=mediumorlow
Correct the producing recipe step so it emits one coherent state:
terminal_success=true
terminal_state=IMPLEMENTED_VERIFIED
terminal_reason=implementation and verification completed
implementation_completed=true
verification_completed=true
terminal_failure=false
or:
terminal_success=false
terminal_state=BLOCKED_CI
terminal_reason=required status check unit-tests failed
terminal_failure=true
Distinguish Implementation Failure from Reporting Failure¶
Finalization classifies two failure families separately so free-form explanatory output — or a transient failure in a reporting step — can never erase proof that the implementation succeeded.
FAILED_IMPLEMENTATION means durable implementation or verification evidence is
absent or failed while meaningful work remains:
terminal_success=false
terminal_state=FAILED_IMPLEMENTATION
implementation_completed=false
verification_completed=false
required_next_action=Resume default-workflow from implementation and verification.
FAILED_REPORTING means the implementation succeeded but a reporting/finalization
step failed. Durable evidence is preserved:
terminal_success=false
terminal_state=FAILED_REPORTING
reporting_failure=true
implementation_completed=true
verification_completed=true
pr_url=https://github.com/rysweet/amplihack-rs/pull/123
pr_number=123
required_next_action=Re-run the reporting step; the implementation is intact.
Retry the reporting step for FAILED_REPORTING; do not re-run the
implementation. Resume from implementation only for FAILED_IMPLEMENTATION.
The finalizer narrative is never parsed, so its text cannot cause either state. Read it as diagnostics only:
Do not patch CI scripts to ignore these states. They mean finalization could not prove closure.
Fix HOLLOW_SUCCESS¶
HOLLOW_SUCCESS means a workflow path looked complete at the process level but
did not produce meaningful terminal evidence. This often follows setup-only,
design-only, inaccessible-codebase, or empty/generic agent output.
Inspect the evidence:
jq '.. | objects | select(.terminal_state? == "HOLLOW_SUCCESS") | {
terminal_reason,
required_next_action,
observed_phases,
implementation_completed,
verification_completed,
publish_state_reached,
evidence_used
}' result.json
Recovery is one of:
| Missing evidence | Recovery |
|---|---|
| Implementation | Resume default-workflow from implementation on the existing branch/worktree. |
| Verification | Run the selected validation, tests, or pre-commit phase and rerun finalization. |
| Publish or follow-up | Publish the meaningful diff or create a durable follow-up PR/issue. |
| Valid no-op | Emit NO_DIFF_SUCCESS, MERGED, CLOSED_OBSOLETE, SUPERSEDED, or ALLOW_NO_OP with deterministic proof. |
Fix BLOCKED_CI¶
BLOCKED_CI is a terminal failure state, not an incomplete finalizer run. It
means the finalizer found a matching PR or publish target, but required checks
are failing, pending beyond policy, or unavailable when required.
For GitHub PRs:
Then fix or rerun the failing checks. Do not convert BLOCKED_CI into success
unless the CI evidence changes and finalization is rerun.
Fix FAILED_MEANINGFUL_DIFF¶
FAILED_MEANINGFUL_DIFF means local branch changes still exist, but
finalization could not prove that the diff is represented by a valid PR,
follow-up, merge, no-op, or completed implementation-plus-verification path.
Inspect the branch against the intended base:
Recovery is one of:
| Situation | Recovery |
|---|---|
| Diff is intended work | Publish or update the workflow-owned PR, then rerun finalization. |
| Diff should be handled later | Create a durable follow-up PR or issue and return FOLLOWUP_CREATED or SUPERSEDED with its identifier. |
| Diff is already upstream or obsolete | Prove NO_DIFF_SUCCESS or CLOSED_OBSOLETE with local no-diff/obsolete evidence. |
| Diff is accidental | Remove or commit the intended changes before rerunning finalization. |
Use an Explicit No-Op Correctly¶
Use a terminal no-op only when the task is legitimately complete without further code-change work.
Valid examples:
- requested change is already merged
- branch is clean with no meaningful diff against base
- issue is explicitly superseded by another workflow-owned PR
- documentation review, audit, or orchestration task with no requested file edits
was classified with
allow_no_op=true
Example:
amplihack recipe run default-workflow \
-c task_description="Verify the already-merged workflow fix" \
-c repo_path=. \
-c pr_number=579
Expected terminal evidence:
Do not use allow_no_op=true to bypass failed implementation or verification.
The gate still requires a valid no-op state and reason.
Verify Routing Propagation¶
When the failure happens under smart-orchestrator, confirm the routed
default-workflow failure is not masked:
set +e
amplihack recipe run smart-orchestrator \
-c task_description="Add validation for user input" \
-c repo_path=. \
--format json > result.json
status=$?
set -e
echo "$status"
jq '.status, .failure_context.step_id, .failure_context.status' result.json
Expected behavior for missing terminal evidence:
If the command exits 0 while the routed development workflow reports missing
terminal evidence, the routing layer is incorrectly masking failure.
Run the Terminal-State Evaluator Directly¶
The shell helper can be run from a checkout to inspect normalized evidence.
WORKFLOW_CLASSIFICATION=Development \
RECIPE_NAME=default-workflow \
REPO_PATH=. \
BRANCH_NAME="$(git branch --show-current)" \
OBSERVED_PHASES="workflow-prep,workflow-worktree,workflow-design" \
amplifier-bundle/tools/workflow_final_status.sh
Expected result:
terminal_success=false
terminal_state=FAILED_MISSING_TERMINAL_EVIDENCE
missing_evidence=implementation_completed,verification_completed,publish_state_reached,terminal_no_op
Add implementation and verification evidence to confirm a valid success path:
WORKFLOW_CLASSIFICATION=Development \
RECIPE_NAME=default-workflow \
REPO_PATH=. \
BRANCH_NAME="$(git branch --show-current)" \
IMPLEMENTATION_COMPLETED=true \
VERIFICATION_COMPLETED=true \
TERMINAL_STATE=IMPLEMENTED_VERIFIED \
TERMINAL_REASON="implementation and targeted tests completed" \
amplifier-bundle/tools/workflow_final_status.sh
Expected result:
CI Usage¶
In CI, run the same workflow command and let the process exit code gate the job:
export NODE_OPTIONS=--max-old-space-size=32768
amplihack recipe run smart-orchestrator \
-c task_description="$TASK_DESCRIPTION" \
-c repo_path="$GITHUB_WORKSPACE" \
--format json > recipe-result.json
Do not post-process FAILED_MISSING_TERMINAL_EVIDENCE into success. That state
means the code-change task did not reach implementation/verification/publish or
a valid terminal no-op.