Spec — Nutrition / Body Domain App

Working name: Repast (placeholder — naming not final, same as the Organizer).

Purpose: a single coherent brief to hand to Claude Code + BMAD. This is not a new project — it is the Body/Nutrition domain getting its own face on the shared substrate already specified in the Organizer brief (E2EE local store, on-device inference, encrypted CRDT sync, the Guide voice). Read this alongside that document; it inherits §4 Architecture and §5.3 Guide wholesale and only specifies what is new. Structure favors decomposition into epics and stories.


1. Vision

A nutrition app that helps a person stay aware of how they eat without turning eating into an audit. You log at whatever fidelity you feel like — a barcode and a measured weight when you care, or "a pizza with tomato sauce and ham, maybe 28 cm" when you don’t — and you get an honest range, not a false-precision number. It exists to help you feel good and notice patterns, not to win a 512-vs-515-kcal argument with yourself.

Everything is local / E2EE. The Guide rides along as the emotional layer, the same voice as everywhere else in the suite.


2. Positioning

  • vs MyFitnessPal / Cal AI / PlateLens / NutriScan: they optimize for logging accuracy or weight-loss coaching, in the cloud, with a red/green "you went over" loop. This optimizes for awareness without anxiety, locally and privately.

  • vs MacroFactor: closest in non-preachy spirit, but still cloud, still number-centric, and not part of a life ecosystem.

  • The wedge: log at any fidelity, see an honest range, feel reflected-on rather than judged — and none of your food data leaves your device.

The honesty point is also a factual one: human eyeball portion estimates carry roughly ±40—​60% error and manual database logging still carries ±15—​25%. An app that shows "1,147 kcal" is performing a precision it does not have. Showing a band is both more truthful and less anxiety-inducing. This is a wellbeing design choice, not a limitation.


3. Ecosystem fit (how it connects — it is not standalone)

Life domain App

Money

Finia (exists, separate)

Time / Life

the Organizer

Relationships

Contacts (roadmap)

Body / Nutrition

this app

It connects to the rest through three shared things, all already built:

  1. The substrate — encryption, on-device model, CRDT sync, key handling. Reused as-is.

  2. The calendar-block entity — a meal is also a ScheduledBlock/DailyBlock. That means the Organizer already knows when you ate, and this app does not reinvent a timeline.

  3. The Guide voice + trigger system — the single biggest reason to build this inside the suite. The Guide can reflect across domains: it sees from the Organizer that work over-ran three evenings and sees here that dinner got skipped, and surfaces one nudge about protecting a real break — something no standalone food tracker can ever do.

The life-domain model is the product-family map; this is simply the next domain filling in.


4. Architecture (delta only — inherits Organizer §4)

Inherited unchanged: local-first, E2EE, zero-knowledge server, single capable on-device model for MVP (grow into router+adapter later), local RAG over the user’s own decrypted data, encrypted CRDT sync, passphrase + per-device keys.

New, domain-specific:

  • Local nutrition knowledge base — Open Food Facts. Open, barcode-keyed, redistributable. Ship a slimmed local mirror (or syncable subset) so barcode lookups and the food-name → nutrition mapping work fully offline and on-device. This is the local RAG knowledge for this domain; the model is still just the engine.

  • NL estimation adapter (or prompt path on the single MVP model): turns "pizza, tomato, ham, ~28 cm" into a structured estimate with an explicit range and a confidence level, reasoning over the Open Food Facts data.

  • Barcode + measured-weight path: Tauri v2 has native barcode scanning out of the box (already proven in the Ersthelfer work). Barcode → product → user enters grams → tightest possible range.

  • Photo path is explicitly deferred (vision is heavier and lower-accuracy than the marketing suggests) — see roadmap R2.


5. Core design principles (the soul of the product — these are non-negotiable in v1)

  • Variable fidelity, no penalty for being loose. A vague entry is a first-class citizen, not a degraded one. The UI never makes "I just ate a pizza" feel like a failure to do it properly.

  • Always a band, never a point. Every estimate displays as a range (e.g. "~900—​1300"). The daily view accumulates a band, not a single hard number.

  • No mandatory goal number. Default mode has no calorie target at all — the product is pattern-awareness, not target-hitting. A soft goal is opt-in and can be turned fully off. The app must work, and feel complete, with zero numeric goal.

  • The Guide reflects; it never scolds. No red/green. No "over budget." Surfaces on patterns over time, never on a single meal. Tone per Organizer §5.3: dry, warm, cosmically humbling, never preachy, leaves the reader relieved.

  • Awareness, not optimization. Success = the user feels good and notices something true about how they eat. Not maximum logging streak, not minimum calories.


