PR 338 review

rancher/rancher-ai-ui PR 338 (torchiaf), additional info on the planning tasks, at 8ff42d5, reviewed 2026-11-05. Focus: functional behaviour and component usage.

Preview: rancheraipr338r.mf-created-dashboard.ui.rancher.space, built from 8ff42d5, backend mf-rancher-16. PR + suggestion: built from local-only 8a8a93a, never pushed.

Verdict: it works, change the toggle before approving

Needs someone: the agent image behind e2e is missing

The red e2e here isn't from this PR, and Cypress never started. CI installs the chart from agent main, which moved to v1.2.0-alpha.6 an hour before this run. That image's publish job failed on a 504 while installing cosign, and the registry returns 404 for it (alpha.5 returns 200). That fits the log: the agent deployment never became available and the install timed out. Any rancher-ai-ui PR should fail the same way until the image exists.

The fix is to re-run that job in rancher-ai-agent, then re-run the e2e here. I didn't touch either. The new spec hasn't run on CI yet. I ran the same steps with Playwright, on the real agent and on stubbed frames, and they hold, but that isn't Cypress itself.

Test it yourself

mf-rancher-16's agent is back on alpha.5, which drops additional_info, so "Show more" won't appear by itself. This snippet adds the field to incoming plan frames and queues a plan in llm-mock. It proves the UI only. I tested it on the PR preview.

  1. Open a preview from the top bar, log in, and open Liz.
  2. Paste this in the DevTools console. It should print seven 204s.
  3. Send any message to Liz. Re-run the snippet for each new plan.
Snippet
(async () => {
  const INFO = [
    "Deployment named 'web' in the local cluster, using the 'nginx:1.27' image, with 3 replicas, exposing container port 80.",
    '',
    'Use the image registry.suse.com/rancher/web@sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 and keep it pinned.\nReplicas: 3\nPort: 80',
  ];
  const data = Object.getOwnPropertyDescriptor(MessageEvent.prototype, 'data');

  Object.defineProperty(MessageEvent.prototype, 'data', {
    configurable: true,
    get() {
      const value = data.get.call(this);

      if (typeof value !== 'string' || !value.startsWith('<plan>')) {
        return value;
      }
      const plan = JSON.parse(value.slice(6, -7));

      plan.tasks.forEach((task, i) => {
        task.additionalInfo = INFO[i] || '';
      });

      return `<plan>${ JSON.stringify(plan) }</plan>`;
    },
  });

  const csrf = decodeURIComponent((document.cookie.match(/(?:^|;\s*)CSRF=([^;]+)/) || [])[1] || '');
  const push = (text) => fetch('/api/v1/namespaces/cattle-ai-agent-system/services/http:llm-mock:80/proxy/v1/control/push', {
    method:  'POST',
    headers: { 'content-type': 'application/json', 'x-api-csrf': csrf },
    body:    JSON.stringify({ agentResponses: [], text: { chunks: [text] }, uiTools: [] }),
  }).then((r) => r.status);
  const subtasks = [
    { task: "Deploy nginx in the 'test2' namespace.", agent: 'rancher', status: 'pending' },
    { task: 'Create a service for it.', agent: 'rancher', status: 'pending' },
    { task: 'Pull the private image.', agent: 'rancher', status: 'pending' },
  ];
  const codes = [await push(JSON.stringify({ subtasks }))];

  for (const s of subtasks) {
    codes.push(await push(`Finished: ${ s.task }`), await push('yes'));
  }
  console.log('llm-mock', codes.join(' '), '(all 204 = ready). Now send any message to Liz.');
})();
Findings
1

Long values are cut off and line breaks are lost

StatusInfo.vue:242 (span) and :421 (.label rule)
Should fix

.label has word-break: break-word and white-space: pre-line. The new .additional-info has neither. The planner is told to put image names and parameters in this field, so a digest is a realistic value.

PR: the digest is cut at the right edge, and the three lines are flattened.
PR: the digest is cut at the right edge, and the three lines are flattened.
With the fix: the digest wraps and the lines are kept.
With the fix: the digest wraps and the lines are kept.

