Skip to content

fix(messages): reserve a stable scrollbar gutter on the channel feed - #451

Merged
wesbillman merged 5 commits into
mainfrom
scroll-view-jitter
Sep 30, 2026
Merged

wesbillman merged 5 commits into
mainfrom
scroll-view-jitter

Conversation

@matt2e

@matt2e matt2e commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On Mac WebKit with classic (space-taking) scrollbars, the channel feed could jitter between two wrap widths. The vendored Virtua patch's interruptMomentum() sets the feed to overflow-y: hidden !important on every nonzero size correction. That removes the scrollbar for a frame, which widens the content box and re-wraps rows above the viewport. Their new heights then trigger the next correction, and the cycle keeps going.

  • Fix: .feed now sets scrollbar-gutter: stable, so its inline size stays the same when overflow is toggled. The momentum interrupt stays, because fix(sidebar): paint channel rows with the scroller contents #428 measured that disabling it brings back the WebKit 262287 blank frames.
  • Cleanup: removes the unused .feed::-webkit-scrollbar* rules. Both engines ignore them because scrollbar-width/scrollbar-color are set. .threadHistory is unchanged: it has no Virtualizer and no overflow toggle, so it can't loop.
  • Docs: patches/README.md records the rule that every scroller the patched Virtualizer drives on Mac WebKit must keep a constant inline size across the toggle.
  • Test: adds tests/browser/timeline-scrollbar-gutter.spec.mjs. It applies the patch's exact inline toggle and restore, asserts that clientWidth and a visible paragraph's width match in all three states, and checks the computed scrollbar-gutter in both engines. Against the old CSS the width case failed on Chromium (hidden-state clientWidth 1106 vs 1095).

Review follow-ups

  • Image strip focus reveal (P2): the gutter reserves the thin scrollbar width in headless Chromium even under --hide-scrollbars (10 px on Linux CI, 11 px on a legacy-scrollbar Mac). At 768 px that narrowed the image strip into a range where a pre-existing defect shows: Blink and WebKit both skip horizontal focus scrolling when the newly focused element is already partly visible, so Tab could leave the last thumbnail clipped. MessageRow.tsx now reveals the focused tile within the strip's own scroll padding, only while html[data-keyboard-navigation] is set so pointer focus stays quiet per DESIGN.md. image-strip.spec.mjs asserts against the scroll-padding box in both Tab directions and checks that a mouse press on a clipped tile does not move the strip. The under-scroll reproduces on the base commit for strip widths 330 to 390 px.
  • Classic-scrollbar premise fails loudly (P3): the width case is tagged @classic-scrollbars and runs in a new chromium-classic-scrollbars project that drops --hide-scrollbars and asserts the scrollbar takes space. It runs unconditionally on Linux, opts in on macOS via BUZZ_CLASSIC_SCROLLBARS=1, and otherwise skips with a stated reason. CI runs it as a second step of the measurements job with its own output directory, so the required job blocks on it.

Verification

  • A standalone WKWebView probe (patched Virtua, 400 rows, legacy scrollers) counted overflow-y: hidden toggles: 248 without the gutter, 3 with it.
  • bin/pnpm check passed after every commit.
  • Vitest timeline and Virtua compensation suites: 129 passed. MessageRow tests: 71 passed.
  • Playwright Chromium and WebKit for the timeline, layout, navigation, history and gutter specs: 165 passed. Thumbnail and image specs after the focus fix: 64 passed across both Mac engines. Measurement projects (scroll, channel-opening): 12 passed.
  • Linux CI reproduced in mcr.microsoft.com/playwright:v1.63.0-noble: image-strip.spec.mjs fails at the CI assertion with the old MessageRow.tsx and passes with the fix; the classic-scrollbar project passes with 10 px of scrollbar space; the exact new CI step exits 0 with the measurements report intact.
  • The WebKit layout.spec.mjs:398 failure on the first CI attempt is a pre-existing load-sensitive flake, not related to this change: Linux WebKit reserves 0 px for the gutter, and the test passed 28 of 28 runs without the gutter and 19 of 20 with it under host load.
  • A manual check on a Mac with legacy scrollbars is still the definitive test for the loop itself.

