Skip to content

feat(alerts): live coverage preview in the schedule editor - #2435

Merged
Makisuo merged 56 commits into
mainfrom
ux/schedule-preview
Nov 10, 2026
Merged

Makisuo merged 56 commits into
mainfrom
ux/schedule-preview

Conversation

@Makisuo

@Makisuo Makisuo commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #2426. The on-call schedule editor now shows who is on call while you edit, and where nobody is.

What changed

  • Live coverage preview. A timeline beside the form (stacked on narrow screens) redraws from the draft on every edit: a "Final schedule" lane with who gets paged, one lane per layer, a line for now, shaded weekends, the schedule's time zone on the axis. Range 1, 2 or 4 weeks, step by week.
  • Gaps. Time with nobody on call is a hatched red "No one" bar, and a line above the timeline counts them: "10 gaps in the next 14 days, longest 2d 10h (Sat 14 Nov 08:00 to Mon 16 Nov 18:00)". Each gap is a link that focuses its bar. No gaps reads "Covered for the next 14 days"; an empty schedule reads "Nobody is on call for the next 14 days".
  • Same numbers as the server. The preview runs the server's own renderOnCall (now exported as @maple/alerting-core/oncall; it only depends on effect and domain types) on the draft, so nothing is duplicated. A test samples the preview against onCallAt every 15 to 30 minutes, including across a DST change.
  • Detail page uses the same timeline over the server's shifts (overrides included), 14 days by default.
  • Overrides count in the editor too. Editing a saved schedule loads its overrides and layers them over the draft, so the editor and the detail page report the same gaps. While they load the timeline is a skeleton; if the read fails the preview says gaps may be filled and offers a retry.
  • A half-edited layer (no people, or an invalid time window) is left out with "Fix this layer to see shifts" instead of showing false coverage.
  • Kit: shift-timeline gains a gap tone, weekend shading, a zone label, labels that hide when a bar is too narrow, and bar ids. formSection now stacks by its container's width.

Before / after

Before After
Covered Detail page 4 weeks Phone

Editing a saved schedule with an override:

Lab: /lab/oncall?state=editor-gaps|editor-covered|editor-early|editor-override.

