product

Family Wall — JQ voice actions ("do it", not just "ask")

Status: ✅ BUILT (2026-07-18, migration 539) — see INDEX.md → "JQ voice actions + device identity + reminders". This doc is the original design; the shipped shape matches it (device identity location_kind/owner_member_id, the attribution rule, family_reminders, the pure action detector + LLM fallback, the ask-who flow). Built on the on-wall-editing PR (#1393, migration 538).

The ask

Today "Ask JQ" on the wall is read-only — it answers questions grounded in the wall's current content (family-wall-ask.ts + the deterministic pre-filter family-wall-prefilter.ts). Make it act: "add milk to the shopping list", "we're having tacos tonight", "leave a note that grandma visits at 5", "remind Ada to pack her cleats".

Foundation: wall device identity (shared vs. personal)

Both JQ actions and the intercom need to know whose wall this is. New per-wall settings on family_wall_displays:

  • location_kind text'shared' (kitchen/living-room, default) | 'personal' (a bedroom wall belonging to one member).
  • owner_member_id uuid — for 'personal' walls, the family_members.id this wall belongs to. NULL on shared walls.

Owner sets both in wall settings. (location_kind is also the intercom's shared-vs- bedroom signal + quiet-hours anchor — one column, two features.)

Attribution rule (owner-specified)

When an action needs a who (a reminder/task assigned to a person):

  • Personal wall (location_kind='personal') → auto-attribute to owner_member_id. No prompt. "Remind me to…" just works for that member.
  • Shared wall → JQ asks "who's this for?", lists the family members (voice or tap), and attributes to the chosen member.

Actions with no "who" (shopping item, tonight's dinner, a general note) never prompt — they're household-shared already.

Action taxonomy (v1)

Utterance intentExecutesNeeds "who"?
add <item> to shoppingshoppingAddFromWall (#1393)no
set/what's for dinner <meal>mealSetFromWall (#1393)no
leave/post a note <text>noteAddFromWall (#1393)no
remind/assign <who?> <task>family_reminders (new)yes

Reminder/task model (new — the one net-new table)

A one-off, member-attributed reminder — deliberately NOT a recurring family_routine (those stay the chore-chart system; the user already deferred wall-created routines).

family_reminders:

  • id, parent_user_id (family owner), family_member_id (the assignee — the "who"),
  • text (≤200), due_at timestamptz NULL (optional; JQ parses "tomorrow", "at 5"),
  • done boolean default false, created_by, created_at.

Shown on the wall on the assignee's member card (a small "📌 reminders" list), tappable to complete on an allow_checkin wall. Surfaced in resolveWallView like pets/points.

Flow

  1. JQ hears/reads the utterance (existing mic + text paths).
  2. Classify intent locally first — extend classifyIntent in the pre-filter to detect the 4 action intents + extract the payload (item/meal/note/reminder text). Deterministic where possible (private, no LLM); fall to the LLM only to parse messy phrasing into {action, payload, who?}.
  3. Gate: actions require allow_ask AND allow_editing. A wall with Ask-JQ on but editing off → JQ answers "I can't change the wall — ask a grown-up to turn on Add-from-wall." (read-only stays the default).
  4. If the action needs a who and the wall is shared → JQ asks, collects the member.
  5. Execute via the (existing or new-reminder) endpoint, then JQ confirms out loud what it did ("Added milk to the shopping list."). Confirm-after, not confirm-before (low stakes; the wall refetches so the change is visible immediately).

Endpoint

Extend the existing public POST /api/family/wall/view/:token/ask to return a structured { action, needs_who, members? } when it detects an action, and add POST /api/family/wall/view/:token/act (token-scoped, allow_ask+allow_editing, re-scoped to the wall's parent) that performs { action, payload, member_id? }. Both go in the route-auth INTENTIONAL_PUBLIC allowlist. Rate-limit like ask.

Safety

  • Writes gated behind the explicit allow_editing opt-in (a leaked token still can't act unless the owner turned editing on) — same bright line as #1393.
  • Everything re-scoped to the wall's own parent; the "who" can only be a member of that family. A shared wall can't assign a reminder to another household.
  • Bedroom/minor personal walls inherit the [[project_family_frame]] counsel posture.

Sequencing

  1. #1393 merges (needs migration 538 applied to prod).
  2. This PR: migration (location_kind, owner_member_id, family_reminders) → settings UI (device identity + assignee) → reminder service + wall projection → JQ action classify/execute + confirm.
FAMILY WALL JQ ACTIONS — Docs | HiveJournal