Live status — 2026-05-30. Canonical per-turn gate 87/87, deterministic on events-in-studio (shell-smoke flake auto-recovers via scoped Playwright retries). The Events Studio admin app is fully de-frauded and verified end-to-end; the wave is now in test-hardening and awaiting operator direction on what comes next. Turn-by-turn detail lives in the tables below.
✅ Done & live-verified
SAMPLE_*).🔧 In flight — P8-T15
segments count-drift vs the live simulator; help-docs nav abort) deterministic without weakening the de-fraud guarantee. Test-only.⏳ Awaiting the operator
See Jim's J7 · Operator QA.
SAMPLE_* in the Events Studio shell live path (fixture mode intentionally sample-backed). Polish-7 underway: P7-T1 simulator current-window traffic realism — clamped all simulator/audit timestamps to now±30d, bounded backfill, purged far-future rows (438 events + ~12k audit/guest rows); live dashboard now shows believable today/30-day data (events today 2, registered 491, checked-in 421, date 2026-05-29), gate 147. Next: ongoing daily-cadence + registration-curve realism so traffic grows organically day-over-day. All operator-filed findings (#1 / #2 / #25 / #26) cleared.
voyage-notifications worker 500 to a D1 binding drift (bound to dead voyage-tenant-ops → repointed to canonical aperture-ops, redeployed). Worker-path SMS now sends via Twilio (provider=twilio, real SM… SIDs) — closes the deferred Polish-6 SMS go-live smoke. Nick + Jim test texts delivered through the live worker.
Polish-4 shipped a cron-triggered simulator that produces realistic activity through real /v1/admin/* endpoints, deepening the 6 Polish-3 D1-backed surfaces with production-shape data. T25–T29 backend is live. The remaining simulator-finishing work moved to Polish-7 so we can audit, polish, and broaden coverage before deepening further.
| Turn | Status | Title | Scope | Gate |
|---|---|---|---|---|
| T25 | Shipped | Simulator scaffold + persona base | 5-min cron worker, 40 Aperture staff personas, events_studio_simulator_state D1 table, /admin/simulator shell route. |
148/148 |
| T26 | Shipped | Calendar/availability engine | Per-persona rolling 14-day availability, deterministic sick/time-off injection. 1680 availability rows + 1682 audit actions live. | 149/149 |
| T27 | Shipped | Event creation cadence | 15 templates, capacity- and skill-matched auto-create through existing admin endpoint. 31 events live. Idempotent re-runs. | 150/150 |
| T28 | Shipped | Booking/RSVP curve engine | S-shaped arrival curves, past-event finalization with 75/22/3 attended/no-show/cancelled split. 1591 registrations + 3182 booking responses live. | 151/151 |
| T29 | Backend ✅ | Failure-mode injection | 5 chaos engines (sick-cascade, overbooking+waitlist, double-booking, payment-declined, bulk-cancel-24h). Audit table with severity + recovery tracking. Backend live; full cumulative gate deferred to Polish-7. | deferred |
One dedicated turn to re-audit the 52 tracked Events-in-Studio routes against the Issue #22 baseline, the latest Claude design output, and this morning's operator findings. Produces the canonical Polish-5 backlog plus any newly surfaced Polish-6 / Polish-7 / Polish-8+ work.
| Turn | Status | Title | Scope | Gate |
|---|---|---|---|---|
| T33 | Shipped | Polish audit pass |
|
— |
Polish-5 keys off the operator's morning findings in polish-5-usability-findings.md, prioritized after T33's audit. Order may be revised by T33; below is the current best ordering. P5-T1 (chrome + icon visual re-sync against Claude design) must ship first — operator-elevated 2026-05-28T~12:50Z.
| Turn | Status | Title | Scope | Gate |
|---|---|---|---|---|
| P5-T1 | Shipped | Chrome + sidebar + icon visual re-sync vs Claude design |
Pure discriminating UI pixel-correctness + interaction audit against latest Claude design. No new functionality; just match the design.
|
— |
| P5-T1.5 | Shipped (72 passed gate) | Chrome follow-ups: shared <StatCard> + sidebar collapse wiring |
Bundles two P5-T1 follow-ups before moving to P5-T2:
|
~64 |
| P5-T2 | Shipped (81 passed gate) | Tenant switcher + bug-widget cleanup + publish roadmap as hidden route |
Three things bundled:
|
81 |
| P5-T3 | Shipped (84 passed gate) | Google OAuth callback 401/404 fix item #11 |
OAuth round-trip lands cleanly. Three pieces shipped:
|
84 |
| P5-T4 | Shipped (87 passed gate) | Event-drawer tab full-refresh fix item #12 |
Drawer tabs converted to path-based URLs (/events/:id, /events/:id/guests|tickets|share|settings) using React Router <Link> so tab switches are router-internal. Root cause was actually useRouteSkeletonLoading(pathname, search) being keyed off location.search — the visible refresh was the route skeleton flashing the background events list, not a duplicate API fetch. Codex pivoted from the directive's <a href> / [location]-deps guesses to the real fix. Stable selectors event-drawer, event-drawer-tabs, drawer-tab added; legacy event-detail-drawer preserved for Issue #22 regression coverage. Live verify: /events/evt-winter-collection-promo/guests — 200, no background flash on tab switch.
|
87 |
| P5-T5 | Shipped (91 + 1 flake) | Google setup wizard interaction polish + copy buttons items #7+#8+#9+#10 |
All four pieces shipped. Step 6 opens OAuth in a new tab, polls every 2.5s until {status:"connected"}, 5-min timeout. Step 4 auto-completes when step 5 credentials land (no-op Validate removed). Step 5 auto-greens on credentials saved (trivial Validate removed). Shared <CopyField> primitive (data-jrni-component="copy-field") applied to OAuth consent app name/domain/scopes, app name, redirect URI, Client ID, Client Secret. Cumulative gate 91 passed + 1 flaky shell HTML load that passed on retry — the flake was a transient net::ERR_NETWORK_CHANGED on initial nav, not a P5-T5 regression. 5 turn-branches landed via non-ff merges (wizard polish → 2x spec-fix → worker port → cumulative spec refresh). Live: Wizard.
|
91+1 |
| P5-T6 | Subsumed by P5-T5 | Copy buttons — bundled into P5-T5 item #10 | Copy buttons are small enough to bundle with the Validate-flow rework. Ship together so PM walk-through covers the full wizard. | — |
| P5-T7 | Subsumed by P5-T2 | Higher-ed tenant scrub item #5 |
Shipped in P5-T2 (single-tenant render as plain span[data-jrni-tenant-mode="single"], ?tenant=higher-ed fixture preserved). Row kept for ID-stability across links/notes.
|
— |
| P5-T8 | ✅ Shipped + verified (live) | Event-creation final-screen polish items #1+#2 |
Both items done — this row was stale (Queued); corrected 2026-05-30:
polish5-t8-create-event-publish-dedupe spec passes live (2/2 re-runs); shipped at gate 132.
|
132 |
| P5-T8.5 | Shipped | /events stat-card chrome cleanup + capacity-detail overflow item #14 |
The four /events stat cards (UPCOMING / LIVE NOW / TOTAL REGISTERED / ARCHIVED) were NOT in the P5-T1.5 seven-route shared <StatCard> migration — still on route-local StatTile with the pre-fix tiny-icon-in-big-box "amateurish" look. PLUS the TOTAL REGISTERED card has the green detail 24% of capacity wrapping word-by-word vertically instead of inline next to the value. Fix is small: migrate to the shared <StatCard> (will inherit the 28×28 / 14px / soft-tinted layout), confirm detail-text wraps correctly. Should bundle as a fast follow-up — small fix, high visible signal because /events is a frequently-viewed PM surface. Could be promoted ahead of P5-T8 / P5-T9 if operator wants the chrome story 100% closed first.
|
— |
| P5-T8.6 | Bundled into P5-Chrome-Finale | Wizard chrome polish (CopyField density + masked credentials) — folded into chrome finale | Items #16 + #17 bundled into the chrome finale turn below per operator direction 2026-05-28T~19:28Z. Single turn for the entire chrome closure. | — |
| P5-Chrome-Finale | Shipped (100 passed) | Shared <Button> + icon library audit + wizard chrome density + masked credentials items #15+#16+#17 |
Operator direction 2026-05-28T~19:28Z (priority change): "I'm also going to reject the UI as complete… I need that icon component polished turn right now, and I want the cards that we have for these integration steps not to be so stupidly huge… So again, next turn is polish on this integration and finally polish on these icons." Ships the moment P5-T8.5 closes. NO interleaving with P5-T8 / P5-T9 / anything else until the chrome story is 100% closed.
data-jrni-component="button" + variants, field-lock; reuses P5-T3/T5 selectors. Specs: button scrub, copyfield density, masked credentials. Live-URL after-screenshots of /events top-right + wizard Step 3 + wizard Step 5 connected. Largest visual turn of Polish-5 but each replacement is pattern-match. Operator-stated patience: "I need that icon component polished turn right now."
|
— |
| P5-IconLibrary-Refresh | Shipped (107 passed) | Icon library visual quality refresh + platform-wide inline-SVG scrub item #19 |
Operator direction 2026-05-28T~20:18Z: "I want every icon in the platform to fit in appropriate and professional looking design. That means every icon, whether it's in a stats card or elsewhere, needs to match this component type." After P5-Chrome-Finale shipped, the operator screenshots /events stat cards (UPCOMING / LIVE NOW / TOTAL REGISTERED / ARCHIVED) and /dashboard stat cards (EVENTS TODAY / REGISTERED TODAY / CHECKED IN TODAY / EVENT REVENUE) still feel "garbage" — the chrome finale fixed icon AFFORDANCES (no more text-character `v`/`+` carets) but did NOT touch the visual quality of the icon glyphs themselves.
|
— |
| P5-T8.9 | Shipped (112 passed) | Google OAuth "Error 401: invalid_client" — credential precedence fixed item #18 | Operator completed the OAuth flow in Google's UI and landed on Google's "Error 401: invalid_client" page instead of the events-studio callback. The credentials stored in Step 5 aren't being accepted by Google. Likely encryption pipeline corruption — the worker reads back a different value than what was typed at save time. Probe the encrypt → store → decrypt → OAuth-URL-construction path; deterministic round-trip spec; live smoke with known-good credentials. Same encryption codebase as P5-T9 (Salesforce decrypt) so this turn may also surface or resolve the Salesforce bug. Operator quote: "clearly something is wrong with the client ID we've saved." REQUEUED 2026-05-28T~20:18Z behind P5-IconLibrary-Refresh per operator direction. | — |
| P5-T8.93 | Shipped (119 passed) | Event status not derived from start_at/end_at vs now — Feb events still "Live" in May item #23 | Operator screenshotted /events showing events dated Fri, Feb 6, 2026 with a ● Live pill — three months in the past. Status was a stored field set at create time, never re-evaluated.
|
— |
| P5-T8.92 | Shipped (116 passed) | "Open landing page" returns "event not found" runtime error item #22 |
Clicking Open landing page on an admin event drawer routes to /public/events/<slug> — Pages returns HTTP 200 (SPA shell loads) but the SPA's data fetch returns "event not found." The admin sees the event as Live; the public landing-page worker can't find it. Most-likely root cause: public events live in a different D1 source than admin events (separate events_public table, or a publish-snapshot pipeline that simulator-seeded events skipped). Could also be slug mismatch or tenant scoping. Operator quote: "If I click open landing on some events I get event not found. This should never happen." Sample URL: https://events-in-studio.vxge-aperture.porivo.com/public/events/winter-collection-promotion. Same "no toy, no vaporware" pattern as the recurring concern — admin claims Live but the user-facing landing isn't actually wired. Probe: which D1 table is the public worker querying, does the admin event exist there with the same slug, what's the simulator's publish-to-public path. Pull ahead of P5-T8.96 (chrome polish) — this is a demo blocker.
|
— |
| P5-T8.96 | Shipped (124 passed) | Minor-polish bundle — multi-icon pill padding + public landing loading state items #21+#24 |
Two operator-stated minor findings bundled into one fast turn. Multi-icon format pills now expose data-jrni-format-pill-variant="single|multi" with explicit horizontal padding and 12px icon sizing; single-icon variant keeps the existing 38px square geometry. Public landing route now runs a { status: 'loading' | 'loaded' | 'error' } state machine with data-jrni-public-event-state on the root; skeleton renders during fetch, "Event not found" only renders after the fetch resolves missing. Three specs added (pill padding + loading transition + 404 regression). Honest accounting: directive referenced /events/new but the current shell only mounts /events/create/* — Codex correctly used the existing route rather than add a routing alias inside a styling-scope turn. Live URLs: /events/create for pills; /public/events/winter-collection-promotion for loading state; /public/events/this-event-does-not-exist for 404 regression. Repos: voyage f85b9bd6, voyage-aperture 20bb9ab1.
|
124 |
| P5-T8.97 | Closed by P5-T8.96 | Event public page flashes "event not found" before rendering item #24 | Closed by P5-T8.96's loading/loaded/error state machine. Public landing route now renders skeleton during fetch and "Event not found" only after fetch resolves missing — the flash is eliminated. Row kept for ID stability. | — |
| P5-T8.95 | Shipped (121 passed) | Account-details page shows wrong identity ("Lori" placeholder) item #20 |
Clicking the avatar dropdown's Account details menu item brought the operator to a profile page rendering "Lori" — a placeholder / Polish-4 simulator staff persona — instead of their actual authenticated identity. Root cause was fixture/sample account details still being passed into the route even though the tenant shell already had identity-worker whoami session data. Shipped fix: account details now derives name/email/role/tenant from the authenticated session, exposes data-jrni-account-identity-source="identity-worker", and renders Not set for identity-worker gaps instead of falling back to fixtures. Live gate added direct-route and avatar-menu regressions proving no "Lori" text inside data-jrni-component="account-details". Operator quote: "I'm brought to what is clearly not my identity or my configuration. It's clearly some placeholder, somebody named Lori that's fucked up."
|
— |
| P5-T8.98 | Shipped | Event drawer Guests tab — count mismatch + inert arrows + inert Export item #25 |
Three sub-issues on the event drawer Guests tab from operator's "Vendor breakfast - 2026-05-28" screenshot:
|
— |
| P5-T9 | Shipped (127 passed) | Salesforce integration credential decryption fix item #13 | Root cause class (e) — worker D1 binding drift, NOT a crypto bug.
|
127 |
| P5-T10+ | TBD | Additional items surfaced by T33 audit + ongoing operator review | The T33 audit and ongoing operator surface walk-throughs will continue to add polish items. Slot them in here in priority order. | — |
Operator priority: convert /dashboard, /hubs, /events/templates, /landing-pages from SAMPLE_* to real D1-backed data. All four shipped. Each turn added a server-side aggregate endpoint (bounded/paginated, gateway-routed, source:"d1"), wired the shell to it, removed the SAMPLE_* path, and proved it with a red→green spec + the serial cumulative gate. Closing audit: rg "SAMPLE_" packages/events-studio-shell/src → zero matches in the live path (fixture mode stays intentionally sample-backed).
| Turn | Status | Title | Scope | Gate |
|---|---|---|---|---|
| P6-T1 | Shipped | /dashboard StatCards → real D1 |
GET /v1/admin/dashboard/summary (gateway-routed) returns server-computed aggregates only — events-today / registered-today / checked-in-today / event-revenue, each source:"d1". Added idx_events_studio_guests_tenant_registered_at to both ops DBs. No client raw-row reduction.
|
144 |
| P6-T2 | Shipped | /hubs → real D1 |
Bounded GET /v1/admin/hubs?page&limit (gateway-routed) with page/limit/total/hasMore + per-hub server aggregates (eventsCount / visits30d / registrations30d). Hubs already a first-class table — no fake rows; visits30d honestly disclosed as a registration-count proxy until a real hub-visit table exists.
|
145 |
| P6-T3 | Shipped | /events/templates → real D1 |
Bounded GET /v1/admin/events/templates?page&limit — templates derived from real event data (normalized event titles), server-computed usage/registration aggregates, derivation disclosed in the payload (no fake template table invented). Added idx_events_studio_events_tenant_active_updated to both ops DBs.
|
146 |
| P6-T4 | Shipped | /landing-pages → real D1 (hardened) |
/landing-pages already consumed the real /v1/landing endpoint (from P5-T24/T25); this turn hardened it — bounded pagination + server aggregates (visits30d / registrations30d / conversionPct), removed the live SAMPLE_LANDING_PAGES fallback, added idx_landing_pages_tenant_updated to both ops DBs. Closing SAMPLE_* audit ran here: zero matches.
|
147 |
Aperture must contain zero custom code — it is only a deployment of Voyage. Done: all aperture-local workers were upstreamed into Voyage and composed into Aperture, then the aperture-local copies deleted. Identity worker (incl. the phone_number SSO-SMS column) lives in Voyage; notifications consolidated on canonical voyage-notifications (D1 binding drift fixed); integrations / events / porivo-ai / preview-proxy / salesforce-mock / _shared all composed from Voyage.
| Turn | Status | Title | Scope | Gate |
|---|---|---|---|---|
| P5-T11→T25 | Shipped | Upstream + compose all aperture workers; delete aperture-local copies | Identity worker upstreamed (src + migrations incl. phone_number), composed, aperture copy deleted, SSO/login green. Remaining workers (notifications / integrations / events / porivo-ai / preview-proxy / salesforce-mock / _shared) reconciled to Voyage canonical + composed. Zero aperture-custom code remains. |
✅ |
PM validation of /events/new (thread: porivo #voyage-product). Resolved arc: J2/J3 validated; publish→landing (P7-T4); landing/Hubs CRUD (P7-T5); wizard polish (P7-T6/T7); re-val #2 — register submit blocker fixed with a real fill→submit→confirm test (P7-T8), landing polish (P7-T9), event-creation wizard (P7-T10), and #10 email+SMS confirmations launched + verified delivering to a real recipient (P7-T12/T14). Jim confirmed email + SMS received on a live registration (2026-05-29). All 10 actionable items done. Re-val #3 also DONE (P7-T15): #44 (step-3 Dates selectable time list, start + end) and #45 (registration email/phone format validation + international phone country selector → E.164) shipped + deployed. Operator UX #47 (P7-T17) DONE: integration cards now render as distinct staggered index cards. Operator QA #48 (P7-T18, in flight): Google Calendar status pill reads "Disconnected" despite a complete setup — reconciling. Full lists: QA findings.
| # | Status | Item |
|---|---|---|
| J1 | Shipped | New-event-from-scratch path (no forced template); + Event → blank wizard or dropdown new-from-template. |
| J2 | ✅ Validated | Hero image upload/import. Jim refinement #33 (P7-T6): show the uploaded image in the console + preview with a clear "received/accepted" confirmation on import (currently only renders in preview). |
| J3 | ✅ Validated | Dynamic, editable tags derived from page selections — confirmed by Jim. |
| J4 | Shipped | Dedupe registration open/close date+time — removed from Dates screen, kept on Registration. |
| J5 | Shipped | Seeded default registration questions (First/Last/Email/Phone, formatted + validated) + custom questions. |
| J6 | ✅ Ready | Branding controls work + published landing renders (P7-T4). |
| J7 | ✅ ALL #1–#10 done + Jim-validated | All 10 items shipped, walked live by Claude, confirmed by Jim.
|
| J7b | ✅ Fixed (P7-T4) | Publish→public-landing now renders (finding #27). Root cause: public endpoint only matched landing_pages.slug, but public URLs use the event id. Fixed to resolve (slug OR event_id); verified live — operator's event returns JSON 200 with published content; real wizard-publish→public-page e2e spec added. Gate 149. |
Live QA by the operator. #27 is the prioritized next turn (P7-T4).
| # | Status | Finding |
|---|---|---|
| #27 | ✅ Fixed (P7-T4, gate 149) | Publish→public-landing now renders. Public endpoint resolved only by landing_pages.slug; public URLs use the event id → fell through to the not-live fallback. Fixed to resolve (slug OR event_id); verified live (operator's event → API 200 w/ published content); real wizard-publish→public e2e spec added. |
| #32 | ✅ Fixed (P7-T5, gate 151) | landing-pages + Hubs admin CRUD now works. Added LandingPageEditor route + hub metadata columns/DELETE endpoint; wired create/edit/delete/publish to real D1 on both. Verified live: created+edited a landing page and a hub, both persisted through reload + API. Migration in both ops DBs. |
| #33 | ✅ Fixed (P7-T6) | J2 hero-image upload feedback. Imported/uploaded hero images now show the accepted feedback state + preview image in the admin basics console. |
| #28 | ✅ Fixed (P7-T6) | Event date defaults + validation. New scratch events default to local today+14d, 12:00→13:00; past dates blocked; invalid schedules show inline validation; Continue disabled until valid. |
| #29 | ✅ Fixed (P7-T6) | "Welcome copy" placeholder. Brand-kit voice guidance is now a placeholder only — no longer populates/submits as welcome copy; empty stays empty in preview + payload. |
| #31 | ✅ Fixed (P7-T7, gate 155) | Staff avatars render. Placeholder photoUrls didn't resolve; shared Avatar primitive now swaps failed images → initials fallback (onError). Live: 25 broken → 0. |
| #30 | ✅ Fixed (P7-T11, gate 160) | Simulator controls consolidated + gated behind platform-admin RBAC. First-class users.platform_role claim (migration 0008), server-side requirePlatformAdmin() (non-admin → 401/403 + redirect), one admin-only simulator nav. Live: admin sees one entry + 200; non-admin no chrome + 401/403. |
| # | Status | Finding |
|---|---|---|
| #34/#35 | ✅ Fixed (P7-T8, gate 156) | Public registration now submits. #34: loading state wasn't passed through → "unavailable" rendered during load (fixed). #35: phone validation rejected normal `(415) 555-0199` → Continue silently disabled (now accepts + normalizes US formats, visible errors). Real fill→submit→confirm e2e + live proof: 201, guest created, phone `+14155550199`. |
| #36 | ✅ Fixed (P7-T9, gate 157) | Hero image dedupe. Public hero used the event image as a CSS background (un-assertable, duplicated under added blocks); now renders exactly one <img> with the gradient as a separate layer. Live: heroDataImages 0→1, heroBackgroundUrlCount 1→0. |
| #37 | ✅ Fixed (P7-T9, gate 157) | Single register CTA. Renderer hardcoded a hero CTA + a sidebar reserve-card CTA. Hero CTA is now the single default; sidebar CTA is opt-in via showSidebarRegisterCta (default off), toggle in the landing editor, persisted by the tenant worker. Live: registerButtons 2→1. |
| #38 | ✅ Fixed (P7-T9, gate 157) | Share-link removable. Share card was unconditional; now gated by showShareCard (default off) with a landing-editor toggle. Live: shareSections 1→0; opt-in proof re-enables it. |
| #39 | ✅ Fixed (P7-T10, gate 158) | Blank / start-from-scratch path is now first-class — "Start from scratch" in the type picker yields an empty draft (no theme seed) via a shared blank-draft builder. |
| #40 | ✅ Fixed (P7-T10, gate 158) | Template seeds are theme-coherent — draft seeds keyed off the selected template's own name/category/description; cross-theme markers avoided; unit coverage in create-event-drafts.test.ts. |
| #41 | ✅ Fixed (P7-T10, gate 158) | Ticket-optional / registration-only mode. Step-4 registration-only mode hides ticket tiers, carries through the draft, summarizes "Registration-only — no ticket tiers" on publish; worker accepts blank optional fields (live 201). |
| #42 | ✅ Fixed (P7-T10, gate 158) | No silent date default. Design source treats dates as explicit scheduling fields; scratch dates now start empty and block progression until a valid start/end pair is entered (no hidden today+14d commit). |
| #43 | ✅ Launched + verified (P7-T12/T14) | Jim #10 — email + SMS confirmations launched, both verified to a real recipient. SMS: wired the missing Twilio secrets onto voyage-aperture-notifications (was sandbox no-op) → real Twilio, Twilio API status=delivered to a real phone (lands in spam on first contact — known; enterprise sender deferred). Email: Cloudflare send_email from [email protected] → operator confirmed inbox receipt; a live probe to an arbitrary external address was accepted (NOT verified-destinations-only). Sent from the Voyage backend, no special-casing. |
Jim re-walk (Claude, 2026-05-29): personally drove all 10 items end-to-end on live before any re-engagement. 9 of 10 verified to terminal success — incl. a green live spec that creates a registration-only event and submits a public registration through to "Registration confirmed" + guest read-back (the dead-Continue blocker does NOT recur for registration-only events). #10 (above) launched + verified. The readiness gate did its job — caught the cosmetic-vs-real-dispatch gap before any false "ready" ping.
| # | Status | Finding |
|---|---|---|
| #44 | ✅ Fixed (P7-T15, gate 164) | Step-3 Dates — selectable time list restored. Replaced the native <input type="time"> hand-type spinner with a selectable time-list combobox (15-min increments, 96 options) for both start and end. Spec asserts the datalist + selectable values; Continue stays enabled. |
| #45 | ✅ Fixed (P7-T15, gate 164) | Registration validation + international phone. Email + phone now have real inline format validation that blocks submit on bad input; phone input has a country selector (flag + dial code, incl. GB) normalizing to E.164. Spec asserts inline [data-jrni-reg-field-error] + Continue disabled on invalid, normalized on valid. |
| #46 | ✅ Fixed (P7-T16, gate 165) | Integration setup panels — width capped.
|
| #47 | ✅ Reverted (P7-T22) | Staggered index cards — REVERTED per operator. P7-T17 added an even-row 20% inset stagger; operator rejected it ("only changed Gmail, that's bogus"). P7-T22 removes the stagger (keeps the #46 640px cap + card chrome) and replaces the direction with collapsible completed cards (#52). |
| #48 | ✅ Fixed (P7-T18 + P7-T19) | Google Calendar status pill read "Disconnected" despite a complete setup.
|
| #50 | ✅ Fixed + live-verified (P7-T20) | Setup walkthrough + OAuth config disappear once connected. Fixed: ConnectedProviderManage now renders the walkthrough for any setup-backed provider (not just stripe/zoom), keeps the "Provide OAuth Client credentials" step editable (Unlock stored credential → Update credentials, no disconnect needed), and suppresses the misleading empty "Configuration" card. Component test + my own live Playwright check on the deployed host both green. Deploy Pages 634fb7dd. |
| #51 | ✅ Fixed + live-verified (P7-T21) | Calendar entry click full-refreshed the screen. Root cause: a route split (`/events` vs `/events/:eventId/:eventTab?`) remounted the calendar on selection. Fixed by collapsing to one optional route /events/:eventId?/:eventTab? — selection updates params in place, drawer opens, URL deep-links, no remount. Spec proves the calendar DOM node persists (not a remount); gate 172/172. Claude re-ran it live. Deploy e64190b1. |
| #52 | ✅ Fixed + live-verified (P7-T22) | Completed cards collapse (roll-up); stagger dropped. Reverted the #47 stagger (cards align; 640px cap + chrome kept). Completed setup-step cards now collapse to a header disclosure by default (aria-expanded/aria-controls + chevron + pointer cursor); click the header to expand/re-collapse; non-complete steps stay open; a just-locally-completed step stays open so the success isn't hidden. Component tests + Claude's live Playwright check (collapsed→click→expand→re-collapse) both green. Deploy 9e7f04c0. |
| #49 | Awaiting operator | Gmail test send "succeeded" but not received. NOT a stub — hits the real Gmail API (no Google mock; GOOGLE_GMAIL_API_BASE_URL unset), returns a real message id. Most likely a self-send: messages.send sends from the connected account; a self-addressed message files under Sent/All Mail, not Inbox (subject "Aperture setup verify"). Awaiting operator confirmation (search All Mail) before any code change. |
Simulator realism: P7-T1 fixed the time window, P7-T2 made the cron cadence grow the dashboards organically, P7-T3 shipped interactive operator controls. P7-T4 (priority) pivots to the operator's 2026-05-29 QA: fix the broken publish→public-landing round-trip (#27). Then event-wizard date/validation + welcome-copy (#28/#29), staff avatars (#31), and the platform-admin RBAC gate for the simulator (#30) + chaos-engine gate + real visit tables. See Operator QA 2026-05-29.
| Turn | Status | Title | Scope | Gate |
|---|---|---|---|---|
| P7-T1 | Shipped | Current-window traffic realism (finding #6) |
|
147 |
| P7-T2 | Shipped | Registration-curve realism + ongoing daily cadence |
Fixed registrationsSkippedNoCurveDue — current-window events (incl. backfill/auto-created) now get a registration curve so each cron tick registers against them. Bounded organic per-tick booking cadence so the today/30-day aggregates grow tick-over-tick instead of freezing at the P7-T1 backfill snapshot. Worker tests cover curve coverage + tick-over-tick growth.
|
147 |
| P7-T3 | Shipped | Operator simulator controls |
Interactive /admin/simulator?panel=controls: persisted pause/resume, bounded rate multiplier (0.25–3), six per-engine on/off flags. GET/PATCH state endpoints with bounded validation; dispatcher reads persisted state every tick. Live toggle-off proof: all engines off → tick produced 0 registrations + 0 chaos events; reset restored. Migration applied to both ops DBs. (Shipped UNGATED — gating to platform admins is finding #30, queued.)
|
148 |
| P7-T4 | Shipped | Fix publish→public-landing round-trip (#27) |
Root cause: public endpoint resolved only by landing_pages.slug, but public URLs use the event id → scheduled-event not-live fallback → blank. Fixed to resolve (slug OR event_id) with slug precedence; shell "View landing" routes to /public/events/<id>. Real wizard-publish→public-page e2e spec added. Verified live: operator's event → API 200 w/ published content + public page renders. Gate 149.
|
149 |
| P7-T5 | Shipped | landing-pages + Hubs admin CRUD (#32 — cleared Jim J7) | Added LandingPageEditor route + hub metadata columns + DELETE endpoint; wired create/edit/delete/publish to real D1 on both surfaces; fixed picker navigation + hub save stale-state. Live proof: created+edited a landing page and a hub, both persisted through reload + API. Migration in both ops DBs. Gate 151. | 151 |
| P7-T6 | Shipped | Event-wizard polish: J2 image feedback (#33) · date defaults/validation (#28) · welcome-copy placeholder (#29) | Dates default today+14d / 12:00→13:00 local, past dates blocked, Continue gated on valid schedule. Welcome-copy guidance = placeholder, not value. Hero image shows accepted state + preview. Also root-caused a create→editor race (async create handlers were void-wrapped) + stabilized two pre-existing flaky specs. Gate 154. |
154 |
| P7-T7 | Shipped | Staff UI avatars render (#31) | Placeholder photoUrls didn't resolve; shared Avatar primitive now swaps failed images → initials fallback (onError) + stable selectors. Live: 25 broken → 0. Gate 155. |
155 |
| P7-T8 | Shipped | Fix public registration submit blocker (#34/#35, Jim re-val #2) | Root causes: loading-state not passed through (→ "unavailable" flash) + phone validation rejecting normal formats (→ Continue disabled). Now accepts/normalizes US phone, visible errors, real loading state. Real fill→submit→confirm e2e (clicks Register, normal phone, asserts 201 + confirmation + reads guest back). Live proof: 201, guest created, phone normalized. Gate 156. | 156 |
| P7-T9 | Shipped | Landing-page polish (#36/#37/#38) | One real hero <img> (was a CSS bg that duplicated); single default Register CTA with opt-in sidebar CTA; share card opt-in (default off) with editor toggle; tenant worker persists both flags. Live before/after: heroDataImages 0→1, registerButtons 2→1, shareSections 1→0. Gate 157. |
157 |
| P7-T10 | Shipped | Event-creation polish (#39/#40/#41/#42) | First-class blank/start-from-scratch path (#1); theme-coherent template seeds (#2); registration-only mode hides ticket tiers + worker accepts blank optional fields, live 201 (#9); explicit scratch dates, no silent default (#8, design-checked); publish→landing unavailable-flash verified gone (#3). Direct-API 201 proof + focused live spec 1/1. Gate 158. | 158 |
| P7-T11 | Shipped | Platform-admin RBAC primitive + consolidate/gate simulator controls (#30) | First-class users.platform_role claim (migration 0008) surfaced via whoami + edge; server-side requirePlatformAdmin() (non-admin → 401/403 on simulator endpoints + redirect, service actors allowed); one consolidated admin-only simulator nav. Red-on-main proven; focused live 2/2. Also stabilized brittle networkidle waits in old P5/P6/P7 gate specs. Gate 160. |
160 |
| P7-T12 | Shipped | Public registration → confirmation email/SMS (#43 / Jim #10) | Public register path now enqueues a real confirmation (email always; SMS when phone present) via the existing event.registration.confirmed → NOTIFICATIONS_OUTBOX_QUEUE mechanism; idempotent; UI "sent" copy gated on actual enqueue. Live-proven: real D1 outbox rows email sent + SMS sent. Clean single gate, no reruns. Closes the last Jim item. Gate 161. |
161 |
| P7-T13 | Shipped | Events-worker unit-suite audit + chaos-engine gate groundwork | Broad @voyage/events-worker test RED→GREEN: 4 failed files/33 tests → 56 files/542 tests, zero quarantines (all stale-date fixtures fixed). One deterministic chaos engine (overbooking-waitlist) gated + double-booking-conflict worker coverage. Anti-churn rule held: 1 isolated flake → 1 focused rerun → proceeded. Gate 162. |
162 |
| P7-T14 | Shipped | Email/SMS notification launch — delivery verification + hardening | Email + SMS launched + verified to a real recipient. SMS real Twilio (delivered); email Cloudflare send_email (probe confirmed it accepts arbitrary recipients — not verified-only; operator confirmed inbox receipt). Delivery-verification spec asserts real providers (not sandbox); Twilio/retry/DLQ failure hardening. (Resend scaffold added here is being reverted in P7-T15 — Cloudflare-only per operator.) Gate 162. |
162 |
| P7-T15 | Shipped | Jim re-val #3: Dates time-list picker (#44) + registration validation/intl phone (#45) + revert Resend | #44 step-3 Dates: replaced native type=time with a selectable time-list combobox (96 options, start + end). #45 registration: email/phone inline format validation (blocks submit) + an international phone country selector (flag + dial code → E.164). Reverted the unwanted Resend scaffold (Cloudflare-only per operator). Gate 164. |
164 |
| P7-T16 | Shipped | #46 integration-card max-width cap + payment-declined-rollback chaos engine |
Capped integration setup/provider panels at 640px (field-map 820px, no wrap); live before/after GSuite 1220→640, SF guest-sync 824→640; data-jrni-component="integration-provider-card" marker. Gated the payment-declined-rollback chaos engine (P7-T13 pattern). Gate 165; 2 old polish5 nav flakes → focused rerun 5/5 (anti-churn). |
165 |
| P7-T17 | Shipped | #47 integration cards as staggered index cards + 2 chaos engines | Distinct card chrome (design tokens) + 16px gaps + staggered even-row 20.0% inset via margin-left: max(0px, min(20%, calc(100% - 640px))) (responsive collapse, 640px cap held). Gated staff-sick-cascade-cancel + bulk-cancel-24h — chaos backlog closed. Gate 171 (1 unrelated landing-CRUD flake → focused rerun 1/1, anti-churn). Deploy worker c0037eb1 / Pages d7843285. |
171 |
| P7-T18 | Shipped | #48 Google Calendar status-pill reconciliation | Reconciled the google_calendar catalog status (connection + verification lookups) to the gsuite ('gsuite','custom') keys. Test-first, demonstrated the half-fix trap. Worker suite 384 tests; gate 170/171 (unrelated P6-T4 aggregate flake → focused rerun 1/1). Deploy dce566cd. Live check: connection now recognized → pill is "Needs attention" (no ok=1 verification recorded yet) → P7-T19 takes it to "Connected". |
171 |
| P7-T19 | Shipped | #48 follow-through: gsuite verify-step → "Connected" | Successful gsuite verify-step now records a passing integration_connection_verifications ok=1 row + the google_calendar Run-verification handler reads the reconciled keyspace. Worker suite 387 tests; gate 169/171 (2 old flakes → focused rerun 2/2). Deploy 34d78ace. Live-verified: latest verification ok=1 + active connection → pill derives "Connected". |
171 |
| P7-T20 | Shipped | #50 keep walkthrough + OAuth config reachable/updatable once connected | Walkthrough now renders in the connected view for any setup-backed provider; "Provide OAuth Client credentials" step editable (Unlock→Update, no disconnect); misleading empty-config card suppressed. Also root-caused + fixed an old P5-T4 drawer-remount (route collapse to /events/:eventId/:eventTab?). Component test + Claude's live Playwright check both green. Deploy 634fb7dd. |
171 |
| P7-T21 | Shipped | #51 calendar entry click → reactive update (no full-refresh) | Collapsed the events route split to one optional route /events/:eventId?/:eventTab? so calendar entry selection updates params in place (no remount). Spec proves the calendar DOM node persists; gate 172/172 no reruns; Claude re-ran live. Deploy e64190b1. |
172 |
| P7-T22 | Shipped | #52 revert stagger + collapsible completed setup-step cards | Stagger removed (aligned cards, 640px cap kept); completed setup-step cards collapse to a header disclosure (aria-expanded/chevron), click to expand. Component tests + Claude live check green; gate 173. Deploy 9e7f04c0. Closes the events-studio polish cluster (#46–#52). |
173 |
| P8-T1 | ✅ Shipped + live-verified | De-fraud #1: user/team management → real identity tenant_memberships | Identity-worker admin member API (GET/POST/PATCH/DELETE, admin-gated via permission catalog, bounded) + useTeamMembers hook + live host wiring; SAMPLE_TEAM_MEMBERS removed. Found+fixed a real prod-D1 role-constraint mismatch (migration 0010) + CORS + 2 flaky tests. Claude re-ran the live acceptance spec (invite→role→remove via UI+API, 1/1) + confirmed 12 real members in D1. Gate 173/174 (1 race → focused rerun). Deploys identity 081439bb + Pages 044d3fa7. = SSO Phase 1. |
173 |
| P8-T2 | ✅ Shipped (feature verified) | De-fraud #2 (small): reports "Today" drilldown → real D1 | New GET /v1/admin/reports/drilldowns/today (bounded D1 today check-ins/registrations) + useReportsTodayDrilldown hook; /reports Today cards consume real totals (data-report-source="events-api"); SAMPLE_DRILLDOWNS_TODAY removed. Claude verified the endpoint directly (HTTP 200, real D1, 0.5s, no rate-limit). Deploy worker d0affa63 + Pages cfc5faf6. (Surfaced a gate-health issue → P8-T3.) |
~real |
| P8-T3 | ✅ Shipped + Claude-verified | Gate stabilization — restore a deterministic, trustworthy per-turn live gate | Defined a canonical deterministic core gate — scripts/events-studio-live-gate.sh, 7 specs / 69 tests (shell-smoke + polish6 real-D1 ×4 + polish8 team-management + polish8 reports-today-drilldown). Fixed the flaky waitForResponse races (reports spec now reads the endpoint directly + asserts rendered markers), relocated volatile simulator/seed-dependent specs to a separate suite (events-studio-volatile-live-gate.sh — coverage preserved, not deleted). No product code touched. Codex proved 69/69 ×2 + post-merge; Claude independently re-ran 69/69 on events-in-studio (a 64/69 first run was Claude's own stale admin.-host override, not a gate flake — corrected). Voyage a44d7183 + aperture e5ecbb4f. |
69/69 |
| P8-T4 | ✅ Shipped + Claude-verified | De-fraud #3: command-center KPIs + check-in pace + activity feed → real D1 | New GET /v1/admin/dashboard/command-center (source:"d1") + useCommandCenterData hook → real kpiMetrics (registered 50 / checked-in 13 / waitlist 1), 60-min checkInPace, bounded activity; SAMPLE_KPI_METRICS/SAMPLE_CHECK_IN_PACE/SAMPLE_ACTIVITY removed from the live path. polish8-command-center-real spec asserts real markers + API-value matches + sample-absence. Claude independently probed the endpoint (real D1) + re-ran the gate (command-center green; lone 69/70 fail = unrelated templates-smoke flake, passed focused rerun 829ms). Codex caught+fixed a real marker bug (ActivityFeed markers normalized to card → owned wrapper). Worker fae75258 + Deploy run 26672537073 success; live at /dashboard/command. Voyage d9dcc7b5 + aperture c0a5a3a9. |
70/70 |
| P8-T5 | ✅ Shipped + Claude-verified | De-fraud #4: campaigns + notification templates → real D1 (record CRUD, no mass-send) | Real D1-backed /v1/admin/campaigns + /v1/admin/notification-templates (8 record-only endpoints, source:"d1", safety:{dispatchEnabled:false}, migration + indexed tables + seed) + useCampaignsData/useNotificationTemplatesData hooks through /comms + /comms/templates; SAMPLE_CAMPAIGNS/SAMPLE_NOTIFICATION_TEMPLATES removed from live path. Codex caught the live-404 = edge-gateway route table missing the new paths → fixed + deployed BOTH workers (events fcdddb01 + gateway 312f685d). Claude probed both endpoints (real records + dispatchEnabled:false + pagination) + gate green (lone 70/71 = unrelated public-hub-smoke flake, focused rerun 344ms). Deploy run 26673490354 success. Voyage 24dcc5f1 + aperture aa5f9ddb. |
71/71 |
| P8-T6 | ✅ Shipped + Claude-verified | De-fraud #5: segments + invite templates + send-invite records → real D1 (record CRUD, no dispatch) | Real D1 /v1/admin/segments + /v1/admin/invite-templates + /v1/admin/invites (10 endpoints, 3-table migration + indexes); SAMPLE_SEGMENTS/SAMPLE_INVITE_TEMPLATES + fake @segments.local removed. Segment audience computed server-side from events_studio_guests — Claude probed live: 6 / 1 / 13 / 37 (real; checked-in 13 = P8-T4 KPI, internally consistent). dispatchEnabled:false, route scan confirms no dispatch binding. Edge-gateway routes added proactively + both workers deployed (events 5c3a81d6 + gateway a3b6fa5f). Claude probed both endpoints + gate green (lone 71/72 = unrelated /reports-smoke flake, focused rerun 705ms). Voyage ffaa71da + aperture 1bfbebcb; live at /guests/segments + /guests/invite. |
72/72 |
| P8-T7 | ✅ Shipped + Claude-verified | De-fraud #6: dashboard alerts → real D1-computed (agenda verified already-real) | New GET /v1/admin/dashboard/alerts (source:"d1") computes real alerts from D1 — capacity ≥90% / waitlist / registration follow-up / check-in pace + an "operations clear" fallback; SAMPLE_ALERTS removed from the live path. Claude probed live: 5 real alerts tied to real event ids (alert-capacity-evt-style-consultation, alert-waitlist-evt-spring-sale-launch, …). Agenda confirmed already-real (/v1/admin/calendar/agenda → real event ids), no patch needed. Edge-gateway needed no change (/dashboard/* already routed). Bonus: cleaned a leftover SAMPLE_CHECK_IN_PACE ref. Gate 73/73; events worker 8eab8f55 + Deploy run 26675098174 success; live at /dashboard. Note: the shell-smoke nav tweak (waitUntil:commit) shifted the recurring flake (nav-timeout → faster visibility race) but didn't kill it — proper Playwright retries fix deferred to P8-T8. Voyage 2cb72fb0 + aperture 7c23d9da. |
73/73 |
| P8-T8 | ✅ Shipped + Claude-verified | De-fraud #7: guest-imports history → real D1 + proper shell-smoke retries fix | Real GET /v1/admin/guest-imports (backed by contact_import_batches, 4 real seed batches; SAMPLE_GUEST_IMPORTS removed).
|
74/74 |
| P8-T9 | ✅ Read shipped + Claude-verified | De-fraud #8: workspace settings (locations + branding + account) → real D1 (READ) | Real GET /v1/admin/settings (source:"d1", migration on aperture-ops, edge-gateway route + both workers deployed) → 4 real locations + real branding (#0A6B68) + real account; SAMPLE_LOCATIONS/SAMPLE_BRANDING/SAMPLE_ACCOUNT_DETAILS removed from the live display. Claude probed the endpoint + gate green (74 passed + 1 flaky auto-retried = EXIT 0; the retries fix caught a live-load /guests nav flake within the run — no manual rerun). Write handlers still no-op (onCreateLocation/etc., onSaveBranding) → P8-T10. Voyage a8f8d5a5 + aperture ac642d72; live at /settings/locations, /settings/branding, /account/details. |
75/75 |
| P8-T10 | ✅ Shipped + Claude-verified (live CRUD round-trip) | Settings WRITE: make the inert location/branding buttons interactive (real CRUD) | Added POST/PATCH/DELETE location routes + PATCH branding (tenant-scoped, validated, source:"d1", index on aperture-ops); wired all four handlers (onCreateLocation/onUpdateLocation/onDeleteLocation/onSaveBranding) to real round-trips. Claude drove the live write path personally: POST→201 (real D1 location loc-7d539c22…), GET read-back→present, DELETE→200→gone, cleaned up to baseline. Spec is a true create→read-back→UI-markers→delete→confirm-gone→branding→restore round-trip (PM-validation terminal-success-state bar). Gate 76/76 (75 + 1 flaky auto-retried, EXIT 0). Account stays read-only (no save form). Workers 75fc2883/096f8339 + Pages 26677414164; voyage 10a08bb0 + aperture 29c10d1e. "Complete coverage = interactive" gap CLOSED. |
76/76 |
| P8-T11 | ✅ Shipped + Claude-verified — WAVE CLOSED | De-fraud completeness audit + finish any remaining live-path SAMPLE_ | Classified all ~37 SAMPLE_* consts with evidence (REAL / fixture-only / higher-ed-only / FRAUD) and finished the long tail.
|
82/82 |
| P8-T12 | ✅ Shipped + Claude-verified | Docs audit (Phase 1): audit /help, author credible core docs, capture screenshots | Audited /help (11-entry gap table) and authored credible docs.
|
84/84 |
| P8-T13 | ✅ Shipped + Claude-verified | Help-docs i18n foundation + supported-language recommendation | The app was English-only (no i18n framework). Built the foundation:
|
86/86 |
| P8-T14 | ✅ Shipped + Claude-verified (live re-run) | Full-lifecycle cross-surface capstone e2e (system-level verification) | The system-level check the per-turn gate doesn't do — a true end-to-end lifecycle proving the de-frauded surfaces work together with real live D1 data.
|
87/87 |
| P8-T15 | ✅ Shipped + Claude-verified | Canonical-gate flake stabilization (deterministic green, no rerun crutch) | Pre-merge gate #2 exposed two recurring NON-product flakes that force a focused rerun: (1) polish8-segments-real asserts exact equality between an API count and a re-fetched page count, which races the live traffic simulator (3701→3703); (2) polish8-help-docs-real hit a nav ERR_ABORTED. Both are test-robustness issues. Harden them to deterministic green (segments: tolerate the simulator's monotonic drift while still proving the count is real/server-computed/non-fixture; help-docs: robust nav) WITHOUT weakening the de-fraud guarantee or adding retries to retries:0 specs. Prove each fix by running it 3–5× consecutively + the gate twice-green pre-merge with NO focused rerun. Test-only; same class as P8-T3/P8-T8. |
87 |
| P8-T16 | ✅ Shipped + Claude-verified (live) | Help-docs translation (i18n Phase 2) |
Populate real translations on top of the P8-T13 English baseline so the /help switcher renders localized content (honest English fallback stays for anything untranslated).
|
+1 |
| P8-T17 | ✅ Shipped + Claude-verified (live) | Campaign + invite mass-send (real dispatch) |
Wire the campaigns/invites “Send” buttons to real dispatch through the proven notifications worker (voyage-aperture-notifications — Twilio + Cloudflare email, P7-T14).
|
+1 |
| P8-T18 | ✅ Shipped + Claude-verified (live) | Inbox inbound ingestion (guest reply → thread) |
The inbox is send + actions today (P8-T4); this makes it two-way — a guest email/SMS reply lands on the matching inbox thread instead of vanishing.
|
+1 |
| P8-T19 | ✅ Shipped + Claude-verified (live) | Billing real backend (honest: real D1/activity-backed, no fabricated charges) |
Turn the “empty-not-fake” billing surface into a real module backed by D1 + actual tenant activity.
|
+1 |
| P8-T20 | ✅ Shipped + Claude-verified (live) | Inbound EMAIL worker bridge (complete the P8-T18 email path) |
CF Email Routing can't POST to an HTTP endpoint — it needs a Cloudflare Email Worker. This builds the missing bridge.
|
+1 |
| P8-T21 | In flight | Security real backend (honest: real data, no fabricated controls) |
Turn the “empty-not-fake” security surface into real platform/D1-backed data.
|
+1 |
| Inbound wiring | ✅ SMS live · email bridge built (1 operator CF step) | P8-T18 inbound: provider→inbox delivery needs dashboard wiring |
The inbound endpoints are deployed + verified; real provider delivery needs two credential-gated dashboard steps (Codex's tokens 403'd / Twilio creds are write-only secrets):
|
— |
| Inbox (checked) | ✅ Already real | Message inbox — operator's 3rd named area | Checked during P8-T4 review: the inbox is NOT fraudulent — useInboxMessages is D1-backed for the default tenant (/v1/admin/inbox list + detail; real actions mark-read/unread, archive/unarchive, flag, reply; pagination + search + status filter). Only remaining gap = inbound ingestion (guest email/SMS reply → new thread) which needs provider webhooks (Cloudflare Email Routing + Twilio inbound) + likely operator config; deferred to a deliberate later turn, not an unattended overnight one. |
real |
| Polish-8 wave | ✅ De-fraud wave COMPLETE — 15 turns, all Claude-verified live | De-fraud / real-data wave — Opus-audited backlog (operator overnight directive 2026-05-29) |
Done — all 14 turns live-verified:
SSO/IAM + the tenant-management UI belong to the Voyage Fleet Management sibling app — not this wave. |
87 |
| P7-T21+ | Queued | Real visit tables; enterprise SMS sender (10DLC); #49 if a fix emerges | Replace visits30d proxies with real hub-visit/landing-view tables; 10DLC brand/campaign for clean SMS inbox placement (deferred per operator); #49 Gmail cross-account delivery — under investigation, becomes a turn only if a code fix is identified. |
+N |
Issue #22 listed 44 pixel-replica routes; Polish-3 addressed 6 (events, guests, calendar, reports, inbox, booking responses) and Polish-6 added 4 more (/dashboard, /hubs, /events/templates, /landing-pages) — 10 of 44, ~23% now real-D1-backed. The remaining ~34 routes (below) are candidate Polish-8+ waves.
| Area | Status | Scope |
|---|---|---|
| Event detail 7-tab shell | Not started | Details / Landing page / Related services / Pricing / Guest management / Event notifications / Message guests. Largest single block of unbuilt functionality. |
| Dashboard home | Not started | Awaiting Figma per Issue #22. Blocked on full sidenav drop. |
| Notifications stack | Not started | Notifications worker exists with liquidjs templating but UI not wired. Email composer + SMS composer + notifications list page. |
| Segments / Campaigns | Not started | Pixel replicas, no backend. |
| /your-business | Not started | 6 screens: locations, staff, resources, business-details. Pixel replicas. |
| /account + /settings/* | Not started | 6 screens: account, billing, branding, general, security, team. Stub labels or pixel replicas. |
| Bulk importer | Not started | Events + customers bulk import flows. Pixel replicas. |
| Customize / Templates / Canvas | Not started | 3 screens at the Claude Skill boundary. Pixel replicas. |