Skip to content

Guest page: the guest's composer and its own messages (carries #26819) - #30518

Merged
teamleaderleo merged 3 commits into
feat-cmux-nextfrom
lane/mp-guest-composer-carry
Nov 1, 2026
Merged

teamleaderleo merged 3 commits into
feat-cmux-nextfrom
lane/mp-guest-composer-carry

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Leo's words (2026-10-28), on Theo's T3 Code "Share with guest": "we want to be having, be able to do this kind of flow for CMux multiplayer ... we can work on the agent chat multiplayer." In that flow each message the guest sends waits for the owner. And today: "eh i think we'd better try to get at least the agent sessions' group chats in and refined".

This carries #26819 (part 2 of the guest page) onto current feat-cmux-next, now that part 1 landed as #29901 (6e5c3a5). It has only #26819's own three commits, cherry-picked with their authorship kept; #26779's commits are already on base through #29901. All three applied cleanly, so no line here differs from #26819.

  • 8212e5e Guest page: the guest's composer and its own messages (GuestComposer.tsx, guestPrompts.ts, typingSignal.ts, the waiting gallery and tests).
  • a3ef8f7 Guest page: text fields show focus by their edge, not a ring.
  • 5cde0f9 test: the guest page's spy test gives the page its storage (part 2's prop).

Plan: manaflow-ai/cmuxterm-hq#4766. Spec: leo-workspace design/chat-multiplayer.md, section 3 (the guest's composer) and section 4.3 (prompt, typing, prompt_state, prompt_status).

The owner's side of a held prompt (Approve / Decline) is the held-prompt stack (#28859, #29003, #26862, #26742), owned by another lane; until it lands a guest's prompt shows as waiting.

#26819 can close once this lands.

Agent session: agent session

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Adds the guest page's composer so a guest can send messages to the agent, while the chat's owner approves or declines each one before the agent sees it.

  • The guest's messages carry a stable client id in sessionStorage, so a resend after a dropped connection or a reload is the same prompt.
  • Held messages show a "sending" then "waiting on {owner}" state; decided ones collapse to a one-line "Sent / Declined / Withdrawn / Not sent" summary.
  • Typing is signalled at most twice a second and turns off on send, clear, or 5s idle.
  • The owner's Approve / Decline UI is not in this PR; until the held-prompt stack lands, guest messages remain in "waiting".

Written for commit 2f3724b. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 3 commits November 1, 2026 07:53
Part 2 of the guest page (design/chat-multiplayer.md sections 3 and 4.3,
manaflow-ai/cmuxterm-hq#4766).

- Composer: text only (no attachments, slash commands or pickers); Return
  sends, Shift-Return a new line. A message over 32 KiB (UTF-8) cannot be sent
  and says so.
- Each message is `prompt {client_id, text}`. The client id is 128 random bits
  made when the message is written and kept with it in the tab's
  sessionStorage (guestPrompts.ts), so a resend is the same prompt: a message
  the room never acknowledged goes again, same id, with the next snapshot.
- The guest's own messages: while waiting, its chip, the text and "Sending…"
  then "Waiting for <owner>"; decided, one quiet line each: "Sent: …",
  "Declined: …", "Withdrawn: …", "Not sent: …", and for share.too_many_held
  "Not sent, too many messages waiting: …". States come from prompt_state and
  the snapshot's prompts; the snapshot asks prompt_status for held ones it
  does not answer.
- Typing (typingSignal.ts): on at the first keystroke, off on send, clear or
  5 s idle, at most two frames a second, one-shot timers only; a reconnect
  re-sends the current state.
- Gallery guest-page.waiting (held, decided).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
(cherry picked from commit 8212e5e)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
(cherry picked from commit a3ef8f7)
…prop)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
(cherry picked from commit 5cde0f9)
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent claude-opus-5-5 medium, independent): SHIP at 2f3724b

No blocking findings. Guest text and names render as React text (no HTML injection); the page sends only prompt, typing and prompt_status on a synced socket; room prompt_state and stored prompts are validated; resends keep client_id; typing timers are one-shot with dispose/reset; all 10 new strings are in the acpmux catalog; every GuestPage caller passes the new storage prop.

Follow-ups (tracked in an issue):

  • [follow-up] A prompt accepted on a live socket but never answered stays "Sending…" until reconnect (no retry/timeout).
  • [follow-up] After reload, a stored held prompt the host no longer knows shows "Waiting for " forever; needs a "Not sent" fallback.
  • [follow-up] Increased contrast: --agent-border equals --agent-border-strong, so the new :focus rule leaves the composer and join field with no visible focus.
  • [follow-up] firstLine splits on \n only; pasted \r\n leaves a stray \r.
  • [follow-up] No guard against a decided prompt going back to held on a late prompt_status.

@cubic-dev-ai cubic-dev-ai 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.

5 issues found across 18 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="webviews/src/agent-session/guest/redeem.ts">

<violation number="1" location="webviews/src/agent-session/guest/redeem.ts:72">
P3: The added `joinedName` declaration captures the existing `rememberJoined` JSDoc, so `joinedName` is documented as if redeeming succeeded and `rememberJoined` loses its documentation. Move the name getter (and its comment) before the redeem comment, or place the redeem comment directly above `rememberJoined`.</violation>
</file>

<file name="webviews/test/guest-prompts.test.ts">

<violation number="1" location="webviews/test/guest-prompts.test.ts:50">
P2: This retention test checks only the count and final item, so it can pass with old decided messages retained and newer ones dropped. Assert the complete retained sequence to verify that `decided 4` through `decided 19` remain.</violation>
</file>

<file name="webviews/src/agent-session/guest/guest.css">

<violation number="1" location="webviews/src/agent-session/guest/guest.css:27">
P2: The non-shrinking dock can exceed the viewport on short phone or keyboard-resized views, leaving the composer or Send button below the clipped page. Let the dock/message list shrink or provide an internal scroll path so the composer remains reachable.</violation>
</file>

<file name="webviews/src/agent-session/guest/GuestComposer.tsx">

<violation number="1" location="webviews/src/agent-session/guest/GuestComposer.tsx:38">
P2: The decided rows render above waiting rows, putting older status summaries before actionable pending prompts. Render `open` before `decided` to match the documented guest-message order.</violation>
</file>

<file name="webviews/src/agent-session/guest/GuestPage.tsx">

<violation number="1" location="webviews/src/agent-session/guest/GuestPage.tsx:222">
P3: Guests with an existing session that has no stored name show their opaque guest ID instead of a usable name in the own-message chip. Pass the localized fallback into `participant()` before it can fall back to the ID.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

}
const list = prompts.list();
expect(list[0]!.clientId).toBe(waiting.clientId);
expect(list.length).toBe(17);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: This retention test checks only the count and final item, so it can pass with old decided messages retained and newer ones dropped. Assert the complete retained sequence to verify that decided 4 through decided 19 remain.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/test/guest-prompts.test.ts, line 50:

<comment>This retention test checks only the count and final item, so it can pass with old decided messages retained and newer ones dropped. Assert the complete retained sequence to verify that `decided 4` through `decided 19` remain.</comment>

<file context>
@@ -0,0 +1,57 @@
+  }
+  const list = prompts.list();
+  expect(list[0]!.clientId).toBe(waiting.clientId);
+  expect(list.length).toBe(17);
+  expect(list.at(-1)!.text).toBe("decided 19");
+});
</file context>
Suggested change
expect(list.length).toBe(17);
expect(list.map((each) => each.text)).toEqual([
"waiting",
...Array.from({ length: 16 }, (_, index) => `decided ${index + 4}`),
]);

.guest-live__ask-title{color:var(--agent-muted);font-family:var(--font-mono);overflow-wrap:anywhere}
.guest-live__transcript{flex:1;min-height:0;display:flex;flex-direction:column}
/* The dock under the chat: the guest's own messages, then its composer (GuestComposer.tsx). */
.guest-live__dock{flex:none;display:flex;flex-direction:column;gap:8px;padding:8px var(--guest-inset) 12px;border-top:1px solid var(--agent-border)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The non-shrinking dock can exceed the viewport on short phone or keyboard-resized views, leaving the composer or Send button below the clipped page. Let the dock/message list shrink or provide an internal scroll path so the composer remains reachable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/guest/guest.css, line 27:

<comment>The non-shrinking dock can exceed the viewport on short phone or keyboard-resized views, leaving the composer or Send button below the clipped page. Let the dock/message list shrink or provide an internal scroll path so the composer remains reachable.</comment>

<file context>
@@ -22,3 +23,14 @@
 .guest-live__ask-title{color:var(--agent-muted);font-family:var(--font-mono);overflow-wrap:anywhere}
 .guest-live__transcript{flex:1;min-height:0;display:flex;flex-direction:column}
+/* The dock under the chat: the guest's own messages, then its composer (GuestComposer.tsx). */
+.guest-live__dock{flex:none;display:flex;flex-direction:column;gap:8px;padding:8px var(--guest-inset) 12px;border-top:1px solid var(--agent-border)}
+[data-borders="none"] .guest-live__dock{border-top:0}
+.guest-mine{display:flex;flex-direction:column;gap:8px;max-height:40vh;overflow-y:auto}
</file context>

Comment on lines +38 to +58
{decided.map((prompt) => (
<p key={prompt.clientId} className="guest-mine__decided" data-state={prompt.state}>
{t(
prompt.reason === "share.too_many_held"
? "guest.prompt.tooManyHeld"
: DECIDED_TEXT[prompt.state as "approved"],
{
text: firstLine(prompt.text),
},
)}
</p>
))}
{open.map((prompt) => (
<div key={prompt.clientId} className="cv-user guest-mine__held" data-state={prompt.state}>
<AuthorChip author={me} />
<div className="ui-glass cv-user__bubble selectable">{prompt.text}</div>
<span className="guest-mine__label">
{prompt.state === "sending" ? t("guest.prompt.sending") : t("guest.prompt.waiting", { owner })}
</span>
</div>
))}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The decided rows render above waiting rows, putting older status summaries before actionable pending prompts. Render open before decided to match the documented guest-message order.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/guest/GuestComposer.tsx, line 38:

<comment>The decided rows render above waiting rows, putting older status summaries before actionable pending prompts. Render `open` before `decided` to match the documented guest-message order.</comment>

<file context>
@@ -0,0 +1,117 @@
+  if (!open.length && !decided.length) return null;
+  return (
+    <section className="guest-mine" aria-live="polite">
+      {decided.map((prompt) => (
+        <p key={prompt.clientId} className="guest-mine__decided" data-state={prompt.state}>
+          {t(
</file context>
Suggested change
{decided.map((prompt) => (
<p key={prompt.clientId} className="guest-mine__decided" data-state={prompt.state}>
{t(
prompt.reason === "share.too_many_held"
? "guest.prompt.tooManyHeld"
: DECIDED_TEXT[prompt.state as "approved"],
{
text: firstLine(prompt.text),
},
)}
</p>
))}
{open.map((prompt) => (
<div key={prompt.clientId} className="cv-user guest-mine__held" data-state={prompt.state}>
<AuthorChip author={me} />
<div className="ui-glass cv-user__bubble selectable">{prompt.text}</div>
<span className="guest-mine__label">
{prompt.state === "sending" ? t("guest.prompt.sending") : t("guest.prompt.waiting", { owner })}
</span>
</div>
))}
{open.map((prompt) => (
<div key={prompt.clientId} className="cv-user guest-mine__held" data-state={prompt.state}>
<AuthorChip author={me} />
<div className="ui-glass cv-user__bubble selectable">{prompt.text}</div>
<span className="guest-mine__label">
{prompt.state === "sending" ? t("guest.prompt.sending") : t("guest.prompt.waiting", { owner })}
</span>
</div>
))}
{decided.map((prompt) => (
<p key={prompt.clientId} className="guest-mine__decided" data-state={prompt.state}>
{t(
prompt.reason === "share.too_many_held"
? "guest.prompt.tooManyHeld"
: DECIDED_TEXT[prompt.state as "approved"],
{
text: firstLine(prompt.text),
},
)}
</p>
))}


/** The redeem worked: the secret and the attempt are spent, and the tab remembers it joined. */
export function rememberJoined(shareId: string, guestId: string, storage: Storage): void {
/** The name this tab joined the share with. */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The added joinedName declaration captures the existing rememberJoined JSDoc, so joinedName is documented as if redeeming succeeded and rememberJoined loses its documentation. Move the name getter (and its comment) before the redeem comment, or place the redeem comment directly above rememberJoined.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/guest/redeem.ts, line 72:

<comment>The added `joinedName` declaration captures the existing `rememberJoined` JSDoc, so `joinedName` is documented as if redeeming succeeded and `rememberJoined` loses its documentation. Move the name getter (and its comment) before the redeem comment, or place the redeem comment directly above `rememberJoined`.</comment>

<file context>
@@ -69,10 +69,14 @@ export function attemptId(
 
 /** The redeem worked: the secret and the attempt are spent, and the tab remembers it joined. */
-export function rememberJoined(shareId: string, guestId: string, storage: Storage): void {
+/** The name this tab joined the share with. */
+export const joinedName = (shareId: string, storage: Storage) => storage.getItem(key(shareId, "name")) ?? undefined;
+
</file context>


const owner = ownerOf(people);
const ownerName = owner?.name ?? t("guest.live.owner");
const me = participant(guestId, people.find((person) => isMe(person.id, guestId))?.name ?? name) ?? {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Guests with an existing session that has no stored name show their opaque guest ID instead of a usable name in the own-message chip. Pass the localized fallback into participant() before it can fall back to the ID.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/guest/GuestPage.tsx, line 222:

<comment>Guests with an existing session that has no stored name show their opaque guest ID instead of a usable name in the own-message chip. Pass the localized fallback into `participant()` before it can fall back to the ID.</comment>

<file context>
@@ -203,6 +219,16 @@ export function LiveChat({
 
   const owner = ownerOf(people);
   const ownerName = owner?.name ?? t("guest.live.owner");
+  const me = participant(guestId, people.find((person) => isMe(person.id, guestId))?.name ?? name) ?? {
+    id: guestId,
+    name: t("guest.you"),
</file context>
Suggested change
const me = participant(guestId, people.find((person) => isMe(person.id, guestId))?.name ?? name) ?? {
const me = participant(guestId, people.find((person) => isMe(person.id, guestId))?.name ?? name ?? t("guest.you")) ?? {

@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Found 18 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpqkz6npj8/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpw2jowlom/summary-missing.json (live):/summary-missing.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
nightly must build and hand off the macOS 26 helper and Xcode 26.5 app before publishin
g/
nightly must build and hand off the macOS 26 helper and Xcode 26.5 app before publishin
g
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs

...and 8 more test failures. View all on Blacksmith: run 41287673764, run 41287673623

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 2f3724b: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr30518 -f ref=lane/mp-guest-composer-carry -f platform=macos -f backend_mode=local

Gallery before/after for 2f3724b: 16 states rendered, 12 images differ, 1095 more touched states not rendered. Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41287673579 -R manaflow-ai/cmux -n gallery-advisory-30518-2f3724b3bb3ff9701b74fb5b744480c6597a25a6 (then read gallery-review.json)

States
State Theme Status Diff Picked by
guest-page.ended/expired Apple System Colors Light unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/expired Apple System Colors unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/revoked Apple System Colors Light unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/revoked Apple System Colors unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/removed Apple System Colors Light unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/removed Apple System Colors unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/used Apple System Colors Light unchanged 0% own GuestEnded.gallery.tsx
guest-page.ended/used Apple System Colors unchanged 0% own GuestEnded.gallery.tsx
guest-page.join/empty Apple System Colors Light unchanged 0% own GuestJoin.gallery.tsx
guest-page.join/empty Apple System Colors unchanged 0% own GuestJoin.gallery.tsx
guest-page.join/offline Apple System Colors Light changed 0% own GuestJoin.gallery.tsx
guest-page.join/offline Apple System Colors changed 0% own GuestJoin.gallery.tsx
guest-page.join/bad-link Apple System Colors Light unchanged 0% own GuestJoin.gallery.tsx
guest-page.join/bad-link Apple System Colors unchanged 0% own GuestJoin.gallery.tsx
guest-page.live/working Apple System Colors Light changed 1.47% own GuestLive.gallery.tsx
guest-page.live/working Apple System Colors changed 1.45% own GuestLive.gallery.tsx
guest-page.live/asking Apple System Colors Light changed 2.03% own GuestLive.gallery.tsx
guest-page.live/asking Apple System Colors changed 2% own GuestLive.gallery.tsx
guest-page.live/connecting Apple System Colors Light changed 1.07% own GuestLive.gallery.tsx
guest-page.live/connecting Apple System Colors changed 1.06% own GuestLive.gallery.tsx
guest-page.waiting/held Apple System Colors Light new 0% own GuestComposer.tsx
guest-page.waiting/held Apple System Colors new 0% own GuestComposer.tsx
guest-page.waiting/decided Apple System Colors Light new 0% own GuestComposer.tsx
guest-page.waiting/decided Apple System Colors new 0% own GuestComposer.tsx
agent-pane.url-chip/globe Apple System Colors Light unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/globe Apple System Colors unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/cached-favicon Apple System Colors Light unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/cached-favicon Apple System Colors unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/token-url Apple System Colors Light unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/token-url Apple System Colors unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/pull-request-polished Apple System Colors Light unchanged 0% names Localizable.xcstrings
agent-pane.url-chip/pull-request-polished Apple System Colors unchanged 0% names Localizable.xcstrings

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base bcaf263; does not block

Shipped in:

Copy link
Copy Markdown
Collaborator Author

SW-12 integration warning for this guest-composer PR (exact head 2f3724b3bb3ff9701b74fb5b744480c6597a25a6): P1 source review on platform#147 identified cross-tab guest identity confusion on multi-use links. The room sets one cmux_share_guest cookie per share/path; a second tab in the same browser profile redeems as guest B and overwrites guest A's cookie, while A's GuestPage/prompt storage keeps guestId A. After A reconnects, the room authenticates B from that cookie and A's new prompts are stamped as B. This PR adds the composer that makes the attribution error visible. Please coordinate an identity-bound handshake plus per-guest cookie isolation before the two-guest E2E, and test A/B in one browser context with two tabs, distinct sessionStorage, reconnect and separate prompt attribution. Also see host reconnect lost join/leave event. Source review only; no edits to this active branch.

@teamleaderleo
teamleaderleo merged commit f7d2d7a into feat-cmux-next Nov 1, 2026
189 of 209 checks passed
@teamleaderleo
teamleaderleo deleted the lane/mp-guest-composer-carry branch November 1, 2026 10:31
@teamleaderleo teamleaderleo added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Nov 1, 2026

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 2f3724b3 Deployed Nov 1, 2026 by teamleaderleo via wait for same-key tree publisher #94784
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant