◉ Engineering
June 2026

A Holiday Is Not a Meeting

Almanac said I had worked 356 hours that week. There are 168 hours in a week. The number was not a rounding error. It was a category error -- the calendar was counting a holiday as a twenty-four-hour workday, and it was right there in the dashboard the whole time.

356 Hours in a Week

The two apps I have been building most recently are Almanac, which aggregates calendars, and Weekly, which writes a plain-language review of your week from everything the suite already knows. Both are local. Both are private. Both were quietly wrong.

The tell was the "This Week" panel in Almanac: 36 events, 356.5 hours. Fifty hours a day. The cause was mundane. An all-day event -- a holiday, a birthday, a day blocked off -- has no start and end time, so it gets stored as midnight to 23:59. Sum a week of those and every holiday silently adds a full twenty-four hours to your "time at work."

Local-first was never the hard part. Keeping your data on your own machine is a deployment decision. Classifying it correctly is the actual work, and it is the part nobody screenshots.

This is the uncomfortable thing about owning your data: when it is wrong, there is no vendor to blame. The holiday was counted as work because I told the calendar that an all-day block is a 24-hour block, and never told it that some calendars are not about work at all.

Almanac Was Never Just Google Calendar

Almanac started as a read-only Google Calendar sync. Since then it has grown into something closer to a time data plane for the whole suite -- the thing that knows when everything happened and which account it belongs to.

It now speaks CalDAV, so iCloud and Nextcloud calendars sit alongside Google ones. It handles multiple accounts per person. It exposes a narrow, opt-in feed of attendee identities so other apps can reason about who you are meeting -- and nothing more. The job is no longer "show me my calendar." It is "be the authoritative answer to when and with whom, for every other app that asks."

And a data plane that cannot tell a holiday from a standup is not authoritative. It is just storage.

A Category Belongs to the Calendar, Not the Event

The fix sounds obvious once you say it out loud: a holiday is not a property of an event, it is a property of a calendar. The "Holidays in United States" calendar is holidays. The "Birthdays" calendar is birthdays. Every event they contain inherits that, no per-event guessing required.

So Almanac learned to classify the source. Google holiday and birthday calendars have stable, recognizable IDs. CalDAV only gives you a display name, so a name match covers the rest. And because heuristics are never perfect -- a CalDAV "Company Days Off" feed will not announce itself -- every calendar carries a category you can override by hand. Override it once and the choice survives every future sync.

Source signal Category is derived from the calendar, not the event. Google holiday/birthday calendars by ID; CalDAV by name; a one-click override for anything the heuristics miss.
Hours All-day blocks contribute zero hours. An all-day conference is not twenty-four hours of work, and a holiday is not work at all.
Events Holidays are pulled out of the meeting count entirely and shown as their own number, only when there is one to show.
Backfill Thousands of events synced before any of this existed get reclassified once, automatically, from data already on disk. No re-sync, no API calls, no lost history.

Two Numbers That Were Lying

The dashboard now reads the way a human would expect. Holidays leave the meeting count and the hours total and become a separate, quiet "Holidays" card that only appears when you actually have one. All-day events stop inflating the clock. The 356 became a number that fits inside a week.

Local but wrong
Holiday counted as a meeting
All-day block = 24 working hours
356 hours in a 168-hour week
Every calendar treated the same
Your data, lying to you privately
Local and correct
Holidays in their own category
All-day blocks add zero hours
Hours that fit inside a week
Category owned by the calendar
Your data, classified by you

Weekly Had to Survive a Logout

If Almanac is the data plane, Weekly is the narrative layer -- the app that turns a week of meetings, email, tasks, and code into a paragraph you would actually read. And a narrative layer has a different failure mode than a calendar: it produces something you do not want to lose.

Weekly generates its review by streaming from a local model, which can take a while. The original design saved the result only after the stream finished. Close the tab, switch pages, or log out mid-generation, and the half-written review evaporated -- on both ends. Worse, even a finished review lived only in a history tab; the main page came back blank on reload, as if nothing had happened.

So generation became durable. The work now runs as a detached task that persists to the database whether or not you stay connected. Each review has a lifecycle -- generating, complete, or interrupted -- and the page restores the latest one on load, resuming a run that is still in flight or showing the finished one that survived your logout. A process that dies mid-generation marks the run interrupted rather than leaving a ghost. Your intentions, your summary history, your meeting-prep notes: all of it is meant to outlive a browser tab, a redeploy, and a bad Wi-Fi moment.

What "durable" had to mean
Disconnect Close the tab mid-generation and the review still finishes and saves.
Reload The main panel restores the latest review instead of coming back empty.
Redeploy Finished work persists; an interrupted run is marked, never silently lost.

Data Plane and Narrative Layer

Splitting the two apps along this line changed how I think about the whole suite. Almanac holds the structured truth about time and context. Weekly reads that truth and tells a story with it. Neither pretends to be the other.

Which is exactly why the holiday fix had to land in both. Almanac stops counting a holiday as work. Weekly, reading the same data through Gopher, now narrates a holiday as a day off rather than folding it into how busy you were -- and it will not seed next week's intentions off a public holiday either. The category that started as one wrong number in a dashboard now flows correctly through the entire pipeline.

A calendar that counts a holiday as twenty-four hours of work is local, private, encrypted, yours -- and wrong. Sovereignty is the floor, not the finish line. The real bar is data you can actually trust, because the only person left to get it right is you.
#Almanac #Weekly #MyOwnLifeOS #LocalFirst #CalDAV #DataModeling #BuildInPublic #Ollama
Ovais Quraishi