diff --git a/conductor/tracks.md b/conductor/tracks.md index 91c9c29..6400928 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -6,3 +6,8 @@ This file tracks all major tracks for the project. Each track has its own detail - [x] **Track: Upgrade the SilverBullet iCalendar plug to use DST-aware timezone resolution and add recurring event support using rrule.** *Link: [./tracks/timezone_rrule_20260218/](./tracks/timezone_rrule_20260218/)* + +--- + +- [ ] **Track: Fix TypeError: r.replace is not a function in icalendar.ts** + *Link: [./tracks/fix_rrule_type_error_20260219/](./tracks/fix_rrule_type_error_20260219/)* diff --git a/conductor/tracks/fix_rrule_type_error_20260219/index.md b/conductor/tracks/fix_rrule_type_error_20260219/index.md new file mode 100644 index 0000000..73e78a1 --- /dev/null +++ b/conductor/tracks/fix_rrule_type_error_20260219/index.md @@ -0,0 +1,5 @@ +# Track fix_rrule_type_error_20260219 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) \ No newline at end of file diff --git a/conductor/tracks/fix_rrule_type_error_20260219/metadata.json b/conductor/tracks/fix_rrule_type_error_20260219/metadata.json new file mode 100644 index 0000000..9def283 --- /dev/null +++ b/conductor/tracks/fix_rrule_type_error_20260219/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "fix_rrule_type_error_20260219", + "type": "bug", + "status": "new", + "created_at": "2026-02-19T00:00:00Z", + "updated_at": "2026-02-19T00:00:00Z", + "description": "Fix TypeError: r.replace is not a function in icalendar.ts" +} \ No newline at end of file diff --git a/conductor/tracks/fix_rrule_type_error_20260219/plan.md b/conductor/tracks/fix_rrule_type_error_20260219/plan.md new file mode 100644 index 0000000..c146dfc --- /dev/null +++ b/conductor/tracks/fix_rrule_type_error_20260219/plan.md @@ -0,0 +1,20 @@ +# Implementation Plan - Fix `r.replace is not a function` + +## Phase 1: Reproduction & Test Setup +- [ ] Task: Create a reproduction test case + - [ ] Create a new test case in `icalendar_test.ts` that mocks an event with a non-string `rrule` property (e.g., an object or number). + - [ ] Run the test to confirm it fails with the expected `TypeError`. +- [ ] Task: Conductor - User Manual Verification 'Reproduction & Test Setup' (Protocol in workflow.md) + +## Phase 2: Implementation +- [ ] Task: Implement defensive check in `icalendar.ts` + - [ ] Modify `expandRecurrences` function to check if `rruleStr` is a string before calling `.replace()`. + - [ ] If `rruleStr` is not a string, log a warning and return the original event (non-recurring fallback). + - [ ] Run the reproduction test again to confirm it passes. +- [ ] Task: Conductor - User Manual Verification 'Implementation' (Protocol in workflow.md) + +## Phase 3: Verification & Cleanup +- [ ] Task: Verify fix and check for regressions + - [ ] Run all tests in `icalendar_test.ts` to ensure existing functionality is preserved. + - [ ] (Optional) Verify with actual calendar sync if possible/safe. +- [ ] Task: Conductor - User Manual Verification 'Verification & Cleanup' (Protocol in workflow.md) \ No newline at end of file diff --git a/conductor/tracks/fix_rrule_type_error_20260219/spec.md b/conductor/tracks/fix_rrule_type_error_20260219/spec.md new file mode 100644 index 0000000..eb43b52 --- /dev/null +++ b/conductor/tracks/fix_rrule_type_error_20260219/spec.md @@ -0,0 +1,25 @@ +# Specification: Fix `r.replace is not a function` in `expandRecurrences` + +## Overview +This track addresses a `TypeError: r.replace is not a function` error occurring in `icalendar.ts` during calendar synchronization. The error suggests that the `rrule` property of an event is not a string when it reaches the `expandRecurrences` function, causing the subsequent `.replace()` call to fail. This is likely due to the `ts-ics` parser returning a non-string value (e.g., an object or `undefined`) for the `rrule` property in certain scenarios (specifically observed with Outlook calendars). + +## Functional Requirements +- **Defensive RRULE Handling:** The `expandRecurrences` function in `icalendar.ts` must safely handle cases where `rrule` (or `recurrenceRule`) is not a string. +- **Graceful Fallback:** If `rrule` is not a string: + - It should be ignored/logged if it cannot be interpreted as a valid RRULE string, preventing the crash. + - The event should still be processed (treated as a non-recurring event if the rule is invalid), rather than crashing the entire sync for that event. + +## Non-Functional Requirements +- **Stability:** The plug should not crash or throw unhandled exceptions during sync due to malformed or unexpected property types in the source ICS data. +- **Logging:** Maintain existing error logging but ensure the error message is descriptive (e.g., "Invalid RRULE type: object"). + +## Implementation Steps +1. **Reproduce Issue:** Create a unit test in `icalendar_test.ts` that mocks an `icsEvent` with a non-string `rrule` property (e.g., an object or number) and calls `expandRecurrences`. +2. **Implement Fix:** Modify `icalendar.ts` to check the type of `rruleStr` before calling `.replace()`. + - If it's not a string, attempt to convert it or return the original event (as if no recurrence rule exists) with a warning. +3. **Verify:** Run the new unit test to confirm the fix. + +## Acceptance Criteria +- [ ] A new unit test case exists in `icalendar_test.ts` that passes with a non-string `rrule`. +- [ ] The `expandRecurrences` function no longer throws `TypeError: r.replace is not a function` when `rrule` is not a string. +- [ ] The sync process completes successfully even if some events have malformed `rrule` properties. \ No newline at end of file