Built in public · Changelog

How Supernova learned the job.

The product story, newest first: what actually became possible in each stretch, not a list of tweaks. Generated live from the engineering journal; the log is the changelog.

99

improvements shipped

9

days of building

11

shipped per day, avg

9
6 Jul
8
7 Jul
1
8 Jul
2
10 Jul
5
11 Jul
25
12 Jul
6
13 Jul
peak37
14 Jul
6
15 Jul

Product panorama

One deal, one continuous operating loop.

Six agents live in the product today, propose-only, a named human at every gate. Everything below ships; nothing is a mock.

01every desk, daily

Brief

The Daily Brief opens each cockpit: meetings with exact times, deals needing a touch, the one move.

02critic-checked

Draft

The Email Drafter investigates the thread through scoped tools, then a fresh-context critic verifies every claim.

038 dimensions

Qualify

Deal Check scores MEDDPICC with the evidence that earned each score, never vibes.

04pre-call

Prep

Meeting Prep briefs every call: who is in the room, where it stands, what to ask.

05with provenance

Track

The Promise Tracker extracts what each side committed to, source attached, resolved in place.

06propose-only

Audit

Every run costed and receipted: model, tokens, verdict, the audit trail behind every artifact.

14

Jul 2026

Tuesday

4 shipped

Fix

/design goes espresso: the dark-mode contrast pass, fixed in the reusables

The user's read on "the app feels light but not the landing's way" became a direction: the design page now runs the full espresso dark theme as the proving ground. /design wears .app-theme…

The user's read on "the app feels light but not the landing's way" became a direction: the design page now runs the full espresso dark theme as the proving ground. /design wears .app-theme dark, an espresso rail (.section-dark sidebar with the landing wordmark register), the landing's ruled eyebrow on the header, and a dark-aware canvas (faint cream dots, warm glow, never a white haze). Global radius knob turned down 14px→10px (crisper at app density).

The contrast pass then went component by component, every fix in the REUSABLE layer so the whole app inherits:

  • Root cause found: .dark only remaps variables, so any text without an explicit color class inherited body's light-resolved ink — dark-on-dark across the page. Fix: the dark scope carries text-foreground (documented in the page).
  • Table rewritten (ui/table.tsx): mono uppercase header BAND on a tone step with a stronger rule, real cell padding (px-4 py-2.5), theme-real hover (row-hover token, not invisible muted/50), selected rows in the warm clay wash, footer on the strong rule. Now reads as a data grid in both themes; every table in the app upgrades for free.
  • Elevation became theme-aware: --shadow-rest/raised/float now route through --elev-* vars (warm-tinted on cream, real black weight on espresso — a 5% warm shadow is invisible on dark).
  • Skeleton / Progress / Slider tracks: bg-muted (a near-zero tone step on espresso) → foreground-relative washes, visible in both themes.
  • Scrims (dialog/sheet/drawer/alert-dialog): bg-black/10 gets dark:bg-black/45.
  • Sonner on the dark page pins theme="dark" (it otherwise follows the OS, not the page scope).
  • Canvas glow fix shipped to the light app too: the near-white radial that washed every app page pale at the top is now warm cream.
Fix

Proshort: incremental 10-min sync + a false-match fix

