242 lines
8.8 KiB
Gherkin
242 lines
8.8 KiB
Gherkin
Feature: Session Domain Model
|
|
As a developer
|
|
I want session domain models for conversation management
|
|
So that sessions can be created, tracked, and exported via CLI
|
|
|
|
# ---- Session Creation ----
|
|
|
|
Scenario: Create a session with valid ULID
|
|
When I create a session with a valid ULID
|
|
Then the session model should be created
|
|
And the session model session_id should be a valid ULID
|
|
|
|
Scenario: Create a session with actor name
|
|
When I create a session with actor name "local/orchestrator"
|
|
Then the session model should be created
|
|
And the session model actor_name should be "local/orchestrator"
|
|
|
|
Scenario: Create a session without actor name
|
|
When I create a session without actor name
|
|
Then the session model should be created
|
|
And the session model actor_name should be empty
|
|
|
|
Scenario: Session has default namespace local
|
|
When I create a session with a valid ULID
|
|
Then the session model namespace should be "local"
|
|
|
|
# ---- Session ID Validation ----
|
|
|
|
Scenario: Session rejects invalid ULID format
|
|
When I try to create a session with invalid ID "not-a-ulid"
|
|
Then a session model validation error should be raised
|
|
|
|
# ---- Actor Name Validation ----
|
|
|
|
Scenario: Session rejects invalid actor name format
|
|
When I try to create a session with invalid actor name "badformat"
|
|
Then a session model validation error should be raised
|
|
|
|
Scenario: Session accepts None actor name
|
|
When I create a session without actor name
|
|
Then the session model should be created
|
|
|
|
# ---- Message Append with Auto-sequencing ----
|
|
|
|
Scenario: Append a user message to session
|
|
Given a session with no messages
|
|
When I append a user message "Hello"
|
|
Then the session model should have 1 message
|
|
And the session last message content should be "Hello"
|
|
And the session last message role should be "user"
|
|
And the session last message sequence should be 0
|
|
|
|
Scenario: Append multiple messages with auto-sequencing
|
|
Given a session with no messages
|
|
When I append a user message "Hello"
|
|
And I append an assistant message "Hi there"
|
|
Then the session model should have 2 messages
|
|
And the session last message sequence should be 1
|
|
|
|
# ---- Message Role Validation ----
|
|
|
|
Scenario: Tool message requires tool_call_id
|
|
When I try to create a tool message without tool_call_id
|
|
Then a session model validation error should be raised
|
|
And the session model error should mention "tool_call_id"
|
|
|
|
Scenario: Tool message with tool_call_id is valid
|
|
When I create a tool message with tool_call_id "call_123"
|
|
Then the session message should be created
|
|
And the session message tool_call_id should be "call_123"
|
|
|
|
Scenario: User message does not require tool_call_id
|
|
When I create a user message "Hello"
|
|
Then the session message should be created
|
|
|
|
# ---- Content Validation ----
|
|
|
|
Scenario: Message rejects whitespace-only content
|
|
When I try to create a message with whitespace-only content
|
|
Then a session model validation error should be raised
|
|
And the session model error should mention "whitespace"
|
|
|
|
Scenario: Message rejects empty content
|
|
When I try to create a message with empty content
|
|
Then a session model validation error should be raised
|
|
|
|
# ---- Message Ordering ----
|
|
|
|
Scenario: Messages must be ordered by sequence
|
|
When I try to create a session with out-of-order messages
|
|
Then a session model validation error should be raised
|
|
And the session model error should mention "ordered by sequence"
|
|
|
|
# ---- Plan Linking ----
|
|
|
|
Scenario: Link a plan to session
|
|
Given a session with no messages
|
|
When I link plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" to the session
|
|
Then the session should have 1 linked plan
|
|
|
|
Scenario: Plan linking deduplicates
|
|
Given a session with no messages
|
|
When I link plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" to the session
|
|
And I link plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" to the session
|
|
Then the session should have 1 linked plan
|
|
|
|
Scenario: Link multiple plans
|
|
Given a session with no messages
|
|
When I link plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" to the session
|
|
And I link plan "01BX5ZZKBKACTAV9WEVGEMMVRY" to the session
|
|
Then the session should have 2 linked plans
|
|
|
|
# ---- Token Usage Tracking ----
|
|
|
|
Scenario: Default token usage is zero
|
|
When I create a session with a valid ULID
|
|
Then the session token usage input_tokens should be 0
|
|
And the session token usage output_tokens should be 0
|
|
And the session token usage estimated_cost should be 0.0
|
|
|
|
Scenario: Token usage with values
|
|
When I create a session with token usage 100 input 50 output 0.05 cost
|
|
Then the session token usage input_tokens should be 100
|
|
And the session token usage output_tokens should be 50
|
|
And the session token usage estimated_cost should be 0.05
|
|
|
|
Scenario: Token usage rejects negative values
|
|
When I try to create token usage with negative input tokens
|
|
Then a session model validation error should be raised
|
|
|
|
# ---- Export Dict ----
|
|
|
|
Scenario: Export dict contains checksum
|
|
Given a session with some messages
|
|
When I export the session
|
|
Then the export dict should have key "checksum"
|
|
And the export dict should have key "schema_version"
|
|
And the export dict should have key "messages"
|
|
And the export dict should have key "session_id"
|
|
|
|
Scenario: Export dict round-trip preserves data
|
|
Given a session with some messages
|
|
When I export the session
|
|
Then the export dict messages count should match session message count
|
|
|
|
# ---- CLI Dict ----
|
|
|
|
Scenario: CLI dict has required fields
|
|
Given a session with some messages
|
|
When I get the session CLI dict
|
|
Then the session cli dict should have key "session_id"
|
|
And the session cli dict should have key "message_count"
|
|
And the session cli dict should have key "created_at"
|
|
And the session cli dict should have key "updated_at"
|
|
And the session cli dict should have key "token_usage"
|
|
And the session cli dict should have key "namespace"
|
|
|
|
Scenario: CLI dict includes recent messages
|
|
Given a session with some messages
|
|
When I get the session CLI dict
|
|
Then the session cli dict should have key "recent_messages"
|
|
|
|
Scenario: CLI dict includes actor when set
|
|
When I create a session with actor name "local/orchestrator"
|
|
And I get the session CLI dict
|
|
Then the session cli dict should have key "actor_name"
|
|
|
|
# ---- Empty Session Properties ----
|
|
|
|
Scenario: Empty session has zero message count
|
|
Given a session with no messages
|
|
Then the session message count should be 0
|
|
And the session is_empty should be true
|
|
And the session last_message should be none
|
|
|
|
# ---- get_messages with limit/offset ----
|
|
|
|
Scenario: get_messages with no limit returns all
|
|
Given a session with 5 messages
|
|
When I get messages with no limit
|
|
Then I should get 5 messages
|
|
|
|
Scenario: get_messages with limit
|
|
Given a session with 5 messages
|
|
When I get messages with limit 3
|
|
Then I should get 3 messages
|
|
|
|
Scenario: get_messages with offset
|
|
Given a session with 5 messages
|
|
When I get messages with offset 2
|
|
Then I should get 3 messages
|
|
|
|
Scenario: get_messages with limit and offset
|
|
Given a session with 5 messages
|
|
When I get messages with limit 2 and offset 1
|
|
Then I should get 2 messages
|
|
|
|
# ---- Session Error Types ----
|
|
|
|
Scenario: SessionServiceError is base error
|
|
Then SessionServiceError should be an Exception subclass
|
|
|
|
Scenario: SessionNotFoundError inherits from SessionServiceError
|
|
Then SessionNotFoundError should be a SessionServiceError subclass
|
|
|
|
Scenario: SessionExportError inherits from SessionServiceError
|
|
Then SessionExportError should be a SessionServiceError subclass
|
|
|
|
Scenario: SessionImportError inherits from SessionServiceError
|
|
Then SessionImportError should be a SessionServiceError subclass
|
|
|
|
# ---- MessageRole enum ----
|
|
|
|
Scenario: MessageRole has expected values
|
|
Then the MessageRole enum should have values "user,assistant,system,tool"
|
|
|
|
# ---- Session metadata ----
|
|
|
|
Scenario: Session supports metadata
|
|
When I create a session with metadata
|
|
Then the session metadata should contain key "env"
|
|
|
|
# ---- Export dict linked plans ----
|
|
|
|
Scenario: Export dict includes linked plan IDs
|
|
Given a session with no messages
|
|
When I link plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" to the session
|
|
And I export the session
|
|
Then the export dict should have key "linked_plan_ids"
|
|
|
|
# ---- Robot Smoke Alignment: Serialization Order ----
|
|
|
|
Scenario: Export dict keys are in expected serialization order
|
|
Given a session with some messages
|
|
When I export the session
|
|
Then the export dict keys should be in expected serialization order
|
|
|
|
Scenario: Export dict messages are ordered by sequence
|
|
Given a session with some messages
|
|
When I export the session
|
|
Then the export dict messages should be ordered by sequence
|