Verification

  • apps/web: bunx vitest run src/page/alerts src/lab 548 pass, root src/*.test.ts 132 pass. New: 14 coverage tests (layering, overrides, handoffs, DST, empty layers, server match), scene tests for live updates, the gap summary, range switching, the stale-range skeleton and the preview not re-rendering while typing the name.
  • packages/views timeline tests 9 pass; alerting-core oncall 25 pass.
  • Typecheck clean (@maple/web, packages/views); oxlint -c .oxlintrc.effect.json clean on changed files; ui:index, ui:patterns:check pass.
  • An independent review found 12 issues (a fake gap while the range loads, past weeks reading "Covered", half-edited windows showing full coverage, recompute on every keystroke, gap and on-call bars the same colour); all fixed.

Not verified: gap-link focus in a real browser (the command is tested), the uptime form's look after the formSection change, and a live org (preview test pending). listOverrides returns only overrides that have not ended, so one that ended earlier today is not drawn in the past part of today (gaps are checked from now, so the summary is unaffected).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Schedule forms now include a live coverage preview with date-range controls, week navigation, coverage gaps, and links to focus on gaps. Draft changes appear without saving.
    • Editing a schedule loads its overrides for the preview; if loading fails, you can retry.
    • Schedule calendars support selectable date ranges and show coverage gaps and time-zone information. Timeline views include clearer date labels and weekend shading.
    • Previews highlight empty schedule layers and, for new schedules, rotations already underway.
  • Bug Fixes
    • Long schedule names wrap in delete confirmations and remain visible in calendar headings.
    • Preview times update as the clock advances.

- Kit: rightSheet over the Dialog Submodel (672px form size, scrolling body,
  sticky footer, slide dropped under reduced motion) with followUrl/isDismissed;
  page/kit/sheet-param holds the ?sheet= helpers (push to open, replace to close).
- Sidebar group labels fold their rows (sidebarGroupToggle, aria-expanded),
  saved to localStorage; the group holding the current page and the collapsed
  rail always show every row.
- Footer on-call pill from the schedules list's on_call_now and the session
  user: on call until the handoff, not on call, or hidden without schedules.
  Re-read at each handoff; a dot with a tooltip on the rail.
- /lab/shell shows all three, with a demo form in the sheet.
- Sheet: opening pushes a history entry marked as this tab's; dismissing
  goes back past it, and only a deep link replaces the param. Kit renamed
  to sidePanelSheet, footer receives close; sheet-param tests sit beside it.
- On-call pill: a shift past its end reads as unknown; reads again at the
  handoff, hourly while off call, on focus and visibility, and with backoff
  (60s doubling, capped) after a stale or failed answer, keeping the last
  good data. Schedule and override writes announce a re-read.
- An org with no schedules is cached per org for a day and skips the request;
  a schedule write clears it.
- "until" uses the viewer's time zone with a short zone name.
- Sidebar: the collapsed rail renders plain labels (no tab stops); the group
  holding the current page can fold and keeps only that row. The pill uses
  aria-label on the rail instead of a title.
… side panel

- Each hub section has its own path (/alerts/rules, /alerts/uptime, /alerts/slos,
  /alerts/silences, /alerts/maintenance, /alerts/on-call, /alerts/routing); /alerts
  stays the Inbox. One page instance serves them all, so a section change reads
  nothing it already has.
- Old /alerts?tab= links replace themselves with the section's path and keep
  their other params ("oncall" and "settings" map to on-call and routing).
- The sidebar's Alerts row lists the sections when active and replaces the hub's
  own section rail. Sub-item aria-current now follows the most specific match.
- New silence opens in a URL-held side panel (?sheet=silence) with a sticky
  Cancel / Save footer; Back, Cancel, Escape and a save close it.
  sidePanelSheet gains onSubmit so the panel is a form.
- The silence panel clears ?sheet= in the model as soon as it closes itself,
  so a clock tick before the URL change can't reopen it. It opens only on the
  Silences section, and a viewer who can't manage loses a linked ?sheet= once
  the grants load (replaced away).
- A rule lives at /alerts/rules/<ruleId>; /alerts/<ruleId> (notifications, the
  apps) replaces itself with it, keeping its tab and window. The rule page and
  editor go back to Rules and their crumbs go through it.
- Settings automation and setup health link to the new section paths.
- The sidebar reveals the open section, every sub-item past the edge fades, on
  each route change; sub-rows are tighter, thin rules split the former groups,
  and the Inbox shows its unacknowledged count from the alert_incidents
  collection, read only while an alerts page is open.
- One AlertsTab schema next to AlertsSection; the sheet commands answer with a
  clock read instead of a no-op message.
… page

The schedule editor renders the draft with the server's renderOnCall
(alerting-core/oncall) on every edit: a lane per layer, the final lane
with No one gap bars, a gap summary with links that focus each gap,
weekend shading, a now line and a 1/2/4 week range. The detail page
draws the same timeline from the server's shifts.
… fit, narrow day headers

A gap is a hollow, hatched bar in the error tone instead of a warning
wash. A bar hides its label under 3.75rem and shows initials when two
characters fit. Layer rows can leave the tab order. Day headers stack
and thin out their dates as days narrow, and the label column sizes to
the timeline's own width.
- The detail calendar draws a skeleton until the shifts for the picked
  range land, instead of old shifts read as one long gap.
- A wholly past range says its gaps are not checked; a draft cannot
  step back from today.
- A layer with a half-typed window does not preview as always active.
- The preview redraws only when the zone, layers, members, minute or
  range change.
- An uncovered schedule says nobody is on call; a gap cut off by the
  range's end has no end time.
- The start note shows only for a new schedule started on an earlier
  day and names who is on call now.
- The editor is two columns from 46rem of room, the preview held in
  view while the form scrolls.
- One shared focus command for gap links.
@coderabbitai

coderabbitai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The changes add shared schedule coverage calculations and timeline rendering. The editor and schedule calendar use previews with selectable date ranges and gap navigation. Saved schedule previews load overrides. The delete-schedule dialog wraps long names.

Changes: On-call schedule coverage previews

Layer / File(s) Summary
Draft coverage and gap calculations
packages/alerting-core/package.json, apps/web/package.json, apps/web/src/page/alerts/schedule-form/form.ts, apps/web/src/page/alerts/shared/schedule-coverage.ts, apps/web/src/page/alerts/shared/schedule-coverage.test.ts
The on-call package adds an export used by the web app. New helpers convert draft layers and calculate coverage, gaps, ranges, and summaries. Tests compare calculated assignments with schedule assignments.
Shared coverage preview and timeline
apps/web/src/page/alerts/shared/coverage-preview.ts, packages/views/src/ui/shift-timeline.ts, packages/views/src/ui/shift-timeline.test.ts, packages/views/src/ui/shift-timeline.scene.test.ts, packages/ui/src/styles/tokens.css
The shared preview renders shifts, gaps, notes, and range controls. Timeline updates add gap styling, responsive labels, weekend indicators, time-zone labels, and configurable tab stops.
Schedule editor preview and override loading
apps/web/src/page/alerts/schedule-form/*, apps/web/src/page/kit/form-section.ts, packages/views/src/ui/INDEX.md, apps/web/src/lab/oncall-lab.ts
The editor fetches overrides for saved schedules and renders draft coverage with clock updates and preview controls. Layout updates and lab fixtures support the editor preview.
Schedule calendar coverage view
apps/web/src/page/alerts/schedule/{message,model,update,view}.ts, apps/web/src/page/alerts/schedule/schedule.scene.test.ts
The schedule calendar uses the shared preview and supports range selection and gap focus. It shows loaded shifts only when their read range matches the selected range.

Long schedule names in delete dialog

Layer / File(s) Summary
Delete dialog title wrapping
apps/web/src/page/alerts/hub/view-oncall.ts, apps/web/src/page/alerts/hub/hub-oncall.scene.test.ts
The delete dialog title uses wrapping typography. A test checks that the full long schedule name appears in the dialog’s accessible name and heading.

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant ScheduleForm
  participant FetchScheduleFormOverrides
  participant listOverrides
  participant draftCoverage
  participant coveragePreview
  ScheduleForm->>FetchScheduleFormOverrides: request overrides for an edited schedule
  FetchScheduleFormOverrides->>listOverrides: retrieve schedule overrides
  listOverrides->>ScheduleForm: return override result
  ScheduleForm->>draftCoverage: calculate draft shifts and gaps
  draftCoverage->>coveragePreview: provide coverage for the selected range
Loading

Possibly related PRs

Suggested labels: preview:web

Merge Risk: Minimal · up to 58a34

The preview’s kit-surface inconsistency does not block merging.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main change: adding a live coverage preview to the schedule editor.
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 25 files. (1 skipped: 1 unsupported.)

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5da909ec-a9e1-44b1-9607-498d68a7144d
Commits

Reviewing files that changed from the base of the PR and between 00a9419 and 58a34f0.

Files ignored due to path filters: 1

  • bun.lock is excluded by !**/*.lock
