Orchestrata Ultimate / Specs / 017-calendar-integration

017-calendar-integration: Calendar Integration

The Calendar Integration is a VizInt Command Center gadget that provides calendar visibility and event management within the Orchestrata dashboard. It displays today's events with time blocks, supports creating events from the command center, and automatically syncs orchestration session start/close times to the user's calendar. The gadget supports both Google Calendar (via OAuth2) and CalDAV-compatible servers (via app password).

At a glance

Item Value
Spec directory specs/017-calendar-integration/
Status line in the spec Draft
Requirement IDs defined 70
With a @traces citation in src/ 23 (32.9%)
With a @traces citation in tests/ 0 (0.0%)
Tracked files 6
RTM page 017-calendar-integration

Reading this spec

The Calendar Integration is a VizInt Command Center gadget that shows calendar events and manages them inside the Orchestrata dashboard. It displays today's events as time blocks, creates events from the command center, and pushes orchestration session start and close times to the user's calendar. Before it, session times were recorded in the session context file but invisible in the user's calendar, and time blocking for orchestration work was manual.

The scope is five user stories (view today's events, connect calendar accounts, create events, sync session times, navigate between days) and five functional groups: calendar data fetching, Google Calendar OAuth2, CalDAV integration, event creation and session calendar sync. Requirement IDs use the REQ-017- prefix.

The design is a browser-side JavaScript gadget with no Python backend. It supports Google Calendar through OAuth2 and CalDAV-compatible servers through a proxied endpoint, renders a day-view timeline, has an event creation form with title, times, description and calendar selector, and registers as a Command Center gadget through a GadgetManifest with the category productivity. It learns about session lifecycle from other gadgets through the event bus.

Because the gadget is browser-side JavaScript, the Python trace table is small and its entries are in other packages: orchestrata_ultimate/memory/cold_store, orchestrata_ultimate/memory/embedding, orchestrata_ultimate/memory/compressor and orchestrata_ultimate/llm/client. The per-requirement view is on the RTM page.

The spec's status line reads Draft. It tracks 6 files and defines 70 requirement IDs. The full text follows below.

Measured coverage is 23 of 70 requirements cited by at least one @traces in src/ (32.9%), spread over 6 modules; the module citing the most of them is orchestrata_ultimate/memory/cold_store (6 requirements). In tests/, 0 requirements are cited by a test-side @traces.

Coverage gaps: 47 requirements have no citing symbol. The largest untraced groups are REQ-017-* (47). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (0 against 23).

Requirements

Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.

ID Done Requirement Traced by
REQ-017-001 no Gadget displays a vertical day-view timeline for the current date none
REQ-017-002 no Events are rendered as colored time blocks at their correct time positions none
REQ-017-003 no Each time block shows the event title and time range none
REQ-017-004 no All-day events are displayed in a separate section above the hourly timeline none
REQ-017-005 no Multi-calendar events are color-coded by source calendar none
REQ-017-006 no Current time is indicated by a horizontal red marker line none
REQ-017-007 no Time marker updates its position every 60 seconds none
REQ-017-008 no Timeline auto-scrolls to center the current time on first load none
REQ-017-009 no Clicking an event shows a detail popover none
REQ-017-010 no Detail popover includes: full title, description, location, attendees, calendar name none
REQ-017-011 no Detail popover includes a link to the event in the source calendar app none
REQ-017-012 no Popover dismisses on click outside or Escape key 1
REQ-017-013 no Event data auto-refreshes every 5 minutes (configurable) 1
REQ-017-014 no Manual refresh button in gadget header triggers immediate re-fetch 1
REQ-017-015 no Last sync timestamp displayed in the gadget footer 2
REQ-017-016 no Settings panel provides "Connect Google Calendar" button 1
REQ-017-017 no Button initiates OAuth2 implicit grant flow in a popup window none
REQ-017-018 no OAuth2 access token stored in localStorage encrypted via Web Crypto API 1
REQ-017-019 no Token expiration detected on 401 response, re-authentication prompted none
REQ-017-020 no Calendar list fetched via calendar.list after successful authentication none
REQ-017-021 no Settings panel provides CalDAV connection form none
REQ-017-022 no Form fields: server URL, username, app password none
REQ-017-023 no Credentials stored in localStorage encrypted with AES-GCM none
REQ-017-024 no Available calendars discovered via CalDAV PROPFIND none
REQ-017-025 no Connection validated on form submission with test PROPFIND none
REQ-017-026 no Multiple calendar accounts connectable simultaneously none
REQ-017-027 no Individual calendars toggleable on/off within each account none
REQ-017-028 no Connection status indicator: green (connected), yellow (expiring), red (error) none
REQ-017-029 no "Disconnect" button removes credentials and cached events none
REQ-017-030 no Account list persisted in localStorage none
REQ-017-031 no "New Event" button in gadget header opens creation form 1
REQ-017-032 no Form fields: title, start time, end time, description, calendar selector 1
REQ-017-033 no Start time defaults to next 30-minute boundary 1
REQ-017-034 no End time defaults to 30 minutes after start time none
REQ-017-035 no Calendar selector shows all writable calendars from connected accounts none
REQ-017-036 no Empty title rejected with inline error message none
REQ-017-037 no End time before start time rejected with inline error message 1
REQ-017-038 no Duration exceeding 24 hours rejected with inline error message 1
REQ-017-039 no Invalid date/time format rejected with inline error message 1
REQ-017-040 no Google Calendar events created via events.insert endpoint none
REQ-017-041 no CalDAV events created via PUT with VEVENT body 1
REQ-017-042 no Created event appears in timeline immediately on success 1
REQ-017-043 no API error displayed with retry button (form data preserved) 1
REQ-017-044 no calendar.event.created emitted on ctx.bus after success 1
REQ-017-045 no VEVENT generated with RFC 5545 compliant properties 1
REQ-017-046 no GadgetBridge subscription to session.events for event_type: "opened" none
REQ-017-047 no Calendar event created with title "Orchestrata Session {number}" none
REQ-017-048 no Event description includes session purpose/goals none
REQ-017-049 no Event start time matches session open timestamp none
REQ-017-050 no Event created in configurable target calendar (default: primary) none
REQ-017-051 no GadgetBridge subscription to session.events for event_type: "closed" none
REQ-017-052 no Corresponding calendar event end time updated to session close timestamp none
REQ-017-053 no Session-to-calendar-event mapping stored in localStorage none
REQ-017-054 no If matching calendar event not found, new event created with estimated duration 1
REQ-017-055 no Session sync enable/disable toggle in gadget settings 1
REQ-017-056 no Target calendar selector in gadget settings 1
REQ-017-057 no Session event includes a dashboard link in description 1
REQ-017-058 no Failed sync retried with exponential backoff (1s, 2s, 4s, max 30s) 1
REQ-017-059 no Maximum 5 retry attempts before logging failure none
REQ-017-060 no Pending syncs persisted in localStorage for retry on page reload none
REQ-017-061 no Previous day button (left arrow) in gadget header none
REQ-017-062 no Next day button (right arrow) in gadget header none
REQ-017-063 no "Today" button returns to current date none
REQ-017-064 no Date picker allows jumping to any date none
REQ-017-065 no Current displayed date shown in gadget header none
REQ-017-066 no Events for navigated date fetched on demand none
REQ-017-067 no Fetched events cached with 5-minute TTL 1
REQ-017-068 no Loading spinner shown during fetch none
REQ-017-069 no Cache hit renders immediately without spinner none
REQ-017-070 no Navigation preserves scroll position relative to time of day none

Code that traces this spec

Module Symbols Requirements
orchestrata_ultimate/llm/client 5 4
orchestrata_ultimate/llm/exceptions 1 2
orchestrata_ultimate/memory/cold_store 6 6
orchestrata_ultimate/memory/compressor 5 5
orchestrata_ultimate/memory/embedding 5 5
orchestrata_ultimate/memory/memory_engine 1 1

Checklists

checklists/README.md

Calendar Integration Checklists

Project: Orchestrata Calendar Integration (Spec 017) Component: Calendar Gadget Status: Planning Phase Owner: Architecture Team


Overview

The Calendar Integration is a VizInt Command Center gadget that provides calendar visibility and event management within the Orchestrata dashboard. It supports Google Calendar (OAuth2) and CalDAV servers (app password), displays today's events as time blocks, enables event creation, and automatically syncs session start/close times to the user's calendar.


Checklist Summary
Checklist Total Items Completed Progress
Requirements 70+ 0 0%
Constitutional Compliance 55+ 0 0%
Testing Plan 120+ 0 0%
TOTAL 245+ 0 0%

Key Responsibilities
1. Calendar Event Display
2. Calendar Account Management
3. Event Creation
4. Session Calendar Sync

Performance Targets
Metric Target Critical Threshold
Google API Fetch < 1s P95 < 2s P99
CalDAV Fetch < 2s P95 < 3s P99
Timeline Render (20 events) < 100ms < 200ms
Event Creation < 2s P95 < 3s P99
Cache Hit < 10ms < 50ms
Memory Usage < 10MB < 20MB

Checklist Files
1. requirements.md

Functional requirements organized by user stories:

2. constitutional.md

Compliance with all 11 constitutional articles covering agent autonomy, Prolog governance, session isolation, extensibility, testing standards, observability, graceful degradation, and versioning.

3. testing.md

Comprehensive testing strategy:


Integration Points
Upstream Dependencies
Downstream Consumers

Dependencies
Required APIs
Required Libraries
Optional Services

References

Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team

checklists/constitutional.md

Calendar Integration - Constitutional Compliance

Component: Calendar Gadget Spec: 017-calendar-integration Status: Compliance Review Total Compliance Items: 50+


Overview

This document tracks compliance of the Calendar Integration gadget with the Orchestrata Constitution. As a browser-side productivity gadget, the calendar integration has a lighter constitutional footprint than core system components but must still meet security, observability, and extensibility requirements.


Article I: Agent Autonomy

Principle: Agents retain autonomy; gadgets observe and assist without interference.

Compliance Requirements

Priority: Medium Verification: Code review + integration tests


Article II: Prolog as Single Source of Truth

Principle: Governance rules defined in Prolog.

Compliance Requirements

Priority: Medium Verification: Integration tests


Article III: Session Isolation

Principle: Sessions are isolated; state does not leak between sessions.

Compliance Requirements

Priority: High Verification: Integration tests


Article IV: Hooks for Extensibility

Principle: Extension points for customization without core modification.

Compliance Requirements

Priority: Medium Verification: Architecture review


Article V: Minimal Core, Maximal Extension

Principle: Core is minimal; features added via extensions.

Compliance Requirements

Priority: High Verification: Architecture review


Article VI: Implementation Standards

Principle: JavaScript ES2024 with modern async patterns (browser-side gadget).

Compliance Requirements

Priority: High Verification: Code review + linting


Article VII: Testing Without Mocks

Principle: Tests use real implementations.

Compliance Requirements

Priority: Critical Verification: Test code review


Article VIII: Metrics and Observability

Principle: All operations observable and measurable.

Compliance Requirements

Priority: Medium Verification: Log review + observability tests


Article IX: Graceful Degradation

Principle: System degrades gracefully under failure.

Compliance Requirements

Priority: High Verification: Failure injection tests


Article X: Version Compatibility

Principle: APIs are versioned; breaking changes avoided.

Compliance Requirements

Priority: Medium Verification: Compatibility tests


Article XI: Documentation First

Principle: Documentation precedes implementation.

Compliance Requirements

Priority: High Verification: Documentation review


Summary Statistics
Article Total Items Completed Percentage
Article I (Autonomy) 5 0 0%
Article II (Prolog) 5 0 0%
Article III (Isolation) 5 0 0%
Article IV (Hooks) 5 0 0%
Article V (Minimal Core) 5 0 0%
Article VI (Implementation) 5 0 0%
Article VII (No Mocks) 5 0 0%
Article VIII (Observability) 5 0 0%
Article IX (Degradation) 5 0 0%
Article X (Versioning) 5 0 0%
Article XI (Documentation) 5 0 0%
TOTAL 55 0 0%

Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team

checklists/requirements.md

The requirement list above comes from this file; 0 of 70 checkbox items are ticked.

checklists/testing.md

Calendar Integration - Testing Plan

Component: Calendar Gadget Spec: 017-calendar-integration Status: Test Planning Phase Total Test Cases: 120+


Overview

This document defines the testing strategy for the Calendar Integration gadget. All tests follow the strict "no mocking" policy. Unit tests use JSDOM for real DOM interaction, integration tests use real calendar APIs (sandbox accounts), and E2E tests use Playwright with a real browser.


Test Categories Summary
Category Test Count Purpose Priority
Unit Tests 50+ Core logic validation Critical
Integration Tests 35+ API and system integration Critical
E2E Tests 20+ Full browser workflow High
Performance Tests 15+ Latency and rendering High
TOTAL 120+

Unit Tests (50+)
Timeline Rendering (15 tests)
Event Creation Form (10 tests)
Event Cache (10 tests)
Session Sync Engine (10 tests)
iCalendar Parser (5 tests)

Integration Tests (35+)
Google Calendar API (10 tests)
CalDAV Integration (10 tests)
Session Sync Integration (10 tests)
Credential Management (5 tests)

E2E Tests (20+)

Performance Tests (15+)

Summary Statistics
Category Test Count Completed Percentage
Unit Tests 50 0 0%
Integration Tests 35 0 0%
E2E Tests 20 0 0%
Performance Tests 15 0 0%
TOTAL 120 0 0%

Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team

Other tracked files

Full spec text

Verbatim from specs/017-calendar-integration/spec.md; headings are pushed down two levels.

SPEC-017: Calendar Integration

Metadata


Overview

What

The Calendar Integration is a VizInt Command Center gadget that provides calendar visibility and event management within the Orchestrata dashboard. It displays today's events with time blocks, supports creating events from the command center, and automatically syncs orchestration session start/close times to the user's calendar. The gadget supports both Google Calendar (via OAuth2) and CalDAV-compatible servers (via app password).

Why
How

User Scenarios

US-001: View Today's Calendar Events

As a developer using the Command Center I want to see today's calendar events in a timeline view So that I can plan my orchestration work around existing commitments

Priority: P0

Acceptance Criteria:

US-002: Connect Calendar Accounts

As a developer I want to connect my Google Calendar and CalDAV accounts So that the calendar gadget can display my events

Priority: P0

Acceptance Criteria:

US-003: Create Calendar Events

As a developer I want to create calendar events from the Command Center So that I can block time for orchestration tasks without switching apps

Priority: P1

Acceptance Criteria:

US-004: Sync Session Times to Calendar

As a developer I want session start and close times automatically recorded in my calendar So that I have a permanent record of my orchestration work sessions

Priority: P1

Acceptance Criteria:

US-005: Navigate Between Days

As a developer I want to view calendar events for other days So that I can plan ahead or review past sessions

Priority: P2

Acceptance Criteria:

Standardized Acceptance Criteria
SAC-US1: View Today's Calendar Events
SAC-US1: View Today's Calendar Events
# Criterion Verification
SAC-US1-01 Calendar gadget renders a day-view timeline with all events for the current date within 2 seconds of mount Playwright E2E: mount gadget with test calendar, assert timeline container and event blocks present within 2s
SAC-US1-02 Events are rendered as colored time blocks with title and time range visible at default zoom Vitest DOM: render 5 events, assert each block has .event-title and .event-time text content
SAC-US1-03 All-day events are displayed in a dedicated section above the hourly timeline Vitest DOM: render mix of timed and all-day events, assert all-day events in .allday-section above .timeline-section
SAC-US1-04 Events from different calendars are color-coded by their source calendar color Vitest DOM: render events from 2 calendars with different colors, assert background-color matches calendar color
SAC-US1-05 A horizontal "now" marker line is rendered at the current time and updates every 60 seconds Vitest DOM: render timeline, assert .now-marker position matches current hour; advance fake timer 60s, assert position updated
SAC-US1-06 Clicking an event opens a detail popover with title, description, location, and attendees Playwright E2E: click event block, assert popover visible with all 4 fields populated
SAC-US1-07 On first load, the timeline scroll position centers the current time in the viewport Vitest DOM: mount at 14:00, assert scrollTop positions 14:00 within the middle third of the viewport
SAC-US2: Connect Calendar Accounts
# Criterion Verification
SAC-US2-01 "Connect Google Calendar" button opens an OAuth2 popup with correct client_id and scopes Playwright E2E: click button, assert popup URL contains accounts.google.com/o/oauth2 with expected client_id and scope params
SAC-US2-02 After OAuth2 callback, access token is stored in localStorage under commandcenter.state.calendar.google.token Playwright E2E: complete OAuth2 flow with sandbox account, assert localStorage key exists with valid token JSON
SAC-US2-03 CalDAV connection form accepts server URL, username, and app password and validates URL format Vitest DOM: submit form with invalid URL, assert validation error; submit with valid URL, assert no error
SAC-US2-04 CalDAV credentials are encrypted with AES-GCM via Web Crypto API before localStorage write Integration test: connect CalDAV, read raw localStorage value, assert it is not plaintext and round-trip decrypts correctly
SAC-US2-05 Multiple accounts (Google + CalDAV) can be connected and display events simultaneously Playwright E2E: connect 1 Google + 1 CalDAV account, assert events from both appear in timeline with distinct colors
SAC-US2-06 Individual calendars within an account can be toggled on/off and events update immediately Playwright E2E: toggle off a calendar, assert its events disappear; toggle on, assert they reappear
SAC-US2-07 Connection status indicator shows green (connected), yellow (token expiring), or red (error) per account Vitest DOM: set account status to each state, assert .status-indicator has correct CSS class
SAC-US2-08 Disconnecting an account removes all stored credentials, cached events, and associated calendars from the UI Playwright E2E: disconnect account, assert localStorage keys removed and events gone from timeline
SAC-US3: Create Calendar Events
# Criterion Verification
SAC-US3-01 "New Event" button opens a creation form with title, start, end, description, and calendar selector fields Vitest DOM: click button, assert form with all 5 fields is rendered
SAC-US3-02 Start and end time default to the next available 30-minute slot from current time Vitest DOM: mount at 14:17, assert start defaults to 14:30 and end to 15:00
SAC-US3-03 Calendar selector lists only writable calendars from all connected accounts Vitest DOM: connect 2 accounts (1 read-only, 2 writable calendars), assert selector shows only 2 writable options
SAC-US3-04 Created event appears in the timeline immediately upon successful API response Playwright E2E: create event via form, assert new event block appears in timeline without manual refresh
SAC-US3-05 Validation rejects blank title, end time before start time, and duration exceeding 24 hours Vitest DOM: submit each invalid case, assert corresponding validation error message displayed
SAC-US3-06 Failed API call displays error message with retry button; form data is preserved Vitest DOM: simulate API failure, assert error banner visible with retry button and form fields unchanged
SAC-US3-07 calendar.event.created event is emitted on ctx.bus with the created CalendarEvent payload Integration test: listen on ctx.bus, create event, assert bus event received with matching event ID and title
SAC-US4: Sync Session Times to Calendar
# Criterion Verification
SAC-US4-01 When session.events emits event_type: "opened", a calendar event is created with title "Orchestrata Session {N}" Integration test: emit session opened event, assert Google/CalDAV API received events.insert with correct title
SAC-US4-02 Session calendar event description contains the session purpose/goals text Integration test: emit session opened with purpose "Fix auth bug", assert created event description contains that text
SAC-US4-03 When session.events emits event_type: "closed", the matching calendar event end time is updated Integration test: emit session closed, assert events.update called with correct event ID and new end time
SAC-US4-04 Session sync targets a configurable calendar (default: primary), changeable in gadget settings Vitest: change session_sync_calendar setting, emit session opened, assert event created in the configured calendar
SAC-US4-05 Session sync can be disabled in settings and no calendar events are created when disabled Vitest: set session_sync_enabled: false, emit session opened, assert no API call made
SAC-US4-06 If calendar API is unavailable, sync is queued in localStorage and retried with exponential backoff up to 5 times Integration test: simulate API failure, assert localStorage queue entry; restore API, assert retry succeeds and queue cleared
SAC-US4-07 Session calendar events include a dashboard link in the description Integration test: emit session opened, assert created event description contains http://localhost:8080/#session-{N}
SAC-US5: Navigate Between Days
# Criterion Verification
SAC-US5-01 Previous/next day buttons navigate the timeline to the adjacent date Playwright E2E: click next, assert displayed date is tomorrow; click previous twice, assert displayed date is yesterday
SAC-US5-02 Date picker allows jumping to any specific date and the timeline updates Playwright E2E: select a date 7 days ahead, assert timeline header shows that date and events are fetched
SAC-US5-03 "Today" button returns to the current date from any navigated date Playwright E2E: navigate to another date, click Today, assert current date displayed with now-marker visible
SAC-US5-04 Navigation preserves scroll position relative to the same time of day Vitest DOM: scroll to 14:00, navigate to next day, assert scroll position still shows 14:00 region
SAC-US5-05 Event data for non-today dates is fetched on demand and cached for 5 minutes Integration test: navigate to tomorrow (assert API call), navigate away and back within 5min (assert no new API call), wait 5min+ and navigate back (assert new API call)

Functional Requirements

FR-001: Calendar Data Fetching

User Story: US-001, US-005

FR-002: Google Calendar OAuth2

User Story: US-002

FR-003: CalDAV Integration

User Story: US-002

FR-004: Event Creation

User Story: US-003

FR-005: Session Calendar Sync

User Story: US-004


Non-Functional Requirements

Performance Requirements

NFR-001: Event Fetching

NFR-002: Event Creation

Reliability

NFR-003: Offline Behavior

NFR-004: Data Integrity

NFR-007: Navigation

NFR-008: Resource Usage

Observability
Logging
Event Level Fields
Google OAuth2 flow initiated INFO account_email (if re-auth), scopes_requested
Google OAuth2 token acquired INFO account_email, expires_at, calendars_discovered_count
Google OAuth2 token expired WARNING account_email, expired_at, cached_events_count
CalDAV connection established INFO server_url, username, calendars_discovered_count
CalDAV connection failed ERROR server_url, username, http_status, error_message
Calendar events fetched INFO provider, calendar_id, date, event_count, latency_ms, cache_hit
Calendar event fetch failed ERROR provider, calendar_id, date, http_status, error_message, retry_count
Event created INFO provider, calendar_id, event_id, title, duration_minutes
Event creation failed ERROR provider, calendar_id, title, http_status, error_message
Event updated INFO provider, calendar_id, event_id, updated_fields
Session sync: event created INFO session_number, calendar_event_id, calendar_id, provider
Session sync: event updated (close) INFO session_number, calendar_event_id, session_duration_minutes
Session sync: queued for retry WARNING session_number, attempt_count, next_retry_ms, error_message
Session sync: abandoned after max retries ERROR session_number, total_attempts, last_error
Credential encryption failed ERROR operation (encrypt/decrypt), error_type
Google API rate limit hit WARNING calendar_id, retry_after_ms, requests_in_window
Cache eviction DEBUG provider, calendar_id, date, reason (ttl_expired/manual_refresh)
Metrics (Browser Performance API)
Metric Type Labels Description
calendar_events_fetched_total Counter provider, calendar_id, cache_hit Total event fetch operations
calendar_events_fetch_duration_ms Histogram provider, cache_hit Event fetch latency (API or cache)
calendar_events_displayed Gauge provider Currently rendered events in timeline
calendar_event_creation_total Counter provider, status Event creation attempts (success/failure)
calendar_event_creation_duration_ms Histogram provider Event creation round-trip latency
calendar_session_sync_total Counter status Session sync outcomes (success/failure/queued)
calendar_session_sync_duration_ms Histogram — Session event to calendar event latency
calendar_session_sync_retry_total Counter — Total retry attempts for failed session syncs
calendar_session_sync_queue_depth Gauge — Pending session syncs in localStorage queue
calendar_accounts_connected Gauge provider Connected calendar accounts
calendar_cache_size_bytes Gauge — In-memory event cache size
calendar_oauth_refresh_total Counter status OAuth2 token refresh attempts
calendar_caldav_request_total Counter method, status CalDAV HTTP requests (PROPFIND/REPORT/PUT)

Metrics are collected via performance.mark() / performance.measure() and exposed to the Command Center's gadget metrics aggregator via ctx.metrics.

Tracing
Span Parent Attributes
calendar.mount gadget.mount provider_count, total_calendars
calendar.fetch_events calendar.mount / calendar.navigate provider, calendar_id, date, cache_hit
calendar.render_timeline calendar.fetch_events event_count, allday_count, render_ms
calendar.create_event user_action provider, calendar_id, title, duration_minutes
calendar.update_event session_sync provider, calendar_id, event_id, updated_fields
calendar.oauth2_flow user_action account_email, scopes
calendar.caldav_connect user_action server_url, calendars_found
calendar.session_sync.open session.events session_number, target_calendar
calendar.session_sync.close session.events session_number, duration_minutes
calendar.session_sync.retry calendar.session_sync.open session_number, attempt, backoff_ms
calendar.cache_refresh calendar.navigate provider, calendar_id, date, evicted_count

Spans are propagated via the Command Center's ctx.tracing interface. Each span includes gadget_id: "orchestrata-calendar" as a resource attribute.

Health Check

The calendar gadget exposes health status via the Command Center's ctx.health gadget health protocol:

ctx.health.report('orchestrata-calendar', {
    status: 'healthy',
    providers: {
        google: { status: 'connected', accounts: 1, calendars: 3 },
        caldav: { status: 'connected', accounts: 1, calendars: 2 }
    },
    cache: {
        entries: 5,
        size_bytes: 24576,
        oldest_entry_age_seconds: 180
    },
    session_sync: {
        enabled: true,
        pending_queue_depth: 0,
        last_sync_at: '2026-03-28T13:00:00+03:00',
        last_sync_status: 'success'
    },
    uptime_seconds: 3600.5
});

Health status levels:


Technical Design

Architecture
┌───��──────────────────────────────────────────────┐
│              Calendar Gadget (Browser)              │
├────────��──────────────────────────���──────────────┤
│                                                      │
│  ┌──────────────┐  ┌──────────────┐                 │
│  │ Calendar      │  │  Event       │                 │
│  │ Timeline      │  │  Creator     │                 │
│  │ (day view)    │  │  (form)      │                 ��
│  └──────────────┘  └���─────────────┘                 │
│         │                 │                           │
│         ▼                 ▼                           │
│  ┌───��──────────┐  ��──────────────┐                 │
│  │  Event       │  │  Session     │                 │
│  │  Cache       │  │  Sync        │                 │
│  │ (in-memory)  │  │  Engine      │                 │
│  └─────���────────┘  └────��─────────┘                 │
│         │                 │                           │
│         ▼                 ▼                           │
│  ���──────────────────────────────────────────┐       │
│  │           Calendar Providers              │       │
│  │  ��──────────────┐ ┌─────���────────┐       │       │
│  │  │ Google Cal   │ │ CalDAV       │       │       │
��  │  │ Provider     │ │ Provider     │       │       │
│  │  │ (OAuth2)     │ │ (Basic Auth) │       │       │
│  │  └──────────────┘ └──────────��───┘       │       │
│  └───────��──────────────────────────────────┘       │
│         │                 │                           │
│         ▼                 ▼                           │
│  ┌──────────────┐  ┌──────────────┐                 │
│  │  ctx.bus      │  │ localStorage │                 │
���  │ (session      │  │ (tokens,     │                 │
│  │  events)      │  │  settings)   │                 │
│  └─────��────────┘  └──────────────┘                 │
└──���───────────────────────────────────────────────┘
          │                           │
          ▼                           ▼
┌─���────────────────┐    ┌──────────────────────┐
│  Google Calendar │    │  CalDAV Server       │
│  API (REST)      │    │  (Nextcloud, etc.)   │
│  OAuth2 tokens   │    │  Basic Auth          │
└────────���─────────┘    └──────────────────────┘
Key Interfaces
/**
 * CalendarGadget — Main gadget class for the calendar integration.
 */
class CalendarGadget {
    /** Mount the gadget into the Command Center grid. */
    async mount(ctx) {}

    /** Unmount and clean up subscriptions and timers. */
    async unmount() {}

    /** Refresh event data for the currently displayed date. */
    async refresh() {}

    /** Navigate to a specific date. */
    async navigateTo(date) {}
}

/**
 * ICalendarProvider — Protocol for calendar backends.
 */
class ICalendarProvider {
    /** Authenticate with the calendar service. */
    async authenticate(credentials) {}

    /** List available calendars. */
    async listCalendars() {}

    /** Fetch events for a date range. */
    async fetchEvents(calendarId, startDate, endDate) {}

    /** Create a new event. */
    async createEvent(calendarId, event) {}

    /** Update an existing event. */
    async updateEvent(calendarId, eventId, updates) {}

    /** Delete an event. */
    async deleteEvent(calendarId, eventId) {}

    /** Get connection status. */
    getStatus() {}
}

/**
 * SessionCalendarSync — Syncs session lifecycle to calendar events.
 */
class SessionCalendarSync {
    /** Start listening for session events and syncing. */
    async start(bridge, provider, targetCalendarId) {}

    /** Stop session sync. */
    async stop() {}

    /** Retry any failed syncs. */
    async retryPending() {}
}
Gadget Manifest
{
    "id": "orchestrata-calendar",
    "name": "Calendar",
    "version": "1.0.0",
    "description": "Calendar integration with Google Calendar and CalDAV support",
    "entry": "gadgets/calendar/calendar.js",
    "icon": "calendar",
    "category": "productivity",
    "dependencies": ["GadgetBridge"],
    "min_api_version": "1.0.0",
    "default_size": {"columns": 1, "rows": 2},
    "supports_multi_instance": false,
    "config_schema": {
        "type": "object",
        "properties": {
            "session_sync_enabled": {"type": "boolean", "default": true},
            "session_sync_calendar": {"type": "string", "default": "primary"},
            "default_event_duration_minutes": {"type": "integer", "default": 30},
            "cache_ttl_minutes": {"type": "integer", "default": 5},
            "time_format": {"type": "string", "enum": ["12h", "24h"], "default": "24h"}
        }
    }
}
CalendarEvent Schema
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "CalendarEvent",
    "type": "object",
    "required": ["id", "title", "start", "end", "calendar_id"],
    "properties": {
        "id": {"type": "string"},
        "title": {"type": "string", "maxLength": 500},
        "start": {"type": "string", "format": "date-time"},
        "end": {"type": "string", "format": "date-time"},
        "all_day": {"type": "boolean", "default": false},
        "description": {"type": "string"},
        "location": {"type": "string"},
        "calendar_id": {"type": "string"},
        "calendar_name": {"type": "string"},
        "color": {"type": "string", "pattern": "^#[0-9a-fA-F]{6}$"},
        "attendees": {
            "type": "array",
            "items": {"type": "string", "format": "email"}
        },
        "source": {
            "type": "string",
            "enum": ["google", "caldav"]
        }
    }
}
Configuration
# In configs/command-center.yaml under gadgets section
gadgets:
  orchestrata-calendar:
    session_sync_enabled: true
    session_sync_calendar: "primary"
    default_event_duration_minutes: 30
    cache_ttl_minutes: 5
    time_format: "24h"
    google:
      client_id: "${GOOGLE_CALENDAR_CLIENT_ID}"
      scopes:
        - "https://www.googleapis.com/auth/calendar.events"
        - "https://www.googleapis.com/auth/calendar.readonly"
    caldav:
      servers: []
