Feature: Invariant Enforcement in Strategize Phase
  As a plan strategizer
  I want invariants to be loaded and enforced during the Strategize phase
  So that plan actions that violate constraints are rejected with clear error messages

  Background:
    Given a fresh InvariantService for enforcement
    And a fresh PlanLifecycleService for enforcement

  # === Invariant Loading ===

  @load_invariants
  Scenario: Load all active global invariants
    Given a global invariant "Never delete production data" from source "system"
    And a global invariant "All APIs must maintain backward compatibility" from source "system"
    When I load active invariants for plan "01JQAAAAAAAAAAAAAAAAAAAA01"
    Then 2 invariants should be loaded
    And the loaded set should contain "Never delete production data"
    And the loaded set should contain "All APIs must maintain backward compatibility"

  @load_invariants
  Scenario: Load invariants with project scope
    Given a global invariant "Never delete production data" from source "system"
    And a project invariant "Use ORM for all queries" from source "local/api-service" for project "local/api-service"
    When I load active invariants for plan "01JQAAAAAAAAAAAAAAAAAAAA01" with project "local/api-service"
    Then 2 invariants should be loaded
    And the loaded set should contain "Never delete production data"
    And the loaded set should contain "Use ORM for all queries"

  @load_invariants
  Scenario: Load invariants respecting plan > project > global precedence
    Given a global invariant "Use REST for all APIs" from source "system"
    And a project invariant "Use REST for all APIs" from source "local/api-service" for project "local/api-service"
    And a plan invariant "Use REST for all APIs" from source "01JQAAAAAAAAAAAAAAAAAAAA01"
    When I load active invariants for plan "01JQAAAAAAAAAAAAAAAAAAAA01" with project "local/api-service"
    Then 1 invariant should be loaded
    And the winning invariant for "use rest for all apis" should be from "plan" scope

  @load_invariants
  Scenario: Inactive invariants are not loaded
    Given a global invariant "Never delete production data" from source "system"
    And a global invariant "All APIs must maintain backward compatibility" from source "system"
    When I deactivate the invariant "All APIs must maintain backward compatibility"
    And I load active invariants for plan "01JQAAAAAAAAAAAAAAAAAAAA01"
    Then 1 invariant should be loaded
    And the loaded set should contain "Never delete production data"
    And the loaded set should not contain "All APIs must maintain backward compatibility"

  # === Invariant Checking ===

  @check_invariants
  Scenario: Action that violates "do not delete" invariant is rejected
    Given a global invariant "Never delete production data" from source "system"
    When I check action "Delete all production database records" against loaded invariants
    Then an InvariantViolationError should be raised
    And the error should include invariant ID
    And the error should include the violated text "Never delete production data"
    And the error should include the action text "Delete all production database records"

  @check_invariants
  Scenario: Action that violates "must not" invariant is rejected
    Given a global invariant "Must not use hardcoded credentials" from source "system"
    When I check action "Add hardcoded API key to config file" against loaded invariants
    Then an InvariantViolationError should be raised
    And the error should include the violated text "Must not use hardcoded credentials"

  @check_invariants
  Scenario: Action that complies with invariant is accepted
    Given a global invariant "Never delete production data" from source "system"
    When I check action "Create backup of production database" against loaded invariants
    Then no inv error should be raised
    And the action should be accepted

  @check_invariants
  Scenario: Multiple invariants are all checked
    Given a global invariant "Never delete production data" from source "system"
    And a global invariant "All APIs must maintain backward compatibility" from source "system"
    When I check action "Create backup of production database" against loaded invariants
    Then no inv error should be raised
    And the action should be accepted

  @check_invariants
  Scenario: First violating invariant raises error
    Given a global invariant "Never delete production data" from source "system"
    And a global invariant "Must not use hardcoded credentials" from source "system"
    When I check action "Delete production data with hardcoded key" against loaded invariants
    Then an InvariantViolationError should be raised
    And the error should include one of the violated invariants

  @check_invariants
  Scenario: Empty action text raises ValidationError
    Given a global invariant "Never delete production data" from source "system"
    When I check action "" against loaded invariants
    Then an inv ValidationError should be raised
    And the error message should contain "Action text must not be empty"

  # === Integration with Strategize Phase ===

  @strategize_integration
  Scenario: Strategize phase loads invariants at startup
    Given a plan "01JQAAAAAAAAAAAAAAAAAAAA01" in Strategize phase
    And a global invariant "Never delete production data" from source "system"
    When I start the Strategize phase for the plan
    Then invariants should be loaded
    And 1 invariant should be active for the plan

  @strategize_integration
  Scenario: Strategize phase rejects violating strategy decision
    Given a plan "01JQAAAAAAAAAAAAAAAAAAAA01" in Strategize phase
    And a global invariant "Never delete production data" from source "system"
    When I attempt to create a strategy decision "Delete all production database records"
    Then an InvariantViolationError should be raised
    And the plan should remain in Strategize phase
    And the decision should not be recorded

  @strategize_integration
  Scenario: Strategize phase accepts compliant strategy decision
    Given a plan "01JQAAAAAAAAAAAAAAAAAAAA01" in Strategize phase
    And a global invariant "Never delete production data" from source "system"
    When I create a strategy decision "Create backup of production database"
    Then the decision should be recorded
    And the plan should progress normally

  @strategize_integration
  Scenario: Invariants survive plan restarts
    Given a plan "01JQAAAAAAAAAAAAAAAAAAAA01" in Strategize phase
    And a global invariant "Never delete production data" from source "system"
    When I start the Strategize phase for the plan
    And I restart the plan
    And I start the Strategize phase again
    Then invariants should be loaded fresh from database
    And 1 invariant should be active for the plan

  # === Error Messages ===

  @error_messages
  Scenario: Violation error includes all required information
    Given a global invariant "Never delete production data" from source "system"
    When I check action "Delete all production database records" against loaded invariants
    Then an InvariantViolationError should be raised
    And the error message should include the invariant ID
    And the error message should include the invariant text
    And the error message should include the action text
    And the error should have scope information
    And the error should have source_name information

  @error_messages
  Scenario: Clear error message identifies violated invariant
    Given a global invariant "Never delete production data" from source "system"
    When I check action "Delete all production database records" against loaded invariants
    Then an InvariantViolationError should be raised
    And the error message should clearly identify which invariant was violated
    And the error message should explain why the action violates the invariant

  # === Edge Cases ===

  @edge_cases
  Scenario: No invariants loaded for empty context
    When I load active invariants for plan "01JQAAAAAAAAAAAAAAAAAAAA01"
    Then 0 invariants should be loaded

  @edge_cases
  Scenario: Checking action with no invariants succeeds
    When I check action "Delete all production database records" against empty invariants
    Then no inv error should be raised
    And the action should be accepted

  @edge_cases
  Scenario: Case-insensitive invariant checking
    Given a global invariant "Never delete production data" from source "system"
    When I check action "DELETE ALL PRODUCTION DATABASE RECORDS" against loaded invariants
    Then an InvariantViolationError should be raised

  @edge_cases
  Scenario: Whitespace-only action text raises ValidationError
    Given a global invariant "Never delete production data" from source "system"
    When I check action "   " against loaded invariants
    Then an inv ValidationError should be raised
