- A new capture kind "symptom" (illness module, illness write grant) in
the bottom bar's picker and the dashboard Add menu. The sheet follows
the measurement and mood forms: the person's symptoms as chips with the
cycle sheet's dashed "new symptom" chip, the 0-10 slider with its
anchors, the time prefilled with now, an optional note, and a "during"
selector only while an illness episode is open.
- "Your symptoms" on the illness page: one line per symptom (how often in
30 days, how strong at worst, when last), the last 30 days grouped by
day, edit and delete per entry, rename, icon, hide and delete per
symptom. Renders nothing until a symptom exists.
- "Symptoms logged" on an episode's page: the entries filed against it or
logged while it ran, the filed ones marked. This is the reader of the
episode link.
- Query keys live under the illness root, so either side's writes
refresh both.
Every active symptom definition enters pattern discovery as an outcome
channel SYMPTOM:<id>, labelled with its decrypted name (the data label
the interpretation already prefers over the key). The daily value is the
day's highest intensity in the person's zone; days without an occurrence
count as 0 only between the first and the last logged day. At most eight,
the active-definition cap. The SYMPTOM: prefix resolves to the illness
module in the surface map, so the family leaves the matrix with the
module, and the discovery guard lists the new fetcher.
The dashboard add menu and the bottom bar's capture picker gain a
workout entry next to measurement, mood and medication. It belongs to
the workouts module (capture:workout) and is offered in one's own record
only, because the batch ingest resolves the caller and no grant reaches
it.
Refs #1085
The Coach correlations tool, the per-metric card and the period
narrative scanned every channel, so a switched-off module still fed
their statistics and the text a model was grounded on. The matrix's
modules option is now required, each caller resolves the record's map,
and the Coach skips the lab pass with labs off. A registry guard holds
every caller to resolving the map itself.
The mask's doc comment now states what it does to the false discovery
correction: fewer channels is a smaller family, so q-values of the
remaining pairs move and a borderline pair can cross the threshold.
The hero rings read their owner from the surface map instead of their
own map, and the readiness, recovery and sleep score rings no longer
wait on the AI analysis switch: they are computed scores, not model
text. The dose ring still follows the medications module.
Each family of ids must name a surface that exists (nav hrefs, sub-page
directories, section ids, widget ids, derived ids, Settings slugs,
correlation channels). Sub-pages, trend slots and correlation channels
must follow the owner of the types they plot, joined against the
dashboard's summary owners, and a pinned table covers the owners no
join can derive. The replaced per-surface keys and the redirecting page
guard are searched for in source, and the derived route's gate is
compared with the map entry by entry.
Broken on purpose before committing: dropping the sleep sub-page entry,
the mood trend entry or a nav entry, drifting a derived owner, and
reintroducing a per-destination key each fail by name.