Aligned the plan lifecycle model with the specification:
1. ERRORED is now treated as terminal in is_terminal property,
matching the spec table where errored is marked "Terminal? Yes"
for all processing phases.
2. Added per-phase state validation via model_validator: APPLIED
and CONSTRAINED are only valid in APPLY phase; COMPLETE is only
valid in STRATEGIZE or EXECUTE phases. Invalid combinations
now raise ValueError at construction time.
3. Updated ProcessingState.COMPLETE docstring to clarify phase-level
terminality semantics.
4. Fixed assignment ordering in execute_plan() to set
processing_state before phase, consistent with the state-first
pattern used in apply_plan() and _perform_reversion().
5. Added defensive coercion in LifecyclePlanModel.to_domain() to
handle legacy DB rows with invalid phase/state combinations
(e.g. APPLY/COMPLETE -> APPLY/APPLIED) with warning-level
logging for observability.
6. Updated module docstrings: ERRORED description now reflects
terminal semantics, terminal outcomes location clarified for
all phases, can_revert_to docstring notes ERRORED/CONSTRAINED
are terminal but revertable, is_terminal docstring explains
the distinction between terminal and permanently irrecoverable
and documents why COMPLETE is not plan-terminal despite the
spec marking it "Terminal? Yes" (phase-level vs plan-level).
7. Updated PlanResumeService.validate_eligibility() docstring to
reflect that ERRORED is now terminal but still eligible for
resume.
8. Added CHANGELOG entry.
ISSUES CLOSED: #918
Address review-driven fixes across actor schema, preflight guardrails, docs/examples,
and Behave/Robot coverage: unify preflight warning behavior with shared role-warning logic,
resolve actor-name to config payloads in production preflight flow, harden response_format
validation/coercion edge cases, extract duplicated helper logic, and expand negative-path
test coverage. Also fix cross-scenario patcher leakage in step modules to eliminate
full-run-only coverage failures.
Fixed 5 bugs preventing the M1 E2E acceptance test from passing:
1. _get_lifecycle_service() in action.py and plan.py bypassed the DI
container, creating PlanLifecycleService without UnitOfWork. All
plan/action data was in-memory only and lost between subprocess
calls. Now uses container.plan_lifecycle_service() for DB persistence.
2. `plan execute` CLI only called service.execute_plan() (a pure state
transition) without running PlanExecutor phase processing. Rewrote
to detect the plan's current phase/state and dispatch synchronously:
Strategize/queued → run_strategize(), Strategize/complete → transition
+ run_execute(), Execute/queued → run_execute().
3. `plan apply` CLI had no plan_id argument. Added optional positional
plan_id with _lifecycle_apply_with_id() that drives the plan through
Apply/queued → Apply/processing → Apply/applied.
4. Preflight guardrail in start_strategize() built action_registry from
the in-memory _actions dict only. Added get_action(plan.action_name)
call to load the action from DB into cache before the guardrail check.
5. Robot Framework Create File syntax used continuation lines producing
9 arguments instead of 1. Fixed to use Catenate SEPARATOR=\n then
pass single variable to Create File. Also fixed --branch main to
--branch master (git init default).
update mocks for execute_plan CLI changes across unit and integration tests
The new execute_plan() command calls _get_plan_executor() and
service.get_plan(plan_id) for phase/state detection. Existing tests
only mocked _get_lifecycle_service, so MagicMock defaults caused
phase/state comparisons to fail.
Changes across 14 files:
- Patch _get_plan_executor in all test setups that invoke the CLI
execute command (Behave step files + Robot helper scripts)
- Set service.get_plan.return_value to real Plan objects with correct
phase/state so the execute_plan dispatch logic works
- Fix error-path tests to use STRATEGIZE/COMPLETE plans so the error
side_effects are actually reached
- Fix "Multiple plans eligible" → "Multiple plans ready" message text
to match existing test expectations
increase Robot Framework subprocess timeouts for CI resource contention
Three integration tests were timing out in CI due to resource contention
when pabot runs multiple test suites in parallel. All three pass locally
and the timeouts were simply too tight for constrained CI environments.
- tdd_session_create_di.robot: 30s → 90s (DI container init + DB setup)
- database_integration.robot: 60s → 120s (Run Python Script keyword)
- m3_e2e_verification.robot: 60s → 120s (correction-live-revert spawns
3 sequential CLI subprocesses with full container initialization)
ISSUES CLOSED: #789