🤖 Generated with Claude Code

matt2e and others added 2 commits September 30, 2026 13:58
The vendored Virtua patch's interruptMomentum() sets the feed to
overflow-y: hidden !important on every nonzero size correction on Mac
WebKit. With classic, space-taking scrollbars that frame removes the
scrollbar, widens the content box and re-wraps rows above the viewport,
whose new heights produce the next correction, so the feed oscillates
between two wrap widths. scrollbar-gutter: stable keeps the feed's inline
size constant across the toggle and opens the ring, while the momentum
interrupt itself stays because PR #428 measured that disabling it brings
back the WebKit 262287 blank frames.

The dead .feed::-webkit-scrollbar* rules are removed: with scrollbar-width
and scrollbar-color set both engines ignore them, and if they ever became
live again the gutter would reserve the classic width instead of the thin
one. .threadHistory deliberately does not get the gutter. It has no
Virtualizer and no overflow toggle, so it cannot loop, and reserving a
gutter there would give short threads a right inset in legacy scrollbar
mode as a design change rather than a bug fix. Its ::-webkit-scrollbar
rules are left as they were.

tests/browser/timeline-scrollbar-gutter.spec.mjs drops Chromium's
--hide-scrollbars so platform scrollbars take space, detaches with
upper(), applies the patch's exact inline toggle and restore, and asserts
clientWidth and a fully visible paragraph width are equal in all three
states. It skips where the scrollbar takes no space (Playwright WebKit on
macOS uses overlay scrollbars) and guards the computed scrollbar-gutter
in both projects. Run against the unchanged CSS it failed on Chromium
(hidden state clientWidth 1106 vs 1095, paragraph 1006 vs 995) and the
CSS guard failed in both engines; with the change it passes on Chromium
and the width case skips on WebKit as intended.

No existing browser spec asserting absolute widths or x positions broke
from the 11 px gutter headless Chromium now reserves, so none changed.

The standalone WKWebView probe under /tmp/wkprobe (patched Virtua bundle,
400 prose rows, AppKit reporting legacy scrollers) was re-run against the
final .feed declarations. overflow-y hidden toggles seen by a
MutationObserver on the scroller's style attribute:
- at bottom, idle, 1 s: 40 without gutter, 0 with
- after scrollBy(-700), detached, 2 s: 80 without, 0 with
- after a +1 px content change on a row above the viewport, 3 s: 120
  without, 1 with
- total: 248 without gutter, 3 with

Suites run (Hermit bin/pnpm):
- bin/pnpm check: passed (biome, typecheck, design typecheck, design
  checks)
- vitest virtua-compensation.test.mjs, ChannelTimeline.test.tsx,
  ChannelTimeline.restore.test.tsx, ChannelTimeline.report.test.tsx:
  4 files, 129 tests passed
- Playwright --project=chromium --project=webkit --no-deps: messages,
  layout, message-actions, message-actions-floating, message-navigation,
  navigation-thread-history, history-loading, image-scroll,
  initial-position, sidenav-polish, design-system,
  timeline-scrollbar-gutter: 165 passed, 1 skipped (the WebKit width
  case)
- Playwright --project=chromium-measurements
  --project=webkit-measurements --no-deps --workers=1: scroll.spec.mjs,
  channel-opening.spec.mjs: 12 passed

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
…th invariant

Follow-up to 386a0746 addressing its review. patches/README.md now records in
the momentum-interrupt section that the overflow-y: hidden frame removes a
classic scrollbar, so every scroller the patched Virtualizer drives on Mac
WebKit must keep a constant inline size across the toggle (scrollbar-gutter:
stable, as .feed does), or re-wrapped rows feed new corrections back into the
interrupt. The .feed comment's precondition is corrected: the global * rule in
scrollbars.css also sets scrollbar-width/scrollbar-color, and what keeps
::-webkit-scrollbar dead is engine support for the standard properties
(Chromium 121+, WebKit from Safari 18.2), not the declarations staying on this
rule.

