learning_ai_clock/docs/AGENTIC_AI_ROADMAP.md

689 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 `<MaintenanceBanner />`, 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~~ — templates now cloned via `crypto.randomUUID()`, original stays reusable (0e7c1ae) |
| ✅ **TODO-005** | high | A.4 | `backend/src/lib/ai-context.ts` | ~~Wire LLM~~ — dual-path: extraction-service → Ollama `/api/generate` (5s timeout, feature-gated) (229ce4f) |
| ✅ **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=<ISO>&end=<ISO>&minSlotMinutes=<N>` — 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=<ISO>` + `GET /routines/sync?since=<ISO>`
- 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=<timestamp>,v1=<signature>` 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.