Automated decision-making disclosure
The Children's Online Privacy Code (exposure draft s 28) gives a child, or a person with
parental responsibility, the right to request information about how their personal information
is handled, and s 28(2)(g) lists "whether there is any automated decision-making, including
profiling … and, if so, clear and meaningful information about the context of such decisions,
including the logic involved and the consequences", answered within 30 days. This page
pre-answers that request for everyone rather than waiting to be asked. Read precisely, the Code
requires the answer on request; it requires a plain-language explanation of any
automated decision-making the app does. This document is that explanation, written for anyone
who needs the fuller, more technical version — the in-app copy at app/automated-decisions.tsx
(constants/automatedDecisions.ts) is the same claim in shorter, plainer language for the person
using the app. Issue #228; background in
docs/privacy_posture.md §4.2.
There are three automated decisions in this app
- Who does a task or event. When a household adopts a meal plan or auto-allocates a batch of tasks, the AI task allocator decides who should do each item, from a list the app already built. The rest of this document is about that one, because it is the one with rules worth explaining.
- Whether a written review or a dish photo meets the content rules.
submit-reviewclassifies a written recipe review against a fixed list of categories before it is published; a review it rejects is not published and the writer is told which rule it failed (the category selects a message the app already holds — nothing the model writes is shown), and a borderline review can be escalated to a person (pending_human).moderate-photochecks a dish photo is a photograph of food that plausibly matches the recipe before it is stored; a refused photo is never stored. Both fail closed: no key, an upstream error or an unparseable verdict means nothing is published and the user is told the check is unavailable, not that they were rejected. A person who believes a check was wrong can resubmit or write to the privacy address. - A suggested start time for a new event.
lib/scheduleLookup.tslooks a new event's title up against the group's own recent events (an exact title match first, then an embedding nearest-neighbour on agent-server) and pre-fills the start and end times. It never overrides a time the person has touched, every failure is silent, and the person can change the suggestion before saving. It is a suggestion about timing, not a write.
The first draft of this document said there was exactly one decision. Review found the other two: an automated-decision disclosure that leaves out content moderation is precisely the omission the Code's disclosure duty exists to prevent, so the list above is the honest one.
The deterministic result is the floor, always
AGENTS.md states the invariant this whole feature is built against, under "A Model May Choose WHO. It May Not Choose WHAT.":
ai-task-allocatorreturns{ index, assigned_user_id }against a list the client computed and sent. It cannot invent, drop, retime or rename an item.
Concretely, in order:
- The app computes a complete allocation for every task and event first, using deterministic
rules — who already has the most on this week, and what each person has said they can take on
(
lib/allocator.ts→allocateTasksOptionC). That allocation is applied immediately; nothing waits on the model. - The model is then asked, once, to refine it: it may reassign some items to a different household member. It is never shown the ability to add an item, remove one, change a date or time, or change a title — the request it receives does not include a way to do any of those things, so there is nothing to validate against because there is nothing to misuse.
- Every answer is validated before use. An
assigned_user_idnaming someone outside the household, or anindexoutside the range of items sent, is discarded, and that item keeps its deterministic assignment. A model call that is unavailable, over the household's weekly AI budget, slow, or simply wrong costs the household nothing — the schedule from step 1 is what ships either way. - A person can change any of it. Both the deterministic assignment and any refinement the
model made are ordinary rows in
group_tasks/group_schedule_events. Reassigning, retiming or deleting one is the same action a household member would take on anything else on their calendar or task list, with no special "AI-assigned" state that resists being edited.
What it does not decide
- What needs doing. The list of tasks and events, and their dates, comes from the meal plan template or from what a group member entered — never from the model. The one thing a model suggests about timing is a new event's start time (decision 3 above), which the person can change before saving.
- Priority or urgency. Nothing in the app ranks a task's importance algorithmically.
- Anything about a person's health or a child's wellbeing. The Baby Tracker and its guidance surfaces make no automated judgement at all — see AGENTS.md "Health Content — Baby Tracker": the app "holds NO clinical content — no schedules, no thresholds, no intervals, no verdicts". That is a separate, stronger rule than this one, stated here only to be clear the allocator's remit does not brush up against it.
- Membership, roles or access. No automated process can add, remove or demote a member, or change what anyone is allowed to do in a household.
- Anything with a legal or similarly significant effect on a person. The allocator's decision is "who does the washing up on Tuesday" — a household convenience, not a decision the Code's higher-stakes disclosure obligations are really aimed at. It is disclosed here anyway, because the honest and complete answer is more useful than an argument about whether disclosure was strictly required.
Why this is easy to state honestly
Because the deterministic floor already exists and is already applied first, this disclosure does not have to describe a system that "usually" behaves a certain way, or hedge about edge cases. The floor computation and the validation of the model's answer are the same code path regardless of whether the model is called at all, is slow, or returns nonsense — so the sentence "the deterministic result is always the floor" is true in every one of those cases, not just the common one.
Keeping this true
If the allocator's contract ever changes — the model is given the ability to add or remove
items, validation is loosened, or a second automated decision is introduced elsewhere in the
app — this document, the in-app page, and lib/__tests__/automatedDecisions.test.ts all need to
change in the same commit as the behaviour. A disclosure that quietly stops matching the code is
worse than no disclosure, for the same reason AGENTS.md gives for privacy copy generally: it is
read by someone deciding whether to trust the app with their household's or their child's
information.