229dbc8925
- add with_superseded_by() helper for frozen model mutation - document frozen model + superseded_by interaction in docstring - clarify sequence_number uniqueness is a persistence concern - add scenario for invalid corrects_decision_id ULID validation - add scenario for with_superseded_by copy behavior - type step helper dict as dict[str, Any]
247 lines
10 KiB
Gherkin
247 lines
10 KiB
Gherkin
Feature: Decision domain model
|
|
Validates the Decision, DecisionType, ContextSnapshot, ResourceRef,
|
|
and ArtifactRef domain models including ULID validation, enum coverage,
|
|
tree structure helpers, correction constraints, and serialization.
|
|
|
|
# ------------------------------------------------------------------
|
|
# DecisionType enum
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: All 11 decision types are defined
|
|
Then the DecisionType enum should have exactly 11 members
|
|
|
|
Scenario: Strategize-phase types are correctly classified
|
|
Then STRATEGIZE_TYPES should contain "prompt_definition"
|
|
And STRATEGIZE_TYPES should contain "invariant_enforced"
|
|
And STRATEGIZE_TYPES should contain "strategy_choice"
|
|
And STRATEGIZE_TYPES should contain "subplan_spawn"
|
|
And STRATEGIZE_TYPES should contain "subplan_parallel_spawn"
|
|
And STRATEGIZE_TYPES should have exactly 5 members
|
|
|
|
Scenario: Execute-phase types are correctly classified
|
|
Then EXECUTE_TYPES should contain "implementation_choice"
|
|
And EXECUTE_TYPES should contain "resource_selection"
|
|
And EXECUTE_TYPES should contain "tool_invocation"
|
|
And EXECUTE_TYPES should contain "error_recovery"
|
|
And EXECUTE_TYPES should contain "validation_response"
|
|
And EXECUTE_TYPES should have exactly 5 members
|
|
|
|
Scenario: user_intervention is not in either phase set
|
|
Then STRATEGIZE_TYPES should not contain "user_intervention"
|
|
And EXECUTE_TYPES should not contain "user_intervention"
|
|
|
|
# ------------------------------------------------------------------
|
|
# Decision creation and ULID validation
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: Create a minimal root decision
|
|
Given a valid plan ULID
|
|
When I create a prompt_definition decision with sequence 0
|
|
Then the decision should be created successfully
|
|
And the decision should be a root decision
|
|
And the decision should have a valid ULID as decision_id
|
|
And the decision type should be "prompt_definition"
|
|
And the decision is_strategize_type should be true
|
|
|
|
Scenario: Create a non-root decision with parent
|
|
Given a valid plan ULID
|
|
And a valid parent decision ULID
|
|
When I create a strategy_choice decision with sequence 1 and a parent
|
|
Then the decision should be created successfully
|
|
And the decision should not be a root decision
|
|
And the decision is_strategize_type should be true
|
|
|
|
Scenario: Create an execute-phase decision
|
|
Given a valid plan ULID
|
|
And a valid parent decision ULID
|
|
When I create an implementation_choice decision with sequence 2 and a parent
|
|
Then the decision should be created successfully
|
|
And the decision is_execute_type should be true
|
|
And the decision is_strategize_type should be false
|
|
|
|
Scenario: user_intervention is valid in any phase
|
|
Given a valid plan ULID
|
|
When I create a user_intervention decision with sequence 3
|
|
Then the decision should be created successfully
|
|
And the decision is_any_phase_type should be true
|
|
|
|
Scenario: Invalid plan_id is rejected
|
|
When I try to create a decision with plan_id "not-a-ulid"
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "plan_id"
|
|
|
|
Scenario: Invalid parent_decision_id is rejected
|
|
Given a valid plan ULID
|
|
When I try to create a decision with parent_decision_id "bad-id"
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "parent_decision_id"
|
|
|
|
# ------------------------------------------------------------------
|
|
# prompt_definition root constraint
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: prompt_definition with a parent is rejected
|
|
Given a valid plan ULID
|
|
And a valid parent decision ULID
|
|
When I try to create a prompt_definition with a parent
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "root"
|
|
|
|
# ------------------------------------------------------------------
|
|
# Confidence score validation
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: Confidence score within valid range
|
|
Given a valid plan ULID
|
|
When I create a decision with confidence score 0.85
|
|
Then the decision should be created successfully
|
|
And the decision confidence score should be 0.85
|
|
|
|
Scenario: Confidence score of 0.0 is valid
|
|
Given a valid plan ULID
|
|
When I create a decision with confidence score 0.0
|
|
Then the decision should be created successfully
|
|
|
|
Scenario: Confidence score of 1.0 is valid
|
|
Given a valid plan ULID
|
|
When I create a decision with confidence score 1.0
|
|
Then the decision should be created successfully
|
|
|
|
Scenario: Confidence score above 1.0 is rejected
|
|
Given a valid plan ULID
|
|
When I try to create a decision with confidence score 1.5
|
|
Then a decision validation error should be raised
|
|
|
|
Scenario: Confidence score below 0.0 is rejected
|
|
Given a valid plan ULID
|
|
When I try to create a decision with confidence score -0.1
|
|
Then a decision validation error should be raised
|
|
|
|
Scenario: Confidence score of None is valid
|
|
Given a valid plan ULID
|
|
When I create a decision with confidence score None
|
|
Then the decision should be created successfully
|
|
And the decision confidence score should be None
|
|
|
|
# ------------------------------------------------------------------
|
|
# Correction metadata
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: Create a correction decision
|
|
Given a valid plan ULID
|
|
And a valid corrected decision ULID
|
|
When I create a correction decision
|
|
Then the decision should be created successfully
|
|
And the decision is_correction should be true
|
|
|
|
Scenario: is_correction without corrects_decision_id is rejected
|
|
Given a valid plan ULID
|
|
When I try to create a decision with is_correction true but no corrects_decision_id
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "corrects_decision_id"
|
|
|
|
Scenario: corrects_decision_id without is_correction is rejected
|
|
Given a valid plan ULID
|
|
And a valid corrected decision ULID
|
|
When I try to create a decision with corrects_decision_id but is_correction false
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "is_correction"
|
|
|
|
Scenario: superseded_by marks decision as superseded
|
|
Given a valid plan ULID
|
|
When I create a decision that is superseded
|
|
Then the decision is_superseded should be true
|
|
|
|
Scenario: Invalid superseded_by ULID is rejected
|
|
Given a valid plan ULID
|
|
When I try to create a decision with superseded_by "invalid"
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "superseded_by"
|
|
|
|
Scenario: Invalid corrects_decision_id ULID is rejected
|
|
Given a valid plan ULID
|
|
When I try to create a decision with corrects_decision_id ULID "not-valid"
|
|
Then a decision validation error should be raised
|
|
And the decision error should mention "corrects_decision_id"
|
|
|
|
Scenario: with_superseded_by returns a new superseded copy
|
|
Given a valid plan ULID
|
|
When I create a prompt_definition decision with sequence 0
|
|
And I call with_superseded_by on the decision
|
|
Then the original decision should not be superseded
|
|
And the superseded copy should be superseded
|
|
|
|
# ------------------------------------------------------------------
|
|
# ContextSnapshot
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: Create a decision with a populated context snapshot
|
|
Given a valid plan ULID
|
|
And a context snapshot with hash and resources
|
|
When I create a decision with the context snapshot
|
|
Then the decision should be created successfully
|
|
And the decision context snapshot hash should not be empty
|
|
And the decision context snapshot should have resources
|
|
|
|
Scenario: Default context snapshot is empty
|
|
Given a valid plan ULID
|
|
When I create a prompt_definition decision with sequence 0
|
|
Then the decision context snapshot hash should be empty
|
|
|
|
# ------------------------------------------------------------------
|
|
# ResourceRef and ArtifactRef
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: ResourceRef requires non-empty resource_id
|
|
When I try to create a ResourceRef with empty resource_id
|
|
Then a decision validation error should be raised
|
|
|
|
Scenario: ArtifactRef requires non-empty artifact_path
|
|
When I try to create an ArtifactRef with empty artifact_path
|
|
Then a decision validation error should be raised
|
|
|
|
Scenario: Decision with artifacts_produced
|
|
Given a valid plan ULID
|
|
When I create a decision with artifacts
|
|
Then the decision should have 2 artifacts produced
|
|
|
|
# ------------------------------------------------------------------
|
|
# Serialization
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario: Decision round-trips through dict serialization
|
|
Given a valid plan ULID
|
|
When I create a fully populated decision
|
|
Then the decision should round-trip through model_dump and model_validate
|
|
|
|
Scenario: as_cli_dict returns expected keys
|
|
Given a valid plan ULID
|
|
When I create a prompt_definition decision with sequence 0
|
|
Then as_cli_dict should contain key "decision_id"
|
|
And as_cli_dict should contain key "type"
|
|
And as_cli_dict should contain key "confidence"
|
|
And as_cli_dict should contain key "parent"
|
|
|
|
# ------------------------------------------------------------------
|
|
# All 11 decision types can be instantiated
|
|
# ------------------------------------------------------------------
|
|
|
|
Scenario Outline: Each decision type can be instantiated
|
|
Given a valid plan ULID
|
|
When I create a decision of type "<dtype>"
|
|
Then the decision should be created successfully
|
|
|
|
Examples:
|
|
| dtype |
|
|
| prompt_definition |
|
|
| invariant_enforced |
|
|
| strategy_choice |
|
|
| implementation_choice |
|
|
| resource_selection |
|
|
| subplan_spawn |
|
|
| subplan_parallel_spawn |
|
|
| tool_invocation |
|
|
| error_recovery |
|
|
| validation_response |
|
|
| user_intervention |
|