Feature: Plan CLI coverage boost As a developer I want to exercise uncovered branches in plan.py So that code coverage is improved for the plan CLI module # ---- _plan_spec_dict helper ---- Scenario: _plan_spec_dict returns error_message when truthy Given a v3 Plan with error_message set to "Strategy failed" When I call _plan_spec_dict on the plan Then the spec dict should contain key "error_message" with value "Strategy failed" Scenario: _plan_spec_dict falls back to legacy format for non-Plan objects Given a non-Plan object with string value "legacy plan data" When I call _plan_spec_dict on the object Then the spec dict should equal {"plan": "legacy plan data"} Scenario: _plan_spec_dict omits error_message when it is None Given a v3 Plan with error_message set to None When I call _plan_spec_dict on the plan Then the spec dict should not contain key "error_message" Scenario: _plan_spec_dict includes estimation_result when set Given a v3 Plan with estimation_result set When I call _plan_spec_dict on the plan Then the spec dict should contain key "estimation" Scenario: _plan_spec_dict includes invariants when populated Given a v3 Plan with invariants populated When I call _plan_spec_dict on the plan Then the spec dict should contain key "invariants" Scenario: _plan_spec_dict includes execution_environment when set Given a v3 Plan with execution_environment set When I call _plan_spec_dict on the plan Then the spec dict should contain key "execution_environment" And the spec dict should contain key "execution_env_priority" Scenario: _plan_spec_dict includes dod_evaluation when validation_summary set Given a v3 Plan with validation_summary populated When I call _plan_spec_dict on the plan Then the spec dict should contain key "dod_evaluation" Scenario: _plan_spec_dict includes last_completed_step and last_checkpoint_id Given a v3 Plan with last_completed_step and last_checkpoint_id When I call _plan_spec_dict on the plan Then the spec dict should contain key "last_completed_step" And the spec dict should contain key "last_checkpoint_id" # ---- _print_lifecycle_plan helper ---- Scenario: _print_lifecycle_plan prints all optional timestamps Given a v3 Plan with all timestamps populated When I call _print_lifecycle_plan on the plan Then the printed output should contain "Strategize Started" And the printed output should contain "Strategize Completed" And the printed output should contain "Execute Started" And the printed output should contain "Execute Completed" And the printed output should contain "Applied At" Scenario: _print_lifecycle_plan prints estimation_actor when set Given a v3 Plan with estimation_actor set to "local/cost-estimator" When I call _print_lifecycle_plan on the plan Then the printed output should contain "Estimation Actor" And the printed output should contain "local/cost-estimator" Scenario: _print_lifecycle_plan prints invariant_actor when set Given a v3 Plan with invariant_actor set to "local/invariant-checker" When I call _print_lifecycle_plan on the plan Then the printed output should contain "Invariant Actor" And the printed output should contain "local/invariant-checker" Scenario: _print_lifecycle_plan falls back for non-Plan objects Given a non-Plan object with string value "legacy-plan-object" When I call _print_lifecycle_plan on the object Then the printed output should contain "legacy-plan-object" # ---- execute_plan non-rich format ---- Scenario: execute_plan outputs JSON when format is json Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has a complete strategize plan for execute When I invoke execute with "--format" "json" and plan id Then the plan coverage command should succeed And the plan coverage output should contain "plan_id" And the plan coverage output should contain "sandbox" And the plan coverage output should contain "worker" And the plan coverage output should contain "progress" And the plan coverage output should contain "strategy_summary" And the plan coverage output should contain "command" And the plan coverage output should contain "exit_code" @tdd_issue @tdd_issue_4251 @tdd_expected_fail Scenario: execute_plan JSON output has spec-required envelope structure Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has a complete strategize plan for execute When I invoke execute with "--format" "json" and plan id Then the plan coverage command should succeed And the execute JSON output has the spec-required envelope fields And the execute JSON output data has sandbox with strategy field And the execute JSON output data has progress list with label and status # ---- apply_plan non-rich format ---- Scenario: apply_plan outputs JSON when format is json Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has a complete execute plan for apply When I invoke apply with "--format" "json" and plan id Then the plan coverage command should succeed And the plan coverage output should contain "plan_id" # ---- list_plans regex and state/processing_state filtering ---- Scenario: list_plans filters by regex pattern Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has multiple plans for lifecycle list When I invoke list with regex "alpha" Then the plan coverage command should succeed And the plan coverage output should contain "alpha" And the plan coverage output should not contain "beta" Scenario: list_plans filters by state Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has plans in different processing states When I invoke list with "--state" "processing" Then the plan coverage command should succeed Scenario: list_plans filters by processing_state alias Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has plans in different processing states When I invoke list with "--processing-state" "complete" Then the plan coverage command should succeed Scenario: list_plans rejects invalid regex Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has multiple plans for lifecycle list When I invoke list with regex "[invalid" Then the plan coverage command should abort And the plan coverage output should contain "Invalid regex" Scenario: list_plans filters by action name Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has multiple plans for lifecycle list When I invoke list with "--action" "local/test-action" Then the plan coverage command should succeed Scenario: list_plans outputs JSON when format is json Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service has multiple plans for lifecycle list When I invoke list with "--format" "json" Then the plan coverage command should succeed And the plan coverage output should contain "plan_id" # ---- cancel_plan ---- Scenario: cancel_plan in non-rich format without reason Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service can cancel a plan When I invoke cancel with "--format" "json" and no reason Then the plan coverage command should succeed And the plan coverage output should contain "plan_id" And the plan coverage output should not contain "cancel_reason" Scenario: cancel_plan in non-rich format with reason Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service can cancel a plan When I invoke cancel with "--format" "json" and reason "not needed" Then the plan coverage command should succeed And the plan coverage output should contain "cancel_reason" And the plan coverage output should contain "not needed" Scenario: cancel_plan in rich format with reason Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service can cancel a plan When I invoke cancel in rich format with reason "obsolete" Then the plan coverage command should succeed And the plan coverage output should contain "Plan cancelled" And the plan coverage output should contain "Reason: obsolete" Scenario: cancel_plan in rich format without reason Given a plan lifecycle CLI runner for coverage And a mocked lifecycle service for plan coverage commands And the service can cancel a plan When I invoke cancel in rich format without reason Then the plan coverage command should succeed And the plan coverage output should contain "Plan cancelled"