Files selected for processing: 2

  • apps/web/src/page/alerts/schedule-form/view.ts
  • packages/views/src/ui/INDEX.md
Files skipped from review as they are similar to previous changes: 1

  • packages/views/src/ui/INDEX.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

@maple-review-bot

This comment has been minimized.

@maple-review-bot maple-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 inline note from Maple's review. The score and summary are in the review comment above.

…size

- A `scrim-panel` token (12% black, 24% in dark) with no blur sits beside a
  side panel, so the page it edits stays readable. Dialogs and other sheets
  keep `scrim`.
- `sidePanelSheet` takes `size`: `compact` (28rem) for a few short fields,
  `form` (42rem, the default) or `wide`.
- The on-call pill is one 32px row of the footer list: a status dot and
  "On call until Mon 09:00" in the viewer's zone (the date instead of the
  weekday once the handoff is over six days out), or a muted "Not on call".
  The zone, date and schedules are its tooltip and accessible name. On the
  collapsed rail it is a calendar glyph badged with the dot.
- Group chevrons show faintly at rest; the toggle is 28px tall.
- A folded group holding the current page shows that page's parent row
  alone, highlighted, without its sub-items.
- Hover is a neutral wash. When a sub-item is the current page only it is
  tinted; its parent keeps the medium weight on a plain background.
- Sub-item rows are 28px on desktop and 36px in the mobile sheet.
- /lab/shell gains Services and Logs pages, a far handoff and both panel sizes.
… the silence panel

- Each section's header has one primary action: New rule (split) on the Inbox
  and Rules, New monitor, New SLO, New silence, New window, New schedule and
  Add destination on their own sections. A section whose empty state already
  offers it shows none until it has rows.
- The Alerts sub-list sets its groups apart with a 4px gap instead of rules,
  and its rows take the kit's height again.
- The silence panel's Services, Environments and Tags are chips inputs that
  suggest what the org's rules name (and the services Uptime listed); a typed
  name can still be added. Its labels share one style.
- A picked end is on the viewer's clock and the field names the zone
  ("Ends, CET"); a scheduled row names its day once. The lab reads the
  viewer's zone instead of UTC.
