feat(gui): generic projection value store — host-pushed whole values, higher-seq-wins

The push-model client base (session-projection RFC final): ProjectionValueStore
holds key → {value, seq} per session, seeded by the tail page's projections
block and updated by session/projection frames under one rule — higher seq
wins on both paths (stale baseline cannot overwrite a newer frame; replayed
frames cannot regress; an omitting fresh baseline clears = capability absent);
truncate() drops phantom rows past a subscribed durable baseline. Per-key
identity-stable faces (always defined; absence is an undefined snapshot) feed
useProjection; the renderer contract's projections member becomes faceOf.
12 store specs cover both seq directions, absence, truncation, and batching.
This commit is contained in:
imccyu
2026-07-27 22:01:48 +08:00
parent 1097330df2
commit 531eb7cf0e
5 changed files with 397 additions and 24 deletions
+7 -6
View File
@@ -45,13 +45,14 @@ export interface SessionMaybeProvideInfo {
/** Static plain-member roster; values are undefined with the session. */
props: Record<string, unknown>
/**
* Key-addressed projection-cell sources (the useProjection framework seat,
* session-projection RFC). Unlike `hooks`, the key space is open — cells
* come and go with domain plugins — so the render side binds per resolved
* cell instead of per static roster member. Absent with the session; an
* unresolved key uniformly reads as capability absent.
* Key-addressed projection value sources (the useProjection framework seat,
* session-projection RFC). Unlike `hooks`, the key space is open — values
* arrive from host-computed push frames — so the render side binds per
* resolved key instead of per static roster member. Faces are always
* defined per key (absence is an `undefined` snapshot); the whole member is
* absent with the session.
*/
projections?: { cellOf(key: string): HostObservable<unknown> | undefined } | undefined
projections?: { faceOf(key: string): HostObservable<unknown> } | undefined
}
/** Definite per-session standard props resolved for strict session slots. */