Before adding "every N weeks/months" support, found the recurrence
window math was independently hand-written in three places (main app's
TaskItem.isOccurrence, and two separate widget extensions' countdown
progress calculations) with no shared code to keep them in sync.
Extracted the math into Shared/RecurrenceRule.swift (pure Foundation,
no framework deps) compiled into both the app and widget extension
targets via a new project.yml Shared/ source path, and pointed all
three call sites at it. Verified every case is identical to prior
behavior at interval==1 by compiling and running a standalone test
driver directly against the real file with swiftc - 38/38 passing,
including Jan-31-monthly and Feb-29-leap-year-yearly edge cases.
Groundwork only - no recurrenceInterval field on TaskItem yet, the
actual interval feature comes next on top of this.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
end(_:dismissalPolicy:) requires iOS 16.2 but LiveActivityManager.end
only gated to 16.1 (Live Activities' own minimum) - branch on
#available with the deprecated overload as fallback. Separately,
auditing all countdown widgets per user request found the "Event
Countdown (Bars)" widget family had its own independent start-date
resolution that never considered the task's real creation date at
all - EventEntity now carries createdAt and resolveSpan prefers it
the same way KC-65 already does for the dot-grid widget.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Bars widget: tracked ("Track Countdown") events now also advance — a completed
or past (non-recurring) tracked event falls through to the next-nearest, and the
refresh boundary covers the tracked event's expiry. Recurring tracked events
still roll forward. Completes the KC-26 auto-advance for all paths.
- Progress Dots on the lock screen (accessoryRectangular): show 28 larger dots
instead of 100 tiny ones, render with .primary for the vibrant tint, and use
AccessoryWidgetBackground so it's legible (Home Screen keeps the 100-dot grid).
- Notifications: snooze action labels now read "Snooze 15 min/30 min/1 hour/
2 hours" (lock screen) and "Snooze 15 Minutes…" (in-app Postpone menu).
- New period milestone notifications: recurring "One more week/month/year passed"
at end of week (Sun 20:00), month (1st 09:00), and year (Jan 1 09:00); gated by
a kisani.periodMilestones flag, scheduled via the existing reschedule path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Today ⋯ menu: implemented the placeholder actions.
- Background: 5 selectable themes (Default/Warm/Cool/Mono/Paper), persisted.
- Group & Sort: group by Date (default)/Priority/Category/Quadrant and sort by
Smart/Due/Priority/Title; non-date groupings render via UpcomingSection.
- Select: multi-select sheet with Select All/Deselect All and bulk
Complete/Priority/Move/Delete.
New isolated file TodayMenuFeatures.swift; added TaskViewModel.allActiveRows.
- Matrix "Move" submenu now lists only the other three quadrants (excludes the
current one) using clear matrix labels.
- Event Countdown (Bars) widget auto-advances: each timeline entry re-resolves
"nearest to finish" as of its own time and refreshes at the moment the current
event expires, so it rolls to the next event on expiry/completion.
- Splash wordmark rebranded to "wenza." (regular-weight typewriter + orange dot).
- ISSUES.md: logged KC-23 (Pick Date + time-based reminders), KC-24 (Wenza
rebrand), KC-25 (Move trim), KC-26 (widget auto-advance).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The real bug behind "Leona's Birthday, 5 days left" showing 0% filled:
Mode B (recurring span: previous -> next occurrence) only ran for
app-tracked events, while the upcoming-queue / picked-event paths still
anchored from first-seen (so a yearly birthday started at 0%).
- EventEntity now carries isRecurring/recurrenceLabel (populated from the
shared task data) so the auto-select and picker paths know the rule.
- resolveSpan() centralizes the window: recurring -> prev/next occurrence
everywhere; one-off -> explicit start / tracking date / first-seen.
- A yearly birthday 5 days away now reads ~98% (≈360/365 days elapsed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Task long-press menu gains Track/Stop Tracking Countdown, storing the
tracked event id + tracking date in the App Group (CountdownTracker)
and reloading widget timelines.
- The widget reads the tracked event directly and bypasses its config:
Mode A (one-off) = tracking date -> event date; Mode B (recurring) =
previous occurrence -> next occurrence via the task's recurrence rule.
- WidgetTask decodes isRecurring/recurrenceLabel from the shared JSON.
- With nothing tracked, the configured modes remain the fallback.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Persist a per-event "first tracked" anchor in the App Group instead of
resetting the progress start to now on every refresh (auto mode), so
the bar actually fills toward the event. Explicit "Counting from" wins
when it's before the event date.
- Make Event date / Counting from optional ("Choose") — the same-second
defaults produced a zero-length span (always 0%) and looked broken.
- Pre-render timeline entries every 30 min (12h horizon) so the bar and
time-left label move between refreshes instead of only at midnight.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the dot-grid EventCountdownWidget and TasksCompleteWidget from the
gallery: widget structs, their views, the todayTaskCompletion() helper
(only consumer), and bundle registrations. Shared event plumbing
(EventConfigIntent/Provider/Entry, CycleCountdownUnitIntent) stays for
the surviving Event Countdown (Bars); DotGrid stays for Day Progress.
Remaining widgets untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- New EventBarsWidget ("Event Countdown (Bars)") using BarGrid + EventBarsView,
with a fine "X hr, Y min left" label; registered in the bundle.
- Re-themed every home-screen widget to the shared WidgetTheme (dark slate
background + brand orange): Day Progress, Tasks Done Today, Event Countdown
(dots), My Tasks. Lock-screen widgets keep .thinMaterial (system-tinted).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add "Upcoming queue" toggle to the Event Countdown widget. When on, it
auto-tracks the Nth nearest upcoming event (Nearest / 2nd … 5th, new
AutoSelectRank enum). When off, track a picked or fully custom event.
- parameterSummary now shows only the relevant fields per mode (toggle +
auto-select, or event/name/date), so the date input only appears for
custom events.
- Replace the dense 380-day placeholder with a ~90-day window so the
gallery preview shows a legible dot grid.
(The interactive task-checkbox widget already exists as "My Tasks".)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- My Tasks widget: today's tasks with interactive check-off (ToggleTaskIntent)
and a "+" that opens the app's add-task sheet; writes preserve all task
fields and sync via the App Group.
- Event Countdown: AZURE/AWS-style header (accent name + countdown label +
percent); tap the label to cycle days → weeks → time remaining.
- Today: collapsible "Completed" archive section below Upcoming.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Widgets (new KisaniCalWidgets extension)
- Event Countdown widget: configurable via AppIntent, pick from your events
or set a custom name/date; dot-grid progress toward the event.
- Day Progress and Tasks-Done-Today widgets; lock screen widgets.
- Shared dot grid sizes circles to fill the widget evenly at any count.
- Tasks/calendar prefs now persist to the App Group so widgets read live data.
Health & streaks
- Persist HealthKit authorization and re-establish on launch (fixes the
Today dashboard and streak sync disappearing after relaunch).
- Add a Health permission toggle to onboarding; unify Settings/Profile on the
manager's state.
- Day streak counts from a logged Health workout OR marking all exercises
complete; nudge to mark exercises complete even when Health logged the workout.
Workout editor
- Drag to reorder exercises and move them across sections (drag-and-drop);
swipe to delete.
- Add-exercise sheet: global search and keep-adding-multiple with a running count.
Fixes
- Restore app entitlements link (Sign in with Apple, HealthKit, App Group, iCloud).
- Add HealthKit usage strings; widget Info.plist NSExtension + nested bundle id.
- Calendar "Connect" routes to Settings when access was denied.
- Bake DEVELOPMENT_TEAM and shared versions into project.yml.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>