{"slug":"state-management-decision-review","title":"state-management-decision-review","summary":"Reviews whether data is correctly classified as server state, client state, or derived state, and whether the resulting store/cache design (query keys, invalidation, optimistic-update rollback, SSR instantiation, selector shape) avoids duplication, stale-data bugs, and unnecessar","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-10-05T21:52:17.215056Z","repo":{"url":"https://github.com/VincentChuWaiChow/vanguard-frontier-agentic","stars":24,"forks":3,"license":"Apache-2.0","updatedAt":"2026-10-05T13:00:24Z"},"bodyHtml":"<hr>\n<h2>name: state-management-decision-review\ndescription: Reviews whether data is correctly classified as server state, client state, or derived state, and whether the resulting store/cache design (query keys, invalidation, optimistic-update rollback, SSR instantiation, selector shape) avoids duplication, stale-data bugs, and unnecessary re-render cascades.\nallowed-tools: Read Grep Glob\nmetadata:\nauthor: \"github: VincentChuWaiChow\"\nversion: \"0.1.0\"\nupdated: \"2026-07-02\"\ncategory: architecture</h2>\n<h1>State Management Decision Review</h1>\n<h2>Purpose</h2>\n<p>Review a proposed or existing state-management design without re-litigating routing/URL-state ownership, API contract shape, or SSR hydration-mismatch diagnosis in every response. Most state-management bugs trace back to a single category error: treating server-owned data (fetched from an API, subject to staleness, shared across users or tabs) as if it were client-owned data (form input, UI toggles, ephemeral interaction state). Once that error is made, every downstream decision — where to put the data, when to refetch it, how to invalidate it, whether an update needs a rollback path — compounds it. This skill exists to catch that root-cause error early and to evaluate the caching/invalidation strategy and store topology against two measurable failure modes: stale/duplicated data and unnecessary re-render cascades.</p>\n<h2>When to use</h2>\n<p>Use this skill when the user asks to:</p>\n<ul>\n<li>review a PR that introduces new fetching, caching, or store logic,</li>\n<li>diagnose a \"stale data after save\" or \"the list didn't update after I created/deleted an item\" bug report,</li>\n<li>diagnose a \"page freezes while typing\" or \"every keystroke re-renders half the tree\" performance complaint tied to a shared store,</li>\n<li>evaluate a proposal to introduce a new state-management library or a new global store,</li>\n<li>audit an existing store for entities that duplicate or conflate server-fetched data with client-only data.</li>\n</ul>\n<p>Do not use this skill for:</p>\n<ul>\n<li>routing/URL-state ownership review (filters, pagination, tabs that should be reconstructable from the URL) — that is <code>routing-navigation-review</code>,</li>\n<li>BFF/API contract shape, request/response schema, or endpoint design review — that is <code>api-integration-contract-review</code>,</li>\n<li>SSR hydration mismatch diagnosis unrelated to store/query-client serialization (server/client markup divergence) — that is <code>ssr-hydration-streaming-diagnosis</code>. This skill only covers SSR store/queryClient <em>instantiation</em> (per-request vs. shared singleton), not hydration mismatch mechanics.</li>\n</ul>\n<h2>Context7 Documentation Protocol</h2>\n<ul>\n<li>Resolve <code>/tanstack/query</code> with <code>resolve-library-id</code> before asserting any caching default (<code>staleTime</code>, <code>gcTime</code>, <code>refetchOnWindowFocus</code>) — these are documented defaults, not universal truths, and the repo's installed major version governs behavior. <code>staleTime</code> defaults to <code>0</code> (query is considered stale immediately after any successful fetch) and <code>refetchOnWindowFocus</code> defaults to <code>true</code>; do not assume the reviewed repo has left these at default without checking the <code>QueryClient</code> construction site.</li>\n<li>Before flagging an optimistic-update pattern as missing rollback, call <code>query-docs</code> on <code>/tanstack/query</code> for \"optimistic updates\" to confirm the current documented shape (<code>onMutate</code> cancels in-flight queries, snapshots prior data, returns it as mutation context; <code>onError</code> restores the snapshot from that context; <code>onSettled</code> invalidates). Do not invent an alternate rollback API.</li>\n<li>Resolve <code>/pmndrs/zustand</code> with <code>resolve-library-id</code> before recommending a selector-based re-render fix. Confirm current <code>useShallow</code> import path and behavior via <code>query-docs</code> before telling a user to add it — the import path (<code>zustand/react/shallow</code> vs <code>zustand/react</code>) and default <code>Object.is</code> comparator behavior are version-sensitive.</li>\n<li>Before approving a <code>persist</code> middleware usage that touches auth/session data, call <code>query-docs</code> on <code>/pmndrs/zustand</code> for \"persist middleware\" to confirm current <code>partialize</code> and <code>storage</code> options exist and are the documented way to exclude sensitive fields — do not assume a field-exclusion API without checking it.</li>\n<li>If Context7 is unavailable for either library, fall back to the <code>official_docs</code> URLs in this skill's <code>metadata.json</code> and label every caching-default or API-shape claim <code>documentation-based, verify against installed version</code> rather than stating it as settled fact.</li>\n<li>Read <code>package.json</code> first to confirm which server-state library (if any) is actually installed and its major version. Do not recommend a fix keyed to an API that the installed major version does not have.</li>\n</ul>\n<h2>Lean operating rules</h2>\n<ul>\n<li>Build the entity classification table before evaluating anything else. Every piece of state in scope must land in exactly one bucket: <strong>server state</strong> (fetched from an API/DB, has a remote source of truth, can go stale, is potentially shared across users or tabs), <strong>client state</strong> (exists only in this session — form inputs before submit, modal open/closed, hover/focus, drag position), or <strong>derived state</strong> (computed from server and/or client state — never independently stored). Do not evaluate caching strategy before this table exists; the table is the review's foundation, not an afterthought.</li>\n<li>Any entity classified as server state that is held in <code>useState</code>/<code>useReducer</code>/a plain client store instead of a query/cache library is a category-error finding, not a style note — it is the root cause of most manual-refetch and stale-cache bugs the skill exists to catch.</li>\n<li>Any entity classified as derived state that is independently stored (rather than computed on read, in a selector, or in a memoized derivation) is a duplication finding — it can drift from its inputs and is a second, harder-to-find source of staleness.</li>\n<li>For every server-state entity, require an explicit, inspectable cache key and an explicit invalidation trigger (what mutation, what event, or what time-based policy causes a refetch). \"It'll refetch eventually\" without a named trigger is not an answer.</li>\n<li>For every optimistic update (a mutation that updates the UI before the server confirms), require a paired rollback path (<code>onError</code> restoring a snapshot taken in <code>onMutate</code>) per the current documented pattern. An optimistic update with no rollback path is a HARD STOP, not a note — it means a failed mutation leaves the UI showing state the server never accepted, with no correction mechanism.</li>\n<li>For SSR applications, require that the query client and any global store be instantiated per-request (inside component state / a request-scoped factory), never as a module-level singleton created once at import time. A module-level singleton in SSR is a HARD STOP — it is a cross-request/cross-user data-leak vector, not merely a performance concern.</li>\n<li>Do not accept a re-render-cascade \"fix\" (memoization, selector narrowing, splitting a store) without profiler evidence (a before/after render count or a flame-graph excerpt). A fix justified only by \"this should reduce re-renders\" is speculation, not a verified finding — require the evidence or explicitly flag it as unverified.</li>\n<li>Do not recommend introducing a new global store as the default fix for a data-caching problem that a server-state library already solves (deduping, background refetch, invalidation). Naming a new store as the fix for a caching bug is itself a finding to push back on.</li>\n<li>Never execute, build, or run application code as part of this review; this is a static-review skill (Read/Grep/Glob only). Profiler evidence must come from the user/PR description, not from live reproduction performed by this skill.</li>\n<li>Treat any store or persisted-storage design that writes auth tokens, session identifiers, or PII to <code>localStorage</code>/<code>sessionStorage</code> (directly or via a <code>persist</code> middleware without a <code>partialize</code> exclusion) as a security-relevant finding requiring explicit encryption/expiry/justification — do not wave it through as a caching-pattern detail.</li>\n</ul>\n<h2>References</h2>\n<p>Load these only when needed:</p>\n<ul>\n<li><a href=\"references/workflow-and-output.md\">Review workflow and findings contract</a> — use for the step-by-step review procedure, the classification/decision tree, and the required output shape.</li>\n<li><a href=\"references/server-state-caching-and-invalidation.md\">Server-state caching and invalidation</a> — load only when reviewing query-key design, invalidation triggers, optimistic-update rollback, or SSR query-client instantiation.</li>\n<li><a href=\"references/client-store-topology-and-rerenders.md\">Client-store topology and re-renders</a> — load only when reviewing store-slice design, selector shape, <code>useShallow</code> usage, or a reported re-render-cascade / typing-jank complaint.</li>\n</ul>\n<h2>Response minimum</h2>\n<p>Return, at minimum:</p>\n<ul>\n<li>the entity classification table (server / client / derived) for every entity in scope,</li>\n<li>for each server-state entity: its cache key, its invalidation trigger, and (if applicable) its optimistic-update rollback path,</li>\n<li>for each client-store slice reviewed: its selector shape and whether it is exposed to unnecessary re-render risk,</li>\n<li>for bug diagnosis: a root-cause statement distinguishing stale-cache vs. race-condition vs. re-render-cascade vs. normalization/duplication bug — not a vague \"state management issue\",</li>\n<li>evidence level per finding (<code>repo evidence</code>, <code>documentation-based</code>, or <code>inference</code>),</li>\n<li>verdict (approve / approve-with-notes / block), with HARD STOPS (missing rollback, SSR singleton) called out separately from lower-severity notes,</li>\n<li>open questions or scope the review could not cover (e.g., \"re-render claim requires profiler evidence to confirm\").</li>\n</ul>\n","files":[{"path":"metadata.json","sizeBytes":1957,"isText":true},{"path":"references/client-store-topology-and-rerenders.md","sizeBytes":8337,"isText":true},{"path":"references/server-state-caching-and-invalidation.md","sizeBytes":8949,"isText":true},{"path":"references/workflow-and-output.md","sizeBytes":6392,"isText":true},{"path":"SKILL.md","sizeBytes":9585,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-10-05T21:59:01.379706Z","sha256":"0373CB33DECDD8E1CA9D3E908FBA06B41C5A9F2B86425E5D03321BDCA654AEF4","sizeBytes":15655},"review":null,"source":{"repositoryUrl":"https://github.com/VincentChuWaiChow/vanguard-frontier-agentic","path":"skills/frontend/state-management-decision-review","license":"Apache-2.0","commit":"febe32a08e78fd06b1e466187410d673f1958d87","subtreeSha":"80B1B10DF0FC0DDD6FD1487C51B322F4BAA5BC113917F4DF00799DC3ABB52AED","lastSyncedAt":"2026-10-05T21:51:58.639905Z"},"reviewedAt":"2026-10-05T22:12:57.682274Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/tree/master/skills/frontend/state-management-decision-review"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install vincentchuwaichow-vanguard-frontier-agentic@llmmart"},{"target":"git","command":"git clone https://github.com/VincentChuWaiChow/vanguard-frontier-agentic.git"}]}