6. The fidelity ladder (the central mechanic)

Every entry records the fidelity level it was logged at, and the displayed range widens or tightens accordingly. The user moves up the ladder only when they want to.

Level Input Resulting estimate

L0 — Marker

"I ate" / a tag, no detail

No numbers; just a logged event for pattern/rhythm awareness

L1 — Freeform NL

"pizza, tomato sauce, ham, ~28 cm"

Wide honest band from the NL adapter

L2 — Photo (roadmap)

snapshot of the plate

Vision estimate, medium band

L3 — Structured items

picked from Open Food Facts

Narrower band

L4 — Barcode + weight

scan + measured grams

Tightest band

L1 and L4 are the MVP. The point of the ladder is that L1 and L0 are valid forever — you are never required to climb it.


7. Unified data model (delta only — inherits Organizer §6)

New entities:

  • Meal — a logged eating event; is-a / links-to DailyBlock so it lands on the shared timeline.

  • FoodComponent — one item within a meal (name, optional quantity, source level).

  • FidelityLevel — L0—​L4 enum carried per Meal and per FoodComponent.

  • Estimate — a range: low, high, confidence; never a bare scalar.

  • NutritionFacts — energy + macros (micros deferred); always expressed so a range can be derived.

  • FoodKBEntry — local Open Food Facts record (barcode, name, per-100g facts).

  • MealPattern — a derived, locally computed signal (rhythm, skipped meals, recurring components) that feeds Guide triggers.

Reused: DailyBlock/ScheduledBlock, GuideEntry, GuideTrigger, Domain (a Body domain instance), the calendar entities.

All entities client-side encrypted; all derived signals computed locally.


8. Guide integration

  • New GuideTriggers fire on patterns, never single meals: e.g. recurring skipped meals on long work days (cross-domain, reads the Organizer), a week that leaned heavily one way, a return to logging after a gap.

  • Entry template unchanged: Truth · Turn · Do · Footnote, where Do is one schedulable action (e.g. "block 20 min for a real lunch tomorrow").

  • Seed ~6—​8 starter nutrition entries in the existing Guide voice. None of them moralize about food; they are about rhythm, energy, and kindness to oneself.


9. MVP scope (v1)

In:

  • Reuse the substrate: E2EE local store, key setup/recovery, single on-device model.

  • Local Open Food Facts mirror (slimmed) + offline barcode lookup.

  • Fidelity ladder L0, L1, L4 (marker, freeform NL, barcode+weight).

  • Range-only estimates everywhere; daily and weekly band views.

  • Meals land on the shared DailyBlock timeline (Organizer interop).

  • No-goal default mode; optional soft goal fully toggleable off.

  • Guide: starter nutrition entries + a few pattern triggers (incl. one cross-domain).

Out (roadmap):

  • L2 photo/vision estimation.

  • Micronutrients.

  • Any optional-cloud inference path.

  • Social / sharing.

  • Recipe building, meal planning.


10. Roadmap (post-MVP)

  • R1 — Intelligence: richer MealPattern signals; expand the Guide nutrition library.

  • R2 — Photo path (L2): on-device vision estimate, kept honest (wide bands, shown confidence).

  • R3 — Micronutrients & deeper KB: expand Open Food Facts usage.

  • R4 — Optional cloud (mirrors Organizer R3): per-task, opt-in, anonymized, self-hosted only, payload shown before send. Off by default.

  • R5 — Deeper Organizer interop: the planner actively protects meal blocks the way it protects gym/family blocks.


11. BMAD handoff — candidate epics

  • E1 — Domain substrate reuse: wire the Body domain onto existing store, sync, keys.

  • E2 — Food knowledge base: package, ship, and query a local Open Food Facts subset.

  • E3 — Fidelity ladder + estimation: L0/L1/L4 capture, NL adapter, range model.

  • E4 — Range-first UI: capture flow, day/week band views, no-goal default.

  • E5 — Organizer interop: meals as DailyBlocks on the shared timeline.

  • E6 — Guide nutrition layer: entries, triggers (incl. cross-domain), surfacing.

Acceptance themes to carry into stories: no entry is ever penalized for low fidelity; no screen ever shows a bare scalar where a range is meaningful; the app is fully usable and feels complete with zero numeric goal set; the Guide never scolds and never fires on a single meal.