Feature: Decision type phase-gating at recording time
  As a developer
  I want the DecisionService to enforce phase-gating on decision types
  So that decisions recorded during Strategize or Execute are constrained
  to the types permitted in each phase

  Background:
    Given a phase-gated decision service

  # --- Valid types in Strategize phase ---

  Scenario Outline: Valid decision types succeed in Strategize phase
    When I record a "<decision_type>" decision in the "strategize" phase
    Then the phase-gated decision should be recorded successfully
    And the phase-gated decision type should be "<decision_type>"

    Examples:
      | decision_type          |
      | prompt_definition      |
      | invariant_enforced     |
      | strategy_choice        |
      | resource_selection     |
      | subplan_spawn          |
      | subplan_parallel_spawn |
      | user_intervention      |

  # --- Valid types in Execute phase ---

  Scenario Outline: Valid decision types succeed in Execute phase
    When I record a "<decision_type>" decision in the "execute" phase
    Then the phase-gated decision should be recorded successfully
    And the phase-gated decision type should be "<decision_type>"

    Examples:
      | decision_type          |
      | implementation_choice  |
      | resource_selection     |
      | tool_invocation        |
      | error_recovery         |
      | validation_response    |
      | subplan_spawn          |
      | subplan_parallel_spawn |
      | user_intervention      |

  # --- Invalid types in Strategize phase ---

  Scenario Outline: Execute-only types are rejected in Strategize phase
    When I try to record a "<decision_type>" decision in the "strategize" phase
    Then a phase violation error should be raised
    And the phase violation error decision_type should be "<decision_type>"
    And the phase violation error plan_phase should be "strategize"
    And the phase violation error allowed_types should not contain "<decision_type>"

    Examples:
      | decision_type         |
      | implementation_choice |
      | tool_invocation       |
      | error_recovery        |
      | validation_response   |

  # --- Invalid types in Execute phase ---

  Scenario Outline: Strategize-only types are rejected in Execute phase
    When I try to record a "<decision_type>" decision in the "execute" phase
    Then a phase violation error should be raised
    And the phase violation error decision_type should be "<decision_type>"
    And the phase violation error plan_phase should be "execute"
    And the phase violation error allowed_types should not contain "<decision_type>"

    Examples:
      | decision_type      |
      | prompt_definition  |
      | invariant_enforced |
      | strategy_choice    |

  # --- Phase-agnostic types work in both phases ---

  Scenario Outline: Phase-agnostic types succeed in both phases
    When I record a "<decision_type>" decision in the "strategize" phase
    Then the phase-gated decision should be recorded successfully
    When I record a "<decision_type>" decision in the "execute" phase
    Then the phase-gated decision should be recorded successfully

    Examples:
      | decision_type          |
      | resource_selection     |
      | subplan_spawn          |
      | subplan_parallel_spawn |
      | user_intervention      |

  # --- Error message quality ---

  Scenario: Phase violation error message includes type, phase, and allowed types
    When I try to record a "tool_invocation" decision in the "strategize" phase
    Then a phase violation error should be raised
    And the phase violation error message should contain "tool_invocation"
    And the phase violation error message should contain "strategize"
    And the phase violation error message should contain "Allowed types"

  # --- Phase-gating via database lookup ---

  Scenario: Phase resolved from database when plan_phase not explicitly provided
    Given a phase-gated decision service with a persisted strategize plan
    When I record a "strategy_choice" decision without explicit phase
    Then the phase-gated decision should be recorded successfully
    When I try to record a "tool_invocation" decision without explicit phase
    Then a phase violation error should be raised

  Scenario: Phase resolved from database for execute plan
    Given a phase-gated decision service with a persisted execute plan
    When I record a "tool_invocation" decision without explicit phase
    Then the phase-gated decision should be recorded successfully
    When I try to record a "strategy_choice" decision without explicit phase
    Then a phase violation error should be raised

  Scenario: Phase-gating skipped when plan not found in database
    Given a phase-gated decision service with an empty database
    When I record a "tool_invocation" decision without explicit phase
    Then the phase-gated decision should be recorded successfully

  # --- No phase-gating when phase is unknown ---

  Scenario: Phase-gating is skipped when phase cannot be resolved
    Given a phase-gated decision service without persistence
    When I record a "tool_invocation" decision without explicit phase
    Then the phase-gated decision should be recorded successfully

  # --- PHASE_ALLOWED_TYPES constant ---

  Scenario: PHASE_ALLOWED_TYPES maps strategize and execute correctly
    Then the PHASE_ALLOWED_TYPES should map "strategize" to STRATEGIZE_TYPES
    And the PHASE_ALLOWED_TYPES should map "execute" to EXECUTE_TYPES

  # --- DecisionPhaseViolationError attributes ---

  Scenario: DecisionPhaseViolationError exposes correct attributes
    Given a DecisionPhaseViolationError for type "tool_invocation" in phase "strategize"
    Then the phase violation error decision_type should be "tool_invocation"
    And the phase violation error plan_phase should be "strategize"
    And the phase violation error allowed_types should not be empty

  # --- _validate_phase_gating static method ---

  Scenario: _validate_phase_gating does not raise for ungated phases
    When I call _validate_phase_gating with type "tool_invocation" and phase "action"
    Then no phase violation error should be raised
    When I call _validate_phase_gating with type "tool_invocation" and phase "apply"
    Then no phase violation error should be raised

  # --- String coercion of plan_phase ---

  Scenario: plan_phase accepts a string value
    When I record a "strategy_choice" decision with string phase "strategize"
    Then the phase-gated decision should be recorded successfully

  Scenario: plan_phase accepts a PlanPhase enum directly
    When I record a "strategy_choice" decision with PlanPhase enum "strategize"
    Then the phase-gated decision should be recorded successfully

  # --- Invalid plan_phase string ---

  Scenario: Invalid plan_phase string raises ValidationError
    When I try to record a "strategy_choice" decision with invalid phase "not_a_real_phase"
    Then a validation error should be raised for invalid phase
    And the validation error message should contain "not_a_real_phase"

  # --- Database error resilience ---

  Scenario: resolve_plan_phase gracefully handles database errors
    Given a corrupted database unit of work for phase resolution
    When I call resolve_plan_phase with the corrupted unit of work
    Then resolve_plan_phase should return None
