6247585b66
PR-1 'core' of #370: introduces page_history.kind ('manual'|'agent'|'idle'| 'boundary'; legacy null = autosave) and rebuilds the snapshot triggers around a three-tier intentionality model. Draft durability (pages/ydoc hocuspocus autosave) is unchanged; only the frequency and labelling of history points change. - Migration 20260705T120000: page_history.kind nullable varchar(20), no default. - Manual Save: one stateless 'save-version' path for human AND agent; kind is derived SERVER-SIDE from the signed context.actor (never the payload), readOnly connections rejected, the fresh ydoc runs through the existing store path (no REST race), then broadcasts version.saved. - Idle-flush: trailing debounce (one BullMQ job per page, remove-then-readd) with IDLE_INTERVAL_USER=60m / AGENT=15m AND a max-wait ceiling (IDLE_MAX_WAIT_USER=10m / AGENT=5m) so a continuous editing session can't starve the autosnapshot (review round-1 WARNING). - Boundary: generalized from the user→agent special-case to ANY lastUpdatedSource transition (user↔agent↔git), same isDeepStrictEqual gate — covers git-sync free. - Removed the agent delay=0 fast path and the old HISTORY_FAST_* constants; the agent joins the common idle pipeline. - Promote-not-dup: a manual save on unchanged content promotes the latest autosave's kind in place (or no-ops if already manual) instead of duplicating a heavy content row. - Client: mod+S hotkey + menu button (hidden when readOnly), history-panel kind badges, dimmed autosaves, a 'versions only' filter (indices map to the full list so diff/restore still target the true previous snapshot), live refresh on version.saved. Internal review: APPROVE-with-suggestions; the round-1 WARNING (idle starvation) is fixed here via the max-wait ceiling, and the generalized-boundary + ceiling behaviours are pinned with new tests (115 collab/repo specs green, server tsc 0). Deferred to later PRs: shares.published_mode (PR-2), the save_page_version MCP tool + role prompts (PR-3), actor='git' wiring into #359 (PR-4). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
29 lines
1.2 KiB
TypeScript
29 lines
1.2 KiB
TypeScript
/**
|
|
* #370 — page-version stateless wire formats. Kept in one place so the client
|
|
* emitter (Save hotkey / button) and the client listener (page-editor) agree
|
|
* with the server (PersistenceExtension) on the message shapes.
|
|
*/
|
|
|
|
/** Client → server: "save a version now". The server derives the tier
|
|
* (manual/agent) from the signed connection actor, never from this payload. */
|
|
export const SAVE_VERSION_MESSAGE_TYPE = "save-version";
|
|
|
|
/** Server → all clients: a version was saved (or promoted / already existed). */
|
|
export const VERSION_SAVED_MESSAGE_TYPE = "version.saved";
|
|
|
|
export interface VersionSavedMessage {
|
|
type: typeof VERSION_SAVED_MESSAGE_TYPE;
|
|
historyId: string;
|
|
kind: "manual" | "agent";
|
|
/** True when the latest snapshot was already a manual version (a no-op save). */
|
|
alreadySaved: boolean;
|
|
}
|
|
|
|
/**
|
|
* Cross-component coordination flag so only the client that pressed Save shows
|
|
* the confirmation toast, while every other client silently refreshes its
|
|
* history panel on the broadcast. A module-level ref avoids stale-closure
|
|
* pitfalls in the editor's long-lived stateless handler.
|
|
*/
|
|
export const saveVersionPending = { current: false };
|