Feature: Validation apply gate As a plan executor I want attached validations to run before apply So that required validation failures block apply Background: Given a validation apply test environment # -- Attachment model ---------------------------------------------------- Scenario: Create a required validation attachment Given a validation attachment "lint-check" for resource "res-001" with mode "required" Then the attachment mode should be "required" And the attachment scope should be "direct" Scenario: Create an informational validation attachment Given a validation attachment "style-check" for resource "res-002" with mode "informational" Then the attachment mode should be "informational" Scenario: Create a project-scoped attachment Given a project-scoped attachment "lint-check" for resource "res-001" targeting "my-project" Then the attachment scope should be "project" And the attachment scope target should be "my-project" Scenario: Create a plan-scoped attachment Given a plan-scoped attachment "lint-check" for resource "res-001" targeting "01PLAN0001" Then the attachment scope should be "plan" And the attachment scope target should be "01PLAN0001" # -- DefaultValidationRunner --------------------------------------------- Scenario: DefaultValidationRunner passes when context matches Given a validation attachment "lint-check" for resource "res-001" with mode "required" And a validation run context with key "lint-check" and value "passed" When I execute the validation with DefaultValidationRunner Then the validation result should be passed Scenario: DefaultValidationRunner fails when context has no match Given a validation attachment "lint-check" for resource "res-001" with mode "required" And a validation run context with key "status" and value "no matches" When I execute the validation with DefaultValidationRunner Then the validation result should be failed Scenario: DefaultValidationRunner matches via arguments Given a validation attachment "coverage-check" for resource "res-001" with mode "required" And the attachment has argument "threshold" with value "90" And a validation run context with key "coverage" and value "90 percent" When I execute the validation with DefaultValidationRunner Then the validation result should be passed # -- ApplyValidationSummary ---------------------------------------------- Scenario: Summary all required passed with no failures Given an apply validation summary with 2 required passed and 0 required failed Then the apply summary should report all required passed And the apply summary total should be 2 Scenario: Summary blocked when required failure exists Given an apply validation summary with 1 required passed and 1 required failed Then the apply summary should not report all required passed And the apply summary required failed count should be 1 Scenario: Summary with informational results does not block Given an apply validation summary with 0 required passed and 0 required failed And the summary has 1 informational passed and 1 informational failed Then the apply summary should report all required passed And the apply summary informational failed count should be 1 Scenario: Empty summary reports all required passed Given an empty apply validation summary Then the apply summary should be empty And the apply summary should report all required passed Scenario: Summary to_plan_metadata has expected fields Given an apply validation summary with 1 required passed and 1 required failed Then the plan metadata should have key "total" And the plan metadata should have key "all_required_passed" And the plan metadata should have key "results" Scenario: Summary format_cli_output shows BLOCKED on failures Given an apply validation summary with 0 required passed and 1 required failed Then the validation gate CLI output should contain "BLOCKED" Scenario: Summary format_cli_output shows no details when neither message nor error Given an apply validation summary with a bare failure result Then the validation gate CLI output should contain "no details" Scenario: Summary format_cli_output shows error in failure detail Given an apply validation summary with an error result Then the validation gate CLI output should contain "execution timed out" Scenario: Summary format_cli_output shows PASSED when all pass Given an apply validation summary with 2 required passed and 0 required failed Then the validation gate CLI output should contain "PASSED" Scenario: DefaultValidationRunner populates duration_ms Given a validation attachment "lint-check" for resource "res-001" with mode "required" And a validation run context with key "lint-check" and value "passed" When I execute the validation with DefaultValidationRunner Then the validation result duration_ms should be >= 0 Scenario: DefaultValidationRunner handles exception during execution Given a validation attachment "err-val" for resource "res-err" with mode "required" And a validation run context that raises an error during iteration When I execute the validation with DefaultValidationRunner Then the validation result should be failed And the validation result should have an error message # -- ApplyValidationGate ------------------------------------------------- Scenario: Gate allows apply when all required pass Given a validation attachment "lint-check" for resource "res-001" with mode "required" And a validation run context with key "lint-check" and value "ok" When I run the apply validation gate for plan "01PLAN0001" Then the gate should allow apply Scenario: Gate blocks apply when required validation fails Given a validation attachment "lint-check" for resource "res-001" with mode "required" And a validation run context with key "other" and value "irrelevant" When I run the apply validation gate for plan "01PLAN0001" Then the gate should block apply And the gate failure reasons should mention "lint-check" Scenario: Gate allows apply despite informational failures Given a validation attachment "style-check" for resource "res-001" with mode "informational" And a validation run context with key "other" and value "irrelevant" When I run the apply validation gate for plan "01PLAN0001" Then the gate should allow apply Scenario: Gate with multiple attachments mixed results Given a validation attachment "lint-check" for resource "res-001" with mode "required" And a validation attachment "style-check" for resource "res-001" with mode "informational" And a validation run context with key "lint-check" and value "passed" When I run the apply validation gate for plan "01PLAN0001" Then the gate should allow apply And the apply summary total should be 2 Scenario: Gate failure reasons include error text when result has error Given an apply validation summary with an error result Then the gate failure reasons should mention "error:" Scenario: Gate with no attachments allows apply When I run the apply validation gate for plan "01PLAN0001" with no attachments Then the gate should allow apply And the apply summary should be empty