Skip to content

Agent pane: a look at a video's frames draws as a filmstrip card - #30940

Merged
teamleaderleo merged 4 commits into
feat-cmux-nextfrom
lane/video-frames-card
Nov 1, 2026
Merged

teamleaderleo merged 4 commits into
feat-cmux-nextfrom
lane/video-frames-card

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

What

When an agent looks at a video's frames through the cmux video_frames agent tool, the transcript now draws a compact video card instead of the raw call:

  • The row says what it did: Looked at 8 video frames.
  • Under it, starting at the row's text column, the video's name and length (and size), then a filmstrip of the frames, each with its time in a corner (0:02, or 0:02.5 when whole seconds would repeat).
  • Click a frame to open it large in the pane's existing image viewer.
  • Click the name to play the video in Quick Look. This is the same viewer an attached video's tile opens (video.quickLook), and the host checks the path the same way. In a read-only (guest) transcript the name is plain text.
  • Opened, the call shows the tool's note (length, size, frame times) without the frames' base64.

Every frame box takes the video's shape before it decodes, so the transcript never shifts. With many frames the strip scrolls sideways at the row's width instead of growing taller.

Leo, 2026-11-01, looking at two screenshots of an agent's look at an attached video (a Shell card with a long ffmpeg command and the full Chat Uploads path printed twice, then Read /tmp/vidframes.../grid.png with a contact sheet): "i feel like cmux-next should give u better tools to deal with this kind of thing ... you can see what we can work on", then "can you help work on all these".

Source shape

The video_frames tool is #30921 (open). videoFrames.ts reads its exact output, and the gallery and a test use that wording. The output is one image/jpeg block per frame and one text block. The text's header line is <path>: 16.40 s, 1920x1080, 30 fps, no audio. 8 frames below, ..., which gives the resolved path, the length and the size. Each frame then has a #N at T s line with its time. Frames may arrive as ACP image blocks (tool.images) or inside an MCP envelope in the output, and are never deduped, so a still screen's identical frames keep their times. Other wordings still parse: key: value notes, numbered lists and JSON. Detection uses the MCP tool name (mcp__<server>__video_frames, or Codex's {server, tool}). If a call's frames can't be found, it draws exactly as before.

It's parsed once per immutable tool snapshot (a WeakMap), never per render or per streamed token. The card adds no timer, observer or animation loop. Frame images use loading="lazy".

Not changed

  • Ordinary Shell cards and every other tool row render exactly as before. Only McpCallRow changes, and only for a video_frames call.
  • The sent user bubble for an attached video: a separate open lane already changes that bubble and the video's prompt (videoPrompt.ts). Its stated design is that the bubble draws the video's own tile and never the frames, so this PR leaves the bubble alone.

Gallery

agent-pane.video-frames (VideoFramesCard.gallery.tsx), built from the real ACP updates through mergeToolItem and drawn by the real McpCallRows:

Variant What
strip (chosen) name and length above a one-row filmstrip
grid the frames as a contact sheet that wraps
poster the first frame large, the rest in a strip under it, the name below
strip-many 16 frames: the strip scrolls sideways
strip-unnamed no file named: length and frames, no name to play

Why strip: it's what was asked for (a filmstrip). It's the most compact, under 90px tall at any frame count, so a look at a video takes about as much room as one image strip and never pushes the turn's reply off screen. It also reads in time order left to right. grid gets tall fast at 8 to 16 frames, and poster repeats the first frame at a size the image viewer already gives on click.

Design spec: design/chat-transcript.md (leo-workspace), tool rows. No settled design is replaced.

Tests

  • videoFrames.test.ts: Claude and Codex call shapes, an MCP envelope with a JSON note, other note wordings and paths with spaces, untimed frames, and non-calls (other tools, running, failed, frameless, a shell ffmpeg).
  • Fleet run (cmux-ci test): the unit tests, gallery coverage, typecheck, design tokens, catalog keys, fmt and lint on the changed files.
  • Two new strings in every shipped language: tools.videoFrames (a plural) and media.videoFrameAt. The play button reuses composer.playVideo.

Follow-ups

  • Two video_frames calls in a row group under the generic MCP group line, and their cards show only once the group is opened. A call made inside a cmux_exec script gets no card.
  • The name shows as playable even for a path the host refuses (e.g. /tmp). The refusal is silent.
  • Let the image viewer step through a card's frames with the arrow keys (today it opens one frame).

🤖 Generated with Claude Code

Agent session: agent session