Integration Points
Component Integration
SPEC-016 VizInt Command Center Gadget lifecycle, chrome, ctx.bus, GadgetBridge
Google Calendar API OAuth2 implicit flow, events.list, events.insert, events.update
CalDAV Protocol PROPFIND, REPORT, PUT for event CRUD
ctx.bus Session lifecycle events from session-manager gadget
localStorage Token storage, settings persistence, session-event ID mapping

Success Criteria

  1. Calendar Display: Today's events from connected calendars displayed in timeline view within 2 seconds of gadget mount
  2. Multi-Provider: Both Google Calendar and CalDAV accounts connectable and displaying events simultaneously
  3. Event Creation: New events created from the Command Center appear in the external calendar within 5 seconds
  4. Session Sync: Session open/close times automatically recorded as calendar events with correct duration
  5. Offline Resilience: Cached events remain visible when calendar APIs are unreachable
  6. Performance: Timeline renders within 100ms with up to 20 events; no jank on scroll

Security

Authentication
Authorization
Input Validation
Audit Logging

All security-relevant events logged for audit trail:

Event Level Fields
OAuth2 flow initiated INFO account_email, scopes_requested
OAuth2 token acquired INFO account_email, expires_at
OAuth2 token expired WARNING account_email
CalDAV authentication failed ERROR server_url, username, http_status
Credential encryption failed ERROR operation, error_type
Credential storage attempted without secure context WARNING reason
Data Protection