tests/browser/timeline-scrollbar-gutter.spec.mjs reads offsetWidth minus
clientWidth and decides the overlay-scrollbar skip right after open(), before
paying for the wheel-gesture detach; selects the measured paragraph once and
reuses that node for the before, hidden and restored reads so a re-wrap cannot
swap the compared element; merges the config's launchOptions through a fixture
function instead of replacing them; and its header states that Chromium never
runs interruptMomentum (the MacIntel/Apple predicate is false), so the spec
proves the CSS invariant by replaying the patch's exact inline toggle rather
than the loop, and WebKit only runs the toHaveCSS guard.

.threadHistory and its scrollbar rules are unchanged.

Suites run (Hermit bin/pnpm):
- bin/pnpm check: passed (biome, typecheck, design typecheck, design checks)
- vitest virtua-compensation.test.mjs, ChannelTimeline.test.tsx,
  ChannelTimeline.restore.test.tsx, ChannelTimeline.report.test.tsx:
  4 files, 129 tests passed
- Playwright --project=chromium --project=webkit --no-deps
  timeline-scrollbar-gutter.spec.mjs: 3 passed, 1 skipped (the WebKit width
  case, now skipped before the detach). The Chromium width case passing with a
  nonzero scrollbar width confirms the merged launchOptions dropped
  --hide-scrollbars.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
@matt2e
matt2e requested review from a team, comp615 and wesbillman as code owners September 30, 2026 04:02

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No source-level changes requested; the stable gutter addresses the overflow-toggle width feedback without changing Virtua’s momentum policy.

Star Lord’s automated source review via Wes’s account — head b68a91a1328e6bff4f51d19be55c1c7555eb4209, base 329fe2a1de0ad7f9aa8eebbc02e1a957bcafa25d.

Source-only: no tests/app execution; the author’s native probe was not independently reproduced, and legacy-scrollbar Mac acceptance remains unverified.

The CI snapshot is not green: WebKit panel-resize bottom-follow and Chromium image-strip focus-visibility tests failed, other jobs were still running, and causality is not established.

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 Two actionable issues below: a required image-strip journey fails at the narrower feed width, and the new geometry regression can silently skip its behavioral assertion. The Linux failure is corroborated by width emulation, not a local native-Linux reproduction.

Comment thread src/features/messages/Messages.module.css
Comment thread tests/browser/timeline-scrollbar-gutter.spec.mjs Outdated
matt2e and others added 2 commits September 30, 2026 16:47
Tabbing through a posted image strip relies on native focus scrolling, and
both engines refuse to scroll horizontally when the newly focused element
is already partly visible. Blink sets the partial-visibility behaviour to
no-scroll in Element::UpdateSelectionOnFocus, and WebKit keeps its 32px
legacy horizontal visibility threshold on the focus reveal path; only
scrollIntoView() opts out of either rule. A thumbnail whose far edge is
clipped therefore takes focus without ever coming fully into view, and its
focus ring is cut off. On the base commit this already happens for every
strip width from 330 to 390px. The feed's scrollbar-gutter narrows the
strip by 10px (Linux) or 11px (legacy-scrollbar macOS) under headless
Chromium, which moved image-strip.spec.mjs's fixed 768px viewport into
that window and made the Chromium shard of PR #451 fail at the last-tile
visibility check (review comment P2).

MessageRow.tsx now handles onFocus on the strip group (React's onFocus is
the bubbling focusin, so one handler covers every tile) and nudges only
the strip's own scrollLeft until the focused tile lies inside the strip's
scroll-padding box. In Blink the native reveal runs first and the handler
corrects the clipped case; in WebKit the handler runs first and the
timer-driven native reveal then finds a fully visible element and does
nothing. A strip-local adjustment is used instead of scrollIntoView so
that overflow: hidden ancestors such as the thread container are never
scrolled. Inline start and end are treated as left and right, matching
the app's LTR layout. The feed's scrollbar-gutter CSS is unchanged.