teamleaderleo and others added 2 commits November 1, 2026 05:03
The row names what the agent looked at ("Looked at 8 frames of clip.mp4"); under it, the
video's name (plays it in Quick Look) and length, then its frames, each with its time; a frame
opens in the image viewer. Opened, the call shows the tool's note without the frames' base64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-bbe6e8ca1bc11f92f25b
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026

@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 7 files

You’re at about 95% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

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/acpmux/conversation/conversation.css">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/conversation.css:2484">
P2: The focus ring on a frame button in the strip sits outside the box, and the strip's `overflow-x: auto` clips it at the top and bottom edges. Draw the outline inside the frame instead.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/VideoFramesCard.tsx">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/VideoFramesCard.tsx:81">
P2: When the note has no duration, this button's `aria-label` falls back to "Play video" and drops the visible file name. Screen-reader users lose which video it plays. Use the name in the fallback too.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/videoFrames.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/videoFrames.ts:171">
P2: `readFacts` drops bare numeric seconds because `TIME` requires a unit for decimal values. Include an optional seconds unit so notes such as `Duration: 16.4` still show the duration and frame timestamps.</violation>

<violation number="2" location="webviews/src/agent-session/acpmux/conversation/videoFrames.ts:178">
P2: `numberAt` parses numeric strings as seconds even when callers use it for millisecond fields and pixel dimensions. Parse millisecond and dimension strings as plain numbers, while retaining time parsing only for second-based fields.</violation>

<violation number="3" location="webviews/src/agent-session/acpmux/conversation/videoFrames.ts:230">
P2: A frame line without a time is dropped from `facts.times`, so every later timestamp shifts onto the previous frame. Push `undefined` for a frame line whose time is missing, so the index stays aligned with the image.</violation>
</file>

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

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

Comment on lines +2484 to +2487
button.cv-video-frames__frame:focus-visible {
outline: 2px solid var(--agent-accent-soft);
outline-offset: 2px;
}

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 focus ring on a frame button in the strip sits outside the box, and the strip's overflow-x: auto clips it at the top and bottom edges. Draw the outline inside the frame instead.

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/acpmux/conversation/conversation.css, line 2484:

<comment>The focus ring on a frame button in the strip sits outside the box, and the strip's `overflow-x: auto` clips it at the top and bottom edges. Draw the outline inside the frame instead.</comment>

