Files
openchamber/.agents/skills/sync-state-invariants/SKILL.md
T
Bohdan Triapitsyn 68f1c1efe3 docs(agent): streamline guidance and skills
Keep always-on instructions concise and route specialized work through focused skills. Split large skills into progressive references and add dedicated change, desktop, sync, and performance guidance.
2026-07-14 00:45:44 +03:00

4.9 KiB

name, description
name description
sync-state-invariants Use when changing session synchronization, bootstrap or reconnect state, event reducers, polling, optimistic updates, message queues, live activity, ordering/reconciliation, runtime-scoped caches, or directory-dependent session behavior.

Sync State Invariants

Read First

Read packages/ui/src/sync/DOCUMENTATION.md and the nearest owning module documentation before editing.

Sources Of Truth

Classify every input before deriving state:

Input Valid use
Directory child store Live per-directory session/message/status/permission state
Global sessions store Complete global active/archived cache and retention/sidebar coverage
Persisted history/cache Startup continuity and context restoration, never proof of current activity
Optimistic shadow state Temporary UI continuity until authoritative reconciliation

Prefer deterministic authoritative records over heuristics. Derive live behavior from live channels, not historical anomalies.

Failure Is Not Empty

Any authoritative loader whose result can replace, delete, or clear state must distinguish failure from successful empty data.

Use an existing pattern:

  • Throw when an outer logical block can catch and preserve prior state.
  • Return T | null when follow-up work must continue and null exclusively means fetch failure.

Never swallow an SDK/API error into [], {}, or another valid empty success. Verify that callers skip destructive replacement after failure.

Track completeness at the smallest entity/scope. One failed project or directory blocks destructive work for itself, not for unrelated complete scopes.

Live And Historical State

  • Use historical state to restore context, not to infer ongoing execution.
  • Scope delayed-live fallbacks to the active entity and clear them when authoritative state arrives.
  • Do not let stale persisted data keep a fallback active indefinitely.
  • Define field precedence when global and local/live snapshots feed the same view.
  • Use one ordering/rank source for all views of the same entities.

Event Reducers

  • Clone only fields the event mutates; preserve every unrelated reference.
  • Return no change for semantically identical events.
  • Gate scans behind cheap event/entity checks.
  • Coalesce repeated same-entity events without violating ordering.
  • Reject stale async/event completions using generation or authoritative timestamps.
  • Do not widen a narrow fallback to arbitrary historical records.

For streaming-frequency work, also load performance-engineering.

Polling And Bootstrap

  • Preserve rich fields when lightweight polling omits them.
  • Use cheap change detection before heavy per-directory fetches.
  • Treat startup 502/503 as transient with bounded retry/recovery.
  • A retry loop requires a real failure signal; swallowed errors disable retries.
  • Preserve previous authoritative state during transient bootstrap/reconnect failures.

Optimistic Updates

  • Insert optimistic data into the visible store and a separate shadow tracker.
  • Use client-generated IDs accepted and echoed by the server to reconcile in place.
  • Remove optimistic data from both visible and shadow state on failure.
  • Reconcile deterministically on authoritative fetch/event; do not guess from unrelated events.
  • Stabilize callbacks stored in module-level refs to avoid effect loops.

Session And Queue Consistency

  • Capture provider, model, agent, variant, and other send configuration when queueing.
  • Do not re-resolve queued configuration from mutable current state at send time.
  • Preserve server-backed attachments and convert paths at the transport boundary.
  • Pass a directory hint when a newly created session is not indexed yet.
  • Read mutable current directory at call time; never cache it in a long-lived closure.

Cache And Lifecycle

  • Match session-store limits to loaded data before events can trigger trimming.
  • Invalidate message/prefetch/file caches on mutation and session eviction.
  • Key runtime-scoped caches by runtime identity when IDs or paths can collide.
  • Clean optimistic and local cache state after partial failures.

Verification

Cover the relevant lifecycle, not only static state:

  • fresh bootstrap and successful empty result;
  • fetch failure preserving prior state;
  • reconnect/retry and stale completion;
  • repeated/no-op/out-of-order events;
  • optimistic success, reconciliation, and rollback;
  • create, stream, abort, permission, archive/delete, and revisit when session behavior changes;
  • partial multi-directory/project failure;
  • runtime or worktree switch with dynamic directory resolution.

Red Flags

  • Fetch helper catches and returns [].
  • Historical message/session data drives a live spinner.
  • One failed entity blocks or clears all entities.
  • Light polling overwrites fields it did not fetch.
  • Queue reads current model/agent at send time.
  • New session lookup assumes SSE already indexed it.
  • Optimistic data has no shadow entry or rollback.