OneShot

← All packs

Scheduling & Availability Core

complex-universaldraft

Recurrence, timezones, DST and double-booking done correctly inside your own product: RFC 5545 expansion in floating wall-clock time, IANA zone-identity handling with a pinned gap/overlap policy, buffers and multi-seat capacity, and a booking path that is safe under real concurrency — an agent-executable blueprint with a 39-check acceptance harness that runs property tests over real DST transitions across six zones and races 16 concurrent bookers against real PostgreSQL.

How install works

  • Accounts
  • Tools

Tool install: ~10 minutes if you already have Node and Docker; ~25 if not. No accounts to create.

Full setup walkthrough ships in the zip after purchase.

Coming soon — $99
Execution receiptVerification pending

This pack has not completed a verification run yet, so nothing is published here. When the harness runs it, this space becomes the measured record: pass rate as M of N clean-scaffold runs on a pinned model, per-run token cost and wall time, per-check results, locked dependency versions, and whether the scaffold was left pristine. No pass rate, token cost, or deploy is claimed until then.

Scheduling looks like CRUD until the clocks change and two people click Book at the same second — and then it is recurrence expansion across a 23-hour day, a wall clock that happens twice, a 30-minute DST shift on Lord Howe Island, and a write-skew race that passes every single-threaded test you would think to write. This pack builds the hard core of that: RFC 5545 recurrence expanded in floating wall-clock time, IANA zone-identity handling with a pinned answer to the two ambiguous cases, buffers and multi-seat capacity, and a booking transaction guarded by a per-resource lock and a PostgreSQL exclusion constraint. The proof is `verify.sh`: **39 checks**, including >20,000 property samples over 12 real DST transitions across six zones, the RFC's own published recurrence examples, and 16 concurrent bookers racing against real PostgreSQL — plus one check that asserts the *naive* check-then-insert pattern genuinely does double-book in that same database, so the race test is proven to have teeth rather than assumed to.

**Status: `draft` — no receipt yet.** Every verified pack in this catalog publishes a measured pass rate as *M of N* clean-room builds. This one has not been through the harness, so it publishes nothing: no pass rate, no measured token count, no measured dollar cost. The figures below that are not version pins or citations are labelled as estimates. When it runs, whatever comes out gets published.

Example use cases

  • **A dental or physio practice-management tool** where three chairs are three seats on one resource, appointments carry a 15-minute turnaround buffer, and the recurring "Tuesdays 9–5, no Wednesdays" template has to still mean 9am on the Tuesday after the clocks change.
  • **A gym or studio class-booking app** where a 6am HIIT class holds twelve people — exactly twelve, including the morning fifty people refresh the page at once — and a cancellation two minutes before must free exactly one spot even if the customer taps Cancel four times.
  • **A field-service / trades dispatcher** covering vans across several regions in different zones, where the booking horizon is "up to 30 days out, at least 4 hours' notice", and a job's travel buffer must block the slot on either side without eating into the technician's shift window.
  • **An indie SaaS adding "book a call with me" inside its own product** rather than sending users to a third-party scheduling link — same brand, same session, same database, one `POST /bookings`.
  • **A tutoring or lessons marketplace** where a tutor in `Pacific/Auckland` and a student in `America/New_York` are looking at the same slot list on opposite DST schedules, and both need to be right.
  • **An agency re-stamping one scheduling core across client projects** — clinic, salon, driving school — instead of rediscovering the DST and double-booking bugs once per contract.

Why this pack

No "always" claims — agents are stochastic, and no scheduling design is free of tradeoffs. This is what the pack pre-solves, what it costs, and what you give up.

