Files
cleveragents-core/features/changeset_persistence.feature
freemo 1cafe1de08 feat(changeset): persist changesets and diff artifacts
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
2026-02-25 03:30:51 +00:00

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