- Per-memory cost spike daily digest section closes the email channel gap on the rev-161 alarmNew buildMemoryCostSpikesSection() helper renders up to 5 spiking memory entries with ⚡ ratio + today vs avg + kind chip + importance chip + retrieval count + structural-fix copy ('pin or raise importance ≥9 to exempt, or ack to silence today'). Pre-fetched once per workspace via the existing rev-161 detectMemoryCostSpikes() helper and reused across every owner/admin recipient on the cron daily digest path — same pattern the rev-60 source / rev-63 assignee / rev-68 tag daily spike sections use. Workspace-shared (every owner/admin sees the same list since 'this knowledge entry is anomalously expensive today' is workspace-level diagnostic context). The rev-161 daily Slack push + outbound memory.cost_spike event were already fired by pingMemoryCostSpikes() earlier in runDailyDigest, so the email surface stays in lockstep with the chat + integration channels. The detector itself filters out entries acked today via the rev-162 costSpikeAckedAt stamp so the email rows match what the dashboard ⚡ pill shows. Closes the alarm cluster's seventh axis on the email channel — workspace (rev 32) / per-task (rev 55) / per-source (rev 60) / per-assignee (rev 63) / per-tag (rev 68) / per-memory daily (rev 164) all now reach the digest email.
- Per-memory chronic-warning digest section closes the named rev-163 next-sprint candidate at the email channelCloses the explicit rev-163 next-sprint candidate ('per-memory chronic-warning digest section'). New buildMemoryChronicWarningSection() helper mirrors the rev-75 source/tag chronic-warning sections at the per-memory axis with amber ⏳ Nd-in-a-row chips + ⚡ ratio + structural-fix copy ('the entry is being retrieved too often by too many cycles — pin, raise importance, or refactor surrounding tasks'). Pure derived state from the rev-161 detector return shape: filter to entries whose consecutiveSpikeDays counter has crossed the chronic threshold (3 days, matching rev 70/72/163) AND whose chronicAckedAt stamp is absent or older than the 7-day TTL — same filter shape as the rev-75 source/assignee/tag chronic filtering. Workspace-shared (memory entries don't have assignees so the section lists every chronic entry in one block, mirroring the rev-75 source/tag chronic-warning sections rather than the rev-49 per-recipient stale pattern). The rev-163 chronic-warning Slack push + outbound memory.chronic_warning event were already fired by pingMemoryCostSpikes() so the email surface stays in lockstep with the chat + integration channels. Closes the chronic horizon on the alarm cluster's seventh axis on the email channel: per-source chronic (rev 75) / per-assignee chronic (rev 75) / per-tag chronic (rev 75) / per-memory chronic (rev 164) — every chronic axis now reaches the digest email.
- Plumbed through buildDigestHtml + production cron + admin preview path in lockstepBoth new sections wired into the buildDigestHtml() params signature with optional fields — undefined-safe so no behavior change on workspaces without spikes. Cron daily digest path (runDailyDigest) pre-fetches memorySpikes once per workspace via detectMemoryCostSpikes() and derives the chronic entries inline using the same CHRONIC_THRESHOLD_DAYS + CHRONIC_ACK_TTL_MS constants the rev-75 chronic sections use — one shared filter shape across all four chronic axes. Admin preview path (previewDigestForUser, the rev-36 send-test path) mirrors the cron exactly so admins iterating on configuration see the same surface they'll receive in production. Render order: per-memory daily section appears LAST among daily alarm sections (after per-task/per-source/per-assignee/per-tag) so readers scan the cost story in one visual block; per-memory chronic appears LAST among workspace-shared chronic sections so the four-axis chronic vocabulary reads in one visual block. The detector is read-only — no counter increment, no chronic-ack stamping — so running an admin preview does NOT alter the rev-163 consecutiveSpikeDays counter or the rev-162/163 ack stamps.
- OpenAPI 3.1 spec changelog header documents the rev-164 closure — 86th unbroken cadence revNo new v1 endpoints (the rev-161 /memory/cost-spikes + rev-163 /memory/chronic-warnings already cover the protocol-bound surface). The OpenAPI 3.1 spec changelog header gains a rev-164 block explaining the email-channel parity gap closure on both alarms in a single cycle. The cadence pattern from rev 78 onward (every dashboard primitive gets typed in the OpenAPI 3.1 spec in the same cycle it ships) reaches its 86th unbroken rev with rev 164 — even though no new v1 endpoint ships, the pattern is preserved by documenting the rev-164 closure in the OpenAPI changelog header so MCP-host code generators reading the spec see exactly when each rev's primitive landed (either as new endpoint or as channel expansion of an existing alarm). The cost-spike alarm cluster's seventh axis (per-memory) now reaches every operator-loaded channel — in-app ⚡ + ⏳ chips, daily Slack push, outbound webhook events, AND digest email — across both daily and chronic horizons.