0.28.0
Wave F of docs/plan/store-waves-f-g-h.md: the storage layer starts becoming entity-runtime's. One runtime version instead of two, one adapter over any of its stores, events that reach the file, a SQLite plan that reopens, and a conformance verb that names what it ran against. The plan and its five stories were accepted, implemented and moved to implemented on recorded evidence the same day.
Added
-
aep-backend-entity: the contract over anyentity_store::Store.EntityBackend<S>is whatSqliteBackendwas — apply inaep-backend-memory, thencommitto the provider with a read expectation, latch on failure, latch covers reads — with the provider as a type parameter. The sixteen suites and the faulty-backend guard run against it overSqliteStoreand over the runtime'sMemoryStore. The next durable backend is a line:EntityBackend<TheirStore>. -
A SQLite plan file now holds its own history. Every accepted command writes one event per affected entity into the store, in the same transaction as the instance: the command's type as the event type, the status before and after, the fields written, and — in the event's
payload— who issued it, when, in which flow, what caused it, and what a status move was decided on. A second process reading the file gets the history; before this it got the instances and an empty log. A refused command writes nothing, a replayed one writes nothing, and the stored events fold back to the stored instance through the runtime's ownrehydrate. -
The pin moved to
entity-runtime0.10.0, which carriesStateProvider::ids— what hydration enumerates with.EntityBackend::overis fallible now, because opening reads. -
protocol conformance --backend memory|markdown|sqlite [--store <path>]. The verb ran the sixteen suites against the in-memory reference backend and nothing else, while its help said so and a story said otherwise. It now runs them against the backend you name —--storesays where a durable one lives; without itsqlitegets an in-memory database andmarkdowna scratch directory, because the suites write — and the report's first line saysran against: …, with aran_againstfield in JSON and YAML. The default staysmemory, so no existing invocation changes meaning;--backend memory --store …is refused rather than ignored. -
A populated SQLite plan is read back on open.
SqliteBackend::openhydrates: every entity with its metadata and history, every relation not since removed, every audit record — a refusal's too — and every applied command, all under the identities the first process stored. A second process sees what the first wrote, continues past it with fresh identities, and recognises a replayed command. The refusal "the database already holds…, and this backend did not write it" is gone with the defect it guarded against. A store holding a row the backend cannot read back refuses to open, naming the row, rather than answering about part of it. Measured over this repository's own plan: 124 artifacts and 241 relations reopen in about 120 ms (debug build); seeding them through the contract took 11.5 s, three SQLite transactions per command.
Changed
-
aep-backend-sqliteis an instantiation.SqliteBackendisEntityBackend<SqliteStore>behind the sameopen,in_memory,latched,lenandis_empty; nothing a caller writes changes. Its conformance tests moved to the adapter's crate —cargo xtask guardsis what says they moved rather than copied — and what stays inaep-backend-sqliteis what only a file can show: the row read back through a second handle, and the foreign-row refusal. -
One
entity-runtime, at0.9.1. Two were compiled into this workspace:entity-core0.5.2 underaep-backend-markdown, which decides everyprotocol artifact move, and 0.8.0 underaep-backend-sqlite—cargo tree -i entity-coreanswered "specification is ambiguous". The tag is now declared once, in[workspace.dependencies], for all threeentity-*crates, and a new gate step,dep-check(cargo xtask deps), fails naming both versions if that ever splits again.What the move-deciding kernel gains from 0.5.2 → 0.9.1:
DomainEventrecordsfrom_state,to_stateand the fields itchanged(their R-89), andentity_core::rehydratefolds an instance from its events, refusing any event whose transition the definition does not declare — including a forged creation event, closed in their 0.8.0 (R-97). Every ladder verdict is unchanged:tests/kernel_equivalence.rspasses against the single version, and nothing you type changes.