Bare agent, no packEmbedded-scheduling API (Cal.com Platform / Cronofy / Nylas)Hand-rolled in-houseThis pack
**Cost**"Free" (agent time only)Recurring, and priced in three incompatible units: Cal.com Platform bills **per booking** ("charged for a scheduled booking only when the booking starts", plus overage above the plan's included volume); Cronofy's published API tiers start at **$819/mo** billed annually; Nylas prices **per connected calendar account** (Calendar plan **$10/mo** including 5 accounts, then **$1.50/account/mo**)Engineering time — realistically weeks, paid however you pay engineers**$99 one-time**
**Time to correct behaviour**Unknown. An agent asked to "add booking" has no reason to know these bug classes exist until a customer finds themFast to integrate, and correctness is theirs — genuinely their strongest argumentSlow. These bugs are usually found by users in March and October, not by tests3 sessions on a $20/mo agent plan, per the pack's own budget (estimate — no receipt yet)
**Correctness risk**High and seasonal — see the bug classes belowLow for what they cover; you inherit their semantics and their bugs, and cannot fix eitherHigh until you have independently rediscovered every failure mode belowBounded by `verify.sh`'s 39 checks. **No published pass rate yet** — this pack is `draft`
**Lock-in**None, but no guardrails eitherReal. Your availability model, booking lifecycle and data live behind their API; leaving means rebuilding the core *and* migrating booking historyNoneNone — your repo, plain TypeScript and PostgreSQL, one runtime dependency (`pg`), no runtime call to us or anyone
**Fits inside your product**YesDepends. Their scheduling primitives, your UIYesYes — three functions, no UI, no HTTP layer, no opinion about your framework

### Buy the product instead, if that's what you actually want

**If what you need is a booking *product* — a scheduling page, a shareable link, calendar sync, reminder emails, round-robin across a team — buy that.** Calendly's Standard is **$10/seat/mo** and Teams **$16/seat/mo** billed yearly (Enterprise starts at a published **$15k/yr**); Cal.com is **free for one user**, **$12/user/mo** for Teams and **$28/user/mo** for Organizations billed yearly. Either will be live this afternoon and will do a dozen things this pack explicitly does not: no UI, no calendar-provider sync, no notifications, no payments, no round-robin, no `.ics` import/export (all listed as non-goals in the PRD, not omissions).

This pack is for the other case: **scheduling that lives inside a product you own**, where the booking flow is your product's flow, the data is in your database, and sending users to a third-party page is not an option. That is a real and different job, and it is the one where the timezone and concurrency work stops being someone else's problem.

One thing worth knowing if you were planning to self-host Cal.com to get the best of both: **Cal.com went closed-source in April 2026.** The public repository is now `calcom/cal.diy` — an MIT-licensed, community-maintained fork with Teams, Organizations, Insights, Workflows and SSO removed, no hosted version, and a production codebase that Cal.com states "has significantly diverged, including major rewrites of core systems". "Self-host Cal.com free under AGPL" is no longer a thing that exists. That changes the build-vs-buy arithmetic and it is why it is in this table rather than a footnote.

### What a bare agent typically ships that this pack pre-solves

These are specific bug classes, not a claim that every agent hits every one. Each has a named check in `ACCEPTANCE.md`.

  • **Storing a UTC offset instead of a zone identifier.** `+05:30` or a `timestamptz` availability anchor looks correct and is correct until the zone's next transition, then wrong by exactly the transition size, forever. Every recurring appointment breaks twice a year. `tz:offset-storage-drifts` reproduces and *measures* the drift. The trap has a second lip: `EST` and `PST8PDT` are resolvable legacy tz entries that carry no location, so a resource "in EST" silently opts out of DST permanently — the pack rejects them at the boundary.
  • **Expanding RRULEs in UTC instead of local wall clock.** Adding 86,400,000 ms per day is right until a 23- or 25-hour day, after which "9am every Tuesday" is 8am or 10am. And it is *not* uniform: Lord Howe Island shifts 30 minutes, not 60, so a whole-hour correction is wrong there too, and Chatham sits at +12:45/+13:45 so anything assuming whole-hour offsets fails before DST even enters the picture.
  • **Picking the disambiguation policy by accident.** Twice a year every zone produces a wall clock that happens twice and one that never happens. Most implementations resolve them however their date library happens to; this pack pins **first occurrence** for the overlap and **pre-transition offset** for the gap, which is RFC 5545 §3.3.5 FORM #3 and is byte-for-byte `Temporal`'s `disambiguation: "compatible"` — cited, not chosen.
  • **Silently ignoring an RRULE part you didn't implement.** An agent that parses `FREQ`, `INTERVAL` and `BYDAY` and drops `BYSETPOS`, `WKST` or `BYWEEKNO` produces availability the caller believes they restricted and the system did not. This pack **rejects** every unsupported part at parse time with a named error. (`WKST` is not cosmetic: RFC 5545 ships the demonstration that changing only `WKST` from MO to SU changes which dates a rule produces.)
  • **Check-then-insert with no constraint and no lock.** Two READ COMMITTED transactions both see a free slot, both insert, both commit. It passes every single-threaded test that will ever be written against it, and double-books the first time two people click at once. `race:naive-check-then-insert-double-books` proves this happens in the pinned database before asserting that the shipped path does not.
  • **`ON CONFLICT DO NOTHING` as the "fix" for the constraint violation.** Verified on PostgreSQL 18.4: it does not error — it inserts nothing and returns nothing. A handler that does not inspect `rowCount` tells the customer "booked" while the database holds no booking, and it looks like a happy path in every log line. (`ON CONFLICT (cols)` raises `42P10` and `DO UPDATE` raises `42809`; there is no upsert path for an exclusion constraint at all.)
  • **A `seats_remaining` counter.** The obvious model, and it makes cancellation non-idempotent: a retried cancel decrements twice and the resource is quietly overbooked forever after. This pack has **no counter anywhere** — capacity is counted from confirmed rows, and a partial exclusion constraint frees the seat the instant a status changes.
  • **Checking raw ranges instead of buffered ones.** A 15-minute post-appointment buffer that the availability check ignores is not a buffer. Worse, if the app's overlap rule and the database's constraint index different ranges, they will eventually disagree about what a conflict is.

### These bugs are live in funded, mature products

Not hypothetical, and not cherry-picked from hobby projects:

  • **Microsoft Bookings shifts availability by an hour around DST transitions.** Microsoft's own support responder, on a question asked 2026-03-18: Bookings "relies on time-zone conversion (using UTC internally), and during Daylight Saving Time transitions, availability can temporarily appear shifted by one hour if time-zone settings are not fully aligned" ([Microsoft Q&A](https://learn.microsoft.com/en-au/answers/questions/5827732/how-come-bookings-can-books-appointments-outside-b), retrieved 2026-08-02). A separate January 2026 thread has slots displayed 4:00am–1:00pm instead of 9:00am–4:00pm, with the recommended fix being the "Always show time slots in business time zone" setting ([Microsoft Q&A](https://learn.microsoft.com/en-us/answers/questions/5723721/microsoft-bookings-showing-wrong-times-for-meeting)) — while [another thread](https://learn.microsoft.com/en-us/answers/questions/7c3f1838-f162-4791-b995-05d88898e839/microsoft-bookings-showing-wrong-times-with-always) reports that same setting *causing* wrong slots plus a "Slot is not available" error on submit, resolved by turning it off.
  • **Microsoft Bookings ships a user-visible double-booking race message.** *"Someone beat you to it. This time is no longer available. Please choose another one."* — reported on a **1:N multi-attendee service** (max 4 per slot), i.e. exactly the capacity>1 case an exclusion constraint alone cannot express ([Microsoft Q&A, 2024-12-14](https://learn.microsoft.com/en-us/answers/questions/5398616/issue-with-cancellation-and-rescheduling-for-1-n-s), retrieved 2026-08-02).
  • **Calendly maintains a standing timezone troubleshooting guide** in its community ([Time Zone Troubleshooting Guide](https://community.calendly.com/how-do-i-40/time-zone-troubleshooting-guide-242)), an official [time zones overview](https://calendly.com/help/time-zones-overview), and a dedicated [Troubleshoot Tool article for "unavailable times that should be available"](https://calendly.com/help/how-to-troubleshoot-unavailable-times-that-should-be-available). A scheduling company shipping a permanent diagnostic tool for "why isn't this slot bookable" is the clearest statement available that this is hard.
  • **Cal.com — a scheduling company — has open bugs of both classes in its own engine.** [#23974 "Reservation-to-Booking flow allows double-booking reserved slots"](https://github.com/calcom/cal.diy/issues/23974) (opened 2025-09-22, still open, labelled urgent/S1-Critical) describes a textbook time-of-check-to-time-of-use: "another user could book the slot before reservation deletion". [#24350](https://github.com/calcom/cal.diy/issues/24350) (opened 2025-10-08, open) is a DST offset bug — backend stores correct UTC, frontend re-derives it wrong at the March/October transition. [#22801 "Duplicate double bookings using recurring booking links"](https://github.com/calcom/cal.diy/issues/22801) (opened 2025-07-30) is open too. All retrieved 2026-08-02.

None of this is a claim that those products are bad. It is the opposite: these are well-funded teams who have thought about scheduling for years, and this is still where the bugs are. That is the argument for buying the answers rather than deriving them.

Scale envelope

Derived from the shipped design, not aspiration, and labelled as estimates where they are estimates. Nothing here is load-tested — this pack has no receipt yet, so it has no measured performance numbers at all.

The serialisation point is **one `pg_advisory_xact_lock` per resource**. That is the ceiling to reason about, and it is deliberately per-resource rather than global so that a busy clinic does not queue behind an idle one.

  • **Bookings per resource (estimate, not load-tested):** a booking transaction is a lock acquisition, four small indexed reads, and one insert. On managed Postgres in the same region that is typically tens of milliseconds, putting a rough order-of-magnitude ceiling in the **low hundreds of bookings per second for a single resource** — sustained. A "resource" is one practitioner, room, chair or van. No real one is booked hundreds of times a second, which is why this ceiling is comfortable rather than clever.
  • **Resources in parallel:** unbounded by this design — different resources take different lock keys and never contend. The real limit becomes your `pg.Pool` size (default `max: 10`) and the database's `max_connections` (PostgreSQL's default is 100), both of which you tune, not this pack.
  • **Availability reads:** `slotsForResource` is pure computation over the rules for one resource plus one indexed range query for overlapping bookings. Expanding a year of weekly rules is a few hundred instances; the hard cap is 10,000 instances per call. Cache it if you serve the same month to many visitors — this pack does not, deliberately, because cache invalidation on booking is your product's decision.
  • **Rows:** one row per booking, one per availability rule, one per exception. Millions of bookings is an ordinary PostgreSQL table for this schema, with a partial GiST index on the confirmed ones. Storage is not the constraint.
  • **First ceiling you will actually hit:** a single hot resource (a popular class, a "book the whole shop" flow) where concurrent booking attempts on the *same* resource start queuing on its advisory lock. That is added latency, not incorrect behaviour.
  • **Upgrade path when you hit it:** replace the lock with the lock-free variant — try seat 0, catch `23P01`, `ROLLBACK TO SAVEPOINT`, try seat 1 — which is correct by the same exclusion constraint and bounded by `capacity` attempts. `ARCHITECTURE.md` names it as the documented upgrade with the tradeoff (savepoints and a retry loop in the hot path) already stated.

**What this comfortably covers as shipped:** a multi-location clinic, a studio with a full class timetable, a trades business with a fleet, a marketplace with thousands of independent providers — anything where load is spread across resources. **What it isn't sized for out of the box:** a single resource under genuine thundering-herd load (ticket-drop shaped, not appointment shaped). That is the upgrade path above, not a change this build makes for you.

**What it costs to skip the pack:** honestly, we do not know yet, and we will not invent it. The verified packs in this catalog publish a measured per-run token cost from their receipts; this one is `draft` and has none. What can be said without measuring: the timezone layer is roughly 35 lines and the recurrence layer a few hundred, so **do not buy this to save typing.** Buy it because the 39 checks encode which 35 lines, and because several of those checks map directly onto bugs that are open right now in products built by companies whose entire business is scheduling.

Target models

  • claude-opus-5
  • claude-sonnet-5
  • claude-haiku-4-5

Supported stacks

  • node-postgres
    node24.18.1
    typescript6.0.3
    tsx4.23.4
    pg8.22.0
    @types/node24.13.3
    @types/pg8.20.3
    postgres18.4

Estimated buyer token cost

560,000 tokens for one build pass (estimate, not a guarantee).

FAQ

What if the build fails?

`verify.sh` is the arbiter, and it's deterministic — no network calls beyond `npm install` and the first Docker image pull, no credentialed API, no wall-clock dependence, and all 12 DST fixtures are past transitions that cannot be invalidated by a tz database update. Full refund within 14 days of purchase if `verify.sh` fails on a supported configuration (the pinned stack and a model from the pack's matrix) — reply to your Stripe receipt email with the verify output or `FAILURE-REPORT.md` attached. If your agent modified a frozen file (`verify/`, `src/core/types.ts`, `src/db/schema.sql`, `docker-compose.yml`, or the pinned versions) or added a date/recurrence library to get a check to pass, that falls outside the guarantee — the fix is to fix the implementation, not the test, per the pack's own verify prompt.

Does this pack have a receipt?

No. It is `draft`, which is why this listing publishes no pass rate, no measured token count and no measured cost. It becomes `verified` only after OneShot's harness runs it end to end in a clean workspace N times, and the result is published as *M of N* — whatever M turns out to be. If it cannot be got green, it does not get listed. The estimates on this page (3 sessions, ~560k fresh tokens) are extrapolated from a comparable verified pack in the catalog and will be replaced by measurements, not defended.

What models does this need?

Written against `claude-opus-5`, `claude-sonnet-5` and `claude-haiku-4-5` — but with no receipt yet, that matrix is the intended target, not a verified result. Tasks are pre-tagged `cheap`/`standard`/`capable` in `TASKS.md` and routed accordingly; five tasks are Opus-tier (the zone layer, the recurrence layer, slot generation, the booking path, and the verify/fix pass), which is what forces a session split on a $20/mo plan rather than raw token volume. Anthropic doesn't publish an exact token-per-window figure for Pro's rolling-window and weekly caps, so treat the 3-session estimate as an expectation, not a guarantee.

Why does it have no UI?

Because a UI would be the least valuable and most opinionated part, and shipping one would make this a worse version of a product you can already buy. What is hard about scheduling is not the calendar grid; it is what the calendar grid is *told*. The pack ships three functions and tells you exactly where to attach your own handlers. If you want the grid, buy Calendly or Cal.com — the "Buy the product instead" section above says so plainly and means it.

Why hand-roll the timezone and recurrence layers instead of using a library?

Two different reasons, both stated in `ARCHITECTURE.md` rather than assumed. For timezones: the disambiguation policy *is* the product, and a scheduling core that outsources it has outsourced the one decision the buyer is paying to have made, to a library whose policy they never chose and cannot cite — and it is 35 lines against a dependency, because full ICU (the entire IANA database) has shipped inside Node by default since Node 13. For recurrence: `rrule@2.8.1` is the obvious candidate, its last npm publish was **2023-11-10** and its last commit **2024-06-27** with 212 open issues, and — by its own README — it computes in floating time and hands back `Date` objects that must be re-interpreted before they are instants. Since that re-interpretation is the timezone layer we own anyway, the library solves the easy half and hands the hard half back. So the pack scopes the RRULE subset instead, and *rejects* what it does not implement rather than ignoring it. The result is one runtime dependency: `pg`.

Which RRULE features are actually supported?

`FREQ` (DAILY, WEEKLY, MONTHLY, YEARLY), `INTERVAL`, `COUNT`, `UNTIL`, `WKST`, `BYDAY` (with and without ±ordinals), `BYMONTHDAY` (including negative), `BYMONTH`, `BYSETPOS`, plus `EXDATE` and `RDATE`. Explicitly **rejected at parse time with a named error**: `BYWEEKNO`, `BYYEARDAY`, `BYHOUR`, `BYMINUTE`, `BYSECOND`, `RSCALE`/`SKIP` (RFC 7529), and `FREQ` of SECONDLY/MINUTELY/HOURLY. That is a real limit and it is enforced rather than papered over — a rule your system silently ignored is worse than one it refused. If you need ISO week numbers or non-Gregorian calendars, this is the wrong core and the pack will tell you so at write time rather than at booking time.

Can I customise it after the build?

Yes, and the seams are named. The disambiguation policy is one function. Buffer semantics (`post + pre`, pinned) are one expression. `maxHorizonDays` is exact 24-hour days; making it calendar days in the resource's zone is a one-function change. The RRULE subset is extensible if you need `BYWEEKNO`. Auth and tenancy are a `WHERE` clause in your own handlers. In every case `verify.sh` is still there to tell you what else your change moved — which is the actual reason to own the code.

Do I own the code?

Yes. Once built it's your repo — plain TypeScript and SQL with one runtime dependency (`pg`), no runtime call to any third-party scheduling service or to us, no license key, no recurring anything.

What happens when a country changes its DST rules?

Your running app doesn't break — it runs on the tz data baked into its Node runtime and keeps working; only *future* instants in the affected zone go stale. The fix is a runtime bump plus a `verify.sh` run, and `MIGRATION.md` ships a copy-paste prompt that has your agent read the tzdb NEWS file since your runtime's version, work out whether the release touches a zone you actually operate in, apply the change and re-run the suite until green. The occasional case that needs real work is a zone **rename or split** (`Europe/Kiev` → `Europe/Kyiv`; `America/Coyhaique` split out of `America/Santiago` in 2025) — a rename is a no-op if you stored identifiers, and a split is a `WHERE` clause. If you had stored offsets, neither would be recoverable. We re-verify listed packs on our own schedule and prior buyers get every re-verified version free, but we promise no delivery date and this is not a subscription or a maintenance contract — section 3 of `MIGRATION.md` exists so your build never has to wait on us.

Does it sync with Google Calendar or Outlook?

No, and that is a stated non-goal rather than a gap. Calendar-provider sync is an OAuth-credentialed surface that could not be verified hermetically, and this catalog does not ship what it cannot prove. If "check my Google busy times" is a core requirement, Cronofy and Nylas exist and that is precisely what they sell.

Prescribed services

Disclosure: some links on this page are affiliate links. We may earn a commission if you sign up through them, at no extra cost to you. We only link to services the pack actually verified against.