Fix

Add .additional-info next to .label in the existing rule. Tested: overflow gone (402 of 402px), line breaks kept.

2

Two buttons for one toggle, so focus is lost on every click

StatusInfo.vue:230-239 and :249-257
Should fix

"Show more" and "Show less" are separate RcButtons, and each one removes itself when clicked.

Fix

One RcButton after the text, with the info span above it under its own v-if. The layout is the same as the PR's, and the two div wrappers with the same condition go away. Tested: focus stays on the button in both directions, and the PR's e2e selectors still match.

3

RcButton already has a link style

StatusInfo.vue:233-234, :238, :459-484
Suggestion

The toggle uses variant="ghost", an inner <a> with no href, and 26 lines of CSS that undo the button and rebuild a link. variant="link" does this already, and it's what oboc-sts asked for and torchiaf applied to Cancel in PR 330 (still open). All that's left is one line, --rc-button-padding: 0, the variable the shell provides for this.

small is also deprecated in the pinned shell (3.0.14). It logs a console warning per button, 10 of the 20 in my scenario come from these two. Line 182 of the same file already uses size="small". Only the two new buttons are in scope here.

PR: black, underlined, 14px.
PR: black, underlined, 14px.
Suggestion: link blue, 12px. It fits on the summary line more often.
Suggestion: link blue, 12px. It fits on the summary line more often.

What it changes

This one changes the look, so it's a design call. The text goes blue and 12px, a row with a toggle is 3px taller (24px minimum height), and hover gets the shell's tint with dark text (--lightest is undefined, same as PR 330). If black and underlined was asked for, keep card 2 and drop this one. Switching only small to size="small" isn't a drop-in then: reading the selectors, .btn-small outranks the overrides on font size, height and padding.

Suggestion, hover in light theme.
Suggestion, hover in light theme.
Suggestion in dark theme.
Suggestion in dark theme.
4

Is the rename to summary needed?

format.ts:266-274, types.ts:237
Question

The agent still sends task. Agent PR 479's description shows a summary field, but what merged keeps task as the short text and adds additional_info. So the UI's rename looks left over from the earlier shape.

Keeping task would drop this formatPlanning hunk and most of the test and spec churn in the diff. Today the object carries both task and summary, and the type only declares summary. Nothing is broken, it's only about a smaller diff, and summary does read better than task.task.

5

No unit test for the toggle

StatusInfo.test.ts
Optional

The test changes are renames, and additionalInfo only appears as undefined. The toggle, the empty-string case and the reset on plan collapse are covered only by the new e2e, which hasn't run yet (see above).

For you, not in the suggested text
A

After a feedback re-plan, the open state sticks to the index

StatusInfo.vue:44, seen with the real agent
FYI

A re-plan reuses the same panel, so if task 0 was open, the new task 0 opens too. The text shown is correct, it's only open without being asked. Harmless, so I left it out of the suggested text. If it bothers you, keying the state by summary fixes it.

Real agent: after "Use 5 replicas instead", the new first task is already open.
Real agent: after "Use 5 replicas instead", the new first task is already open.
B

Small visual leftovers on finished plans

StatusInfo.vue:524-537
FYI

On a cancelled plan the toggle stays at full strength while the rest dims. On a failed task the summary is red and the details aren't. These only look a little odd, so they aren't in the suggested text.

C

The 40vh change makes sense, but it isn't in the description

StatusInfo.vue:400
FYI

At 1000x660 with tasks open and the plan running, the sticky panel is 351px of a 363px message area, so the answer streams behind it until you close something. At the old 50vh it would be taller than the area. I'd keep it.

1000x660, plan running, two tasks open. The list scrolls inside the panel.
1000x660, plan running, two tasks open. The list scrolls inside the panel.
D

Reopened chats have no plan panel

not changed by this PR
FYI

Reopening a chat from history shows the user message and the final answer only, so the details aren't there either. The PR doesn't touch that path, and its history specs expect exactly this.

