# Changelog

All notable changes are documented here. Individual session changelogs live in `docs/changelogs/`.

> Format: **version [semver]** — date. Categories: New Features · Bug Fixes · Performance · Security · Infrastructure.


---


## [1.0.0-beta.1] — 2026-06-01

_1047 sessions across 35 days_


### New Features

- **Transparent Build Studio + citation-grounded research**
  Two transparency upgrades to the pitch workflow, per direct user request.

- **Shot List: Auto-Storyboard generation + Unsplash reference autofill**
  Two shot-list features plus the backend that powers them:

- **Shot List system template in the Sheets engine**
  A schema-driven **Shot List** system template for the Sheets/Univer document workspace — the sibling of the Call Sheet and Run of Show templates. It renders every shot in a project as a dynamic range with live data binding, status-based row coloring, a reference + storyboard colu…

- **Swap the main image: reference photo ⇄ storyboard**
  A per-shot toggle to choose which image is the large "main" one — the reference photo or the generated storyboard frame — and swap them. New shot_list.primary_media column (reference | storyboard, default reference). A "Make storyboard main" / "Make photo main" swap button appear…

- **Curated role presets · universal pinned widgets · two widget paths · re-run wizards · org setup wizard**
  Second pass on role-based personalization. Adds a **Creative Director** preset and re-curates **Director / Executive Producer / Production Manager (UPM) / Production Assistant** with explicit hidden-nav lists so each role's header is tailored, not exhaustive. Introduces **two uni…

- **Realtime header credit balance (app-wide)**
  The header credit pill (#header-credits-balance + tooltip + mobile profile credits) was rendered **once at page load** with no realtime subscription, so a credit deduction only became visible after a manual reload — and because two header code paths exist (populateHeaderUser in h…

- **QuickBooks Online Integration + Unified ACH Abstraction**
  Full QuickBooks Online integration for organizations, plus a unified ACH abstraction layer that lets both QB and Stripe operate as first-class payment processors from the same "Pay ACH" flow.

- **Restructure the Pre-Production Book from the uploaded brand-kit reference**
  A brand kit's extracted design_system.structure (the ordered section sequence read from an uploaded pre-pro book) now drives the **Pre-Production Book structure** for that production company / org: - BrandKitExtract.packSectionsFromDesign(ds) maps the reference's sections → an or…

- **PPB Import System — Canva / Drive / Dropbox + AI Section Routing**
  Three-part change: (1) Canva Connect card added to the org integrations page so all org members can connect/disconnect their personal Canva from one place; (2) two new PPB section types added to the media pool; (3) a new ppb-import.js engine that enhances any MediaPool instance w…

- **Positional shot insert with atomic cascade re-letter**
  Two follow-ups to the create_shot duplicate fix:

- **Pitches: dashboard tab, AI brainstorm, treatment builder, mood board, voice**
  Adds a **Pitches** phase to CrewDeck — the pre-project stage where a user first engages with an idea, before any project / budget / breakdown / bid exists. A new "Pitches" tab on the dashboard lists pitches and creates them via a 3-question flow. Each pitch opens a workspace (pit…

- **Location deck as part of a pitch + condensed pitch status card**
  Integrated the location deck builder into the pitch system end to end:

- **Pitch deliverable plan (scope → approve → run) + research-during-brainstorm**
  The creative Pitches brainstorm now **ends in finished deliverables** through an explicit plan-and-approve flow that mirrors the existing ai_orchestrations plan→approve→run pattern (without the sheet-specific engine). After brainstorming (text or voice), the user clicks **Plan & …

- **Pitch credits pill — balance + credits used on this pitch**
  The pitch header now shows a credits pill: the billing workspace's **credit balance** (org pool if an org workspace is active, else personal) plus **"used here"** — the credits this pitch has consumed. CrewAI.call now fires a window.cdOnCreditsDeducted(n, taskType) hook (alongsid…

- **Personal-workspace access gating on every project page**
  Two rules enforced consistently across project pages:

- **Org-funded ACH — bank connection + destination-charge model**
  Replaced the platform-float transfer model (which required CrewDeck to hold money in its Stripe balance — it doesn't; live balance was −$0.44) with an **org-funded destination-charge model**. The organization connects its own bank account via Stripe Financial Connections, and ven…

- **Voice onboarding now uses gemini-live realtime (same as the header live mode)**
  Replaced the Web Speech voice onboarding with the **real gemini-live realtime voice** — the same WebSocket voice the header's live mode uses. The voice page opens gemini-live with a new sessionType=onboarding, streams mic PCM16 @16kHz and plays the AI's audio @24kHz, and on "Done…

- **Onboarding: skip org-setup steps for solo/free plan users**
  Beta onboarding seeds an organization for every new user. This caused solo/free plan users to land on "What's your production company called?" (Step 3 of 10) because the org membership check set account_type = 'org'. Fixed by overriding account_type to 'personal' when profiles.pl…

- **Re-run setup starts at Hello; prefill + seed AI with saved context**
  "Redo setup wizard" (Settings) now begins at the **Hello** screen so the user re-picks their setup method (voice / chat / form), and every path carries their saved info — prefilled on the form, and seeded into the AI's context on the chat/voice paths so it refines rather than res…

- **Header-nav customization: dashboard invariant, balanced split, drag + AI edit**
  Implements the full header-nav customization request across the form, chat, and voice onboarding paths:

- **onboarding-form.html — Crew Cash welcome-gift intro step**
  New informational step at the end of the Quick Form onboarding wizard (serves both org and personal account types) that reveals the user's Crew Cash as an animated welcome gift. An indigo gift box drops in with a springy overshoot, does an anticipation shake, then the lid flies o…

- **Dashboard pinned far-right + distinct Apps-menu icon**
  Two header-nav refinements requested after testing setup:

- **Mood Board manual photo search, type filter, multi-source locations**
  The pitch Mood Board tab gains a manual photo search and uses its type dropdown as a filter. A search box next to "AI Suggest References" lets the user type a query and pull real photos as approve / reject / swap candidate cards (the same machinery the AI suggest flow uses). The …

- **Mood Board: custom category dropdown that filters, + fetch-more references**
  Follow-up to the mood-board manual search. Three issues the user hit:

- **Mood Board "AI Suggest References" → real approve/reject/swap photos**
  The mood board's "AI Suggest References" used to render search-link chips to unsplash.com. It now sources **real reference photos** the user can approve, reject, or swap. The AI proposes 8 specific references and tags each with the best **source**: unsplash (mood/lighting/color/ …

- **AI Media Pool + song upload/analysis (pitches)**
  Adds an **AI Media Pool** — a persistent, visible pool of media + documents the AI has in context for a creative workspace — and makes **songs** a first-class, deeply-analysed media type. From a pitch, a user opens the **AI Context** drawer, adds a file or URL, and toggles items …

- **Location deck builder: real photos via Giggster listing pages + Google Places**
  The location-deck builder's photo sourcing was dead: it relied on searchFilmingLocations (scraping Giggster/Peerspace **search** pages), and both broke at the source — Giggster's search page is now a JS-rendered SPA whose listings come from an auth-gated API, and Peerspace return…

- **Insert menu: batch storyboards + AI-ranked reference autofill**
  The shot-list editor-header **Insert** menu (File/Edit/View/Insert/Tools) gains two whole-list batch actions:

- **hello.html — Helvetica Light, white outline buttons, cinematic animation**
  Three visual refinements to the first-run Hello screen. The "Hello" text is now Helvetica Neue 300 (Light) — thin, elegant, airy — while keeping the rainbow hue-rotate gradient. The choice buttons are white cards with a light gray outline and dark stroke icons instead of filled c…

- **hello.html — point-cloud fly-through intro  ⚠️ SUPERSEDED / REVERTED**
  Replaced the CSS transform "settle" (never read as smooth) — and then the first Canvas-2D point cloud (too sparse/chunky) — with a **Three.js WebGL** particle fly-through: "Welcome" materializes solid from ~50k fine rainbow particles, holds, then a real perspective camera acceler…

- **hello.html — Animation polish + Hello→Welcome rename**
  Iterative polish to the first-run welcome screen across six rounds in one session. Net result: the rainbow word reads "Welcome", fades in from invisible, breathes in place, then glides up with a long ease-out (no positional jump) while the indigo choice cards fade in timed to the…

- **Duplicate Project — deep clone (structure | full)**
  Built an actual **Duplicate Project** feature (CrewDeck previously had no project duplication — only duplicate-shoot-day). Right-click a project on the dashboard → **Duplicate** → a modal lets you name the copy and choose a scope:

- **Desktop app v1.0.1 — splash screen, rebranded icons, bundle ID fix + Landing page beta gate + status page**
  Two independent deliverables in one session:

- **Deep workflow interview · onboarding-generated default playbook · playbook resolution in the AI assistant**
  Turns the chat/voice onboarding into a genuine **workflow interview** and uses everything learned to (a) design the dashboard widgets and (b) write the user's **default playbook**. The chat wizard now runs an AI-driven, colleague-style conversation (one question at a time, follow…

- **Elevated deck design + automatic image sourcing during build**
  Two upgrades to every AI-generated deck/treatment:

- **Header credits: self-contained refresh, no personal flicker, focus refresh**
  Two reported issues: (1) the credit pill didn't update after a deduction until a reload/page-switch, and (2) on page switch it flickered to the personal balance (~200) before showing the org balance.

- **create_shot auto-assigns the next scene letter (no duplicates)**
  When the AI (footer Shot List AI / agent, or voice) added a shot, create_shot took shot_number **verbatim** from the model. If the model echoed an existing number (e.g. a second "1B" in a scene that already had 1A–1E), it inserted a DUPLICATE — two shots labelled 1B — instead of …

- **Canva Connect Integration — OAuth + Design Import + Brand Kit Sync**
  Full Canva Connect API integration: OAuth 2.0 with PKCE (Canva's required flow), per-user token storage (AES-GCM encrypted), a design/brand-template picker modal, and a brand kit import path. Real Canva API keys are needed from the Canva Developer Portal before the integration is…

- **Brand Kit modal redesign + error toast bug fix**
  The "Add Brand Kit" modal in Personal Workspace settings had a silent bug where interacting with the "Attach to" radio buttons triggered an unhandled ReferenceError — the inline onchange="_pwBkToggleAttach('none')" handler referenced a closure-scoped function not exported to wind…

- **Brand kits from an uploaded reference (PDF / PowerPoint) + folder-scan detection**
  A production company / personal workspace can upload a **pre-pro book / brand book** (PDF, image, or **PowerPoint .pptx**) into a brand kit; the app extracts its **visual design language** — palette, fonts, logo, page aspect ratio, and the ordered **section structure incl. the th…

- **Brand-kit scanning from Google Drive / Dropbox (single file + folder detection) + dedup**
  Extends brand-kit-from-reference to cloud files, reusing the shared js/brand-kit-extract.js engine + the VPS pptx→PDF converter + Gemini vision.

- **Beta NDA ID-verification toggle (skip IDV for test accounts)**
  The live beta-NDA gate (login.html → POST /functions/v1/esign {action:'provision-beta-nda'} → handleProvisionBetaNda) hard-coded requires_id_verification: true / id_verification_required_type: 'id_scan_liveness' on every beta NDA envelope, forcing an ID-scan + liveness step befor…

- **Auto-generate a full breakdown when a treatment is built**
  Building a treatment now automatically produces a **full breakdown in the database** — no project required. After a treatment deck saves, the treatment's prose is run through the existing 14-pass treatment_breakdown_pass AI (character · location · prop · vehicle · wardrobe · set_…

- **Apple iOS-style toggle switches**
  Replaced all toggle switches on the settings, organization, and calendar pages with an Apple iOS-style pill toggle. The previous design used a 36×36px square checkbox with an X/checkmark icon mask. The new design is a 50×28px pill-shaped track with a sliding white circular thumb …

- **App-wide AI transparency — expandable real tool input/output everywhere**
  Carries the pitch Build Studio's "see the actual code/data" transparency to ALL of CrewDeck's AI at the shared chokepoint, so every surface inherits it from one change. The ai-agent SSE stream already emitted reasoning_step (visible thinking), tool_start (real sanitized input arg…

- **AI-generated reference-photo search + editable/paginated picker**
  The reference-photo picker's auto-query was a naive concat of shot fields that produced garbage like "low angle low angle hero lacing training shoes" (duplicated terms, character names, camera jargon, narrative verbs) → zero Unsplash matches.

- **CrewAI.call resolves the client from window._supabaseClient**
  CrewAI.call and CrewAI.classify resolved the Supabase client from window.db then window.supabase. But window.supabase on most pages is the CDN **library** (the createClient factory, no .auth), and 13 pages — including shot-list.html — expose the actual client ONLY as window._supa…

- **ACH vendor payment flow — Stripe Connect**
  The entire ACH payment feature was non-functional: three edge function slugs were called by the frontend and execute-ai-approval but never implemented in stripe-functions/index.ts. Any attempt to pay a vendor via ACH returned "Invalid or missing slug provided." This commit implem…

- **Two-Tier Spotlight Tutorials — 510 pre-built + AI dynamic fallback**
  Reworked the spotlight tutorial system from a small hand-written library into a **two-tier** architecture:

- **Support System + AI Interactive Spotlight Tutorial Engine**
  A complete, industry-standard in-app support system plus the headline feature: an **AI-driven interactive spotlight tutorial engine**. A persistent ? launcher now appears bottom-right on every header-bearing page and opens a slide-in panel with three tabs — **Ask AI**, **Help Cen…

- **SPA Nav HTML/CSS Leak Fix + Shot List Dark Background in Light Mode**
  Three related bugs fixed. (1) Navigating from budget or production-report back to dashboard via SPA left orphaned swipe-viewport HTML from the origin page in the DOM, causing layout bleed. Root cause: dashboard.html and casting.html put #swipe-viewport outside <main>, so the SPA …

- **SPA nav: fix dashboard `#main-container` orphan leak + id-protect JS-injected `<style>` singletons**
  A thorough Chrome-MCP visual test of the shot-list page and SPA navigation between it and every other page surfaced two distinct regressions, both rooted in the SPA body-swap path:

- **SPA nav: clear the stuck "Save failed" autosave pill across pages**
  js/autosave.js appends a body-level position:fixed singleton (#autosave-pill) pinned top-left and REUSES it across the session. Its error state ("Save failed", red) never auto-hides — unlike saved, which fades after 1.5s. Because the floating pill lives OUTSIDE <main>, the SPA ro…

- **Shot List — gallery-swipe status column + unified AI import**
  Two critical bugs from the shot-list page audit.

- **Shot List — Mobile Card List View + Shot Detail Bottom Sheet**
  Adds a second mobile view mode to the shot list page: a scrollable **card list** that sits alongside the existing Tinder-style **swipe gallery**. A mobile-only view switcher (List / Swipe) toggles between them and persists the choice in localStorage (shotListMobileView), defaulti…

- **Schedule: add-all-shots-for-scene + first-open onboarding & discoverability**
  Two feature sets on shooting-schedule.html, both already committed to main in 4300217:

- **Shooting Schedule — pre-production scene/day strips, scene-aware cascade, palette redesign**
  Major UX pass on shooting-schedule.html to support a two-phase workflow: **(1) pre-production** — build a preliminary schedule from day strips and scene strips *before any shots exist*, and **(2) finalization** — drop shots into that structure once the shot list is locked. Previo…

- **Schedule: right-click insert menu + mobile bottom-sheet strip picker + Print/Export designation routing**
  Completes the Schedule UX pass started in the prior session (which shipped add-all-shots-for-scene + first-open onboarding, all verified present). This session adds the remaining three pieces:

- **Routes — mobile "Locate me" button hidden behind search bar**
  On the Routes page mobile view, the floating map toolbar's **"Locate me"** (crosshairs / current-location) button was not visible. The toolbar (#rt-map-toolbar: Measure / Locate me, plus Satellite / Nearby / Sun in Shot Locations mode) is anchored to the **top-right** of the map …

- **Routes — blue-dot auto-load on page load + one-finger map pan from load**
  Two Routes map bugs on mobile:

- **Publishing consolidated onto the Sheets publishing system**
  There were two parallel "publishing" mechanisms: per-project boolean flags (projects.is_call_sheet_published / is_schedule_published / is_shot_list_published / is_credits_published / is_release_hub_published, toggled from the dashboard and the global Publishing modal) AND the She…

- **Per-page publish + export routing + personal-workspace access + SPA navigation audit**
  Finished the outstanding publishing + access-model work and ran a full SPA navigation audit across both workspaces.

- **Purchase Orders — Actions-panel split-button label clipping (mobile)**
  Fixed a mobile UX bug on the Purchase Orders page reported from a phone screenshot: in the swipe **Actions** panel, two controls between the project selector (KOH V2 · FU2605) and the action buttons (Wrap Project, Top Sheet Template, …) rendered only a partial, mid-word slice of …

- **Personal production company logo: upload, attach, and per-workspace logo resolution**
  Personal-workspace projects can be attached to a production company (the ones saved under Settings → Personal Workspace → Production Companies), and that production company can now have an uploaded logo. The "org / production company logo" placeholder that appears on call sheets …

- **Onboarding pathways (chat / form / voice) + role-based dashboard personalization**
  Major revamp of onboarding plus a new role-based personalization engine. The Hello screen now offers **Voice** and **Chat or Form**; the latter routes to a new intermediate chooser (onboarding-mode.html) that splits into the existing conversational **AI Chat** wizard and a new st…

- **Full-screen onboarding chat wizard + Company Move global strip type**
  Two changes. **(1)** Added the Company Move strip type (#ffedd5) to the global_strip_types DB table — it already lived in the canonical JS/TS registry (js/strip-types.js, _shared/strip-types.ts) but was missing from the table that seeds the strip palette for every account, so the…

- **Searchable multi-select production company picker (pills) + project↔PC many-to-many**
  The "Create New Production" modal's pickers are now nicer, searchable, pill-style comboboxes. The **Production Company** picker is searchable **and multi-select**: a project can have more than one production company, each shown as a removable pill. The Agency / Brand pickers also…

- **Schedule: Insert ▸ Add Strip ▸ — full strip vocabulary via the shared handler**
  The menu bar's **Insert ▸ Add Strip ▸** submenu now offers the exact same vocabulary as the right-click context menu and the palette — **Add Shot, Add Scene, and every configured strip type** (Prep, Lunch, Crew Call, Company Move, Camera Wrap, Safety Meeting, Travel, Banner, …) —…

- **"Hello" first-run welcome screen (macOS-style)**
  A premium, Apple-MacBook-"Hello"-inspired first-run experience shown **once per account** on first login, regardless of how the account was created. Phase 1: a giant chromatic "Hello" (continuous hue-rotate rainbow gradient clipped to the glyphs) breathing on a pure-white screen …

- **Schedule & Shot List — finish the menu-bar migration: every control in the menu bar, old toolbar gone at all widths**
  Follow-up to the initial toolbar→menu migration (ac7b8c7). Two gaps remained:

- **Changelog: Sheets-style editor header on Schedule / Shot List / Casting**
  Added a shared, config-driven editor header + menu bar (#editor-header 80px + #editor-menubar 32px) that visually matches the sheets in-sheet header (#sheet-header / #sheets-menubar). It is mounted only when a project is selected (?id= present) on Shooting Schedule, Shot List, an…

- **Docs page — mobile UX overhaul**
  Fixed the four reported mobile bugs on the Document Center (docs.html) and hardened the doc-tile thumbnail rendering. All changes are CSS/HTML/JS inside docs.html; no schema, edge-function, or other-file changes.

- **Destructive-action connection guards (app-wide audit + fixes)**
  Across the app, many destructive actions deleted/removed items that other data depended on, with either a bare confirm("Are you sure?") or **no confirmation at all**, leaving dangling references and broken workflows (orphaned commitments, an active chargeable virtual card survivi…

- **Standardize `dark-mode-critical` anti-flash block across pages**
  Auditing dark mode across the shot-list SPA navigation matrix surfaced that the <style id="dark-mode-critical"> anti-flash block (the inline CSS that paints a dark background BEFORE /css/dark-mode.css loads) had drifted into **6 distinct variants** across the app. 23 pages shippe…

- **Casting page: Talent Skins designated sheet + Publish banner**
  The casting page can now have a designated sheet (doc type **talent_skins** — "Talent Skins / Casting"), assignable from the Sheets page "Set as…" menu, and shows the same Published/Draft + Publish/Unpublish banner as the other doc-type pages, publishing the designated sheet's pu…

- **Canonical strip-types registry + normalization layer**
  Four parts of the app invented incompatible names for the same shooting-schedule strip types ("shot" vs "shoot", "Lunch" vs "lunch", "Scene Start" vs "scene", "Call" vs "call"). The mismatch silently broke features: AI-imported strips were invisible to the time cascade (importer …

- **Branded access-gate splash + page wiring across project pages**
  Finished the personal-workspace page-access gate work:

- **Wrapped-project file archiving — Phase 1 (pack-to-archive, no deletion)**
  When a project is wrapped, a background cron sweep now compresses the project's **stored files/documents** (the bulk of the storage footprint) into a single ZIP in the private wrapped-archives bucket. **Phase 1 = pack-to-archive only; nothing is deleted** — originals stay in plac…

- **Todos page — code-review QA + four inline fixes**
  Read-only audit of todos.html (1342 LoC) covering workspace separation, realtime channel gating against the actual loadTodos query, RLS surface for public.todos, todo CRUD (create / edit / complete / delete), filters (quick + project + source + assignee), due-date logic, the new-…

- **fix(mobile): remove static will-change on #swipe-track — iOS WebKit blank-band repaint bug**
  #swipe-track had will-change: transform applied unconditionally in the mobile media query, permanently promoting it to its own GPU compositing layer. iOS WebKit has a long-standing bug where composited ancestors of a scroll container fail to invalidate during a scroll, leaving la…

- **Subscription sub-tabs — Organization | Personal**
  In Settings → Billing, the personal-workspace subscription card and the organization subscription card(s) used to stack on top of each other (with the Admin Seats card wedged between them) once the page refreshed after any billing action. That made it easy to scroll past the wron…

- **SPA port follow-ups: routes structure, canvas first-paint, body-overlay tagging, null-guards**
  Follow-ups to the morning's SPA port (docs / routes / canvas / shooting-schedule / petty-cash). Three real bugs surfaced during visual testing in Chrome and got fixed live:

- **Port docs / routes / canvas / shooting-schedule / petty-cash to SPA lifecycle**
  Five more top-level pages opt into the SPA router (Mobile Phase 1.5 — see js/spa-router.js). Each page now registers window._cdPageLifecycle = { init, teardown } so navigating to/from it swaps only the <main> region instead of triggering a full document reload — no white flash, h…

- **SPA navigation body-overlay leak audit + universal sweep**
  After navigating from purchase-orders.html back to dashboard.html, the PO AI panel content (mode selector, checkmarks, action list) bled through onto the dashboard view. Root cause: the SPA router only swaps <main>, so any element appended to <body> (or otherwise outside <main>) …

- **Bump Solo / Solo Max project caps + de-jargon subscription tier copy**
  Two changes. (1) Raised the project caps for the Solo tier family in plan_permissions.permissions->'max_projects': **Solo 5 → 10**, **Solo Max 5 → 25** (beta variants matched to their retail tier; legacy solo_* grandfathered to the Solo Max cap per _baseSlug()). (2) Rewrote subsc…

- **Shot List — exhaustive QA + mobile optimization**
  Live QA of shot-list.html in both personal and organization workspaces surfaced four functional bugs and a whole-page mobile-responsiveness gap. All five issues were fixed inline, per-file deployed, and verified live.

- **Shoot Locations + Scout Candidates browse panels — JS module (completes ded95f8)**
  Commit ded95f8 (feat(location-deck): voice parity + slide-editor save buttons) shipped the markup, CSS, script tag, and Mode B init wiring for two new browse panels in decks.html (Shoot Locations + Scout Candidates) but never landed the JS module that backs them. Without window.P…

- **Sheets: shared-sheet edit access gated to paid plans**
  Personal-workspace shared sheets now treat VIEW access as universal (free or paid) but gate EDIT access behind a paid plan. If a free user opens a sheet that was shared with them at permission='edit', the page downgrades them to view-only on load and shows a non-blocking banner w…

- **Settings: default Profile tab on cold load, PW › AI Settings inlined, avatar menu wiring, PW seed for Mark**
  Four small Settings-page changes plus a one-shot DB seed for Mark's Personal Workspace.

- **settings.html: two distinct bugs killed clicks on the header (loader + stale spotlight override)**
  Two unrelated bugs were both eating clicks on the settings-page header. Fixing the first one exposed the second.

- **shooting-schedule.html — 7s loader safety timeout**
  On mobile, shooting-schedule.html was getting stuck permanently on the CrewDeck loading spinner because the page had no loader safety timeout — if any async call in the init chain hung (network, loadSharedHeader, profile/permission lookups, project fetch, etc.) the #page-loader o…

- **Routes — defer header project-picker open in `_rtRequireProjectOrPrompt`**
  End-to-end QA of routes.html uncovered a flow where the "add a stop" gate told the user to "Select a project first" but never opened the project picker — defeating the purpose of the prompt. _rtRequireProjectOrPrompt called document.getElementById('hdr-proj-switcher-btn').click()…

- **Routes map: force-recreate `_rtMap` on degenerate bounds**
  After an SPA navigation back into routes.html, the existing google.maps.Map on #rt-map-canvas would occasionally boot into a "degenerate viewport" state: _rtMap.getBounds() returns a zero-area rectangle (SW === NE). In that state panTo() cannot move the camera (it pan-clamps back…

- **File Structure UI redesign + per-project Google Drive / Dropbox folder sync**
  Two coordinated changes:

- **Purchase Orders auto-selects dashboard's active project**
  When the user navigates to purchase-orders.html from the dashboard with a project actively expanded, the PO page now auto-selects that project's POs instead of showing the default empty/all-projects state. Previously this only worked for navigation paths that explicitly appended …

- **Personal billing tab shows actual plan instead of "Free Plan"**
  The Settings › Billing › Personal tab was rendering "Free Plan / Active" for users whose profiles.plan_id was set to a paid tier but whose profiles.stripe_subscription_id was null. This was the state for any account on a comped/beta plan, or any account where the Stripe webhook n…

- **Mobile chat hub — drop Messages tab, add To Dos tab**
  The mobile chat hub no longer surfaces SMS / chat_threads content. Tabs are now **Console | Tasks | To Dos** (in that order). The phone-line gating, chat_threads / chat_messages queries, the comms-send web_compose path, the per-thread settings sheet, the mode/agentic/detail toolb…

- **Mobile chat hub — keep #mobile-tab-bar visible while hub is open**
  .mch-overlay used inset: 0 at z-index 9500, so the dimmed scrim covered #mobile-tab-bar (z-index 1000, height calc(64px + env(safe-area-inset-bottom, 0px))). Now the overlay stops above the bar — top/left/right: 0 with bottom: calc(64px + env(safe-area-inset-bottom, 0px)) — so th…

- **Mobile chat hub — swipe right on conversation pane to go back**
  Adds an iOS Messages-style swipe-right gesture to the mobile hub's conversation pane. A right swipe of ≥60px with <50px vertical drift on .mch-view--convo calls the same showThreadList() that the back arrow calls. One handler covers both Messages threads and Console/Tasks threads…

- **Mobile chat hub — SSE streaming + process log parity with desktop**
  The mobile hub's conversation pane now renders AI responses with the same live process log, thinking indicator, and streaming behavior as the desktop js/ai-chathub.js. Previously the mobile hub did a single-shot CrewAI.call('ai_chat', …) — no tool calls, no reasoning steps, the w…

- **Mobile chat hub — "+ New" creates ai_chat_thread inline**
  The header pencil button on the Console / Tasks tabs was closing the mobile hub and calling window.AIChatHub.open() — which is the desktop right-side drawer, the wrong surface on mobile. Now both Console and Tasks insert a fresh ai_chat_threads row inline, push it onto the local …

- **Mobile hub convo polish + ai-agent web_search tool**
  Three changes shipping together:

- **Mobile chat hub — inline Console/Tasks view + Console default on re-open**
  Three mobile-hub bugs. (1) Tapping a Console or Tasks row was closing the mobile hub and opening the desktop right-side AIChatHub drawer — wrong on mobile. Console/Tasks rows now slide into the hub's existing conversation pane and render ai_chat_messages for that thread as chat b…

- **Mobile chat hub — compose bar on Console/Tasks threads (sends via ai_chat)**
  Previously the inline AI-thread view was read-only — .mch-ai-mode CSS hid the entire bottom toolbar+compose stack, so there was no way to type. Now the same .mch-compose form renders for all three tabs (Messages, Console, Tasks); only .mch-toolbar and .mch-staged-files stay hidde…

- **Mobile chat hub — full-screen overlay from middle tab button**
  Builds a custom mobile-only chat overlay that lets the user browse threads and read/reply without leaving the current page. On surface-less pages (dashboard, projects, etc.), the middle tab-bar button (#mobile-search-btn) now opens this in-place overlay instead of navigating to /…

- **Mobile chat hub — fix "Could not load messages" + add Dispatch/Tasks tabs**
  Mobile testing surfaced two issues, both fixed in js/mobile-chat-hub.js:

- **Mobile chat hub — full ai-chathub.js control set on comms data**
  Brought js/mobile-chat-hub.js up to control-parity with js/ai-chathub.js (the desktop AI chat hub) while keeping its data layer pointed at the COMMS backend (chat_threads / chat_messages / comms-send web_compose, mirroring chats.html). The overlay now ships the same toolbar, mode…

- **Mobile middle AI button → /chats.html on surface-less pages**
  On mobile, tapping the middle #mobile-search-btn from a surface-less page (e.g. dashboard) previously fell back to window.AIChatHub.open(), which opens the right-side desktop-style drawer over the mobile viewport. The fallback now SPA-navigates to /chats.html (via window.cdNaviga…

- **Load template picker — usable on PW Personal Default, PC, and Org**
  Templates saved via the existing **Save as template…** button now have somewhere to land. A new **Load template…** button next to it opens a picker showing:

- **Importer modal: scan Drive / Dropbox folders for structure**
  The "Import file structure from folder" modal (Settings → Personal Workspace → Production Companies → Import from folder, and the Personal Default equivalent) now offers two cloud-scan options in addition to the local drag-drop:

- **Folder classifier: payment-method buckets on scan + import**
  When the AI scans a linked Google Drive or Dropbox folder, or when the client-side importer ingests a dropped folder, the generated structure_json now recognizes payment-method bucket folders (AMEX, WIRE/ACH, CHECK, UNPAID, ALL) and emits the canonical po_group content_source spe…

- **RLS: allow users to save templates of type `template`**
  The **Save as template…** button in the Visual file-structure editor (Settings → Personal Workspace → Production Companies → File Structure, and the org equivalent) failed with:

- **File-structures Tree view — Grid | Tree toggle on the cards editor**
  Adds a second viewing mode to the cards-view file-structure editor: a top-down org-chart Tree that shows the whole structure at once. The toolbar now carries a Grid | Tree segmented pill; the selected mode is persisted in localStorage (crewdeck-fs-cards-layout) and the Tree auto-…

- **emails.html: default to project picker; Templates button opens template editor**
  When emails.html loads without a ?id=<projectId> URL param, it used to drop the user straight into the workspace-wide email Template Editor. That conflated two flows — "compose a real email for a project" and "build a reusable template" — and made it easy for a user landing on Em…

- **crew-list: 7s safety timer to force-dismiss splash loader**
  Navigating to crew-list.html via SPA body-swap from the dashboard could leave the user staring at the sailboat splash loader forever — if any of init()'s awaited fetches stalled or threw, the dismiss line at the end of init never ran and the loader stayed up. Mirrors the same reg…

- **Crew list: replace checkbox with whole-row select + corner flag, add bulk Onboard**
  The project-view crew row no longer carries a leading checkbox. Instead the entire row card is clickable: a click toggles a crew-card--selected state and lights up a small triangular corner flag in the top-left. All existing bulk-action wiring (tcSelectedCrewIds, tcUpdateBulkBar,…

- **crew-list: empty-state for master crew database**
  When no project is selected, crew-list.html renders the master crew database view. Previously, an empty org showed only the table header ("Name / Position / Email / …") with no body — confusing for first-time users who couldn't tell whether the list was loading, broken, or genuin…

- **crew-list: stop flicker when exiting edit mode**
  When the user clicked the edit-mode toggle to leave edit mode, the page visibly flickered before settling on the saved data. Reproduced in both project-view (Mode A) and master-view (Mode B) with a project selected.

- **Console / Chat thread titles shortened to 3-5 word labels**
  Console rail labels (and the spotlight chat conversation list) used to show the raw user prompt truncated at 40-48 characters — e.g. "On Test Project 11, create a new budg…" or "log damage to the hero Mustang from…". These were hard to scan and indistinguishable from each other w…

- **Replace sailboat logo with CD monogram across the web app**
  Mark provided a new CD monogram (interlocking C + D, charcoal on textured paper) and asked that it replace the sailboat across the app in the same indigo as the old logo (#4038c8). First attempt hand-traced the curves and produced an approximation; this commit redoes it as a **ke…

- **Casting page + is_talent_dept flag**
  Scaffolds the new Casting surface and the data hook it needs. A new casting.html SPA page lands at /casting.html with project sidebar + roles list and a "Import a casting submission to get started" empty state on the right. The page is registered in the desktop app launcher (head…

- **Casting page — light-mode background + universal mobile swipe panels**
  Two polish fixes to casting.html:

- **Canvas — personal workspace save + library workspace-isolation QA**
  QA pass on https://crewdeck.io/canvas.html against both personal workspace (lastWorkspace.type = 'individual') and an org workspace (King Of Hearts, id 51). Six bugs surfaced — one critical (no save in personal workspace), four workspace-isolation leaks (My Canvases / Shared with…

- **Calendar.html — Exhaustive QA + Context-Menu Fix**
  Exhaustive QA pass against https://crewdeck.io/calendar.html in both personal and organization workspaces (Mark / King Of Hearts). Found and fixed two real bugs: the right-click context menu silently failed for all normal (non-shoot-day) events, and deleteEventBtn carried a dupli…

- **Breakdown a Script — Modal Overhaul + Inline Header Flow**
  Two changes to the "Breakdown a Script" entry points so producers can break down a file from anywhere in the app without leaving the page they're on.

- **Settings Billing — separate Organization & Personal tabs**
  The Settings → Billing pill sub-tabs (added in 283d032) rendered the same content in both tabs: the Personal panel showed the full pricing grid mixing personal-scope (Solo, Solo Max) and org-scope (Production, Studio, Education) "Select Plan" cards, and on first load the Organiza…

- **Beta plan visibility driven by a single production_launch_date**
  Replaces the prior three-phase open-beta gate (today < start, start ≤ today < end, end ≤ today) with a single date-driven rule:

- **AI Location Deck — Phase 1c — Pitch Deck subtypes mirror breakdown_categories + Phase 1 wiring verified**
  Two-part entry, both shipped together:

- **AI Location Deck — Phase 1b — Pitch Deck subtype hierarchy**
  Same-day clarification on top of [2026-05-30-ai-location-deck-phase1](2026-05-30-ai-location-deck-phase1.md). Location decks are NOT a standalone deck type — they're a **subtype of "Pitch Deck"**, alongside Picture Car decks and Specialty Item decks. The Phase 1 ship treated "Loc…

- **AI Location Deck — Phase 1 (foundation + breakdown-anchored search + final/scout save targets)**
  Phase 1 of the AI Location Deck feature (full spec: docs/pitches/ai-location-deck-pitch.md). Adds the foundational schema, shared helpers, six AI tools, and the Location Deck deck type so a user can say *"build me a location pitch deck from the breakdown — 3 options per location"…

- **AI Location Deck — Phase 1 follow-ups (voice parity + slide save actions)**
  Closes the two known issues called out in [2026-05-30-ai-location-deck-phase1.md](2026-05-30-ai-location-deck-phase1.md):

- **Gate W-2 employee payroll pipeline as "Coming Soon"**
  Mark deferred the in-house W-2 employee payroll pipeline (Wrapbook stays as the future provider; no in-house build right now). Every UI surface and AI tool that exposes W-2 employee classification, Wrapbook payroll runs, or import-from-time-logs staging is now gated behind a sing…

- **Unified Invoices & Payment Hub + W-9 collection**
  Rebuilt invoices.html from scratch as the single payment-tracking hub that closes the full payment loop. Four tabs — **Payments owed to me** (default), **Payments I owe** (org owner/admin only), **Standalone invoices**, **W-9 status**. "Owed to me" aggregates the four real paymen…

- **todos.html — fix SPA-entry crashes (outside-`<main>` refs)**
  Navigating to /todos.html via the SPA router **from /settings.html** threw two sequential runtime errors that left the page un-wired:

- **Fix: `window.supabase` clobber broke cd-spa page init on SPA-entry**

- **SPA isolated-mount: sheets.html (Univer escape hatch)**
  sheets.html embeds Univer (an 890 KB spreadsheet engine that owns its own canvas, web workers, and DI graph). The current SPA router body-swaps <main> on every same-origin nav, which would orphan Univer's mounted DOM and leak its workers across the swap. This change adds a new "i…

- **Mobile SPA port: remaining pages (credits, payroll, documents + responsive long-tail)**
  Continues the Phase 1.5 zero-refresh SPA migration (planning/mobile-apps-PLAN.md, router in js/spa-router.js) across the set of pages not owned by the sibling audit/comms-ports tasks. Three in-app pages got the **full** body-swap port (<meta name="cd-spa"> + <main> + init()/teard…

- **Mobile SPA port — emails, invoices, calendar (communications.html is a no-op redirect)**
  Ports emails.html, invoices.html, and calendar.html to the shared mobile SPA pattern already established by purchase-orders.html, shooting-schedule.html, routes.html, todos.html, etc.

- **SPA router lifecycle: chats.html (the realtime comms page)**
  Ports chats.html to the SPA router lifecycle (planning/mobile-apps-PLAN.md §3.5). chats.html is the renamed "communications.html" the plan flags as the highest-care realtime page; it was deferred from the 2026-05-29-spa-lifecycle-invoices-emails.md pass because it is structurally…

- **SPA modal-bleed sweep — move all chats-specific modals + similar siblings inside `<main>`**
  Commit 3e4f591 (the prior /loop task) moved #phone-gate-modal and #upgrade-gate inside <main> to stop them bleeding into the dashboard's widget panel after SPA navigation away from chats. The fix wasn't complete: seven more chats-specific modals were still sitting between </main>…

- **SPA modal-bleed sweep — remaining pages + dashboard teardown + body-class strip widen**
  bf6d3ac (the prior pass) moved body-level modals inside <main> on chats, crew-list, calendar, emails, documents, and purchase-orders. This pass completes the sweep across the remaining SPA pages and addresses dashboard — which structurally can't move its modals inside <main> and …

- **SPA per-page conversion — organizations.html + dashboard.html + settings.html (sibling-hot cluster COMPLETE)**
  The prior batch (2026-05-29-spa-conversion-batch.md) intentionally deferred dashboard.html, settings.html, and organizations.html as "sibling-hot" because parallel tasks were editing them. This session targets that cluster. Result: **organizations.html and dashboard.html shipped;…

- **SPA router lifecycle: invoices.html + emails.html (calendar verified; chats deferred)**
  Second pass of the comms/emails/invoices/calendar mobile work. The earlier session (changelog 2026-05-29-spa-port-comms-emails-invoices-calendar.md) added the **CSS / swipe-panel layer**. This session adds the **SPA router lifecycle layer** (planning/mobile-apps-PLAN.md §3.5, rec…

- **SPA-entry robustness: load page deps + guard outside-`<main>` refs**

- **SPA — dashboard mobile scaffold rehydrate on body-swap entry**
  When dashboard.html is opened via SPA body-swap from another SPA-enabled page (chats, crew-list, calendar, todos, …), the mobile project-detail panel rendered "not optimized" — desktop chrome leaked through and the fullscreen detail panel resolved against the wrong containing blo…

- **SPA conversion: shot-list.html (second prod page; enables calendar↔shot-list)**
  Second production page on the SPA router. With calendar.html already enabled, this creates the first real two-page cluster so a real→real SPA swap (no reload, scroll restore, teardown) can be E2E-verified.

- **SPA conversion: crew-list.html (cluster grows to 3 pages)**
  Third production page on the SPA router (after calendar.html + shot-list.html). crew-list is nav-bar-linked and adjacent to many pages, so this adds real seamless-nav reach.

- **SPA conversion: calendar.html (first production page on the SPA router)**
  First real CrewDeck page flipped onto the zero-refresh SPA router. Validates the migration recipe (Phase 1 changelog §"Migration recipe") on production code.

- **SPA router per-page conversion — batch (continued)**

- **Solo Subscription UI QA — full surface walk + fixes**
  QA pass of every UI surface available to a **Solo** (solo_personal_monthly) subscriber, driven through Chrome MCP against live crewdeck.io with Mark's logged-in session. Ground truth: client PlanGating.check() map verified identical to DB plan_permissions for solo_personal_monthl…

- **Settings: harden splash-loader dismiss**
  **FROM:** The Settings full-screen splash loader could linger indefinitely. The dismiss relied solely on the fade-out CSS transition's transitionend event to call _loader.remove(). In a throttled/backgrounded tab the transition is paused and transitionend never fires, so the load…

- **Routes: gate Driver View on driver-assignment, not workspace type**
  The Routes page forced the **Driver View** (the read-only driver share UI, with its "Driver View" header and a perpetual loading state for non-drivers) on any user in a **personal workspace** who had a crew row on the loaded project — including org owners/admins and crew members …

- **Routes map: center on the user's current location "no matter what"**
  The Routes page was opening centered on Los Angeles (a hardcoded cold-start fallback) and never panned to the user even after the browser geolocation fix landed — the blue-dot indicator module acquired a location but had no hook back into the map's centering logic, and with no pr…

- **Apple-Maps-style "blue dot" current-location indicator on all routes.html maps**
  Adds an Apple-Maps-style "you are here" blue dot to the maps on the routes page. A new shared helper module renders the indicator — a translucent accuracy halo (Apple system blue #007aff at 18% opacity that scales with the device's reported GPS accuracy), a white "pop" ring, a so…

- **Personal Workspace tabs — full visual parity with the org page**
  Mark's directive: the Personal Workspace (PW) settings tabs must look like an independent, polished settings surface matching organizations.html — and the "Manage in org" delegation pattern is fully retired (already done for Integrations in the prior entry; this entry confirms ze…

- **Pull-to-refresh direction lock + panel-drag coordination**
  mobile-pull-refresh.js (Phase 6) attached touchstart/touchmove listeners to document and committed to "pulling" the moment a single-touch landed at scrollTop === 0. It then preventDefault()-ed once dy > 8. On the dashboard — where mobile-panels.js owns horizontal swipes between Q…

- **Production Report ← Picture Cars Phase 1 integration**
  Folds the Phase 1 Picture Cars data cluster (9 tables shipped 2026-05-29 in docs/changelogs/2026-05-29-picture-cars-phase1.md) into the daily production wrap report — not as a bolted-on "Picture Cars" mega-section, but threaded into the report's existing sections so picture-car a…

- **Picture Cars Phase 2 — production layers (convoy / rigging / police / period landmarks)**
  Ships Phase 2 of the Picture Cars cluster (features 7, 8, 9, 11 from planning/picture-cars-PLAN.md): convoy/motorcade choreography, process-trailer rigging with capacity validation, police escort handoffs with privacy-default badge gating, and a period-landmark anachronism valida…

- **Picture Cars Phase 1 — foundation cluster (action_blocks → damage log)**
  Ships Phase 1 of the 18-feature Picture Cars cluster on routes.html → Picture Cars tab. This phase delivers the foundation 7 features the user called out (action blocks, EMS staging, driver certifications, vehicle insurance certificates, stunt coordinator signoff, hot/cold transi…

- **Picture Cars Phase 1 follow-ups — EMS live lookup, stunt-coord column, insurance RLS, wrap PC inject, Fabric→PDF**
  Five follow-ups closing out gaps left after Picture Cars Phase 1/2:

- **Petty-cash virtual-card plan gate (Solo)**
  **FROM:** petty-cash.html had no client-side plan gate on virtual-card issuance, so a Solo-tier user (plan_permissions.virtual_cards=false) could see and use the issuance affordances. Only the server-side mitigations applied (Lithic "not configured" guard + ai_approval_queue for …

- **Personal Workspace Integrations — own sign-in per provider**
  Settings → Personal Workspace → Integrations now gives each integration its **own** Connect flow with its **own** user-scoped OAuth token — fully separate from the organization's connection. A single CrewDeck user can have org Google Drive Account-A connected AND personal Google …

- **Personal Workspace: functional Departments / Clients / Vendors / Locations / Brand Kits / Playbooks / Integrations**
  The Settings → Personal Workspace section previously shipped read-only stubs ("coming in the next update"). This change makes those tabs **fully functional CRUD**, mirroring the organizations.html management tabs but scoped to the signed-in user instead of an organization. A solo…

- **New CrewDeck logo (indigo sailboat, background removed)**
  **FROM:** old logo. **HOW:** Mark provided a new sailboat logo on a cream background. Removed the background by keying on blue-dominance (isolating the boat from the cream bg, the soft shadow, the white sail-gap negative space, and a faint compass watermark), recolored the boat t…

- **Mobile Phase 6 — UI polish (custom dialogs, back button, pull-to-refresh, keyboard, status bar)**
  Phase 6 of the Capacitor mobile app work — the polish layer that turns a "web app in a frame" into a native-feeling app. Five things shipped together:

- **Mobile Phase 6 activation — pull-refresh scroll-ancestor, keyboard route-reset, header-loader wiring**
  This ships the Mobile Phase 6 polish modules end-to-end (the header-loader script-injection block, cd-dialogs.js, mobile-back.js, mobile-keyboard.js, mobile-pull-refresh.js, mobile-status-bar.js) plus two correctness fixes that were blocking activation:

- **Mobile Phase 3 — Push Notification Backend (APNS + FCM, inactive pending creds)**
  Backend foundation for native push notifications on the Capacitor mobile app (iOS + Android). Builds the device-token store, a JWT-authenticated registration endpoint the mobile shell calls when Capacitor PushNotifications hands back a token, and a service-role dispatcher that si…

- **Mobile Phase 2: deep links, biometric unlock, PKCE auth options + Phase 1 activation**
  Activates the Phase 1+1.5 mobile work (committed 8c4924e, deployed a396772) and lands the Mobile Phase 2 deep-link + biometric + auth scaffolding.

- **Mobile apps: Capacitor scaffold + zero-refresh SPA routing layer**
  Implements Phase 1 (Capacitor native shell) and Phase 1.5 (SPA routing layer) from planning/mobile-apps-PLAN.md. The Capacitor scaffold lives in a new mobile/ subfolder and always-loads https://www.crewdeck.io with a bundled offline fallback shell. The SPA router (js/spa-router.j…

- **Mark subscription flip: super → Solo (testing)**
  Deliberate manual flip of Mark's account (mzgower@gmail.com, id 6021f6dc-5439-4314-88d7-99238d1ecaf3) from the super plan to the canonical Solo personal-workspace plan solo_personal_monthly for testing. Stripe was **not** touched — this is a local DB flip only. The canonical "Sol…

- **In-editor script breakdown (replaces full-page overlay on docs.html)**
  Mark (2026-05-29): "no — it should not be an overlay, it should be in the actual TinyMCE editor." The script breakdown previously ran in a full-page #breakdown-overlay that rendered the script as read-only text in its own column. This change moves the entire breakdown experience …

- **Forms editor redesign + placeholder registries aligned**
  **FROM:** Earlier today's docs/forms integration (commit 7ab5442) seeded 13 new system form templates and shipped 6 AI tools that generated incident reports + stunt safety briefings as plain text. The form templates were labelled with the right field names but had no placeholder …

- **Footer AI assistant works on SPA-entry for calendar + shot-list; floating Schedule FAB removed**

- **Field-interactive signer page (pdf.js + positioned fields)**
  Upgrades the proprietary signer experience (sign-document.html) from a single fixed-signature flow to a **field-aware** one for PDF documents that carry positioned per-signer fields. The signer now sees the actual PDF rendered with pdf.js and their assigned fields highlighted in …

- **Dual Subscription Support — a user can hold a personal AND an org plan at once**
  A user can now hold BOTH a personal-tier subscription (e.g. Solo Max, charged to profiles) AND an org-tier subscription (e.g. Production, charged to organizations) at the same time, on a single Stripe customer. Previously the Stripe webhook treated **every** subscription as perso…

- **Full PDF tool on the Docs page with seamless AI/manual annotation parity**
  Turns the Docs page detail panel into a fully-functional in-browser PDF tool — view, import, fill, annotate, sign — modelled on Preview/Acrobat. The critical requirement is **visual parity with the AI doc-intelligence output**: a PDF that is half-filled by the AI and half by a hu…

- **Personal-subscription PDF import (org-less documents)**
  Reported by the user: "it should let me import pdfs in the personal subscription." The Docs PDF import was gated behind an organization workspace ("Select an organization workspace to import documents.") because org_documents was org-only (organization_id bigint NOT NULL). CrewDe…

- **Send a docs-page PDF for signature via the provider-agnostic e-sign system**
  Wires the docs-page PDF viewer into the EXISTING provider-agnostic e-signature system (esign edge fn + adapter layer: docusign/adobe/dropbox/pandadoc/ boxsign/signnow/proprietary). The annotated/filled PDF from the viewer is sent through create-envelope, which dispatches to the o…

- **E-sign follow-ups: personal-workspace, delegated signing fields, signed-PDF child doc**
  Closes the three documented follow-ups from the e-sign integration.

- **Docs/Forms ↔ Picture Cars integration**
  **FROM:** Picture Cars Phase 1 (commit 55ce6a6 today) shipped 9 new tables and 14 AI tools for action_blocks / damage_log / stunt_signoffs / vehicle COIs / driver_certs / EMS staging / hot_cold transitions / camera_car_routes — but the docs/forms surface didn't know about any of …

- **Doc AI assistant opens from the footer button (floating launcher removed)**
  **FROM:** js/doc-ai-engine.js init() built a fixed bottom-right circular launcher (#docs-ai-launcher) + a hint tooltip (#docs-ai-tooltip) that toggled the Doc AI panel. Redundant with the shared footer AI button. **HOW:** stopped building the launcher + tooltip; instead expose th…

- **Docs: "Convert to PDF & set up signature/fill fields" bridge**
  First (keystone) phase of the Acrobat-style "edit a PDF → add fill/signature boxes → send for signature" + "CrewDeck-native doc → PDF with form/signature fields" vision.

- **Tauri 2.0 desktop scaffold (macOS + Windows, unsigned)**
  Stands up a native **desktop client** for CrewDeck using **Tauri 2.0**, so Mark has an installable macOS/Windows app today while D-U-N-S enrollment (and code signing) is pending. The app is a **thin native shell**: the main window loads the production web app at https://www.crewd…

- **Desktop Google sign-in via system browser + crewdeck:// deep link**
  Google sign-in did not work in the desktop app because **Google blocks OAuth inside embedded webviews** (the Tauri window is a macOS WKWebView; GIS relies on FedCM/iframes that webviews don't support). Fixed with the standard desktop OAuth pattern — run the flow in the **system b…

- **Dashboard AI search toggle hidden for personal/solo workspaces**
  The "AI" toggle in the dashboard header search disappeared for users in a personal / solo workspace (reproduced on web and the desktop app). Root cause: the gate used hasPermission('general.canUseAiSearch') === false, but hasPermission() **default-denies** when a permission key i…

- **Crew Time Clock — Phase 3 (wrap-export content sources + voice parity)**
  Phase 3 closes out the Crew Time Clock feature on two fronts: it freezes the project's overtime + meal-penalty record into the **wrap-export archive**, and it brings the 12 crew-time AI tools to the **voice** surface at parity with chathub.

- **Crew List: unblock the individual (Solo) workspace**
  **FROM:** Opening Crew List in the individual (personal/Solo) workspace hung on the full-screen splash loader forever. Root cause: loadAdminPortal had a stale access-control gate — "Access Denied: the Crew List feature is only available within a Production Company workspace" — th…

- **Crew List: hide onboarding + config controls in personal (Solo) workspace**
  After unblocking Crew List for the individual/Solo workspace, the onboarding controls were still showing. Onboarding (crew_onboarding) and role/onboard configuration are org/production-only features (Solo has crew_onboarding=false), so they must not appear in the personal workspa…

- **ChatHub: remove the "Plans" tab**
  Removed the **Plans** tab from the AI ChatHub rail (the left-strip tab list that previously was Tasks / Dispatch / Todos / **Plans**). The tab surfaced a card list of ai_orchestrations rows grouped by status, with an "Awaiting review" pending badge. Per product direction, plans a…

- **Chathub file-upload flow live E2E + 2 P1 fixes**
  The 3 request_file_upload file-upload-flow scenarios (FU1 petty-cash receipt, FU2 contract review, FU3 picture-car damage photo) in docs/qa/2026-05-28-voice-chathub-parity.xlsx were code-verified-only on 2026-05-28 — their CHATHUB column was **BLOCKED** because the Anthropic acco…

- **Centralize Apps-menu plan gating into header-nav.cdGatePlanApps**
  The Apps launcher's per-plan visibility logic was duplicated and drifted across pages: dashboard.html and calendar.html each had their own freeApps/soloApps tier block, shot-list/contracts/invoice-generator had a hardcoded allowedIndividualApps whitelist, and the unified invoices…

- **Canvas ↔ Routes integration — stunt diagrams + annotated route maps**
  Ships Phase 1 of the Canvas ↔ Routes integration spec. Two routes-page entities can now carry a back-reference to a canvas (visualizations) document:

- **Calendar fits desktop viewport without page scroll**
  The month calendar overflowed the desktop viewport by ~493px and required vertical scrolling. Root cause: .calendar-day { min-height: 140px } forced the 6-week grid to a fixed 847px regardless of available height. On a 1512×767 desktop the grid alone ran from y=309 to y=1156.

- **Calendar month-view event pills clipped at cell edges**
  The month-view calendar clipped event pills at day-cell edges. Two distinct clips, both rooted in .calendar-day { overflow: hidden } (desktop media query):

- **Business Plan v17 → v18 — current-cycle ship rollup**
  **FROM:** BUSINESS PLAN/BUSINESS_PLAN.md at v17 (Solo/Solo Max as-implemented reconciliation, commits b98e160 + 2e5e53c). Part 24 ended at 24.10 (Picture Cars "planning in flight"); module count 34; footer/snapshot stamped v16.

- **Script breakdown system integrations**
  Connects the in-editor script breakdown to the rest of CrewDeck: production report, sheets, stripboard/schedule, e-sign approval, doc-intelligence script detection, and AI-agent tools. Built incrementally; each item deployed + verified on its own.

- **Brand kits attachable to a production company OR client + AI persona auto-pull**
  Extends the just-shipped Personal Workspace Brand Kits so a solo user can build brand kits for **both production companies and clients**, and so the AI persona auto-applies a project's brand voice when generating content.

- **Fix: Bids view unreachable for Solo (nav routed to deprecated pages)**
  Mark on the Solo plan (solo_personal_monthly, personal workspace) reported he couldn't reach the Bids view. Investigation showed there was **no plan- or workspace-type gate**: the Bids tab on budget.html is statically rendered and was already visible to Solo (confirmed live — dat…

- **Avatar menu: Org Dashboard link for all org members + correct plan badge**
  Two fixes to the shared header avatar dropdown (rendered by populateHeaderUser in header-loader.js and populateHeaderData in header-nav.js, inherited by every authenticated page):

- **Adobe Sign: unify connections, set secret, verify connect → send → cancel live**
  Closed the last gaps so Adobe Sign is fully working, and verified the whole path live against Mark's dev account (org 20).

- **Adobe Sign: independent org + personal-workspace connections (same or different accounts)**
  Ensures a Solo / Solo Max (personal-workspace) user can connect AND use Adobe Sign from Settings → Personal Workspace → Integrations, fully independent of any org connection — different Adobe accounts per scope, or the same account for both.

- **Adobe Acrobat Sign — connectable integration on org + Personal Workspace surfaces**
  Adds **Adobe Acrobat Sign** as a connectable OAuth integration on **both** Integrations surfaces — organizations.html → Integrations (org-scope, owner-only) and settings.html → Personal Workspace → Integrations (personal-scope). **DocuSign** and **Dropbox Sign** appear alongside …

- **Adobe Sign as an e-sign provider + Mode A/B envelope credit billing**
  Scope expansion on the Adobe Sign integration: wire Adobe Sign into the e-sign SEND flow as a selectable provider, and charge org credits per envelope **only when CrewDeck pays Adobe** (Mode B). Crucially, most of the heavy lifting already existed in the codebase — the discovery …

- **Adobe Sign: drop Mode B — pure pass-through to the user's own subscription**
  Per Mark (2026-05-29): **drop Mode B entirely.** Adobe Sign in CrewDeck is now a pure pass-through to the user's OWN Adobe subscription — Adobe bills the user, CrewDeck charges $0 and never hosts a shared Adobe account. If a user hasn't connected Adobe, they can't pick it as a pr…

- **Adobe Sign connect: force an account-choosing step (logout → authorize)**

- **Phase 0 + Phase 1 E2E smoke + two P0 fixes**
  Ran the deferred E2E smoke checklist for Phase 0 (sibling local_d822ac77) and Phase 1 (sibling local_c9d5e3ec) via Chrome MCP against crewdeck.io. 18 of 20 scenarios PASS outright; 2 PARTIAL (org SYSTEM-proxy byte-diff and cross-user RLS — both code-verified, live cross-checks de…

- **Voice ↔ Chathub Parity Audit**
  User requested verification of "full parity between the AI tools available in the chat hub and the real-time AI voice interface" including project creation re-verification (already shipped) and every other AI tool including multi-step operations.

- **Voice realtime path — live E2E parity audit + F2 credit-gate fix**
  The prior parity audit (local_612f9dbe, workbook 2026-05-28-voice-chathub-parity.xlsx) compared the voice tool surface (gemini-live) to chathub (ai-agent) **statically** but never drove the actual voice client. This session closed that gap: a WebSocket harness opened the *same* w…

- **Two-phase beta system: closed beta + open beta plan tiers**
  Replaces the single-date beta gate with a two-phase system. Phase 1 is the existing **closed beta** (free plans: solo_max_beta + production_beta), visible once beta_launch_date passes. Phase 2 is a new **open beta** (discounted paid plans at $29/mo and $39/mo), which becomes visi…

- **Stripe Price IDs Wired — Solo Max / Solo / Beta Plans**
  Creates the live Stripe price objects for all repriced and new plans introduced in the 2026-05-27 Solo Max / Solo Personal Workspace launch, then wires the resulting price IDs into both the public.plans DB table and the CREWDECK_PLANS JS catalogue in settings.html. Resolves the "…

- **Routes session — UX polish, Routes-management surface, AI Describe billing**
  A long single-session polish pass on routes.html covering layout, dark-mode, project-selector behaviour, live-tracking consolidation, driver dropdowns, custom-select clipping, the New Route surface, AI Describe (time inference + vendor/location lookup + iterative refine + history…

- **request_file_upload — one tool, two transports (voice modal + chathub CTA)**
  **FROM:** when an AI task needed a file/photo to proceed (log a receipt, review a contract, log damage from a photo) but none was attached, the model had no structured way to ask for one — and the realtime voice surface had no upload affordance at all. **HOW:** new request_file_u…

- **Pickup search popup: phone / website / email contact rows**
  On the Routes page Pickups view, when a user searches a location and the search-result info popup appears (the one with the Street View preview box, _puOpenSearchPinInfo), the popup now also surfaces the location's contact details from Google Places — **phone**, **website**, and …

- **Phase 1 — Tier 2 content_source handlers (budget / sheets / docs / petty cash / crew)**
  Phase 1 shipped the resolver + walker + 5 AI tools + SYSTEM-default proxy for PO-only wraps. Phase 1's Tier 2 content_source handlers were deferred — custom file structures could *reference* budget_xlsx, sheet_pdf, etc. but the walker would unknown_content_source-throw because no…

- **Phase 1 Sessions 0 + 1 — Export-Surface Audit + Schema Migrations**
  Session 0 = the full export-surface audit (Q10 lock) — every page and edge function that emits a project-linked artifact was inventoried, every project-scoped storage bucket mapped, and the canonical content_source registry produced. Session 1 = the four schema migrations the res…

- **Phase 1 — Dynamic, Configurable Export File Structures (final)**
  Phase 1 of the Dynamic File Structures initiative ships end-to-end. Producers can now define per-organization and per-personal-production-company wrap-folder structures; the wrap export orchestrator resolves the right structure for each project and walks it via a shared TypeScrip…

- **Phase 0 Session 3 — AI tools for wrap / archive / unwrap**
  Adds 6 ai-agent tools so users can drive the Phase 0 wrap/archive flow from chat: wrap_project, wrap_and_archive_project, unwrap_project, redownload_project_wrap, archive_project, unarchive_project. All five state-changing tools are tier-destructive and fire the YES/NO confirmati…

- **Phase 0 Session 2 — Wrap Modal + Three Entry Points + Dashboard Badge Fix**
  Ships the user-facing wrap/archive UX from planning/dynamic-file-structures-PLAN.md §0.3–§0.5. Adds a shared, state-aware wrap modal (js/wrap-project-modal.js) that's reachable from three entry points: dashboard right-click, budget toolbar, and the existing purchase-orders toolba…

- **Phase 0 Session 2 enrichment — wrap modal summary now shows budgets, key crew, prodCo**
  Per Mark 2026-05-28 — the wrap modal's summary block was too sparse. Rewrote loadProject() + loadSummary() + the summary render so the modal now surfaces budget version subtotals (estimate / working / actual + variance), production company name, executive producer + other key cre…

- **Phase 0 Session 1 — Wrap & Archive Schema**
  First session of Phase 0 from planning/dynamic-file-structures-PLAN.md. Lays the schema groundwork for the upcoming Wrap & Archive modal flow: adds projects.archived_at, creates a project_wrap_events audit log table, and corrects the 2026-05-17 date-derived auto-wrap backfill (wh…

- **Personal AI line — manual attach/detach UI + AI tools**
  **FROM:** the comms provisioning task (sibling local_ad820996) shipped the profiles.attached_to_org_id schema + dual-page UI routing (settings.html when null, organizations.html when set) and wired the stripe-webhook to auto-attach a Solo Max personal line on activation. The webh…

- **File Structures: rich tree editor replaces raw-JSON textarea**
  Phase 1 (0fa6fd0) shipped Dynamic File Structures with a raw-JSON textarea for editing the wrap-folder tree. This change replaces that textarea with a self-contained rich tree editor — drag/drop, variable picker chips, content_source dropdown, predicate selector per node, live pr…

- **Folder-to-Structure Importer (standalone module)**
  Adds a third path into the Dynamic File Structures system: point at a real folder you've laid out on disk (a wrap from a prior job, a template a producer keeps in Dropbox), and snap that layout into a file_structures row. The importer is a **standalone** browser module — no depen…

- **export-project-wrap: parallel walker + parallel orchestrator hydrate**
  The Dynamic File Structures resolver-walker path used by every org/PC project ran sibling tree nodes serially — each top-level subtree (1. BUDGET, 2. PPB:TALENT, 3. LOGISTICS, … 8. PC) had to complete its sub-fn fan-out before the next one started. On Gymnopedie Doc (org 51, 4 PO…

- **Unified Document Intelligence — extend the existing doc-intelligence layer + surface every document**
  CrewDeck already had a Document Intelligence layer — the **doc-intelligence edge function** (analyze / cross_reference / re_annotate / merge_pdfs / fill_form / edit_document / extract_images; Gemini-2.5-Flash → Claude fallback; caches in doc_extraction_cache / cross_reference_res…

- **Crew Time Clock — Phase 2 (production-report, routes, budget, PO, payroll + AI tools)**
  Phase 2 wires the Phase-1 crew time-clock model (crew_time_logs + crew_time_calculations view + canonical _shared/payroll-calc.ts engine, mirrored client-side as js/payroll-calc.js) into five surfaces so overtime + meal-penalty data flows everywhere it matters, and adds three AI …

- **Crew Time Clock — Phase 1 (schema + engine + crew-list UI + 9 AI tools)**
  Phase 1 of the crew time-clock feature: a per-crew, per-day punch model (crew_time_logs) with union-aware overtime + meal-penalty calculation, surfaced on the crew list page (per-crew Start/Lunch/Wrap + live timer, bulk actions, and a floating AD time-controls panel) and exposed …

- **Org credit gate — single source of truth (Category A + B bypass closures)**
  Closed the remaining org credit gate bypass paths that ai-router can’t enforce on its own. Extracted the canonical gate predicate into a shared module (_shared/credit-gate.ts) and wired it into both ai-router and every service-role / callModel-direct caller that used to bypass.

- **Communications → Chats brand rename**
  User-facing rename of the "Communications" / "Comms" hub to **Chats** across the web app, navigation, plan-gating, AI tool descriptions, and the plan-permission schema key. The page file rename (communications.html → chats.html) was already committed to main in 55bd0dc; this chan…

- **Communications: Test matrix verification (KOH org) + 3 schema fixes**
  Ran the 5-scenario page-ownership routing matrix against Mark's profile and KOH (King Of Hearts, org_id=51) using a synthetic personal shared AI line (+15555550101). All 5 scenarios passed, but the exercise surfaced three pre-existing schema bugs that had been silently masking th…

- **Communications: page ownership refactor — settings UX moves off communications.html**
  Per Mark's routing clarification, **line settings UX is owned by the page that owns the user's context, not by the messaging UI**:

- **Communications: Dual-section lines dashboard for org owners with personal AI agent line**
  Implements LOCK 2 from Mark's directive: org owners who have a personal shared AI agent line (Production + Personal Line Beta / profiles.line_provisioning_status != 'none') now see a dual-section layout on the Communications page instead of the product-selection cards.

- **Communications: Composable section rendering + re-verified 6-scenario matrix**
  Per Mark's business-rule correction, the personal and company sections on organizations.html → Comms tab are NOT mutually exclusive — they're independent and BOTH can render simultaneously when an owner pays for two subscriptions (e.g. a personal Solo Max retail subscription that…

- **Call Sheet discoverability — empty-state CTA + designation deep-link**
  The call sheet is not a standalone page — it was migrated into the sheets system as CALL_SHEET_SCHEMA_V2 (standalone call-sheet.html was permanently deleted + gitignore-locked in 51c21ab, 2026-05-13). A survey of the current systems found that almost all of the requested "restore…

- **Business Plan v17 — Solo + Solo Max as-implemented reconciliation**
  Audited the v16 business plan's Solo + Solo Max sections against the live plan_permissions / plans rows and the verified gate stack (Part A stress test). The v16 Feature Gating Matrix and retail prices were **accurate** — no entitlement or pricing drift. The drift was concentrate…

- **Business Plan v15 → v16 (audit-driven correction pass)**
  BUSINESS PLAN/BUSINESS_PLAN.md rolled forward from v15 to v16. Audit-driven correction pass — no new Parts added. Five hard locks applied (margin multiplier reverted to 3.0×, real Blooio COGS at $89 shared / $285 dedicated, closed-beta ladder, $27/mo overhead-recovery framing on …

- **Budget versions render side-by-side natively, by default**
  The Budget page (budget.html) now shows **all budget versions side-by-side by default** on desktop — the existing "compare view" was promoted from a toggle-gated mode to the primary landing grid, matching the pattern Actual (getactual.io) uses for production budgets. Each version…

- **Archive decoupled from wrap state**
  Phase 0 (Q18) had locked archive behind wrap — projects had to be wrapped before they could be archived. Mark's original directive was that archive is INDEPENDENT of wrap: "a way to archive projects in the dashboard to hide them from view" (cancelled productions, stalled projects…

- **AI confirmation-style preference + universal action toasts**
  Two related AI-UX features.

- **Sun Seeker style overlay in Street View + search-bar fit**
  Adds two improvements to the Shot Locations Street-View experience:

- **Solo Max + Solo Personal Workspace — Full Platform Implementation**
  Implements the full Solo Max / Solo Personal Workspace tier system. Added a new solo_personal plan (the personal workspace plan without the AI phone line, $39/mo) as a distinct tier below solo_max. Fixed three incorrect solo_max permissions (crew_onboarding: false, virtual_cards:…

- **routes.html — SL/PC project gate + Pickups selector retained**
  Spec update to the previous session's pickup-map-parity task. The project selector is now retained on Pickup & Runs (no change), and Shot Locations + Picture Cars get a hard project gate. When either mode is loaded without a ?id= param, the #rt-overlay-panel shows a "Select a pro…

- **routes.html — Right-click context menu on Shot Location cards**
  Right-clicking any Shot Location card in the SL panel now opens the shared _rtShowCtxMenu with 6 actions:

- **routes.html — Right-click: street address via Geocoder promise form + Save as Candidate**

- **routes.html — Right-click direct-add + Street View header action buttons**
  ### Right-click "Set as location" now fully adds (no form step)

- **routes.html — Pickup & Runs map parity + SL/PC project selector**
  Two desktop-only quality-of-life changes to routes.html:

- **routes.html — Optimize button in all tabs with routing-options modal**
  The Optimize button previously appeared only in the Shot Locations tab. It is now visible in all three route modes and opens a modal with routing preferences before running.

- **routes.html — MV2 project selector + SL/PC mobile gate**
  Full-parity update for MV2 mobile (≤767px viewport) to match the desktop spec shipped in a5e0d33:

- **routes.html — Right-click on map to set location**
  Right-clicking anywhere on the desktop map now opens the shared _rtShowCtxMenu with two actions:

- **routes.html — Skip geolocation prompt on page load when position is cached**
  The Routes page was prompting the browser for location permission on every single page load.

- **routes.html — desktop gate title/links refresh on SL↔PC mode switch**
  When the page loaded without a ?id= param into SL gate mode, then the user switched to the PC tab (still no project), the desktop gate card still showed "Select a project to view **Shot Locations**" and all four project links still navigated to ?mode=shot_location. Clicking any p…

- **routes.html — Floating map search bar + action card (Phase 1)**
  Replaced the static ADD LOCATION form at the bottom of the Shot Locations panel with a map-native floating search experience. The panel is now cleaner; all location-adding happens directly on the map canvas.

- **routes.html — Universal custom dropdown for all native `<select>` elements**
  Every native <select> on the routes page (desktop and mobile) is now replaced with a styled custom dropdown — a trigger button with an animated chevron and a div-based option panel — matching the page's indigo design system.

- **routes.html + ai surface + google-places-proxy — AI Map Search Phases 2.5, 3, 4**

- **routes.html + ai-router + google-places-proxy — AI Map Search (Phase 2)**
  Phase 2 of the Shot Locations map search redesign: an **AI toggle** on the floating search bar lets the user type natural-language scout queries ("find parks with east-facing morning sun") and get a panel of candidate locations with map markers.

- **routes.html — Address autocomplete preview pin on map**
  Selecting any address from an autocomplete dropdown on the routes page now immediately pans the map to that address and drops a temporary green preview pin — without requiring the user to confirm the add first. This applies to every address field on the page: the Shot Locations a…

- **PO page: strip payroll-route suffix from crew display; modal top-right = #budget_line_item_id**
  Two surgical fixes to purchase-orders.html. Fix 1 removes the · Wrapbook (and · PO) suffix that was being appended to crew member names in the PO edit modal dropdown and the new-PO gate crew list — payroll route is internal routing, not a display label. The "Routes via: Wrapbook"…

- **MV2: fix stale map markers + list sheet on tab switch**
  Two related tab-switch bugs in the MV2 routes page:

- **MV2: light-mode text contrast on sheets + confirm dialog**
  Field labels, section headers, address lines, and the confirm-dialog message text were all using gray-400 (#9ca3af, ~2.8:1 on white) or gray-500 (#6b7280, ~4.6:1 on white) for their light-mode foreground color. All of those fail or barely pass WCAG AA for small text. Bumped to gr…

- **Fix: header AI search background + file attachment wiring**
  Three fixes to the header AI inline-answer flow (task local_afc4801c).

- **File attach on all AI engine panel surfaces**
  Adds a file-attach control (paperclip button + drag-and-drop + preview chips) to every AI panel powered by js/ai-engine/engine.js. This covers 16 surfaces: Purchase Orders, Budget, Docs, Calendar, Crew List, Emails/Communications, Payroll, Petty Cash, Decks, Routes, Shot List, Sh…

- **Dropbox Sign E-Sign Adapter — Full Implementation**
  Replaces the Dropbox Sign adapter stub with a complete implementation against the Dropbox Sign (HelloSign) v3 API. Aligns the credential key used by the adapter (DROPBOX_API_KEY) with what connectEsignProvider('dropbox') stores via organizations.html. Adds an ackBody field to the…

- **Desktop: Pickup & Runs map parity + SL/PC project selector**
  Two desktop polish changes to routes.html. (1) Pickup & Runs now shows the same full-bleed map layout as Shot Locations and Picture Cars: #pickup-mode-wrap was moved inside #route-mode-panel and becomes a 300px glass overlay on desktop, using the shared _rtMap/#rt-map-canvas canv…

- **Dashboard Locations — Role/Type Picker with Routes Color Parity**
  The dashboard Locations edit form previously had no way to set a location's type/role — users could only enter a name and address. The routes page has a 10-role enum (Basecamp / Exterior / Interior / Parking / Crew Park / Truck/Equip / Holding / Catering / Hospital / General) wit…

- **Credit gate: fix super-user bypass in org workspace**
  The org credit gate in ai-router was bypassed by users with a personal super plan tier. The gate read profiles.plan_id === 'super' (Mark's personal user profile) and wrapped the entire org balance check in if (!_isSuper), meaning a super-tier user could call AI in any org workspa…

- **Credit gate: extend to non-billable tasks in org workspace**
  Follow-up to 69bd70a (2026-05-27, credit-gate-super-org-bypass). The previous fix blocked billable tasks in depleted orgs, but tasks with billable:false in TASK_CONFIG still bypassed the gate entirely — the outer condition was if (config.billable && user).

- **Communications: AI Agent Line + Company Line product selection**
  Restructures the Communications page to offer two clearly-distinguished line products instead of a single org-only flow. Adds a line_type column to phone_lines (values: dedicated_company | shared_ai), a dual-tier plan gate (personal ai_agent_line permission for Solo Max + existin…

- **Communications: Provisioning state machine + Blooio removal**
  Full Communications purchase UX overhaul per Mark's 9-point directive. Removes all "Blooio" from user-facing copy everywhere; gates line access through subscription tier only (upgrade CTAs go to /settings.html?tab=billing); adds a line_provisioning_status state machine on both or…

- **Cloud Storage Write Integration — Google Drive Phase 2 + Full Dropbox**
  Wires the three auto-save triggers (call_sheet_publish, purchase_order_finalized, signed_document) so files automatically flow to Google Drive and/or Dropbox when those events occur. Adds a complete Dropbox integration in parallel with Drive: org-level OAuth (owner connects once,…

- **Adobe Acrobat Sign Integration + E-Sign Provider UI Cleanup**
  Replaces the Adobe Sign adapter stub with a complete implementation against the Adobe Acrobat Sign v6 REST API. Builds the full OAuth flow as a popup (start + callback edge functions, encrypted tokens, region-aware api_access_point handling, automatic refresh-token rotation).

- **Fix: Schedule strip removal — intent misclassification, wrong project context, missing search tool**
  Three bugs triggered by "Can you remove the indoor subway schedule strip" sent in the "CD PROD | KOH" iMessage thread. Bash replied with "Couldn't find a sheet called 'call sheet' on All The Way" — completely wrong intent, wrong project, wrong tool. Root cause: the comms_orchestr…

- **Routes — Universal Right-Panel Widget Chrome**
  Adds the universal widget panel chrome to routes.html so it matches sheets, docs, and all other pages. Mobile layout is now 3-panel: left (Drivers) + center (Routes content) + right (universal widgets). Desktop: right panel hidden — right-panel.js handles the desktop drawer path …

- **Routes MV2 C3 — Pin-Tap Card + Long-Press Drop-Pin Menu**
  Two new MV2-only map interactions, both behind body.routes-mv2 guard:

- **Routes MV2 — List View Sheet (C5)**
  ### Mobile (MV2)

- **Routes MV2 — geocode-exact POI Fallback Pass**
  ### Problem

- **Routes MV2 — Geocode-Exact + SL Pin Card Editing + Role Enum**
  ### 1 — js/geocode-exact.js — shared exact-address utility

- **Routes MV2 — Day Selector**

- **Routes Mobile v2 — C2: Full-Screen Map + Floating Top Tabs**
  Implements Checkpoint 2 of Routes Mobile v2, strictly behind the ?mobile-v2=1 flag. Baseline path byte-identical to the working 930cf93 shared-engine state.

- **Routes Mobile v2 — C1: Feature Flag Plumbing**
  Adds the feature-flag plumbing for the incremental Routes Mobile v2 rebuild. An inline <script> immediately after <body> defines window.isMobileV2() and sets body.routes-mv2 when the flag is active. Zero visual change — the existing swipe-track layout is untouched on both code pa…

- **Routes Mobile — Align with Universal 3-Panel Chrome**
  Aligns routes.html's mobile chrome with the universal shared pattern used by dashboard, sheets, docs, and all other pages. Routes was the only page with a custom 2-panel driver-board left panel diverging from the app-wide standard.

- **Revert: routes.html mobile-first shell — stable baseline deploy**
  The mobile-first refactor of routes.html (4 commits plus 4 iOS-Safari fix attempts, total 10 commits spanning 2026-05-25/26) produced a blank white screen on iPhone Safari that could not be resolved without root-cause diagnosis. Rather than continue patching, the mobile shell is …

- **Routes Mobile — Migrate to Shared initMobilePanels Engine**
  Replaced routes.html's one-off initMobileSwipe() with the app-wide shared initMobilePanels() engine from js/mobile-panels.js — the same engine used by dashboard, docs, documents, and sheets. Routes was the only page using a custom swipe function; it was missing critical iOS Safar…

- **Routes Mobile — Revert Universal 3-Panel Chrome**
  Reverts commit 508906c (universal 3-panel chrome alignment). That commit caused a blank white center panel on Mark's iPhone Safari — the header and bottom nav were visible but all routes content (tabs, map, panels) was empty.

- **Routes — Drivers Section Restored to Left Panel**
  e7c3873 (universal left nav wiring) moved the Drivers panel content to hidden stubs, breaking the queued "Drivers panel project dropdown" item. This commit restores the Drivers content as a second section in the left panel, below the universal nav tiles — satisfying both requirem…

- **Routes — Drivers Panel Project Selector**
  Adds a project dropdown at the top of the Drivers panel (#swipe-left-panel) so users can select a project from inside the panel without navigating away. Previously the panel showed "Select a project first" with no mechanism to do so.

- **Routes — 4-Panel Swipe Restructure**
  Mark's structural correction: the universal nav-buttons panel must be its own panel (far-left), not stacked inside the same panel as Drivers.

- **Remove deprecated mobile apps-grid menu**
  Removed the deprecated Pre-Pro / Production / Wrap phase-tabbed apps-grid popup from the mobile nav bar on every page. The menu was a bottom-sheet with a grid of icon+label nav buttons, reachable via a 4-square "Apps" tab (Tab 4) in the shared header's mobile tab bar. It was a le…

- **MV2: C5 visual polish + C6 default-on for mobile viewports**
  Final stretch of the C1–C6 mobile-v2 sequence. C6 flips the MV2 layout to default-on at viewports ≤767px — no flag needed. An opt-out via ?mobile-v2=0 (or localStorage.routes_mobile_v2='0') lets anyone with an issue fall back to the legacy stack-view. Desktop (≥768px) is unchange…

- **2026-05-26 — KOH group chat: Bash replying to ambient chatter + error fallback bleed**
  Two bugs caused Bash to reply to Ennio's "Copy thanks guys, just finished moving everything! See yall in the morning":

- **Google Drive Integration**
  Org-level Google Drive integration. The org owner connects Drive once via GIS popup OAuth; every org member benefits — the AI (iMessage, chathub, AI search bar) can search, list, and read Drive files, and the AI plus manual "Save to Drive" actions can write files back. Saves are …

- **Unsplash OAuth — Connect button + encrypted token storage**
  Builds the full Unsplash OAuth connect flow mirroring the Gmail integration. Any org member can click "Connect Unsplash" in the Integrations tab, approve access in the Unsplash popup, and have the org's access token stored encrypted server-side. The image search in comms_image_se…

- **Unsplash API — key wired + compliance fixes (comms_image_search)**
  The comms_image_search handler in ai-router already had the Unsplash API call stubbed out but the UNSPLASH_ACCESS_KEY secret was never set and the implementation was missing two items required by Unsplash's API guidelines: the download-trigger event and UTM-tagged attribution lin…

- **Toll petty cash AI workflow + Part 1 verification on KOH V2**
  Part 1 verified end-to-end on the live KOH V2 project that the existing toll calculation (pickup_lists.metadata.toll_estimate saved by fetchAndRenderTolls) plus the two AI-driven PO workflows still work after recent routes-page changes. Part 2 added a third AI workflow — "add the…

- **Fix: TO-DO widget wired to real todos table with assignee priority**
  The TO-DO card in the project-details right rail was displaying generic derived workflow items ("Publish call sheet", "Send onboarding to N crew", "Set department call times", etc.) instead of the project's real todos. The code already had a todos table query, but it was missing …

- **Replace Tailwind CDN with local purged stylesheet (all 44 pages)**
  Every page in the app loaded https://cdn.tailwindcss.com — the Tailwind Play/JIT CDN build. This has two costs paid on every page load by every user:

- **Spotlight floating controls transparent + todos header parity**
  Three fixes in one session. (1) The spotlight search bar showed a dark rectangular box behind the 4 floating icon buttons in dark mode — caused by html.dark #project-search-input-wrapper { background-color: #181b24 } in dark-mode.css, which was removed. (2) The .cd-fc-btn buttons…

- **feat(ai-agent): schedule-aware shot list import + model correctness fixes**
  Added schedule-aware behaviour to the analyze_shot_list_file tool. When a project already has a shooting schedule with scene strips, the tool now automatically links each imported shot to the correct existing shoot day by matching the shot list's scene numbers against the schedul…

- **feat(ai-agent,doc-intelligence): reference photo extraction for shot list import**
  Added reference photo scraping to the analyze_shot_list_file pipeline. When a shot list document (PDF or image) contains embedded reference or storyboard images, the AI now identifies which shots have associated photos and the pipeline extracts those images, uploads them to the r…

- **fix(ai-agent): cache extracted shots in proposal to eliminate non-deterministic confirm re-extraction**
  analyze_shot_list_file was calling doc-intelligence action:analyze twice — once on the proposal pass and again on the confirm pass. Gemini's response is non-deterministic under load, so the confirm pass sometimes returned 0 shots even when the proposal returned 15. This caused "N…

- **Shoot Locations — reusable map component + satellite, measure, find-nearby, golden hour, drive times**
  Built the foundation for the approved "Shoot Locations map expansion." Introduced js/crewdeck-map.js — a reusable CrewDeckMapPanel component that can power both Shoot Locations and future Pickups redesign. The component handles satellite toggle, measure tool, find-nearby POI sear…

- **Shoot Locations — Scout candidates, weather badges, company move strips, Pickups map toolbar**
  Completed all four punch-list items from the map expansion:

- **Schedule UI — time picker, location chip, routes bidirectional sync**

- **Routes Mobile-First Layout + Shared Apps Tab Icon**
  Two related mobile UX improvements. First, the routes page is now mobile-first: on ≤767px screens the fixed swipe-track is replaced by a normal scroll layout, the map (#pickup-route-map-wrap) bleeds edge-to-edge and grows to 44 vh so it reads as the primary surface, and the Drive…

- **Fix: Cross-Org Routes Showing in Wrong Workspace**
  Users who belong to multiple organizations were seeing routes from a different org when viewing routes.html in the Good Company (or any other) workspace.

- **Routes: Cameras Pill + Fullscreen Map Overlay + Panel Collapse; Canvas: Toolbar Bug Fix**
  **routes.html** — Three changes bundled into one routes.html commit:

- **Routes — Apple Maps Mobile Shell**
  Full Apple Maps-style mobile layout for routes.html. On ≤767px the map becomes a fixed full-screen background, a translucent pill tab bar floats over it at the top, and a 3-detent bottom sheet slides up from below carrying the content. The sheet has:

- **Route Tolls Display + Toll PO AI Tools**
  Surfaces toll estimates on the Routes page and wires two new AI workflows for toll PO operations. Toll data comes from the Google Routes API v2 (routes.googleapis.com/directions/v2:computeRoutes) via extraComputations: ["TOLLS"], which returns estimated toll prices per leg and pe…

- **Vehicles: vendor + PO line-item links + inline rental-PO create**
  Promotes the project_vehicles shape from "registry + counter" to a first-class three-way link: **vehicle → vendor → PO → PO line item**. Production-side users can now register a rental against a real vendors row, point at the exact po_line_items row that bills it, and — when ther…

- **project_vehicles table + per-vehicle toll scaling**
  Adds a first-class project_vehicles registry table and uses its active-row count to scale toll cost estimates everywhere they're surfaced (per-leg breakdown, per-route total, route-list pills, aggregate banner, and the toll-log amount written into POs / petty cash). Production-si…

- **Fix: Comprehensive project-details dark mode readability pass**
  Comprehensive dark mode readability pass over the project-details view (the expanded project card and all its widgets). Four categories of issues were fixed: (1) shoot-day timeline tabs with status tints (Today / Future / Past) showed vivid green/amber/gray light-mode backgrounds…

- **Fix: Download All POs HTTP 546 — streaming ZIP via fflate**
  Download All POs on project f7b00a95 (GRINDR x M · 26030) returned HTTP 546 WORKER_RESOURCE_LIMIT ("Function failed due to not enough compute resources"). This is a regression of the May 22 fix: that fix set PO_EXPORT_CHUNK = 20 based on empirical testing with a heavy-template pr…

- **Fix: RLS on pickup_lists and pickup_items**
  pickup_lists and pickup_items had **RLS disabled** (relrowsecurity = false). Three open qual: true policies existed on each table but were never enforced. Any caller with the Supabase anon key could read and update every row in both tables across all organizations.

- **Mobile left-panel Routes icon: truck → route glyph**
  js/mobile-panels.js (MOBILE_LEFT_CATEGORIES) still had the original filled truck SVG for the Routes tile. Replaced it with the same origin-circle + S-curve + destination-pin glyph (stroke="currentColor") that the desktop nav and the mobile app drawer (header-nav.js) use, so all t…

- **Fix: Mobile day-tab strip — all days now reachable**
  On mobile, a 3-day project only showed Day 1 and Day 2; Day 3 was unreachable. The root cause was overflow-x: hidden on .project-detail-container in the mobile media query, which clipped the #shoot-day-tabs-container even though the container already had overflow-x: auto and -web…

- **Mobile day-selector dropdown**
  On mobile viewports (≤767 px) the horizontal scrolling day-tab strip inside the project-detail panel is replaced by a full-width custom dropdown. The trigger shows the currently selected day name and date (e.g. "Day 2 · Sun, May 24") with a rotating chevron. Tapping it opens a bo…

- **Lithic Virtual Card Integration**
  - **Migration** adds Lithic columns to petty_cash_envelopes and a new   lithic_webhook_events audit table. - **lithic-card-create** edge function (JWT required) handles create,   reveal, and update (pause/resume/close) operations. Gated: if   LITHIC_API_KEY is absent, returns a f…

- **Feat: Job Code field in project-detail edit mode**
  Added an editable Job Code field to the shoot-day core-info edit view (the panel that opens when you tap the pencil icon in the project details left column). The field sits below Day Length, pre-populates with the project's current job_code, and saves to projects.job_code (separa…

- **Fix: consolidate GoTrueClient — eliminate 4 duplicate instances on dashboard load**
  Dashboard load was triggering "Multiple GoTrueClient instances detected in the same browser context" four times — meaning 5 total GoTrueClient instances were created on every page load. Each extra instance adds ~50 ms of redundant auth initialisation and risks token-refresh races…

- **Fix: Delete Day button, profile address autocomplete, Google avatar upload gate**
  Three UI fixes requested by Mark. FIX 1: the Delete Day / Rename Day / Duplicate Day context-menu buttons in the dashboard project-details shoot-day tab bar were silently broken — clicks fired but nothing happened. FIX 3: the profile Mailing Address Street field now has Google Pl…

- **Fix: crew-add from shared contact — three root-cause bugs**
  After the credit gate was restored, sharing a contact card and saying "Bash can you add him as a production assistant for tomorrow please" still failed. The error changed from the credit-depletion fallback to "Hit a snag pulling that up — want me to try a different angle?" — mean…

- **Fix: org credit depletion message, vCard probe pass, crew-add deflection**
  Three bugs observed in the KOH iMessage group chat ("CD PROD | KOH"):

- **fix(credits-modal): dark mode support for org credit modal**
  The credits modal (opened from the header credit pill) rendered with a white background and light cards on dark-mode pages, causing a jarring clash with the dark UI and unreadable low-contrast text. Added html.dark CSS overrides to the injected <style id="cdcm-styles"> inside _en…

- **Feat: Contact info scope picker (day vs. all days) + right-click dark mode**
  Two changes in one deploy:

- **Cmd+/ → spotlight; Cmd+// → full ChatHub**
  Two keyboard shortcuts for the AI surfaces:

- **Calendar — workspace switcher now works**
  The workspace switcher in the calendar page header was stuck on the personal workspace — clicking an org had no visible effect. Two bugs combined to cause this. First, loadAdminPortal called populateHeaderUser() instead of populateHeaderData(), so renderWorkspaceSwitcher was neve…

- **Fix: Avatar dropdown menu dark mode text contrast**
  The avatar dropdown menu (#user-menu-panel) had poor dark mode text contrast for regular menu items and section labels. The .user-menu-item CSS class sets color: #374151 (dark gray), which is nearly invisible on the dark panel background (#181b24). The section labels ("Account", …

- **Fix: AI-Created PO Line Items Reset to Zero on Save**
  When the AI created a PO from an attachment (e.g. a PO log image), it correctly extracted and stored amount values for each line item, but in cases where it couldn't determine an explicit rate, the rate column was stored as null. The PO page's pwRecalcRow function runs immediatel…

- **AI "turn on dark mode" now applies immediately**
  When a user asked the AI to "turn on dark mode" via the spotlight search bar, the AI called update_user_setting (which wrote to profiles.user_settings.appearance.dark_mode), replied "Done — switched to dark mode," but the page visually stayed in light mode. Root cause: the generi…

- **Action Proposed card: compact layout with inline parameter rows**
  The "Action Proposed" confirmation card previously showed only a short title and Confirm/Cancel buttons, leaving a large empty rectangle — visually heavy but information-light. Users had to scroll up to remember what they were confirming.

- **URL state persistence across all pages**
  All main pages now persist the active view/tab into the URL via history.replaceState so that refreshing the page restores the same view without causing a page reload on every tab click. On load, each page reads the relevant URL parameter and initialises to that view before render…

- **Stripe Live Cutover — Credit Packs + Subscriptions**
  Flipped CrewDeck's Stripe integration from TEST → LIVE mode. All credit-pack and subscription plans now point to live Stripe products/prices. The live webhook endpoint is registered, the frontend loads the live publishable key, and the backend runs with the live secret key. All S…

- **2026-05-24 — Schedule: right-click strip context menu — Rename and Delete**
  Right-clicking any schedule strip now shows a **"This Strip"** section at the top of the context menu (before the existing Color Change / Color By / Configure Strip Types items):

- **Routes: "Sort by schedule" + Schedule: "Sort by route"**
  Two cross-linked sort features connecting the Routes and Schedule pages:

- **2026-05-24 — shooting-schedule: consolidate talent to single section with full names + call times**
  The shooting schedule page showed talent in two places:

- **2026-05-24 — sheets-export-pdf: apply strip color overrides to schedule section**
  Exported PDFs (call sheet / run of show) were rendering schedule strips with hardcoded default colors (SCHEDULE_TINTS) even when the user had changed strip colors via the "Change Strip Color" picker on the schedule page.

- **2026-05-24 — sheets-export-pdf: use designated sheet workbook for all sheet types**
  The sheets-export-pdf edge function previously always loaded a generic workbook from sheet_templates (looked up by url_slug). This meant the exported PDF would not reflect any org-specific customisations (column widths, row heights, header layout, extra branding cells) the user h…

- **2026-05-24 — Schedule: Toolbar redesign + right-click strip context menu**
  **1. Toolbar cleanup** — Removed the Strip/List view toggle pill (strips-only always), removed the Group By dropdown, Color By dropdown, Sticky Group button, and Configure Strip Types gear from the toolbar. The toolbar now contains only the icon-only Export PDF and Import buttons…

- **2026-05-24 — Schedule PDF: use call_sheet template for parity with sheets page**
  The schedule page's "Export PDF" button was producing a stripped-down schedule-only PDF (just TIME / ACTIVITY / LOCATION rows) because it passed sheet_type: 'schedule' to the sheets-export-pdf edge function. The sheets page uses the full call-sheet template (_buildSheetPdf) which…

- **2026-05-24 — analyze_schedule_file: department + individual call time assignment**
  When a shooting schedule is imported via analyze_schedule_file, call times are now recognized and assigned to the correct targets — matching the same three-tier hierarchy the shooting schedule page uses when displaying talent call times.

- **2026-05-24 — Fix: Run of Show designation banner visibility + PDF download**
  Two fixes to the Run of Show designation banner on the schedule page:

- **2026-05-24 — Schedule AI: real-time presence, strip highlights, per-step approval, day context**
  Four coordinated improvements to the Schedule AI experience.

- **2026-05-24 — Schedule AI: approval gate (Approve Plan / Reject / New Version & Approve)**
  When any Schedule AI tool returns a would_* proposal (strip moves, day changes, reorders, deletes, etc.), the batch confirmation modal now presents **three options** instead of one:

- **Routes: map-forward redesign for Shot Locations + Picture Cars; new route nav icon**
  Redesigned the Shot Locations and Picture Cars views on routes.html from a plain list layout to a Google Maps-forward layout — full-bleed map canvas as the background, translucent glass overlay panel pinned to the left (300px, backdrop-filter: blur), styled after Google Maps dire…

- **Schedule / Run of Show — project title placeholder parity with Call Sheet**
  The Schedule / Run of Show system template header cell had "v":"" (empty cached value) and no "t" type flag, while the Call Sheet system template correctly sets "v":"Sample Music Video" and "t":1. Both already had =CREWDECK.FIELD("project.title") as the formula. This migration al…

- **2026-05-24 — Header: plan badge + Super Admin panel in populateHeaderData**
  Pages that use populateHeaderData (from header-nav.js) — including shooting-schedule.html and other non-dashboard pages — were missing:

- **Header AI search: route all queries through ai-agent (full tool registry)**
  The header AI search previously called the standalone ai-spotlight-search edge function for any query that wasn't a page-nav or how-to. That function had its own system prompt and made direct Gemini calls with no tool registry — so the AI could answer questions but couldn't take …

- **Gmail: Full Integration — Per-User OAuth + Server-Side Draft Creation**
  Full Gmail integration: each user connects their own Gmail account from Settings → Integrations, and both the AI (iMessage + chathub) and the emails-page Send button create drafts server-side via the stored token.

- **Replace Supabase OAuth redirect with GIS signInWithIdToken + Gmail popup flow**
  Previously, Google login used supabase.auth.signInWithOAuth({ provider: 'google' }), which redirected the browser through https://afbclfjxwvqkfzjwpaec.supabase.co/auth/v1/authorize — making the Supabase project domain visible to users and requiring Supabase's $10/mo Custom Domain…

- **Emails: Call Sheet PDF Attachment + AI Deep-Link Draft Flow**
  Two improvements that complete the Gmail draft workflow end-to-end.

- **2026-05-24 — Day-Specific Crew Overrides (Phase 1)**
  Restructures crew attributes from **global (per crew per project)** to **per-day overrides**, backed by a new crew_day_overrides table. Right-clicking a dynamic range cell on a specific day now lets you exclude that person from *that day only*, hide their contact info for *that d…

- **Backup Manifest — Day-Specific Crew Overrides**

- **Dashboard widgets: real project todos in TO-DO + clickable headers → relevant pages**
  Two related dashboard widget improvements:

- **crew-list avatar menu: full parity with shared header**
  The avatar/profile dropdown on crew-list.html was missing the **ORGANIZATION → Organization Dashboard** section that appears on all other pages (dashboard, routes, etc.). The root cause: updateUserUI() called populateHeaderUser without the opts argument, so isAdmin and isOwner de…

- **Auto-open today's shoot day tab on project open**
  When opening project details, if the user's local date matches one of the project's shoot days, that day's tab is now automatically selected instead of always defaulting to the first chronological day. The comparison uses the user's local midnight (not UTC) so "today" is correct …

- **AI: get_route_stops tool + weather-along-route routing**
  Bash was responding to "weather along the shoot route?" with "I don't have your shoot route on file." Root cause: no tool existed to read back existing shot_location routes and their stop addresses. Added get_route_stops to ai-agent, added PHRASE MAP routing rules, fixed load_sch…

- **Address autocomplete on every address field; manual locations promotable from dashboard**
  Three connected changes so every address field in the Routes/Schedule/Dashboard surfaces uses Google Places autocomplete, and so a location entered via the schedule's "manual address" path can be promoted to a real org locations record from the dashboard:

- **Fix: "look for any spot" + venue_recommendations spawn_task override**
  Follow-up to 61ce001 / 0d2534a (same session). After the previous fix, two phrasings from the KOH thread still routed to spawn_task (ai-task-worker → ai-agent, no web search) instead of comms_web_search (Claude native web_search_20250305):

- **2026-05-23 — Stripe pre-cutover: webhook, ledger, Platform Financials, polish**
  | Layer | Change | |---|---| | DB | New public.stripe_purchases ledger (UNIQUE on stripe_pi_id) | | DB | New stripe_webhook_events idempotency log | | DB | Super-admin SELECT RLS on stripe_purchases | | Edge fn | stripe-webhook redeployed with --no-verify-jwt | | Edge fn | stripe…

- **Stripe Phase 2 — Subscription Webhook Test Matrix + Bug Fixes**
  Ran the Phase 2 subscription webhook test matrix (S1–S6) from docs/stripe-cutover/2026-05-23-phase2-and-live-cutover-runbook.md in Stripe TEST MODE. Uncovered and fixed two bugs in stripe-webhook:

- **Sheets PDF resolver — full parity with inline sheet display**
  The sheets-export-pdf edge function had its own hand-rolled resolveField() switch that had drifted from js/sheets-field-resolver.js (the authoritative browser-side resolver). Six confirmed divergences caused the PDF to show different/missing data compared to the live inline sheet…

- **Org credit hard gate — block AI when balance is depleted**
  When an org's AI credit balance reaches zero (or negative), every AI capability in the org workspace is now blocked at the server with INSUFFICIENT_CREDITS (HTTP 402), and the frontend renders an in-app "Out of AI credits — Buy more credits" card that links to /organizations.html…

- **Fix: Crew Phone Numbers Format Correctly on Mobile**
  On mobile (shared call sheet view), crew-table PHONE column was rendering raw database strings — e.g. "757 553 2945" — instead of the formatted "(757) 553-2945" that desktop showed. The PRODUCTION CONTACT at the top of the call sheet formatted correctly on both platforms because …

- **GRINDR x M — PO Paid-Status Reconciliation + Vendor Display Alignment**
  Two reconciliations for the GRINDR x M project (org 89 — GOODCOMPANY, project id f7b00a95):

- **fix(sheets): CREWDECK.FLEX priority_list blank on Day 2+ of multi-day call sheets**
  On KOH V2's multi-day call sheet, the flex cell (configured as a priority_list of brand_logo_url → brand_name → client_name) displayed correctly on Day 1 but was blank on Day 2 and all subsequent days. Four root causes across two sessions:

- **Emails: Gmail Draft E2E + Dept Crew Counts + Default Recipient Config**
  Three cohesive improvements to the emails page.

- **fix: confirmed destructive deletes not firing + batch_delete_purchase_orders**
  When the AI presented a batch of 5 PO deletions and Mark confirmed "Yes please delete those duplicates", the AI called delete_purchase_order (single-PO) for the first item and sent "Are you sure? Reply YES to confirm." Mark said "Yes." The bare "Yes" had no @Bash mention, so it b…

- **fix(ai-agent): vendor_capabilities .catch crash in create_vendor**
  create_vendor crashed whenever it tried to seed vendor_capabilities rows after creating a new vendor. The chain .insert(capRows).throwOnError().select().maybySingle().catch(...) fails in the Deno edge runtime because PostgrestMaybySingleResponse is a custom thenable — it exposes …

- **Fix: "call time tomorrow" false denial + SerpAPI comments removed**
  **Session also includes commit 61ce001** (web search misroute fix) deployed earlier this session — that commit is documented in 2026-05-23-web-search-misroute-fix.md.

- **AI Agent: create_email_draft Tool + Enhanced list_email_templates**
  Two AI agent improvements that extend the emails workflow.

- **Dashboard widget realtime refresh**
  Dashboard widgets (project tab + sidebar) now refresh their view immediately when the editing user exits edit mode, and update in realtime for every other org user viewing the same project. Previously, after editing Mission Brief, Day Schedule, Weather, Hospital, Crew Summary, et…

- **vCard ingestion (text contacts → crew add) + group-rename webhook fix**
  Mark spec'd a new capability: text the AI a contact vCard + "add this person to the crew for [project]" — the AI parses the vCard and creates the crew row with name/email/phone/(title→role)/(org→dept). Built end-to-end. Then a separate bug surfaced when Mark tested in a renamed g…

- **Stripe Billing Phase A — Producer / AD / Solo Max tiers + per-tier route gating**
  Phase A of the Stripe billing rebuild. Extends the existing tier ladder from solo / production / studio to **five** personal-and-org tiers:

- **Header AI search — step-list nav answers + markdown stripping + deterministic how-to resolver**
  Mark's review of the original header inline answer ("how do I make a call sheet in this?") flagged three real problems:

- **Sheets: source compatibility graph + multi-source ranges + diagnostics + auto-fix**
  Mark called out the pattern: dynamic-range sources have natural relationships — strips + shots compose, but full schedule + prelim conflict because one subsumes the other. The pattern was implicit (in Mark's head); the codebase had no representation, so the system couldn't detect…

- **Sheets: right-click menu — no text-select bleed, no AI items, no scroll, picker bootstrap**
  Four related changes to the cell context menu:

- **Per-edit revisions history + undo audit trail**
  Every autosave on a sheet now writes a row to a new sheet_revisions table — full content snapshot + a per-cell diff vs the prior revision + a short human label. The History modal (toolbar clock icon) lists those revisions newest-first; each row carries an "Undo this edit" button …

- **Platform Settings: AI Analytics tab + single Beta tab**
  Two Mark-requested changes for the platform settings page:

- **Schedule template — TALENT and PRELIM RUN OF SHOW as visibly distinct dynamic ranges**
  The top half of the Run of Show template shows the day's prelim timeline on the left and the talent / cast list on the right. They were already two separate dynamic_range overlays (timeline at cols 0-7 → day.run_of_show, cast at cols 8-11 → day.cast), but neither carried a sectio…

- **Schedule dynamic-range borders wrap actual emitted cells, not the pre-allocated region**
  The dashed amber border around each schedule dynamic range now wraps only the rows the range actually emits, not the legacy 8-row pre-allocation. With Mode A's single-prototype render, PRELIM RUN OF SHOW = 2 rows (title + 1 strip), TALENT = 3 rows (title + headers + 1 cast row), …

- **Schedule template — overlay-style dynamic ranges + centralized strip colors**
  Multi-step work to make the schedule system template render data-driven sections via the existing dynamic_range pipeline, plus centralize the stripboard color map so timeline tint / color-key legend / formula lookup all read from one source.

- **Mode A: schedule dynamic ranges render title + one prototype row, always in order**
  In Mode A (template editor), every schedule dynamic range now renders exactly like a call-sheet dynamic range: title row, column header row, ONE row of =CREWDECK.RANGE(...) placeholder formulas. Previously schedule overlays force-flipped _exampleMode to false, which sent Mode A d…

- **Schedule Mode A: empty rows collapsed + color palette as a real dynamic range**
  Two coordinated Mode A polish changes:

- **Schedule Import — per-day schedule_versions (fix bigint:null)**
  analyze_schedule_file now resolves schedule_versions PER SHOOT DAY, the same way the page-side handleAddVersion does. The version-creation moved from a single project-wide block (pre-loop) into the per-day loop (after we have shootDayId).

- **Show strip + summary times in 12h AM/PM on shooting-schedule.html; harden call-sync triggers against mixed time formats**
  Mark hit the schedule page rendering military (24h) time after the earlier call-time sync change. He wants AM/PM display everywhere — strip chips, Mode A meta line, Run-of-Show summary, PDF export.

- **Schedule page — desktop UX polish**
  Mark reported "I can't scroll in the schedule page" and a lot of visible desktop UX bugs (sparse spacing, off-screen content, weak empty states).

- **Schedule page — desktop polish round 2 + page-loader scroll lock fix**
  Round 2 follow-up to 2026-05-22-schedule-desktop-polish.md. Mark reported two remaining issues after the first density pass:

- **Routes page expansion — Pickup/Runs · Shot Locations · Picture Cars**
  Renamed pickups.html → routes.html and expanded the page to support three top-level route types — the existing Pickup/Runs workflow, plus new Shot Location Routes (sequences of filming locations, with a one-click "Load from Schedule" that pulls Scene Start strips off shooting_sch…

- **Robust PDF Extraction — pdfjs + binary fallback**
  Added server-side text extraction with pdfjs-dist to analyze_schedule_file / analyze_shot_list_file. The PDF helper now sends BOTH a deterministic text track AND the binary PDF to doc-intelligence, so the model has two signals:

- **Rename Pickups page to Routes**
  Renamed the Pickups page to **Routes** end-to-end. The page file pickups.html is now routes.html, the AI surface file js/ai-engine/surfaces/pickups.js is now routes.js, and every navigation link, dashboard widget, redirect stub, edge-function tool description, and notification de…

- **Fix: Download All POs on 50-PO project (HTTP 546 WORKER_RESOURCE_LIMIT)**
  Download All POs on a project with 50 POs returned HTTP 546 WORKER_RESOURCE_LIMIT (Function failed due to not having enough compute resources). The Supabase edge function export-pos-zip was hitting the runtime's memory/CPU ceiling because:

- **Subscription plan credit allocations rebalanced**
  Mark-approved rebalance of subscription plan credit allocations after the 2026-05-22 credit-pricing reconciliation audit. Two issues with the prior values:

- **KOH V2 call sheet layout collision + bulk_import_crew show_on_call_sheet default**
  Two related fixes around Mark's KOH V2 call sheet report:

- **Move "Import & Analyze" into the File menu (sheets + docs)**
  The "Import & Analyze" button has lived on the page editor body toolbar in both sheets.html and docs.html since 2026-05-10. This move re-homes it as a menu item under the **File** dropdown on the menubar (next to **Edit**), aligning with spreadsheet/office conventions where bulk …

- **Header AI search — turn-1 always inline; turn-2 opens chat hub seeded**
  Refines the escalation rule per Mark's directive: the header AI search is a **turn-1 inline surface**. Every first submission renders an answer INLINE — either a page-nav tile (page-finding queries, the fast path shipped earlier today in [2026-05-22-header-ai-search-page-nav.md](…

- **Header AI search — page-nav fast path with inline styled app tiles**
  When a user types a page-finding query into the header AI search bar ("im looking for the crew list page", "where is the budget", "take me to schedule", "find the POs page"), we now resolve it entirely client-side: render a short friendly sentence + a styled tile that mirrors the…

- **GRINDR project moved to new GOODCOMPANY org; org 51 renamed to King Of Hearts**
  Split the existing GOODCOMPANY org (id 51) into two orgs at Mark's request:

- **Docs page: always-visible org templates + draggable org logo**
  Two UX fixes to docs.html. (1) Org-level document templates (Templates, E-Sign, Sent, Signed tabs) now remain visible when a project is selected — previously initializeProjectView hid the entire doc-list-container, making it impossible to access org templates without deselecting …

- **docs: Mode B resolved-view for project-scoped template editing**
  When docs.html is opened with ?id=<projectId> (Mode B / project-selected), clicking a template card now opens the TinyMCE editor with every [Placeholder] already filled in from real project data — rather than showing bare bracket tokens or placeholder pills. Each resolved value i…

- **Default header-nav config — new signups + backfill existing users**
  New users now inherit the same header-nav button layout as mzgower (reference account) instead of starting with empty / null nav arrays. Existing users whose nav columns were NULL or empty were backfilled to match the same defaults; users with any customization were left untouche…

- **Dashboard — Day Schedule edit no longer jitters / drops out of edit mode while typing a Location**
  Reported: on the dashboard, opening the Day Schedule edit view ("Mission Brief" area) and typing into a Location name input caused the widget to "jitter and go out of edit mode" — the input would re-render mid-keystroke, swallowing the typed text and dropping the user back to the…

- **Fix crew save: `payment_type=null` AND `payroll_route=null` violated NOT NULL constraints**
  Mark hit a save error in the Crew List on KOH V2:

- **Crew list: letter-by-letter Realtime sync in both view and edit mode**
  When one user is typing in edit mode, viewers now see the changes appear in the display view within ~200ms — no page refresh, no full re-render, no disruption to anyone's open edit row.

- **Crew list: realtime autosave per row + bulk-save no longer aborts on first bad row**
  Two related changes to the project-view crew list edit experience:

- **Crew list: position field combobox + dept autofill, modal address w/ Google Places, TBD filter**
  On the crew list inline-edit row (both project and master views), the Position field now opens the custom searchable combobox sourced from the org's crew_positions registry — same UI used by the Name and Department fields. When a user picks a position from the dropdown, the row's…

- **Crew list: drag rows to reorder — writes to the same display_order as Settings**
  In project view with "Structure" sort selected, each crew row now shows a 6-dot drag handle on hover (left side of the Name column). Dragging a row to a new position updates departments.display_order and crew_positions.display_order in the DB — the exact same columns that the Set…

- **Crew batch add — reliability fix (chathub + iMessage)**
  Mark hit two P0 bugs on 2026-05-22 while pasting a multi-person crew list into the AI:

- **Communications page stuck on loader — phone gate hidden behind it**
  Reported by Mark: crewdeck.io/communications never advanced past the initial CrewDeck-logo + progress-bar loading screen. The page was fully loaded under the hood; the bug was a z-index ordering issue between the page-loader overlay and the phone-gate modal that the comms phone-g…

- **comms_rename_chat: preserve verbatim name with pipes/slashes/special chars**
  Mark reported that texting Bash AI "Bash Rename this chat to CD PROD | KOH" renamed the thread to "CD PROD |" — the pipe and everything after it was silently dropped, and the AI's confirmation message echoed the truncated value ("Done — renamed to 'CD PROD |'."). Root cause: Clau…

- **Chat hub rail tabs no longer overlap + correct call-sheet guidance**
  Two fixes from Mark's review of the chat hub:

- **Chathub confirm cards — stop leaking raw tool-call JSON**

- **Traffic Layer + DOT Camera Pins (Canvas + Routes + AI)**
  Adds a dedicated **Cameras** pill alongside the existing **Traffic** pill on both canvas.html and routes.html, plus four new ai-agent tools that let Bash search, surface, and link out to DOT traffic cameras. The canvas-traffic-cams edge function now pulls from Caltrans D4 (511 Ba…

- **nsCreateSheetFromTemplate: scope slug lookup to org + system to survive multi-org users**
  Fixes the "Template not found" toast Mark hit today when picking the Call Sheet template from the New Sheet → From template modal. Root cause: an unscoped url_slug lookup that errored with "more than one row" whenever the user belonged to multiple orgs (the database has one call-…

- **Call Sheet Run of Show — convert to dynamic_range with rowAccent + merge cloning**
  Mark asked for the Call Sheet's Run of Show to behave like the schedule template's PRELIM RUN OF SHOW — auto-expand to N rows, tint each row by strip_type, always render in order. Two code-level additions to the user-marked dynamic_range expander get us there without rewriting th…

- **Mode B auto-save gate + PDF export wiring**
  Two regressions surfaced while QAing the KOH V2 call sheet that needed immediate code fixes:

- **Call-sheet walkthrough — check for existing sheet before creating a new one**
  Per Mark: when the user asks "how do I make a call sheet", the answer should first instruct them to look for an existing Call Sheet for the project before creating a new one. Otherwise users end up with duplicate sheets cluttering the Sheets list.

- **AI Search Bar — Schedule + Shot List Import (server-side, strip-level)**
  Built two new server-side AI tools that accept an attached file in the AI search bar (chathub) and write DETAILED rows into the project's shooting_schedule (with strip-level scene/cast/time data) and shot_list tables. Tested end-to-end on the live AI Import Test project (3eeebe16…

- **Ambiguity ask on target-day-vs-import-date mismatch; bi-directional sync between `shoot_days.general_crew_call` and a 'general' call strip on `shooting_schedule`**
  Three follow-ups to the 2026-05-22 day-merge fix, per Mark's directive ("make sure if there's no day it adds a day, if there's ambiguity like if I say add to day 1 but the date is different then it should ask. Also programmatically we need to link the call times in the system for…

- **analyze_schedule_file: default-merge into existing Day 1 (no parallel day series)**
  The AI schedule importer (analyze_schedule_file tool in ai-agent) was creating a brand-new parallel day series on every run, even when the project already had shoot days. Reported by Mark on the "AI Import Test" project (King Of Hearts org): existing DAY 1 / 2 / 3 - Monday/Tuesda…

- **AI Import — All Formats + Shot Pairing + Dedupe**
  Extended analyze_schedule_file + analyze_shot_list_file with three additions, all in supabase/functions/ai-agent/index.ts:

- **ai-agent: add_crew_to_project + bulk_import_crew now dedupe positions/departments against the org registry**
  The AI's two crew-add tools (add_crew_to_project and bulk_import_crew) used to store role and department as raw free-text strings. The model would happily pass "gaffer" when the org's registry has "Gaffer" — which then created visual duplicates in the inline-edit autocomplete and…

- **Wire footer-AI button into 7 pages that were missing surface scripts**
  Audit on 2026-05-21 found seven pages whose per-page AI surface scripts (js/ai-engine/surfaces/<page>.js) existed but were never loaded in the HTML. Without the surface mount, window.<Page>AIEngine is undefined, the page never gains body.show-footer-ai, and the shared #footer-ai-…

- **Shooting Schedule mobile visual upgrade**
  The shooting-schedule page on mobile was functional but visually rough next to the dashboard: it used Playfair Display for all headings, the day/version tabs forced long "Tech-Scout 2 (2025-09-24)" labels to wrap vertically inside narrow columns, the run-of-show summary card had …

- **Fix: Settings mobile tab list cut off by bottom nav bar**
  On mobile (≤767px), the settings page tab list (#settings-nav-wrapper) had no bottom padding, so the last few tabs (e.g. Roadmap, Beta) were hidden behind the 64px bottom navigation bar and could not be tapped. Added padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)) t…

- **Settings mobile back button (iOS-style)**
  Adds an iOS-style sticky back button nav bar at the top of the settings slide-in content panel on mobile. When a settings tab is tapped, #settings-content-wrapper slides in full-screen and now shows a "← Settings" back button pinned to the top. Tapping it calls closeMobilePanel()…

- **Schedule + Shot List — Mode A project picker & loader parity with budget/dashboard**
  Brought shooting-schedule.html and shot-list.html to visual parity with the rest of the app for two things the user called out:

- **Schedule mobile: pill-row scroll + Run-of-Show legibility**
  Follow-up to 2026-05-21-schedule-mobile-visual-upgrade.md (commit cae12d6). The first pass introduced pill-shaped day/version chips and a polished summary card, but field-testing on a 375 px viewport surfaced five issues:

- **Schedule mobile: full sweep — section heads, talent table, empty state, strip rows, day-totals, time-bank**
  Follow-up to 2026-05-21-schedule-mobile-pill-scroll-ros-legibility.md. The prior pass fixed the five issues the user called out (pill scroll, ROS legibility, event grouping, crew labels, section dividers). This pass is the full-sweep audit the user then requested — every element …

- **Mobile audit: shooting-schedule.html**
  Full mobile audit of shooting-schedule.html matching the 3-panel swipe system already present on purchase-orders.html and budget.html. The page already had the loadMobilePanels() call wired, but was missing the touch/scroll hygiene that prevents iOS gray scroll flicker and jitter…

- **Project detail widgets — force single-column stacking on mobile**
  On iPhone the expanded project detail view was rendering the project widget grid as two columns and clipping the right column at the viewport edge — "Review timeca…", "Collect signed…", "Return equipm…" in the TO-DO widget and "Tech-", "Shoot", "Shoot" in KEY EVENTS were all cut …

- **Project detail mobile — tighten day-pills → command-bar gap**
  The mobile expanded project detail view had ~20px of dead vertical space between the day-tabs pill row and the command-bar action icons. Two stacked padding sources fed that gap: the outer tabs row (pt-1 pb-2 inline) and #command-bar-container (pt-3 pb-3 inline). On a small phone…

- **PO mobile: stats+actions swipe panel (4th panel)**
  Adds a dedicated middle-right swipe panel to the PO page mobile layout. Previously the stats bar was scattered into the right/widgets panel and the toolbar was in the left/nav panel. Now both live in a single "Stats & Actions" panel (panel index 2 of 4), giving a cleaner swipe fl…

- **Remove `#po-stats-bar` from PO mobile view**
  The desktop stats strip (Total Value / PO Count / Avg PO / Committed / Paid / Budget Linked) was rendering adrift on the PO mobile view. mobile-panels.js relocates #po-main and #po-toolbar into swipe panels, but #po-stats-bar was left behind in the original body flow with no usef…

- **PO mobile: filter/sort bar and project selector**
  Adds two mobile-only controls to the Purchase Orders center panel, sticky at the top of the PO card list. Previously, mobile users had no way to filter or sort the PO list (the sortable table headers are hidden on mobile) and had to swipe to the left panel to reach the project sw…

- **PO Card Three-Dot Context Menu**
  Removes the redundant "Edit PO" button from all PO card views (desktop table + mobile cards) — tapping/clicking the card itself already opens edit mode. Replaces the "Download PO" split button with a three-dot (⋮) icon button in the top-right corner of each card header (next to t…

- **Position-based permissions — Phase 6: dead-code cleanup**
  Removes ~1,590 lines of unreachable role-based and page-diagram permission code that Phases 1–5 left behind. After Phase 5 wired the position-based overlay end-to-end, the page-diagram render functions (renderDashboardPermissionMap, renderBudgetPermissionMap, etc.) and the role-c…

- **Position-based permissions — Phase 5: per-project overrides**
  Wires the long-empty project_position_permissions table (created back in the Phase 1 schema migration) into the live system. Org-level position_permissions remain the default; project_position_permissions rows override them on a per-project basis for matching (position, key) pair…

- **Position-based permissions — Phase 3 discovery + Phase 4 runtime enforcement**
  Adds the two remaining pieces of the position-based permissions plan: **Phase 3 Discovery Mode** (clicking an untagged interactive element in Permissions Mode now opens a "Register this element" popover that writes to permission_key_registry and runtime-tags the live element) and…

- **Position permissions — departments, templates, and role-UI strip**
  Extends the Phase 1/2 build ([2026-05-21-permissions-phase-1-2](2026-05-21-permissions-phase-1-2.md)) with two product additions and a deprecation:

- **Position-based permissions — Phase 1 schema + Phase 2 overlay**
  Lays the foundation for [docs/permissions-system-pitch.md](../permissions-system-pitch.md) — position-keyed, button-level permissions. Phase 1 adds three new tables (position_permissions, project_position_permissions, permission_key_registry) and extends the existing get_my_permi…

- **Position-based permissions — page-level master switch**
  Adds a page-level master switch on top of the existing position+department permission system. The convention is reserved keys of the form page.<pagename>.access written into the same position_permissions and department_permissions tables — no new tables. Values match the existing…

- **Permissions Mode banner — custom dark-themed dropdowns**
  Replaces the two native <select> elements in the Permissions Mode banner (the "Choose a position or department…" picker and the "Org default (all projects)" scope picker) with custom, dark-themed dropdown components that match the banner's navy/indigo styling. Native selects rend…

- **Permissions tab — remove Page Diagrams section**
  The Permissions tab in organizations.html previously included a "Page Diagrams" section: a page-picker combobox plus a visual mock-wireframe of the selected page (Dashboard, Calendar, Schedule, Documents, Call Sheet, Crew List, Budget, Invoices, Settings) with clickable overlays …

- **Org Dashboard link: admin/owner only**
  The "Organization Dashboard" entry in the header avatar dropdown was previously visible to **any** user whose current workspace was an organization — including regular members who have no business landing on /organizations.html (the page shows an "access denied" screen for non-ow…

- **Universal new-project/bid chooser modal**
  The "+" / New Project button in the global header now opens the same project/bid/breakdown chooser modal on every page, including dashboard.html. Previously the click handler detected the active dashboard tab (projects vs bids) and skipped the chooser to jump straight to the rich…

- **Dashboard's rich create modal now opens on every page**
  Earlier today (see [2026-05-21-new-project-modal-standardize.md](2026-05-21-new-project-modal-standardize.md)) the chooser modal (Project / Bid / Breakdown) was made universal — every page's "+" button opens the same chooser. After that landed, the user clarified that the **rich …

- **Retire dashboard's inline rich modal; single source of truth**
  Phases 1–4 (see [2026-05-21-new-project-modal-rich-everywhere.md](2026-05-21-new-project-modal-rich-everywhere.md)) put the rich create-modal flow in /js/new-project-flow.js and wired it on every non-dashboard page. Dashboard kept its inline implementation for safety. Phase 6 ret…

- **NDA Tracker — mobile card layout at ≤640px**
  The NDA Tracker table in Settings > Beta Settings had 6 columns (Recipient, Source, Sent, Status, Signed, Actions) that overflowed at 390px — the STATUS column was clipped off-screen, dates like "May 17, 2026 at 1:30 PM" wrapped across multiple lines taking huge vertical space, a…

- **Mobile AI swipe panel — middle tab-bar button opens page surface as right-slide drawer**
  On mobile (<1024px) the middle button in #mobile-tab-bar (#mobile-search-btn, the rainbow AI icon) now opens the **page's own AI surface** — the AIEngine panel (docs / decks / emails / calendar / todos / POs / etc.) or the SheetsAIBar — as a full-height right-slide drawer instead…

- **Canvas — Figma-style spacebar pan (and toolbar Pan tool fix)**
  Replaces the clunky spacebar-pan implementation with a Figma/Photoshop-grade pan. The previous code had four compounding issues:

- **Canvas — Film-production SVG icon library**
  Adds a purpose-built library of 30 film-production SVG icons (vehicles, base camp / staging, crew positions, location markers, production gear) plus a new **Icons** tool on /canvas.html that opens a category-tabbed picker — right-rail panel on desktop, bottom-sheet on mobile. Cli…

- **Canvas — E2E audit, setCenter NaN fix, full AI tool set**
  End-to-end audit of canvas.html (the Fabric.js editor formerly known as visualizations). Inventoried every user-facing feature including the recent window.db wiring, traffic layer, camera pins, route planner, and freeze-to- static map flow. Caught and fixed a regression where can…

- **Mobile Back button: show + back out of expanded project detail**
  The mobile tab-bar Back button (#mobile-tab-back) was only appearing when body.modal-open or body.spotlight-open was set. On the dashboard, drilling into a project detail view sets body.project-expanded-mobile but does NOT open a modal — so the Back button stayed hidden and there…

- **AI realtime voice — inline HUD + pulsing perimeter ring on surface pages**
  On any page that has registered an AI surface (body.show-footer-ai — calendar, crew-list, decks, docs, petty-cash, purchase-orders, sheets, shooting-schedule, todos, plus every page wired in by the feat(ai-surfaces) batch on 2026-05-20) the realtime voice button no longer takes o…

- **AI rename_project + update_job_code tools, project creation client-save fix, organizations.html Clients audit**
  Three related changes in one session:

- **AI tools audit + master reference doc**
  End-to-end audit of CrewDeck's AI tools system. Read all 404 tool definitions in ai-agent, all AI-related audit docs and changelogs, the full ai-router routing tree, comms-analyze intent classification, cron workers (reminder-fire, scheduled-action-fire, notification-rule-runner)…

- **Wrap folder structure for PO export + Wrap Project download**
  All PO export downloads now use the 16_WRAP_FOLDER folder structure the producer uses for wrap deliverables. The "Download All POs" button outputs a <Project>_WRAP/7. POs/ hierarchy with dynamic payment-method subfolders (only the folders used by the project's POs are created). A…

- **Fix re_annotate: signed-URL InvalidJWT + wrong-project row selection**
  Two bugs surfaced during end-to-end iMessage testing of the re_annotate flow (following the document_path fix shipped in abba563).

- **Mobile panels: Purchase Orders, Payroll, Petty Cash**
  The Purchase Orders, Payroll, and Petty Cash pages already wired the universal loadMobilePanels system (3-panel swipe: nav left, content middle, widgets right), but on mobile their top toolbar and stats-bar elements still rendered above the swipe viewport. The flex-wrapping toolb…

- **Replace Mapbox GL with Google Maps on overhead map canvas**
  The overhead map feature on the canvas page previously used Mapbox GL JS for map rendering, relying on a demo token that couldn't access Mapbox vector tiles (the "Shader" style was broken). This change replaces the entire Mapbox rendering layer with Google Maps, using the existin…

- **Gmail OAuth Connector (org-scoped)**
  Adds Gmail as a first-class org-scoped OAuth integration, modeled exactly on the existing Frame.io pattern. One Gmail connection per organization, connected by an org admin; all org members can then search the org's inbox for receipts and invoices. Tokens are AES-GCM encrypted at…

- **Fix: cross-reference signed URL InvalidJWT + group chat sender auth**
  Two related fixes for the cross-reference PDF link flow:

- **doc-intelligence: iMessage status updates + parallel entity extraction**
  Two improvements to doc-intelligence to reduce perceived latency on large PDFs.

- **doc-intelligence: tighten cross-reference matcher to eliminate near-miss false positives**
  Three tightening changes to poFirstMatch so the cross-reference matcher emits only confidently-correct matches on clear documents (eg. an Amex statement with ~20 line items against a project's PO list). Previously the matcher could emit "fuzzy" near-miss matches on borderline-ven…

- **Iterative annotation editing for cross-reference**
  When a user said "make the highlights smaller" or "use green" after receiving a cross-referenced PDF, the agent's only path was to re-run cross_reference_document — paying for the full doc-intelligence extraction + matching pipeline again (an LLM extraction call + matching pass t…

- **Cross-Reference Web UI E2E test — Fuzzy Match Test Project**
  End-to-end test of the cross-reference feature via the AI ChatHub on crewdeck.io/dashboard, using mock_amex_statement_fuzzy.pdf against the **Fuzzy Match Test Project — AMEX May 2026**. Confirmed the web-UI path is healthy now that Anthropic credits are restored: project find, en…

- **Diagnosis: cross-reference annotated PDF links confirmed working**
  User reported that annotated PDF links from cross-reference were still returning "invalid link" after the bucket-private fix (7f80352). Diagnosis confirmed all prior fixes are working correctly — no code changes were needed.

- **Cross-Reference Web UI E2E retest — Fuzzy Match Test Project (48 POs)**
  End-to-end re-run of the AI ChatHub cross-reference flow against the Fuzzy Match Test Project after the previous session seeded 43 additional production-oriented vendor POs (Catering by Design, Hungry Bear Productions, California Rigging, Hertz, Marriott, Filmtools, etc.) on top …

- **ai-agent: drop edit_document chain for cross-reference — use annotated_url directly**
  eca3e48 (Mark's commit, 2026-05-20 00:09) rewrote doc-intelligence's cross-reference annotation path to render the annotated PDF server-side via buildCrossRefAnnotatedPdf — green/yellow/pink/gray row bands using the extractor's anchor-corrected y_fractions, with no LLM in the ren…

- **Per-tool cache TTL, beta training-consent gate, per-(tool, user) analytics**
  Three changes ship together:

- **Blooio attachments → inline base64 for Gemini (no more fileData URL)**
  The iMessage cross-reference path was failing whenever Gemini was the primary model on cross_reference_document. Root cause: when comms-analyze handed an inbound Blooio attachment to ai-agent, it forwarded the att.media_url (bucket.blooio.com/...) as a url hint. ai-agent's _toInl…

- **Visualizations — Suggest Layout Apply polish + Realtime presence**
  Two changes to visualizations.html:

- **Visualizations Phase 4 — AI Diagram Tools**
  Adds four AI-powered diagram tools to the visualizations.html canvas editor under a new "AI" section in the left tools panel. visualizations.html is an infographics, data-visualizer, and overhead-map editor (not a photo editor), so the tools are framed around layout, element gene…

- **Visualizations Phase 3 — Brush / Paint Tools**
  Adds four dedicated paint/brush tools to the Fabric.js canvas editor in visualizations.html. A new "Paint" section appears in the left tools panel below the zoom controls, separated by a labelled divider. When any paint tool is active, the right-side properties panel is replaced …

- **Visualizations Editor — Phase 2: Placeholder Pill System + Mode B Data Resolution**
  Phase 2 of the canvas editor adds the full placeholder→live-data pipeline. Placeholder tokens inserted from the left-panel tool now render as styled pill objects (Fabric.js Group with a rounded accent-color rectangle + white label text). Switching to Mode B fetches the selected p…

- **Overhead map templates now render on a real Mapbox background**
  The six "Overhead Map" templates in visualizations.html (Overhead Map, Basic Film Set, Location Scout Map, Exterior Action Map, Department Zone Map — Studio Floor Plan is intentionally excluded) now mount a real, interactive **Mapbox GL JS** map as a background layer behind the F…

- **Visualizations page — AI tools, overhead templates, From-Data, sharing**
  End-to-end completion of visualizations.html. Replaces the four AI-tool stubs with real ai-router calls, adds five overhead-map templates, wires four data-to-diagram generators behind a new **From Data** button, and ships a share-link + viewer-mode + improved PDF/call-sheet expor…

- **Visualizations Phase 1 — Canvas editor + template library**
  Replaces the AI-only visualizations.html (type-picker → AI generates → render-only) with a Photoshop-class canvas editor built on Fabric.js 6.7.0 — the same version decks.html runs in production. Phase 1 ships the editor shell, basic tools (select, rect, ellipse, line, text, imag…

- **Vendor rename consistency + loan-out company tools**
  Two vendor-management fixes triggered by a Mark screenshot showing a vendor "rename loop." First fix is a self-contradiction bug — the AI was telling the user that "Pablo Diez" both did and did not exist as a vendor across consecutive turns because rename/create/PO-relink were ea…

- **shooting-schedule.html: labeled Export PDF button, AI client_action_required bridge, file-import → AI parse → calendar_events**
  A previous task added the schedule_export_pdf tool in ai-agent that returns client_action_required:true with a structured payload — but nothing on the page consumed it. This change closes that loop and adds two visible toolbar entry points so users can run the same flows without …

- **Visualizations page renamed to Canvas**
  "Canvas" is now the canonical name for what was previously called "Visualizations." The page file is now canvas.html, the global header nav button reads **Canvas** and points at /canvas.html, and every user-facing label inside the page (titles, tabs, modal headers, toasts, defaul…

- **2026-05-19 — Receipt Upload form fields backfill + empty-form guard in `send_*_request` tools**
  - Form 151 ("Receipt Upload", org 51) now has 9 fields matching the canonical template in supabase/functions/forms-engine/index.ts:330-427. - send_receipt_upload_request and send_petty_cash_form now refuse to create a form_invite when the underlying form has zero form_fields, ret…

- **PO modal: remove Type + Pay-via selectors, derive category from linked budget line**
  Removed two PO-level taxonomy fields that don't belong on a PO: the **Type** button row (Rate / Kit fee / Box rental / Mileage / Per diem / Car allow. / Other allow.) and the **Pay via** button row (Vendor / Card / Card·P / Payroll / PC). Both shipped on every PO create/edit moda…

- **2026-05-19 — Purchase Orders mobile layout re-aligned with sheets design system**
  The first mobile pass on purchase-orders.html (c8d22d0) used a PO-specific responsive pattern that worked, but felt like a different app from sheets and (after the 2026-05-19 petty-cash rework) felt like a different app from petty-cash too — different breakpoint, different radius…

- **PO downloads audit + universal download loading bars**
  Two things in one pass:

- **PO modal: read-only Budget Line card + Vendor/Crew Member type gate**
  Two changes to the PO create/edit flow, both driven by the same idea: PO-level fields should reflect data that lives *on the PO*, and budget/people data should be surfaced as context, not as editable PO fields.

- **PO export attachments — infer file extension from Content-Type / magic bytes**
  When a PO attachment URL has no file extension (Blooio MMS media URLs look like .../1779140825301-mms-2), the saved-into-backup/ file inherited the URL-derived basename unchanged. The bytes were still a valid PDF/image, but Finder / Preview / Quick Look had nothing to dispatch on…

- **Petty Cash Notification System — 4 Bug Fixes**
  E2E audit of petty cash notifications uncovered 4 bugs that caused all petty cash notifications to silently fail. Every event type dispatched from ai-agent (_dispatchPCNotif) or forms-engine arrived at notification-dispatch but was dropped before any channel was fired. The root c…

- **2026-05-19 — Petty Cash page mobile responsive layout**
  petty-cash.html had a desktop-only layout: full-width envelope table with 9 columns, two additional 7-column tables for pending requests + receipts, a 560–900px envelope edit modal with embedded spreadsheet-style line-item tables, and toolbar buttons sized at ~28px tall. On a 390…

- **2026-05-19 — Petty Cash mobile layout re-aligned with sheets design system**
  The first mobile pass on petty-cash.html (a4ed3aa) ported the purchase-orders.html mobile pattern verbatim. It worked, but it felt like a different app from sheets — different breakpoint, different radius scale, different modal pattern (full-screen vs bottom-sheet), different voc…

- **Payment Waves — queued + batched payment approvals**
  Adds the complete Payment Waves system: a named batch of outbound payments (ACH, virtual cards, petty cash, payroll) that get grouped, reviewed by a human, then executed by Stripe together. Individual payments outside of waves are also supported.

- **notification-rule-runner — daily sweep that fires schedule-based notification_rules**
  20260519160001_notification_rules.sql added time-based scheduling columns (trigger_offset_hours, trigger_time, recipient_type, recipient_value, channel, message_template, use_group_chat) to notification_rules but flagged "FOLLOW-UP REQUIRED" for the firing mechanism. This is that…

- **iMessage MMS document delivery**
  Closes the broken iMessage → generate doc → MMS delivery chain.

- **Forms Module System + Google Forms Redesign**
  Two parallel tracks:

- **Fix doc cross-reference: amount parsing, opaque-descriptor fallback, server-side annotated PDF**
  Test scenario: user uploaded a Grindr Amex statement (23 line items), asked to cross-reference against the POs on the GRINDR x M project. The AI replied "none of the 23 lines matched an existing PO" even though POs should have matched, and then asked the user to reply "Annotate w…

- **fix: cross-reference yearless entity dates + tighten subset-sum tolerance**
  Two more matcher bugs surfaced when retesting the Grindr Amex cross-reference against 19 POs. The earlier parse-amount fix (HEAD 3d9e4b8) cleaned up dollar-string parsing but matches were still returning 0. Root cause: (1) the entity extractor was prompted to emit dates like "May…

- **fix: cross-ref year-tolerant date diff + 1hr lookback + extraction cache**
  Closes out the Grindr Amex cross-reference debug loop. After the earlier parseAmount fix (3d9e4b8) and yearless-date parseEntityDate fix (a9f5a17), the matcher still returned 0/19 because the LLM extractor was inferring 2025 as the year on a statement whose header showed only "Ca…

- **cross_reference v2 + zero-error standard for doc-intelligence**
  Second iteration on cross_reference, motivated by an Amex Business Platinum statement test that revealed two new failure modes:

- **fix: cross-reference amount parsing + annotated PDF URL surfacing**
  Two bugs fixed in the doc cross-reference flow. **Bug 1:** entity amounts extracted by Claude from credit card / bank statements can arrive as strings like "$1,234.56" instead of plain numbers. Number("$1,234.56") returns NaN, which || 0 silently coerced to zero, so every PO amou…

- **Compliance: never persist card or ID data**
  Audited the repo for any code path that could persist credit-card or government-ID data, and added a hard guardrail to the only function that could realistically end up holding it: doc-intelligence. The function now detects card/ID inputs (by analyzer classifier or by fill_form f…

- **Mapbox GL JS overhead map on Canvas templates**
  canvas.html's six overhead-map templates (Overhead Map, Basic Film Set, Location Scout Map, Exterior Action Map, Department Zone Map — Studio Floor Plan stays interior-only) now mount an interactive **Mapbox GL JS v3.3.0** map as a background layer behind the Fabric.js canvas. Th…

- **Calendar AI assistant + `calendar-full.html` → `calendar.html`**
  Renamed calendar-full.html → calendar.html (canonical name; old URL will 404 by design) and built out the page's AI assistant to parity with the sheets / PO / docs surfaces. The calendar page now loads the shared AI Engine, publishes window.calendarContext on every render, and ex…

- **Budget line "type" field (labor, kit, mileage, overtime…)**
  Adds a line_type field to budget line items so each line can carry a category (Labor, Kit/Equipment, Box Rental, Mileage/Vehicle, Per Diem/Meals, Hotel/Accommodation, Travel/Transport, Overtime/Turnaround, Materials/Supplies, Miscellaneous) independent of whether the line is also…

- **Budget Compare View — QA Audit + Bug Fixes**
  Full QA pass of the budget compare view across 8 test sections (entry points, layout, edit verification, row operations, writeback, compare actions, AI integration, edge cases). Three bugs were found and fixed. All editable fields in the active-version column work correctly. The …

- **ai-router — Visualizations Diagram & Layout Actions**
  Adds four AI actions to ai-router that back the AI toolbar in visualizations.html. The visualizations editor is a canvas-based infographic and diagram builder (overhead maps, data visualizers, call sheet layouts) — not a photo editor. All four actions use Claude Sonnet (claude-so…

- **AI Document Intelligence — generate, analyze, cross-reference, merge + AI Modified tabs**
  Adds a unified AI document intelligence system that lets the user ask the AI to **generate** documents from project data (PO log, budget summary, project summary, payroll summary, sheet PDF, ZIP of POs, custom), **analyze** any attached file (PDF / image / text), **cross-referenc…

- **AI Cost Tier 2 — 5-Lever Optimization**
  Tier-2 cost optimization targeting ≤1 cent/call (down from ~5 cents post Tier 1). Five levers applied across the AI agentic loop: prompt-cache on the tool schema (L1), conversation history compression (L2), selective Sonnet escalation for only the intents that need it (L3), condi…

- **AI Cost Tier 2 Re-Apply — L1-L4 on top of gate fix**
  Re-applies four AI cost levers to ai-agent/index.ts on main, targeting ≤1¢/call for the agentic loop (down from ~5¢+ before):

- **AI Cost Gaps 1+2+3 — Prompt Cache Activation, More L4 Strips, Single-Iter Writes**
  Three targeted fixes to ai-agent/index.ts:

- **Actuals canonical per project — wire every spend source through one Actuals budget**
  The budget page's Actuals tab was showing all zeros even on projects with millions of dollars in purchase orders. Root cause: the budget_line_commitments view aggregates spend per budget_line_item_id and the Actuals tab filtered the view by the Actuals budget id — but every PO/pe…

- **vision: Downscale Large Images Before Passing to Claude**
  Mark texted Bash a Westside Market receipt photo and got "Hit a snag on that one — try again in a sec." The ai_activity_log shows:

- **ai-billing + ai-agent + comms-analyze: URL-Source Images for Claude**
  Final piece of today's image-pipeline trilogy. After fixing the base64-aware threshold (raw vs encoded) and the imagescript OOM, the user still had to manually resize iPhone photos > 3.6 MB before sending — which is annoying. This change makes the resize unnecessary.

- **Universal Notification Rule Tools (Phase 2)**
  Mark broadened the channel-picker spec mid-task from "form-send-specific" to "make sure the notification rules have this structure for all notifications" (see feedback_universal_notification_channel_picker.md). This commit addresses the AI-tool half of that — adding four universa…

- **Universal iMessage destructive-action confirm gate**
  The iMessage path was running ai-agent with effectiveApprovalLevel='none' (auto-approve everything), which meant the model could call delete_vendor, delete_contractor, remove_crew_from_project, etc. without ever asking the user. The web chathub already had a per-tool confirm moda…

- **generate-po-topsheet: Method-aware Payment Confirmation Labels**
  The XLSX top sheet shipped with hardcoded "Check #:" / "Deposit Chk#:" / "#:" labels in the Payment Confirmation block (rows 36-39). The modal UI was updated earlier today to re-label these fields based on the picked payment_method (Card last 4 / Card type / Auth code / Transacti…

- **Petty Cash — Add 5 petty cash write patterns to TOOL_REQUIRED_PATTERNS**
  During QA of B7 (add_petty_cash_transaction via iMessage), the AI model deflected instead of calling the tool. Root cause: TOOL_REQUIRED_PATTERNS had no petty cash entries, so Gemini Flash handled iter-0 and failed to reliably invoke petty cash write tools. Claude Sonnet is neede…

- **agent_error_fallback: Specific User Messages for Common 400-Class Failures**
  Mark's request: the generic "Hit a snag on that one — try again in a sec." doesn't tell him WHY. When the actual error is "image exceeds 5 MB", he wants the AI to say that.

- **Side panels truly cover header + per-page toolbar; widget cards have zero chrome; POs page has no horizontal scroll**
  Follow-up session to [2026-05-18-panels-full-height-no-card-border.md](2026-05-18-panels-full-height-no-card-border.md). After the initial fix put both panels at top:0; height:100dvh, Mark reported the panels still appeared to "not extend to the top" — the global header + per-pag…

- **Mobile UX Audit: Settings & Organizations Pages**
  Thorough mobile UX audit of settings.html and organizations.html at 390×844 viewport (iPhone-equivalent). Found and fixed 36 issues across 6 files: emoji glyphs in visible UI, inputs with font-size < 16px that trigger iOS Safari auto-zoom, number inputs missing inputmode="numeric…

- **po_line_items: Relax (po_id, budget_line_item_id) UNIQUE Constraint**
  Mark asked to link every line on PO 013 (Courier Car Rental) to a budget line. Rentals → Production Trucking, tolls/gas → Parking/Tolls/Gas. The po_line_items_po_budget_line_idx UNIQUE constraint blocked it — only one line per (PO, budget_line) was allowed.

- **comms-analyze: Refuse Oversized Image at Ingest, Skip Agent**
  The earlier downscale fix (imagescript decode → resize → JPEG re-encode) handles JPEG and PNG fine, but imagescript can't decode HEIC. Mark's iPhone delivers HEIC sometimes — those photos pass through at original size, hit Claude's 5 MB inline limit, and burn an agent round-trip …

- **Receipt-upload invite carries envelope context end-to-end**
  send_receipt_upload_request now resolves and persists the petty-cash envelope on the form-invite token so the uploaded receipt auto-links to the right envelope without manual re-linking.

- **PO Downloads: Append W-9 from Private Bucket + XLSX-with-W9 PO Folder**
  W-9 documents were moved to the private crew-assets bucket on 2026-05-17 for compliance, but three PO-download edge functions were still using plain fetch(url) against the legacy /storage/v1/object/public/... URLs stored in contractors.w9_url. Those fetches silently returned 400 …

- **PO Page: Inline Vendor Edit Modal + W-9 Download**
  The pencil-icon edit button in the PO modal's Vendor row used to open /organizations.html?tab=vendors&vendor=<id> in a new tab — an awkward context-switch that left the user's PO modal in the background. Mark wants it to open an inline modal that shows the full vendor info and a …

- **generate-po-topsheet: consistent currency styling on all line items + aspect-preserving logo sizing**
  Mark caught two issues in the downloaded EQX Catering PO topsheet (PO_JOB_000_EQX Catering & Events City (SCNY Rock Inc.).xlsx):

- **PO snag unblock + universal iMessage gate restore (third re-application)**

- **purchase-orders.html: remove read-only viewer modal — single-click opens edit directly**
  Mark's ask: "remove the View modal from the po page entirely, it should simply open to the edit view when i open the po."

- **2026-05-18 — Purchase Orders page mobile responsive layout**
  purchase-orders.html had a desktop-only layout: full-width table with 7 columns, 560–960px modals, and toolbar buttons sized at ~28px tall. On a 390px iPhone viewport the table overflowed, modals overflowed, action buttons were below the 44px tap-target minimum, and form fields t…

- **PO Page: Flat List by Default, Right-Click Toggle for Section Grouping**
  The PO list page always grouped POs by their linked budget-line section with banner rows + per-section subtotals. Mark wants the default to be a flat list, with section grouping as an opt-in toggle accessible by right-clicking any column header.

- **PO Page: Rename "Description" Column → "Budget Line"**
  The PO list table's third column was labeled "Description" and rendered po_type (Labor / Rental / Meals Crafty / Equipment / etc.). Mark wants it to show the budget line the PO is linked to instead — that's the meaningful info when scanning POs against the budget.

- **PO Modal: Instant Open (Defer Async Loads)**
  Clicking a PO row used to feel like nothing was happening for ~500ms–2s before the edit modal appeared. Root cause: openModalForEdit awaited two Supabase round-trips (vendor lookup + line items) BEFORE adding .open to the modal.

- **ai-agent system prompt: stop refusing PO creation when no crew on project**
  Live test caught the AI refusing to create POs from a master-sheet PDF because the project's crew table was empty:

- **ai-agent: derive po_line_items.rate from amount/quantity so the UI modal renders non-zero**
  Live test caught a UI parity bug: Mark's PO Edit modal showed Pablo Diez's two line items ("Sound Labor" qty 1, "Kit Fee" qty 1) with empty Rate cells and $0.00 subtotals/totals — even though the AI's chat reply confirmed "$600 labor + $350 kit" and the purchase_orders.amount was…

- **ai-agent: full audit of po_line_items inserters + project-create template fallback + GRINDR x M Hot Budget seed**
  Three follow-ups from the previous round of PO-line-item fixes:

- **ai-agent: Kill Duplicate PO Creation + Duplicate Budget-Line Ask**
  Follow-up to 2026-05-18-imessage-plan-and-budget-line-rules.md. Mark retested with two Target receipt PDFs + "add as one new target PO. these link to the craft service line". Two regressions still showed up in the DB:

- **PO Edit Modal: Collapsible Payment Confirmation + Signature + Payment Method Picker**
  Two PO edit-modal sections were always visible and cluttering the form for every new PO, even though most POs don't carry payment-confirmation or approval-signature data until late in their lifecycle. They're now hidden behind "+ Add …" trigger buttons. The Payment Confirmation s…

- **PO Modal: Chip shows Line Number + Remove PO Log Section Override**
  Two paired PO-modal cleanups Mark called out:

- **PO Page: Keep Header `budget_line_item_id` in Sync With Linked Lines**
  Mark manually linked a line item on PO 014 (B&H Photo, $359.28) to a budget line but the PO still showed under "UNASSIGNED (NOT LINKED TO BUDGET)" on the PO page.

- **PO: Auto-Paid From Invoice / Card Photo + Dynamic Labels + Sign-Button Fixes**
  Four bundled improvements around how the PO edit modal handles payment + signature state, plus a new AI flow that auto-marks POs as Paid from an attached final invoice or charge confirmation.

- **ai-agent: Auto-number new POs + Budget-link Truthfulness**
  Two issues from Mark's iMessage flow:

- **Petty Cash QA Session 3 — iMessage re-tests + Section D notification pipeline**
  Fresh iMessage re-tests of B7, B8, B9 on a new open envelope (B7-TEST, pc_number='B7-TEST', id=5b68ca85). All three tests pass clean with no history contamination. Completed Section D (notification integration tests): pipeline confirmed working end-to-end. Two config/UX findings …

- **Petty Cash QA Session 2 — B7/B8/B9/C1/C2 re-tests + bug fixes**
  Continued petty cash QA after Anthropic credit top-up. Re-tested B7/B8/B9 (iMessage) and C1/C2 (AI panel chathub). All 5 tests now PASS. Fixed 4 additional bugs discovered during re-test, all in ai-agent/index.ts.

- **Petty Cash — Phases B, C, D: Visual Parity, Receipt Pipeline, Notifications**
  Three phases of petty cash system build-out. Phase B brought petty-cash.html to visual parity with the purchase orders page: status pills, hover-reveal row actions, checkbox bulk-select, status filter dropdown, a right-slide detail drawer, right-click context menu, and extra stat…

- **ai-agent: `add_petty_cash_expenditure` Uploads In-Context Receipt**
  After today's URL-source image fix Mark sent a 4.29 MB iPhone receipt to Bash with "Add to cara's pc". The AI correctly:

- **Petty Cash — Full Card AI Plumbing + UI Gaps + Forms System Integration**
  **Part 1 — Card AI plumbing:** Connects the existing Stripe Issuing infrastructure (already wired in stripe-functions) to the AI layer. Adds 9 new AI tools for card lifecycle management, iMessage routing for card phrases, and closes two UI gaps on the Petty Cash page: a missing "…

- **Petty Cash — AI Creator E2E: 13/13 PASS (0 PARTIAL / 0 FAIL)**
  E2E audit of the AI creator on organizations.html → Notifications → Add Rule → AI Describe for petty cash event types. Surface was fundamentally non-functional on arrival and the petty cash event catalog was completely missing from the AI panel. Six file deploys, 11 bug fixes, al…

- **comms-analyze + ai-billing: end-to-end PDF support for the iMessage path**
  When Mark attached a PDF (GOODCO_MxGRINDR PRODUCTION MASTER SHEET ... .pdf) to an iMessage and asked the AI to "Add POs to anyone labeled as Loan Out," the AI replied "I need to see the PDF to pull the loan-out names — can you resend it here?" three times in a row, even after the…

- **petty-cash: Export Chevron Fix + PC LOG-Style Template Topsheet**
  Two things, both flagged by Mark on the petty-cash page.

- **petty-cash: Replace Per-Page AI Button + Panel With Shared Footer Engine**
  The Petty Cash page had its own circular clock-icon button (#ai-toggle-btn) in the toolbar that opened a small custom AI panel (#pc-ai-panel) bottom-right. Mark wants the toolbar button gone and the AI assistant accessed from the shared footer that the rest of the app (sheets, PO…

- **Apps + widgets panels span full viewport; remove widget card border**
  Mark: "on every page the left slide in app menu stops too low on the page leaving a lot of empty space above it" → followed by "make sure both the app menu and widgets menu both go from the bottom to the top of the page, over the tool bars on pages and over the header" → followed…

- **Orchestrator: "linked to budget line" must not route as `comms_share_link`**
  When a user texted "create a $50 PO on GRINDR x M linked to the craft service budget line", the iMessage orchestrator was misclassifying it as task_type: comms_share_link because the LLM keyed off "linked to <category>". The share-link handler then tried to resolve a project to g…

- **ai-agent: narrow the destructive YES/NO gate to delete-family operations only**
  Mark called out the confirm gate firing on the "change AlphaCine to equipment + mark paid" iMessage flow. His directive: "It should only require the confirm gate for deleting things." The gate was set up to fire on the entire ACTION_TIERS 'destructive' tier — which includes ~80 o…

- **Multi-Step Plans: Suppress Per-Tool Destructive Gate After Prose YES**
  Mark's screenshot: AI proposed "I'll delete the 4 existing Courier POs and replace them with one clean PO with all 4 line items totaling $641.52. Want me to do that?". Mark replied "Yes do it" → AI tried to delete 4 POs but only ONE delete fired before the agent loop exited. The …

- **ai-agent: Multi-Attachment → One PO (Single-Vendor Bundles)**
  Mark's case: he might send 3+ attachments that all belong to ONE PO — e.g. invoice PDF + W-9 + payment-confirmation screenshot from the same vendor. Previous batch logic blindly fan-out by attachment count: 3+ attachments always became 3+ POs via batch_create_po_from_attachments.…

- **mark_po_paid: default Charge amt to payment_amount + Charge date to payment_date**
  After the earlier mark_po_paid expansion, the AI was leaving the "Charge amt" / "Check amount" slot blank because params.check_amount is technically optional and the tool description treated it as an explicit-override field. Mark's expectation is the opposite: marking a PO paid s…

- **comms-analyze: surface a "switch to Medium" hint when Low/Haiku fails a write-orchestration**
  Phase 5.9 wired chat_threads.ai_detail_level='low' → Haiku for ai-agent's main loop. The live test on org 51 / thread d1e29de5 caught the expected weakness: Haiku is fine for read-only lookups (~67% cheaper than Sonnet) but unreliable on multi-step write orchestration — specifica…

- **ai-agent: line_items schema — rate is explicit; amount is line TOTAL**
  Mark sent the 500 Peacocks LLC invoice with 4 lines:

- **ai-agent + comms-analyze: Finish Multi-Step Tasks; Stop Re-Asking About Budget Lines**
  Mark sent two Target PDFs to Bash with "add both of these as one new target PO" + "dont worry about budget lines for the first two, these two both link to the craft service line". Three things went wrong in the AI's response:

- **vision: Guard imagescript Decode Against Edge-Worker OOM**
  Immediate follow-up to 2026-05-18-image-base64-aware-threshold.md. Tightening the downscale trigger to 3.6 MB pushed Mark's 4.29 MB iPhone JPEG into the imagescript decode path, and the edge worker died with **HTTP 546 WORKER_LIMIT** after ~9 s. Mark texted "i sent a test and did…

- **vision + comms-analyze: Base64-Aware Image Size Threshold**
  Mark kept getting "That photo's too large…" on iPhone receipts that were "only" 4.29 MB raw. Everything we'd already fixed (HEIC decode, downscale on imagescript, regex broadening, ingest refusal) was running correctly — but the photo never tripped any of them, because **none of …

- **vision: Decode HEIC Photos via libheif-js WASM**
  iPhone's default photo format is HEIC. iMessage MMS sometimes preserves HEIC bytes (with content-type=image/heic, image/heif, or even image/jpeg when the gateway mis-labels). imagescript — the lib doing the downscale resize — only handles JPEG/PNG/GIF/WebP. HEIC photos fell throu…

- **Form Send Channel Picker with Rule Save (Phase 1)**
  Implements **Phase 1** of Mark's "send the form to X" spec — the AI can now remember a user's preferred delivery channel(s) per form, and replay it the next time the user asks to send that form. Adds three new AI tools (set_form_send_default, list_form_send_defaults, delete_form_…

- **comms-analyze fast-path: Multi-Attachment iMessage Support**
  Slow-path already supported multiple attachments — it resolved every attachment on the inbound message via findAllInlineImagesFromCurrentMessage and passed them to ai-agent as attachments[]. ai-agent then fans out via batch_create_po_from_attachments for 3+ or runs create_po_from…

- **Port fake-multiple-projects scanner to ai-task-worker**
  Commit 798e5d1 added a server-side hallucination scanner to comms-analyze that catches and rewrites fabricated "Found multiple projects matching that…" replies when the agent didn't actually call find_project this turn. The scanner only fires on the fast-path and slow-path replie…

- **Server-side guard against fabricated "Found multiple projects" replies**
  Mark caught the iMessage AI replying with disambiguation prose like "Found multiple projects matching that: X, Y. Which one?" — but the ai_action_log showed **zero** find_project invocations on those turns. The model was fabricating the candidate list from training data or stale …

- **comms-analyze: Early "On it" Ack on Heavy Turns**
  Mark sent a multi-step request (delete some petty cash + handle a new B&H receipt). The agent took ~60s to complete and Mark sat with no signal — felt like he was being ignored.

- **E2E Test Bench — Full Project Seed**
  Seeded the E2E Test Bench project (5fb5da2a-d871-4121-ba2c-af3cb81bcae2, org 51) with a fully populated test dataset so Bash AI iMessage tests can run against realistic project data instead of relying on production project state.

- **AI outbound — user-prompt-shape refusal (server side + tool boundary)**
  This is the **server-side** companion to the frontend-only composer guard shipped earlier today (2026-05-18-comms-composer-ai-prompt-guard.md). The FE-only fix protected Mark from typing prompts into the comms composer by mistake. Mark followed up with a screenshot pinpointing a …

- **Comms composer — AI-prompt guard against accidental group SMS**
  Mark reported on 2026-05-18: "Why is the ai sending messages to the group chat from the comms page?" — believing the AI was sending unsolicited SMS to a real production group.

- **comms-analyze: org auto-fills production_company + orchestration sends bypass user-prompt guard**
  Two bugs surfaced while testing the iMessage comms_create_project flow today:

- **comms-analyze: Bump ai-agent fetch timeouts (30s/20s → 240s)**
  Mark sent a PDF + "Make a PO for this on the Grindr Project". The AI completed the task and answered: "I created the 500 Peacocks LLC ($404.25) PO but couldn't guess a budget line. What category is this? (e.g. 'crafty', 'camera', 'transpo')". But comms-analyze then ALSO sent the …

- **Channel Picker — Org Outbound Capability Gate**
  Mark added a new rule mid-session: only offer / persist / dispatch text channels for organizations with an active Blooio phone line. The change cuts across the AI tool surface (set rule + send invite), the runtime dispatcher, and the Notification Center UI. Source of truth is pho…

- **BUG C Fixed — Per-Sheet og:image Thumbnail in iMessage Rich Preview**
  BUG C (open since 2026-05-17): iMessage share link preview showed the CrewDeck logo (og-default.png) instead of a rendered image of the sheet itself.

- **PO Modal: Budget-line Search by Line Number + XLSX Terms Overlap Fix**
  ### 1. Budget-line popover: search by line number + show line number on rows

- **Budget Line + Section AI Tools — Phase 4 First Wave**
  Closes the highest-priority gaps surfaced by docs/budget-ai-coverage-audit.md: budget-line CRUD coverage for iMessage was 4 / 15 wired (27%) and section CRUD was 0 / 5 (0%). This change ships the crew↔budget-line linking tools (the single highest-frequency ask flagged in the audi…

- **Budget AI second wave — Tier 2-6 reads, versions, fringes, ACH status**
  Phase 4's first wave (commit ce1ae09) shipped the structural budget write tools — sections, line items, version create, crew↔line linking. That brought the coverage matrix from 39% baseline to roughly the same number, because all the gaps were on the read/narration side: "what's …

- **Anthropic prompt-cache TTL bumped 5m → 1h (default)**
  callClaude (the shared Anthropic wrapper used by every CrewDeck Claude call path) now defaults cache_control.ttl to '1h' and sends the extended-cache-ttl-2025-04-11 beta header alongside the existing prompt-caching-2024-07-31 flag. The 1h window keeps system prompts + tool defini…

- **ai-agent: Smart PDF Routing When Intent is Ambiguous**
  Mark's directive: when a chat is attached to a project and he drops a PDF with no/minimal context, the AI should figure out what to do by classifying the doc AND checking existing records for a match. Card-last-4 on a receipt that matches an open PO's card → that's a payment rece…

- **ai-agent: PO insert must always set organization_id (org-scoped update fail)**
  User flow: Mark asked the AI to mark several non-labor POs as Paid with the same card. The AI responded with "Are you sure? YES/NO" → user replied "YES" → the AI returned **"No PO found with id 67619392-... in this organization"** even though the PO clearly existed.

- **ai-agent + PO Page: Match Against Actuals Budget; Surface Line Number + Section**
  Mark's screenshot of PO 017 in the Edit modal showed every line's BUDGET LINE column rendering as #129927 ✕ instead of the line description. Two distinct issues, one fix each.

- **AI Cost Gap 2 — pruneSystemPrompt: 12-Section L4 Strip**
  Replaced the 6 individual systemPrompt.replace() calls with a single pruneSystemPrompt() function that handles 12 strippable sections. Added 5 new strip patterns on top of the prior 6:

- **ai-agent system prompt stabilized for 1h prompt cache**
  The 1h prompt-cache TTL bump from earlier today (9cc1ba9) was correctly plumbed end-to-end but delivered ~zero of its expected value because ai-agent's system prompt embedded per-call dynamic timestamps (REQUEST_TIMESTAMP, USER_LOCAL_NOW, SERVER_PRE_COMPUTED_FIRE_AT) **inside** t…

- **ai-agent: chat_threads.ai_detail_level → model override**
  The L/M/H "detail level" chips on the ai-chathub toolbar and the ts-ai-mode controls in communications.html have always written chat_threads.ai_detail_level (default medium) but the value only drove the credit-estimate badge — it never affected which model actually ran. This chan…

- **ai-agent: AFFIRMATIVE FOLLOW-UP directive (user "yes" to AI's offer)**
  Mark's iMessage flow surfaced an AI mis-interpretation:

- **Vendor/Contractor Full CRUD via AI Natural Language**
  Added full CRUD AI tools for vendors (org-level company directory) and contractors (individual crew contractors). Also fixed two bugs: delete_vendor now refuses if the vendor has open POs and offers archiving instead, and update_vendor's allowed-field list was expanded from 5 fie…

- **Vendor Capabilities: Multi-valued PO Type System**
  A vendor like Quixote Studios can rent equipment on one shoot and provide crew (labor) on another. The old single vendors.category field couldn't represent this. This change introduces a vendor_capabilities table — a multi-valued (vendor_id, po_type) junction — as the authoritati…

- **UI Polish — Support Panel, Trackpad Hint, App Panel Hover, NDA Ctx Dark Mode, Widgets Padding**
  Six small UI fixes and polish passes landed in this session:

- **Share Link og:image Attempt + Regression Fix (BUG C)**
  **BUG C attempt + regression + revert:**

- **Share Link BUG B Redux + Bare Noun-Phrase Document Guard**
  Two fixes completing the Run of Show iMessage pipeline:

- **Run of Show Template v2 — Two-Section Prelim Strips + Shot-by-Shot Breakdown**
  Restructures the Run of Show system template to have two distinct sections, per Mark's spec: "the top part of the run of show system template is the prelim day strips for that day and then under it in the bottom detailed section it should show every strip for every day strip and …

- **Run of Show — iMessage E2E test suite + bug fixes**
  Full E2E test pass of the Run of Show iMessage delivery system against Bash AI (+19728590040). 8 test scenarios × 3 phrasing variants (24 total). 5 bugs found and fixed; 1 open.

- **Run of Show — Mode B Resolution Audit & shots_flat Per-Day Fix**
  Full Mode B field-resolution audit on the All The Way "Schedule / Run of Show" sheet (3f29b830-beb5-4631-b0d9-686799351e27). The sheet is a 7-tab day-repeating workbook (pre-v2 ROS format, created 2026-05-16) with tab IDs ros1__day_<id>.

- **Run of Show — Prelim / Full Display Mode Toggle**
  Adds a **[ Prelim | Full ]** two-state toggle to static CREWDECK.FIELD sections in sheets. The toggle appears on the amber dynamic-range border label (same indicator used for CREWDECK.RANGE sections). Clicking toggles which columns show data.

- **2026-05-17 — Right-panel + apps-panel polish**
  Iterative polish on the universal widgets panel (right side) and apps panel (left side):

- **Universal Remove Confirm Gate — Audit and Fixes**
  Mark's 2026-05-17 directive: every Remove / Delete / Unassign / Revoke action must gate with a custom in-app modal (YES/NO), never a native window.confirm() and never fire with no confirmation. An automated audit across all pages found 6 native confirm() calls plus 2 unguarded de…

- **QR Auto-Generate on Sign With Phone + Dark Mode Sweep (Settings + Orgs)**
  Two improvements to the signature handoff and dark mode coverage on the Settings and Organizations pages.

- **2026-05-17 — PO system full compliance pass (post contractors → vendors merge)**
  The earlier contractors → vendors merge left the back-compat contractors view in a half-safe state: it ran as security_definer (bypassing vendors RLS — a tenant-isolation hole that would have let any authenticated user across all orgs read every vendor via from('contractors')), a…

- **create_placeholder_po: amount + po_type + context-based guess + telemetry**
  Three layered specs shipped together in one feature arc:

- **Pickups: driver_name fuzzy + list_name fuzzy + compound actions + Google Places geocoding**
  After the first pickups parity ship (project_name + list_name on create_pickup_item, auto-create-default-route fallback), Mark surfaced two more gaps: (1) driver assignment was unreachable from natural language because assign_driver_to_list still wanted a UUID, and (2) compound c…

- **Pickups: AI-routable from natural language + auto-resolve list_id**
  After shipping create_todo / create_reminder routing earlier in the same session, Mark flagged that "things like pickups" should also be addressable. Pickups already had a full set of AI tools (create_pickup_list, update_pickup_list, delete_pickup_list, assign_driver_to_list, cre…

- **Org Sheet Designations (Phase 1c.4)**
  Adds a right-click "Set as…" submenu on sheet tiles in the Sheets page, letting org admins/owners designate one sheet per production doc type (Call Sheet, Run of Show, Shot List, Crew List, etc.). Designation is stored per-org in a new org_sheet_designations table with UNIQUE(org…

- **2026-05-17 — Notification feed parity across all pages**
  The in-app notification feed (bell icon + dropdown panel in the shared header — header.html lines 504–521) rendered correctly on /dashboard but was silently empty on every other page (sheets, settings, todos, docs, decks, budget, crew-list, shooting-schedule, communications, orga…

- **NDA Tracker — Right-Click Context Menu, Copy Link, Resend, Delete**
  Adds right-click context menus to every NDA Tracker row, inline action buttons per row, and three new server-side edge function actions to generate signing links on demand, resend invite emails, and hard-delete envelopes.

- **Apply the pickups-template natural-language parity to shot-list, petty-cash, decks, payroll**
  After shipping the pickups deep-parity template (project_name + list_name + driver_name fuzzy resolution, compound-action discipline, Google Places place_id capture, WRITE_TOOL_NAMES registration), Mark asked us to apply the same treatment to every other page from the audit. This…

- **2026-05-17 — Header dark-mode parity across all pages**
  Two pages weren't actually matching the dashboard's #main-header in dark mode, plus four pages had a brief light-mode FOUC on cold load.

- **Cross-task iMessage interference — diagnostic pattern + fix playbook**
  Two Claude Code sessions running E2E iMessage tests against the same Bash AI number (+19728590040) on the same iMessage thread cannot be isolated from each other. The Bash AI processes each incoming message sequentially and replies into the same thread — responses interleave, the…

- **COI residuals — strip every remaining reference from dashboard.html**
  Follow-up to commit 3f920e0 which deleted the four COI HTML/SQL files plus the dedicated coi_tracker widget + renderCoiTrackerContent function from dashboard.html. This pass strips every remaining small COI reference so the surface is truly gone:

- **Designation Chip Pills + File Selector Context Menu + list_sheets AI Tool**
  Third extension on the org sheet designations system. Adds three things:

- **BUG-21 + BUG-22 root cause fix — write-intent TOOL_REQUIRED_PATTERNS + todo PHRASE MAP + must_say enforcement**
  Round-2 smoke test (75c5569) left BUG-17 (must_say caveat-elision), BUG-21 (create_placeholder_po + create_todo refuse to fire), and BUG-22 (vanilla LLM persona instead of Bash) open. Root cause for BUG-21 + BUG-22 was identical: TOOL_REQUIRED_PATTERNS at ai-agent/index.ts:6794 o…

- **BUG-079 — Formula Engine Day-Bleed Fix (Non-Active Tabs)**
  Fixes **BUG-079**: in a day-repeating sheet (e.g. Run of Show with 7 day tabs), =CREWDECK.FIELD(...) cells on non-active day tabs resolve using the *active* tab's day context instead of each tab's own day. Symptom: every tab shows the same time value — e.g. day30, day31 … all sho…

- **Budget Section + Line Item AI Tools; Scout-Link Fix**
  Closes two high-severity AI tool gaps from the 2026-05-17 Part B meta-audit:

- **Beta Invite — Pre-Clear NDA Gate for Already-Signed Emails**
  When an admin sends a beta invite to an email address that already has a completed signed NDA (standalone or beta type), the invite flow now proactively stamps beta_nda_signed_at and beta_nda_envelope_id on the profile at invite time. This means the NDA gate is already cleared wh…

- **Auto-Designate on Sheet Creation from Typed Template**
  Extends the org sheet designations system (70ec26b) with an auto-designate flow: when a sheet is created from a system template that carries a canonical doc_type, and the org has no designation for that doc type yet, the user is offered a non-modal banner (UI) or a YES/NO follow-…

- **Attach Sheet Context Menu + AI attach_sheet Tool**
  Adds the parallel UX to "Set as…" for the file-upload path: right-clicking on the blank sheet-list area now shows "Attach Sheet as…" with the full 18-type doc-type submenu. Clicking a doc type opens the Import & Analyze modal pre-bound to that type, so upload + designation comple…

- **Widgets System — Phase 4 E2E Bug Fixes + iMessage Confirmation Flow**
  This session covers two work blocks:

- **Widget Exhaustive Audit — Universal Panel Parity + Mobile Panel Expansion**
  Exhaustive audit of the two widget systems (universal sidebar and project-detail) plus full cross-page universal panel parity sweep. Added initUniversalRightPanel to 24 pages that were missing the desktop right widget drawer. Added full mobile swipe panel support (loadMobilePanel…

- **Project-wide Todos System**
  Lands the full Todos system: a single public.todos table backing a dedicated /todos page (list + kanban + grouping + bulk actions + detail panel + new-todo modal), a 10-tool AI-agent family (create/update/complete/cancel/assign/list + bulk_create_todos + 3 auto-generation tools),…

- **Todos — Delegation Expansion**
  Adds role-aware delegation on top of the Todos system. New schema (todos.watchers UUID[] + public.org_delegation_rules with 15 canonical seed rows per org) drives 7 new AI-agent tools (auto_delegate_todos, bulk_assign_todos, reassign_by_role, list_todos_by_assignee, suggest_deleg…

- **Sheets: source-import backlink, View source toggle, re-share tighten**
  Closes the gap from the 2026-05-15 Sheets import-fidelity audit: the sheet-imports bucket already preserves the original XLSX/PDF/DOCX blob, but sheets rows had no pointer back. This change

- **Sheets pixel-perfect Phase 1 — respawn verification closure**

- **Right-click "Exclude from dynamic range" with confirmation modal + immediate re-render**
  Mark requested a top-level right-click menu item that excludes the row backing the right-clicked cell from a Mode B dynamic_range materialization, with a custom confirm/cancel modal and an immediate re-render so the row disappears without a manual page refresh. This wires a disco…

- **Sheets AI tools — coverage audit + 12 new atomic tools (Tier 1 + 2 + 3 subset)**
  Audited every user-invokable manual action on sheets.html (164 distinct affordances in main table + ~50 in Appendix A–J primitive sub-actions = ~214 total) against the existing ai-agent tool registry. Found 13 sheet-relevant tools out of ~200 total, all scoped to typed sheets (ca…

- **Script Breakdown — 7 Deferred Items Closed — 2026-05-16**
  Closed all 7 deferred items from the 2026-05-15 E2E. Expanded the engine from 6 to 14 production categories, fixed visual highlight alignment, populated the breakdown_scenes table, auto-resolved deck_id from the deck editor, added an AI-agent tool for chathub invocation, verified…

- **AI-driven scheduled actions — defer any tool to fire later**
  Sibling to the reminders system shipped earlier today: where reminders ping the user passively, **scheduled actions execute any ai-agent tool on the user's behalf at a future time**. The user says "onboard Jack tomorrow morning" over iMessage and Bash routes the request to schedu…

- **Shooting Schedule — Redesign + AI Assistant (rolling)**
  A full sweep of /shooting-schedule.html: feature audit, broken-feature inventory, redesign to current CrewDeck visual language, dedicated AI footer assistant tuned to scheduling, Mode A list-view parity with budget.html, and end-to-end AI tool coverage for every manual action. Ma…

- **Reminders — Confirmation YES Repeated via Slow-Path Gap**

- **AI-driven reminders system (Phase 1)**
  AI-driven personal reminders system. Bash can now schedule, list, update, cancel, and snooze reminders for the user, and proactively offers to remind them when they defer an action ("I'll do that later"). Fires via a one-minute pg_cron worker that dispatches to the user's preferr…

- **Reminders — Org Scope, Group-Chat Collapse, iMessage Confirmation Flow**
  Three scope additions on top of 2026-05-16-reminders-notifications-router.md:

- **Reminders — Notification Router + Tool-Call Enforcement**
  - **E — Tool-call enforcement**: Strengthened REMINDER_OFFER_RULE (fast + slow path) and fpActionHonestyRule in comms-analyze + REMINDERS context block in ai-agent to require create_reminder be called in the same turn, prohibit vague future-tense promises, and mandate echo-back o…

- **Reminders — Direct-Fire: No YES/NO Confirmation Gate**

- **Reminders — Approach A: Server Pre-Compute fire_at (Training Chat 29 follow-up)**

- **PO Document-Type Classifier + Receipt-Pending Flow**
  Extends the multi-vendor PO import flow (shipped 2026-05-16, commit 03ca9b1) with document-type classification. When a single attachment is used to create multiple POs, the AI now classifies it as receipt, final_invoice, or source_only (default). Source-only documents (PO logs, r…

- **PO Multi-Vendor Single-Attachment Import**
  Previously the AI could only create one PO per attachment. If a user sent a PO log, rate sheet, or any spreadsheet/PDF containing multiple vendors, it would produce a single PO for the whole file. This change adds batch_create_pos_from_single_attachment — the inverse of the exist…

- **Placeholder PO — position resolution + confirmParams fast-path**
  Three related fixes for the placeholder-PO flow (create_placeholder_po):

- **create_placeholder_po AI Tool**
  Adds a create_placeholder_po AI tool that creates placeholder purchase orders for unfilled crew positions or specific crew members. Two modes:

- **iMessage Dispatch classifier — spawn Tasks-tab tasks from inbound iMessages**
  Closes Phase A of Mark's scope expansion making **iMessage threads a Dispatch surface** alongside the in-app Dispatch chat tab (shipped earlier today as 0b3ba30). When an inbound iMessage's orchestrator intent resolves to direct_reply (i.e. not handled by comms_create_chat, statu…

- **Fix: iMessage image search now delivers real photos via Unsplash API**
  When a user asked the CrewDeck AI via iMessage to "send a photo of X", it was attaching a "search content · 91 KB" file with a question-mark icon instead of a real image. Root cause: the previous implementation used Claude's web_search_20250305 tool to find an image URL, which fr…

- **Fuzzy sheet-name resolution, publish-on-demand, tool-required tier flip, and access-control bake-in**
  Four coupled fixes — three closing the deferred follow-ups from the 2026-05-15 Run of Show audit (docs/changelogs/2026-05-15-run-of-show-bake-leak-fix.md), plus a critical Phase 5.8.1 access-control bake-in (Mark's same-session addendum) that prevents the new fuzzy matcher from l…

- **feat(comms): fetch_listing_photos — pull full gallery from Giggster/listing URLs via iMessage**
  When Mark or a crew member sends a Giggster listing URL via iMessage (or asks "get photos from this Giggster listing"), the CrewDeck AI now pulls ALL gallery photos from that listing and delivers them as a multi-image MMS via Blooio's attachments[] array.

- **Docs AI tools — coverage parity audit (18 new tools + surface preamble + 2 bug fixes)**
  Mirrored the recent crew-list AI-coverage audit (docs/changelogs/2026-05-15-crew-list-ai-tools-coverage.md) onto docs.html. Enumerated every user-invokable manual action on the page — **174 distinct affordances across 17 categories** — and closed every backend-reachable coverage …

- **Dispatch chat → auto-spawn Tasks**
  Closes the gap the prior PM_SYSTEM_PROMPT self-described: *"Background-task spawning lights up in a follow-up phase; for now stay conversational."* When the user sends a message in the ChatHub's **Dispatch** tab, the model now classifies the request into 0, 1, or N work tasks and…

- **Crew-list: hire-fill lifecycle, breakdown→crew integration, AI animation tokens**
  Three parallel sub-tasks shipped as one commit:

- **Comms: pre-resolve asker crew row + current-message focus hardener**
  Two distinct bugs surfaced in TRAINING CHAT 29 (thread 4a0e2f5c-b364-4dfb-b654-246c4e805ba1):

- **ChatHub process transparency — render SSE events across every web AI surface**
  Mark's verbatim: "Make sure the ai chat hub shows the processes the ai is taking like dispatching parallel agents and also what it's thoughts are in the process. It needs to be transparent about where it is in the process in the chat." This shipped exactly that — every web AI sur…

- **Call sheet schedule section now renders example strips when shooting_schedule is empty**
  Bug report (Mark, 2026-05-16): "It's not showing the schedule dynamic range on the unpublished version" — screenshot of the Snipes Holiday Supplemental call sheet rendered at afbclfjxwvqkfzjwpaec.supabase.co showed every section present (PRODUCTION, TALENT, CLIENT, etc.) except R…

- **VPS-only files recovery + visualizations.html drift + cleanup findings**
  Follow-up to 2026-05-15-ai-engine-drift-recovery.md. After recovering the 10 drifted ai-engine files, this audit hashed every .html/.js/.css on the VPS (322 files) and compared against main (297 files). Findings:

- **Template-driven chat creation: iMessage + Web AI now use department templates**
  Vision: a user in iMessage (or the web AI Chat Hub) can say *"start a chat for camera department for snipes"* and the AI looks up the message_templates row attached to the Camera department, looks up the crew assigned to Camera on the Snipes project, and presents a complete confi…

- **2026-05-15 — Standalone script breakdown + bid/project/save outcome**
  A new top-level surface — /breakdown.html — lets a producer paste or upload a script and run the 6-pass AI breakdown without first committing to a project or a document template. After the breakdown finishes, a modal offers three outcomes:

- **sheets-export-pdf — weather-card layout + WebP logo support**
  Two visual fixes to PDF exports observed on Snipes Holiday Supplemental call sheet:

- **AI-exported call sheet PDF: schedule section now passes through template rows**
  Yesterday's fix (c69a710, 2026-05-14-pdf-weather-schedule-fix.md) restored the SCHEDULE section to the AI-exported call sheet PDF by adding a custom buildScheduleSection that synthesized rows from schedule_versions / shooting_schedule DB strips. That brought the section back, but…

- **sheets-export-pdf — schedule strip styling (style IDs + per-strip_type tints)**
  Two-step fix to the PDF export's RUN OF SHOW / schedule section. The prior session (3cd35df) wired the section to render dynamic DB strips instead of static template rows, but the cells were assigned the wrong style IDs and every strip rendered with the same flat gray background …

- **sheets-export-pdf — page-resolver parity (weather card layout + crew toggles + production team)**
  Two sweeps to bring the PDF Edge Function output in line with what users see on sheets.html:

- **Sheets page dark-mode polish — editor goes dark, Print Preview added, Publish redesigned**
  Mark asked for the same dark-mode treatment we gave the dashboard, then refined the ask several times as I iterated. The final state:

- **Script Breakdown E2E Test + Parser/Persistence Fixes — 2026-05-15**
  Walked the script breakdown feature end-to-end on docs.html (standalone launcher path + Doc Assistant chat path) and on decks.html (polymorphic deck-surface path). Confirmed architectural separation: script breakdown and placeholder analysis are independent AI tasks, modules, UI …

- **"Save this chat as a template" — new orchestrator intent + gather flow**
  Users can now ask the iMessage AI to save the current chat as a message_templates row — e.g. *"save this chat as a template called Camera Crew Intro and make it the default for camera"* — and the AI gathers anything it needs, shows a review card, then writes the template (plus th…

- **Drop per-page top realtime dot; route status through footer Live indicator**
  Each page used to render its own top-of-page realtime-status-dot (red when disconnected, green when subscribed). On pages like purchase-orders.html that don't subscribe until the user selects a project, the dot stayed red on first load — looked like a broken indicator. The shared…

- **PO Top Sheet xlsx + Download All POs ZIP + wrap-rule naming conventions**
  First session of the PO/Wrap sprint. Implements the file-naming, folder- structure, and top-sheet pieces Mark gave verbatim. Future sessions cover wrap workflow (notes + budget/spent/saved), petty-cash parity, and AI statement reconciliation.

- **PO polish — logo aspect, signature placement, NDA-gate-matching e-sign, PDF bundle**

- **PO PDF — exact xlsx match via LibreOffice on the VPS**

- **Full PO flow E2E: fresh project → Hot Budget template → sync → modal → export**
  End-to-end exercise of the PO page from an empty project all the way through sync → modal verification → manual PO → Hot Budget export → 3 download formats. Verified the placeholder sync fixes from earlier in the session work against a real project that uses the Hot Budget AICP S…

- **Purchase Orders page — full E2E test report**
  End-to-end test of everything shipped to the Purchase Orders page in this session: custom confirmation modal, kind taxonomy in the Type field + Description column, Hot Budget AICP Standard global template, Hot Budget PO Log export with dynamic budget-driven banners, per-PO po_log…

- **PO multi-line placeholder POs + full modal rebuild (native CrewDeck aesthetic)**
  Three interlocking changes shipped in one session:

- **PO Log export now uses the project's actual budget sections**
  The first cut of export-po-list hardcoded 9 banner sections that mirrored Mark's GOODCO wrap binder. That works when there's no budget on the project, but ignored the fact that every CrewDeck project that does have a budget already has its own section taxonomy (e.g. AICP A–N, Hot…

- **PO top sheet — full field coverage + e-sign approval signature + org/project logo swap**

- **PO page: custom confirm modal + kind taxonomy as the visible "Type"**
  Two user-visible cleanups on the Purchase Orders page that landed together because they touch overlapping JS:

- **PO AI Tools Coverage — 16 new tools + create_purchase_order extension**
  Closes the gap between what users can do on purchase-orders.html and what the AI agent can do from the web AI Chat Hub + iMessage. Adds 16 new tools to ai-agent/index.ts and extends create_purchase_order to optionally seed line items in one call. Tier convention follows the lite/…

- **Phase 5 — Batch attachment handling + parallel PO creation**
  Drop N receipts/invoices/W-9s on the AI search bar (or paste them in ChatHub or iMessage), ask "make POs from each on this project", and the AI now spawns a **task with parallel sub-agents** — one per attachment — capped by the org's agent_concurrency_settings.max_concurrent_agen…

- **Phase 5.5 — Plan rule + iMessage + live task card**
  Three small but high-value follow-ups to Phase 5g (batch PO creation):

- **PO AI deep E2E test pass — 6 bugs found + fixed**
  Hammered every PO AI tool with multi-turn process flows (not single-shot prompts). Each flow drives through follow-up questions and DB verification. **6 real bugs found, all 6 fixed + deployed** + 2 minor UX nits documented for later.

- **Placeholder sync now round-trips the budget line linkage end-to-end**
  Mark asked me to "make sure the placeholders sync fills their linked budget line in the modal." Investigation showed the sync edge function (sync-placeholder-pos) was already doing the right thing at the data layer — it inserts po_line_items rows with budget_line_item_id set on e…

- **Org-toggled placeholder PO sync + reverse-sync trigger + manual sync buttons**
  Builds on 21de42f (2026-05-14 — per-kind position links + forward auto-PO creation) by adding the reverse direction and the manual control surface.

- **Placeholder expert mode — content-presence filter + AI commentary noise gate**
  The 25-page screenplay run on 2026-05-15 fully passed (218 tags, outcome modal opened), so we moved to the second half of the verification task — running a real contract through the placeholder expert mode end-to-end. The test exposed two leak paths in the markdown-fallback parse…

- **Petty cash requests + 6 funding pipelines — schema foundation**
  Mark shared the GOODCO PC PETTY CASH FORM.xls — a classic film/TV petty cash envelope reconciliation sheet — and asked for two things:

- **Hot Budget PO Log export (export-po-list edge function + dropdown)**
  Replaces the single "Export" button on the Purchase Orders page with a split button (Hot Budget XLSX by default + ▾ menu for Showbiz / Generic + kind filter chips). The Hot Budget format is the one Mark uses for wrap binders; it clones the styled PO LOG sheet from his master-shee…

- **Hot Budget AICP Standard — global system template**
  Imports the full Hot Budget AICP commercial-production budget structure as a system template visible to every CrewDeck workspace. The template lives at budget_templates with is_system=true, organization_id=NULL, user_id=NULL, so the existing RLS read policy (budget_templates_read…

- **Ask "distribute contact cards?" before the chat-create review card**
  The iMessage comms_create_chat flow used to jump straight from participant resolution to the full review card, with SEND CONTACT CARDS defaulting from the org's ai_defaults.contact_cards_default (itself defaulting to YES when absent). Users had no in-flow prompt to make that deci…

- **Footer AI button — visible on every page + Chat Hub chevron + draft guard**
  Three coupled changes that roll out the existing AI Chat Hub to every page:

- **Footer AI button — cross-editor audit + ai-engine drift finding**
  After the footer AI rollout (c6383a4) shipped, the user asked to verify the button still works on every editor that previously had it (docs, decks, emails, budget, payroll, purchase orders, invoice, etc.). The audit confirmed:

- **Font registry: shared 28-font picker across docs.html and sheets.html**
  Adds /js/fonts.js as the canonical 28-font registry shared by both the docs editor (TinyMCE) and the sheets editor (Univer). Replaces the docs editor's hardcoded 17-font picker (mostly legacy system fonts including Webdings, Wingdings, and Symbol) and Univer's bundled defaults (1…

- **2026-05-15 — Docs page E2E audit, send-modal fixes, breakdown schema groundwork**
  Thorough E2E pass over docs.html: opened every menu, tested every toolbar control, exercised the Editor/Preview toggle, Source Code modal, Share modal, Send-for-Signature modal, the four tabs (Templates / E-Sign / Sent / Signed), Select Project dropdown, + New Template flow, the …

- **Docs page (TinyMCE editor) dark mode + View › Print preview**
  Mark asked the docs page to follow the same dark-mode treatment as the sheets page but with a sharper requirement: in dark mode the **editor itself should be dark, with light font color regardless of any authored inline color**; **Print preview** should flip back to white paper w…

- **Day-rate two-way binding (crew ↔ budget_line) + canonical onboarding notification rule**
  Two related follow-ups to the Crew List AI surface that landed in local_6691c713.

- **Move Plans from dashboard.html into the AI ChatHub**
  Mark wanted Plans (ai_orchestrations) to live in **one** canonical place — the AI ChatHub — instead of being split between a tab on the dashboard and an inline section in the chathub's left rail. This change rips out the dashboard's Plans workspace tab entirely and promotes the c…

- **Dashboard dark-mode polish — 3 deploy passes**
  Mark caught a stack of dark-mode visual regressions on /dashboard during the AI search e2e and asked me to chase them until every visible element looked good in dark. The dashboard's critical dark-mode CSS only mapped a tiny set of utility classes (bg-white, bg-gray-50, text-gray…

- **Crew List AI tools — coverage parity audit (7 new tools + surface preamble)**
  Audited every user-invokable manual action on crew-list.html (91 distinct affordances across 12 categories) against the existing ai-agent tool registry (~60 crew-relevant tools). Closed seven Tier-1 coverage gaps so every manual action on the page now has an atomic, intent-mapped…

- **Crew List AI Surface — footer-button launcher with crew-list-tuned context**
  Wired the shared AI engine into crew-list.html so the footer AI button now opens a Crew AI panel with full PO/sheets/docs visual + interaction parity. The surface is tuned to crew-list workflows: payroll routing (PO contractors vs Wrapbook W-2), multi-rate day rates (prep/shoot/w…

- **Changelog — Comms Pending-Proposal Persistence 2026-05-15**
  Three-layer fix so the AI can resume a pending proposal hours or days after offering it, instead of dropping the context after a few minutes.

- **Bash silent drop on context-dependent follow-up questions**
  After today's 8f2d1a4 ("For sure 🙌" affirm/decline pre-check) and ca8bb1a (pending proposal TTL) fixes shipped, Mark hit a different silent-drop pattern in TRAINING CHAT 29:

- **comms-analyze: forbid bullet-style suggestion lists + persona-name self-prefix in iMessage replies**
  TRAINING CHAT 29 regression — two distinct iMessage formatting bugs in the same screenshot:

- **ChatHub: split rail into 3 tabs (Tasks / Dispatch / Plans), rename PM chats → Dispatch, custom modals**
  Builds on the 2-tab Chats/Plans split that shipped earlier today (8b3e8f9 + 04ac900, see docs/changelogs/2026-05-15-dashboard-remove-plans-chathub-plans-tab.md and the schema-fix follow-up). Per Mark's coordination spec, this change:

- **Full chat-create gather flow (name → people → first message → project → vcards) + template shortcut**
  Before this change, asking the AI to start a chat with vague input (*"can you start a new chat bash"*) produced a half-empty confirmation card — default name New Group Chat, just the sender, PROJECT: N/A — and the user had to revise it field-by-field via free text on the review c…

- **2026-05-15 — Breakdown Phase 4 follow-ups: stripboard import, crew suggestions, call-sheet flex fallbacks**
  Ships the user-controlled half of the breakdown integration:

- **2026-05-15 — Breakdown Phase 4 build: AI tool + call-sheet hooks + readiness widget**
  Shipped the foundation for the breakdown → production pipeline:

- **2026-05-15 — Breakdown Phase 4: budget materialiser + web-search task + pickups optimization pitch**
  Shipped two of the three held items (budget materialiser, web-search task) and presents the design pitch for the third (pickups optimization) below for approval before building.

- **Breakdown decks parity — polymorphic `source_type` on `script_breakdowns`**
  Mark's scope clarification on 2026-05-15: the script-breakdown feature should work on **both** docs.html and decks.html — a treatment can live on either surface, and the persisted breakdown row needs to record which one it came from so downstream consumers (get_project_breakdown …

- **Bid mode budgets fully working: persistence + reload + award migration**
  This session fixes the four bugs that the 2026-05-15 bid-to-pay E2E test flagged as blocking the full bid → award → project flow on budget.html:

- **Bid-to-Pay E2E Test — 2026-05-15**
  Walked the production bid → budget → award → link → onboard → PO → petty cash → export → header flow end-to-end on Friends Unknown. Twelve phases collapsed into nine. Found and patched two P0 blockers inline (RLS-rejected bid insert + non-existent projects.status column) plus one…

- **Bid-to-Pay E2E Re-run — 2026-05-15**
  End-to-end re-test of the bid → award → onboard → PO → pay flow after the 2026-05-15 e9444dd bid-mode persistence fix. The bid loop that previously failed (BUG-03/06/07/08/09) is now **fully passing in production**. Walked all 8 phases on a fresh bid through to a paid PO and conf…

- **AI header search — planned queries escalate into ChatHub with agentic on org-opt-in**
  The header AI search already classifies the user's intent as planned (multi-step) or direct (single-shot) via ai-orchestrate-classify. Before today, planned opened the AIChatHub with the query pre-filled in the input — the user still had to press Enter, the new thread had agentic…

- **AI lite-tier dark mode toggle from chat (PM ChatHub)**
  The PM AI ChatHub on the Sheets page (and everywhere else) refused to toggle dark mode when the user asked: it replied "I can't change your display settings directly — go find a toggle in user settings." Mark reported this with agentic mode ON, expecting the AI to be able to take…

- **Add: `ai_imessage_context_loaded` log row when ai-agent runs in iMessage context**
  Follow-up to the 2026-05-14 iMessage thread-context auto-fill fix. The four delivery tools (export_sheet_pdf, send_imessage, reply_to_message_thread, create_sheet_share_link) now silently fall back to ctx.commsThreadId when the agent omits thread_id. Silent fallbacks are a regres…

- **`/js/ai-engine/` drift recovery — pulling live VPS state into main**
  The 2026-05-15 footer-AI cross-editor audit (docs/changelogs/2026-05-15-footer-ai-button-cross-editor-audit.md) discovered that the live VPS holds substantial unmerged work across the entire /js/ai-engine/ tree — same regression class as the 2026-05-11→13 meeting-bot incident. Th…

- **ai-agent `export_sheet_pdf` accepts `project_name` fallback + compound-phrase parsing guidance**
  The export_sheet_pdf tool previously required a resolved project_id, which forced the model to either silently fail or hallucinate when the user named a project conversationally ("send me the snipes tech scout PDF"). Two regressions stemmed from this: (1) the model would pack the…

- **AI Header Search + ChatHub end-to-end test pass + 3 inline bug fixes**
  Exhaustive end-to-end test of the two AI surfaces that ride on every page — the header search bar (js/header-ai-search.js) and the full ChatHub modal (js/ai-chathub.js) — using Chrome MCP only per the project rule. 60 discrete test cases, 34 PASS, 5 FIXED-INLINE, 21 DEFERRED (mos…

- **Fix: chat-rename vs MCL person-name routing; vCard auto-promote suppressed by resolve_contact**
  Three bugs surfaced when testing "Bash can you change Sneha's name to Snej":

- **Fix: AI agent sends wrong call sheet when user names a specific day type**
  When a user texted "Bash can you send the call sheet for snipes tech scout pls", the AI agent sent the "Snipes Holiday Supplemental — Shoot Day 1" PDF instead of the Tech Scout sheet. The root cause was a missing parameter: the export_sheet_pdf tool schema only exposed a day inte…

- **Website field end-to-end + vCard pipeline wiring**
  Added a website column to both master_crew_list and crew tables, plus a Website input field in the crew detail modal on crew-list.html. Wired the field through all save/sync paths (modal save, spreadsheet save, master crew sync, artist auto-insert) and into the vCard generation p…

- **sheets.html / sheets-flex-cells.js — Weather color persists; production-company logo COALESCE**
  ### Weather cell color persistence (4 bugs fixed across 4 commits)

- **sheets.html — Weather cell formatting persists and propagates across modes**
  Weather flex cells had no persistence mechanism for user-applied styling (background color, font color, etc.). Each reload reverted to the schema default. Two scenarios are now handled:

- **voice: wavy background animation driven by mic + AI audio**
  Replaced the static frosted-glass voice overlay with a live canvas animation that reacts to both the user's microphone and Gemini's audio output. Two wave sets — indigo for mic, emerald for AI — rise from the bottom of the overlay in proportion to the current audio volume. When t…

- **voice: full tool parity with chat AI (22 new tools)**
  The voice AI previously had only 2 tools (create_project, create_bid). This session brought it to full parity with the chat AI by auditing every tool in ai-agent and implementing all high-value capabilities directly in gemini-live.

- **voice: fix project creation + ripple ring animation**
  Two changes shipped in this session:

- **voice: wire Gemini function calling to real agentic execution**
  The voice AI was hallucinating agentic actions — saying "I've created the project" without actually doing anything. Root cause: no execution layer existed between Gemini's spoken response and the database. Fixed by wiring Gemini's native function-calling API (toolCall / toolRespo…

- **sheets-export-pdf — normalize hyphens in day_label matching**
  When a caller passed day_label (e.g. "tech scout") to the PDF exporter, the lookup did a case-insensitive substring match against the sheet's day name. That failed when the stored name contained a hyphen (e.g. "Tech-Scout 1") because "tech-scout 1".includes("tech scout") is false…

- **sheets.html — Organization Dashboard always visible in avatar menu**
  The "Organization Dashboard" link (#user-menu-org-owner-section) in the sheets page avatar dropdown was invisible for users who had never visited organizations.html. Root cause: populateHeaderData internally calls _revealOrgOwnerLink(), which only shows the section when localStor…

- **Onboarding → form_invites pipeline + Onboard form protection**
  Fixed the crew onboarding flow end-to-end. The onboard-crew edge function was creating onboarding_tokens records and sending emails with /forms.html?token=<token>, but forms.html validates against form_invites.magic_token — a completely different table. Every onboarding link prod…

- **Mobile bottom nav: actually wire up the AI Voice tab on every page**
  The earlier "fix" (handler clicks #ai-voice-chat-btn) did not actually help, because the document-level click listener for #mobile-tab-ai is registered inside _initTabBarListeners(), which was only invoked from populateHeaderData(). Dashboard.html (and likely several other pages)…

- **Mobile PDF viewer + publish UI polish**
  Four incremental improvements to the mobile call-sheet experience, all in sheets.html. The PDF iframe now starts at a more zoomed-out initial view without shrinking the viewer area; pinch-zoom inside the PDF no longer triggers page zoom; and the Publish popover was rebuilt as a p…

- **Meeting Bot — Recall.ai integration end-to-end**
  Wires up the dashboard meeting-bot widget that has been sitting half-built since cd0175f. Pasting a Zoom / Google Meet / Teams URL into the widget now actually invites a Recall.ai transcription bot to the call. When the call ends, the transcript is pulled, sent to Gemini Flash fo…

- **Implicit command detection + position update + attach/detach project to chat**
  Four features + two hotfixes across five commits addressing group chat UX, crew/project management via iMessage, voice AI project context, and iMessage pipeline bugs.

- **gemini-live: restore `--no-verify-jwt`; document the rule so it can't be dropped again**
  All realtime voice sessions site-wide were failing with "Could not connect — check your connection." The previous mobile-nav fix correctly opened the overlay and ran _vcOpen/_vcStart, but the WebSocket to wss://…/functions/v1/gemini-live died at the Supabase gateway with close co…

- **ai-billing: log provider fallbacks to ai_activity_log**
  **Context:** Investigation found that Gemini 2.5 Flash (agentic_inference) is failing 57% of the time and silently falling back to Claude Sonnet 4.6, which then also hits rate limits. The fallback error was only logged to console.warn — invisible in the DB.

- **Forms: Share button opens invite modal**
  The Builder's Share button (#fb-share-btn, visible in Mode A — unscoped/org-level forms) was wired to openSharePanel(), which silently copied an edit-link to the clipboard. The visible "Link copied!" toast was easy to miss, and the more useful behavior — opening the existing "Sen…

- **sheets-flex-cells.js — priority_list flex cells show =CREWDECK.FLEX(...) when editing**
  priority_list flex cells (including client logo and production company logo cells) were written as bare values by applyAll — no formula. When the user clicked into one to edit it, the formula bar showed the raw resolved string (a logo URL, a field value) rather than a CrewDeck fo…

- **Flex cell context menu — smart actions per cell type**
  The Univer right-click context menu now adapts to the cell being right-clicked. When the cell is already a flex cell the creation options (Insert placeholder, Find placeholder, AI cell, Dynamic range, Flex cell) are hidden and replaced with cell-type-specific actions: weather fle…

- **dashboard: fix three runtime errors (shoot_date column, collapseProjectDetailView scope, gemini-live model)**
  Fixed three runtime errors reported from the dashboard console.

- **crew-list.html — remove inline header overrides, delegate to shared modules**
  crew-list.html had a large block of inline header logic that duplicated and in several cases shadowed the shared globals in header-nav.js and spotlight-search.js. The local ALL_APP_DEFINITIONS was missing six apps (Communications, Visualizations, Decks, Sheets, Bids, Payroll). Th…

- **Fix: iMessage delimiter leak (round 2) + agent "I need the thread ID" hallucination**
  Two bugs reported by the user immediately after the morning's comms-analyze fix:

- **comms: conversational one-question-at-a-time comms_create_project flow**
  Replaced the single-shot review card with a proper conversational gather flow. Each field is collected in a separate message, waiting for the user's reply before asking the next question.

- **Fix: strip find_project JSON metadata from web chat responses**
  When the AI agent calls find_project, it can append a structured JSON object to the response text containing fields like activeProjectId and entities. The _extractEmbeddedViz function in spotlight-search.js is responsible for stripping this trailing JSON before rendering — but it…

- **Budget line ↔ crew position ↔ onboarding ↔ PO auto-creation**
  A budget line can now be linked to a crew position **and** a payment-kind (Rate, Kit Fee, Box Rental, Mileage, Per Diem, Car Allowance, Other Allowance). That single decision drives three downstream behaviors:

- **Rich weather widget in call sheet**
  The call sheet weather cell previously rendered plain text (e.g. "Scattered clouds"). It now renders a Google-style card overlay in the sheet: an SVG condition icon, the high temperature in large type, H/L range, condition label, and sunrise/sunset times — all on a light blue-gra…

- **May 13 Session Batch — NDA IDV, Standalone Send, Carry-Over, Comms AI, UX Polish**

- **comms: regex pre-classifier + fuzzy project matching + rate-limit error fix**
  Three fixes to the comms iMessage pipeline addressing rate-limit exposure, project name resolution, and error classification.

- **comms: client creation multi-turn flow + iMessage logo upload**
  Two new features built on top of the comms_create_project agentic flow.

- **Changelog — sheets-export-pdf template org_id Filter 2026-05-11**
  Second-stage fix from the iMessage call-sheet flow. After the [orchestrator status_check guard](2026-05-11-comms-orchestrator-status-check-guard.md) landed, the agent correctly classified Mark's "send the call sheet for the All The Way shoot" as comms_export_pdf and spawned the t…

- **ID Scanner: Drop AI pipeline, ship pure classical CV**

- **Changelog — Comms Orchestrator status_check Guard 2026-05-11**
  Fixed a regression where iMessage requests like *"Bash, can you send the call sheet for the All The Way shoot?"* were silently dying with the hardcoded reply *"Nothing running at the moment — what do you need?"* — completely bypassing the ai-agent flow that should look up the pro…

- **Changelog — Permission Gate + Two-Message Link Split + Brand Fallback 2026-05-11**
  Three layered changes to the iMessage call-sheet-send flow, all rolled into one wrap-up:

- **Signing Flow: Document Preview + Phone-to-Computer Handoff**

- **Phone-as-Camera Handoff for ID Scanning**

- **E-Sign Bulk Send — Phase 6 (2026-05-10)**

- **2026-05-10 — docs.html AI Surface: Breakdown, Placeholder Finder, Import & Analyze**

- **Beta NDA Gate + Manual Send Template**

- **Changelog — Audit Remediation 2026-05-10**
  Closed all 4 critical deployment flags and resolved 7 feature gaps surfaced by the 2026-05-10 audit. Score improved from 5/15 LIVE to 12/15 LIVE.

- **Universal Right Panel — Widget Registry Architecture**
  Introduces a universal right-side panel with a self-registering widget architecture. Every non-dashboard page gets a Workspace drawer (desktop: slide-in panel triggered by a toggle button in the header; mobile: auto-populates #mobile-sidebar-panel). The panel is driven entirely b…

- **Unified Share System — v1 Changelog**
  Single unified sharing layer for docs and sheets. One module (js/share-system.js), one edge function (unified-share), two DB tables. Progressive outside-org detection with inline prompts. Bundled magic-link email — one click accepts resource access + optional org join + optional …

- **Changelog — Recipient Portal v1 + budget.html Mobile Pass**

- **Petty Cash → Actuals Budget Link Fix**

- **Payroll Page + Wrapbook Integration (Phase 1)**
  Introduces the Payroll page and all scaffolding for the Wrapbook employer-of-record integration. W-2 crew are tracked via wrapbook_payroll_runs; LLC contractors remain on the existing PO path (crew.payroll_route = 'po'). Phase 1 ships a full manual-entry workflow with budget reco…

- **feat(comms): per-org AI default toggles for new chat threads**
  Adds per-org AI default toggles surfaced in the AI Controls section of organizations.html. Four toggles — Analyze new threads, Auto-participate, Agentic mode, Contact cards — control the initial state seeded into the chat-create review card whenever comms-analyze creates a new iM…

- **Header Nav — Rename "Onboard Form" to "Forms"**
  The global header "Onboard Form" app menu button has been renamed "Forms" and now links to /forms.html (the new forms engine UI built in the Forms Engine P1 task). The old onboard.html page remains live for backward compatibility but is no longer linked from the primary navigatio…

- **Global Trackpad Swipe-Nav Guard**

- **Forms Engine — Phase 1**
  Full forms engine: schema, edge function, builder UI, runner module, 5 built-in templates, and magic-link invite flow. Admins build data-driven forms with a drag-drop canvas, publish them, and send per-recipient invite links. Recipients open a clean mobile-first form via a single…

- **E-Sign System — Full Platform Launch**
  Full end-to-end electronic signature system built in one pass. Legal posture is full ESIGN Act (15 U.S.C. § 7001 et seq.) / UETA compliance from day one — no preview mode. System features cryptographically chained audit events (SHA-256 hash chain), per-signer one-time JWT signing…

- **fix(comms): chat-create card toggle defaults YES + restore PROJECT line**

- **BG-007: Restore cellStartEdit actual-readonly guard**

- **Sheets Publish Gate + Comms AI Fixes**

- **Sheets — Logo Cells: Text Fallback When No Logo on File**

- **Sheets Export PDF — Always Regenerate, Deterministic Filename, CDN Cache-Bust**

- **Fix: Add Day modal — day type picker no longer shows duplicates**

- **Changelog: Comms Export — PDF + Share Links from iMessage**

- **Sheets Provenance — "View plan" link + schema FK**
  Hardened the "How was this made?" right-click provenance dialog in Sheets to link back to the originating orchestration plan when an AI edit was made via an orchestration. Adds a created_by_orchestration_id FK to sheet_change_sets so the dialog can batch-fetch pitch_token_hash an…

- **Track 2 Hardening — Nine Items**

- **Phase 5.8 — Archive Viewer + Provenance**

- **Phase 5.7 — Parallel Sub-Agent Coordination**
  Hardens parallel sub-agent dispatch with write-region overlap detection, a dependency graph, cross-sub-agent messaging, optimistic concurrency control, and graceful failure recovery. Implements §2.13 parallel AI cells, R37 overlap enforcement, and R45 version-conflict protection.

- **Phase 5.6 — Designer + Placeholder Modes**

- **Phase 5.2 — Pitch Page MVP + Plan-Mode Classifier Guard**

- **Petty Cash — Stripe Issuing Card Management + AI Assistant**

- **Petty Cash — Full Redesign & Bug Fix**

- **Dashboard: tighten project details widget spacing**
  Reduced dead space in the project details view: the gap between the day tabs / command bar and the first widget row, and the gap between widget rows. Four CSS changes in dashboard.html only — no logic or content changes.

- **comms_web_search — Full Orchestration Unification**
  Every iMessage web search query (regardless of complexity) now routes through a new comms_web_search task type in ai-router, creating a full ai_orchestrations row with mode='direct', scope_surface='comms', status: running → completed. The answer is returned to comms-analyze for d…

- **Organizations Dashboard**

- **Option A: Sheets unified query — project context is render-time only**

- **sheets.html — Mobile PDF preview rewritten as PDF.js canvas (BUG-021 + BUG-022)**
  Mark reported mobile PDF preview overflowing on right edge across iOS Safari, iOS Chrome, and (after Chrome MCP testing) Chrome desktop at <768px width. Iterated through five attempted fixes (BUG-015 transform:scale → BUG-016 viewport-width → BUG-017 height collapse → BUG-018 tra…

- **Sheets mobile PDF — [object Object] fix + overflow fix (BUG-014, BUG-015)**
  Three bugs in the mobile call-sheet PDF viewer were investigated; two were fixed and deployed.

- **sheets.html — BUG-018 mobile PDF iOS overflow (transform:scale revert)**
  After BUG-016/BUG-017 redeploy landed, Mark reported the mobile PDF still overflowed horizontally on both iOS Safari and iOS Chrome — right-side columns clipped, large blank vertical slab below table content. Root cause: BUG-016 relied on the browser's built-in PDF viewer to auto…

- **sheets.html — BUG-016 mobile PDF viewport-width fix (confirmed delivery)**
  Previous deploy at commit 880f554 had updated the markers (.deployed-commit on VPS and .deployed-commits.json locally) claiming ed0cc72 was shipped, but curl confirmed the VPS still served the BUG-015 transform:scale content (490,446 bytes). This re-deploy ran rsync again from th…

- **fix(sheets): AI bar panel never opens (BUG-011) + thread title hardcoded (BUG-012)**

- **sheets.html — BUG-074: mobile time decimals still showing after BUG-067**

- **BUG-066: Post-login redirect preserves intended destination**

- **Weather Cell — External Integration Flex Cell (Phase 1c.4i v2)**

- **2026-05-02 — Visualizations Hub**
  New central hub for all production visualizations. Manually created or AI-generated from any source (iMessage thread, Spotlight chat, Sheets cell, or directly on this page).

- **Run-of-Show Stripboard Layout — 2026-05-02**

- **Project Selector in Sheets Editor — 2026-05-02**

- **sheets-field-write v2 Phase 1c.4k.1 — flexible_fields upsert path**
  Upgrades sheets-field-write from v2 Phase 1c.2 (crew allowlist + universal write-back baseline) to v2 Phase 1c.4k.1, which adds the flexible_fields upsert path required for AI cell pin-to-field and flex cell sync_mode='synced' writes. The prior live version (v7, Phase 1c.2) lacke…

- **Dynamic Range Borders — Mode A Only — 2026-05-02**

- **organizations.ai_cell_budget_cents — Phase 1c.4k.1 AI cell budget cap**
  Adds ai_cell_budget_cents integer NOT NULL DEFAULT 1000 to the organizations table. This is the Phase 1c.4k.1 monthly spending cap for ai_compute_cell task type calls routed through the ai-router. Once a producer's org accumulates ai_compute_cell credit spend exceeding this cap i…

- **community_ai_cell_templates — Phase 1c.4k.6 community template sharing**
  Creates the community_ai_cell_templates table backing the Phase 1c.4k.6 "Share to community" flow in js/sheets-flex-cells.js. When a user clicks "Share to community" in the AI cell template library, the frontend inserts a row with moderation_status='pending'. The community-submis…

- **Sheets phases doc — consolidate today's architectural decisions**
  Brings archive/SHEETS_PHASES.md back into sync with the architectural decisions Mark has made across multiple in-flight conversations on 2026-05-01. The doc had fallen behind on (a) Phase 1c.2's surgical narrowing to formulas-not-strings, (b) Phase 1c.3 flex cells (mostly DONE — …

- **Sheets — Phase 1c.4k.2 + 1c.4k.3: AI Transform + Placeholder Finder**

- **Phase 1c.4k.1 — AI synthesizer cells (substrate landing)**
  Lifts the 2026-04-30 stop-gate on Phase 1c.4k and ships the **synthesizer baseline** — the foundational substrate for AI computed cells in the sheets engine. A new source: "ai_compute" flex-cell mode holds a prompt + a list of context field paths; the resolver invokes ai-router w…

- **Sheets Phase 1c.4k — Revert v1 (overship rollback)**
  A v1 of Phase 1c.4k (AI computed flex cell) was shipped and deployed before Mark's planning gate. Mark requested a stop-before-1c.4k so the architecture could be planned before any code lands again. This commit cycle:

- **Sheets Phase 1c.4i — External integrations: weather (v1)**
  Phase 1c.4i first wave: **weather**. New weather-forecast edge function wraps Open-Meteo (free, no API key) and returns { high, low, desc, sunrise, sunset, fetched_at }. Flex cell schema gains source: "external:weather" with params (lat / lon / date paths + chosen field). Resolve…

- **Sheets Phase 1c.4d — Conditional logic flex cells**
  mode: "conditional" flex cells. Walks spec.rules[] in order. Each rule has { if, then, else }. The if is one of: a string path (truthy when resolveField returns non-empty), a comparator node { path, op, value } with ops =, !=, <, <=, >, >=, contains, empty, nonempty, or { and: [.…

- **Sheets Phase 1c.4c — Permission-aware flex cells (schema + resolver)**
  Phase 1c.4c — permission_aware flex cells. Schema lets a cell declare different paths per role. Resolver reads ctx.user.role (case-insensitive), matches against the spec's paths keys, and falls back to paths.default when no role matches. _loadFieldContext now populates ctx.user.r…

- **Sheets Phase 1c.4b — Time-aware flex cells (schema + resolver)**
  Phase 1c.4b time-aware flex cells. Schema upgrade lets a flex cell declare mode: "time_aware" with an anchor field and three phase paths (pre / during / post). The resolver compares the anchor date to today's midnight in the org's timezone and picks the matching phase's path. Fal…

- **Phase 1c.4 — AI Describe rebuild**
  The AI Describe sub-tab in the New Sheet modal was routing through ai_chat (Gemini Flash, generic flat-table prompt). Output was a 10-column placeholder blob (LOCATION_NAME, CREW_NAME) that didn't resemble a real call sheet.

- **Phase 1c.3a — Flex cells: schema + resolver**
  Introduces the flex_cell primitive — a single-cell COALESCE-style fallback chain. Each flex cell holds an ordered priority_list of field paths plus a default; the resolver returns the first non-empty value. Sibling to dynamic_range (Phase 1c.2). This commit ships the schema valid…

- **Sheets Phase 1c.3 Close-out — Flex cell tooltip + Mode B dynamic_range borders**
  Closes out Phase 1c.3. Two patches: (1) the flex cell hover tooltip now appends Currently showing: <winning path> so the user can see which fallback link is feeding the cell at this moment; (2) the _exampleMode gate that restricted _paintDynamicRangeBorders to Mode A is removed, …

- **Sheets Phase 1c.2 — Universal write-back with confirmation (Stage 1)**
  Architectural Invariant #1 — universal write-back with confirmation — implemented in stage 1. Every dynamic_range-resolved Mode B cell now triggers the same confirmation-modal-then-write flow as native =CREWDECK.FIELD() cells. The flow:

- **Sheets Phase 1c.2 — Per-cell `sync_mode` (synced default / isolated)**
  Architectural Invariant #2 implemented. Each placeholder-resolved cell can be flipped between synced (default — edits flow through the universal write-back path) and isolated (edits stay local to the sheet's content_jsonb, no source-record write). Storage is sparse: only isolated…

- **Sheets Phase 1c.2 Surgical Narrowing — Mode B emits per-record FIELD formulas**
  Mode B dynamic_range expansion now emits a concrete per-record =CREWDECK.FIELD("<canonical path>") at the leaf of the expansion pipeline. Univer renders the same display value because it resolves the formula. No expansion-order, layout, column-group, sort, or PDF-render change. P…

- **Sheets Phase 1c.2 — Mode B formula bar display sugar**
  Architectural Invariant #4 implemented. In Mode B, when the active cell is a CREWDECK.FIELD formula, an overlay div above the formula bar shows the path arg substituted with the resolved value, e.g. =CREWDECK.FIELD("Snipes Holiday Supplemental") instead of =CREWDECK.FIELD("projec…

- **Sheets Phase 1c.2 — FIELD_TYPES + enum dropdowns**
  Architectural Invariant #3 implemented. New FIELD_TYPES registry alongside FIELD_REGISTRY declares each path's type. The confirmation modal renders a <select> dropdown when the type is enum or reference, sourced from a static option list or a live context array (ctx.crew_position…

- **Save indicator: unify across sheets, docs, emails, decks**
  Mark 2026-05-01: "make sure the save state indicator is exactly the same as the sheets page. there should be no green tooltip, just the gray saving with loading sign at the top toward the left. make sure it is consistent across sheets page, docs page, emails page, and decks page.…

- **Header "Docs" button → /docs.html (was /contracts.html)**
  docs.html replaced contracts.html. The shared header's "Docs" button (and the inline copy of that button across every page that hadn't migrated to the shared header yet) still pointed at /contracts.html. This sweep retargets every UI button, spotlight tile, mobile panel, and disp…

- **Emoji removal — roadmap.html (timeline + kanban headers)**
  First commit in the 8-commit emoji-removal sweep. Removes all 8 emoji glyphs from the public roadmap page. The kanban column headers and timeline phase nodes already convey state through colored dots, borders, and pills — the emojis were redundant decorative reinforcement and hav…

- **Docs editor pills now carry bold / italic / underline / color / size through to the rendered output**

- **Docs editor autosaves on every change**
  Docs editor now saves automatically as the user types — no manual click required. Mirrors the sheets pattern: shared js/autosave.js provides the status pill ("Saving… / ✓ Saved / ⚠ Save failed"), and a 800ms debounce coalesces keystrokes into one DB write per pause.

- **Widget header icon buttons + Nearest Hospital address wrap (mobile)**
  Fourth of six commits in the project-details mobile pass. After the grid collapse (commit 3) every widget renders full-width on mobile and most look clean — but two real tap-target / overflow issues remained inside individual widgets.

- **Dashboard project-details widget grid — single column on mobile**
  Third of six commits in the project-details mobile pass. After commit 2 the Day Schedule address wraps cleanly inside its column, but the *widget grid* itself was still desktop-shaped: #pw-widget-grid uses repeat(auto-fill, minmax(260px, 1fr)), which at the simulated 412px viewpo…

- **Sticky mobile project-name header (project-details shell)**
  Sixth and final commit in the project-details mobile pass. Adds a slim sticky strip pinned to the top of the expanded project on mobile, showing the **project logo + name + first badge**. Solves the "no PROJECT-level context when scrolled" gap noted as a follow-up in commit 1: th…

- **Dashboard project-details — mobile shell tap targets**
  First of six commits making the **project details widgets** mobile-friendly on dashboard.html. This commit only touches the project-details *shell* — the tab strip, the header action buttons (delete / customize), and the command bar (the 6 quick-action icons + Copy Brief). Everyt…

- **Dashboard Day Schedule — address overflow + Map/Copy tap targets**
  Second of six commits in the project-details mobile pass. Targets the Day Schedule widget's content lines and action pills only — no JS, no markup, no desktop styles touched.

- **Floating Customize button + day-menu-toggle tap targets (mobile)**
  Fifth of six commits. After commits 2-4 every individual project widget was audited and most interactive elements measure ≥ 44 pt. A targeted sweep turned up two remaining sub-44 pt taps inside the project-details shell:

- **Sheets — `=` key opens Insert Placeholder picker**
  Fixes master report follow-up #3 — alias autocomplete on =. The master report documented that Univer 0.21.x doesn't expose a public API for inline cell-editor autocomplete, so a true inline dropdown overlay would require either (a) DOM-level event interception of Univer's editor,…

- **Sheets — Wire up `project.track_name` (deferred column)**
  Master report follow-up #6 — the project.track_name resolver entry was intentionally returning '' because no track_name column existed on projects. This patch:

- **Sheets Phase 1c.2c.5 Slices F+G — Cross-surface multi-mount + handoff**
  Wires the cross-surface handoff Mark described 2026-04-30:

- **Sheets Phase 1c.2c.5 Slice E — Task chat lifecycle**
  Lights up the global task-chat audit trail. Adds:

- **Sheets Phase 1c.2c.5 Slice C — Cmd+/ rebind**
  Repoints the global Cmd/Ctrl + / hotkey from the legacy spotlight search to window.AIChatHub.toggle(). The hotkey is now the canonical way to reach the AI surface app-wide.

- **Sheets Phase 1c.2c.5 Slices B+D — ChatHub UI shell + PM round-trip**
  First user-facing slice of the Phase 1c.2c.5 ChatHub. Adds a global two-pane chat dialog that any page with the shared header can open:

- **Sheets Phase 1c.2c.5 Slice A — ChatHub schema**
  Foundation for the two-tier ChatHub described in Phase 1c.2c.5. Adds ai_chat_threads + ai_chat_messages tables with full RLS, indexes optimized for the hub's list view, and triggers that keep the parent thread's updated_at in sync with its latest message (so the list sorts by rec…

- **Sheets Phase 1c.2c.5.3 — Save-as-Template sharing scope picker**
  Per Mark 2026-04-30: when saving a template in an org workspace, give the user a choice of who can see it. Three options:

- **Sheets Phase 1c.2c.4 — Bottom-slide AI chat bar**
  Adds an iterative-editing AI chat bar to the sheets page. A round launcher button (rainbow CrewDeck logo, matching the header AI search button style) sits fixed bottom-right. Clicking it slides up a 320px panel from the bottom — leaves the canvas visible above. The panel is colla…

- **Sheets Phase 1c.2c.3 — AI Describe sub-tab in the New Sheet modal**
  Adds a 5th sub-tab — **AI Describe** — to the New Sheet modal's template picker. The user describes the sheet they need; we route through ai-router (ai_chat task type) with a sheet-template-designer system prompt. The AI returns a structured <template>{...}</template> JSON propos…

- **Sheets Phase 1c.2c.2 — Templates UX rebuild (Featured / Org / Personal / Community)**
  Rebuilds the New Sheet modal's template browser with sub-tabs that mirror the dashboard's Add Widget modal pattern (openAddWidgetModal / wbSwitchTab in [dashboard.html:7874](dashboard.html:7874)). Adds a Personal templates tier (user-scoped, no org) and community display-name att…

- **Sheets Phase 1c.2c.2.1 — Community tab search bar**
  Adds a client-side search bar to the New Sheet modal's Community tab. Filter is case-insensitive substring match across name, description, and publisher_display_name. Search bar persists across keystrokes — only the results region re-renders so the input keeps focus + caret.

- **Sheets Phase 1c.2c.1 — Mode B "Templates" tab → "Shared with me"**
  Removes the "Templates" tab from the Mode B project sheets list view (showModeBList) and replaces that slot with a "Shared with me" tab that mirrors the standalone-sheet sharing query already used by Mode A (showSheetList). Templates remain fully accessible via the New Sheet moda…

- **Sheets Phase 1c.2a — Dynamic cell ranges: schema foundation**
  Lays the schema and JS substrate for the dynamic_range primitive that the new call-sheet redesign will rely on (crew, talent, schedule, locations sections). No editor UX yet — that's Phase 1c.2c. This commit ships:

- **Clip logo overlay below column-header strip + remove org.ai_name footer**
  Two follow-ups Mark reported after the schema-version-stamp + re-bake fix:

- **Sheets — Top-level menu bar (File / Edit / View / Insert / Format / Data / Help)**
  Adds a traditional desktop-app menu bar above the Univer container. Univer 0.21.x's @univerjs/preset-sheets-core doesn't include one — only the formatting ribbon (Start / Formulas / Data tabs) — so this is a custom implementation that calls Univer's command service for native ops…

- **Sheets — CI hookup for static formula-path audit**
  Master report follow-up #8 — promote the prior session's /tmp/formula_audit.js ad-hoc script to a tracked CI check at tools/sheets-formula-audit.js, wired into a new GitHub Actions workflow .github/workflows/sheets-audit.yml that runs on every PR (and main pushes) touching the re…

- **Field-bound cells show formula on edit + logo chip in Mode A**
  Two requests Mark surfaced after the overlay-clip + Bash-footer fix landed:

- **Sheets — `day.location[N>0]` Mode B fallback chain**
  Master report follow-up #7. The report claimed Mode B "doesn't expand past index 0" for day.location[N]. Live testing showed the resolver actually already handles N>0 correctly when ctx.locations has entries — a synthetic ctx with 5 locations resolves [0]…[4] correctly. The proba…

- **Sheets — Compound `&` formula tokenizer (real parse, not split)**
  Fixes master report follow-up #5. Compound formulas like ="Day "&CREWDECK.FIELD("day.number")&" of "&CREWDECK.FIELD("day.total") were being resolved by String.split('&'), which fragments any & inside:

- **Sheets AI Bar — focus-stealing fix, ai-router bridge, resize/drag, close UX**
  Five fast follow-up commits to land the bottom-slide AI chat bar fully usable end-to-end:

- **Sheets Phase 1c.2c v2 3/3a — Templates in modal**
  Lights up the templates side of the dynamic_range editor UX. The modal now has a "From scratch | From template" mode toggle. From-template loads dynamic_range_templates (system seeds + this org's saved templates, RLS-filtered) and on Apply writes the template's cell_template colu…

- **audit(po,ai): import ai-router + 3 RPCs + onboarding cluster; v9 credit flow confirmed; 3 dead-code findings**
  Phase 1c — final source-control import batch. Ships:

- **audit(po,permissions): import 7 more Edge Functions; flag get-permissions as legacy; tier-gating rebuild deferred**
  Phase 1b follow-up to commit 90d5ac2 (Phase 1a). Source-controls 7 more Edge Functions central to PO/onboarding/W9/permissions work, captures the AI/credit/permissions table schemas, and flags get-permissions as LEGACY per Mark's directive to rebuild tier gating from the ground u…

- **audit(stripe,po): import stripe-functions + complete-onboarding into source; Stripe tier hookup audit**
  Phase 1a of archive/PO_PHASES.md (Schema + RPC + Edge Function source-control audit). This commit retroactively pulls the two most critical Edge Function bodies into source control (stripe-functions v93 and complete-onboarding v43) — they were deployed to Supabase but their sourc…

- **fix(po,budget): promote PO page to root, retire admin variant; null-check budget updateStats**
  Three things in one commit:

- **Move placeholder to `/home` URL (file + nginx index swap)**
  Mark wants the URL to read crewdeck.io/home (not /index) when visitors hit the homepage. Two pieces:

- **Add Sheets entry to dashboard.html All Apps menu**
  Mark reported the Sheets button missing from the header's "All Apps" menu. Root cause: there are two parallel definitions of ALL_APP_DEFINITIONS — one in js/header-nav.js (which has the view-sheets-btn entry) and a duplicate inline copy in dashboard.html (which doesn't). The inli…

- **Remove Publishing entry from dashboard.html All Apps menu**
  Mark asked to remove the Publishing button from the header's All Apps menu. The button was already deprecated in js/header-nav.js (its ID publishing-settings-btn is in _deprecated = new Set([...]) at line 37, and it isn't even in header-nav.js's ALL_APP_DEFINITIONS). But the dupl…

- **Consolidate triplicate ALL_APP_DEFINITIONS**
  ALL_APP_DEFINITIONS was defined three times across the repo:

- **Sheets — UX bundle: paste-format-only + Insert Placeholder picker + ALIAS_INDEX**
  Power-user UX bundle for sheets.html — three of the four originally planned items shipped, with the remaining items (alias autocomplete on =, top-level File/Edit/View menu bar) documented as deferred for clear technical reasons.

- **Sheets — Talent Skins column 5 binds to sizes (not POC)**
  Talent Skins template column 5 had a header reading "SIZES" but the data cell underneath was bound to project.talent[N].poc. Swapped the cell binding to project.talent[N].sizes across all 10 talent rows, added a sizes resolver that composes a "Shirt: M, Pants: 32, Shoe: 10" summa…

- **Sheets — Mode B schema-recompile slug-lineage fix**
  Fixes the Mode B blank-values bug flagged as #1 in 2026-04-29-sheets-formula-stress-test-master-report.md. Project-day sheets created from a schema-backed template (e.g. Snipes Holiday Supplemental Day 2 — 9fce0c59-4039-417c-b339-77fc067d219a) carry url_slug=null and a saved cont…

- **Sheets — Formula stress test: master report**

- **Sheets — Formula stress test (Batch 1): resolver gap closures (404/404 Mode A clean)**
  Closes every gap in the =CREWDECK.FIELD() resolver where a path used in one of the three preloaded templates fell through to a [ field-name ] bracket placeholder in template-only (Mode A) preview, or returned blank in live (Mode B) mode for a path that does have meaningful semant…

- **Sheets — Tabbed list views (Mode A + Mode B)**
  Replaces stacked section layout on desktop with a pill-tab interface matching the dashboard Projects/Bids pattern. Mobile swipe panels are unchanged.

- **Sheets — In-sheet header + community publish**
  Three items bundled into one commit:

- **Sheets — Standalone Sheets**
  Adds standalone sheets as a third category alongside Templates and Project-Scoped Sheets. Standalone sheets live in sheets with project_id = NULL — org-scoped working documents not tied to any project (vendor master lists, scratch pads, cross-project trackers, etc.).

- **Sheets Phase 1b — Sharing**
  Full sheet sharing system: email-based invites + link-based sharing + share modal UI with Gmail-style chips, debounced member lookup, and permission selection. Privacy-safe: chips never expose whether a recipient has a CrewDeck account — only org membership is revealed.

- **Sheets Phase 1a.5**
  Establishes the two-mode sheets architecture, day scoping, the CREWDECK.FIELD bidirectional placeholder system, the Call Sheet template IWorkbookData, and the critical Univer CDN fix (unpkg importmap had bare-specifier imports that stalled the spinner; esm.sh ?bundle resolves all…

- **Sheets Phase 1a.5 — Templates + Edge Function + Budget Field Paths**
  Follow-up to Phase 1a.5 base commit. Ships the real write path (sheets-field-write edge function), two new system spreadsheet templates (Schedule/Run of Show + Talent Skins/Casting), extended CREWDECK.FIELD registry with crew-position-level paths and budget/payment paths, and a s…

- **Sheets Phase 1a — Foundation Commit**
  Lands the Document Workspace (sheets) foundation: Univer spreadsheet skeleton, universal model picker setting, and a schema addendum. No edge functions were deployed in this cycle. Mark applies migrations and smoke-tests locally before deploying to VPS via ./deploy.sh.

- **Sheets — New Sheet modal + emoji strip**
  Two changes bundled into one commit:

- **Sheets — Layered Access Control**
  Two-layer access model for sheets. Layer 1 is default access from org/project membership (no explicit share needed). Layer 2 is explicit overrides — additive via existing sheet_shares, subtractive via new sheet_access_denials table.

- **Sheets — Auto-slug on rename**
  Slug auto-regenerates from name whenever a sheet or non-system template is renamed. Old slugs are preserved in a slug_history jsonb column for 30 days — URLs using the old slug still resolve and redirect to the canonical new one. System template slugs (call-sheet, schedule, talen…

- **Budget Templates & Line/Section UX Plan**


### Bug Fixes

- **Fix dashboard AI widget builder (Gemini thinkingBudget:0 → HTTP 400)**
  The dashboard's "describe a widget → AI builds it" chat (wbSendMessage) and its suggestion-chip helpers (_wbGenerateChips, _wbGenerateFollowUpChips) call Google Gemini gemini-3.1-pro-preview with generationConfig.thinkingConfig.thinkingBudget: 0. That model now **rejects thinking…

- **Fix: onboarding wizard bypassed hello.html gate**
  onboarding-chat.html was missing a guard for profiles.has_seen_hello. When both has_seen_hello and has_completed_onboarding were false, navigating directly to /onboarding-chat.html (via back button, bookmark, direct URL, or browser history restore) would run the wizard instead of…

- **Fix `seed_forms_for_new_org()` crash that broke all new beta org signups**
  While testing the new-account beta invite flow for crewdeckhelp@gmail.com, admin-invite-beta-user returned 500 Database error creating new user for any brand-new email. Root cause was a latent production bug in the public.seed_forms_for_new_org() trigger (fires AFTER INSERT on or…

- **SPA navigation audit — bug fixes — 2026-05-31**
  Full SPA navigation audit across all 23 cd-spa-enabled pages (each page navigated to/from dashboard with multi-round-trips, 10s dwell sampling for clunky loading states and console errors). Fixes the bugs found: an uncaught view-transition promise rejection on every interrupted n…

- **shooting-schedule.html — live browser QA + 5 fixes + 2 product changes**
  Full live-browser QA of the Shooting Schedule page against https://crewdeck.io in both the organization workspace (King Of Hearts / org 51) and Mark's personal workspace, using Chrome MCP. On entry the page was **completely broken for org owners** — it hung forever on "Loading sc…

- **Purchase Orders — mobile-card UX audit fixes**
  Thorough UX bug audit of the Purchase Orders page, performed at the mobile/ card breakpoint (@media max-width:767px, the swipe-panel card layout) via Chrome MCP. Fixed three real defects: (1) the per-card action button spilling past the card's bottom border, (2) the same primary …

- **shooting-schedule.html — 3-fix QA bundle**
  Code-review-only QA pass on shooting-schedule.html (12,238 LoC) covering workspace separation (personal vs org), realtime channel gating, RLS-sensitive queries, JS bugs, XSS hygiene, empty states, and project scoping. Three real bugs were found and fixed inline; nine other known-…

- **Sheets — publish-button toast wording (QA fix)**
  During the 2026-05-30 exhaustive QA pass on sheets.html, the Publish button in **personal workspace** was found to toast "Save the sheet first before publishing." even though the sheet was already saved. The real gate was that personal sheets have no org_id, and the publish pipel…

- **Routes — two bug fixes uncovered during exhaustive QA**
  Exhaustive end-to-end QA pass over routes.html (covering all three modes, both workspaces, AI agent flow — see docs/qa/2026-05-30-routes-exhaustive-qa.md) surfaced two additional bugs after the earlier _rtRequireProjectOrPrompt defer fix (aac8152, separate changelog). Both fixed …

- **Purchase Orders QA — five bug fixes**
  Code-review-only QA pass over purchase-orders.html (6,650 LoC). Audited workspace separation, realtime channel gating, RLS-sensitive queries, the PO modal create / edit / delete / sign / pay flows, exports, and empty states. Five real bugs found and fixed inline; the rest of the …

- **PO AI panel bleed-through — hard force-hide on SPA nav**
  Follow-up to [2026-05-30 — SPA navigation body-overlay leak audit](./2026-05-30-spa-nav-leak-audit.md) (commit d386765). That fix added a sweepBodyOverlays() pass that closes window.AIEngine / strips .open between teardown and the <main> swap. Despite that, the "PO AI" panel kept…

- **Payroll mobile blank screen when W-2 gate fires**
  Surfaced during mobile-viewport QA sweep (≤1023px) across every SPA-enabled page. Payroll loaded as a fully blank screen on mobile — header at top, tab bar at bottom, empty middle. Same code on desktop rendered the W-2 Coming Soon banner correctly.

- **Dashboard widget double-render + chathub rail bleed (chats → dashboard SPA nav)**
  Two distinct bleed bugs on SPA nav from chats → dashboard, both stemming from body-level state that the SPA <main>-swap can't dispose. Bug 1: chats's #swipe-viewport (built by loadMobilePanels, wraps <main id="comms-layout">) survives into the destination; its #mobile-sidebar-pan…

- **Docs QA — duplicate New Template submit fix**
  During the exhaustive docs.html QA pass on 2026-05-30, every successful click on the New-Template modal's Create Template button reliably produced **two** rows in document_templates (two POSTs to rest/v1/document_templates arriving 1 ms apart with identical body). Only one explic…

- **Dashboard QA — personal-workspace widget + channel gating**
  Live exhaustive QA against https://crewdeck.io/dashboard.html in both personal (Mark Gower) and organization (King Of Hearts) workspaces. Found three workspace-separation bugs in dashboard.html where org-only widgets and realtime channels were active in personal workspace. All th…

- **Dashboard — drop AI toggle overrides; use canonical header.css**
  dashboard.html carried two ad-hoc <style> overrides for the spotlight search AI toggle that conflicted with the canonical rules in css/header.css. The dot override repainted the white circle indigo, so when AI mode was toggled on the dot disappeared into the indigo track — the to…

- **Crew List — personal workspace gating + save constraint fixes**
  End-to-end QA of crew-list.html against the live site uncovered three real bugs in personal workspace and one rule violation. The page met the core workspace policy (no onboarding affordances in personal, full onboarding in org) only via DOM-level CSS hides — the underlying realt…

- **Routes (MV2 mobile) — map touch pan/zoom + search-bar overlap with mode tabs**
  Two mobile-screenshot bugs reported against the canvas map page, corrected mid-session to routes.html (MV2 mobile layout, body class routes-mv2):

- **budget.html — exhaustive code-review QA + five fixes**
  Code-review-only QA pass against budget.html (9088 LoC, ~6.4k JS). Covered workspace separation (personal vs org), realtime channel gating, RLS-sensitive queries, totals/math, autosave/sync structure, empty states, project scoping, and JS / XSS surface. Full QA grid (63 tests acr…

- **Fix: chats `#phone-gate-modal` + `#upgrade-gate` bleed into dashboard after SPA nav**

- **Solo full page-walk fixes**
  Bugs found and fixed while walking every Solo-accessible page as a true Solo user (role=user, individual workspace). One entry per page fix below.

- **Fix: New Project / New Vendor modals auto-open on page load**
  On organizations.html (and any page using the shared header), two modals — **New Project** (#new-project-modal) and **New Vendor** (#new-vendor-modal) — rendered visible on page load.

- **Fix: `.modal-overlay.hidden` modals rendering open on load**
  **FROM:** On shot-list (and any page using the .modal-overlay + .hidden pattern) every modal — Import Shot List with AI, Shot List Settings, Project Gear, Add Camera/Lens, etc. — rendered OPEN and stacked on page load, blocking the page (undismissable).

- **Fix: Dashboard widgets render twice on SPA re-entry (chats→dashboard round-trip)**
  After commit 91d8abe patched the orphaned #dashboard-right-col DOM duplication, users still saw every widget rendered twice on a chats→dashboard SPA round-trip. The root cause was that _cdDashInit had no idempotency guard: if a second call path fired on the same SPA mount (DOMCon…

- **Fix dashboard styling on SPA body-swap entry**
  When the user navigated to dashboard.html via SPA body-swap (e.g. from chats.html), stat cards and project cards rendered minimally / unstyled. Root cause was in spa-router.js: the swap path replaced <main> and updated <title> + body.className, but never touched <head>. Every Cre…

- **Fix: calendar Apps menu restricted in individual workspace (now matches dashboard)**
  **FROM:** In individual workspace the calendar's Apps launcher showed only 3 apps (Credits/Calendar/Shot List), while the dashboard showed the full set (Invoices, Routes, POs, Petty Cash, Overages, Prod Report, Chats, Canvas, Decks, Bids, …). Reported by Mark: "it's not showing t…

- **dashboard.html — drop orphan `#dashboard-right-col` in mobile swipe panel on SPA re-entry**
  Mobile dashboard widgets — Pending Approvals, Add Bot to Meeting, and the sidebar widget cards — were rendering twice in the right swipe panel after any SPA navigation away-and-back to the dashboard. Two stacked copies appeared: one in a stale "fully-rendered" state with the Cust…

- **Voice ↔ Chathub Parity Audit — STRESS-CHATHUB P0 Fixes (S2, S5, S10)**
  Three P0 STRESS-CHATHUB findings (S2 — interrupted multi-step silently dropped; S5 — no cross-tool FK substitution; S10 — credit gate semantic verification) remediated per Mark's locked decisions. S2 + S5 ship as code changes; S10 is a verification-only outcome (current predicate…

- **Solo + Solo Max Gating Stress Test — drift fixes**
  Ran a full gating stress test of the Solo (solo_personal_*, $39) and Solo Max (solo_max_*, $59) tiers — page gates, action gates, AI/credit gates, the project cap, beta variants, and the upgrade flow — verified against the live plan_permissions / plans rows and the client gate st…

- **Phase 0 Session 2 Hotfix — project_wrap_events INSERT policy + modal error logging**
  Hotfix caught by the live Chrome E2E walkthrough of Session 2: the Session 1 migration enabled RLS on project_wrap_events and created a SELECT policy, but no INSERT policy. With RLS on, authenticated INSERTs are denied by default — so every wrap/unwrap/re-download event the modal…

- **routes.html + DB — Fix scout candidate save (silent failure)**

- **routes.html — MV2 day sheet shows "No shoot days" on valid project**
  On MV2 mobile (≤767px), tapping the day picker button on any tab (including Pickup & Runs) showed "No shoot days for this project." even when the project had shoot days.

- **routes.html — per-tab marker arrays + _clearTabMarkers to prevent mode-switch bleed**
  Bug: Shot Locations pins were appearing on the Pickup & Runs map on MV2 mobile after switching tabs. Two root causes missed by df318f4:

- **crewdeck-map.js — Fix "Find Nearby" (migrate to new Places API)**

- **fix(routes): guarantee page-loader hides on iOS Safari — blank white screen fix**
  iPhone Safari was showing a persistent blank white screen on routes.html. Root cause: iOS Safari has a compositor-layer bug where CSS opacity transitions on position:fixed elements silently fail when a child element has an active animation. The #page-loader element (white, positi…

- **Routes MV2 — SL Pin-Tap + Pickup Long-Press Fix**

- **Routes Mobile — Baseline Panel Shift Fix**
  Fixes a pre-existing baseline bug where the center panel appeared shifted off-screen left on iOS Safari — the right edges of tabs were visible but the left side of content was cut off. Discovered when testing C1 on real device. C1 itself was innocent (zero CSS); the bug existed o…

- **Routes — Universal Left Nav Panel + MV2 Swipe Area Fix**
  Fixes two issues reported by Mark against 964816d.

- **MV2 tap target + select arrow fixes (routes mobile v2 QA)**
  QA audit of the routes.html MV2 rewrite identified five touch-target and affordance issues. Four small-button elements sat below the 36px minimum height needed for reliable one-handed tap on mobile. The fifth issue was the <select> inside the pin-card edit form: appearance:none h…

- **mobile-panels.js — Double-Snap Fix**
  A hard swipe starting on #mobile-tab-bar caused the panel to jump two positions (e.g. widgets → nav, skipping the center maps panel). Root cause: two independent handlers both processed the same touch gesture.

- **Lithic Webhook Pipeline — End-to-End Fixes**
  Three bugs fixed, pipeline verified end-to-end in sandbox:

- **fix(header-nav): remove orphaned applyMobileNavOrder call**
  The nav-menu-removal commit (3719538) deleted applyMobileNavOrder() from header-nav.js but left a call to it inside populateHeaderData(). Every page that uses the shared header hit a ReferenceError: applyMobileNavOrder is not defined the moment populateHeaderData was called. On r…

- **Canvas — Fabric 6 migration fixes + full E2E QA**
  Full E2E QA of canvas.html against the KOH project. 33 test cases run (CNVS-001–033); 29 passed, 4 bugs found and fixed. All bugs are Fabric.js 6 API migration issues: the Promise-based loadFromJSON, removal of toGroup/toActiveSelection, and ActiveSelection's side-effect of adjus…

- **Fix: Weather widget Refresh button and stale-cache bugs**
  Fixed three bugs in the weather widget's manual Refresh handler (fetchWeatherBtn click listener inside displayManualWeather) that caused the widget to use stale location/date data, show pre-save weather after reopening a project, and occasionally flash old weather data mid-fetch.

- **Spotlight polish: transparent container, dark mode toggle, project picker**
  Four bugs fixed in the spotlight search bar and one dashboard border fix:

- **Fix: Shoot-date save — tab pill stale date + double flicker on edit-mode exit**
  Two related bugs reported after changing a shoot day's date in the project-details edit mode:

- **2026-05-25 — sheets: weather cell renders correct day on PDF export**
  Exporting the Day 3 call-sheet PDF produced a blank weather cell, even though the weather card rendered correctly in the inline sheet view.

- **2026-05-25 — sheets: Run of Show (and all day-repeating sheets) show correct day on every tab**
  Opening the Run of Show (or any day-repeating call sheet) and switching to Day 2 or Day 3 showed stale Day 1 data — wrong date, wrong crew call time, wrong schedule entries — even though the correct tab was active.

- **2026-05-25 — sheets: fix right-click "exclude from day" on crew dynamic range**
  Right-clicking a crew member in a day-repeating call sheet's CREW dynamic range and choosing "Exclude from [Day]" left the person visible — they were not removed from that day's range.

- **2026-05-25 — sheets: right-click "Hide/Show contact info" buttons missing after any prior right-click**
  Right-clicking a crew dynamic range phone/email cell showed the "Exclude from dynamic range" button but NOT the "Hide/Show contact info" scope submenu — unless the phone/email cell happened to be the very first cell right-clicked since page load.

- **Comms silent reply fix + batch_add_schedule_strips**

- **Fix: NYC DOT Camera Source (webcams.nyctmc.org)**
  The NYC DOT traffic camera dataset 6gwh-yvqs on data.cityofnewyork.us was removed (returns {"error":true,"code":"dataset.missing"}). Any request with NYC coordinates was returning 0 cameras silently. This was the reason cameras appeared to work for LA/Bay Area users but showed no…

- **Fix: "args is not defined" when asking AI to turn on dark mode**
  Typing "turn on dark mode" in the header AI search bar returned "args is not defined" as the AI response. Root cause: executeTool(name, params, ctx) — the update_user_setting case read args.setting and args.value instead of params.setting and params.value. The bare args is not in…

- **Stripe Live Cutover — Customer ID Compatibility Fix**
  After the Stripe live cutover (see [2026-05-24-stripe-live-cutover.md](2026-05-24-stripe-live-cutover.md)), users who had made previous test-mode purchases had a test-mode Stripe customer ID stored in profiles.stripe_customer_id (e.g. cus_test_...). When the frontend called creat…

- **fix(chathub): shot list file-analysis confirm-flow — three bugs found and fixed**
  End-to-end QA of the analyze_shot_list_file pipeline (upload CSV in AI Chat Hub → AI analyzes → imports shots to shot_list table) exposed three bugs in js/ai-chathub.js that prevented the confirm step from completing. All three were fixed in two commits (c504ea9, 4815bca) and dep…

- **Sheets: blank thumbnails on day-repeating sheets + email column wrapping**
  Two display bugs on the Sheets page fixed. Bug 1: call sheet thumbnails in the home grid showed as blank white while schedule/ROS thumbnails rendered correctly. Root cause: day-repeating call sheets store their compiled workbook under content_jsonb.days[n].content.sheets, not at …

- **2026-05-24 — sheets: fix strip color legend + project-level color overrides**
  Two bugs in loadOrgStripColors (js/sheets-item-shapes.js) caused the DAY STRIP KEY legend to disappear and strip row colors to be missing in the Run of Show sheet:

- **2026-05-24 — Schedule: Time Bank, Export PDF, Designation Banner fixes**
  **1. Designation banner invisible** — renderProjectListView() hides #designation-banner-root for layout; loadProjectDetails() never restored it. Banner was injected into a display:none container. Fixed: restore display before calling initDesignationWidget.

- **2026-05-24 — Onboard Audit: Send Error Surfacing + Resend Fix + AI Tool Parity**
  Audit of the onboarding flow discovered two crew members (Mateo Lara, Charles Hoy) on KOH V2 whose onboarding_tokens.send_error = "Edge Function returned a non-2xx status code" — meaning create-onboarding-session ran and created valid form_invites + onboarding_sessions rows, but …

- **Crew List NC/OC call-time buttons — duplicate listener bug fix**
  Clicking the O/C or N/C buttons in the crew detail modal did not reliably set the crew member's call time. After opening the modal more than once (e.g. view crew A → close → view crew B, then switch to edit mode), clicking N/C would fire two handlers that toggled dataset.callStat…

- **Fix: comms AI web search misrouted to spawn_task (KOH iMessage incident)**
  Mark reported that the comms AI was not reliably using web search in the KOH iMessage thread. The specific exchange: after an address was shared, "Send more options and double check that they are open at 8pm" produced "I couldn't find cheap food options in the database" (DB searc…

- **Stripe Phase 2 — Subscription Webhook Bug Fixes + Full Matrix Verification**
  Three bugs in stripe-webhook were found and fixed during Phase 2 subscription testing. All three are now deployed. The full S1–S6 test matrix was run (S5/S6 require manual browser steps). The subscription credit system now correctly routes renewals to the monthly_credits_remainin…

- **Sheets PDF — wrong day + Mode B edit parity fixes**
  Two bugs in the browser-side PDF generator (_buildSheetPdf / _downloadDesktopPdf): (1) multi-day sheet files always exported Day 1 regardless of which day tab was active; (2) manual Mode B edits on non-first-day tabs were invisible in the exported PDF. Both trace to the same one-…

- **NDA Mobile Submit — Disabled Submit Button Fix**
  The Submit button on the NDA signing page (sign-document.html) was permanently grayed out on mobile for any envelope whose documentUrl contained nda.html (including Mateo Lara's NDA token). The root cause: the data-sharing consent checkbox required before enabling Submit was embe…

- **Group-chat bare-name mention continuation fix (KOH "Yeah use production assistant" drop)**
  Two bugs caused group-chat affirmative replies to be silently dropped after the AI asked a clarifying question. Observed live at 2026-05-23 16:00:07 UTC on the "CD PROD | KOH" thread: Mark replied "Yeah use production assistant" to Bash's question "Want me to add Lester Lora as a…

- **Dashboard — Cross-Org Data Bleed Fix (Widgets + Composer)**
  While in the GOODCOMPANY org (org 89), the Upcoming Shoots widget was showing projects from KOH V2 (King of Hearts, org 51). Two sources of cross-org bleed were found and fixed in dashboard.html:

- **Onboarding form-invite fix + Feature B wrapped invite**
  End-to-end onboarding test exposed three things that needed work in one pass:

- **Dashboard — Nearest Hospital "Refresh" now works in display mode and picks the truly-closest ER**
  The Nearest Hospital widget's "Refresh" button had two bugs:

- **Credit margin → 4.5×, six tasks made billable, Studio + Education plan re-priced**
  Raised the credit margin multiplier from 3.0× → 4.5× (env + all in-router fallbacks + ai-rates DEFAULT_MARGIN), flipped six review/create tasks from billable: false → true so token-based charges actually flow through to user balances, raised the Studio plan's monthly credits from…

- **ai-agent: actually deduct credits + comms-analyze: extract clean field values**
  Two real bugs caught during a Mark-authorized credit-charge accuracy test on org 51:

- **Call Sheet QA on KOH V2 + cross-org production_team bug fix**
  Seeded test positions + Run-of-Show schedule into KOH V2 (project f985a4d3-74eb-4117-a2f0-0740f31f3775, org 51) and verified the Call Sheet template (fe78202e-aa61-4118-8bfd-d91f1f54092b) renders end-to-end against real project context. Caught and fixed one real bug along the way…

- **All direct Anthropic fetches now log + deduct correctly**
  Follow-up to today's earlier credit-deduction-fix commit. Closes Bug #5 (4 direct Anthropic fetches bypassing ai_usage_ledger) and aligns TASK_CONFIG with Mark's stated billing policy:

- **Settings — mobile tab-list invisible regression fix**
  The previous fix (c6ebc4d) replaced inset: 0 with width: 100vw; left: 0 on #settings-content-wrapper to stop it from expanding to 3× the viewport width inside the CSS-transformed swipe-track. That fix introduced a worse regression: position: fixed inside a transformed ancestor us…

- **Settings — Beta section mobile layout fix**
  The settings mobile slide-in panel (#settings-content-wrapper) is a position: fixed; inset: 0 element that lives inside the #swipe-track DOM node. Because swipe-track carries a CSS transform, it creates a new containing block for its position: fixed descendants — so inset: 0 expa…

- **PO Page Mobile UX Fix**
  Fixed six mobile layout issues on the Purchase Orders page: 1. First card top cut off under the fixed header 2. No swipe affordance — users couldn't discover the left/right panels 3. Download PO button spanning full card width instead of sharing space with Edit 4. Cards lacking v…

- **Fix: PO mobile card scroll-gesture gray highlight flicker**
  On iOS Safari, swiping up/down through the PO card list caused gray horizontal bands to flash across each card mid-gesture. The cause: inner <td> elements in the card rows (tr.data-row) had no -webkit-tap-highlight-color set, so WebKit applied its default gray tap-highlight to ea…

- **PO mobile actions panel — remove stat cards + fix split-button clipping**
  Two fixes to the PO page's mobile swipe panel (panel 2 of 4 — previously "Stats & Actions"):

- **Permissions System — full-page QA bugfix sweep**
  Full QA sweep over every nav-bearing page on https://crewdeck.io tested the freshly-merged Phase 1–6 Permissions Mode overlay and runtime enforcement. Found and shipped seven bugs that prevented the system from working on most pages, plus two missing <script> tags. Each fix was d…

- **Fix: Hide Permissions menu item on personal workspaces**
  The Permissions menu item in the avatar dropdown (and mobile sheet) was visible on personal workspaces despite the hidden class being applied by header-loader.js. Root cause: .user-menu-item { display: flex } in header.css (rule index 475) overrides .hidden { display: none } (rul…

- **NDA Tracker "Copy link" iOS Safari fix (v2 — manual-copy modal)**
  The previous v1 fix (2026-05-21, e13bbed) tried to recover from iOS Safari's post-await clipboard block by falling through to document.execCommand('copy'). That path is **also blocked on iOS Safari** once the user-gesture context is dropped — both navigator.clipboard.writeText() …

- **Mobile safe-area padding: respect mobile breakpoint in renderProjectListView**
  While verifying the prior commit (75d199e, mobile iOS fixes), live inspection revealed that #main-container on the project-list view was still showing padding-bottom: 12px on mobile despite the new @media(max-width:767px) rule specifying calc(80px + env(safe-area-inset-bottom, 0p…

- **Mobile iOS fixes: safe-area padding, light-mode background, compact banners**
  Three iOS Safari regressions reported from a light-mode iPhone screenshot: (1) talent avatars and bottom schedule content were clipped under the iOS tab bar, (2) the page background appeared dark/black in light mode due to .swipe-panel being     transparent with no opaque backgro…

- **Dashboard search-open blur now covers right-column widgets**
  The body.spotlight-open blur rule in css/header.css enumerated #dashboard-main and #dashboard-sidebar but not their shared parent #dashboard-right-col. The right-column container holds three children: #approvals-widget, #meeting-bot-widget, and #dashboard-sidebar. Only the sideba…

- **Fix status-inquiry pre-ack + iOS binary plist sanitization**
  Two iMessage bugs fixed. (1) The heavy-task pre-ack ("Got it — give me a minute.") was firing when the user sent a status-inquiry message ("How's it going?", "Any update?") while a task was already in progress. Added STATUS_INQUIRY_RE guard so the pre-ack is suppressed on status …

- **Fix: PO topsheet PDF export shows $0.00 for "Total this page"**
  The "Total this page" cell (I33) in PO topsheet exports showed $0.00 even though all line items had correct dollar amounts. This affected both the per-PO PDF download and the XLSX files in the Download All ZIP. Two functions had the same root cause: ExcelJS formula+result objects…

- **Fix re_annotate document_path — durable bytes for restyle**
  The 2026-05-20 re_annotate hardening (b03d07c) shipped tighter hallucination guards and clearer error wording, but left a structural URL-404 cause explicitly unaddressed in its "Known issues" section:

- **Fix re_annotate_document hallucination + 404 URL**
  Two-part fix for a reported regression in the iterative cross-reference flow shipped 2026-05-20 (d0fa77b). After cross-referencing a statement, the user asked to make the annotations "more subtle" and got back a hallucinated reply: "I've adjusted the annotations to be a bit more …

- **Fix: PO topsheet xlsx total shows $0.00**
  The Subtotal (I33) and Total (I35) cells in the exported PO topsheet xlsx were showing $0.00 even though all line items had correct amounts.

- **Fix: cross-reference reply now gives per-item attribution**
  User feedback: when a bank statement is cross-referenced against multiple POs, the AI reply was vague ("a few lines matched"). Fixed in two layers:

- **Cross-reference: project scoping, match_data, persistent storage, sha256 dedup, multi-project, reply format**
  Five inter-related fixes to the cross-reference pipeline addressing a P0 data-contamination bug (wrong-project data surfacing in replies) and several follow-on improvements for persistent document storage, structured match caching, multi-project search, and reply conciseness.

- **Cross-reference: project-scoped storage, match_data, project_documents, sha256 dedup, multi-project**

- **fix: cross-ref wrong-project and insufficient fuzzy matching**
  Fixed three bugs in the iMessage-triggered cross-reference pipeline. Bug 1a: when a user says "I'm going to send you a file for Project X, can you cross reference," the agent was incorrectly using a PDF from a prior session (via findInlineImage's 1-hour recent-fallback) instead o…

- **Cross-reference extraction + match fix (498 rows / 43 POs)**
  Five bugs caused the cross-reference pipeline to return "0 matches, 39 unmatched", to use the wrong project (GRINDR x M instead of the named Fuzzy Match Test Project), and to send duplicate result messages — all against the 43-PO Fuzzy Match Test Project.

- **Fix: Cross-reference returning wrong project data (P0 contamination bug)**
  When the user ran a cross-reference for the Scale-Test-50PO project and then later asked "Cross reference the Amex statement for the Grindr project" (with the Grindr PDF attached), the AI replied with Marcus Chen PO data from Scale-Test-50PO under the name "GRINDR x M". Two compo…

- **Cross-reference: P0 contamination fix + storage scoping + multi-project (full verification)**
  Full end-to-end verification of the cross-reference data-contamination P0 fix and all related changes shipped in this session. Five test scenarios run live in iMessage against the production system. All critical scenarios (1-4) pass; Scenario 5 is a design-clarification (see note…

- **fix(canvas): page load broken — splash stuck, library hidden**
  The canvas page (/canvas) was completely broken on load: navigating to it from the dashboard showed only a giant CrewDeck logo splash that never cleared. Three bugs were found and fixed in canvas.html:

- **fix(canvas): save RLS, Fabric v6 chain, back navigation, header parity**
  Four bugs fixed in canvas.html across two deploy cycles:

- **Canvas page — traffic layer, traffic cameras, route planner + audit fixes**
  Ships the three live-only map features that build on the 2026-05-19 Google Maps migration:

- **Fix: W-9 attachment routes to vendor record when identified via PO name**
  When a user iMessaged "I'm attaching a W-9 for the vendor on the Wrap Supplies PO", the AI was matching the generic "attach to PO X" routing rule and either omitting doc_type='w9' (causing the file to land in purchase_orders.invoice_urls instead of vendors.w9_url) or replying "at…

- **Reminder routing fix: "remind Sneha via email" now sends to Sneha**
  Fixed a routing bug in the iMessage AI pipeline where "Remind Sneha via email at 9:30am to be nice to Mark on set" was setting a personal alarm for the sender instead of emailing Sneha. The REMINDER_OFFER_RULE in comms-analyze had no carve-out for third-party recipients, so the L…

- **iMessage PDF delivery fix + zero-matches annotated file**
  Fixed two bugs in the iMessage AI cross-reference PDF flow. (1) When the agent finished annotating a PDF it passed the signed URL as a SendBlue media_url attachment — but SendBlue PDF MMS delivery is unreliable and many carriers reject the request, silently dropping the text body…

- **forms-engine: restore `--no-verify-jwt` after platform deploy regression**
  The feat(forms): module platform + Google Forms redesign deploy (f369678, 2026-05-19) redeployed the forms-engine edge function WITHOUT the --no-verify-jwt flag. That flag is mandatory for forms-engine — it is one of the eight functions explicitly enumerated in CLAUDE.md because …

- **Fix: PO budget-line skip intent + W-9 vendor stamping in attach mode**
  Two PO-flow bugs surfaced from a single iMessage turn:

- **PO "Both" export — diagnostic logging + VPS converter output validation**
  The "Both" export option on the POs page (the ZIP that bundles a merged PDF + filled XLSX + each attachment) was failing with an opaque "edge function error" and Logflare had no logs pointing at the actual failure step. The XLSX-only path worked, which narrowed the blast radius t…

- **Fix doc-intelligence cross_reference: real PO data, aggregation, fuzzy + ambiguity**
  The cross_reference action of doc-intelligence was missing nearly every match. Two root causes plus four behavior gaps:

- **Beta-invite flow — defensive coercion in notification rule renderer**
  User reported the "Invite new beta user" flow in platform settings was throwing an error. Investigation showed the admin-invite-beta-user edge function itself works correctly (direct invocation with crewdeckhelp@gmail.com returns {success:true} and Resend ships the invite email).…

- **iMessage AI: route "remind [3rd party] via email" to email-targeted reminder**
  When a user texted "Remind sneha via email to be nice to mark on at 9:30am", the iMessage AI replied "Done — I'll ping you at 9:30 AM: 'Be nice to Mark on set today.'" — it set a personal alarm for the *sender* instead of emailing Sneha at the requested time. The bug was that cre…

- **PO Page: Vendor Panel + Budget Link + XLSX Folder + Dropdown Direction**
  Four PO-page issues raised together. All four are fixed:

- **Petty Cash — QA Pass: 3 UI violations + 2 AI-agent bugs fixed**
  During the Section A UI QA walkthrough of petty-cash.html, three native dialog violations and two ai-agent runtime bugs were found and fixed.

- **iMessage PO pipeline — sheet-send safety net + runAgentLoop ReferenceError + matcher false-positive**
  Two upstream regressions had landed in the iMessage PO pipeline. (1) When a user said "create a PO and link it to the X budget line," comms-analyze's sheet-send safety net was treating the word "budget" as a document-noun and re-overriding the orchestrator's correct PO-routing de…

- **vision + classifier: Fix Silent imagescript Import + Truncated-Error Match**
  Mark kept getting the generic "Hit a snag on that one — try again in a sec." even after today's earlier image-downscale + specific-fallback fixes. Two root causes:

- **ai-agent: Add `items` Schema to `role_targets` + `trigger_conditions` on Notification-Rule Tools**
  ai_activity_log contained ~7 provider_fallback rows in 30 seconds with errors like:

- **Persist budget-line disambiguation context per PO**
  The iMessage AI pipeline had no memory of which PO was awaiting budget-line disambiguation. When the AI asked "Which budget line for the Quirky Banjo $50 PO? 1. Craft Services PRE-PROD, 2. Craft Services SHOOTING LABOR, …" and the user replied "2", the agent had no anchor and the…

- **ai-agent: create_shoot_day handler now passes user_id explicitly**
  Caught live at 15:23 UTC on org 51 / thread d1e29de5 (Sonnet/Medium): "Can you add a shoot day for Grindr project on may 5th?" → AI replied "Ran into a constraint on my end creating that shoot day — looks like a setup issue with the project."

- **Share Link iMessage Fixes — BUG B + Designation Lookup**
  Five fixes based on Mark's screenshots surfacing issues after the main E2E pass (2026-05-17-run-of-show-imessage-e2e.md):

- **Run of Show QA — Bug fixes (dynamic range + schedule template)**
  QA pass on the Run of Show / Schedule system template surfaced three bugs in the dynamic range and schedule template modules. All three are fixed inline in this commit:

- **NDA Tracker Fixes + crewModal Sweep + ID Verification Toggle**
  Seven follow-up fixes and enhancements to the NDA Tracker shipped across this session:

- **Per-Chat Agentic Mode + Audit-Found Bug Fixes**
  Two workstreams in this session:

- **iMessage E2E: 13 bugs fixed, BUG-13 ROOT CAUSE closed (userId → serviceUserId)**
  Nine rounds of fixing across the iMessage E2E suite at +19728590040. Ran Tests 1–15 of the matrix, surfaced **15 distinct bugs**, **fixed 13**, **verified 1 was not-a-bug**, **left 1 as cosmetic/known**. The session-final BUG-13 ROOT CAUSE was a single-field rename: comms-analyze…

- **Phase 6.5 sub-agent Z — E2E pass on 32 schedule_* AI tools + P0 fix**
  Sub-agent Z ran the end-to-end pass on the 32 Phase 4 + Phase 6 + Phase 6.5 schedule_* ai-agent tools against a live test project (KOH V2 — f985a4d3-74eb-4117-a2f0-0740f31f3775) in Chrome MCP. The pass discovered a P0 wire-up bug that was blocking **every** schedule AI tool call …

- **fix(comms-analyze): route 'send run of show' to comms_share_link + hallucination guards**
  Training Chat 29 (2026-05-16 12:19): Mark asked Bash "send the run of show for the snipes tech scout." The AI responded "On it — running this in the background. I'll text you when it's done." then later "I found the run of show for the Snipes Tech Scout. It's on its way to you no…

- **fix(ai-task-worker): name-based fuzzy sheet lookup — fixes 'run of show' always returning not_found**
  Follow-on fix to Training Chat 29 (2026-05-16 routing fix, commit 97f44a2). The routing fix correctly directs "send the run of show" to comms_share_link. But the task worker's sheet lookup was broken in a second way: it used .ilike('url_slug', ${slugPrefix}%) to find sheets, and …

- **Reminders — Production Spam Fix + Request-Timestamp Anchor + Lead-Time Delivery**
  **Production incident (15:09–15:29 UTC):** Mark received the iMessage "Check the E2E test results." every 2 minutes starting at 11:09am ET. Root cause: the model called create_reminder with recurrence:{kind:'interval_minutes',minutes:2} when Mark said "remind me and Sneha to chec…

- **fix(reminders): resolve Training Chat 29 reminder regression**
  Mark sent "Bash can you remind me to eat my food in 2 min" at 3:25 AM UTC in TRAINING CHAT 29. Bash replied "Sure! I'll remind you in 2 minutes... _(Heads up: I'm a production assistant AI and don't have a built-in timer or notification system, so I can't actually ping you automa…

- **Reminders — Chathub Hallucination Fix & E2E Verification**

- **Reminders — REQUEST_TIMESTAMP Anchor Regression Fix (Training Chat 29)**

- **PDF call-sheet location overlap — flex authoritative + migration row correction**
  AI-exported call-sheet PDFs were rendering the LOCATION column with two strings stacked at the same y-coordinate — the location name overlaid on top of the address row, and the location address overlaid on top of the "HOSPITAL" label row in the metadata strip below. The defect wa…

- **Comms thread-project state: anti-stale-history + cross-project find_project enforcement**
  Fix the user-visible state inconsistency Mark saw in TRAINING CHAT 29 (screenshot in task brief) where Bash referenced "Gymnopedie Doc" project context across three consecutive iMessage turns even though the chat had been detached from that project. The original bug report hypoth…

- **ai-router + ai-agent — Footer AI surface message extraction + tool routing fix**
  Two cross-cutting P0 bugs were surfaced during the crew-list Phase 4 E2E (local_6691c713). Every footer AI surface that uses js/ai-engine/* (13 surfaces in total — crew-list, purchase-orders, docs, budget, calendar, decks, emails, payroll, petty-cash, pickups, schedules, shot-lis…

- **PO topsheet fills every field correctly (vendor, totals, PO#)**
  Mark pointed out the generated PO topsheet PDF was missing a lot of fields that the modal collected — vendor address / Tel / Fax / Contact / EIN were all blank, **Subtotal and Total rendered as $0.00** even with line items present, the PO number was nowhere on the sheet, and the …

- **sheets-export-pdf — weather flex cell coord drift (DB data fix)**
  Weather card was missing entirely from PDF exports. Root cause was a "split-brain" call-sheet template in sheet_templates.content_jsonb: the _crewdeck_flex_cells weather entry was anchored at (row 6, col 6), but col 6 falls inside the hospital cell's merge (6,5)-(6,6), so the ren…

- **Run of Show: example-mode bake-leak fix + AI parity for "give me the Run of Show"**
  Two coupled fixes triggered by a cell-by-cell audit of the standalone Run of Show system template (sheets-schedule-template.js) against the live All The Way project.

- **PO Top Sheet xlsx now visually matches the source template exactly**

- **2026-05-15 — Pickups optimization bundle + live tracker realtime fix + map redesign**
  Three workstreams, all shipped:

- **2026-05-15 — Petty Cash Request as form template + header dropdown fix**
  Two unrelated user requests landed in one session, committed together:

- **Comms AI: deterministic confirm pre-check + find_project category-word guard**
  Two related regressions in the agentic Bash flow this user hit in succession, both diagnosed in local_a618dd39 before that task got stuck on an AskUserQuestion the user couldn't answer. Respawned to ship the approved fix.

- **sheets-flex-cells.js / sheets.html — Weather card overlay color actually shows saved color**
  After f9ea6eb fixed the save path, the weather cell color still reverted visually after reload even though window._crewdeckWeatherStyleOverrides and the DB both had the correct color. Root cause: the weather cell's Univer style was correct after the formula reinstatement loop, bu…

- **vCard auto-promote loosened + affirmative continuation detection**
  Two related iMessage AI bugs:

- **dashboard: fix project_access 404 spam in _silentRefreshWidgets**
  _silentRefreshWidgets (the 90-second background refresh function) was querying db.from('project_access') as if it were a REST table. project_access does not exist as a table — it is only available as the RPC get_my_project_access. Every background refresh cycle produced a 404 err…

- **AI-exported call sheet PDF: weather card resolves, schedule section restored**
  Two regressions in the AI-exported call sheet PDF (supabase/functions/sheets-export-pdf) made the output diverge from what the same template renders on sheets.html:

- **Mobile bottom nav: fix Realtime AI button + remove Sheets tab**
  Two mobile bottom-nav (#mobile-tab-bar) fixes:

- **Fix: iMessage callers now always have full tool access (hallucination root cause)**
  Root cause of AI hallucinating record updates (name, email, phone, position) in iMessage chats: when a chat_thread row has agentic_mode_enabled = false or null (the default), ai-agent filtered out all write tools — including update_master_crew_member — before the model loop ran. …

- **gemini-live: fix WebSocket pipeline (Blob decode, realtimeInput format, try-catch)**
  Three distinct bugs were blocking the gemini-live WebSocket pipeline. Together they caused every voice session to silently stall — the Edge Function's open handler never completing, Gemini's setup_complete never arriving at the client, and audio never playing.

- **Fix: iMessage comms pipeline — MESSAGE_BREAK leak, hallucination false positive, PDF weather cell**
  Three bugs in the iMessage/comms pipeline were identified from Training Chat 29 and fixed in a single commit. (1) The ---MESSAGE_BREAK--- delimiter was leaking as visible text in iMessages when the AI's response began with the delimiter (empty first segment filtered away, leaving…

- **comms: create-chat crash fix + fuzzy client name match in comms_create_project**
  Two fixes to the comms iMessage pipeline, plus a revert of the regex pre-classifier approach.

- **sign-document.html — Production 502 Fix (2026-05-10)**

- **Forms Engine — P1 Fixes**
  Four issues found during end-to-end verification of the Forms Engine P1 and fixed:

- **Email: white button text + dynamic copyright year**

- **fix(comms): chat-create toggle defaults YES — root cause in comms-analyze**

- **fix(comms): slow-path chat_create_review 'neither' keeps pending alive**

- **Fix: Casual Register Matching for Short Acknowledgments in iMessage**

- **Fix: Eliminate Templated "I need to search for" Preamble in Weather/Web Search Responses**

- **Fix: UTC TODAY: line in callClaudeWithWebSearch overrides timezone-aware systemSuffix**

- **Fix: comms_web_search AI gets correct local date (not UTC)**
  Prior fix (91a134d) injected UTC datetime into the comms_web_search system prompt. At 10:50 PM EDT on May 4, UTC was already May 5 — so the AI replied "tomorrow = May 6" when the correct answer was May 5. This fix persists each user's IANA timezone to profiles.last_known_timezone…

- **Session Bug Fixes — Bugs 1–6**

- **fix(sheets): write-back modal new-value shows `[object Object]` — BUG-013**

- **Fix: mobile project sheets list blank in Mode B**
  When navigating to sheets.html?project=<id> on a mobile viewport (iPhone Safari), the project's saved sheets list was entirely blank — a white void between the project pill row and the bottom nav. The page header, project switcher, and nav rendered correctly; only the sheet tiles…

- **Sheets: Desktop PDF Download Fix (2026-05-02)**

- **Settings: Credits Hub Redesign + Org Permissions Fix — 2026-05-02**

- **Phase 1c.3a-fix — Flex cells: wire applyAll at boot + on save**
  The Phase 1c.3a flex-cells primitive shipped 2026-04-30 (6343471) with a complete schema, resolver, editor modal, amber corner-triangle indicator, and persistence — but applyAll(fieldCtx) was never invoked. Persisted flex cells therefore stayed blank until something manually trig…

- **Docs Mode B editor canvas now actually fills the page like Google Docs**

- **Sheets — Section-header rgb-prefix fix (`#` normalization in compiler)**
  Fixes the section-header black-bar regression flagged as #2 in the master report. Univer 0.21.x renders bg.rgb as solid black when the hex value lacks the # prefix; cl.rgb (text color) happens to tolerate either form. The schema-token convention in sheets-layout-schema.js was "he…

- **Sheets bug fix — Logo overlays + dynamic-range indicators leaking onto non-schema sheets**
  Mark reported (2026-04-30, third-attempt session): on a Call Sheet template, adding a second worksheet via Univer's + tab and switching to it shows the logo overlay text ({org.logo_url}) painted on top of the new sheet's canvas, plus the dynamic-range summary pill stays visible. …

- **Sheets Phase 1a — Four Fixes + Protocol Docs**
  Fixes four issues found during Phase 1a smoke testing. Also adds project protocol documentation (PROTOCOLS.md, changelog template, per-file HTML comment blocks) and a Changelog Discipline section to the phases doc.

- **Sheets — Hot fix: locale + CREWDECK formula + header**
  Four bugs fixed in a single commit — all frontend-only changes to sheets.html.


### Performance

- **Performance Audit — DB indexes, realtime cleanup, over-fetch limits, client cache**
  Full performance audit across DB, client JS, and Supabase Realtime. Discovered 17 missing indexes on tables with >100K seq_scans per interval (worst: budget_line_items at 228K scans averaging 4,226 rows/scan — now a keyed lookup). Fixed over-fetching on pitches and help_articles …

- **Wrap performance: parallel fetches across per-PO / per-day / per-envelope loops**
  Heavy projects (4+ POs, multiple shoot days, full crew) were timing out the Chrome MCP wrap test driver (>45s) because export-project-wrap walked every per-PO / per-day / per-envelope loop sequentially. Each iteration blocked on an edge-function round-trip (generate-po-topsheet, …

- **Sheets load-time + bad-connection optimization**
  Profiled the sheets page init waterfall and applied three targeted optimizations to the serial request chain that runs before hideLoader() fires. The primary bottleneck was that loadSharedHeader, profiles, and organization_members each awaited the previous one despite having no d…

- **Dashboard load-time + offline/bad-connection optimization**
  Measured the dashboard load waterfall (61+ Supabase requests per load) and addressed the two reported symptoms: slow load and failure on bad connections. The primary cause was that the full-page spinner waited for ALL background prefetch requests to complete before dismissing — m…

- **Batch page performance — parallelize profile + org_members across all pages**
  After optimizing dashboard.html and sheets.html, the same serial init antipattern was audited across all app pages. Every authenticated page awaited db.from('profiles') and db.from('organization_members') serially, even though both queries only require session.user.id (available …

- **Maps — gmp-place-autocomplete shrunk to normal input size + dropdown forced above all containers**
  Google's new <gmp-place-autocomplete> web component (used by every callsite of CrewdeckMaps.attachAddressAutocomplete — dashboard locations/shuttles/hospital, budget shoot location, canvas address inputs, crew-list contact addresses) defaults to **~48 px tall** with large interna…

- **Revert mobile-tab-bar z-index fix (broke dashboard on iOS Safari)**
  Revert of f32e9f8 — fix(mobile-nav): float #mobile-tab-bar above overlays so dynamic Back button is tappable. The z-index lift and 64px drawer padding bumps broke the dashboard on iOS Safari. Reverting restores the pre-fix overlay stacking and drawer padding so the page renders c…

- **Re-reinstate mobile tab-bar Back button z-index fix**
  Earlier today the back-button z-index fix was reverted (a193704) after an iOS report suggested the change was breaking overlay layering. On further investigation the iOS issue turned out to be a stale browser cache, not caused by our CSS — once the cache cleared, behavior matched…

- **Sheets pixel-perfect xlsx imports — Phase 4**
  Mark's mandate: **"I need to get an excel file or a pdf in and it needs to be pixel perfect. I want to fully build it."** Phase 1 closed single-sheet xlsx cell render, Phase 2 added multi-sheet + named ranges + comments + rich text, Phase 3 added the zip inflater + CF translation…

- **Sheets pixel-perfect xlsx imports — Phase 3**
  Mark's mandate: **"I need to get an excel file or a pdf in and it needs to be pixel perfect. I want to fully build it."** Phase 0 shipped the foundation (backlink + view_mode + PDF iframe + share-link tighten); Phase 1 closed the xlsx single-sheet pixel-perfect render; Phase 2 ex…

- **Sheets pixel-perfect xlsx imports — Phase 2**
  Mark's mandate: **"I need to get an excel file or a pdf in and it needs to be pixel perfect. I want to fully build it."** Phase 0 shipped the foundation (backlink + view_mode + PDF iframe + share-link tighten); Phase 1 closed the xlsx single-sheet pixel-perfect render; **Phase 2 …

- **Sheets pixel-perfect xlsx imports — Phase 1**
  Mark's mandate: **"I need to get an excel file or a pdf in and it needs to be pixel perfect. I want to fully build it."** Phase 0 shipped the foundation (backlink + view_mode + PDF iframe + share-link tighten); Phase 1 closes the xlsx side of pixel-perfect.

- **Strip root `index.html` to a minimal "beta coming soon" placeholder**
  The 2026-04-29 "teaser" index.html was actually the full marketing landing page with a beta banner stitched on top — it still leaked feature copy ("Everything a production needs", "From brief to shoot day in minutes"), audience hints, role callouts, and a signup form. Mark's ask:…


### Infrastructure

- **Breakdown-anchored location sourcing in the Pre-Production Pack**
  The PPB Locations section now SOURCES real options instead of rendering saved data, embodying the production model: a breakdown's N location elements = N requirements to source; the deck presents OPTIONS to cover each requirement, distilling to one finalized location per requirem…

- **Shooting Schedule & Shot List — migrate toolbar controls into the editor menu bar**
  The shared editor header (js/editor-header.js + css/editor-header.css, shipped 2026-05-31) gave the Shooting Schedule, Shot List and Casting pages a sheets-style File/Edit/View/Insert/Tools menu bar, but the pages still rendered their original in-page toolbars — so controls lived…

- **Forms Platform Redesign — Deploy to Production**
  Deploys the form module platform from f369678 (task local_62e7a445). Adds 12 turbo-charge module handlers that fire automatically after every form submission, five new admin actions in forms-engine, four new AI tools in ai-agent, and a full Google Forms–style card grid redesign o…

- **Org Settings Migration: All Org Sections Moved to organizations.html**
  All 14 organization-scoped sections previously living in settings.html have been moved to organizations.html. The organizations page now owns: Profile, Members, Financials, Crew DB, Crew Structure, Clients, Vendors, Locations, Brand Kits, Notifications, Playbooks, AI Integrations…

- **VPS Audit — Junk Cleanup + Sheets Files Redeploy**
  Routine VPS audit found two issues: (1) junk directories publicly accessible on the VPS from old unguarded bulk rsyncs, and (2) sheets.html and its two JS companions were behind main — deployed from a worktree commit (95dfd48) that was never merged to main.

- **flexible_fields migration — Phase 1c.4k.1**
  Creates the flexible_fields table — the polymorphic value store required by Phase 1c.4k AI cell pin-to-field and flex cell sync_mode='synced' writes. This migration unblocks sheets-field-write v8 (already deployed 2026-05-02 03:04:34 UTC), which routes flex cell writes to this ta…

- **deploy.sh — per-file ancestry check + .deployed-commits.json marker**
  Adds a per-file ancestor check plus a committed .deployed-commits.json marker to deploy.sh, layered on top of the existing global .deployed-commit guard. Mark reported the leapfrog problem on 2026-05-01: "every time one task deploys it wipes another updated commit for another wor…

- **Update Everything — Merge + Deploy**
  Merged both open worktree branches into main, resolved stash, and deployed to production VPS.

