docs: document the on-demand projection warm-up in the compatibility page

The warm-up paragraphs (the lastUser stateVersion bump and the
contextActivity dashboard key) now describe the trigger route, the
one-pass-per-process arm, the migration-refusal skip accounting, and the
deployment shapes that never arm the pass.
This commit is contained in:
Bowen Liang committed 2026-09-17 22:46:53 +08:00
1 parent 73dd36418c
commit bf0bba886f
1 file changed
+2 -2
+2 -2
View File
@@ -71,9 +71,9 @@ The skill-injection category (issue #66) bumps the timeline projection's `stateV
The Agent network card covers the orphaned relatives without waiting for a visit: a session listed without a `contextTimeline` row (composition absent, occupancy only) fetches its slim head from the plugin's `/api/dsh-context/detail` fetch route (mounted through Connection's exact-route registry, behind the same authenticated `/api` fence), which folds the durable log on demand — the node's ring renders the full composition the first time the card opens. The same backfill serves sessions whose cache predates the plugin's installation entirely. Where the route is unavailable (the baseline gate, a connection service without the exact-route registry), the card degrades to the pressure-only occupancy ring as before.
The session cards' last-user-message preview (`lastUser` on the `contextTimeline` head) bumps the timeline projection's `stateVersion` (19 → 20): a stale row can never gain the field while its session is idle (it only lands when a user message folds), so on upgrade every cached timeline row is invalidated and refolded from the durable log. To keep the bump from orphaning idle sessions' rows, the startup warm-up (`src/host/backfill.ts`) now probes BOTH dashboard rows — `contextActivity` AND `contextTimeline` — and cold-refolds every session whose either row is missing or version-stale, so previews (and every other head figure) are exact for the whole session list after the first post-upgrade start. A deployment without the cold-path services degrades to the per-session refold on the session's next activity, the same as pre-warm-up upgrades.
The session cards' last-user-message preview (`lastUser` on the `contextTimeline` head) bumps the timeline projection's `stateVersion` (19 → 20): a stale row can never gain the field while its session is idle (it only lands when a user message folds), so on upgrade every cached timeline row is invalidated and refolded from the durable log. To keep the bump from orphaning idle sessions' rows, the warm-up (`src/host/backfill.ts`) probes BOTH dashboard rows — `contextActivity` AND `contextTimeline` — and cold-refolds every session whose either row is missing or version-stale, so previews (and every other head figure) are exact for the whole session list the first time the dashboard opens after the upgrade. A deployment without the cold-path services — or whose client cannot mount the warm-up's trigger route — degrades to the per-session refold on the session's next activity, the same as pre-warm-up upgrades.
The Context Dashboard (the sidebar-foot panel) reads its `contextActivity` projection — a per-day ledger of billed tokens and completed requests, `stateVersion` 1 — off every session-list row's projection column. A new key is purely additive: no existing cached row is invalidated, but sessions folded before the unit existed (and sessions that predate the plugin entirely, whose `contextTimeline`/`contextHeaders` rows are missing too) have nothing to serve until they next go live. The plugin therefore runs a one-pass warm-up at startup (`src/host/backfill.ts`): for every stored session missing the row it cold-reads the durable log once through the projection cache's own cold-read ladder (`coldSnapshot`), which seeds each unit from its cached rows, folds the remainder, and writes the refreshed checkpoint back — live sessions are skipped (they fold for themselves), unreadable logs are logged and skipped, and a connected browser picks the new rows up on the dashboard's next open (the panel re-pulls the session list). A deployment without the sessionQuery/sessionProjectionCache/sessionPersistence/sessions services simply skips the pass.
The Context Dashboard (the sidebar-foot panel) reads its `contextActivity` projection — a per-day ledger of billed tokens and completed requests, `stateVersion` 1 — off every session-list row's projection column. A new key is purely additive: no existing cached row is invalidated, but sessions folded before the unit existed (and sessions that predate the plugin entirely, whose `contextTimeline`/`contextHeaders` rows are missing too) have nothing to serve until they next go live. The plugin therefore runs a one-pass warm-up on demand (`src/host/backfill.ts`): the dashboard is the rows' only reader, so its panel POSTs the plugin's `/api/dsh-context/backfill` fetch route (the same authenticated `/api` fence as the detail route) the first time it opens, and only then does the host walk the corpus — for every stored session missing the row it cold-reads the durable log once through the projection cache's own cold-read ladder (`coldSnapshot`), which seeds each unit from its cached rows, folds the remainder, and writes the refreshed checkpoint back. The pass runs once per host process (later opens and later POSTs are no-ops); live sessions are skipped (they fold for themselves); a legacy log the running harness refuses to migrate (e.g. a v0 artifact carrying events outside the released migration surface) is permanent — its per-session detail logs at debug and the pass ends with one summary info line, so an unmigratable corpus costs one line per dashboard-open process, not one warn per session per boot; and a deployment whose client never opens the dashboard never cold-reads a thing. A deployment without the sessionQuery/sessionProjectionCache/sessionPersistence/sessions services — or whose connection service lacks the exact-route registry — simply never arms the pass (such a client could not open the dashboard to read the rows anyway).
To force a full refold of an existing session sooner, delete its cached projection row — it is a derived cache and is rebuilt from the durable log: