Skip to content

NEXUS-4156: Add workspace Leads and choose a chat's workspace - #2788

Open
gilgtm wants to merge 3 commits into
gil/nexus-4163-solo-lifecyclefrom
gil/nexus-4156-workspace-lead
Open

gilgtm wants to merge 3 commits into
gil/nexus-4163-solo-lifecyclefrom
gil/nexus-4156-workspace-lead

Conversation

@gilgtm

@gilgtm gilgtm commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Restores workspace selection and adds optional workspace Leads (bc4996eb3). It also lets you choose and show a chat's workspace (96a096a50, fa06b6d8f).

  • Selection: a workspace selects from its title or from blank row space. It opens its optional Lead task, or a New chat draft for a Lead when it has none.
  • Header: task creation shows on hover. A header too narrow for both controls keeps only its actions menu, which offers New task at every width.
  • Storage: Leads live in their own private record. They load with Groups and are pruned against freshly read Groups. A failed read affects only Lead selection, and nothing writes Leads after a failed read.
  • Lead drafts: a region's lead draft opens in its workspace with openDraft(..., { lead: true }). The draft start records the Lead only while the draft still targets that workspace; the source saves it with setWorkspaceLead.
  • Who can set a Lead: any running registered region source can save its own Solo task as a workspace Lead. The Lead must still be the owner's own Solo channel in that source's region.

Compared with the previous version of this PR

Rebased onto main. bc4996eb3 also restores the workspace header's blank-space target and its narrow-width rule. On the shared section heading, the strips above and below the label and the trailing space did not select the workspace, and a narrow header kept New task. tests/browser/solo-rename.spec.mjs caught it on hosted CI.

Choose and show a chat's workspace (96a096a50, fa06b6d8f)

  • # in New chat: # lists the workspaces the composer's workspace control offers, above channels. Choosing one removes the #query and sets the control, leaving no text or chip; Send files the chat as before. Only host code can make the workspace edit, so a plugin row that looks like one is dropped.
  • Region adapter: a Solo region can offer an optional workspace adapter for its chats. The composer's workspace control then shows the region's filing and files through it, instead of hiding. Until the chat has a message, # offers the same workspaces and files the chat at once.
  • Focus while saving: the control stays focusable and ignores activation (aria-disabled), so a pointer or keyboard choice keeps focus on it.

Test changes for these two commits

Removed by this PR's diff (0)
  • none
Added by this PR's diff (10)
  • src/bundled/channels/ChannelCompletion.test.tsx: lets workspace rows take their place within the row limit
  • src/bundled/channels/ChannelCompletion.test.tsx: lists a new chat's workspaces first, by the channel name rule
  • src/bundled/channels/ChannelCompletion.test.tsx: offers no workspace rows outside a new chat
  • src/features/conversation/completion.test.ts: keeps a host workspace edit and drops a provider's look-alike
  • src/features/solo/SoloDraft.test.tsx: # chooses New chat's workspace without leaving text, and Send files the chat there
  • src/features/solo/WorkspaceControl.test.tsx: keeps focus on the control while a keyboard choice saves, and ignores it until then
  • src/features/solo/WorkspaceControl.test.tsx: keeps hiding a region chat whose region offers no workspace
  • src/features/solo/WorkspaceControl.test.tsx: shows a region chat's workspace and files it through its region
  • src/features/solo/chat-workspace.test.ts: calls a chat new only while its verified, complete history has no message
  • src/features/solo/chat-workspace.test.ts: never calls a chat new before its history is known

buzz-review-completed

Testing

Local runs on macOS, on the stack rebased onto main 9596cd3db:

  • The pushed heads differ from the tested adbdf424e chain only in tests/browser/solo-rename.spec.mjs. 02f9c0277 makes the new plugin-owned lifecycle test wait for the chat's row before filing it, after the hosted flake check caught it racing the roster load. With that fix, the full solo-rename.spec.mjs passed 180/180 at 02f9c0277 (10 repeats, Chromium and WebKit) and 120/120 at c99d0ce51 (5 repeats).
  • At this PR's head 6d474514c: pnpm check (Biome, TypeScript and the design checks) and the icon check passed. Vitest for the files the flake check selects for this PR: 817 passed.
  • Rust at 6d474514c: cargo fmt --check and cargo clippy -p Buzz --all-targets -- -D warnings passed. relay::kit tests at the stack tip: 9 passed. cargo-deny check passed at the stack tip.
  • At the stack tip adbdf424e: full Vitest, 20556 passed and 23 skipped (includes browser-host/channel-kit.test.mjs).
  • Browser journeys at the stack tip, Chromium and WebKit: the full tests/browser/solo-rename.spec.mjs, repeated 5 times, passed 120/120. The 34 other specs that the flake check relates to the stack, run once in each engine: 343 passed, 3 skipped by their own conditions. The full browser suite was not run locally.
  • The Nexus plugin's connected browser harness ran on the actual Buzz web shell and plugin UI, with a simulated relay and generated identities, before the rebase. Full run at host pin 049a9b57e (now 1fbd49c49): 53 passed. Targeted New task, workspace New task and Solo Workspaces tests at pin 797040559, before its header fix: 4 passed.

Native testing: Gil ran the native desktop app on this stack at adbdf424e, with the matching Nexus plugin build. Gil confirmed that these native-only paths passed:

Agent testing did not reach these paths: the agent ran no native app, no real relay and no real agent.

Known gaps

  • The "Removed" list has two tests that look reworded rather than dropped. Their reworded versions are under "Added": ordinary workspace draft after session replacement, and ordinary drafts not marked as a region draft.

Hosted or local failures that this stack does not cause:

  • tests/browser/typing.spec.mjs:290 ("a growing channel/thread composer lifts history with it at the bottom") intermittently fails with React error Add complete reaction toggles to the message menu #185 on main too. Locally it failed 12 of 12 runs at 9596cd3db and 9 of 12 at a later main commit.
  • On macOS, cargo test -p Buzz crashes the library test binary (SIGSEGV), and some host_command deadline tests fail. Both happen the same way at base 9596cd3db, before this stack. Hosted Linux CI is the reference for these.

Test changes

Titles are compared only in the test files each range changes. Tests that moved or were renamed are matched by title.

Removed by this PR's diff (2)
  • src/app/shell/PrimarySidebar.test.tsx: does not navigate to a replaced session after project creation from %s completes
  • src/features/channel-navigation/SoloInventory.test.tsx: shows and selects the ordinary New chat draft row for %s
Added by this PR's diff (23)
  • browser-host/channel-kit.test.mjs: workspace Leads admission: $name
  • src/app/shell/PrimarySidebar.test.tsx: keeps an ordinary chat editor and pending save through task-source recovery
  • src/app/shell/PrimarySidebar.test.tsx: keeps ordinary Buzz creation controls until a workspace source opts in and restores them when it is removed
  • src/app/shell/PrimarySidebar.test.tsx: opens an ordinary workspace draft from %s and ignores later completion after session replacement
  • src/app/shell/PrimarySidebar.test.tsx: selects the created workspace through its source from %s and retains selection failures for retry
  • src/bundled/channels/SoloWorkspaces.test.tsx: selects a Lead workspace only once its separate Leads record is read, showing the owner's failure with Retry
  • src/bundled/channels/SoloWorkspaces.test.tsx: shares a workspace frame while keeping lead selection, disclosure and chat creation separate
  • src/features/channel-navigation/SoloInventory.test.tsx: selects ordinary drafts without marking a region draft as New chat (%s)
  • src/features/channel-navigation/routes.test.ts: keeps a region lead draft only with its region and workspace
  • src/features/channel-navigation/solo-navigation-draft.test.ts: opens a workspace's lead draft only in that workspace and returns the lead with its start
  • src/features/channel-navigation/solo-workspaces.test.ts: keeps a Lead to the owner's own Solo channel in the source's region
  • src/features/channel-navigation/solo-workspaces.test.ts: lets a running registered source without a task contract set its own Solo task as Lead
  • src/features/channel-navigation/solo-workspaces.test.ts: refuses a Lead from a registered source that is not running or is unregistered
  • src/features/channel-navigation/solo-workspaces.test.ts: resolves archived lead history and replaces only an authoritatively absent lead, fencing source ownership and binding
  • src/features/relay/solo-preferences.test.ts: isolates an unreadable Leads record from workspaces and the catalog, and never writes over it
  • src/features/relay/solo-preferences.test.ts: keeps Leads in their own record, fencing conflicting replacements and leaving Groups at main's fields
  • src/features/relay/solo-preferences.test.ts: keeps unknown Leads fields, hides and prunes orphans, and best-effort removes a deleted workspace's Lead
  • src/features/relay/solo-preferences.test.ts: loads Leads beside Groups, and session recovery retries a transient failure
  • src/features/relay/solo-preferences.test.ts: never lets a refresh begun before a confirmed Lead write show the older Leads
  • src/features/relay/solo-preferences.test.ts: prunes Leads against Groups read after them, so another device's Lead survives
  • src/features/solo/SoloDraft.test.tsx: a region lead draft starts its workspace's lead only while it still targets that workspace
  • tests/browser/solo-rename.spec.mjs: task-source recovery retains an ordinary chat editor, caret and unsaved name
  • tests/browser/solo-rename.spec.mjs: workspace blank space selects independently of its controls ${variant.name}
In the previous version of this PR, not carried over (1)
  • src/features/channel-navigation/SoloInventory.test.tsx: selects ordinary drafts without marking a task draft as New chat (%s)

@gilgtm
gilgtm added this pull request to stack #2791 November 6, 2026 12:04
@gilgtm
gilgtm force-pushed the gil/nexus-4156-workspace-lead branch from 417648c to 0c986b0 Compare November 6, 2026 16:02
baxen pushed a commit that referenced this pull request Nov 8, 2026
…te (#2819)

Deleting a Solo workspace (**Actions → Delete workspace**) removed it
from the groups record but left its settings record live on the relay.
That record holds the workspace's instructions, folders and agents. Once
the workspace was gone, nothing could reach the record, but nothing
deleted it either. This PR tombstones the record after the groups write.

**What you see in the app:** nothing changes. The sidebar, the delete
flow and its timing are the same as on `main`. Only the relay record
changes: `me-section-<sha256(workspace id)>` becomes a tombstone
(`deleted: true`). It has no instructions, folders, agents or teams, and
its name is the neutral "Deleted workspace".

## Before / after

Left: `main` at `067db608f`. Right: this change, recorded at
`d61d1dbb7`, a pre-squash commit made before the review fixes. The
recorded flow is a delete whose groups write confirms, with no other
save in flight, and it takes the same path on this head. The review
fixes only change a retried delete and overlapping kit saves (see
below). The recording uses Chromium at 1280 px and fixture data only.

No app surface shows a deleted workspace's settings record. So the
dashed magenta **TEST HARNESS · NOT PART OF BUZZ** panel in the bottom
right reads the record from the fixture relay and decrypts it. That
panel is a throwaway hook in the recording worktree and is not part of
this PR.

**What to notice:** the app looks the same on both sides, so watch the
harness panel.
- At step 5, after Delete workspace, `main` still reads Launch's record
as **LIVE**. It is still named "Launch chats" and still has the
instructions and `~/Development/launch-site`.
- With the fix, the same record is a **DELETED** tombstone named
"Deleted workspace", with instructions `""` and folders `[]`.
- Step 6 creates Launch again. Its settings open blank on both sides,
because a new workspace gets a new id.


https://github.com/user-attachments/assets/22b860fb-a0cf-462e-b2b9-52ccfa89066d

![Before, step 5 on main 067db60: Launch is gone and Release checklist
is back under Chats, but the harness panel still reads the deleted
workspace's record as LIVE (deleted: false), named "Launch chats", with
the saved instructions and
folder.](https://github.com/user-attachments/assets/7fe9fce1-cf32-4a45-a101-2173a4df49cf)

*Before, step 5 (`main`): the sidebar no longer lists Launch. The
harness panel shows its record still **LIVE**, still named "Launch
chats", with the instructions and folder.*

![After, step 5 with this change: the same sidebar, but the record is
now a DELETED tombstone named "Deleted workspace", with instructions ""
and folders
[].](https://github.com/user-attachments/assets/7a6f4925-45d5-4310-b65a-b0a430f56df6)

*After, step 5 (this change): the sidebar is the same. The same record
is now **DELETED (tombstone)**. Its name no longer mentions Launch, and
its instructions and folders are empty.*

## What changes and why

The fix is in `removeSection` in
`src/features/relay/solo-preferences.ts` (+38/−14). The channel kit's
save guard in `src/features/channel-templates/capability.ts` (+8/−5)
changes too, so the tombstone doesn't block other settings saves.

- **When the groups write is confirmed,** `removeSection` queues a
second write through the store's existing `serialize` queue. That write
looks up the workspace's template with `templateEntry(…, await
projectTemplateId(id))`. If a live template exists, it saves it back
with the kit's existing `save(value, expected, deleted = true)`.
- **The tombstone is emptied.** It empties the lineup with
`emptyLineup()` (instructions, folders, agents and teams), so it doesn't
republish the encrypted instructions.
- **The tombstone is renamed.** It replaces the name `"<workspace>
chats"` with the constant "Deleted workspace", so the user's workspace
name isn't kept either. The TS parser and native `kit.rs` admission both
accept any non-empty name of up to 120 characters. Every reader skips a
deleted template, so nothing displays it.
- **The delete doesn't wait for it.** `removeSection` still resolves
once the groups write lands, so the sidebar and the focus move don't
wait for the second write. Mutations queued after that point wait behind
the tombstone.
- **It's best effort.** A failed tombstone only logs `console.warn`. It
never rejects `removeSection` or undoes the groups write, and the record
stays live but unreachable, as on `main`. A failed groups write queues
no tombstone. There's no write when no live template exists.
- **A retried delete still cleans up.** A groups write can land and
still reject: exact relay confirmation fails and the outbox delivers
later. The sidebar keeps the workspace, so the user retries, and the
retry finds it already gone from the groups record. `removeSection` used
to return early there, so the record stayed live. It now queues the same
cleanup whenever the workspace is absent. The cleanup writes nothing
without a live template.
- **The cleanup signal is bound first.** The queued op's first statement
is `AbortSignal.any([lifetime, generation.signal])`, ahead of the
id-hash `await`. That ties the tombstone to the generation `serialize`
admitted, so a cache clear (`clearCache()` → `soloPreferences.clear()`)
during the hash still aborts it. Bound after the `await`, the tombstone
would take the new generation's signal and write after the clear. An
account switch isn't the case this guards: it ends the session, and
`lifetime` already aborts the tombstone.
- **No import cycle.** `relay/solo-preferences.ts` now imports
`solo/workspace.ts`, but `workspace.ts` never reaches `solo-preferences`
or `session` at runtime.

`docs/solo/README.md` now notes the best-effort tombstone, what a failed
tombstone leaves behind and the retried delete. `docs/buzz-help.md`
doesn't describe what a delete keeps, so it's unchanged.

## Overlap with #2788

#2788 (draft) changes the same `removeSection` hunk. It makes the same
split, `const groups = …; const saved = await save(groups, entry,
active); … return saved;`. Then it queues its own best-effort cleanup of
the workspace's Lead with `void serialize(…)`. This PR uses the same
shape on purpose. Whichever PR lands second gets only a small conflict:

- **Imports:** keep both.
- This PR adds `emptyLineup` to the `../channel-templates/model` import,
and imports `projectTemplateId` and `templateEntry` from
`../solo/workspace`.
  - #2788 adds its Leads names and `isTransientFailure`.
- **`removeSection`:** keep this PR's removal of the early return and
its conditional `const saved = value.groups.some(…) ? await save(groups,
entry, active) : project(value);`. Keep both `void serialize(…)` blocks
between `const saved = …` and `return saved;`, each with its own
`.catch` and warning. Their order doesn't matter: they write different
records, and each binds its own cleanup signal first. Without the early
return, #2788's Lead cleanup also runs for a workspace that is already
absent. Check that it writes nothing when there's no Lead.
- **Tests:** keep both sets in `solo-preferences.test.ts`.

## The channel kit's save guard is per record

The kit used to have one `saving` flag for the whole session
(`src/features/channel-templates/capability.ts`). Workspace settings
(`WorkspaceSettings.tsx`) and New workspace (`NewWorkspace.tsx`) save
defaults through the kit directly, outside the Solo queue. So saving
another workspace's defaults while the tombstone was pending failed with
"Recipe saving is unavailable or already in progress". kalvinnchau
reproduced this in Chromium and WebKit.

- **One save per record.** The guard is now a set keyed by the record's
coordinate (its `d` tag). Saves of other records proceed. A second save
of the same record still fails fast with the same message. Every check a
save makes is already per record: the head read, the unresolved-save
guard and the `created_at` check.
- **The trailing refresh doesn't join an older read.** Once saves
overlap, one save's trailing refresh could join a catalog read that
another save began before this one was confirmed. The snapshot would
then miss the save until the next refresh, and Solo drafts compare their
defaults revision against that snapshot. `kit.save` now ends with
`refresh({ after: true })`. That only adds a read when another catalog
read is already in flight.
- **What can still collide:** two saves of the same record. On this
device, a deleted workspace's settings can't be opened once it's gone
from the sidebar.
- **Queue order.** A mutation queued *during* the groups write runs
before the tombstone. "Later mutations wait behind it" holds for
mutations queued after `removeSection` resolves.

`void serialize` stays, for three reasons:
- Awaiting `kit.save` inside the delete would double the delete's
latency, and a slow signer or confirm would hold the delete open.
- `await serialize(…)` from inside the op would deadlock on its own
queue.
- `void serialize` matches #2788's Leads cleanup.

## Follow-up (pre-existing, not in this PR)

Take a second device that hasn't received the groups update. Its sidebar
still lists the deleted workspace. If someone opens that workspace's
Workspace settings there and saves, a live template is published over
the tombstone. The problem predates this change: on `main`, that save
overwrites a record that was never deleted. A fence would belong in the
project-defaults save path, which is outside this change.

## Verification

Checked on this head (`86feaaa30`):

- **Vitest, the two touched files only:** all 19 tests in
`src/features/relay/solo-preferences.test.ts` and all 35 in
`src/features/channel-templates/capability.test.ts` pass.
  - The tombstone tests cover:
    - the write order: groups, then template;
    - no write when no live template exists;
    - an already-deleted template left alone;
    - a failed groups write, which queues nothing;
    - a failed tombstone, after which `removeSection` still resolves;
    - the emptied, renamed payload.
- **Held-prepare test:** `removeSection` resolves while the tombstone is
held, and a later `createSection` stays unsettled behind it. The writes
land groups → template → groups. The test fails in two wrong versions:
- with the tombstone unqueued, as `void (async () => …)()`:
`createSection` settles while the tombstone is held;
- with the tombstone awaited inside the mutation: `removeSection` never
resolves.
- **Fence test:** it holds `crypto.subtle.digest`, clears the
preferences, then releases. It fails if the cleanup signal is bound
after the hash `await`.
- **Settings save during cleanup (review finding 1):** the tombstone's
preparation is held. Meanwhile another workspace's settings are saved
through `session.channelKit.save`, as Workspace settings does. That save
succeeds and the snapshot shows the edit. On release, the writes land
groups → settings → tombstone. With the session-wide flag restored, the
save fails with "Recipe saving is unavailable or already in progress".
- **Retried delete (review finding 2):** the fixture hides the groups
write from the strong by-id confirmation reads. So the first
`removeSection` rejects with "awaiting exact relay confirmation" after
the write landed, and only the groups record is written. Then the retry
writes the tombstone. Without the fix, the retry writes nothing.
  - **Kit tests:**
- With one record's save held, another record saves, and a second save
of the held record is refused. This fails with the session-wide flag,
and also with no guard at all.
- A save reads itself back after a catalog read that began before its
confirmation. It fails with a plain `refresh()`.
- **Mutation checks:** each of these wrong versions fails at least one
test:
    - unqueued;
    - awaited inside the mutation;
    - the cleanup signal bound late;
    - the session-wide flag;
    - no guard;
    - a plain trailing `refresh()`;
    - the early return for an absent workspace.
- **Earlier mutation checks:** these wrong versions failed on earlier
heads. They weren't rerun here because their code is unchanged:
    - queued before the groups save;
    - `deleted: false`;
    - the name kept;
    - `.catch` removed.
- **Static checks:** `tsc --noEmit` passes. Biome passes on the four
changed source files, and `git diff --check` is clean. The pre-commit
hooks also passed: literal-names, icons, biome, sadscan and git-lfs.

Checked on earlier heads only:

- The 16 affected test files (521 tests), `pnpm lint` and `pnpm
design:check` passed on the pre-squash branch, before the review fixes.
- **Browser flow:** this ran in the throwaway recording harness, which
isn't in this PR. The flow creates Launch, saves instructions and a
folder, deletes the workspace, reads the record, then creates Launch
again. Against `d61d1dbb7`, it passed in Chromium (25.2 s) and WebKit
(27.0 s).
- **Red checks for the flow:**
- against `main`, it fails at the tombstone assertion, because no
tombstone is written;
- against the first draft of the fix, which kept the workspace name, it
fails at the name assertion.
- **No browser journeys added or removed.** The ordering, guard and
failure contracts belong in the Vitest tests. The browser flow above
only produced the recording.
- **Agent review:** two agent reviews ran before kalvinnchau's review.
Their findings were applied, with two exceptions described above: `void
serialize` was kept, and the second-device fence is left as a follow-up.
No new agent review ran on the review fixes.

Not checked:

- **Other kit consumers' tests:** `WorkspaceSettings`, `NewWorkspace`
and session tests weren't run locally for the kit change. CI covers
them.
- **kalvinnchau's app repro:** it holds tombstone preparation while
saving another workspace's defaults. It wasn't rerun in a browser on
this head.
- **The desktop app, a real relay and the native signer.**
- **Human test:** not done yet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Matt Toohey <contact@matttoohey.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@gilgtm
gilgtm force-pushed the gil/nexus-4156-workspace-lead branch from 0c986b0 to 391ac3f Compare November 10, 2026 03:00
@gilgtm gilgtm changed the title NEXUS-4156: Add workspace Lead selection and private storage NEXUS-4156: Add workspace Leads and choose a chat's workspace Nov 10, 2026
@gilgtm
gilgtm removed this pull request from stack #2791 November 10, 2026 03:03
@gilgtm
gilgtm added this pull request to stack #3176 November 10, 2026 03:03
@gilgtm
gilgtm force-pushed the gil/nexus-4156-workspace-lead branch from 391ac3f to 6d47451 Compare November 10, 2026 05:31
gilgtm and others added 3 commits November 10, 2026 00:04
Workspaces select from their title or blank row space and open their
optional Lead task, or a task composer when they have no Lead. Task
cards share workspace chat styling, task creation is exposed on hover,
and a workspace header too narrow for both of its controls keeps only
its actions menu, which also offers New task at every width.

Leads live in their own private record, load with Groups and are pruned
against fresh Groups. A failed read affects only Lead selection; nothing
writes Leads after a failed read. Native recipes admit optional Leads.

A region's lead draft opens in its workspace with `lead`. Its start
records the lead with how the chat started, only while the draft still
targets that workspace, and the source saves it.

Any running registered region source can save its own Solo task as a
workspace Lead. The Lead must still be the owner's own Solo channel in
that source's region.

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Gil Birman <gil@squareup.com>
In New chat, `#` lists the workspaces the composer's workspace control
offers above channels. Choosing one removes the `#query`, sets the control
and leaves no text or chip; Send files the chat as before. Only host code can
make the workspace edit, so a plugin's look-alike row is dropped.

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Gil Birman <gil@squareup.com>
A Solo region can offer an optional `workspace` adapter for its chats.
The composer's workspace control then shows the region's filing and files
through it instead of hiding. Until the chat has a message (its verified,
complete history holds only membership changes), `#` offers the same
workspaces, and choosing one files the chat at once.

While a choice saves, the control stays focusable and ignores activation
(aria-disabled), so choosing by pointer or keyboard keeps focus on it.

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Gil Birman <gil@squareup.com>
@gilgtm
gilgtm force-pushed the gil/nexus-4156-workspace-lead branch from 6d47451 to fa06b6d Compare November 10, 2026 06:17
@gilgtm
gilgtm marked this pull request as ready for review November 10, 2026 06:37
@gilgtm
gilgtm requested a review from a team as a code owner November 10, 2026 06:37

This branch has not been deployed

No deployments
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