Release notes

CycleWingman 1.2: day notes

July 22, 2026 · UpFlyDev engineering

cyclewingmanreleaseengineering

So far CycleWingman has been a one-way instrument: you tell it where a partner is in her cycle, it tells you what kind of day to expect — Green, Yellow, Orange or Red. Version 1.2 adds the other direction. You can now tell the app how the day actually went, right on the calendar and right from your watch. Here's what shipped, and the engineering behind it.

What's new

  • Day notes on the calendar: tap any day, today or past, to log your partner's mood, event tags (a date, quality time, a disagreement, a make-up, good news, a hard day) and an optional written note. Days with a note carry a small dot. Everything is edit- and delete-able.
  • Note-taking on Apple Watch: tap the status card on the watch to jot today's mood and tags from your wrist — no phone needed in the moment.
  • A redesigned day view: tapping a calendar day now opens a centered card tinted with that day's status color. Flick left/right to step days, tap above or below to dismiss.
  • The Today's status card on the home screen is now tappable and jumps straight to today on the calendar; a dashed outline keeps today visible when you've selected another day; and the calendar's edge days from the next month are finally tappable.

Notes are journaling, not diagnosis. They live on your device, they're never uploaded, and — for now — they don't change the forecast. They're groundwork: a private record that a later version can learn from, with your data never leaving your phone to do it.

Under the hood

A journal that deliberately stays out of the forecast

CycleWingman's forecast engine exists twice by design — the TypeScript original in the web layer and a Swift mirror in WingmanCore for the watch — kept honest by golden-fixture parity tests. The obvious thing to do with day notes is feed them back in: "she logged a conflict yesterday, nudge today's estimate." We deliberately didn't.

The moment a note influences a forecast, its data type joins the parity surface: every field and default has to be mirrored in Swift and pinned by a fixture, forever, on both engines at once. For 1.2 we kept notes journaling-only — stored on the partner, drawn on the calendar, read back on the watch, but never entering the engine. The parity contract stays small while the data quietly accumulates; when the shape has settled, a later release can decide to use it deliberately rather than being locked into a schema we picked on day one.

The first path from the watch back to the phone

Until now every byte moved one way: the phone computed forecasts and pushed them out to the watch face. Taking notes on the watch reverses that flow for the first time — and the app's UI being a web view inside a native shell makes it interesting.

The watch sends a note with transferUserInfo, which guarantees delivery even if the phone is asleep in another room. The catch: that note can arrive at the phone's WatchConnectivity receiver before the web layer is even running. So the native shell buffers incoming notes into a shared app group and holds them there; only once the web app boots and posts back a "ready for watch logs" message does the shell flush the queue into the WebView as a custom DOM event, which the app turns into a saved note. Today's note syncs back to the watch too — but written text stays phone-only (you're not typing a paragraph on a watch), and editing mood or tags from your wrist preserves whatever text you'd written on the phone.

A day you can flick through

The old calendar was colored squares and nothing else. 1.2 turns a tap into a centered modal tinted with the day's status color, and lets you move between days without closing it — swipe inside the card or tap its left/right edge to step, tap above or below to dismiss. The fiddly part was telling a tap-to-navigate apart from a swipe on a bare touch surface, with no gesture library, and making the whole thing respect the free-forecast horizon: flick past the edge of what your plan covers and the card becomes the Wingman+ upgrade prompt instead of leaking a locked day.

One quiet piece of maintenance

Android's in-app purchases moved to Google Play Billing Library 9, ahead of Google's requirement that apps be on v8 or later by August 31, 2026. Nothing changed in the subscription flow or pricing — iOS purchases run on StoreKit and were untouched — but the query callback now hands products back through a new result type, so BillingManager was adapted to match.

Get CycleWingman — free, sets up in under a minute, and nothing ever leaves your phone. On both stores.

Download on the App Store Get it on Google Play

Learn more about CycleWingman →