whiskers.git / CLAUDE.md
1@README.md
2
3## Notes for agents
4
5- **The user of this product is a young child.** Every conversation is logged and visible to the
6  parents; that is a requirement, not an option to trade away. Nothing reaches the child without
7  passing the guard. A failure of the model, the guardrail or the network ends in a safe spoken
8  fallback, never in silence or raw error text.
9- **Never log content.** Nothing the child or Whiskers said, no memory facts, no summaries, and not
10  the child's name. Log lengths, counts, ids, durations and whether a profile is set.
11- **The child is a profile, never a literal.** Name and age live in `HouseholdConfig::child`
12  (`whiskers-core/src/profile.rs`) and reach prompts and the guard only through `Audience`. Do not
13  write a name, an age or a pronoun for the child into code, tests, fixtures, docs or comments;
14  test fixtures use `Ada`, age 6. With no profile the guard assumes the youngest supported age
15  (`Age::YOUNGEST`): a missing profile must never be the loose case.
16- **Nothing identifying goes in tracked files.** No family details, hostnames, IPs, device serials,
17  user names, personal paths or secret names: they are build properties and environment variables.
18  `tools/check-private.sh` enforces a deny-list kept in the gitignored `.private-terms`; run it
19  before committing. It also checks commit messages (`--message`) and every unpushed commit (`--push`): the repository is served in full through the code host, so a term in an old commit or a message is as public as one in a file; the hk hooks run both. Never run a push without it, and do not pipe its output (a pipe hides the exit status). Operator-private notes belong outside this repository.
20- **No non-native user interface.** Rust core, Kotlin shell with Jetpack Compose. Logic belongs in
21  the core; the shell draws and listens.
22- **Jev decides whether a message is allowed; a model writes the parents' summary.** Shared Jev
23  client code lives in `third-party/jevcrates` (a submodule); do not write a second client here.
24- **Measure on the device before designing around it.** Speech recognition, the child profile and
25  the Fire OS version differ per device. Do not assume a Google service exists on Fire OS.
26- **Pushing is the owner's call**, per push.
27- **`mise.toml` is the one place for tool versions, environment variables and tasks.** Nix is an optional wrapper (`flake.nix` provides mise and native libraries and packages the service); it holds no version. Anything that must repeat a version (a Cargo pin, the Gradle SDK levels, `hk.pkl`) is checked by `tools/check-versions.sh`. A README tells people to run `mise run <task>`, never cargo, gradle, adb or nix directly: add the task.
28- **Nobody is required to have nix.** Do not write a script, task or doc that needs it, and do not make `nix` the first command in a README.
29- **No banner comments.** A comment is read as markdown on the code host, so a ruled or dashed heading is noise there. Write `// ## Title` (or `# ## Title`) for a heading, or nothing. `tools/check-banners.sh` fails on the lines a commit adds (an hk pre-commit step); `mise run check-banners` lists every one in the tree.