feat: rebuild reactivity state from store after replay

Add `rebuildReactivityFromStore` to synchronize local reactivity
state with the hydrated variable store. This ensures tag activations
are correctly tracked following a reducer replay.

Also remove the unused `invalidateCompletions` function.
This commit is contained in:
hypercross 2026-07-13 10:34:44 +08:00
parent 6f01a29723
commit 3137970b97
4 changed files with 26 additions and 7 deletions

View File

@ -209,12 +209,6 @@ export function ensureCompletions(): Promise<void> {
return _initPromise;
}
/** Force a re-fetch on the next page load. For runtime, call before invalidate triggers. */
let _invalidated = false;
export function invalidateCompletions(): void {
_invalidated = true;
}
/**
* Reactive hooks for the journal input.
* Returns the current completions state + a convenience `data` extractor.

View File

@ -48,7 +48,7 @@ export { StreamMessageCard } from "./StreamMessage";
export { ComposePanel } from "./ComposePanel";
export { JournalInput } from "./JournalInput";
export { DynamicForm } from "./DynamicForm";
export { useJournalCompletions, invalidateCompletions } from "./completions";
export { useJournalCompletions } from "./completions";
export { dispatchCommand } from "./command-dispatcher";
export type { DispatchContext, DispatchResult } from "./command-dispatcher";
export { parseInput } from "./command-parser";

View File

@ -167,6 +167,27 @@ export function setBase(key: string, value: string): void {
baseValues.set(key, value);
}
/**
* Rebuild local reactivity state (baseValues, activeMods, sourceActivations)
* from the hydrated stream variable store. Must be called after replayReducers
* so that tag activations are correctly tracked for subsequent cascade
* computations.
*/
export function rebuildReactivityFromStore(variables: VariableStore): void {
if (!tagModMap) return;
for (const [key, value] of Object.entries(variables)) {
if (!baseValues.has(key)) {
baseValues.set(key, value);
}
const tag = isTagValue(value);
if (tag && !sourceActivations.has(key)) {
activateTagFromSource(key, tag, variables);
}
}
}
/**
* Compute cascade effects after a variable change.
*

View File

@ -14,6 +14,7 @@ import { createSignal } from "solid-js";
import * as Comlink from "comlink";
import type { StreamMessage } from "../journal/registry";
import { getMessageType, validatePayload } from "../journal/registry";
import { rebuildReactivityFromStore } from "../journal/var-reactivity";
import type { WorkerState, WorkerPatch, SessionManifest } from "../../workers/journal.worker";
import type { JournalWorkerAPI } from "../../workers/journal.worker";
import {
@ -162,6 +163,9 @@ function handlePatch(patch: WorkerPatch): void {
saveRole(patch.state.myRole);
// Rebuild derived state (revealedPaths, variables) by replaying reducers
replayReducers();
// Rebuild local reactivity engine state so tag activations from
// hydrated variables are tracked for subsequent cascade computations.
rebuildReactivityFromStore(state.variables);
break;
}