tests/browser/image-strip.spec.mjs now asserts the focused last tile lies
inside the strip's scroll-padding box rather than the parent's bounding
rect. This also catches the base commit's 1px short-of-max state at
398px, where the tile sat inside the border box but past the
scroll-padding end with its ring clipped. Where the strip is too narrow
to hold a tile plus both paddings (the 390px viewport once a gutter is
reserved) the tile's far edge must sit exactly on the scroll-padding end.
No assertion was loosened.

Suites run (Hermit bin/pnpm):
- biome check --error-on-warnings MessageRow.tsx image-strip.spec.mjs:
  clean
- typecheck: clean
- vitest src/features/messages/MessageRow.test.tsx: 71 passed
- Playwright --project=chromium --project=webkit --no-deps
  image-strip.spec.mjs on macOS with legacy scrollbars (Chromium reserves
  an 11px gutter and reproduced the CI failure before the fix): 2 passed
- Playwright --project=chromium --project=webkit --no-deps gifs,
  image-scroll, image-strip, message-management, messages, startup:
  64 passed
- Linux container (mcr.microsoft.com/playwright:v1.63.0-noble, CI config)
  --project=chromium and --project=webkit --no-deps image-strip.spec.mjs:
  1 passed each. Swapping the unpatched MessageRow.tsx back into the
  container fails the Chromium run at the same assertion (now line 131,
  previously 113), so the CI failure is gone rather than moved.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
… project

Resolves review comment P3 on PR #451. The scrollbar-gutter width case
skipped silently wherever the scrollbar took no space, which is every
Chromium run on an overlay-scrollbar Mac and every WebKit run, so a green
sweep could not distinguish "the gutter holds" from "nothing was measured".
The classic-scrollbar premise now fails loudly where it is guaranteed.

tests/browser/timeline-scrollbar-gutter.spec.mjs tags the width case
@classic-scrollbars, drops the launchOptions fixture override and the
space === 0 skip, records the measured scrollbar width in the fixture's
evidence and asserts it is greater than zero with a message naming the
premise. The case is gated by platform rather than by measurement:
unconditional on Linux, opt-in through BUZZ_CLASSIC_SCROLLBARS elsewhere,
otherwise an explicit skip that says why. The toHaveCSS guard stays
untagged so the chromium and webkit projects still run it.

tests/browser/playwright.config.mjs adds the chromium-classic-scrollbars
project: Chromium launched with ignoreDefaultArgs ["--hide-scrollbars"],
grep on the tag, the measurement files ignored, and the inverse grep on
the chromium and webkit projects so the tagged case never runs where
classic scrollbars are not guaranteed. Two details go beyond the design
note. The project depends on webkit-measurements like the engine projects
do, because the local default gate runs every project and a
dependency-free project would share phase 0 with chromium-measurements
under two workers; CI passes --no-deps, so it is unaffected. The project
also has its own outputDir, test-results/browser-classic-scrollbars:
Playwright clears the outputDir of every project a run selects, so a
second invocation sharing test-results/browser would delete the
measurements' ci-report.json, ci-timing.json and per-test evidence.json
before the artifact upload. Probe files confirmed this: a file under
test-results/browser survives the classic run, a file under the classic
outputDir does not.

.github/workflows/ci.yml runs the project as a second step of the
measurements job, after the serial measurements, through
scripts/ci-test-report.mjs with its own report and evidence paths, and the
Measurement evidence artifact uploads both directories. CI required
already needs the measurements job, so the case blocks merges without a
new runner. It is not added to the six-way engine matrix: one file across
--shard=N/6 leaves five shards with no tests, which Playwright treats as
an error. The '*-measurements' glob does not match the new project name,
so the existing step is unchanged, and zizmor reports the same 8 findings
(4 suppressed, 4 low) before and after.

