页面 · Health Debug
13 — Execution: Modules, Sessions & Brain Handoffs
Purpose
The phase plan (docs 04–11) says what to build in what order. This document says how to actually work it session by session: it slices the whole build into modules, slices each module into session-sized units of work, orders them by dependency, and defines the brain handoff every session writes so the next session — possibly a different agent, days later — resumes with zero context loss.
The design goal Fady set: "finish module 1 on backend/iOS/Android/web/chrome, then 2, then 3… each module in one session, and it must be easy to end a session with a handoff for the next one over the brain."
The model: a (module × surface) grid, one cell per session
Work is a grid. Rows are modules (vertical feature slices). Columns are surfaces (build targets). One session builds one cell — or, when a cell is too big, one clearly-bounded slice of it. Every session:
- Opens by reading the brain (§6) and its session card.
- Builds exactly its cell — nothing from another cell.
- Closes by writing a handoff memory and updating the build ledger (§6).
Surfaces (columns)
backend (ToGO) · web (React+TanStack) · mcp (server+CLI) · chrome (MV3) · apple (Swift: iOS/macOS/watchOS/CarPlay/Widgets) · android (Kotlin: phone/Wear/Auto/Glance) · desktop (Electron).
Modules (rows)
| Module | Name | Notes |
|---|---|---|
| M0 | Foundation | Split into session-sized sub-modules M0.1–M0.8 (§2). The core is itself multi-session. |
| M1 | Hydration | The reference engine — build it fully across surfaces first; it sets the pattern every other engine copies. |
| M2 | Caffeine Block | |
| M3 | GERD Window | |
| M4 | Trigger Families (nutrition) | |
| M5 | Medication Grace | |
| M6 | Cycle (Fertility) | Not on chrome. |
| M7 | Contraceptive Security | Not on chrome. |
| M8 | Kinetic Pomodoro | Needs wearable motion → watch/Wear sub-sessions are mandatory, not optional. |
| X1 | Notifications | Delivery (FCM/APNs) + notification center per client. Legacy built routing but never delivered. |
| X2 | AI BYOK proxy | Server proxy + per-client passthrough AI-settings screen. |
| X3 | Sensors / biometrics | HealthKit (apple) + Health Connect (android) read/push + body-metrics module. |
| X4 | Update gate | app_releases + GET /api/app/version + per-client update check. |
| X5 | Release / packaging | Play, App Store, electron-builder, web deploy, extension listing. |
Per-module session cards (the detailed per-surface session list for each module) live in docs/plan/sessions/.
2. M0 Foundation — the core, split into sessions
The core is deliberately multiple sessions so each ends cleanly:
| Session | Surface | Scope | Depends on |
|---|---|---|---|
| M0.1 | backend | ToGO microkernel project boots; config; /healthz; Docker compose with the ToGO postgres image; Atlas + sqlc wired; NOT-NULL+default CI lint gate; CI skeleton (there is no CI in the legacy repo). | — |
| M0.2 | backend | TOGO auth plugin integrated; deny-by-default guard + allowlist; app users row keyed to auth identity; personal access tokens; cross-user isolation test (404-not-403). | M0.1 |
| M0.3 | backend | Engine plugin framework: the plugin contract on the Microkernel registry, hook bus, injected clock, the pure-core/ pattern, and one reference plugin skeleton (no engine logic yet). | M0.1 |
| M0.4 | backend | Expand-contract migration harness proven end-to-end with one real migration; error envelope + ICU-localized rejection codes. | M0.1 |
| M0.5 | web | React + TanStack app shell; router skeleton; typed API client; auth/login flow against M0.2. | M0.2 |
| M0.6 | web | Theme engine: dark-glow / light-flat semantic tokens, system-preference + manual override, no-flash first paint. Single token source (the legacy liability was three hand-maintained token files). | M0.5 |
| M0.7 | web | i18n engine: ICU Message Format, en/ar catalogs, dir=rtl root, CSS logical properties, mirrored progress bars. | M0.5 |
| M0.8 | mcp | MCP server + CLI skeleton: auth via personal access token, transport, first tool wired once /today exists (so this trails M1 backend). | M0.2, M1 backend |
Only after M0.1–M0.4 may any engine backend session start. Only after M0.5–M0.7 may any web/desktop client engine session start.
3. Engine module shape (M1–M8)
Each engine module is the same vertical slice, one session per surface, in this recommended order:
- backend — the engine as its own ToGO plugin (pure
core/state machine +plugin.goregistration + schema migration + endpoints + engine unit tests as executable spec + integration test). Must land before any client session for this engine. - web — the engine's dashboard card/screen, rendering server state only.
- mcp — the engine's log/query tools.
- chrome — popup/badge surface (only for engines that make sense in a browser: M1–M5).
- apple — iOS + relevant watch/widget/CarPlay surface.
- android — phone + relevant Wear/Auto/Glance surface.
- desktop — Electron surface (reuses web components).
M1 (Hydration) is built end-to-end first as the reference; later engines copy its shape, so their per-surface sessions are faster.
4. Dependency & ordering rules
- Backend before clients for the same module.
- M0 foundation (backend .1–.4, web .5–.7) before the corresponding engine sessions.
- Within an engine: backend → web → mcp → chrome → apple → android → desktop.
- Across engines: finish M1 across its surfaces before starting M2 unless you deliberately parallelize by keeping different agents on different modules (each still one cell per session). The brain ledger (§6) tracks the frontier so parallel work does not collide.
- X-modules: X1 notifications and X2 AI after M1 exists; X3 sensors alongside the apple/android engine sessions; X4 update-gate before the first store submission; X5 release last per platform.
- Kinetic Pomodoro (M8) cannot be marked done on apple/android without the watch/Wear motion sub-session — a break must be validated by wearable movement, never faked by the phone or an MCP call.
5. Session done-criteria templates
Backend-engine session is done when: plugin registered on the kernel; migration is expand-contract and every column is NOT NULL with a default; endpoints return computed state; engine unit tests encode every spec constant literally and pass; integration test against real Postgres passes (idempotency replay, cooldown/cap races); no protocol constant appears outside the engine's core/ package.
Client-engine session is done when: the surface renders /today (or the engine endpoint) state and submits log intents only; thin-client/SSOT audit passes (no timer/cooldown/window/trigger logic in client code — grep for the protocol constants finds nothing); both themes render per the strict color spec; Arabic RTL mirrors correctly (incl. progress bars); strings are ICU, none concatenated.
Foundation session is done when: its specific deliverable works end-to-end and is covered by a test or a documented manual check, and the CI gate for its concern (schema lint, thin-client audit, i18n coverage) is in place.
MCP session is done when: each tool calls the real API with the personal-access-token auth, returns server state verbatim, holds no protocol logic and no AI keys, and the excluded tools (no complete_break) stay excluded.
6. The Brain Handoff Protocol
This is what makes a session safely endable. The brain namespace is healthdebug (see docs/brain/BRAIN-INDEX.md for the classification convention).
At the START of every session
memory_recallthe brain-organization record (brain-index) and the build ledger (source_ref: build-ledger).memory_recallthe target module's memories and the latestsession-handofffor the target (module, surface).- Open the module's session card in
docs/plan/sessions/and the plan docs it references.
At the END of every session
Write one session-handoff memory (retain, then memory/edit to attach metadata — retain cannot set metadata), using this exact structure in the content:
source_ref:handoff/<module>/<surface>/<n>(unique per session — never reuse, or it supersedes).metadata:{project:"healthdebug", type:"session-handoff", category:"session-handoff", era:"greenfield", status:"current", surface:"<surface>", module:"<Mx>", title:"Handoff <session-id>", tags:[...], next:"<module+surface>"}.metadata.typeis the field cabrain groups by (brain_details.types); it must be set (a top-leveltypeon retain/edit is ignored) — seedocs/brain/BRAIN-INDEX.md.
Then update the single build-ledger memory (source_ref: build-ledger, edited in place each session) so one recall shows the whole frontier: a compact list of every cell's status (not-started / in-progress / done / blocked) and the current recommended next session. Any architectural decision or new open question also gets its own classified memory and, if it changes the plan, an edit to the relevant plan doc.
Why the ledger + handoffs are separate
The per-session session-handoff memories are the durable audit trail (one per cell, never overwritten). The single build-ledger memory is the always-current frontier map (overwritten each session). A fresh session reads the ledger to know where we are, then the latest handoff for its cell to know how to continue.
7. Finding the next thing to do
Recall the build-ledger memory → it names the recommended next session (module + surface) and lists blocked cells with their blockers. If the ledger is empty (first ever build session), start at M0.1 (backend).
8. Session card index
Detailed per-module session lists live in docs/plan/sessions/ (one file per module: M0-foundation.md, M1-hydration.md, … M8-kinetic-pomodoro.md, X1-notifications.md … X5-release.md). Each card enumerates that module's per-surface sessions with scope, entry dependencies, exit/done criteria, and the plan docs to read.