Governance

Architecture Decision Records
ADR Decision Rationale
ADR-017-001 Browser-side JavaScript gadget No Python backend required; leverages browser APIs for OAuth2 and Web Crypto
ADR-017-002 OAuth2 implicit flow over authorization code Simplifies browser-only authentication; no server-side token exchange needed
ADR-017-003 localStorage for credential storage Meets requirements for persistence; Web Crypto API provides encryption
ADR-017-004 ctx.bus for session lifecycle events Integrates with existing GadgetBridge pattern for inter-gadget communication
Compliance
Maintenance
Support

Visual Architecture

Class Diagram

Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 36:).

classDiagram-direction LR
    class CheetahClawsTUI {
        +__init__()
        #_load_commands(): dict[str, Any]
        +async create_checkpoint(name: str): dict[str, Any]
        +async rewind(steps: int = 1): dict[str, Any]
        +async query_memory(query: str, depth: int = 1): dict[str, Any]
        +async edit_file(file_path: str, old_string: str, new_string: str): dict[str, Any]
        +async search_files(pattern: str, path: str = '.'): list[str]
        +async execute_command(command: str, args: list[str] | None = None): dict[str, Any]
    }
    class OpenRouterProvider {
        +__init__(api_key: str | None = None)
        +async chat_completion(model: str, messages: list[dict[str, str]], **kwargs): dict[str, Any]
        +get_available_models(): list[str]
        +get_model_cost(model: str): float
    }
    class TodoistIntegration {
        +__init__(api_key: str | None = None)
        +is_configured(): bool
        +async create_project(name: str): str
        +async create_task(project_id: str, title: str, **kwargs): str
        +async sync_tasks(project_id: str): list[dict[str, Any]]
        +async close()
    }
    class VizIntWebUI {
        +__init__(host: str = 'localhost', port: int = 8765)
        +async start()
        +async shutdown()
        +async add_project(project_data: dict[str, Any])
        +async broadcast_edit_complete(file_path: str, result: dict[str, Any])
        +async update_task_status(task_id: str, status: str)
        +async get_projects(): list[dict[str, Any]]
    }
GoogleCalendarToken Schema
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "GoogleCalendarToken",
    "type": "object",
    "required": ["access_token", "token_type", "expires_at", "email"],
    "properties": {
        "access_token": {"type": "string"},
        "token_type": {"type": "string", "const": "Bearer"},
        "expires_at": {"type": "string", "format": "date-time"},
        "email": {"type": "string", "format": "email"},
        "scopes": {
            "type": "array",
            "items": {"type": "string"}
        }
    }
}
CalDAVCredentials Schema
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "CalDAVCredentials",
    "type": "object",
    "required": ["server_url", "username"],
    "properties": {
        "server_url": {
            "type": "string",
            "format": "uri",
            "description": "CalDAV server URL (e.g., https://nextcloud.example.com/remote.php/dav)."
        },
        "username": {"type": "string"},
        "encrypted_password": {
            "type": "string",
            "description": "AES-GCM encrypted app password, base64 encoded."
        },
        "display_name": {"type": "string"}
    }
}
SessionSyncMapping Schema
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "SessionSyncMapping",
    "type": "object",
    "required": ["session_id", "calendar_event_id", "calendar_id", "provider"],
    "properties": {
        "session_id": {"type": "string"},
        "calendar_event_id": {"type": "string"},
        "calendar_id": {"type": "string"},
        "provider": {"type": "string", "enum": ["google", "caldav"]},
        "created_at": {"type": "string", "format": "date-time"},
        "synced": {"type": "boolean"}
    }
}

Error Conditions

ERR-ID Condition Handling
ERR-001 Google OAuth2 token has expired and refresh fails Display a "Re-authenticate" button and continue showing cached events
ERR-002 CalDAV server returns 401 Unauthorized Display "Authentication failed" for that account and prompt credential update
ERR-003 CalDAV server does not support CORS headers Display a configuration hint about setting up a CORS proxy
ERR-004 Event creation fails due to API error Display the error message and offer a retry button without clearing the form
ERR-005 Session sync cannot create a calendar event (API unavailable) Queue sync in localStorage and retry on next successful API call (up to 5 retries)
ERR-006 Session close event arrives but no matching session-open calendar event exists Create a new event with estimated start time from session metadata
ERR-007 Multiple calendar accounts connected and target sync calendar is ambiguous Use the first primary calendar found or prompt the user to select one
ERR-008 Browser blocks pop-ups required for Google OAuth2 Detect blocked popup and display instructions to allow pop-ups for the domain
ERR-009 localStorage encryption key derivation fails (Web Crypto API unavailable) Do not store CalDAV credentials and inform user that credential persistence requires a secure context (HTTPS)
ERR-010 Event spans midnight (crosses date boundary) Display visible portion for current date with a visual indicator that the event continues
ERR-011 Google Calendar API rate limit is reached (10 QPS default) Back off and display a rate-limit notice with estimated retry time
ERR-012 CalDAV VEVENT contains unsupported iCalendar properties (RRULE for recurrence) Display the next occurrence only and indicate it is recurring
ERR-013 localStorage quota exceeded when caching events Clear oldest cached events and notify user of cache eviction
ERR-014 Invalid date range selected for event fetch Validate date range and display error if end date is before start date