- The duration choice uses the larger segmented size.
# Conflicts:
#	apps/web/src/shell/oncall.scene.test.ts
#	apps/web/src/shell/view-nav.ts
@maple-review-bot

This comment has been minimized.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

F4 won't fix: the range runs from the start of today for 14 days and gaps are only checked from now, so "the next 14 days" names the range shown on the timeline; a clock-exact window would move the axis every minute. F1 to F3 are being fixed in a follow-up commit (the editor will load the schedule's overrides).

Editing a saved schedule now reads its overrides and renders the draft
with them, so the preview's gaps match paging and the detail page. The
timeline is a skeleton until they land; a failed read previews without
them, says so and offers another try. A new schedule asks for none.

The timeline's day header keeps each day's full name for screen
readers when its drawn label is shortened, and durationText's comment
says minutes show only under a day.
@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

F1 to F3 fixed in 7e5000c. F1: editing a saved schedule now loads its overrides (same listOverrides as the detail page), layers them over the draft and draws them in the final lane; skeleton while loading, a note and retry if the read fails, no request for a new schedule. F2: each day cell carries its full name as visually hidden text. F3: the durationText comment now says minutes show only under a day, pinned by a test.

@maple-review-bot

This comment has been minimized.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

@maple-review-bot won't fix F3 and F4. F3: dropping minutes past a day is intended ("3d 4h 30m" is noise in a summary line); the doc comment now says so and a test pins "2d 10h" for 2d 10h 30m. F4: "the next 14 days" names the range drawn on the timeline, which starts at the beginning of today; a clock-exact window would move the axis every minute.

@maple-review-bot

Copy link
Copy Markdown

Both can be dismissed — your reasoning matches what the code actually does.

F3 — durationText (schedule-coverage.ts:205-216) drops minutes only when days > 0, the doc comment at :204 now says exactly that, and schedule-coverage.test.ts:259-262 pins 2d 10h for 58h30m and 23h 30m for 23h30m. A summary line that floors at hours past a day is consistent with also flooring at minutes under an hour, and the under-statement is bounded at 59m. No objection.

F4 — confirmed the wording describes the drawn range, not a clock-exact window: previewRange anchors on zonedDayStart (:148-156), and gapSummary only uses "the next N days" when weekOffset === 0, falling back to "in this period" otherwise (:250-257), which the tests cover at :231-232 and :245-246. Keeping the axis fixed to day boundaries is the right trade for a calendar; moving it every minute would be worse than the wording gap. Dismissed.

The only thing I'd add, not as a blocker: because gaps are checked over [max(fromMs, nowMs), toMs) (coverage-preview.ts:217-218) while the range starts at the beginning of today, "Covered for the next 14 days" can be verified for as little as ~13 days ahead late in the day. If that ever matters, naming the range end (Covered until Sat 5 Dec 00:00, reusing gapRangeText's day formatter) would be exact without moving the axis — but it's a copy choice, and the current bound is under 24 hours. Nothing new to raise; still fine to merge.

# Conflicts:
#	apps/web/src/shell/command.ts
#	apps/web/src/shell/flags.ts
@maple-review-bot

This comment has been minimized.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

@maple-review-bot won't fix F3. Past a day the length is a headline figure and the exact start and end are printed beside it in the same line, so the minutes are dropped on purpose (the function's comment says so).

@maple-review-bot

Copy link
Copy Markdown

You're right, and F3 can be dismissed. I checked the head commit: the only production caller of durationText is gapRangeText's neighbour in gapSummary (schedule-coverage.ts:254), and the range is always interpolated right after the duration on the same line:

`... longest ${durationText(longest.endMs - longest.startMs)}${isOpenGap(...) ? " or longer" : ""} (${gapRangeText(longest, scope.timeZone, scope.checkedToMs)})`

gapRangeText emits minutes for both ends in every branch it can reach here — Sat 21 Nov 00:00 to 16:00 when same-day, full day+time for the end across days, from Sat 21 Nov 08:00 when open — so the exact length is readable, and the doc comment at line 204 plus the durationText(58 * HOUR + 30 * 60_000) === "2d 10h" test at schedule-coverage.test.ts:265 show the truncation is deliberate rather than an oversight. My finding was that a >24h gap's headline is imprecise; it was not that the information is missing from the UI, and since it isn't, there's nothing to fix. No edit staged.

# Conflicts:
#	apps/web/src/shell/message.ts
#	apps/web/src/shell/model.ts
#	apps/web/src/shell/oncall.scene.test.ts
#	apps/web/src/shell/update.ts
#	apps/web/src/shell/view-nav.ts
#	packages/views/src/ui/sheet.ts
@maple-review-bot