E

The shell already has these strings

en-us.yaml:275-277
FYI

generic.showMore and generic.showLess exist in the shell, including on 2.13, the oldest Rancher this extension supports, and the extension already uses other generic.* keys. Reusing them would drop the three new lines. Too small to raise on its own.

What was checked
Real agent (head image with agent PR 479) and llm-mock
Plan frames carry task, additionalInfo, agent, statusYes, the mapping is right
Toggle only on the task with details; "" gets noneOK
Approval: open a task, re-plan, Start, run to the endOK, stays open, same panel, across the agent's new per-subtask messages
Feedback re-planWorks, see FYI A
Reopen from historyNo plan panel, not from this PR (FYI D)
Real build, stubbed frames in the agent's exact shape
Enter and Space toggleOK
Focus after togglingLost to BODY (card 2)
Long token, line breaksCut off, flattened (card 1)
Scrolled up to the plan, then toggleNo jump, scrollTop 400 → 400 → 400
At the bottom while running, then toggleStays pinned, gap 0
Open tasks survive progress framesOK
Collapsing the plan resets open tasksOK
Dark theme, focus ringOK
Console errorsNone
Code and CI
Other readers of .task after the type changeNone left in the package
Agent text rendered safelyYes, {{ }} and no v-clean-html
Unit (85 in the affected suites, locally), lint, i18n, build-pkgPass
e2eRed, Cypress never started, not this PR
Not checked
Screen reader, Firefox, SafariNot run
Real LLM output (all text came from llm-mock)Not run
Together with PR 330's shell bump (3.0.15-rc.4)Not run
What I changed on mf-rancher-16

For the real-agent run I pointed the agent at the head digest and turned approval on for a few minutes, because alpha.6 doesn't exist. It's restored: image v1.2.0-alpha.5, approval off, Deployment template and llm-config identical to my backups, helm still at revision 7, mock queue empty.

Side effect: the agent keeps chats in memory on this server (DB_ENABLED=false), so my restarts cleared the Liz chat history for every user there, including the old PR 336 probe chats. I didn't list it beforehand, so I can't say what else was in it. I removed the one chat I made after that, so the admin list is now empty. Previews pr338 and pr338fix are still up.

Suggested review

Review body

I tested this on a build of the PR against the agent's head image (with rancher-ai-agent PR 479) and llm-mock: plans with and without approval, a feedback re-plan, collapse and scrolling. It works. A few things on how the toggle is built, inline.

The e2e failure isn't from this PR. rancher-ai-agent:v1.2.0-alpha.6 was never published (the publish job failed on a 504), so the chart install times out and Cypress doesn't start. That also means the new spec hasn't run on CI yet.

StatusInfo.vue:242

.label has word-break: break-word and white-space: pre-line, but .additional-info doesn't get them. A long value like an image digest is cut at the right edge, and line breaks are lost. Adding .additional-info next to .label on line 421 fixes both.

Attach: pr-light-expanded, fix-light-expanded.

StatusInfo.vue:230

These two buttons are one toggle, so I'd use one RcButton that stays in the DOM, after the text. The layout stays the same. Each button removes itself on click, so focus drops to the body after every toggle. It also removes the ternary on line 238, which can't show "Show less" because of the v-if on line 231. With one button we can add aria-expanded, and the aria-labels can go since the text is already the name.

StatusInfo.vue:459

RcButton already has a link style, so variant="link" with size="small" could replace the ghost variant, the inner <a> and this block, leaving only --rc-button-padding: 0. It's the same change as Cancel in PR 330. small is deprecated and logs a warning per button. This does change the look, to blue and 12px, so if black and underlined came from design, ignore this one.

Attach: pr-light-collapsed, fix-light-collapsed.

format.ts:266

The agent still sends task, so do we need the rename to summary? Keeping task would drop this hunk and most of the test changes.

StatusInfo.test.ts

Could we add a unit test for the toggle? Right now only the e2e covers it.