tests/integration/browser-ci.test.mjs gains a guard alongside the
shard-coverage test: the step exists after the serial measurements,
reports through ci-test-report.mjs into a directory disjoint from the
measurements' outputDir, both directories are uploaded, the project's
--list selects only tagged cases in that project, and the chromium and
webkit discovery selects none of them. docs/browser-testing.md describes
the project and the macOS opt-in. patches/README.md does not mention the
spec's skip behaviour, so it is unchanged.

Suites run (Hermit bin/pnpm):
- bin/pnpm check: passed (biome, typecheck, design typecheck, design
  checks)
- biome check --error-on-warnings on the spec, config and integration
  test: clean
- Playwright --project chromium-classic-scrollbars --no-deps on this Mac
  (legacy scrollbars): with BUZZ_CLASSIC_SCROLLBARS=1, 1 passed with
  scrollbar space 11; without it, 1 skipped with the stated reason
- Playwright --project=chromium --project=webkit --no-deps
  timeline-scrollbar-gutter.spec.mjs on this Mac: 2 passed; --list shows
  only the CSS guard in each engine project and only the tagged case in
  the classic project
- Linux container (mcr.microsoft.com/playwright:v1.63.0-noble, CI config):
  --project chromium-classic-scrollbars --no-deps: 1 passed with scrollbar
  space 10; --project chromium and --project webkit --no-deps on the spec:
  1 passed each; the exact workflow step command through
  ci-test-report.mjs exits 0 with a Complete summary and leaves a
  pre-seeded test-results/browser/ci-report.json intact
- node --test tests/integration/browser-ci.test.mjs: 8 passed in the Linux
  container. On this Mac 7 pass and the untouched "browser Rust setup"
  case fails because bash resolves the temp dir through the /private
  symlink; that failure predates this change and does not occur on Linux.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No source-level changes requested on the focus-reveal and classic-scrollbar CI revisions.

Star Lord’s automated source review via Wes’s account — head 37fe84a654c7b34b992b7c1268e399f6ddfb7eb1, base 329fe2a1de0ad7f9aa8eebbc02e1a957bcafa25d.

Hosted measurement artifacts report 9/9 passes plus classic-scrollbar 1/1; full CI was unfinished at the status snapshot.

Source-only: no local tests or app execution; native Mac legacy-scrollbar momentum behavior and a before/after CI-cost comparison remain unverified.

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 The previous focus-visibility and silent-skip findings are addressed. One new pointer-focus regression remains below; its reproduction uses a standalone browser probe, not the candidate app.

Comment thread src/features/messages/MessageRow.tsx
Addresses the review of e4c38af and 37fe84a on PR #451.

React's onFocus is the bubbling focusin, so revealFocusedThumbnail also
ran for pointer focus, and Chromium focuses a link on mousedown (WebKit does
not): pressing a clipped thumbnail on a Chromium host slid the strip under
the held pointer before mouseup, so the release could land on a neighbour or
on padding, and the strip visibly jumped on every such click. DESIGN.md
wants pointer focus quiet, so MessageRow.tsx now gates the reveal on
html[data-keyboard-navigation], the same modality fact MessageComposer.tsx
and useFloatingActionBar.ts read. useKeyboardFocusVisibility sets that
attribute from a capturing window keydown listener, which runs before Tab's
default action moves focus, and clears it from the capturing pointerdown
that precedes the mousedown focus, so a Tab reveal still runs and a press
never does. The code comment records the pointer-focus rationale and that
ordering. The relay-composer fixture already mounts the hook, so the spec's
Tab path keeps revealing.

tests/browser/image-strip.spec.mjs hoists the scroll-padding geometry into
insideScrollPadding(el, edge) and adds two checks per viewport width. After
the max-scroll assertion it Shift+Tabs back to the first tile (Shift+Alt+Tab
on macOS WebKit, matching the forward Alt+Tab), asserting after every press
that the focused tile's leading edge is at or past the scroll-padding start
with the mirrored narrow-strip rule, which exercises the handler's left
branch. It then presses a tile the strip's end clips with the mouse, holds
for two frames, asserts scrollLeft is unchanged, releases, and closes the
viewer the click opened. The width loop must press a clipped tile at least
once. Negative runs confirm each assertion bites: with the handler disabled
the forward pass fails at the last tile; with the left branch removed the
backward pass fails on both Chromium and WebKit; with the gate removed the
pointer check fails with the strip moved 13px on this Mac and 12px on Linux
Chromium.