The mirror had gone stale (525 recordings, last one 12-Jul) because the only tooling was a full backfill (~10 min of throttled calls — too heavy to run often). Re-ran it (525 → 548, now…

The mirror had gone stale (525 recordings, last one 12-Jul) because the only tooling was a full backfill (~10 min of throttled calls — too heavy to run often). Re-ran it (525 → 548, now current through today 14-Jul 11:30), then built the missing incremental path:

  • `src/lib/proshort/sync.ts`syncProshortIncremental(): walks the recordings list newest-first and stops as soon as a page holds nothing new, so a routine run is 1 list call + N details (usually N=0). Also refreshes the last 2 days of recordings, whose insights Proshort finishes generating after the call. Writes a DELTA batch row.
  • `POST/GET /api/proshort/sync` — token-guarded (shared token or Vercel Cron's Bearer $CRON_SECRET).
  • Every 10 minutes: vercel.json cron (*/10 * * * *) for deploy, + scripts/proshort/watch.mjs for local (a loop that hits the route; node scripts/proshort/watch.mjs).
  • Bug fix — false recording matches: getMeetingEvent's matcher joined on any shared party email, so a recording could link to a meeting merely because a colleague was in both (only the 30-min window prevented it). Now requires a genuine external party via the shared nonCorporateDomainsSql (which already excludes our own tenants + free providers).

Finding: the "Negotiation Discussion — Right Horizon x Antino" (13-Jul) has no recording because that call was never recorded — the mirror is current and 16 other calls exist from that day; Right Horizons' last recorded call is 03-Jul.

Fix

Two calendar-data bugs found via the briefing: recurring subjects + a 5:30 timezone error

The briefing surfaced two real mirror bugs (both now fixed in the shared DB + at the source):

The briefing surfaced two real mirror bugs (both now fixed in the shared DB + at the source):

  1. 01Recurring occurrences had no subject. 12,813 of 23,523 graph_events (every event_type='occurrence') had subject/organizer null — Graph puts those on the series master, and occurrences only reference it. Backfilled all 12,813 from their masters (subject, organizer, is_online_meeting, location, body_preview). "(no subject)" is gone.
  2. 02Every meeting was 5:30 early (UTC parsed as IST). graph/importer.ts's dt() did new Date(String(v)). Graph event start/end (dateTimeTimeZone) is a naive timestamp (zone in a separate field, always UTC here); JS parses a bare timestamp as local, so on the IST host every event stored 5:30 early — breaking times AND which-day bucketing (evening meetings fell into the wrong day, so "today's meetings" mis-timed and mis-counted). Fix: dt() now appends Z when there's no zone marker (message receivedDateTime/sentDateTime already carry Z, so they're untouched and were always correct). Backfilled graph_events.start_at/end_at +5:30 (one-time; verified against Anisha's real Outlook: 12:30 / 16:00 / 19:00 / 20:00 — exact match). Blast radius confirmed to be events only (the 4 dt() call sites: event start/end broken, message received/sent fine).

Regenerated all 17 briefings — times, day, and counts now correct.

Fix

Close-on-activity: doing the work closes the follow-up (the durable fix)

The backlog rebuilds because "mark done" is a separate step reps skip. So make the work itself close the task. On the SDR lead hub, logging real activity — Send email / Log a call / Book a…

The backlog rebuilds because "mark done" is a separate step reps skip. So make the work itself close the task. On the SDR lead hub, logging real activity — Send email / Log a call / Book a meeting — now completes the lead's next open follow-up in the same action (completeNextForLead, subject-matched to the lead), toasts "Follow-up marked done ✓ — you just did it", and refreshes so it vanishes. The manual Done on the lead's task list now persists too (was toast-only). Both write the task_completions overlay + an audit event (reversible, PREVIEW).

  • Extracted a shared, role-flexible src/lib/tasks/actions.ts (completeTasks bulk + completeNextForLead); the cleanup panel re-exports from it. getLeadTasks now excludes cleared tasks (overlay), so the hub reflects it instantly. Verified end-to-end (lead "Sagar/Anaplan" → "Followup 2" auto-completes + hides).
  • Not yet wired: the inbox (parallel session's /ae/inbox) and the AE lead hub (inline, no rail) — same pattern applies when those are touched.

13

Jul 2026

Monday

1 shipped

Fix

AE deal inbox (Outlook-style workspace) + timeline HTML sanitization

"the AE also needs to have an inbox similar to what we built for SDR — without inbox none of this has any value." Built /ae/inbox, the SDR inbox one level up the ontology (deals, not…

"the AE also needs to have an inbox similar to what we built for SDR — without inbox none of this has any value." Built `/ae/inbox`, the SDR inbox one level up the ontology (deals, not leads). Same two-pane, mail-client shape: left = the AE's deals split into "In conversation" (open deals whose buying committee — primary contact + contact-role members — has a live email thread in the Graph mirror, ranked by most-recent message across the whole pipeline) and "Open · quiet" (open deals with no live thread — the ones going dark, paginated); right = the deal header (stage chip, ₹, account, contact, Deal hub ↗) + the unified thread (emails + meetings + calls + notes + tasks via getDealTimeline) + a Copilot-draft compose box (preview — nothing sends). New data layer getDealInbox (verified 162ms / 12 real conversations for Anisha) and draftReplyForDeal (Haiku, grounded in the deal's real thread). Inbox added as the AE's #2 nav item. Note: the Copilot draft currently 401s — the ANTHROPIC_API_KEY in .env is expired (wiring is correct; SDR copilot fails identically) — a key rotation, not a code fix.

HTML sanitization — the thread was leaking raw markup (<div style="display:flex…">…) from Zoho notes pasted out of Proshort and Outlook body fragments, since we render detail as text. New htmlToText helper (src/lib/format/text.ts: strips tags, keeps block breaks as newlines, decodes the common entities incl. emoji &#…;) wired into `getDealTimeline`, `getLeadTimeline`, and the peek pane (email body + note content). Deal hub, both inboxes, and every peek now render clean prose. Also promoted the deal description to a clay-accented "What they want" brief at the top of the Deal hub Details card (was a muted grey footnote under the field grid) — narrative leads, facts follow.

Perf note (not a bug): /ae/pipeline?peek=… logged 3.5s in dev. Traced it — getPipeline 29ms + peekDeal 24ms = ~60ms of real work; the rest is Next.js dev-mode render overhead (Turbopack + React dev renderer, amplified by concurrent session load). Production build serves that route in ~100ms. No code change; the peek is a full server round-trip by design (URL-driven master-detail, not a client Sheet).

11

Jul 2026

Saturday

1 shipped

Fix

HEAD_OF_SALES role (admin-tier) + fixed the KPI dashboards

New HEAD_OF_SALES role, admin-tier: it shares the /admin area and sees everything the CXO admins see (Command Board, users, org, audit, integrations). Rohit Naidu (id 163) promoted to it…

  • New `HEAD_OF_SALES` role, admin-tier: it shares the /admin area and sees everything the CXO admins see (Command Board, users, org, audit, integrations). Rohit Naidu (id 163) promoted to it (audited USER_ROLE_CHANGED; scripts/add-head-of-sales-role.ts, which also runs the ALTER TYPE user_role ADD VALUE 'HEAD_OF_SALES' AFTER 'ADMIN').
  • Access refactor so a role can share another's area: ADMIN_ROLES = [ADMIN, HEAD_OF_SALES], new requireAdmin() in dal.ts (replaces requireRole('ADMIN') across all 11 admin pages/actions), SEGMENT_ALLOWED_ROLES in roles.ts drives proxy gating (was 1:1 SEGMENT_ROLES), roleHome(HEAD_OF_SALES) = /admin, ROLE_NAV[HEAD_OF_SALES] = the admin nav. "Head of Sales" is now an assignable role in /admin/users.
  • Fixed two real crashes on the KPI dashboards (they were listed "working" but actually threw on render): (1) server components passed formatter functions (valueFormatter={formatInr}) to the client chart component — forbidden across the RSC boundary; replaced with a valueFormat="inr"|"count" string the client resolves. (2) weekStart from Postgres wasn't always a Date → Intl.DateTimeFormat threw "Invalid time value"; now coerced with a NaN guard. Both /admin/command and /ae/team render clean now.
  • Verified in Chromium: signed in as admin@glue.tools and as rohit.naidu@antino.com — both land on /admin, reach /admin/command, see ₹ figures + 16 chart SVGs, zero console/render errors.

10

Jul 2026

Friday

1 shipped

Fix

Incremental sync fixed for activity modules; first real delta pulled

First real-world incremental sync surfaced two COQL blind spots: activity modules (Tasks/Calls/Events) reject What_Id — the polymorphic link we must have — and Deals.Stage_Modified_Time /…

  • First real-world incremental sync surfaced two COQL blind spots: activity modules (Tasks/Calls/Events) reject What_Id — the polymorphic link we must have — and Deals.Stage_Modified_Time / Calls.CTI_Entry / Events.Participants are unqueryable. Fix: Tasks/Calls/Events now sync via the same Modified_Time-desc REST walk as Notes (REST returns What_Id fine, deletions still tracked via the deleted API); the COQL path self-heals by dropping any column Zoho names in an INVALID_QUERY error (learned per process, mirroring the bulk-import behavior).
  • Sync then pulled two days of real CRM activity cleanly: Leads +650 upserts/2 deletes, Tasks +1,548/4, Notes +81, Calls/Accounts/Contacts small. Post-sync counts verified against live Zoho: Leads 19,034 / Tasks 588,206 / Contacts 140,500 all exact.
  • Known limitation confirmed in the wild: Zoho exposes no deleted-records API for Notes, so notes deleted in Zoho persist here until the next full import (currently 1 such row).

07

Jul 2026

Tuesday

2 shipped

Fix

Sales leadership designations fixed from the org chart

scripts/fix-sales-designations.ts (idempotent, audited USER_UPDATED): the HR sheet's generic VP/AVP titles were overriding the chart's role labels. Rohit Naidu → Head of Sales (per user;…

  • scripts/fix-sales-designations.ts (idempotent, audited USER_UPDATED): the HR sheet's generic VP/AVP titles were overriding the chart's role labels. Rohit Naidu → Head of Sales (per user; chart label was "Director-Business & Strategy"), Anisha Ratnam → Head of Startup, Nitish Kumar → Head of Growth, Himanshu Gupta → Head of Government. Harshad/Vinay already correct.
  • Reporting tree needed no changes — all 17 chart edges already matched the image.
  • L4 "Key Accounts" people keep their specific HR designations (Business Consultant / Trainee / Intern / Tender Executive); the chart's "Key Accounts" reads as the team grouping, not individual titles.
Fix

Sticky nav fix, login verified, founders added as ADMIN

Sticky nav bug fixed: .section-dark set position: relative outside any cascade layer, which beat the layered sticky utility on the landing nav (unlayered CSS wins). Dropped the position…

  • Sticky nav bug fixed: .section-dark set position: relative outside any cascade layer, which beat the layered sticky utility on the landing nav (unlayered CSS wins). Dropped the position (its isolation: isolate already provides the stacking context); verified in-browser — nav pinned at top: 0 with position: sticky at scrollY 2400.
  • Login flow verified in the browser (Playwright/Chromium against the prod build): admin@glue.tools + dev password → lands on /admin, shell shows Sign out; DB health confirmed.
  • Founders added as ADMIN (scripts/add-founders.ts, idempotent, audited): Rajesh Kumar (Co-Founder & COO, rajesh@antino.io, id 234) and Radhakanth Kodukula (Co-Founder, radhakanth@antino.io, id 235). Emails follow the @antino.io leadership pattern but are assumed (flagged in the audit context). Vinay was already ADMIN. Admins now: Glue Admin, Vinay, Rajesh, Radhakanth. Users total: 234.