This comment has been minimized.

Base automatically changed from ux/alerting-pages to main November 10, 2026 14:26
@maple-review-bot

This comment has been minimized.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

F5: fixed in 72e28544e2. The editor now takes the same 30-second clock tick as the schedule page (ReadClock), so the now line and the gaps counted from it move while the editor stays open. A scene test reads the now line before and after a tick. This was also seen in the preview test ("Now" stayed at the page-load time).

@maple-review-bot

This comment has been minimized.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

F6: fixed in 63832b8668. The two-column layout now starts at 58rem of room, so the preview is only placed beside the form once the timeline fits without scrolling. Checked in a browser: at 1024px the preview follows the form at full width, and at 1280px it sits beside it with all 14 days visible.

@maple-review-bot won't fix F3 (dismissed earlier: the exact start and end are printed beside the rounded length).

@maple-review-bot

Copy link
Copy Markdown

Checked the head (63832b8): view.ts 560–593, form-section.ts (formScrollArea now takes a class, the card is a @container/form), coverage-preview.ts, and the two width thresholds in shift-timeline.ts.

F6 is most of the way fixed — the 304px squeeze and the max-w-3xl form column competing for space are gone. One rem is still missing from the arithmetic, though, so there is a narrow band where the columns split and the timeline still scrolls:

  • the container query measures the scroll area's content box, so 58rem with its own p-4 excluded — that part is right,
  • minus the form column 26rem and gap-4 1rem → preview column 31rem,
  • the wrapper at line 581 has p-4, so the preview section and timeline frame get 29rem,
  • and packages/shared… specifically shift-timeline.ts:396-ish, the track is min-w-[45rem] @min-[30rem]:min-w-0, so it only unscrolls at 30rem.

So the split wants 26 + 1 (gap) + 2 (wrapper p-4) + 30 = 59rem. Between 58rem and 59rem the layout is side-by-side but the track is still 45rem inside a 29rem scroller, and the preview's @min-[30rem] branches (controls on one row, six gap links instead of three) are still on the narrow side. The comment at line 564 has the same omission — "the form column plus the 30rem the timeline needs" is 56, or 58 if it counts the p-4 and forgets the gap.

Your 1024px and 1280px checks don't contradict this; 1280px just lands above 59rem. To make it exact: @min-[58rem]/scroll → @min-[59rem]/scroll (line 569, and the four occurrences on line 581), with the comment reading "the form column, the gap and the 30rem the timeline needs".

On F3 I agree — gapSummary always prints gapRangeText beside the rounded length (line 254), and that carries the minutes, with open gaps reading "from …" plus "or longer". Rounded length alone would mislead; beside the exact range it doesn't. Withdrawn.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

Right, the arithmetic was one rem short. 00a94199ae moves the breakpoint to 59rem (26 form + 1 gap + 2 preview padding + 30 timeline) in all six places, and the comment now lists the same four parts.

@maple-review-bot

This comment has been minimized.

@Makisuo

Makisuo commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

F7: fixed in 58a34f0a15. The breakpoint is 60rem now: the 59rem sum plus the card and frame borders, rounded up, so the timeline's @min-[30rem] branch is always reached once the columns split.

@maple-review-bot

maple-review-bot Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 10/10 · safe to merge. The gap and lane logic is pinned by tests that sample the preview against onCallAt across a DST change; the only open finding is the gap-length text the author declined to change.
1 note · tests covered · risk medium

Adds a live coverage preview to the on-call schedule editor (from the draft, overrides included) and reuses it on the detail page, with gap bars, a gap summary and a 30-second clock. shiftTimeline and formSection gained container-query layout. Safe to merge.

  • coveragePreview draws a lane per layer, the final lane and "No one" gap bars
  • The editor loads the saved schedule's overrides and layers them over the draft
  • shiftTimeline gains a gap tone, weekend shading, a zone label and narrow-bar labels
  • The detail page redraws the same preview from the server's shifts over 1, 2 or 4 weeks

Still open from earlier reviews

Fixed since the last review

  • ✅ F7 · Two-column breakpoint lands 4px before the timeline's @min-[30rem]

58a34f0 · What was checked, coverage and telemetry details are on the Maple / review check. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@Makisuo
Makisuo merged commit dce9c2d into main Nov 10, 2026
44 checks passed
@Makisuo
Makisuo deleted the ux/schedule-preview branch November 10, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant