Start with language
Calendar sync gets confusing fast because the same word can mean an account, a calendar inside that account, a copy of an event, or the relationship doing the copying. The first useful work was deciding on a small vocabulary: Connections, Arms, Rules, Main calendar, and Availability.
Those names became contracts used by the command line, database, tests, issues, and future interface plans. That paid off every time a feature crossed layers. A Busy Rule means the same thing in the planner, provider payload, diagnostic output, and product copy.
Using the same names in the code, the database, the tests, and the copy keeps the product boundary clear.
Write the safety contract before the sync loop
The risky part of calendar software is not reading events. It is being wrong while writing them. Calopod's initial charter made the important constraints explicit before implementation: source events are never edited, Busy never leaks details, deletes require ownership proof, repeated runs converge, and incomplete provider data must remain visible as incomplete.
That moved safety out of a final review checklist and into the architecture. Signed markers, normalized state, the operation journal, bounded windows, and generic logs all exist because the contract demanded them.
Milestones follow usable slices
Work was divided into narrow milestones that each left behind something coherent: foundations, read-only aggregation, manual sync, the background service, and then a packaged CLI preview. Each milestone had its own acceptance boundary rather than borrowing confidence from a future interface.
The terminal-first release was a deliberate product decision. It creates a path for technical users now, keeps the CLI as a long-term operator interface, and gives the shared core real use before a Mac app begins wrapping it.
Issues stay small enough to prove
Every implementation issue lives in a milestone and closes through one focused pull request. Dependencies are written down so an installer cannot land before the service it installs, and service controls cannot pretend to work before the service lifecycle exists.
The useful test for issue size is not a line count. It is whether the change can be explained, reviewed, and accepted without pulling an unfinished neighbor across the line with it. Large features are split at operational boundaries, and commits inside them stay small enough to make regressions traceable.
Automated proof, then live proof
Unit and integration tests cover deterministic planning, privacy rules, ownership, recovery, migrations, provider behavior, locking, and command contracts. They run before a pull request is considered ready.
Some boundaries still belong to macOS and real calendar providers. EventKit permission identity, code signing, launchd behavior, sleep and wake, clean installation, and visual calendar presentation require live acceptance. Those pull requests pause before merge until the relevant check passes.
Passing tests narrow what a live check has to cover. They don't replace it.
Privacy changes how testing is reported
Calendar output is useful evidence and private data at the same time. Live checks reduce results to operation counts, interval counts, generic state, and failure categories before they are shared. Calendar labels, event content, attendees, meeting links, provider identifiers, local paths, and signing identity details stay on the test machine.
Synthetic events cover automated tests. Real-calendar acceptance reports only enough aggregate evidence to show that Main and Busy converge independently, Availability is complete, the lock rejects overlap, and source calendars are unchanged.
Ship the technical path before the polished path
The first distributable build is a signed and notarized ZIP with checksum verification, a per-user installer, guided setup, diagnostics, backup, and removal. It is intentionally not the final consumer experience. It is the smallest package a technical user can install without a source checkout and operate without guessing at hidden state.
The goal for the preview is that someone else can install it, understand it, recover it, and remove it safely.The Mac app and broader distribution follow after that claim survives a clean machine.
The tradeoff
This approach produces more explicit gates than a typical side project. A calendar permission change or signing rebuild can stop a merge even when every automated test is green. That costs time, but the alternative is discovering ownership, privacy, or installation failures in someone else's calendar.
The payoff is a project that can move quickly without treating user data as the place where integration testing happens. Each milestone adds capability while preserving the same safety contract underneath it.