- Personal action inbox section in the daily digest emailCloses the named rev-77 next-sprint candidate ('per-recipient digest entry for the personal inbox'). Rev 77 surfaced the operator's actionable inbox in the dashboard status bar via the `PersonalInboxPill` (unacked @-mentions + due-soon assigned + stale assigned). Rev 78 mirrors it on the email channel so operators who don't open the dashboard before noon still get the same one-line 'what waits for me right now?' answer. New `buildPersonalInboxSection()` helper in `src/lib/digest.ts` reuses the rev-77 `getPersonalInbox()` helper verbatim โ pure derived state, no new query. Renders FIRST among the per-recipient sections (above rev-25 assignee, rev-31 mentions, rev-48 stale) since it's the actionable shortlist; the longer sections still render below for the complete view. Hidden when the operator's inbox total is zero so quiet days never read as nag-spam. Plumbed through both the cron production loop and the rev-36 admin preview path. **Strategic significance**: closes the per-recipient personalisation symmetry across rev-25 assignee + rev-31 mentions + rev-49 personal stale + rev-53 personal cost + rev-76 personal chronic + rev-78 personal inbox. The daily digest is now fully personalised across every load-bearing per-recipient surface โ the actionable axis joins the temporal + cost + chronic axes that already had per-recipient digest sections.
- Multi-device sync for panel collapse via `workspace_member.dashboardPrefs` JSONBCloses the named rev-77 next-sprint candidate ('dashboard panel collapse multi-device sync via `workspace_member.dashboardPrefs` JSONB'). Rev 77 ships per-panel collapse state in localStorage; rev 78 layers a workspace-shared canonical store on top so the same operator's tuned panel inventory follows them across devices. New JSONB column on `workspace_member` (currently carries `collapsedPanels: string[]` only; future revs can add panel order, default sort, hidden columns without a new column). New `getDashboardPrefs()` / `setDashboardPrefs()` helpers + `GET/PUT /api/workspace/dashboard-prefs` route. The rev-77 `PanelCollapsibility` component is extended to (a) read localStorage first for sync render, (b) fetch the server prefs and merge by union (a panel collapsed on either device stays collapsed โ safer default than 'last-write-wins'), (c) fire-and-forget the PUT on every toggle so the server stays in sync. localStorage stays as the write-through cache; server is the source of truth for cross-device drift. **Strategic significance**: pairs with the rev-39 density toggle as the second compactness primitive. Until rev 78 a power-user with a tuned dashboard had to re-collapse the same panels on every machine they logged in on. Rev 78 closes that gap.
- `GET /api/v1/openapi.json` โ machine-readable OpenAPI 3.1 spec for the v1 surfaceUntil rev 78 the v1 surface was self-describing only via `/api/v1` (string descriptions of every endpoint) โ fine for human developers reading curl examples but not consumable by code generators. Rev 78 ships an OpenAPI 3.1 spec describing the most load-bearing endpoints (workspace, signals, artifacts, tasks, memory, search, today, stats, runs, cost-today, whats-new, personal-inbox) with typed request/response schemas. Public endpoint โ no auth required to read the spec since the spec describes the auth model itself. 5-minute browser cache + 30-minute CDN cache so the upstream MCP host can poll without thrashing. **Strategic significance**: OpenAPI 3.1 is the published Anthropic / Linear / Stripe / GitHub pattern for surfacing APIs to MCP hosts and code generators. Hosts that read this spec can typecheck their tool calls, generate client SDKs in any language, and (in Anthropic's case) auto-generate MCP tool definitions from path + parameter metadata. Curated subset to start; rev-by-rev the spec grows toward full coverage. The full self-describing index at `/api/v1` remains authoritative for the complete endpoint list. Q3 #1 priority (the actual MCP server wrapping `/api/v1`) gains a typed contract surface.
- Time-bucketed activity log (Today / Yesterday / Earlier this week / Older)The activity log has accumulated 14+ kinds across 35+ revs (per-kind glyphs + tinting in rev 35, chip filter in rev 21, in-place keyword search in rev 38, 'only new since last visit' in rev 76). Until rev 78 the visible rows rendered as a flat scroll regardless of horizon โ operators reading a busy log had to mentally compute 'is this from today or yesterday?' from the timestamp on every row. Rev 78 buckets the visible rows into four time horizons after the chip + keyword + only-new filters apply, so the buckets reflect what the operator chose to see. Bucket headers are quiet uppercase typography โ ambient labels rather than competing with the row content. Activates only when there are 8+ visible rows so quiet workspaces don't see clutter. **Strategic significance**: cumulative diversification of the activity log surface. Pairs with rev-21 chip filter (categorical scoping), rev-38 keyword search (free-text scoping), rev-76 only-new toggle (temporal-since-visit scoping). Rev 78 adds the *temporal-bucketed* dimension. The log now reads at four orthogonal axes without the operator needing to flip between modes.