# ChronoMind — Agentic AI Roadmap > **Product:** ChronoMind — AI-Powered Contextual Clock & Timer > **Repo:** `learning_ai_clock` > **Created:** March 31, 2026 > **Strategy:** Transform ChronoMind from a smart timer app into the **time execution layer** for the agentic AI era. > **Depends on:** Existing backend (port 4011), web engine (373+ Vitest tests), iOS/Android native apps. --- ## Open TODO Index > **For AI agents:** Scan this table, pick the next unresolved TODO by priority, and address it. > Search the codebase for `TODO-NNN` to find the in-code comment with full instructions. > After completing a TODO, remove it from this table and mark the corresponding roadmap checkbox. | TODO | Priority | Phase | File(s) | Summary | |------|----------|-------|---------|---------| | **TODO-001** | medium | 0 | `web/src/app/providers.tsx` | Kill switch maintenance banner — create ``, set React state when `checkKillSwitch()` returns `disabled=true`, disable timer creation buttons | | **TODO-002** | medium | 0 | `web/src/app/(app)/settings/page.tsx` (create) | Wire feedback button into settings page (or floating FAB) using `feedbackClient` from `web/src/lib/feedback.ts` | | **TODO-003** | medium | 0 | `web/src/components/CreateTimerModal.tsx`, `web/src/components/AlarmOverlay.tsx` | Apply `@bytelyst/accessibility` focus trap + screen reader announcements. Ensure `--cm-*` color tokens meet WCAG AA contrast | | **TODO-004** | medium | A.1 | `backend/src/modules/routines/routes.ts` | Clone template into new RoutineDoc instead of mutating in-place. Create new doc with `crypto.randomUUID()`, leave original template unchanged | | **TODO-005** | high | A.4 | `backend/src/lib/ai-context.ts` | Replace extraction-service stub with real LLM call. Option A: `@bytelyst/extraction` client with `timer-context` task. Option B: `@bytelyst/ollama-client` directly | | ✅ **TODO-006** | low | A.4 | `web/src/lib/context-messages.ts` | ~~Centralize backend URL~~ — uses `getBackendBaseURL()` from `product-config.ts` (5dafcc2) | | **TODO-007** | medium | A.3 | `learning_ai_common_plat/services/mcp-server/` | Add integration tests for 5 new ChronoMind MCP tools (reschedule, availability, routine start, agent-actions list, agent-actions approve) | | **TODO-008** | medium | B | `backend/src/lib/telemetry-events.ts`, `web/src/lib/telemetry-events.ts` | Wire `trackEvent()` / `bufferEvent()` calls into routes and components using the defined telemetry constants. See in-code comments for specific call sites | | **TODO-009** | medium | A.4 | `backend/src/lib/ai-context.ts`, `web/src/lib/context-messages.ts` | Add unit tests for `generateContextMessage()` (backend) and `fetchEnrichedMessage()` (web). Test keyword fallback, LLM enrichment, generic fallback, and error paths | | ✅ **TODO-010** | low | cleanup | `backend/src/modules/timers/routes.ts`, `routines/routes.ts`, `households/routes.ts`, `webhooks/routes.ts`, `shared-timers/routes.ts` | ~~Replace hardcoded PRODUCT_ID~~ — imports from `product-config.js` in all 5 files (d74c80a) | | ✅ **TODO-011** | low | cleanup | `web/src/app/error.tsx` | ~~Wire error boundary to telemetry~~ — `trackEvent('error', 'app', 'error_boundary', ...)` (9e63418) | --- ## Current State Summary | Layer | Status | Key Files | |-------|--------|-----------| | **Web engine** | 52 lib files, 16 components, 373+ tests | `web/src/lib/*.ts` | | **Backend** | 5 modules + webhooks, port 4011 | `backend/src/modules/` (timers, routines, households, shared-timers, webhooks) | | **iOS** | Full SwiftUI + Watch + Mac + Widgets, 129 XCTests | `ios/` | | **Android** | Jetpack Compose + Wear OS + Glance, 30 JUnit5 tests | `android/` | | **Sync** | `@bytelyst/sync` engine + platform-sync.ts client | `web/src/lib/platform-sync.ts` | | **Webhooks** | Subscription CRUD + dispatcher (HMAC + retries) + 15 event types | `backend/src/modules/webhooks/` | ### Ecosystem Integration Status | @bytelyst/* Package | Status | Notes | |---------------------|--------|-------| | `@bytelyst/fastify-core` | ✅ Used | `createServiceApp` + `startService` | | `@bytelyst/auth` / `fastify-auth` | ✅ Used | JWT verify via `registerOptionalJwtContext` | | `@bytelyst/auth-client` | ✅ Used | `createAuthClient` in `web/src/lib/auth-api.ts` | | `@bytelyst/react-auth` | ✅ Used | `createAuthProvider` in `web/src/lib/auth-context.tsx` | | `@bytelyst/config` / `backend-config` | ✅ Used | `baseBackendConfigSchema` in backend config | | `@bytelyst/datastore` | ✅ Used | Cosmos/memory abstraction in backend | | `@bytelyst/cosmos` | ✅ Used | Container registration | | `@bytelyst/errors` | ✅ Used | Typed HTTP errors | | `@bytelyst/field-encrypt` | ✅ Used | Encryption at rest | | `@bytelyst/backend-flags` | ✅ Used | `createFlagRegistry` in backend | | `@bytelyst/backend-telemetry` | ✅ Used | `createTelemetryBuffer` in backend | | `@bytelyst/feature-flag-client` | ✅ Used | Web client with streaming | | `@bytelyst/telemetry-client` | ✅ Used | Web telemetry via `createWebTelemetry` | | `@bytelyst/diagnostics-client` | ✅ Used | Web diagnostics via `createWebDiagnostics` | | `@bytelyst/api-client` | ✅ Used | `createApiClient` in platform-sync | | `@bytelyst/sync` | ✅ Used | Sync engine in platform-sync.ts | | `@bytelyst/design-tokens` | ✅ Used | `--cm-*` CSS props in globals.css | | `@bytelyst/ui` | ✅ Used | Imported in providers.tsx | | `@bytelyst/kill-switch-client` | ❌ **MISSING** | Every other product has this — critical for prod safety | | `@bytelyst/feedback-client` | ❌ **MISSING** | No in-app feedback mechanism | | `@bytelyst/event-store` | ❌ **MISSING** | Domain events not persisted — needed for webhooks + audit | | `@bytelyst/webhook-dispatch` | ❌ **MISSING** | Backend uses hand-rolled dispatcher instead of shared package | | `@bytelyst/accessibility` | ❌ **MISSING** | Shared accessibility helpers not consumed | | `@bytelyst/celebrations` | ❌ **MISSING** | Streak/plan completion should use shared celebrations | | `@bytelyst/gentle-notifications` | ❌ **MISSING** | Tempo warnings should use shared gentle notifications | | `@bytelyst/ollama-client` | ⬜ Not needed yet | Will be needed for Phase A.5 (AI context messages) | | `@bytelyst/extraction` | ⬜ Not needed yet | Will be needed for Phase A.5 (LLM parsing fallback) | ### MCP Server Integration (Important) The centralized **MCP server** (`learning_ai_common_plat/services/mcp-server`, port 4007) **already has ChronoMind tools**: - `chronomind.timers.create` / `.list` / `.delete` - `chronomind.routines.list` / `.validate` - `chronomind.syncStatus` - `chronomind.sharedTimers.share` - `chronomind.households.list` These proxy to `chronomind-backend` (port 4011) via `chronomind-client.ts`. **Architecture for new MCP tools:** 1. **Backend** (port 4011): Add new REST endpoints (planner, agent-actions, reschedule, availability, context-message) 2. **MCP Server** (port 4007): Extend `chronomind-tools.ts` + `chronomind-client.ts` to expose new endpoints as MCP tools 3. **Product backend does NOT host its own MCP layer** — all MCP goes through the centralized server --- ## Phase Overview | Phase | Features | Effort | Timeline | |-------|----------|--------|----------| | **Phase 0** | Ecosystem Gap Fixes (kill-switch, feedback, event-store, accessibility) | Low | ~1 day | | **Phase A** | MCP Backend Endpoints + MCP Server Extension + AI Context Messages | Medium | ~3 days | | **Phase B** | AI Day Planner + Agent Inbox | Medium | ~4 days | | **Phase C** | Webhook Migration to @bytelyst/webhook-dispatch + Zapier Compat | Low | ~1.5 days | | **Phase D** | Smart Routine Suggestions + Tempo Mode | Medium | ~3 days | | **Phase E** | Client-Side Sync Integration (Web ↔ iOS ↔ Android) | High | ~4 days | **Total estimated:** ~16.5 working days across 6 phases. **Dependency order:** 0 (first) → A → B → C/D (parallel) → E --- ## Phase 0 — Ecosystem Gap Fixes > **Goal:** Bring ChronoMind into full compliance with the @bytelyst ecosystem before adding new features. > **Why first:** These are production-safety and consistency gaps. Fixing them first prevents new code from repeating the same gaps. ### 0.1 — Kill Switch Client (Web) - [x] `web/src/lib/kill-switch.ts` — integrate `@bytelyst/kill-switch-client` (commit: f3e14e2) - Same pattern as NomGap/NoteLett: `createKillSwitchClient({ baseUrl, productId, platform })` - Check on app init → if killed, show maintenance banner and disable timer creation - Add `pnpm add @bytelyst/kill-switch-client` to web/package.json - [x] Wire into `web/src/app/providers.tsx` — init on mount (commit: f3e14e2) ### 0.2 — Feedback Client (Web) - [x] `web/src/lib/feedback.ts` — integrate `@bytelyst/feedback-client` (commit: f3e14e2) - `createFeedbackClient({ baseUrl, productId, getAccessToken })` - [ ] Add feedback button to settings page (or floating FAB) (commit: ) - TODO-002: Wire feedback button into settings page using `feedbackClient` from `web/src/lib/feedback.ts` ### 0.3 — Accessibility Package (Web) - [x] Add `@bytelyst/accessibility` to web/package.json (commit: f3e14e2) - [ ] Integrate helpers into existing modals (commit: ) - TODO-003: Apply `@bytelyst/accessibility` focus trap + screen reader to CreateTimerModal, AlarmOverlay - Ensure all `--cm-*` color tokens meet WCAG AA contrast ### 0.4 — Feature Flags for New Features (Backend) - [x] Add feature flags for all new agentic features to `backend/src/lib/feature-flags.ts` (commit: f3e14e2) ``` 'mcp.enabled': false, 'planner.enabled': false, 'agent_inbox.enabled': false, 'tempo.enabled': false, 'routine_suggestions.enabled': false, 'ai_context_messages.enabled': false, 'webhooks.zapier': false, ``` - [ ] Gate all new backend routes behind their respective flags (ongoing — applied per-route as built) ### 0.5 — Telemetry Events for New Features - [x] Define telemetry event names for all new features (commit: f3e14e2) - `mcp.tool_executed`, `mcp.tool_failed` - `planner.day_planned`, `planner.plan_applied`, `planner.plan_rejected` - `agent_inbox.action_approved`, `agent_inbox.action_rejected`, `agent_inbox.batch_approved` - `tempo.drift_detected`, `tempo.adjustment_applied` - `routine_suggest.shown`, `routine_suggest.accepted`, `routine_suggest.dismissed` - `ai_context.enriched`, `ai_context.fallback_used` - `webhook.dispatched`, `webhook.failed` - [ ] Add `trackEvent()` calls in backend routes and web components as they're built (ongoing through all phases) ### Phase 0 Exit Criteria - [x] Kill switch client initialized on web app startup (f3e14e2) - [x] Feedback client created (f3e14e2) — UI entry point deferred to TODO-002 - [x] Accessibility package added (f3e14e2) — modal integration deferred to TODO-003 - [x] 7 new feature flags registered (all default `false`) (f3e14e2) - [x] Telemetry event names defined (16 events, backend + web) (f3e14e2) - [x] All existing tests still pass (182 backend + 394 web) --- ## Phase A — MCP Backend Endpoints + MCP Server Extension + AI Context Messages > **Goal:** Let any AI agent create, query, reschedule, and dismiss timers via the centralized MCP server. Upgrade context messages with LLM fallback. > **Why first:** This is the single most differentiating feature for 2026. It positions ChronoMind as infrastructure, not just an app. **Architecture:** Two-layer approach (see "MCP Server Integration" above): - **Layer 1 (this repo):** New REST endpoints in `backend/src/modules/` — standard Fastify routes - **Layer 2 (common-plat):** Extend `mcp-server/src/modules/chronomind/` to proxy new endpoints as MCP tools ### A.1 — New Backend REST Endpoints (chronomind-backend, port 4011) Add 4 new endpoint groups to the product backend. These are plain REST routes — NOT MCP tools: - [x] `backend/src/modules/timers/routes.ts` — add reschedule + availability endpoints (commit: 686f5fb) - `POST /api/timers/:id/reschedule` — shift timer by delta or to new time - `GET /api/timers/availability?start=&end=&minSlotMinutes=` — find free slots - Gate behind `isFeatureEnabled('mcp.enabled')` flag - [x] `backend/src/modules/routines/routes.ts` — add start-routine endpoint (commit: 686f5fb) - `POST /api/routines/:id/start` — start a routine template (changes status → running) - Gate behind `isFeatureEnabled('mcp.enabled')` flag - [x] Tests for new timer + routine endpoints (commit: 29a4802) ### A.2 — Agent Action Audit Trail (New Backend Module) - [x] `backend/src/modules/agent-actions/types.ts` — Zod schemas (commit: 29a4802) - Fields: `id`, `userId`, `productId`, `actorId`, `actorType` (agent/user/mcp), `toolName`, `actionType`, `state` (proposed/approved/applied/rejected), `reason`, `payload`, `createdAt` - Every Cosmos doc includes `productId: "chronomind"` - [x] `backend/src/modules/agent-actions/repository.ts` — CRUD (commit: 29a4802) - Container: `cm_agent_actions`, partition: `/userId` - Uses `@bytelyst/datastore` `getCollection()` — never direct Cosmos SDK - [x] `backend/src/modules/agent-actions/routes.ts` — REST endpoints (commit: 29a4802) - `GET /api/agent-actions` — list (filterable by state, actorId, toolName) - `POST /api/agent-actions` — create action (used by MCP tools) - `POST /api/agent-actions/:id/approve` — approve proposed action - `POST /api/agent-actions/:id/reject` — reject proposed action - `POST /api/agent-actions/batch-approve` — batch approve by actorId - Gate behind `isFeatureEnabled('agent_inbox.enabled')` flag - [x] Register `agentActionRoutes` in `server.ts` (commit: 29a4802) - [x] Register `cm_agent_actions` container in `cosmos-init.ts` (commit: 29a4802) - [x] Agent action tests — 22 tests (commit: 29a4802) ### A.3 — Extend Centralized MCP Server (common-plat) Extend `learning_ai_common_plat/services/mcp-server/src/modules/chronomind/`: - [x] `chronomind-client.ts` — add 6 client functions for new endpoints (commit: efde14ba in common-plat) - `chronomindTimerReschedule`, `chronomindTimerAvailability`, `chronomindRoutineStart` - `chronomindAgentActionCreate`, `chronomindAgentActionsList`, `chronomindAgentActionApprove` - [x] `chronomind-tools.ts` — register 5 new MCP tools (commit: efde14ba in common-plat) - `chronomind.timers.reschedule` — shift timer by delta or to new time - `chronomind.timers.availability` — find free time slots - `chronomind.routines.start` — start a routine template - `chronomind.agentActions.list` — list pending agent actions - `chronomind.agentActions.approve` — approve a proposed action - Write tools (reschedule, routines.start) record agent action for audit trail (fail-open) - [ ] MCP tool tests (commit: ) - TODO-007: Add integration tests for the 5 new ChronoMind MCP tools in common-plat ### A.4 — Context-Aware AI Messages (LLM upgrade) Upgrade `web/src/lib/context-messages.ts` with optional LLM enrichment: - [x] `backend/src/lib/ai-context.ts` — LLM-powered context message generator (commit: c80c1e4) - Accepts: timer label, category, urgency, user's recent timers, time of day - Returns: enriched prep message with source indicator (llm/keyword/generic) - Falls back to keyword rules if LLM unavailable or flag off - Calls extraction-service `timer-context` task when EXTRACTION_SERVICE_URL is set - Gate behind `isFeatureEnabled('ai_context_messages.enabled')` flag - [x] Backend route: `POST /api/context-message` (commit: c80c1e4) - [x] `web/src/lib/context-messages.ts` — add `fetchEnrichedMessage()` (commit: c80c1e4) - Graceful degradation: keyword rules remain primary, LLM messages shown as "AI suggestion" - TODO-008: Wire trackEvent() calls for ai_context.enriched / ai_context.fallback_used - [ ] Tests for AI context generation (commit: ) - TODO-009: Add unit tests for generateContextMessage() and fetchEnrichedMessage() ### Phase A Exit Criteria - [x] 3 new REST endpoints in chronomind-backend (reschedule, availability, routine start) (686f5fb) - [x] Agent action module with full CRUD + batch approve (29a4802) - [x] 5 new MCP tools registered in centralized mcp-server (efde14ba in common-plat) - [x] Context messages enriched by LLM with keyword fallback (c80c1e4) - [x] All gated behind feature flags (default off) (f3e14e2) - [ ] Telemetry events defined but trackEvent() calls needed in routes (ongoing) - [x] All existing tests still pass (219 backend + 394 web) - [x] No breaking changes to existing timer/routine APIs --- ## Phase B — AI Day Planner + Agent Inbox UI > **Goal:** "Plan my day" command + web UI for reviewing agent-proposed timers. > **Depends on:** Phase A (MCP tools + agent actions module). ### B.1 — Day Planner Engine (Backend) - [ ] `backend/src/modules/planner/types.ts` — Zod schemas for plan requests/responses (commit: ) - `PlanDayRequest`: activities array (label, duration, priority, category, constraints) - `PlanDayResponse`: proposed timeline (timer array with computed times, urgency, cascades) - `PlanConstraint`: "after 2pm", "before lunch", "back-to-back with X", "needs 15m break between" - Every Cosmos doc includes `productId: "chronomind"` - [ ] `backend/src/modules/planner/engine.ts` — deterministic slot-fitting algorithm (commit: ) - Step 1: Load existing timers for the target day - Step 2: Compute available slots (gaps between timers) - Step 3: Fit requested activities into slots respecting constraints + priority order - Step 4: Assign urgency based on keywords/category (reuse `context-messages` rules) - Step 5: Assign cascade presets based on urgency (reuse `cascade.ts` defaults) - Step 6: Add prep time buffers (reuse `prep-time.ts` logic) - Returns: ordered timer list with `state: 'proposed'` — not yet committed - [ ] `backend/src/modules/planner/routes.ts` — REST endpoints (commit: ) - `POST /api/planner/plan-day` — generate proposed plan (does NOT create timers) - `POST /api/planner/apply` — commit proposed plan (creates timers + agent action records) - `POST /api/planner/replan` — modify an existing plan with new constraints - Gate behind `isFeatureEnabled('planner.enabled')` flag - Track `planner.day_planned` / `planner.plan_applied` telemetry events - Use `req.log` for logging — never `console.log` - [ ] Planner engine tests (commit: ) - Test: empty day → all activities fit - Test: busy day → overflow reported with alternatives - Test: constraints respected (after/before/back-to-back) - Test: prep time buffers added correctly ### B.2 — Day Planner NL Interface - [ ] Backend NL → plan translation (commit: ) - `POST /api/planner/plan-nl` — accepts natural language ("prep slides 2h, standup 30m, lunch, deep coding 3h — plan my afternoon") - Parses via `@bytelyst/extraction` client to extraction-service, or regex-based NL parser (ported from web `nl-parser.ts`) - Returns same `PlanDayResponse` as structured endpoint - [ ] Tests for NL plan parsing (commit: ) ### B.2b — Extend MCP Server with Planner Tools (common-plat) - [ ] `chronomind-client.ts` — add planner client functions (commit: ) - `chronomindPlanDay(request, opts)`, `chronomindApplyPlan(planId, opts)`, `chronomindPlanNl(text, opts)` - [ ] `chronomind-tools.ts` — register 2 new MCP tools (commit: ) - `chronomind.planner.planDay` — generate proposed plan from activities - `chronomind.planner.planNl` — generate proposed plan from natural language ### B.3 — Agent Inbox (Web UI) - [ ] `web/src/components/AgentInbox.tsx` — review queue for agent-proposed timers (commit: ) - Use `@bytelyst/ui` components: Card, Badge, Button, Toast — never build custom equivalents - List all `state: 'proposed'` agent actions - Show: agent name, reason, proposed timer details, timestamp - Actions: Approve, Reject, Modify then Approve - Batch approve: "Accept all from [agent]" - Trust level badge per agent (auto-approve toggle) - Every interactive element must have `aria-label` or visible text label - Colors via `--cm-*` CSS custom properties — never hardcode hex values - Track `agent_inbox.action_approved` / `.action_rejected` / `.batch_approved` telemetry - [ ] `web/src/lib/agent-client.ts` — typed API client for agent actions (commit: ) - `listAgentActions(filters)`, `approveAction(id)`, `rejectAction(id)`, `batchApprove(actorId)` - [ ] `web/src/app/(app)/inbox/page.tsx` — agent inbox page route (commit: ) - [ ] Sidebar navigation: add "Inbox" nav item with unread badge count (commit: ) - [ ] Tests for agent inbox (commit: ) ### B.4 — Day Planner UI (Web) - [ ] `web/src/components/DayPlanner.tsx` — plan-my-day interface (commit: ) - Use `@bytelyst/ui` components: Card, Button, Badge, Toast — never build custom equivalents - NL input bar: "Plan my afternoon" → calls `/api/planner/plan-nl` - Structured form fallback: add activities with duration + constraints - Timeline preview: visual preview of proposed plan alongside existing timers - "Apply Plan" button → creates all timers at once + fire `@bytelyst/celebrations` confetti on success - "Edit" per-item before applying (change time, urgency, cascade) - Overflow warnings: "3 activities don't fit — 2h overflow. Suggestions: extend day, shorten activities, move to tomorrow" - Every interactive element must have `aria-label` or visible text label - Colors via `--cm-*` CSS custom properties — never hardcode hex values - [ ] `web/src/lib/planner-client.ts` — typed API client for planner (commit: ) - [ ] `web/src/app/(app)/planner/page.tsx` — planner page route (commit: ) - [ ] Sidebar navigation: add "Plan Day" nav item (commit: ) ### Phase B Exit Criteria - [ ] `POST /api/planner/plan-day` returns valid proposed timeline - [ ] NL input parses multi-activity requests correctly - [ ] 2 new MCP tools in centralized mcp-server (planDay, planNl) - [ ] Agent inbox shows proposed timers with approve/reject/batch actions - [ ] Day planner UI shows timeline preview with apply/edit controls - [ ] All UI uses `@bytelyst/ui` components + `--cm-*` tokens + `aria-label` - [ ] All gated behind feature flags, telemetry events tracked - [ ] All existing tests still pass - [ ] New tests cover planner engine, NL parsing, agent client --- ## Phase C — Webhook Event Wiring + @bytelyst/event-store + Zapier Compatibility > **Goal:** Wire lifecycle events into the existing webhook dispatcher, add domain event persistence via `@bytelyst/event-store`, and add Zapier-compatible endpoints. > **Can run in parallel with Phase D.** **Note:** The webhook dispatcher is already **fully functional** — HMAC-SHA256 signing, exponential backoff retries, event logging, auto-disable after failures. No hardening needed. The gaps are: (1) no lifecycle events actually call the dispatcher, (2) no domain event persistence, (3) no Zapier-compatible format. ### C.1 — Domain Event Store Integration - [ ] Add `@bytelyst/event-store` dependency to backend (commit: ) - [ ] `backend/src/lib/events.ts` — create event store singleton + `emitDomainEvent()` helper (commit: ) - Uses `MemoryEventStore` (or `FileEventStore` for local persistence) - All domain events flow through this — webhook dispatcher subscribes to it - Event shape: `{ type, userId, productId, payload, timestamp, correlationId }` ### C.2 — Wire Lifecycle Events into Dispatcher This is the main missing piece — timer/routine state changes should emit events: - [ ] `backend/src/modules/timers/routes.ts` — emit events on state transitions (commit: ) - `timer.created` on POST create - `timer.fired` / `timer.completed` / `timer.dismissed` / `timer.snoozed` / `timer.paused` / `timer.resumed` on state change - Each event calls `emitDomainEvent()` which fans out to webhook dispatcher - Track `webhook.dispatched` / `webhook.failed` telemetry - [ ] `backend/src/modules/routines/routes.ts` — emit events (commit: ) - `routine.started` / `routine.completed` / `routine.step_completed` - [ ] `backend/src/modules/households/routes.ts` — emit events (commit: ) - `household.member_joined` / `household.member_left` - [ ] `backend/src/modules/shared-timers/routes.ts` — emit events (commit: ) - `shared_timer.created` / `shared_timer.fired` / `shared_timer.acknowledged` - [ ] Tests for event emission + webhook dispatch integration (commit: ) ### C.3 — Zapier-Compatible Webhook Format - [ ] Zapier REST hook endpoints (commit: ) - `GET /api/webhooks/zapier/subscribe` — Zapier registers its callback URL - `DELETE /api/webhooks/zapier/unsubscribe` — Zapier unregisters - `GET /api/webhooks/zapier/sample` — sample payloads per event type (Zapier trigger testing) - Gate behind `isFeatureEnabled('webhooks.zapier')` flag - [ ] Document webhook payload schemas in `docs/WEBHOOK_API.md` (commit: ) ### C.4 — Webhook Management UI (Web) - [ ] `web/src/components/WebhookManager.tsx` — manage webhook subscriptions (commit: ) - Use `@bytelyst/ui` components: Card, Button, Badge, Toast - Create subscription: URL, secret, event types (multi-select from 15 event types) - List subscriptions with status (active, paused, failed) - Delivery log per subscription - Test button: fire a test event - Every interactive element must have `aria-label` or visible text label - Colors via `--cm-*` CSS custom properties - [ ] `web/src/lib/webhook-client.ts` — typed API client (commit: ) - [ ] Add to settings page or new `/settings/webhooks` route (commit: ) ### Phase C Exit Criteria - [ ] Domain events emitted on all 15 lifecycle state changes - [ ] Events persisted via `@bytelyst/event-store` - [ ] Webhook dispatcher called automatically on domain events - [ ] Zapier subscribe/unsubscribe/sample endpoints work - [ ] Webhook management UI in web app with `@bytelyst/ui` components - [ ] All gated behind feature flags, telemetry events tracked - [ ] All existing tests still pass --- ## Phase D — Smart Routine Suggestions + Tempo Mode > **Goal:** Proactive intelligence — suggest routines from patterns + adjust pacing when behind schedule. > **Can run in parallel with Phase C.** ### D.1 — Smart Routine Suggestions (Web Engine) Build on existing `adaptive-snooze.ts` pattern detection approach: - [ ] `web/src/lib/routine-suggestions.ts` — pattern detection engine (commit: ) - Scan timer history for recurring sequences (same labels/categories within similar time windows) - Group by day-of-week patterns (weekday vs weekend) - Min threshold: 3 occurrences of same sequence before suggesting - Output: `RoutineSuggestion { name, steps[], confidence, occurrences, dayPattern }` - Pure TS engine — no React imports, testable with Vitest - [ ] `web/src/lib/routine-suggestions.test.ts` — tests (commit: ) - Test: 3x "coffee → standup → email" on weekdays → suggests "Weekday Morning" routine - Test: fewer than 3 occurrences → no suggestion - Test: weekend vs weekday patterns differentiated - Test: overlapping sequences handled (longest match wins) ### D.2 — Routine Suggestions UI - [ ] `web/src/components/RoutineSuggestionCard.tsx` — dismissable suggestion card (commit: ) - Use `@bytelyst/ui` components: Card, Button, Badge — never build custom equivalents - Shows on dashboard when suggestions available - "Create Routine" → opens RoutineEditor pre-filled + fire `@bytelyst/celebrations` on creation - "Dismiss" → hide for 7 days - "Never suggest this" → permanent dismiss for this pattern - Every interactive element must have `aria-label` or visible text label - Colors via `--cm-*` CSS custom properties - Track `routine_suggest.shown` / `.accepted` / `.dismissed` telemetry - [ ] Wire into `Dashboard.tsx` below the quick timer bar (commit: ) - [ ] Store dismissed suggestions in localStorage (commit: ) ### D.3 — Tempo Mode Engine (Web) - [ ] `web/src/lib/tempo.ts` — pace monitoring engine (commit: ) - Track: actual timer completion/dismissal times vs scheduled times - Detect: running behind by >10 minutes (configurable threshold) - Generate `TempoSuggestion`: - Option A: Compress next N timers by X minutes each - Option B: Skip lowest-priority timer - Option C: Push remaining timers back by delay amount - Option D: Extend day (shift evening timers) - Consider energy/mood if check-in data available - Pure TS engine — no React imports, testable with Vitest - Gate behind `isFeatureEnabled('tempo.enabled')` (checked in UI, engine is pure) - [ ] `web/src/lib/tempo.test.ts` — tests (commit: ) - Test: 20 min behind → 3 options generated - Test: on-time → no suggestions - Test: critical timers never suggested for compression - Test: mood data influences suggestions ("low energy → suggest skip gym") ### D.4 — Tempo Mode UI - [ ] `web/src/components/TempoBar.tsx` — pace indicator bar (commit: ) - Use `@bytelyst/ui` Badge for status + `@bytelyst/gentle-notifications` for soft pace warnings - Shows current pace: "On track", "10 min behind", "30 min behind" - Color: green → yellow → red based on delay (using `--cm-*` tokens) - Expandable: shows suggestion options when behind - Actions: accept suggestion → auto-apply reschedule via `POST /api/timers/:id/reschedule` - Every interactive element must have `aria-label` or visible text label - Track `tempo.drift_detected` / `tempo.adjustment_applied` telemetry - [ ] Wire into Dashboard header area (commit: ) - [ ] Gentle notification when pace shifts from green to yellow (via `@bytelyst/gentle-notifications`) (commit: ) ### Phase D Exit Criteria - [ ] Routine suggestions detect patterns from timer history - [ ] Suggestion card appears on dashboard with create/dismiss actions using `@bytelyst/ui` - [ ] Tempo engine detects schedule drift and generates adjustment options - [ ] Tempo bar shows pace status with actionable suggestions - [ ] Gentle notifications for pace warnings via `@bytelyst/gentle-notifications` - [ ] Celebrations on routine creation via `@bytelyst/celebrations` - [ ] All gated behind feature flags, telemetry events tracked - [ ] All existing tests still pass - [ ] New engine tests cover edge cases --- ## Phase E — Client-Side Sync Integration > **Goal:** Make cross-device sync actually work end-to-end (Web ↔ Backend ↔ iOS ↔ Android). > **Depends on:** All other phases (uses the APIs they create). ### E.1 — Web Sync Manager Activation `platform-sync.ts` already has full sync code. Wire it into the app lifecycle: - [ ] `web/src/lib/use-sync.ts` — verify/fix the React hook that triggers sync (commit: ) - Auto-sync on app launch (if authenticated + sync enabled) - Auto-sync on timer create/update/delete (debounced, 5s) - Manual sync button in settings - Sync status indicator: "Last synced 2m ago" / "Syncing..." / "Offline (3 queued)" - Handle pulled timers: merge into Zustand store (upsert by ID, respect syncVersion) - Handle conflicts: server-wins for now, show conflict toast - [ ] `web/src/app/(app)/settings/page.tsx` — add sync section (commit: ) - Toggle: "Enable cross-device sync" - Sign in / sign out (via `@bytelyst/react-auth`) - Sync status display - "Sync Now" button - "Clear local data" button - [ ] Web sync integration tests (commit: ) ### E.2 — iOS Sync Manager - [ ] `ios/ChronoMind/Shared/Cloud/PlatformSyncManager.swift` — verify/complete REST sync client (commit: ) - Uses existing `BLSyncEngine` from ByteLystPlatformSDK (or direct REST if SDK not ready) - Pull delta: `GET /timers/sync?since=` + `GET /routines/sync?since=` - Push batch: `POST /timers/batch` + `POST /routines/batch` - Map between `CMTimer` ↔ `SyncTimerDTO` (same shape as web DTOs) - Offline queue: persist pending changes in UserDefaults - Auto-sync on app foreground + after timer changes - [ ] Wire into `TimerStore.swift` — sync on state changes (commit: ) - [ ] Settings UI: sync toggle + sign in + last sync time (commit: ) - [ ] iOS sync tests (commit: ) ### E.3 — Android Sync Manager - [ ] `android/app/.../sync/SyncRepository.kt` — verify/complete REST sync client (commit: ) - Same delta sync + batch upsert pattern as iOS/web - Map between `TimerEntity` ↔ `SyncTimerDTO` - Offline queue in Room database (or SharedPreferences) - WorkManager for background sync (periodic, 15m interval) - [ ] Wire into `TimerViewModel.kt` — sync on state changes (commit: ) - [ ] Settings screen: sync toggle + sign in + last sync time (commit: ) - [ ] Android sync tests (commit: ) ### E.4 — Auth Flow (All Platforms) - [ ] Web: sign in / register via `@bytelyst/react-auth` + platform-service (commit: ) - [ ] iOS: sign in via `BLAuthClient` (commit: ) - [ ] Android: sign in via `BLAuthClient` Kotlin SDK (commit: ) - [ ] Verify JWT token flow: login → access token → sync API calls → token refresh (commit: ) ### Phase E Exit Criteria - [ ] Create timer on web → appears on iOS and Android after sync - [ ] Create timer on iOS → appears on web and Android after sync - [ ] Offline changes queue and flush when connectivity restored - [ ] Auth flow works on all 3 platforms - [ ] No data loss during sync (conflict resolution: server-wins) - [ ] All existing tests still pass on all platforms --- ## Verification Commands ```bash # ── Backend ──────────────────────────────────────── cd backend && pnpm test && pnpm run typecheck && pnpm run build # ── Web ──────────────────────────────────────────── cd web && pnpm test && pnpm run typecheck && pnpm run build # ── iOS ──────────────────────────────────────────── cd ios && xcodegen generate && xcodebuild -scheme ChronoMind -sdk iphonesimulator build # ── Android ──────────────────────────────────────── cd android && ./gradlew :app:assembleDebug && ./gradlew :app:test ``` --- ## Commit Convention All commits follow: `type(scope): description` | Scope | Examples | |-------|---------| | `ecosystem` | Kill switch, feedback, accessibility, feature flags, telemetry (Phase 0) | | `mcp` | Backend REST endpoints, MCP server tool extensions (Phase A) | | `agent-actions` | Agent action audit trail module (Phase A) | | `ai-context` | LLM-powered context messages (Phase A) | | `planner` | Day planner engine, NL interface, routes (Phase B) | | `agent-inbox` | Agent inbox UI, client (Phase B) | | `webhook` | Event wiring, Zapier compat, management UI (Phase C) | | `events` | Domain event store integration (Phase C) | | `routine-suggest` | Pattern detection engine, suggestion UI (Phase D) | | `tempo` | Tempo engine, pace bar UI (Phase D) | | `sync` | Client-side sync managers (web, iOS, Android) (Phase E) | | `auth` | Auth flow integration (Phase E) | --- ## Risk Mitigation | Risk | Mitigation | |------|------------| | MCP tools break existing timer API | New backend endpoints are additive; MCP tools proxy via centralized mcp-server — no coupling | | Planner engine conflicts with manual timers | Plans are **proposed first**, user must approve before creating | | Webhook dispatch overloads | Rate limit: max 100 webhooks/min per user, exponential backoff (already implemented in dispatcher) | | Sync conflicts lose data | Server-wins strategy + conflict toast notification, full export always available | | LLM context messages slow | LLM is optional enhancement — keyword rules remain primary with <1ms latency | | Phase E scope creep | Auth flow is minimal: login/token/refresh only. No registration, password reset, OAuth in v1 | | New features break existing | All 7 new features gated behind feature flags (default `false`). Can ship incrementally | | Missing ecosystem packages | Phase 0 fills all gaps before new code — prevents cascading omissions | --- ## Audit Findings (Ecosystem Gap Review) Systematic audit against `learning_ai_common_plat/packages/` (58 packages) revealed: ### Already Correct ✅ - Auth pipeline: `@bytelyst/auth-client` + `@bytelyst/react-auth` + `registerOptionalJwtContext` — fully wired - Backend config: `@bytelyst/backend-config` + `backend-flags` + `backend-telemetry` — all used - Web clients: `@bytelyst/feature-flag-client` + `telemetry-client` + `diagnostics-client` — all integrated - Data layer: `@bytelyst/datastore` + `cosmos` + `field-encrypt` — all used in backend - Sync: `@bytelyst/sync` + `api-client` — integrated in `platform-sync.ts` - Design: `@bytelyst/design-tokens` (`--cm-*` CSS props) + `@bytelyst/ui` — both in web - Product config: `PRODUCT_ID = 'chronomind'` properly sourced from `auth-api.ts`, not hardcoded in backend ### Gaps Fixed in This Roadmap ❌ → ✅ | Gap | Severity | Fixed In | |-----|----------|----------| | No `@bytelyst/kill-switch-client` | **Critical** | Phase 0.1 | | No `@bytelyst/feedback-client` | Medium | Phase 0.2 | | No `@bytelyst/accessibility` helpers | Medium | Phase 0.3 | | No feature flags for new features | **Critical** | Phase 0.4 | | No telemetry events for new features | Medium | Phase 0.5 | | MCP tools built in product backend (wrong arch) | **Critical** | Phase A (dual-layer: backend REST + mcp-server proxy) | | Webhook dispatcher never called (no event wiring) | High | Phase C.2 | | No domain event persistence (`@bytelyst/event-store`) | Medium | Phase C.1 | | No `@bytelyst/celebrations` for achievements | Low | Phase B.4, D.2 | | No `@bytelyst/gentle-notifications` for warnings | Low | Phase D.4 | | No `aria-label` requirements stated for new UI | Medium | All UI tasks now require it | | No `@bytelyst/ui` usage requirement for new components | Medium | All UI tasks now require it | | No `--cm-*` token requirement for new components | Medium | All UI tasks now require it | ### MCP Architecture Correction **Wrong (original roadmap):** Build `backend/src/mcp/` with tool contracts + registration in product backend. **Correct:** The centralized MCP server (`learning_ai_common_plat/services/mcp-server`, port 4007) already has `chronomind.*` tools (7 existing). New tools extend that server; product backend only provides REST endpoints. Existing MCP tools in mcp-server: `chronomind.timers.create`, `.list`, `.delete`, `chronomind.routines.list`, `.validate`, `chronomind.syncStatus`, `chronomind.sharedTimers.share`, `chronomind.households.list`. ### Webhook Dispatcher Status Correction **Wrong (original roadmap):** Called it a "skeleton" needing hardening. **Correct:** `backend/src/modules/webhooks/dispatcher.ts` is **fully implemented** (201 LOC): - HMAC-SHA256 signing with `t=,v1=` format - Exponential backoff retries (100ms × 2^attempt, max 5s) - Event log creation + delivery tracking - Auto-increment failure count on subscription - `verifySignature()` consumer helper with constant-time comparison - 10s timeout per delivery attempt The actual gap is that **no code path calls `dispatchEvent()`** — it's built but unwired. --- ## Notes - **Backend migration (original item #5) is ALREADY DONE** — backend lives at `learning_ai_clock/backend/` (port 4011) with 5 modules + webhooks. No work needed. - **Webhook dispatcher (original item #7) is FULLY BUILT** — HMAC, retries, event logging all done. Phase C wires lifecycle events into it and adds Zapier compat. - **Platform-sync client (original item #9) is FULLY BUILT** — `web/src/lib/platform-sync.ts` has 547 LOC with full sync, DTOs, offline queue, `@bytelyst/sync` engine. Phase E wires it into the app lifecycle and verifies iOS/Android clients. - **MCP server already has 8 ChronoMind tools** in `learning_ai_common_plat/services/mcp-server/src/modules/chronomind/`. New tools extend this, not the product backend. - All new code must include `productId: "chronomind"` on every Cosmos document. - All new UI must use `@bytelyst/ui` components, `--cm-*` CSS properties, and `aria-label` on every interactive element. - All new backend routes must be gated behind feature flags (default `false`), use `req.log` (never `console.log`), and track telemetry events.