<file context>
@@ -2378,6 +2378,136 @@ pre.cv-math-source {
+  appearance: none;
+  cursor: zoom-in;
+}
+button.cv-video-frames__frame:focus-visible {
+  outline: 2px solid var(--agent-accent-soft);
+  outline-offset: 2px;
</file context>
Suggested change
button.cv-video-frames__frame:focus-visible {
outline: 2px solid var(--agent-accent-soft);
outline-offset: 2px;
}
button.cv-video-frames__frame:focus-visible {
outline: 2px solid var(--agent-accent-soft);
outline-offset: -2px;
}

type="button"
className="cv-video-frames__name is-playable"
title={video.path}
aria-label={length ? t("composer.playVideo", { name, length }) : t("media.play")}

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: When the note has no duration, this button's aria-label falls back to "Play video" and drops the visible file name. Screen-reader users lose which video it plays. Use the name in the fallback too.

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/acpmux/conversation/VideoFramesCard.tsx, line 81:

<comment>When the note has no duration, this button's `aria-label` falls back to "Play video" and drops the visible file name. Screen-reader users lose which video it plays. Use the name in the fallback too.</comment>

<file context>
@@ -0,0 +1,127 @@
+          type="button"
+          className="cv-video-frames__name is-playable"
+          title={video.path}
+          aria-label={length ? t("composer.playVideo", { name, length }) : t("media.play")}
+          onClick={() => void callChipHost("video.quickLook", { src: video.path! })}
+        >
</file context>
Suggested change
aria-label={length ? t("composer.playVideo", { name, length }) : t("media.play")}
aria-label={length ? t("composer.playVideo", { name, length }) : name}

const rest = frame?.[1] ?? (bullet ? bullet[1] : undefined);
if (rest !== undefined && !/\b(duration|length)\b/.test(lower)) {
const time = TIME.exec(rest);
if (time) facts.times.push(parseTime(time[1]!));

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: A frame line without a time is dropped from facts.times, so every later timestamp shifts onto the previous frame. Push undefined for a frame line whose time is missing, so the index stays aligned with the image.

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/acpmux/conversation/videoFrames.ts, line 230:

<comment>A frame line without a time is dropped from `facts.times`, so every later timestamp shifts onto the previous frame. Push `undefined` for a frame line whose time is missing, so the index stays aligned with the image.</comment>

<file context>
@@ -0,0 +1,295 @@
+    const rest = frame?.[1] ?? (bullet ? bullet[1] : undefined);
+    if (rest !== undefined && !/\b(duration|length)\b/.test(lower)) {
+      const time = TIME.exec(rest);
+      if (time) facts.times.push(parseTime(time[1]!));
+    }
+  }
</file context>
Suggested change
if (time) facts.times.push(parseTime(time[1]!));
if (time || frame) facts.times.push(time ? parseTime(time[1]!) : undefined);

const value = record[key];
if (typeof value === "number" && Number.isFinite(value) && value >= 0) return value;
if (typeof value === "string") {
const time = parseTime(value);

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: numberAt parses numeric strings as seconds even when callers use it for millisecond fields and pixel dimensions. Parse millisecond and dimension strings as plain numbers, while retaining time parsing only for second-based fields.

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/acpmux/conversation/videoFrames.ts, line 178:

<comment>`numberAt` parses numeric strings as seconds even when callers use it for millisecond fields and pixel dimensions. Parse millisecond and dimension strings as plain numbers, while retaining time parsing only for second-based fields.</comment>

<file context>
@@ -0,0 +1,295 @@
+    const value = record[key];
+    if (typeof value === "number" && Number.isFinite(value) && value >= 0) return value;
+    if (typeof value === "string") {
+      const time = parseTime(value);
+      if (time !== undefined) return time;
+    }
</file context>

return Math.round(unit[2] === "ms" ? value : value * 1000);
}

const TIME = /(\d+:\d{1,2}(?::\d{1,2})?(?:\.\d+)?|\d+(?:\.\d+)?\s*(?:ms|s|sec|secs|seconds?)\b)/i;

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: readFacts drops bare numeric seconds because TIME requires a unit for decimal values. Include an optional seconds unit so notes such as Duration: 16.4 still show the duration and frame timestamps.

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/acpmux/conversation/videoFrames.ts, line 171:

<comment>`readFacts` drops bare numeric seconds because `TIME` requires a unit for decimal values. Include an optional seconds unit so notes such as `Duration: 16.4` still show the duration and frame timestamps.</comment>

<file context>
@@ -0,0 +1,295 @@
+  return Math.round(unit[2] === "ms" ? value : value * 1000);
+}
+
+const TIME = /(\d+:\d{1,2}(?::\d{1,2})?(?:\.\d+)?|\d+(?:\.\d+)?\s*(?:ms|s|sec|secs|seconds?)\b)/i;
+
+function numberAt(record: Record<string, unknown>, keys: string[]): number | undefined {
</file context>
Suggested change
const TIME = /(\d+:\d{1,2}(?::\d{1,2})?(?:\.\d+)?|\d+(?:\.\d+)?\s*(?:ms|s|sec|secs|seconds?)\b)/i;
const TIME = /(\d+:\d{1,2}(?::\d{1,2})?(?:\.\d+)?|\d+(?:\.\d+)?\s*(?:ms|s|sec|secs|seconds?)?\b)/i;

@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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 e115316: 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=pr30940 -f ref=lane/video-frames-card -f platform=macos -f backend_mode=local

Gallery before/after for e115316: 16 states rendered, 0 images differ, 1760 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 41316091363 -R manaflow-ai/cmux -n gallery-advisory-30940-e115316ff89c5dabd976dc828f6660417ae7c148 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.access-offer/turn-no-credits Apple System Colors Light unchanged 0% own conversation.css
agent-pane.access-offer/turn-no-credits Apple System Colors unchanged 0% own conversation.css
agent-pane.access-offer/turn-low-credits Apple System Colors Light unchanged 0% own conversation.css
agent-pane.access-offer/turn-low-credits Apple System Colors unchanged 0% own conversation.css
agent-pane.access-offer/turn-no-offer Apple System Colors Light unchanged 0% own conversation.css
agent-pane.access-offer/turn-no-offer Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/single Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/single Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/grouped Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/grouped Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/single-multiedit Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/single-multiedit Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/grouped-multiedit Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/grouped-multiedit Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/single-long Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/single-long Apple System Colors unchanged 0% own conversation.css
agent-pane.approval-edits/grouped-long Apple System Colors Light unchanged 0% own conversation.css
agent-pane.approval-edits/grouped-long Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/duration-columns Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/duration-columns Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/pinned-live-tail-light Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/pinned-live-tail-light Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/pinned-live-tail-dark Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/pinned-live-tail-dark Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/after-latest-message-light Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/after-latest-message-light Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/after-latest-message-dark Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/after-latest-message-dark Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/compact-pill-light Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/compact-pill-light Apple System Colors unchanged 0% own conversation.css
agent-pane.background-activity/compact-pill-dark Apple System Colors Light unchanged 0% own conversation.css
agent-pane.background-activity/compact-pill-dark Apple System Colors unchanged 0% own conversation.css

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); NEW: red check: Script tests (pin-cmux-tui, embed-cef, ensure-cef store) (+2 more) is not red on the base 7491e0f; do not merge until green; see lane-rules

