autocode

← Slotbook experiment

Milestone 3 — cancellation, rescheduling & notifications

Process

Acceptance tests higher is better
CC-Opus4.8-i1 20/20 CC-Opus4.8-i2 20/20 18/20 before one fix-it CX-5.6-i1 20/20 18/20 before one fix-it CX-5.6-i2 20/20 16/20 before one fix-it
Wall-clock (minutes) lower is better
CC-Opus4.8-i1 10.6 CC-Opus4.8-i2 9.7 CX-5.6-i1 15.7 CX-5.6-i2 13.4
Turns context
CC-Opus4.8-i1 106 CC-Opus4.8-i2 92 CX-5.6-i1 n/a CX-5.6-i2 n/a
Output tokens lower is better
CC-Opus4.8-i1 40.8K CC-Opus4.8-i2 37.4K CX-5.6-i1 55.7K CX-5.6-i2 54.4K
Input tokens context
CC-Opus4.8-i1 9.25M CC-Opus4.8-i2 5.55M CX-5.6-i1 6.67M includes fix-it replay CX-5.6-i2 5.56M includes fix-it replay
Actions context
CC-Opus4.8-i1 105 CC-Opus4.8-i2 90 CX-5.6-i1 52 CX-5.6-i2 41
Diff size (lines added) context
CC-Opus4.8-i1 +1,129 CC-Opus4.8-i2 +1,070 CX-5.6-i1 +736 CX-5.6-i2 +882
Self-verification
CC-Opus4.8-i1 browser click-testing, API probes, typecheck, build CC-Opus4.8-i2 browser click-testing, typecheck, build CX-5.6-i1 API probes, ad-hoc self-test suite, typecheck, build CX-5.6-i2 API probes, browser checks (MCP), typecheck, build
Committed work
CC-Opus4.8-i1 no (did at m1) CC-Opus4.8-i2 no (did at m1) CX-5.6-i1 no CX-5.6-i2 no
Code at this milestone
CC-Opus4.8-i1 m3 · diff CC-Opus4.8-i2 m3 · diff CX-5.6-i1 m3 · diff CX-5.6-i2 m3 · diff

Task checks

POST /api/bookings returns a manageToken; the confirmation page shows the manage link
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2
An invalid manage token exposes no management actions
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2
Invitee cancel frees the slot; a new booking can take it
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2
Cancelled booking stays on the host dashboard, marked as cancelled
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2
Reschedule releases the old slot and books the new one
CC-Opus4.8-i1 CC-Opus4.8-i2 1 fix-it CX-5.6-i1 1 fix-it CX-5.6-i2 1 fix-it
Booking emails sent to invitee and host, naming the event
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2 1 fix-it
Invitee cancellation emails the host, action clear in the subject
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2 1 fix-it
Reschedule emails both parties, action clear in the subject
CC-Opus4.8-i1 CC-Opus4.8-i2 1 fix-it CX-5.6-i1 1 fix-it CX-5.6-i2 1 fix-it
All milestone-1 and -2 behavior still passing (regression check)
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2

Code metrics

Source lines context
CC-Opus4.8-i1 3,746 44 files CC-Opus4.8-i2 3,214 40 files CX-5.6-i1 2,102 34 files CX-5.6-i2 2,659 36 files
Own tests context
CC-Opus4.8-i1 0 CC-Opus4.8-i2 0 CX-5.6-i1 0 CX-5.6-i2 0
Most complex function lower is better
CC-Opus4.8-i1 44 CC-Opus4.8-i2 24 CX-5.6-i1 21 CX-5.6-i2 21
Functions over complexity 15 lower is better
CC-Opus4.8-i1 1 CC-Opus4.8-i2 2 CX-5.6-i1 1 CX-5.6-i2 2
Unused exports lower is better
CC-Opus4.8-i1 26 CC-Opus4.8-i2 13 CX-5.6-i1 10 CX-5.6-i2 5
Orphan modules lower is better
CC-Opus4.8-i1 5 CC-Opus4.8-i2 1 CX-5.6-i1 4 CX-5.6-i2 4
Circular dependencies lower is better
CC-Opus4.8-i1 0 CC-Opus4.8-i2 0 CX-5.6-i1 0 CX-5.6-i2 0
Escape hatches lower is better
CC-Opus4.8-i1 0 CC-Opus4.8-i2 2 CX-5.6-i1 1 CX-5.6-i2 0
Bug-prone lint findings lower is better
CC-Opus4.8-i1 1 eqeqeq CC-Opus4.8-i2 2 exhaustive-deps CX-5.6-i1 0 CX-5.6-i2 0
Churn factor context
CC-Opus4.8-i1 1.27 CC-Opus4.8-i2 1.06 CX-5.6-i1 1.06 CX-5.6-i2 1.12
Type coverage (%) higher is better
CC-Opus4.8-i1 99.5% CC-Opus4.8-i2 99.2% CX-5.6-i1 99.3% CX-5.6-i2 99.7%
Duplication (%) lower is better
CC-Opus4.8-i1 0.2% CC-Opus4.8-i2 3.4% CX-5.6-i1 2.9% CX-5.6-i2 2.9%