tests/integration/browser-ci.test.mjs resolves the chromium-classic-
scrollbars project through playwright.ci.config.mjs, which is what the
workflow step runs, requires the local config's project to deep-equal it,
and takes the measurements outputDir from the CI config too, so a CI-only
override of the launch arguments or output directory cannot drift past the
gate. docs/browser-testing.md states next to the test-results/browser
paragraph that the classic project's evidence.json, failure screenshots and
traces land in test-results/browser-classic-scrollbars/ and why.

Suites run (Hermit bin/pnpm):
- biome check --error-on-warnings MessageRow.tsx image-strip.spec.mjs
  browser-ci.test.mjs: clean
- bin/pnpm check: passed (biome, typecheck, design typecheck, design
  checks)
- vitest src/features/messages/MessageRow.test.tsx: 71 passed
- Playwright --project=chromium --project=webkit --no-deps
  image-strip.spec.mjs on this Mac (legacy scrollbars): 2 passed
- Linux container (mcr.microsoft.com/playwright:v1.63.0-noble, CI config)
  --project=chromium and --project=webkit --no-deps image-strip.spec.mjs:
  1 passed each; the gate-removed MessageRow.tsx fails the Chromium run at
  the pointer check before the fixed file passes it
- bin/node --test tests/integration/browser-ci.test.mjs: 8 passed in the
  Linux container. On this Mac 7 pass and the untouched "browser Rust
  setup" case fails on the /private temp-dir symlink, as before this change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No source-level changes requested on the keyboard-only thumbnail reveal, reverse-Tab/pointer regression checks, and CI-config follow-up.

Star Lord’s automated source review via Wes’s account — head e696436abd36510129d9408d3e3acaf228fd77a0, base 329fe2a1de0ad7f9aa8eebbc02e1a957bcafa25d.

The hosted CI snapshot has all required automatic checks passing, including the classic-scrollbar case.

Source-only: no local tests or app execution; native Mac legacy-scrollbar acceptance and a controlled before/after CI-cost comparison remain unverified.

@wesbillman
wesbillman merged commit b2a7919 into main Sep 30, 2026
20 checks passed
@wesbillman
wesbillman deleted the scroll-view-jitter branch September 30, 2026 14:41
TheSentinel454 pushed a commit that referenced this pull request Sep 30, 2026
* origin/main: (27 commits)
  Let plugin pages publish NIP-AR artifacts and embed the host thread view (#434)
  test(app): migrate entity-navigation test off removed buzz://open locator API (#463)
  Show agent activity in navigation (#423)
  test(browser): hold motion when it commits, not on its start event (#459)
  fix(navigation): ignore unknown query parameters on Buzz links and remove the buzz://open locator (#457)
  feat(design-system): distinguish controls on floating surfaces (#429)
  feat(native): add community extras and media preparation (#450)
  Clone inventory identities through reviewed text and fresh identity creation (#289)
  feat(communities): add right-click actions to the community rail (#400)
  fix(messages): keep a send reveal pending until its scroll runs (#454)
  fix(messages): reserve a stable scrollbar gutter on the channel feed (#451)
  fix(sidebar): list plugin pages as sidebar rows via an opt-in primary flag (#401)
  feat(channels): surface canvas content in channel settings (#426)
  fix(profiles): remove redundant presence status row (#394)
  test(browser): count live retries once the page handles startup controls (#443)
  feat(composer): host-owned resource links for the Projects picker (#445)
  feat: support native read state and recent channel activity (#444)
  feat(native): serve relay media and uploads in packaged builds (#433)
  feat(channels): suggest joined channels in the composer (#446)
  feat: support native agent activity, library, memories, and community resolution (#441)
  ...

Signed-off-by: Codex <noreply@openai.com>
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.

3 participants