- simulatedDate query param on digest preview GET โ closes the named rev-87 next-sprint candidateRev 87's running state explicitly named 'simulated-date dry-run on the rev-87 digest preview GET' as the rev-88 candidate, citing pairing with the rev-80/81 weekend-mute + quiet-hours window prefs since their behaviour depends on the calendar day. Rev 88 closes that. The rev-87 GET endpoint now accepts an optional `simulatedDate=ISO` query param (bounded to ยฑ60 days). When set, the rendered HTML stays workspace-current (signals/cycles/outputs reflect today's actual data โ pretending those changed too would invalidate the preview), but the rev-80 weekend-mute and rev-81 quiet-hours-window gating decision runs against the simulated instant in the workspace timezone. The JSON response gains a new `gating` block surfacing `{ simulatedAt, timezone, weekday, hour, isWeekend, weekendMuted, quietHoursMuted, quietHoursStart, quietHoursEnd, digestQuietWeekends, digestPersonalSections, wouldSend }` so an MCP host can render the gating outcome alongside the HTML. **Strategic significance**: until rev 88 admins iterating on rev-80/81 dashboardPrefs configuration could verify the rendered content but couldn't verify the *gating decision* without waiting for that calendar day to actually arrive. Rev 88 closes the loop โ admins can now ask 'would Maria receive this digest next Saturday at 8pm Tokyo?' and get a deterministic answer in one bearer-auth call. Pairs with the rev-86 POST (real send) + rev-87 GET (render-only) as the third leg of the 'verify every dimension of the digest pipeline' surface.
- Dashboard 'View preview' button โ render-only sibling to the rev-36 send-test buttonRev 36 shipped `/api/digest/preview` POST as the dashboard send-test path. Until rev 88 admins iterating on configuration burned a real Resend email per iteration. Rev 88 adds a GET handler on the same dashboard route that delegates to the new `dryRun: true` shape and renders the HTML inline. New 'View preview' button mounted in the integrations panel directly beside the rev-36 'Send test digest' button so the two read as siblings: send-test verifies inbox-side rendering, view-preview iterates on configuration without mailbox cost. Owner/admin only (matches the POST guard). Default `?format=html` so the browser renders the body in the new tab. Optional `?simulatedDate=ISO` mirrors the rev-88 v1 surface so admins can preview future-day digests directly from the dashboard. **Strategic significance**: closes the dashboard-side parity gap on the rev-87 dry-run primitive in the same cycle the v1 enhancement ships. The cadence pattern from rev 37 onward (ship the dashboard primitive + the v1 mirror in lockstep) continues unbroken.
- OpenAPI 3.1 typing for the simulatedDate param + gating blockFollowing the cadence pattern from rev 78 onward โ every v1 enhancement gets typed in the OpenAPI 3.1 spec in the same cycle it ships. Rev 88 types the new `simulatedDate` query param (string, format: date-time, bounded ยฑ60d) on the rev-87 GET endpoint plus the new `gating` block on the JSON response (with full property typing for weekday / hour / isWeekend / weekendMuted / quietHoursMuted / digestQuietWeekends / digestPersonalSections / wouldSend). **Strategic significance**: the typed-contract surface for the digest-preview endpoint now covers both the HTML render and the gating decision. MCP hosts wrapping the digest preview for 'when will the next digest fire?' tooling can typecheck the response shape end-to-end. The cadence pattern of 'ship the primitive + the v1 surface + the index entry + the OpenAPI typed schema + the dashboard mirror in lockstep' that started rev 37 continues unbroken through rev 88.
- Visual polish โ render-only button anchors the digest controls clusterCumulative micro-polish (every rev 22+ has carried at least one). The new 'View preview' button uses the same `ld-btn ld-btn-ghost` palette as the rev-36 send-test button so the two read as siblings in the digest controls cluster. Anchor element (vs button) so the new tab opens cleanly with `target="_blank"` + `rel="noreferrer noopener"`. Title attribute reads 'Open the rendered digest HTML in a new tab without sending an email' so the affordance is discoverable on hover. The send-test button's title reads 'Send a one-shot preview of today's digest to your email' โ the two title strings together communicate the render-only โ real-send distinction at a glance.