# capsite working rules Applies to AI agents working in `capsite/` (goal tree + how-to-run: [capsite-checklist.md](capsite-checklist.md); background: [the capsite notes](capsite-notes.md); workspace-wide policy: [AGENTS.md](../AGENTS.md) — points to the workspace skills, incl. commit trailers). ## Dev servers are the user's job The assistant never starts, stops, or restarts long-running dev servers (`wrangler dev`, `pnpm dev`/`astro dev`). The user runs them and owns the terminals; the assistant observes via `.tmp/capsite.script` (the `script` capture; use `watchme`). One-shot codegen (`wrangler types`), linters, typechecks, and tests are fine. ## Durable state: be LOUD and conservative about breaking changes Persistence is a big deal here: DO ids (cache ids, webapp ids, public ids) are headed toward representing real-world assets. A change that leaves existing stored state unreadable, unreachable, or differently interpreted is a **breaking change**, even in dev. - **Before** making it, say so, prominently: what stored state breaks, why, and the options (migrate, stay compatible, or reset). Get the user's go-ahead; don't discover it after the fact. - Prefer compatibility: read old shapes, add fields rather than repurpose them, migrate in place (schema steps like `SCHEMA_V1` → `V2`). - No silent resets. "Wipe `.wrangler/state`" is a last resort the user chooses, never the default advice. - Cover it with a test: old-shape state in, current code reads it. (Prompted 2026-10-07: making `PublicCache` fetch through its own wiring left public caches created by the earlier `ingest` code unwired — a 502, and no way back through publish.) ## Secrets discipline Worker secrets never in source or wrangler config. `.dev.vars` (gitignored) locally; `wrangler secret put` deployed. Since the 1c cache evolution, no worker secret is needed at all: the cookie lives only in the webapp DO's storage; the webapp-instance id rides the cache DO's wiring; the cache id is a user-held capability (password manager / per-POST paste). Error messages must not contain header or param values (they cross RPC as exceptions and land in logs); URLs appear query-stripped. ## Keep config types generated Run `wrangler types` after any wrangler.jsonc change (`worker-configuration.d.ts` is generated, gitignored; hand-rolled `cloudflare:workers` shims drift and gave red squiggles).