Files
cleveragents-core/docs/reference/changeset_model.md
T

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))