Add AI-enriched context message generation:
- backend/src/lib/ai-context.ts: LLM-powered context generator with keyword fallback
- Calls extraction-service timer-context task when EXTRACTION_SERVICE_URL is set
- Falls back to keyword rules, then generic message
- Gated behind isFeatureEnabled('ai_context_messages.enabled')
- backend/src/lib/config.ts: Add EXTRACTION_SERVICE_URL env var
- backend/src/server.ts: POST /api/context-message route
- web/src/lib/context-messages.ts: fetchEnrichedMessage() with graceful degradation
- Updated AGENTIC_AI_ROADMAP.md checkboxes for Phase A.1 + A.2
All 219 backend tests + 394 web tests pass. No breaking changes.
37 KiB
ChronoMind — Agentic AI Roadmap
Product: ChronoMind — AI-Powered Contextual Clock & Timer Repo:
learning_ai_clockCreated: 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.
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/.deletechronomind.routines.list/.validatechronomind.syncStatuschronomind.sharedTimers.sharechronomind.households.list
These proxy to chronomind-backend (port 4011) via chronomind-client.ts.
Architecture for new MCP tools:
- Backend (port 4011): Add new REST endpoints (planner, agent-actions, reschedule, availability, context-message)
- MCP Server (port 4007): Extend
chronomind-tools.ts+chronomind-client.tsto expose new endpoints as MCP tools - 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)
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-clientto web/package.json
- Same pattern as NomGap/NoteLett:
- Wire into
web/src/app/providers.tsx— init on mount (commit:f3e14e2)
0.2 — Feedback Client (Web)
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(AGENTIC-3): Wire feedback button into settings page UI
0.3 — Accessibility Package (Web)
- Add
@bytelyst/accessibilityto web/package.json (commit:f3e14e2) - Integrate helpers into existing modals (commit: )
- TODO(AGENTIC-4): Apply focus trap + screen reader announcements to CreateTimerModal, AlarmOverlay
- Ensure all
--cm-*color tokens meet WCAG AA contrast
0.4 — Feature Flags for New Features (Backend)
- 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
- Define telemetry event names for all new features (commit:
f3e14e2)mcp.tool_executed,mcp.tool_failedplanner.day_planned,planner.plan_applied,planner.plan_rejectedagent_inbox.action_approved,agent_inbox.action_rejected,agent_inbox.batch_approvedtempo.drift_detected,tempo.adjustment_appliedroutine_suggest.shown,routine_suggest.accepted,routine_suggest.dismissedai_context.enriched,ai_context.fallback_usedwebhook.dispatched,webhook.failed
- Add
trackEvent()calls in backend routes and web components as they're built (ongoing through all phases)
Phase 0 Exit Criteria
- Kill switch client initialized on web app startup (
f3e14e2) - Feedback client created (
f3e14e2) — UI entry point deferred to TODO(AGENTIC-3) - Accessibility package added (
f3e14e2) — modal integration deferred to TODO(AGENTIC-4) - 7 new feature flags registered (all default
false) (f3e14e2) - Telemetry event names defined (16 events, backend + web) (
f3e14e2) - 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:
backend/src/modules/timers/routes.ts— add reschedule + availability endpoints (commit:686f5fb)POST /api/timers/:id/reschedule— shift timer by delta or to new timeGET /api/timers/availability?start=<ISO>&end=<ISO>&minSlotMinutes=<N>— find free slots- Gate behind
isFeatureEnabled('mcp.enabled')flag
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
- Tests for new timer + routine endpoints (commit:
29a4802)
A.2 — Agent Action Audit Trail (New Backend Module)
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"
- Fields:
backend/src/modules/agent-actions/repository.ts— CRUD (commit:29a4802)- Container:
cm_agent_actions, partition:/userId - Uses
@bytelyst/datastoregetCollection()— never direct Cosmos SDK
- Container:
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 actionPOST /api/agent-actions/:id/reject— reject proposed actionPOST /api/agent-actions/batch-approve— batch approve by actorId- Gate behind
isFeatureEnabled('agent_inbox.enabled')flag
- Register
agentActionRoutesinserver.ts(commit:29a4802) - Register
cm_agent_actionscontainer incosmos-init.ts(commit:29a4802) - 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/:
chronomind-client.ts— add client functions for new endpoints (commit: )chronomindTimerReschedule(timerId, { delta?, targetTime? }, opts)chronomindTimerAvailability({ start, end, minSlotMinutes }, opts)chronomindRoutineStart(routineId, opts)chronomindAgentActionsList(filters, opts)chronomindAgentActionApprove(actionId, opts)
chronomind-tools.ts— register 5 new MCP tools (commit: )chronomind.timers.reschedule— shift timer by delta or to new timechronomind.timers.availability— find free time slotschronomind.routines.start— start a routine templatechronomind.agentActions.list— list pending agent actionschronomind.agentActions.approve— approve a proposed action- All write tools record agent action via A.2 endpoints, passing
actorId,actorType: 'mcp',reason
- MCP tool tests (commit: )
A.4 — Context-Aware AI Messages (LLM upgrade)
Upgrade web/src/lib/context-messages.ts with optional LLM enrichment:
backend/src/lib/ai-context.ts— LLM-powered context message generator (commit: )- Accepts: timer label, category, urgency, user's recent timers, time of day
- Returns: enriched prep message (e.g., "Your standup is in 30m — you had 3 unresolved items from yesterday")
- Falls back to existing keyword rules if LLM unavailable
- Uses
@bytelyst/extractionclient to call extraction-servicetimer-contexttask, or direct@bytelyst/ollama-client - Gate behind
isFeatureEnabled('ai_context_messages.enabled')flag
- Backend route:
POST /api/context-message(commit: ) web/src/lib/context-messages.ts— addfetchEnrichedMessage()that calls backend endpoint (commit: )- Graceful degradation: keyword rules remain primary, LLM messages shown as "AI suggestion"
- Track
ai_context.enrichedorai_context.fallback_usedtelemetry events
- Tests for AI context generation (commit: )
Phase A Exit Criteria
- 3 new REST endpoints in chronomind-backend (reschedule, availability, routine start)
- Agent action module with full CRUD + batch approve
- 5 new MCP tools registered in centralized mcp-server
- Context messages enriched by LLM with keyword fallback
- All gated behind feature flags (default off)
- Telemetry events tracked for all new operations
- All existing tests still pass (
pnpm testin backend + web + mcp-server) - 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-messagesrules) - Step 5: Assign cascade presets based on urgency (reuse
cascade.tsdefaults) - Step 6: Add prep time buffers (reuse
prep-time.tslogic) - 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_appliedtelemetry events - Use
req.logfor logging — neverconsole.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/extractionclient to extraction-service, or regex-based NL parser (ported from webnl-parser.ts) - Returns same
PlanDayResponseas 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 activitieschronomind.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/uicomponents: 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-labelor visible text label - Colors via
--cm-*CSS custom properties — never hardcode hex values - Track
agent_inbox.action_approved/.action_rejected/.batch_approvedtelemetry
- Use
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/uicomponents: 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/celebrationsconfetti 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-labelor visible text label - Colors via
--cm-*CSS custom properties — never hardcode hex values
- Use
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-dayreturns 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/uicomponents +--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-storedependency to backend (commit: ) backend/src/lib/events.ts— create event store singleton +emitDomainEvent()helper (commit: )- Uses
MemoryEventStore(orFileEventStorefor local persistence) - All domain events flow through this — webhook dispatcher subscribes to it
- Event shape:
{ type, userId, productId, payload, timestamp, correlationId }
- Uses
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.createdon POST createtimer.fired/timer.completed/timer.dismissed/timer.snoozed/timer.paused/timer.resumedon state change- Each event calls
emitDomainEvent()which fans out to webhook dispatcher - Track
webhook.dispatched/webhook.failedtelemetry
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 URLDELETE /api/webhooks/zapier/unsubscribe— Zapier unregistersGET /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/uicomponents: 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-labelor visible text label - Colors via
--cm-*CSS custom properties
- Use
web/src/lib/webhook-client.ts— typed API client (commit: )- Add to settings page or new
/settings/webhooksroute (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/uicomponents - 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/uicomponents: Card, Button, Badge — never build custom equivalents - Shows on dashboard when suggestions available
- "Create Routine" → opens RoutineEditor pre-filled + fire
@bytelyst/celebrationson creation - "Dismiss" → hide for 7 days
- "Never suggest this" → permanent dismiss for this pattern
- Every interactive element must have
aria-labelor visible text label - Colors via
--cm-*CSS custom properties - Track
routine_suggest.shown/.accepted/.dismissedtelemetry
- Use
- Wire into
Dashboard.tsxbelow 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/uiBadge for status +@bytelyst/gentle-notificationsfor 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-labelor visible text label - Track
tempo.drift_detected/tempo.adjustment_appliedtelemetry
- Use
- 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
BLSyncEnginefrom 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
- Uses existing
- 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
BLAuthClientKotlin 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
# ── 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 inplatform-sync.ts - Design:
@bytelyst/design-tokens(--cm-*CSS props) +@bytelyst/ui— both in web - Product config:
PRODUCT_ID = 'chronomind'properly sourced fromauth-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.tshas 547 LOC with full sync, DTOs, offline queue,@bytelyst/syncengine. 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/uicomponents,--cm-*CSS properties, andaria-labelon every interactive element. - All new backend routes must be gated behind feature flags (default
false), usereq.log(neverconsole.log), and track telemetry events.