- Per-source cost spike detectorCloses the alarm axis to match the rev-57 per-source attribution axis. New `detectSourceCostSpikes()` aggregates the rev-54 `task.dailyCostHistory` JSONB by source (joined via `task.sourceSignalIds → signal.sourceId`) so today's per-source spend can be compared against the trailing 7-day daily average per-source. Cost is split equally across distinct sources on a task — same defensible aggregation as rev-57 attribution. Surfaces sources spiking 2× their baseline AND >= $0.50 absolute today AND with >= 3 historical days of spend. Where rev-32 fires the alarm at the workspace level and rev-55 at the per-task level, rev-58 fires at the per-source level — answers 'which feed is driving the spike?' without making the operator scroll the rev-57 panel and squint at bar widths.
- Daily Slack push + outbound source.cost_spike eventNew `pingSourceCostSpikes()` sweep added to `runDailyDigest()` mirroring `pingCostSpikes` (rev 32) and `pingTaskCostSpikes` (rev 55) shape exactly. Pings Slack via the new `buildSourceCostSpikeSlackPayload()` block (header `:zap: Per-source cost spike` + listing each spike with ratio + today vs avg + contributing-task count + source type), fires the new `source.cost_spike` outbound event via `dispatchSourceCostSpikeWebhook()`, writes a `source_cost_spike` activity-log entry. Rate-limited to once per workspace per 24h matching the rev-32 / rev-55 pattern. Dead-Slack-webhook auto-clear matches `notifyBriefToSlack`. Slack now carries the third axis on the cost alarm surface — workspace (rev 32), per-task (rev 55), per-source (rev 58) — so external automations (CRM, FinOps dashboard, board-status integration) can route the alarm by feed instead of just by workspace.
- Inline ⚡ pill + spike banner on rev-57 cost-by-source panelEvery row currently spiking gets a brand-red ⚡ N× pill in the row header alongside the rev-57 cost amount + percent + label. Tooltip surfaces 'Today $X.XX vs trailing-7d avg $Y.YY — mute or filter to control.' Spiking rows also gain a red left-border accent + tinted amount color matching the rev-57 polish on the rev-51 top-cost-tasks panel — three cost panels, one consistent visual vocabulary. Plus a soft amber→red banner above the source list when any source is spiking, summarising the loudest spike inline so operators see the alarm without reading the full row breakdown. The dashboard now reads cumulatively (cost + percent), trend-aware (sparkline still in TodayPanel), and alarm-aware (rev-58 pill + banner) on the same per-source axis — the same three-level read shipped on the per-task axis in revs 51/54/55.
- GET /api/v1/sources/cost-spikes (close v1 parity gap in lockstep)Bearer-auth endpoint mirrors the rev-58 dashboard primitive in the same cycle the dashboard surface ships (cadence pattern that started rev 37 and held through rev 57 continues). Pairs with `/api/v1/cost/by-source` (rev 57 attribution) + `/api/v1/tasks/cost-spikes` (rev 55 per-task) + the existing rev-32 workspace-level `workspace.cost_spike` outbound event as the three-axis alarm cluster on the protocol-bound surface. The cost-axis MCP cluster now matches across both axes: per-task (rev 51) → per-assignee (rev 52) → per-source (rev 57) on the attribution side; workspace (rev 32) → per-task (rev 55) → per-source (rev 58) on the alarm side. The MCP server has nothing left to design on the cost-spike surface — exclusively protocol-translation work.