1cafe1de08
Add SQLite persistence for ChangeSet entries and ToolInvocation records via new changeset_repository module implementing the ChangeSetStore protocol. - Alembic migration d0_001 creates changeset_entries and tool_invocations tables - SqliteChangeSetStore, ChangeSetEntryRepository, ToolInvocationRepository - PlanApplyService.cleanup_changeset() for cancel/failure cleanup - Behave tests (17 scenarios), Robot tests (5 cases), ASV benchmarks - Reference documentation in docs/reference/changeset.md Closes #163
106 lines
4.7 KiB
Gherkin
106 lines
4.7 KiB
Gherkin
@unit
|
|
Feature: ChangeSet Persistence with SQLite
|
|
As a developer using CleverAgents
|
|
I want changesets and tool invocations persisted to SQLite
|
|
So that diffs, artifacts, and audit trails survive restarts
|
|
|
|
# ---- SqliteChangeSetStore start/record/get ----
|
|
|
|
Scenario: SqliteChangeSetStore start creates a new changeset ID
|
|
Given I have a sqlite-backed changeset store
|
|
When I persist-start a changeset for plan "plan-persist-1"
|
|
Then the persisted changeset ID should be a valid ULID
|
|
|
|
Scenario: SqliteChangeSetStore record and get round-trip
|
|
Given I have a sqlite-backed changeset store
|
|
When I persist-start a changeset for plan "plan-persist-2"
|
|
And I persist-record a create entry in the changeset
|
|
And I persist-record a modify entry in the changeset
|
|
Then persisted changeset get should return 2 entries
|
|
And the persisted first entry operation should be "create"
|
|
And the persisted second entry operation should be "modify"
|
|
|
|
Scenario: SqliteChangeSetStore get returns None for unknown ID
|
|
Given I have a sqlite-backed changeset store
|
|
Then persisted changeset "nonexistent-id" returns None on get
|
|
|
|
Scenario: SqliteChangeSetStore get_for_plan returns entries
|
|
Given I have a sqlite-backed changeset store
|
|
When I persist-start and populate a changeset for plan "plan-fp-1"
|
|
Then persisted get_for_plan "plan-fp-1" returns at least 1 changeset
|
|
|
|
Scenario: SqliteChangeSetStore summarize returns counts
|
|
Given I have a sqlite-backed changeset store
|
|
When I persist-start a changeset for plan "plan-sum-1"
|
|
And I persist-record a create entry in the changeset
|
|
And I persist-record a delete entry in the changeset
|
|
Then persisted summarize should show 2 total
|
|
|
|
Scenario: SqliteChangeSetStore summarize returns empty for unknown
|
|
Given I have a sqlite-backed changeset store
|
|
Then persisted summarize of changeset "no-such-id" returns empty dict
|
|
|
|
# ---- ChangeSetEntryRepository CRUD ----
|
|
|
|
Scenario: ChangeSetEntryRepository saves and retrieves entries
|
|
Given I have a persisted ChangeSetEntryRepository
|
|
When I persist-save an entry for changeset "cs-repo-1" plan "plan-repo-1"
|
|
Then persisted entries for changeset "cs-repo-1" count is 1
|
|
|
|
Scenario: ChangeSetEntryRepository deletes for plan
|
|
Given I have a persisted ChangeSetEntryRepository
|
|
When I persist-save entries for plan "plan-del-1"
|
|
And I persist-delete entries for plan "plan-del-1"
|
|
Then persisted entries for plan "plan-del-1" count is 0
|
|
|
|
Scenario: ChangeSetEntryRepository deletes for changeset
|
|
Given I have a persisted ChangeSetEntryRepository
|
|
When I persist-save an entry for changeset "cs-del-1" plan "plan-del-2"
|
|
And I persist-delete entries for changeset "cs-del-1"
|
|
Then persisted entries for changeset "cs-del-1" count is 0
|
|
|
|
# ---- ToolInvocationRepository CRUD ----
|
|
|
|
Scenario: ToolInvocationRepository saves and retrieves invocations
|
|
Given I have a persisted ToolInvocationRepository
|
|
When I persist-save an invocation for plan "plan-inv-1"
|
|
Then persisted invocations for plan "plan-inv-1" count is 1
|
|
|
|
Scenario: ToolInvocationRepository deletes for plan
|
|
Given I have a persisted ToolInvocationRepository
|
|
When I persist-save an invocation for plan "plan-inv-del"
|
|
And I persist-delete invocations for plan "plan-inv-del"
|
|
Then persisted invocations for plan "plan-inv-del" count is 0
|
|
|
|
# ---- Cleanup on cancel ----
|
|
|
|
Scenario: Cleanup changeset deletes artifacts for plan
|
|
Given I have a PlanApplyService backed by sqlite changeset store
|
|
When I persist-start and populate a changeset for the test plan
|
|
And I call cleanup_changeset on the persisted test plan
|
|
Then the persisted changeset entries for the test plan are empty
|
|
|
|
# ---- Validation ----
|
|
|
|
Scenario: ChangeSetEntryRepository rejects None session_factory
|
|
When I try creating a persisted ChangeSetEntryRepository with None
|
|
Then a persist ValueError should be raised
|
|
|
|
Scenario: ToolInvocationRepository rejects None session_factory
|
|
When I try creating a persisted ToolInvocationRepository with None
|
|
Then a persist ValueError should be raised
|
|
|
|
Scenario: SqliteChangeSetStore rejects None session_factory
|
|
When I try creating a persisted SqliteChangeSetStore with None
|
|
Then a persist ValueError should be raised
|
|
|
|
Scenario: SqliteChangeSetStore start rejects empty plan_id
|
|
Given I have a sqlite-backed changeset store
|
|
When I try to persist-start a changeset with empty plan_id
|
|
Then a persist ValueError should be raised
|
|
|
|
Scenario: Cleanup changeset rejects empty plan_id
|
|
Given I have a PlanApplyService backed by sqlite changeset store
|
|
When I try to persist-cleanup changeset with empty plan_id
|
|
Then a persist validation error should be raised
|