Problem
For ASPIR projects, status.yaml shows plan_phases: [] even when the plan file's machine-readable JSON block is well-formed, with multiple phases defined. This breaks the phase state machine: porch never transitions implement → review on completion because the "all phases complete" predicate cannot fire when the list is empty, and the default on_complete: "implement" action sends it back to itself. The builder observes an endless stream of alternating phase-transition and build-complete porch commits with no advancement.
Observed behavior
Seen on at least two ASPIR projects:
- 694 (team-page-surface-review-block): plan's JSON block had 4 phases. After each
porch done, porch re-entered implement phase, iteration 1, and returned the same initial implement tasks. Workaround: bypass porch and create the PR directly after the 3-way implementation consultation approved unanimously.
- 494 (new-air-protocol-autonomous-im): stuck in
specify with empty plan_phases.
Here's the relevant excerpt from 694's status.yaml after the plan phase supposedly completed:
id: '694'
title: team-page-surface-review-block
protocol: aspir
phase: implement
plan_phases: [] # <-- never populated
current_plan_phase: null
And the plan's JSON block (well-formed):
{
\"phases\": [
{\"id\": \"phase_1_wire_type\", \"title\": \"Extend wire type with reviewBlocking array\"},
{\"id\": \"phase_2_query_and_parser\", \"title\": \"Extend GraphQL query and add two-pass relationship derivation\"},
{\"id\": \"phase_3_dashboard_ui\", \"title\": \"Render review-blocking section in MemberCard\"},
{\"id\": \"phase_4_e2e_and_docs\", \"title\": \"Add E2E coverage and update docs\"}
]
}
Expected behavior
After the plan phase completes (plan file written and committed), porch should parse the JSON block from the plan file and populate status.yaml.plan_phases with the list so that:
current_plan_phase can advance through each phase in order during implement
- The
on_all_phases_complete predicate fires and transitions to review
Reproduction steps
afx spawn <id> --protocol aspir on a project with a multi-phase plan
- Let porch run through specify → plan
- After plan is approved, observe
status.yaml shows plan_phases: []
porch done <id> during implement never advances to review — loops back to implement iteration 1
Suspected root cause
The plan→implement transition handler is not extracting/populating plan_phases from the plan file. The JSON block parses cleanly with python3 -c \"import json; json.load(open(...))\", so the extractor either:
- Is not being called at the expected time, OR
- Is being called but its results are not being written to
status.yaml, OR
- Is looking at the wrong file path (ASPIR vs SPIR path resolution)
Impact
- Breaks autonomous ASPIR workflow — builders must manually work around by creating PRs without porch's state machine
- Creates noisy commit history with 15+ porch state commits that never advance state
- Blocks the optional
verify phase from being reached through porch
Follow-up
Identified during work on project 694 (review). See that file's Follow-up Items section for additional context.
Problem
For ASPIR projects,
status.yamlshowsplan_phases: []even when the plan file's machine-readable JSON block is well-formed, with multiple phases defined. This breaks the phase state machine: porch never transitionsimplement → reviewon completion because the "all phases complete" predicate cannot fire when the list is empty, and the defaulton_complete: "implement"action sends it back to itself. The builder observes an endless stream of alternatingphase-transitionandbuild-completeporch commits with no advancement.Observed behavior
Seen on at least two ASPIR projects:
porch done, porch re-enteredimplementphase, iteration 1, and returned the same initial implement tasks. Workaround: bypass porch and create the PR directly after the 3-way implementation consultation approved unanimously.specifywith emptyplan_phases.Here's the relevant excerpt from 694's
status.yamlafter the plan phase supposedly completed:And the plan's JSON block (well-formed):
{ \"phases\": [ {\"id\": \"phase_1_wire_type\", \"title\": \"Extend wire type with reviewBlocking array\"}, {\"id\": \"phase_2_query_and_parser\", \"title\": \"Extend GraphQL query and add two-pass relationship derivation\"}, {\"id\": \"phase_3_dashboard_ui\", \"title\": \"Render review-blocking section in MemberCard\"}, {\"id\": \"phase_4_e2e_and_docs\", \"title\": \"Add E2E coverage and update docs\"} ] }Expected behavior
After the
planphase completes (plan file written and committed), porch should parse the JSON block from the plan file and populatestatus.yaml.plan_phaseswith the list so that:current_plan_phasecan advance through each phase in order during implementon_all_phases_completepredicate fires and transitions toreviewReproduction steps
afx spawn <id> --protocol aspiron a project with a multi-phase planstatus.yamlshowsplan_phases: []porch done <id>during implement never advances to review — loops back to implement iteration 1Suspected root cause
The plan→implement transition handler is not extracting/populating
plan_phasesfrom the plan file. The JSON block parses cleanly withpython3 -c \"import json; json.load(open(...))\", so the extractor either:status.yaml, ORImpact
verifyphase from being reached through porchFollow-up
Identified during work on project 694 (review). See that file's Follow-up Items section for additional context.