Testing

Testability Considerations
Definition of Done

Integration Points

Component Integration
SPEC-016 VizInt Command Center Gadget lifecycle, chrome, ctx.bus, GadgetBridge
Google Calendar API OAuth2 implicit flow, events.list, events.insert, events.update
CalDAV Protocol PROPFIND, REPORT, PUT for event CRUD
ctx.bus Session lifecycle events from session-manager gadget
localStorage Token storage, settings persistence, session-event ID mapping

Examples

Example: Google Calendar OAuth2 Flow
// User clicks "Connect Google Calendar"
const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth');
authUrl.searchParams.set('client_id', config.google.client_id);
authUrl.searchParams.set('redirect_uri', window.location.origin + '/oauth/callback');
authUrl.searchParams.set('response_type', 'token');
authUrl.searchParams.set('scope', 'https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.readonly');

const popup = window.open(authUrl.toString(), 'google-auth', 'width=500,height=600');
// Callback handler extracts access_token from URL fragment
Example: Fetching Today's Events (Google)
const today = new Date();
const startOfDay = new Date(today.setHours(0, 0, 0, 0)).toISOString();
const endOfDay = new Date(today.setHours(23, 59, 59, 999)).toISOString();

const response = await fetch(
    `https://www.googleapis.com/calendar/v3/calendars/primary/events?` +
    `timeMin=${startOfDay}&timeMax=${endOfDay}&singleEvents=true&orderBy=startTime`,
    { headers: { 'Authorization': `Bearer ${token.access_token}` } }
);
const data = await response.json();
// data.items = [{summary, start, end, description, ...}, ...]
Example: Session Sync Calendar Event