Shipped in:

…w's words

The row reads "Looked at 8 video frames" and the card under it names the video (plays it), so
the name no longer shows twice. The card starts at the row's text column like any line under a
row; frames carry no list roles on buttons; covers name the layout context; formatter pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-bbe6e8ca1bc11f92f25b
The tool's header line (<path>: 16.40 s, 1920x1080, 30 fps, ...) gives the resolved path,
length and size, and its #N at T s lines each frame's time. Frames are never deduped (a still
screen's identical frames keep their times), the label counts every frame the call returned, a
size inside a file name and a line that starts with a decimal are not read as facts, and the
frame buttons take an aria-label instead of a tooltip (review on 246656c).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-bbe6e8ca1bc11f92f25b
@cursor

cursor Bot commented Nov 1, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@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.

1 issue found across 5 files (changes from recent commits).

You’re at about 99% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

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/acpmux/conversation/videoFrames.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/videoFrames.ts:238">
P3: The narrowed size lookbehind drops `WxH` written right after `:`, `=`, `-` or `/` (for example `size:1920x1080`), which the old `\b` matched. Those notes lose width and height, and the card falls back to a 16:9 box. File names are already excluded by the `VIDEO_NAME` replacement, so the stricter prefix is unnecessary. Use a lookbehind that rejects only word characters and dots.</violation>
</file>

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

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

}
if (facts.width === undefined) {
// Not in a path or a file name (`clip_1280x720.mp4`).
const size = /(?:^|[\s,(·])(\d{2,5})\s*[x×]\s*(\d{2,5})\b/.exec(line.replace(VIDEO_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: The narrowed size lookbehind drops WxH written right after :, =, - or / (for example size:1920x1080), which the old \b matched. Those notes lose width and height, and the card falls back to a 16:9 box. File names are already excluded by the VIDEO_NAME replacement, so the stricter prefix is unnecessary. Use a lookbehind that rejects only word characters and dots.

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/acpmux/conversation/videoFrames.ts, line 238:

<comment>The narrowed size lookbehind drops `WxH` written right after `:`, `=`, `-` or `/` (for example `size:1920x1080`), which the old `\b` matched. Those notes lose width and height, and the card falls back to a 16:9 box. File names are already excluded by the `VIDEO_NAME` replacement, so the stricter prefix is unnecessary. Use a lookbehind that rejects only word characters and dots.</comment>

<file context>
@@ -215,16 +234,16 @@ function readFacts(text: string): Facts {
     if (facts.width === undefined) {
-      const size = /\b(\d{2,5})\s*[x×]\s*(\d{2,5})\b/.exec(line);
+      // Not in a path or a file name (`clip_1280x720.mp4`).
+      const size = /(?:^|[\s,(·])(\d{2,5})\s*[x×]\s*(\d{2,5})\b/.exec(line.replace(VIDEO_NAME, " "));
       if (size) {
         facts.width = Number(size[1]);
</file context>
Suggested change
const size = /(?:^|[\s,(·])(\d{2,5})\s*[x×]\s*(\d{2,5})\b/.exec(line.replace(VIDEO_NAME, " "));
const size = /(?<![\w.])(\d{2,5})\s*[x×]\s*(\d{2,5})\b/.exec(line.replace(VIDEO_NAME, " "));

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent claude-opus-5-5 medium): SHIP at e115316

An earlier BLOCK at 246656c (tooltip rule on the new card) is fixed at this head.

Follow-ups:

  • Two video_frames calls in a row group under the generic MCP group line; their cards show only once the group is opened. A call made through cmux_exec gets no card.
  • When the host refuses the video's path, clicking the name does nothing visible.
  • The header parse would cut short a path like a.mov: x/b.mp4 (edge case).

@teamleaderleo
teamleaderleo merged commit ab8c3a2 into feat-cmux-next Nov 1, 2026
182 of 190 checks passed
@teamleaderleo
teamleaderleo deleted the lane/video-frames-card branch November 1, 2026 14:59
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent Codex gpt-6.1-sol, high, via the review router; full diff from merge base 7745465 to this head): SHIP at e115316.

No P1/P2 findings.

This branch was previously deployed

1 inactive deployment
ci-routing-agent — e115316f Deployed Nov 1, 2026 by teamleaderleo via cmux-tui tree preflight #96534
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant