CedarCopilot wants to merge 0 commits into staging from feat/slack-style-reactions
Live on prod, no production signal yet
Strict CloudWatch fallback found 1 prod failure log lines for [MEETING_NOTES_WEBHOOK] Error processing webhook (AskElephant webhook payload must contain at least one attendee with a valid email address), but this domain-wide failure family is not tied to this intent.
Libra has verdicts on 0 of 1 tracked behaviors on prod; 1 is still being checked. Libra checks hourly for 3 days after each deploy.
Four changes, plus a round of review fixes on top.
⇧U , the unread-only filter. Superhuman's ⇧U narrows the inbox you're on to its unread and badges the tab; Cedar's version does it across every channel at once. Email rides an is:unread clause on the compiled Gmail query; LinkedIn / WhatsApp / Slack go through the server's unreadOnly flag, applied at the source (not over the assembled page, which would hand the client a two-item page behind a "Load more" button). The read-state override is part of the predicate, so a chat the rep explicitly marked unread stays in a filtered feed instead of vanishing under a badge that says otherwise. State is keyed by folder slug, is not persisted, and re-keys queryHash so getSplitCounts can't lend a filtered tab an unfiltered count. Toggling shows the unread subset of what's already cached as placeholder data, gated on sameRequestApartFromUnread so a channel or folder switch never reuses another question's rows.
/bookdemo. The demo ask gets its own URL to link, share and measure , the dialog is gone, every CTA points at the page. Page title is now honest about what Cedar is.
Apex-domain scaffolding. cedarcopilot.com for marketing, mail.* for the app, one bundle serving both with the split enforced client-side in lib/marketing-host.ts. Entirely inert until VITE_PUBLIC_MARKETING_URL names a host distinct from the app's, so it ships ahead of the DNS cutover.
Landing on /mail now picks the first inbox tab rather than the literal inbox slug, which nothing owns in the important/other layout , the tab strip used to highlight Important while the thread query ran an unscoped inbox folder.
Compose editor tables, so a signature keeps its shape instead of flattening into divs.
rel=canonical was a bare origin. React Router doesn't merge meta up the tree, so /pricing, /legal/*, /roadmap and /hr were each telling crawlers they duplicate the homepage , while /pricing sat in the sitemap the same build emits. It now names the path you're on, via a shared canonicalUrl helper the blog and /bookdemo use too (the blog pair had been pointing at the app host, which post-cutover is a URL that redirects).robots.txt had a blank line between Allow: / and the new Disallow block. A blank line ends a record, so every one of those rules belonged to no user-agent , the authenticated app would have stayed crawlable.unreadClause had been inserted between splitClause's doc and splitClause, leaving each function carrying the other's contract.role="button" , a button inside a button in the accessibility tree, and unreachable by keyboard anyway.'use client' directive left a React Router route; dead onSubmitted / exported CALENDLY_URL / a comment for a deleted dialog went with it; ~30 stray blank lines came out, two of which had split JSDoc blocks mid-sentence.pnpm run autofix:local , green, both before and after merging origin/staging: 257 mail suites / 2,423 tests, 658 server files / 6,977 tests, exit 0.unread-filter.test.ts (query composition + the per-folder flag, incl. the queryHash re-key), feed-unread-filter.test.ts (the SQL each of the 4 sources × legacy/container paths actually emits), feed-unread-db.test.ts (read-only, real DB, skipped without DATABASE_URL), inbox-landing-redirect.test.tsx, table-round-trip.test.ts.pnpm --filter @zero/server run types clean; @zero/mail clean apart from a pre-existing error in modules/calendar/components/LinkifiedEventText.tsx:148 that this branch doesn't touch.oxlint@1.78.0 --deny-warnings exits 0.Not verified in a running browser: the ⇧U interaction itself, and the marketing split (inert until the Cloudflare cutover).
🤖 Generated with Claude Code
Libra has not measured any production surfaces for this change yet.