docs: capture today's Pres Mgmt config sync lessons for future agents
- BOOTSTRAP__AI_Agent_Quickstart.md: new category 9 under Common Mistakes pointing to today's incident (local/remote config sync pitfalls) - REFERENCE__Common_Agent_Mistakes.md: three new entries — 16) local "shadow field" silently bypasses an admin-synced master field 17) SWR await after a write does not mean dependent caches are fresh 18) conditional/stateful sync gates are effectively undebuggable - PROJECT__Stores_Svelte5_Migration.md: updated the canonical Migration Pattern example to stamp __version in the serializer (the old example silently didn't, which is exactly what caused the leads_loc/pres_mgmt_loc bugs fixed today); flagged badges_loc/launcher_loc/events_auth_loc as not yet fixed (dormant, not harmful) and idaa_loc as the next migration that should get this from day one - TODO__Agents.md: cross-referenced today's Pres Mgmt config sync overhaul in the LCI October restoration section for context, without touching the open items in that list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -72,19 +72,49 @@ export const badges_loc_defaults: BadgesLocState = { ... };
|
||||
```
|
||||
|
||||
### 2. Store file (`*.svelte.ts`)
|
||||
|
||||
**Updated 2026-06-16 — stamp `__version` in the serializer.** The original pattern below (bare
|
||||
`JSON.stringify`) looked fine but has a real failure mode: `store_versions.ts`'s
|
||||
`_check_and_wipe()` compares a `__version` field *inside* the stored JSON, and a bare
|
||||
`JSON.stringify` never writes one. Two consequences were found in production code:
|
||||
`pres_mgmt_loc`'s version bump was silently a no-op (never wired into `_check_and_wipe` at
|
||||
all), and `leads_loc`'s *was* wired in, so `parsed?.__version` was always `undefined` —
|
||||
always failing the comparison — wiping `ae_leads_loc` on **every single page load**. Both
|
||||
fixed 2026-06-16. `badges_loc`, `launcher_loc`, and `events_auth_loc` still use the old bare
|
||||
pattern below and are **not yet wired into `_check_and_wipe`** — not actively harmful (the
|
||||
wipe never runs), but apply this fix before wiring any of them in.
|
||||
|
||||
```ts
|
||||
import { PersistedState } from 'runed';
|
||||
import { badges_loc_defaults } from './ae_events_stores__badges_defaults';
|
||||
import { AE_BADGES_LOC_VERSION } from './store_versions';
|
||||
|
||||
export const badges_loc = new PersistedState('ae_badges_loc', badges_loc_defaults, {
|
||||
serializer: {
|
||||
serialize: JSON.stringify,
|
||||
// Merge with defaults so new fields added after first session get their defaults.
|
||||
deserialize: (raw: string) => ({ ...badges_loc_defaults, ...JSON.parse(raw) })
|
||||
// Stamp __version on every write so store_versions.ts's _check_and_wipe() can
|
||||
// detect a breaking schema change and clear stale browsers on next load. This
|
||||
// import also guarantees store_versions.ts's wipe side-effect runs before this
|
||||
// PersistedState reads from localStorage (ES module execution order).
|
||||
serialize: (value) =>
|
||||
JSON.stringify({ ...value, __version: AE_BADGES_LOC_VERSION }),
|
||||
// Merge with defaults so new fields added after first session get their defaults,
|
||||
// and strip __version back out so it doesn't pollute the typed state object.
|
||||
deserialize: (raw: string) => {
|
||||
const { __version, ...stored } = JSON.parse(raw);
|
||||
return { ...badges_loc_defaults, ...stored };
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Then in `store_versions.ts`'s startup block:
|
||||
```ts
|
||||
_check_and_wipe('ae_badges_loc', AE_BADGES_LOC_VERSION);
|
||||
```
|
||||
|
||||
See `ae_events_stores__pres_mgmt.svelte.ts` and `ae_events_stores__leads.svelte.ts` for the
|
||||
two real, currently-correct examples of this pattern.
|
||||
|
||||
### 3. Consumer syntax
|
||||
```ts
|
||||
// Import (note .svelte extension, not .svelte.ts):
|
||||
@@ -116,6 +146,9 @@ badges_loc.current = { ...badges_loc_defaults };
|
||||
1. **`idaa_loc` → PersistedState** — Highest priority for IDAA stability. Promotes `novi_uuid/verified`,
|
||||
`archives`, `bb`, `recovery_meetings` sub-objects to their own stores following the same pattern.
|
||||
Primary benefit: eliminates the IDAA "Access Denied" corruption from `ae_loc` bootstrap writes.
|
||||
Use the `__version`-stamping serializer from the start (see Migration Pattern above) and wire
|
||||
it into `_check_and_wipe()` immediately — `idaa_loc` holds auth state, so a real wipe-on-schema-
|
||||
change matters more here than anywhere else this pattern has been applied so far.
|
||||
|
||||
2. **`ae_loc` → PersistedState** — Largest scope (~every route in the app). Defer until after
|
||||
`idaa_loc` is done. Consider extracting `auth_loc` (the identity/permission fields) as the
|
||||
|
||||
Reference in New Issue
Block a user