whiskers.git / crates / CLAUDE.md

For agents, on top of README.md, which they read first.

Notes for agents

  • One crate per capability; a new adapter is a sibling crate, never an edit to whiskers-core. The core names ports, not vendors.
  • Build with Cargo for now. The estate default for Rust is Buck2 (see ~/dashboard); that move is open, so do not add a BUCK file ad hoc.
  • The backend is ports and adapters. whiskers-ports (the interface), whiskers-service (the routes' logic) and whiskers-conformance (the suite) must build for wasm32-unknown-unknown: mise run check-wasm. A new host is a new adapter crate that passes the suite, never an edit to the ports to suit it.
  • Adding a capability = a trait + its laws + its routes, in that order, across three crates: the Has… trait in whiskers-ports (and in Backend's supertraits), the fixture trait and Suite method in whiskers-conformance, the route type in whiskers-service (plus Service::complete, the Complete alias and EVERY_ROUTE). An adapter implements only the Has… traits for ports it really holds and is given only the routes it can serve: no stand-in port, no runtime "not configured" for a capability that is simply absent (the compiler refuses the route). See whiskers-ports/README.md.
  • Toolchain is not on PATH. Use nix shell nixpkgs#cargo nixpkgs#rustc nixpkgs#gcc -c cargo test.

Logging convention

A correct function leaves a trace; bugs must be debuggable from the logs alone. Every crate uses the log facade (log::debug! etc.; in whiskers-core write ::log::debug! or use ::log::..., because the crate has its own module called log). The one logger is whiskers_core::logging::init(tag), called first in whiskersd, whiskers-cli and (as init_logging()) from the Kotlin shell via whiskers-ffi. It writes 2026-10-04T18:25:51Z LEVEL target: message to stderr, or to logcat under the tag whiskers-core on Android, and it logs panics (location only).

  • Level is picked with the WHISKERS_LOG environment variable: error, warn, info (default), debug, trace, off.
  • error: something failed and the turn, request or save was lost. warn: a fallback was taken, a request was refused or a degraded path was used. info: state transitions (turn begins/ends, sync start/finish with counts, merges, budget and time-limit decisions, every request). debug: entry to non-trivial functions with ids, lengths and counts. trace: hot paths (per-tick, per-touch, per-append).
  • Log every error path with its context before it is returned or swallowed. Pure tiny getters need no line.
  • Never log content. This is a young child's private data, and the child's name is part of it. No message or reply text, no facts, no summaries, no API keys, no PIN hash (log "pin set = true"), no URLs that carry secrets or ids that act as one (ElevenLabs voice id). Log lengths, counts, ids of facts and pictures, statuses and durations instead. Error values from other systems are logged as they come; do not build one out of her words.