fix(oracle-r4): validate selectedStepId across live refreshes

Oracle r4 'Watch Out For' caught a real edge case: if a backend graph
changes shape while the scenarioId stays the same, the prior
selectedStepId could survive the merge and point at a step that no
longer exists. Two new vitest regressions in state/store.test.ts now
pin the contract:

- refreshLive() resets selectedStepId to the scenario's defaultStepId
  when the prior step no longer exists in the merged catalog
- refreshLive() preserves a still-valid selectedStepId

runLiveFetch() now derives stepStillThere from the merged scenario's
own steps (not the old store) and falls back to defaultStepId when
stale. Same single-set call as before; no extra renders.

Confidence: high
Scope-risk: narrow
Not-tested: real backend definition with step IDs that disappear
mid-session (covered by stub + assertion above)
This commit is contained in:
2026-06-14 00:34:47 +04:00
parent 2e0e4c08e8
commit 49639a0857
2 changed files with 29 additions and 2 deletions
+5 -2
View File
@@ -84,14 +84,17 @@ async function runLiveFetch(
const merged = [...scenarios, ...syntheticScenarios];
const first = merged[0];
const currentId = get().scenarioId;
const currentStepId = get().selectedStepId;
const stillThere = merged.find((s) => s.id === currentId);
const stepStillThere = stillThere?.steps.some((st) => st.id === currentStepId);
const nextScenario = stillThere ?? first;
set({
scenarios: merged,
liveTotals: { workItems: workItems.length, distinctDefs },
liveFetchedAt: Date.now(),
liveLoading: false,
scenarioId: stillThere ? currentId : first?.id ?? currentId,
selectedStepId: stillThere ? get().selectedStepId : first?.defaultStepId ?? null,
scenarioId: nextScenario?.id ?? currentId,
selectedStepId: stepStillThere ? currentStepId : nextScenario?.defaultStepId ?? null,
});
get().pushToast(
"ok",