5.0 KiB
ChangeSet Model Reference
The ChangeSet domain model captures all file changes made by tools during the Execute phase. It is the foundation for plan diff, review, and apply workflows.
Overview
| Model | Purpose |
|---|---|
ChangeOperation |
Enum of operation types (CREATE, MODIFY, DELETE, RENAME) |
ChangeEntry |
Single recorded mutation with content hashes and metadata |
SpecChangeSet |
Collection of entries for a plan, with computed summaries |
ChangeSetStore |
Protocol for persisting and querying changesets |
InMemoryChangeSetStore |
In-memory implementation for M1 milestone |
ChangeOperation
from cleveragents.domain.models.core.change import ChangeOperation
ChangeOperation.CREATE # "create" — new file
ChangeOperation.MODIFY # "modify" — content changed
ChangeOperation.DELETE # "delete" — file removed
ChangeOperation.RENAME # "rename" — file moved/renamed
ChangeEntry
Each ChangeEntry represents a single tool-caused mutation.
Fields
| Field | Type | Description |
|---|---|---|
entry_id |
str |
Auto-generated ULID uniquely identifying this entry |
plan_id |
str |
ULID of the plan that owns this change |
resource_id |
str |
ULID of the resource affected |
tool_name |
str |
Namespaced tool name (e.g. builtin/file-write) |
operation |
ChangeOperation |
Type of change |
path |
str |
Repo-relative file path |
before_hash |
str | None |
SHA-256 of file before change (None for create) |
after_hash |
str | None |
SHA-256 of file after change (None for delete) |
before_mode |
int | None |
File mode before change |
after_mode |
int | None |
File mode after change |
timestamp |
datetime |
UTC timestamp of the change |
ULID Fields
The entry_id and plan_id fields use ULIDs
(Universally Unique Lexicographically Sortable Identifiers). ULIDs are 128-bit
identifiers that encode a timestamp and random component, making them sortable
by creation time while remaining globally unique.
01ARZ3NDEKTSV4RRFFQ69G5FAV
└─────────┘└────────────┘
timestamp randomness
(48 bit) (80 bit)
Example
from cleveragents.domain.models.core.change import (
ChangeEntry, ChangeOperation,
)
entry = ChangeEntry(
plan_id="01HXYZ123456789ABCDEF",
resource_id="01HXYZ000000000000001",
tool_name="builtin/file-write",
operation=ChangeOperation.CREATE,
path="src/models/user.py",
after_hash="e3b0c44298fc1c149afbf4c8996fb924...",
)
SpecChangeSet
A SpecChangeSet groups all ChangeEntry records for a single plan execution.
Fields
| Field | Type | Description |
|---|---|---|
changeset_id |
str |
Auto-generated ULID for the changeset |
plan_id |
str |
ULID of the plan |
entries |
list[ChangeEntry] |
Ordered list of change entries |
created_at |
datetime |
UTC timestamp when created |
Computed Properties
| Property | Type | Description |
|---|---|---|
creates |
int |
Count of CREATE entries |
modifies |
int |
Count of MODIFY entries |
deletes |
int |
Count of DELETE entries |
renames |
int |
Count of RENAME entries |
paths_changed |
set[str] |
Unique file paths affected |
resources_involved |
set[str] |
Unique resource IDs |
Example
from cleveragents.domain.models.core.change import (
ChangeEntry, ChangeOperation, SpecChangeSet,
)
cs = SpecChangeSet(
plan_id="01HXYZ123456789ABCDEF",
entries=[
ChangeEntry(
plan_id="01HXYZ123456789ABCDEF",
resource_id="01HXYZ000000000000001",
tool_name="builtin/file-write",
operation=ChangeOperation.CREATE,
path="src/new.py",
),
],
)
print(cs.creates) # 1
print(cs.paths_changed) # {'src/new.py'}
print(cs.summary()) # {'total': 1, 'creates': 1, ...}
ChangeSetStore
The ChangeSetStore protocol defines the interface for changeset persistence:
class ChangeSetStore(Protocol):
def start(self, plan_id: str) -> str: ...
def record(self, changeset_id: str, entry: ChangeEntry) -> None: ...
def get(self, changeset_id: str) -> SpecChangeSet | None: ...
def get_for_plan(self, plan_id: str) -> list[SpecChangeSet]: ...
def summarize(self, changeset_id: str) -> dict: ...
InMemoryChangeSetStore
The InMemoryChangeSetStore is the M1 implementation that stores changesets in
a plain Python dict. It is suitable for single-process tests and the M1 runtime.
from cleveragents.domain.models.core.change import (
ChangeEntry, ChangeOperation, InMemoryChangeSetStore,
)
store = InMemoryChangeSetStore()
cs_id = store.start("01HXYZ123456789ABCDEF")
store.record(cs_id, ChangeEntry(
plan_id="01HXYZ123456789ABCDEF",
resource_id="01HXYZ000000000000001",
tool_name="builtin/file-write",
operation=ChangeOperation.CREATE,
path="src/new.py",
))
cs = store.get(cs_id)
print(store.summarize(cs_id))