Review

One card per registered criterion; cells are descriptive, not scores. Full text with citations: light review · i2 addendum.

Reschedule write path
CC-Opus4.8-i1 atomicity settled at the database: the swap is a single UPDATE, concurrent takers resolve through the partial unique index — no locks, no both-held/neither-held window; the new slot revalidated server-side with self-exclusion. CC-Opus4.8-i2 converges on i1's resolution: a single in-place UPDATE … WHERE status='confirmed' with the index arbitrating concurrent takers, plus excludeBookingId self-exclusion so a booking can't block its own move. CX-5.6-i1 reuses its m2 concurrency primitive wholesale: row FOR UPDATE + per-host advisory lock + availability re-check with self-exclusion inside one transaction, ending in a single UPDATE. CX-5.6-i2 replicates i1's design wholesale (src/lib/bookings.ts) — the client-submitted slot is never trusted.
Notification semantics
CC-Opus4.8-i1 exactly-once: cancel and reschedule gate on status='confirmed', zero rows updated means no email, and sends are best-effort behind the committed write — a mail failure can't fail or double-fire a mutation. CC-Opus4.8-i2 sends are awaited post-commit with no try/catch — a mail failure surfaces as a user-facing error after the mutation durably succeeded; the m1 email seam, now on three write paths. CX-5.6-i1 invitee-cancel notifies the host only, host-cancel notifies both parties; the optional host message is validated and appended only in the host-cancel branch. CX-5.6-i2 notifications fire only after commit and gate on .changed — repeated cancels can't re-fire mail.
Email copy
CC-Opus4.8-i1 subjects embed raw UTC contract instants (…moved to 2026-08-14T09:00:00.000Z) — machine format in human-facing copy. CC-Opus4.8-i2 raw UTC instants in subjects, as i1's. CX-5.6-i1 best subject lines of the run: event, action, and both times in every notification (lib/booking-emails.ts). CX-5.6-i2 regressed against its own i1: raw UTC instants interpolated directly, and all three notification tests failed before the fix-it.
Manage token & authz
CC-Opus4.8-i1 256-bit randomBytes token, UNIQUE column, unknown token → plain 404; the manage page still works after the host archives the event type. CC-Opus4.8-i2 graceful degradation for orphaned bookings: a deleted event type leaves reschedule reporting no_event_type and the manage UI offering cancel-only. CX-5.6-i1 database-generated UUID with UNIQUE + backfill, format-gated by regex before any query; host cancel scoped in SQL (WHERE host_id) — cross-host cancels and double-cancels are no-ops. CX-5.6-i2 256-bit base64url token, regex format gate, notFound() on miss, noindex metadata.
Picker reuse
CC-Opus4.8-i1 extracted the slot picker into a shared component (src/ui/slot-picker.tsx) — booking and reschedule are literally the same picker; duplication held at 0.2%. CC-Opus4.8-i2 the opposite call to i1: ManagePanel.tsx is a ~360-line copy of BookingFlow.tsx (duplication 0.4% → 3.4%), with copy drift already visible between the twins. CX-5.6-i1 the manage flow copy-pastes the picker's timezone, formatting, grouping and grid code (0.3% → 2.9%, 7 clones) — the opposite call to claude-i1's extraction. CX-5.6-i2 2.9% duplication from timezone-helper and buffer-math copy-paste — i1's rate, from a less severe cause.
Double-booking guard
CC-Opus4.8-i1 the cross-duration overlap race is unchanged: the index arbitrates start equality only, and reschedule inherits the app-level-only overlap check. Milestone 4 targets exactly this. CC-Opus4.8-i2 CX-5.6-i1 CX-5.6-i2
Infra-failure handling
CC-Opus4.8-i1 CC-Opus4.8-i2 CX-5.6-i1 the catch-all 409 propagated: the new reschedule action maps any failure to slot_unavailable — two of three write paths now report infrastructure failure as "slot taken"; cancel's catch returns a generic "failed" (the better pattern, applied inconsistently). CX-5.6-i2
Committed tests
CC-Opus4.8-i1 none. CC-Opus4.8-i2 none. CX-5.6-i1 none. CX-5.6-i2 none.