Skip to main content

ADR: Companion is for every member (default ON, per-member disable)

Date: 2026-07-20 · Status: Accepted · Type: product/scope — reverses a prior decision.

Decision

The companion creature ("the doubling") is available to every household member, enabled by default, and any member can disable their own from Settings.

This reverses the 2026-07-18 "per-child" scoping (companion spec §3 + the final-review polish commit e9717ba, which gated CompanionLayer to isChild). Owner directive (2026-07-20): "have it on by default for parents and they can disable."

Why

  • Finch — the product we emulate — is an adult app. Adults bonding with a forgiving companion is the proven pattern, not a hypothesis.
  • ND kids usually have ND parents (ADHD heritability ~74%); the parent in our target household often needs the same dopamine-timed loop and forgiving presence.
  • It models co-regulation as a family practice — a kid seeing a parent tend their own creature after a chore is the ND-affirming thesis in one image.
  • "Deeper, not wider": same loop, same register, same screen — just more members covered. No new surface; no Picniic risk.
  • The data layer was already member-scoped (companion final-review finding M6): schema, CompanionService, dewdrops, and RLS never encoded "child". Only the presentation mount was child-gated. So this is a cheap, clean reversal.

What changes (presentation only — no migration)

  1. Ungate the mount. CompanionLayer mounts for the authenticated member when the companion is enabled, regardless of MemberKind (was: if (isChild)). Keyed on member id as before (a member switch remounts + reloads).
  2. A per-member "companion enabled" preference, default true, toggled in the More/Settings surface every member already has.
  3. Update the tests committed on 2026-07-19 that asserted "adult ⇒ not mounted": they flip to "any member ⇒ mounted by default" + a new "disabled ⇒ not mounted" case. The member-switch reload test stays valid.

Micro-decisions (controller defaults, owner may redirect)

  • Storage: device-local SharedPreferences, keyed by member id, default ON — mirrors the existing celebration_intensity + appearance prefs (also device-local). Cross-device sync of the toggle is deferred (a member who disables on one device still sees it on another). Upgrade to a synced member setting later if it matters.
  • Scope: self-disable only. Each member toggles their own companion. A parental override to force-disable a young child's companion is a separate parental-control feature — future, not this slice.
  • Copy: unchanged. The creature/sheet copy ("Name me"; stages Seedling / Sprout / Bloom) is plant-growth-neutral and reads fine for an adult. No adult-specific register needed for v1.

Unchanged / preserved

  • Disable is purely presentational: a disabled member's companion row, dewdrops, and cosmetics persist untouched; re-enabling restores exactly what was there.
  • All companion invariants hold (separate non-convertible dewdrops economy; completions-sourced earning; dual-gate RLS; forgiving presence). This slice touches no SDK domain rule, no schema, no RLS.