Drop revisions: items carry their content, one full-state history for every kind #320
Description
Data model change from #309 (Decision 6), split out of #315 so that the v2 tool surface (#310) did not wait for a migration. v2 is live and maps version onto revisions internally; this task removes the revision tables. Start with #309, section "Continue here".
Where the mapping lives today
IItemHistory / RevisionItemHistory in src/Conderis/Services/Items/ItemHistory.cs: Current, Versions, Read and RevisionFor number the published revisions of a memory, page or the instructions along the base-revision chain (with IgnoreQueryFilters, counting privacy-locked revisions so numbers stay stable). ItemStoreTools, ItemReadTools and ItemActionTools use it for version checks, history, reading an earlier version and single-version deletion. Tasks already use their Version column and TaskHistoryEntry.
Precondition: memory proposals off draft revisions
Memory proposals still run on revisions: ProposalService.Create stores a DraftRevisionId for memory creates, KnowledgeService.Store writes a MemoryRevision with Status = pending, and ReviewInTransaction publishes it. Move these paths to ChangesJson proposals first, so that no pending revision is created anywhere and the revision tables hold only published states. Web moderation and item_get with ref: proposal:<id> must show the same content afterwards.
Work
- Memory, page and instruction content moves onto the item (memory: title, summary, detail, tags; page: title, content; instructions: content), as tasks already carry theirs.
- One history table for every kind: item kind and id, version, full content as JSON, author, agent, time, and the names of the changed fields computed at write time. Entries are never modified.
- Every content change increments
Versionand appends a history entry; moves do not (#309 Decision 7). - Migration: published revision content onto the item; existing revisions become history entries numbered as
RevisionItemHistorynumbers them today, so versions agents already hold keep their meaning; proposals derivebaseVersionfrombaseRevisionId(the column already exists);TaskHistoryEntryfield changes replayed into full states;ProjectItemRelation.SourceRevisionIdandPrivacyDeletionRequest.RevisionIdre-pointed to item and version. - Web: history, diff, moderation compare and single-version privacy deletion read from the new history.
- Remove
MemoryRevision,DocumentRevision,ProjectInstructionRevision, everyPublishedRevisionIdcolumn andRevisionItemHistory; the v2 tools read versions from the new history directly. The tool descriptions do not change, soV2Prototypeand the budget stay as they are. - Note storage: full states duplicate page text per version. Record the size of the largest project's history after migration; if it matters, keep full states but compress the content column.
Acceptance
- The history views in the web app look and read as they do today: the task history still shows which field changed from what to what and by whom; memory, page and instruction history still show each version with its text and author. Verified with before/after screenshots of the same items.
- Every earlier state of a memory, page, task and the instructions is readable by version after the migration and matches what history showed before; version numbers are the same before and after.
- No revision id remains in code, MCP responses or web addresses.
- Migrations tested on SQLite and checked against SQL Server LocalDB (#283), including a project with pending memory proposals created before the migration.
- Deployed after the owner agrees (#282); the system guide needs no change unless agent-visible behaviour changes.