When session 89 opens with purpose "Implement WebSocket Gateway":

{
    "summary": "Orchestrata Session 89",
    "description": "Purpose: Implement WebSocket Gateway\nDashboard: http://localhost:8080/#session-89",
    "start": {
        "dateTime": "2026-03-28T10:30:00+03:00"
    },
    "end": {
        "dateTime": "2026-03-28T11:00:00+03:00"
    },
    "colorId": "9"
}

When session 89 closes 2.5 hours later, the event end time is updated:

{
    "end": {
        "dateTime": "2026-03-28T13:00:00+03:00"
    }
}
Example: CalDAV VEVENT Creation
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Orchestrata//Calendar Gadget//EN
BEGIN:VEVENT
DTSTART:20260328T103000
DTEND:20260328T130000
SUMMARY:Orchestrata Session 89
DESCRIPTION:Purpose: Implement WebSocket Gateway
UID:orchestrata-session-89@orchestrata.local
END:VEVENT
END:VCALENDAR

API Contracts

Contract: Calendar Gadget API (contracts/commandcenter/calendar-v1.0.0.yaml)
info:
  title: Calendar Integration Gadget Contract
  version: 1.0.0
  spec_id: 017-calendar-integration
  spec_version: 1.0.0
  maturity: experimental
  consumer: calendar-gadget
  providers: [google-calendar-api, caldav-server]

