# Release v1.33.0

Released: 2026-03-14

## Added

- **Google Calendar Integration** — full M48 implementation with subcalendar management (enable/disable/dormant), MCP push sync, goal-calendar linking with match patterns, and daily review UI for confirming events with auto-progress logging
- **Two sync methods** for Google Calendar: Claude MCP (zero-config fallback) and direct Google API via OAuth2 (faster, no LLM needed), selectable per account
- **Google OAuth2 flow** — credentials management, token storage with auto-refresh, OAuth consent redirect handling in `data/calendar/google-auth/`
- **Auto-configure Google OAuth via CDP browser** — guided setup opens Google Cloud Console, user logs in + selects project, then one-click "Continue" automates: enable Calendar API, configure OAuth consent screen, add test user, create OAuth credentials, and capture client ID + secret
- **Calendar Review tab** (`/calendar/review`) — daily review of events with confirm/skip, auto-logging progress to linked goals, date navigation, sync staleness warning
- **Day view 15-minute blocks** — upgraded from hourly to 15-minute granularity with subtle sub-lines
- **Day view overlap layout** — concurrent events render side-by-side in columns instead of overlapping
- **Goal progress logging** — log activity sessions with date, note, and optional duration on goals
- **Goal-calendar linking** — link Google Calendar subcalendars to goals with optional match patterns for automatic event matching
- **Subcalendar discovery** — "Discover Calendars" button fetches calendar list via MCP or direct Google API

## Changed

- New Google Calendar accounts default to `google-api` sync method when OAuth is already configured
- Calendar account type label changed from "Google Calendar (MCP Push)" to "Google Calendar"
- Sync method config moved above calendar selection in Config tab for better flow

## Fixed

- Day view events no longer overlap — side-by-side column layout for concurrent events
- ReviewTab `.sort()` no longer mutates state (copy before sorting)
- Dynamic imports of `updateSubcalendars` replaced with static imports
- OAuth redirect URI centralized as `OAUTH_REDIRECT_URI` constant deriving port from `process.env.PORT`
- Persist generated tasks before spawning to prevent duplicate task execution
- Clear progress form on cancel and deduplicate date default
- Various review fixes: weekdaysOnly in job update allowlist, null intervalMs handling, memory-fill-blank answers, toast imports, blocked banner labels

## Refactored

- Extracted shared `loadCache`/`saveCache` from calendarSync.js, reused in calendarGoogleSync.js
- Extracted `mergeDiscoveredSubcalendars` helper in calendarAccounts.js
- Extracted `getSyncDateRange` helper for sync services
- Parallelized `getDailyReview` reads with `Promise.all`
- Parallelized Google API calendar fetches with `Promise.all`
- Memoized `layoutEvents` in DayView with `useMemo`
- Removed redundant `autoConfigBusy` state from ConfigTab

## Full Changelog

**Full Diff**: https://github.com/atomantic/PortOS/compare/v1.32.0...v1.33.0
