31472b5413
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / helm (pull_request) Successful in 22s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m43s
CI / typecheck (pull_request) Successful in 3m58s
CI / security (pull_request) Successful in 4m8s
CI / integration_tests (pull_request) Successful in 9m33s
CI / unit_tests (pull_request) Successful in 10m12s
CI / docker (pull_request) Successful in 1m28s
CI / coverage (pull_request) Successful in 12m18s
CI / e2e_tests (pull_request) Successful in 19m51s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 15s
CI / helm (push) Successful in 22s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 3m57s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m10s
CI / unit_tests (push) Failing after 6m58s
CI / docker (push) Has been skipped
CI / integration_tests (push) Successful in 9m15s
CI / coverage (push) Successful in 12m26s
CI / e2e_tests (push) Successful in 23m11s
CI / status-check (push) Failing after 1s
CI / benchmark-publish (push) Successful in 28m31s
CI / benchmark-regression (pull_request) Successful in 54m53s
Add Behave feature/step pairs that exercise uncovered branches across handlers, LSP, CLI, and service layers to reach the coverage gate. ISSUES CLOSED: #1232
363 lines
17 KiB
Gherkin
363 lines
17 KiB
Gherkin
Feature: Database repositories coverage round 3
|
|
Targets uncovered lines in repositories.py for:
|
|
- ActionRepository.list_all (lines 1005-1017)
|
|
- NamespacedProjectRepository.get_context_policy all branches (lines 2982-3012)
|
|
- ToolRegistryRepository create IntegrityError UNIQUE (line 3378)
|
|
- ToolRepository.get, get_by_name, remove, update (lines 3690-3717)
|
|
- SessionRepository list_all, delete error, update error (lines 4063-4173)
|
|
- SessionMessageRepository append error, get, count (lines 4227-4298)
|
|
- AutomationProfileRepository._to_domain legacy safety fallback (lines 4509-4514)
|
|
- SkillRepository update return, delete, flattened tool cache (lines 4851-5085)
|
|
- DecisionRepository full CRUD (lines 5153-5519)
|
|
- CheckpointRepository full CRUD (lines 5564-5717)
|
|
- CorrectionAttemptRepository full CRUD + state transitions (lines 5789-6018)
|
|
|
|
# -- ActionRepository.list_all --
|
|
|
|
Scenario: ActionRepository list_all returns ordered actions
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 an ActionRepository instance
|
|
And drcov3 two actions exist in different namespaces
|
|
When drcov3 I call list_all on the action repository
|
|
Then drcov3 it returns actions ordered by namespace then name
|
|
|
|
Scenario: ActionRepository list_all raises DatabaseError on failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 an ActionRepository with a broken session
|
|
When drcov3 I call list_all expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to list all actions"
|
|
|
|
# -- NamespacedProjectRepository.get_context_policy --
|
|
|
|
Scenario: get_context_policy returns default when project not found
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a NamespacedProjectRepository instance
|
|
When drcov3 I call get_context_policy for "ns/nonexistent"
|
|
Then drcov3 the result is a default ProjectContextPolicy
|
|
|
|
Scenario: get_context_policy returns default when context_policy_json is None
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a NamespacedProjectRepository instance
|
|
And drcov3 a project "ns/proj1" exists with null context_policy_json
|
|
When drcov3 I call get_context_policy for "ns/proj1"
|
|
Then drcov3 the result is a default ProjectContextPolicy
|
|
|
|
Scenario: get_context_policy returns parsed policy from valid JSON
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a NamespacedProjectRepository instance
|
|
And drcov3 a project "ns/proj2" exists with valid context_policy_json
|
|
When drcov3 I call get_context_policy for "ns/proj2"
|
|
Then drcov3 the result is a valid ProjectContextPolicy
|
|
|
|
Scenario: get_context_policy returns default when payload is not a dict
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a NamespacedProjectRepository instance
|
|
And drcov3 a project "ns/proj3" exists with non-dict context_policy_json
|
|
When drcov3 I call get_context_policy for "ns/proj3"
|
|
Then drcov3 the result is a default ProjectContextPolicy
|
|
|
|
Scenario: get_context_policy returns default on ValueError/TypeError
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a NamespacedProjectRepository instance
|
|
And drcov3 a project "ns/proj4" exists with corrupt context_policy_json
|
|
When drcov3 I call get_context_policy for "ns/proj4"
|
|
Then drcov3 the result is a default ProjectContextPolicy
|
|
|
|
Scenario: get_context_policy raises DatabaseError on DB failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a NamespacedProjectRepository with broken session
|
|
When drcov3 I call get_context_policy expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to load project context policy"
|
|
|
|
# -- ToolRepository legacy wrapper --
|
|
|
|
Scenario: ToolRepository get returns None for missing tool
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a ToolRepository instance
|
|
When drcov3 I call ToolRepository get for "ns/missing-tool"
|
|
Then drcov3 the tool result is None
|
|
|
|
Scenario: ToolRepository get_by_name returns None for missing tool
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a ToolRepository instance
|
|
When drcov3 I call ToolRepository get_by_name for "ns/missing-tool"
|
|
Then drcov3 the tool result is None
|
|
|
|
Scenario: ToolRepository remove raises ToolNotFoundError
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a ToolRepository instance
|
|
When drcov3 I call ToolRepository remove for "ns/missing-tool"
|
|
Then drcov3 a ToolNotFoundError was raised
|
|
|
|
Scenario: ToolRepository update raises ToolNotFoundError for missing tool
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a ToolRepository instance
|
|
When drcov3 I call ToolRepository update with a non-existent tool
|
|
Then drcov3 a ToolNotFoundError was raised
|
|
|
|
# -- SessionRepository --
|
|
|
|
Scenario: SessionRepository list_all returns sessions
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SessionRepository instance
|
|
When drcov3 I call session list_all
|
|
Then drcov3 the session list result is a list
|
|
|
|
Scenario: SessionRepository delete raises DatabaseError on failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SessionRepository with a broken session for delete
|
|
When drcov3 I call session delete expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to delete session"
|
|
|
|
Scenario: SessionRepository update raises DatabaseError on failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SessionRepository with a broken session for update
|
|
When drcov3 I call session update expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to update session"
|
|
|
|
# -- SessionMessageRepository --
|
|
|
|
Scenario: SessionMessageRepository append raises DatabaseError on failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SessionMessageRepository with a broken session
|
|
When drcov3 I call message append expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to append message"
|
|
|
|
Scenario: SessionMessageRepository count_for_session returns zero for empty session
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SessionMessageRepository instance
|
|
When drcov3 I call count_for_session with a random session id
|
|
Then drcov3 the count result is 0
|
|
|
|
# -- AutomationProfileRepository._to_domain legacy safety fallback --
|
|
|
|
Scenario: AutomationProfileRepository to_domain uses legacy safety fallback
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 an AutomationProfileModel row without safety_json
|
|
When drcov3 I call _to_domain on the row
|
|
Then drcov3 the result has a SafetyProfile from legacy columns
|
|
|
|
# -- SkillRepository flattened tools cache --
|
|
|
|
Scenario: SkillRepository delete returns True for existing skill
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SkillRepository instance
|
|
And drcov3 a skill "ns/myskill-del" exists
|
|
When drcov3 I call skill delete for "ns/myskill-del"
|
|
Then drcov3 the skill delete result is True
|
|
|
|
Scenario: SkillRepository update_flattened_tools persists cache data
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SkillRepository instance
|
|
And drcov3 a skill "ns/myskill-flat" exists
|
|
When drcov3 I call update_flattened_tools for "ns/myskill-flat"
|
|
Then drcov3 the flattened tools are stored
|
|
|
|
Scenario: SkillRepository get_flattened_tools returns cache data
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SkillRepository instance
|
|
And drcov3 a skill "ns/myskill-getflat" exists with flattened tools
|
|
When drcov3 I call get_flattened_tools for "ns/myskill-getflat"
|
|
Then drcov3 the cache dict has expected keys
|
|
|
|
Scenario: SkillRepository needs_refresh returns True when hash differs
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SkillRepository instance
|
|
And drcov3 a skill "ns/myskill-refresh" exists with flattening_hash "oldhash"
|
|
When drcov3 I call needs_refresh for "ns/myskill-refresh" with hash "newhash"
|
|
Then drcov3 the needs_refresh result is True
|
|
|
|
Scenario: SkillRepository recompute_flattening_hash stores new hash
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SkillRepository instance
|
|
And drcov3 a skill "ns/myskill-rehash" exists
|
|
When drcov3 I call recompute_flattening_hash for "ns/myskill-rehash"
|
|
Then drcov3 the returned hash is a sha256 hex string
|
|
|
|
Scenario: SkillRepository invalidate_cached_summaries nulls cache fields
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a SkillRepository instance
|
|
And drcov3 a skill "ns/myskill-inval" exists with flattened tools
|
|
When drcov3 I call invalidate_cached_summaries for "ns/myskill-inval"
|
|
Then drcov3 the cached fields are None
|
|
|
|
# -- DecisionRepository full CRUD --
|
|
|
|
Scenario: DecisionRepository create and get round-trip
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
When drcov3 I create a decision
|
|
And drcov3 I get the decision by id
|
|
Then drcov3 the retrieved decision matches the created one
|
|
|
|
Scenario: DecisionRepository get_by_plan returns ordered decisions
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 multiple decisions exist for the plan
|
|
When drcov3 I call get_by_plan
|
|
Then drcov3 I get decisions ordered by sequence number
|
|
|
|
Scenario: DecisionRepository get_tree returns BFS-ordered tree
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 a decision tree exists
|
|
When drcov3 I call get_tree on the root
|
|
Then drcov3 I get the root and its descendants in BFS order
|
|
|
|
Scenario: DecisionRepository get_path_to_root walks up to root
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 a decision tree exists
|
|
When drcov3 I call get_path_to_root on a leaf
|
|
Then drcov3 I get a path from leaf to root
|
|
|
|
Scenario: DecisionRepository get_superseded returns superseded decisions
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 a superseded decision exists
|
|
When drcov3 I call get_superseded
|
|
Then drcov3 I get the superseded decisions
|
|
|
|
Scenario: DecisionRepository update_superseded_by marks a decision
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 two decisions exist for supersede test
|
|
When drcov3 I call update_superseded_by
|
|
Then drcov3 the decision has superseded_by set
|
|
|
|
Scenario: DecisionRepository list_by_type filters by type
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 decisions of different types exist
|
|
When drcov3 I call list_by_type for strategy_choice
|
|
Then drcov3 I only get strategy_choice decisions
|
|
|
|
Scenario: DecisionRepository delete removes a decision
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 a single decision exists for delete test
|
|
When drcov3 I delete the decision
|
|
Then drcov3 the delete result is True
|
|
|
|
Scenario: DecisionRepository get_max_sequence_number returns max
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 multiple decisions exist for the plan
|
|
When drcov3 I call get_max_sequence_number
|
|
Then drcov3 the max sequence number is correct
|
|
|
|
Scenario: DecisionRepository count returns the decision count
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a DecisionRepository instance
|
|
And drcov3 a plan exists for decisions
|
|
And drcov3 multiple decisions exist for the plan
|
|
When drcov3 I call decision count
|
|
Then drcov3 the decision count matches expected
|
|
|
|
# -- CheckpointRepository full CRUD --
|
|
|
|
Scenario: CheckpointRepository create and get_by_id round-trip
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CheckpointRepository instance
|
|
And drcov3 a plan exists for checkpoints
|
|
When drcov3 I create a checkpoint
|
|
And drcov3 I get the checkpoint by id
|
|
Then drcov3 the retrieved checkpoint matches
|
|
|
|
Scenario: CheckpointRepository list_by_plan returns ordered checkpoints
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CheckpointRepository instance
|
|
And drcov3 a plan exists for checkpoints
|
|
And drcov3 multiple checkpoints exist for the plan
|
|
When drcov3 I call checkpoint list_by_plan
|
|
Then drcov3 I get checkpoints ordered by creation time
|
|
|
|
Scenario: CheckpointRepository delete removes a checkpoint
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CheckpointRepository instance
|
|
And drcov3 a plan exists for checkpoints
|
|
And drcov3 a checkpoint exists for delete test
|
|
When drcov3 I delete the checkpoint
|
|
Then drcov3 the checkpoint delete result is True
|
|
|
|
Scenario: CheckpointRepository prune removes excess checkpoints
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CheckpointRepository instance
|
|
And drcov3 a plan exists for checkpoints
|
|
And drcov3 five checkpoints exist for prune test
|
|
When drcov3 I call prune with max_checkpoints 3
|
|
Then drcov3 two interior checkpoints are removed
|
|
|
|
# -- CorrectionAttemptRepository full CRUD --
|
|
|
|
Scenario: CorrectionAttemptRepository create and get round-trip
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository instance
|
|
And drcov3 a plan and decision exist for corrections
|
|
When drcov3 I create a correction attempt
|
|
And drcov3 I get the correction attempt by id
|
|
Then drcov3 the retrieved correction attempt matches
|
|
|
|
Scenario: CorrectionAttemptRepository list_by_plan returns records
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository instance
|
|
And drcov3 a plan and decision exist for corrections
|
|
And drcov3 a correction attempt exists for list test
|
|
When drcov3 I call correction list_by_plan
|
|
Then drcov3 the correction list contains the attempt
|
|
|
|
Scenario: CorrectionAttemptRepository update_state transitions pending to executing
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository instance
|
|
And drcov3 a plan and decision exist for corrections
|
|
And drcov3 a pending correction attempt exists for state test
|
|
When drcov3 I update correction state to executing
|
|
Then drcov3 the correction state is executing
|
|
|
|
Scenario: CorrectionAttemptRepository delete removes a record
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository instance
|
|
And drcov3 a plan and decision exist for corrections
|
|
And drcov3 a correction attempt exists for delete test
|
|
When drcov3 I delete the correction attempt
|
|
Then drcov3 the correction delete result is True
|
|
|
|
Scenario: CorrectionAttemptRepository create raises DatabaseError on OperationalError
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository with broken session
|
|
When drcov3 I call correction create expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to create correction attempt"
|
|
|
|
Scenario: CorrectionAttemptRepository get raises DatabaseError on OperationalError
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository with broken session for get
|
|
When drcov3 I call correction get expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to get correction attempt"
|
|
|
|
Scenario: CorrectionAttemptRepository list_by_plan raises DatabaseError on failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository with broken session for list
|
|
When drcov3 I call correction list_by_plan expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to list correction attempts"
|
|
|
|
Scenario: CorrectionAttemptRepository delete raises DatabaseError on failure
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository with broken session for delete
|
|
When drcov3 I call correction delete expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to delete correction attempt"
|
|
|
|
Scenario: CorrectionAttemptRepository update_state raises DatabaseError on OperationalError
|
|
Given drcov3 an in-memory database with schema
|
|
And drcov3 a CorrectionAttemptRepository with broken session for update_state
|
|
When drcov3 I call correction update_state expecting a DatabaseError
|
|
Then drcov3 a DatabaseError was raised containing "Failed to update correction attempt"
|