1@README.md 2 3## Notes for agents 4 5- **No hosting words in here.** Never name Cloudflare, celld, wrangler, Durable Objects, R2/buckets or 6 `fetch`/`Request`/`Response` types in this crate, in code or docs, except to say that an adapter is not 7 this crate. The port is Whiskers' own; the adapter adapts to it, not the other way round. If a port 8 seems to need a host's concept, the port is mis-shaped: change the port's language, not its dependencies. 9- **Must build for `wasm32-unknown-unknown`.** No `std::fs`, `std::net`, `std::thread`, `SystemTime` or 10 `Instant`. Check with `cargo check --target wasm32-unknown-unknown -p whiskers-ports` inside 11 `nix develop ~/whiskers`. Dependencies stay at `serde`, `serde_json`, `log` and `whiskers-core`. 12- **`serde_json` has `preserve_order` on purpose.** Stored journal lines keep a device's key order, and 13 every JSON reply of the service is laid out the same on every backend. Do not remove the feature. 14- **A capability is a trait here, its laws in `whiskers-conformance` and its routes in `whiskers-service`.** Adding one touches all 15 three (the README's "Capabilities" section lists the steps). Never write a stand-in port to satisfy a bound, never add a 16 runtime "not configured" branch to a route for a capability the adapter may lack, and never put a new capability only in 17 `Backend`'s supertraits without a `Has…` trait of its own: an adapter must be able to hold it alone. 18- **A contract is a law in `whiskers-conformance`.** Changing a contract means changing its law in the same 19 commit; adding a port means adding its laws and running them against the in-memory adapter and the native 20 one. A law no adapter can fail proves nothing: keep the "caught" tests in that crate. 21- **Make the wrong thing unrepresentable.** Anything that arrives from outside gets a validated newtype with 22 a private field (`DeviceName`, `SafePictureId`, `SpeechLine`...). Errors are enums that say why; a string 23 goes in a `Diagnostic` and is never branched on. Add a variant rather than parse a message. 24- **Rules live in `whiskers-core` or here, not in adapters.** The merge rules, the window arithmetic 25 (`ThinkingLedger`), the day arithmetic (`VoiceDay`) and the page rule (`Page::of`) are shared on purpose: 26 an adapter decides where state is kept and how access is serialised, and adds nothing to the arithmetic. 27- **Logging** follows `crates/CLAUDE.md`: levelled lines, never content. 28- `whiskers-core` also has a `ports` module (`Model`, `Guard`, `Log`...): those are what a *device's* 29 conversation pipeline runs through. These are the *backend's*. They are different layers.