schemas:
  CalendarEvent:
    type: object
    required: [id, title, start, end, calendar_id]
    properties:
      id:
        type: string
      title:
        type: string
        maxLength: 500
      start:
        type: string
        format: date-time
      end:
        type: string
        format: date-time
      all_day:
        type: boolean
      description:
        type: string
      location:
        type: string
      calendar_id:
        type: string
      calendar_name:
        type: string
      color:
        type: string
      attendees:
        type: array
        items:
          type: string
      source:
        type: string
        enum: [google, caldav]

  CalendarAccount:
    type: object
    required: [provider, display_name, status]
    properties:
      provider:
        type: string
        enum: [google, caldav]
      display_name:
        type: string
      email:
        type: string
      status:
        type: string
        enum: [connected, expired, error]
      calendars:
        type: array
        items:
          type: object
          required: [id, name, writable]
          properties:
            id:
              type: string
            name:
              type: string
            color:
              type: string
            writable:
              type: boolean
            selected:
              type: boolean

  SessionSyncMapping:
    type: object
    required: [session_id, calendar_event_id, calendar_id, provider]
    properties:
      session_id:
        type: string
      calendar_event_id:
        type: string
      calendar_id:
        type: string
      provider:
        type: string
        enum: [google, caldav]
      created_at:
        type: string
        format: date-time
      synced:
        type: boolean

bus_events:
  calendar.event.created:
    description: Emitted when a new event is created through the gadget
    payload:
      $ref: "#/schemas/CalendarEvent"
  calendar.event.updated:
    description: Emitted when an event is updated (e.g., session close updates end time)
    payload:
      $ref: "#/schemas/CalendarEvent"
  calendar.account.connected:
    description: Emitted when a new calendar account is connected
    payload:
      $ref: "#/schemas/CalendarAccount"

session_sync:
  trigger_event: "session.events"
  trigger_conditions:
    open: "event_type == 'opened'"
    close: "event_type == 'closed'"
  event_title_format: "Orchestrata Session {session_number}"
  target_calendar_key: "commandcenter.state.calendar.sync_target"
  retry:
    max_attempts: 5
    backoff_initial_ms: 1000
    backoff_max_ms: 30000

performance:
  google_fetch_p95_ms: 1000
  caldav_fetch_p95_ms: 2000
  cache_hit_ms: 10
  timeline_render_p95_ms: 100
  event_creation_p95_ms: 2000

security:
  oauth2_storage: localStorage_encrypted
  caldav_credential_storage: localStorage_aes_gcm
  api_transport: https_only
  scope_minimization: true

spec_traceability:
  spec_id: "017-calendar-integration"
  spec_version: "1.0.0"
  user_stories: ["US-001", "US-002", "US-003", "US-004", "US-005"]

Observability

Logging Requirements
  1. Component Logging
    • Log all major operations with appropriate log levels
    • Include correlation IDs for request tracing
    • Log performance metrics for critical operations
    • Log errors with full context for debugging
Metrics Requirements
  1. Performance Metrics
    • Operation duration histograms
    • Request/error rate counters
    • Resource utilization gauges
    • Business metrics relevant to domain
Tracing Requirements
  1. Distributed Tracing
    • Trace propagation across component boundaries
    • Span attributes for domain-specific context
    • Trace sampling based on operational needs
Alerting Requirements
  1. Critical Alerts
    • Error rate spikes
    • Performance degradation
    • Resource exhaustion
    • Business metric anomalies
Dashboard Requirements
  1. Operational Dashboard
    • Real-time system health
    • Performance trends
    • Error analysis
    • Resource monitoring

Revision History

Date Version Author Changes
2026-03-28 1.0.0 Mohamed Initial specification
2026-03-29 1.0.1 Mohamed Added std_01 (Standardized Acceptance Criteria) and std_15 (Observability) sections