FN-7343: Remove task chat steering guidance copy
Remove the visible steering/refinement guidance shell from task Activity chat while preserving composer behavior. - Drop the TaskChatTab composer label/hint affordance and stale aria-describedby wiring. - Keep accessible form names and existing steering/refinement send flows intact. - Update dashboard docs, regression tests, and the published package changeset for the copy removal. Files changed: .changeset/fn-7343-task-chat-copy.md | 7 ++++ docs/dashboard-guide.md | 2 +- packages/dashboard/app/components/TaskChatTab.css | 29 --------------- packages/dashboard/app/components/TaskChatTab.tsx | 24 +++++-------- .../app/components/__tests__/TaskChatTab.test.tsx | 41 +++++++++++++--------- .../TaskDetailModal.task-activity-chat.test.tsx | 13 ++++--- .../components/__tests__/TaskDetailModal.test.tsx | 15 ++++---- 7 files changed, 59 insertions(+), 72 deletions(-) Fusion-Task-Id: FN-7343 Fusion-Task-Lineage: ebcffb2c-a42e-46af-8291-1ff77bcec2c6 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7343-task-chat-copy.md
Normal file
7
.changeset/fn-7343-task-chat-copy.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Remove the extra steering guidance copy from task Activity chat.
|
||||
category: fix
|
||||
dev: Keeps the Activity composer APIs intact while removing the visible TaskChatTab label/hint shell.
|
||||
@@ -1120,7 +1120,7 @@ Recommended workflow: ordinary chains stay as `Blocks N` so noise stays low, hig
|
||||
|
||||
<!-- FNXC:TaskDetailActivity 2026-06-30-23:55: Activity Live is the explicit operational steering-comment entry surface, preserving the legacy internal `current` segment id. Feed and Raw Logs remain read-only Activity segments, the Activity-wide expand control is available on every segment, and the top-level Chat tab is intentionally separate planner-model conversation rather than steering. -->
|
||||
<!-- FNXC:TaskDetailActivityFirst 2026-06-30-23:59: Task Detail is Activity-first by default for active tasks: Activity renders before planner Chat and omitted non-done opens land on Activity → Live. Settings → Appearance → Open task details with Chat first restores the previous Chat-first order/default without changing explicit Activity, Chat, or Logs links. -->
|
||||
The **Activity** tab is the first task-detail tab by default and presents a segmented control for **Live**, **Feed**, and **Raw Logs**. Live contains the live, chat-styled transcript of task agent output. Consecutive entries are grouped by role and labeled as Planner, Executor, Reviewer, or Merger; legacy log rows without an agent role use the neutral Agent fallback. Agent group headers and user message headers show a small muted relative timestamp (for example, “just now”, “1m ago”, or “2h ago”) based on the transcript timestamp, while agent group metadata still includes the entry count. Consecutive text/message chunks inside a role group render as one continuous markdown bubble, while consecutive tool/tool-result/tool-error rows collapse into one expandable, compact tool-call summary that stays collapsed by default and mirrors regular Chat's dense treatment; the summary stays single-line/ellipsis-friendly on desktop and mobile, counts tool invocations, lists deduped tool names with overflow, and shows an error count when failures are present, while the expanded body pairs each call with its result or error in dense entry cards. Thinking entries render in a collapsible block that starts expanded. The transcript opens at the latest output whenever the tab loads or becomes active, then follows new live output when you are already near the bottom while preserving your scroll position when you review older messages. When older task-agent history exists, scrolling to the top or selecting **Load previous messages** prepends earlier transcript entries without moving the message you were reading. When you scroll away from the bottom of a populated transcript, a sticky **Latest** button appears inside the transcript so you can jump back to the newest message and resume live follow. For non-`done` tasks, the **Steering comment** composer sends guidance through the same steering path used by comments, including active planning/triage, `in-progress`, and `in-review` sessions, plus live CLI-agent sessions reported by the session bridge; an `in-review` Activity Live message or Comments-tab task comment re-engages an executor unless an open PR blocks moving the task back, and other messages are still saved as queued guidance when no session is currently live. Feed and Raw Logs do not show a steering composer. On a `done` task, the composer switches to **Refinement request** copy; sending starts a refinement task using the typed text as feedback and shows a success toast with the new task ID, while the current task detail modal remains on the completed task. The task-detail Activity Live segment keeps the composer pinned and visible on mobile and desktop while the transcript scrolls internally; its textarea placeholder reads “Steer the currently executing agent” for steering mode and switches to refinement copy for completed tasks, with the same inline, icon-only send affordance to the right of the input at every breakpoint. In the composer, plain **Enter** sends, **Shift+Enter** inserts a newline, and **Cmd/Ctrl+Enter** remains a supported send shortcut.
|
||||
The **Activity** tab is the first task-detail tab by default and presents a segmented control for **Live**, **Feed**, and **Raw Logs**. Live contains the live, chat-styled transcript of task agent output. Consecutive entries are grouped by role and labeled as Planner, Executor, Reviewer, or Merger; legacy log rows without an agent role use the neutral Agent fallback. Agent group headers and user message headers show a small muted relative timestamp (for example, “just now”, “1m ago”, or “2h ago”) based on the transcript timestamp, while agent group metadata still includes the entry count. Consecutive text/message chunks inside a role group render as one continuous markdown bubble, while consecutive tool/tool-result/tool-error rows collapse into one expandable, compact tool-call summary that stays collapsed by default and mirrors regular Chat's dense treatment; the summary stays single-line/ellipsis-friendly on desktop and mobile, counts tool invocations, lists deduped tool names with overflow, and shows an error count when failures are present, while the expanded body pairs each call with its result or error in dense entry cards. Thinking entries render in a collapsible block that starts expanded. The transcript opens at the latest output whenever the tab loads or becomes active, then follows new live output when you are already near the bottom while preserving your scroll position when you review older messages. When older task-agent history exists, scrolling to the top or selecting **Load previous messages** prepends earlier transcript entries without moving the message you were reading. When you scroll away from the bottom of a populated transcript, a sticky **Latest** button appears inside the transcript so you can jump back to the newest message and resume live follow. For non-`done` tasks, the Activity Live composer sends typed guidance through the same steering path used by comments, including active planning/triage, `in-progress`, and `in-review` sessions, plus live CLI-agent sessions reported by the session bridge; an `in-review` Activity Live message or Comments-tab task comment re-engages an executor unless an open PR blocks moving the task back, and other messages are still saved as queued guidance when no session is currently live. Feed and Raw Logs do not show the composer. On a `done` task, the same composer starts a refinement task using the typed text as feedback and shows a success toast with the new task ID, while the current task detail modal remains on the completed task. The task-detail Activity Live segment keeps the composer pinned and visible on mobile and desktop while the transcript scrolls internally; its textarea placeholder reads “Steer the currently executing agent” for steering mode and switches to refinement copy for completed tasks, with the same inline, icon-only send affordance to the right of the input at every breakpoint. In the composer, plain **Enter** sends, **Shift+Enter** inserts a newline, and **Cmd/Ctrl+Enter** remains a supported send shortcut.
|
||||
|
||||
The top-level **Chat** tab opens the planner-model conversation for the same task instead of posting steering comments. It appears after Activity by default, or before Activity when **Settings → Appearance → Open task details with Chat first** is enabled. Each send includes server-built, bounded context for the task id, status/column/progress/current step, dependencies, recent activity/comment excerpts, prompt/plan content, and available source/review state; unavailable sections are labeled so the planner states uncertainty rather than inventing execution evidence. Opening the tab with no existing history does not create a database chat row; when no planner-chat history is found, Chat shows a guided empty state with starter prompts for recent activity, current status/blockers, next best action, and plan/definition review. Selecting a starter creates/resumes the planner chat and sends that prompt as an ordinary chat message through the task-context-aware planner-chat composer/stream path. The starter prompts disappear while history is loading or after conversation history exists, so Activity Live, Feed, Raw Logs, and the steering composer remain separate. Planner Chat defaults to focused mode, keeps its composer visible at the bottom while only the transcript scrolls, and on narrow/mobile task-detail layouts collapses nonessential rows above the chat until the user selects the Chat collapse control.
|
||||
|
||||
|
||||
@@ -481,25 +481,6 @@ FN-7241 adds timestamps inside individual task-detail transcript blocks. Keep bl
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
}
|
||||
|
||||
.task-chat-composer-affordance {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-sm);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.task-chat-composer-label {
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.task-chat-composer-hint {
|
||||
color: var(--text-muted);
|
||||
font-size: var(--space-md);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.task-chat-composer-row {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
@@ -637,16 +618,6 @@ FN-6660 corrects the repeated mobile sizing misses from FN-6507, FN-6604, and FN
|
||||
padding: var(--space-xs) var(--space-sm);
|
||||
}
|
||||
|
||||
.task-chat-composer-affordance {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: calc(var(--space-xs) / 2);
|
||||
}
|
||||
|
||||
.task-chat-composer-hint {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.task-chat-composer-row {
|
||||
align-items: flex-end;
|
||||
gap: var(--space-xs);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AgentLogEntry, AgentRole, SteeringComment, Task, TaskDetail } from "@fusion/core";
|
||||
import React, { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { ChevronDown, Cpu, Loader2, Maximize2, Minimize2, Send } from "lucide-react";
|
||||
@@ -582,7 +582,6 @@ export function TaskChatTab({ task, projectId, active, addToast, onTaskUpdated,
|
||||
const previousActiveRef = useRef(false);
|
||||
const anchorFrameRef = useRef<number | null>(null);
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const composerHintId = useId();
|
||||
|
||||
const userMessages = useMemo(
|
||||
() => mergeUserMessages(task.steeringComments, optimisticMessages),
|
||||
@@ -594,14 +593,14 @@ export function TaskChatTab({ task, projectId, active, addToast, onTaskUpdated,
|
||||
const isDoneTask = task.column === "done";
|
||||
/*
|
||||
* FNXC:TaskDetailActivity 2026-06-30-21:51:
|
||||
* Activity → Live (legacy `current`) is the operational steering surface for task execution. Show an explicit steering-comment affordance here while keeping the top-level planner-model Chat tab separate; Feed and Raw Logs remain read-only Activity segments without this composer.
|
||||
* Activity → Live (legacy `current`) is the operational steering surface for task execution. Keep the top-level planner-model Chat tab separate; Feed and Raw Logs remain read-only Activity segments without this composer.
|
||||
*
|
||||
* FNXC:TaskDetailActivity 2026-06-30-23:59:
|
||||
* Task Activity must keep the operational composer and existing steering/refinement APIs while removing the visible steering-comment guidance label/hint block from task chat. Use non-visible accessible names on the form/textarea/button so the removed copy does not leave a UI shell or dangling aria-describedby reference.
|
||||
*/
|
||||
const composerLabel = isDoneTask
|
||||
? t("taskChat.refinementComposerLabel", "Refinement request")
|
||||
: t("taskChat.steeringComposerLabel", "Steering comment");
|
||||
const composerHint = isDoneTask
|
||||
? t("taskChat.refinementComposerHint", "Create a follow-up refinement task from this completed task.")
|
||||
: t("taskChat.steeringComposerHint", "Send operational guidance to the active task through steering comments.");
|
||||
const composerFormLabel = isDoneTask
|
||||
? t("taskChat.refinementComposerFormLabel", "Task refinement composer")
|
||||
: t("taskChat.activityComposerFormLabel", "Task activity composer");
|
||||
const composerPlaceholder = isDoneTask
|
||||
? t("taskChat.donePlaceholder", "Start a refinement task for this completed task")
|
||||
: t("taskChat.activePlaceholder", "Steer the currently executing agent");
|
||||
@@ -938,11 +937,7 @@ export function TaskChatTab({ task, projectId, active, addToast, onTaskUpdated,
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<form className="task-chat-composer card" onSubmit={handleSubmit} aria-label={composerLabel}>
|
||||
<div className="task-chat-composer-affordance">
|
||||
<span className="task-chat-composer-label">{composerLabel}</span>
|
||||
<span className="task-chat-composer-hint" id={composerHintId}>{composerHint}</span>
|
||||
</div>
|
||||
<form className="task-chat-composer card" onSubmit={handleSubmit} aria-label={composerFormLabel}>
|
||||
<div className="task-chat-composer-row">
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
@@ -953,7 +948,6 @@ export function TaskChatTab({ task, projectId, active, addToast, onTaskUpdated,
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={sending}
|
||||
aria-label={t("taskChat.messageActiveAgentSession", "Message active agent session")}
|
||||
aria-describedby={composerHintId}
|
||||
rows={1}
|
||||
/>
|
||||
<button
|
||||
|
||||
@@ -187,17 +187,25 @@ function renderListSplitTaskChat(task: Task = makeTask()) {
|
||||
);
|
||||
}
|
||||
|
||||
function expectNoComposerGuidanceShell() {
|
||||
function expectNoComposerGuidanceShell(inputLabel = "Message active agent session") {
|
||||
/*
|
||||
* FNXC:TaskDetailChat 2026-06-24-00:00:
|
||||
* Task chat composers communicate the active/idle/done action through placeholders only; tests must prove the removed guidance block does not leave an empty status shell above the entry row.
|
||||
* FNXC:TaskDetailChat 2026-06-30-23:59:
|
||||
* Task Activity keeps the operational composer but removed the visible steering/refinement guidance affordance block; tests must prove no empty wrapper, stale label/hint copy, or dangling aria-describedby remains above the entry row.
|
||||
*/
|
||||
expect(screen.queryByTestId("task-chat-idle-hint")).not.toBeInTheDocument();
|
||||
expect(document.querySelector(".task-chat-session-hint")).toBeNull();
|
||||
expect(document.querySelector(".task-chat-session-hint--idle")).toBeNull();
|
||||
expect(document.querySelector(".task-chat-composer-affordance")).toBeNull();
|
||||
expect(document.querySelector(".task-chat-composer-label")).toBeNull();
|
||||
expect(document.querySelector(".task-chat-composer-hint")).toBeNull();
|
||||
expect(screen.queryByText(/^Steering comment$/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Send operational guidance to the active task through steering comments.")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/^Refinement request$/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Create a follow-up refinement task from this completed task.")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/no agent is working on this task right now/i)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/message the active agent session\. guidance is delivered to the running session in real time\./i)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/^send a message to start a refinement task for this completed task\.$/i)).not.toBeInTheDocument();
|
||||
expect(screen.getByLabelText(inputLabel)).not.toHaveAttribute("aria-describedby");
|
||||
}
|
||||
|
||||
function expectActivePlaceholderWithoutGuidance() {
|
||||
@@ -2415,14 +2423,14 @@ describe("TaskChatTab", () => {
|
||||
expect(onTaskUpdated).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders the same explicit steering composer affordance on desktop and mobile breakpoints", () => {
|
||||
it("keeps the composer usable without visible steering guidance copy on desktop and mobile breakpoints", () => {
|
||||
mockMatchMedia(false);
|
||||
const desktop = render(<TaskChatTab task={makeTask()} active addToast={vi.fn()} />);
|
||||
expect(screen.getByTestId("task-chat-tab")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("task-chat-transcript")).toBeInTheDocument();
|
||||
expect(screen.getByRole("form", { name: "Steering comment" })).toBeInTheDocument();
|
||||
expect(screen.getByText("Send operational guidance to the active task through steering comments.")).toBeInTheDocument();
|
||||
expect(screen.getByLabelText("Message active agent session")).toHaveAccessibleDescription("Send operational guidance to the active task through steering comments.");
|
||||
expect(screen.getByRole("form", { name: "Task activity composer" })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expectActivePlaceholderWithoutGuidance();
|
||||
expect(screen.getByLabelText("Message active agent session")).toHaveClass("task-chat-input");
|
||||
expect(screen.getByRole("button", { name: "Send" })).toHaveClass("task-chat-send");
|
||||
desktop.unmount();
|
||||
@@ -2431,18 +2439,20 @@ describe("TaskChatTab", () => {
|
||||
render(<TaskChatTab task={makeTask()} active addToast={vi.fn()} />);
|
||||
expect(screen.getByTestId("task-chat-tab")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("task-chat-transcript")).toBeInTheDocument();
|
||||
expect(screen.getByRole("form", { name: "Steering comment" })).toBeInTheDocument();
|
||||
expect(screen.getByText("Send operational guidance to the active task through steering comments.")).toBeInTheDocument();
|
||||
expect(screen.getByRole("form", { name: "Task activity composer" })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expectActivePlaceholderWithoutGuidance();
|
||||
expect(screen.getByLabelText("Message active agent session")).toHaveClass("task-chat-input");
|
||||
expect(screen.getByRole("button", { name: "Send" })).toHaveClass("task-chat-send");
|
||||
});
|
||||
|
||||
it("keeps completed tasks on the refinement affordance instead of steering copy", () => {
|
||||
it("keeps completed task refinement functional without the shared visible affordance shell", () => {
|
||||
render(<TaskChatTab task={makeTask({ column: "done" })} active addToast={vi.fn()} />);
|
||||
|
||||
expect(screen.getByRole("form", { name: "Refinement request" })).toBeInTheDocument();
|
||||
expect(screen.getByText("Create a follow-up refinement task from this completed task.")).toBeInTheDocument();
|
||||
expect(screen.getByRole("form", { name: "Task refinement composer" })).toBeInTheDocument();
|
||||
expectDonePlaceholderWithoutGuidance();
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Refinement request" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("FN-6347 pins the composer while the transcript flex-fills without fixed viewport caps", () => {
|
||||
@@ -2767,21 +2777,20 @@ describe("TaskChatTab", () => {
|
||||
const css = readFileSync(resolve(__dirname, "../TaskChatTab.css"), "utf8");
|
||||
const sendRule = getCssRuleBlock(css, ".task-chat-send");
|
||||
const mobileCss = getCssAfter(css, "@media (max-width: 768px)");
|
||||
const mobileAffordanceRule = getCssRuleBlock(mobileCss, ".task-chat-composer-affordance");
|
||||
const mobileComposerRule = getCssRuleBlock(mobileCss, ".task-chat-composer-row");
|
||||
const mobileSendRule = getCssRuleBlock(mobileCss, ".task-chat-send");
|
||||
|
||||
expect(css).toContain("@media (max-width: 768px)");
|
||||
expect(css).toContain(".task-chat-transcript");
|
||||
expect(css).toContain(".task-chat-jump-to-bottom");
|
||||
expect(css).toContain(".task-chat-composer-affordance");
|
||||
expect(css).not.toContain(".task-chat-composer-affordance");
|
||||
expect(css).not.toContain(".task-chat-composer-label");
|
||||
expect(css).not.toContain(".task-chat-composer-hint");
|
||||
expect(css).toContain(".task-chat-composer-row");
|
||||
expect(sendRule).toContain("--btn-icon-size: var(--space-2xl)");
|
||||
expect(sendRule).toContain("inline-size: calc(var(--space-2xl) + var(--space-sm))");
|
||||
expect(sendRule).toContain("block-size: calc(var(--space-2xl) + var(--space-sm))");
|
||||
expect(sendRule).not.toContain("gap");
|
||||
expect(mobileAffordanceRule).toContain("flex-direction: column");
|
||||
expect(mobileAffordanceRule).toContain("gap: calc(var(--space-xs) / 2)");
|
||||
expect(mobileComposerRule).toContain("align-items: flex-end");
|
||||
expect(mobileComposerRule).not.toContain("flex-direction: column");
|
||||
expect(mobileComposerRule).not.toContain("align-items: stretch");
|
||||
|
||||
@@ -81,7 +81,9 @@ describe("TaskDetailModal Activity and planner Chat tab integration", () => {
|
||||
expect(activitySegmentButtons().map((button) => button.textContent?.trim())).toEqual(["Live", "Feed", "Raw Logs"]);
|
||||
expect(activitySegmentButtons().every((button) => (button.textContent ?? "").trim().length > 0)).toBe(true);
|
||||
expect(screen.getByRole("tab", { name: "Live" })).toHaveAttribute("aria-selected", "true");
|
||||
expect(screen.getAllByRole("form", { name: "Steering comment" })).toHaveLength(1);
|
||||
expect(screen.getAllByRole("form", { name: "Task activity composer" })).toHaveLength(1);
|
||||
expect(screen.queryByText(/^Steering comment$/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Send operational guidance to the active task through steering comments.")).not.toBeInTheDocument();
|
||||
expect(screen.getByText("Existing steering guidance")).toBeInTheDocument();
|
||||
expect(screen.queryByRole("heading", { name: "Feed" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("agent-log-viewer")).not.toBeInTheDocument();
|
||||
@@ -89,7 +91,7 @@ describe("TaskDetailModal Activity and planner Chat tab integration", () => {
|
||||
await user.click(screen.getByRole("tab", { name: "Feed" }));
|
||||
|
||||
expect(screen.getByRole("tab", { name: "Feed" })).toHaveAttribute("aria-selected", "true");
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
expect(screen.getByRole("heading", { name: "Feed" })).toBeInTheDocument();
|
||||
expect(screen.getByText("Posted update")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Existing steering guidance")).not.toBeInTheDocument();
|
||||
@@ -98,7 +100,7 @@ describe("TaskDetailModal Activity and planner Chat tab integration", () => {
|
||||
await user.click(screen.getByRole("tab", { name: "Raw Logs" }));
|
||||
|
||||
expect(screen.getByRole("tab", { name: "Raw Logs" })).toHaveAttribute("aria-selected", "true");
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("heading", { name: "Feed" })).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("agent-log-viewer")).toBeInTheDocument();
|
||||
expect(screen.getByText("raw executor line")).toBeInTheDocument();
|
||||
@@ -193,11 +195,14 @@ describe("TaskDetailModal Activity and planner Chat tab integration", () => {
|
||||
expect(within(segmentGroup).getAllByRole("tab").map((tab) => tab.textContent?.trim())).toEqual(["Live", "Feed", "Raw Logs"]);
|
||||
expect(within(segmentGroup).getAllByRole("tab")).toHaveLength(3);
|
||||
expect(screen.getByText("No agent output yet. Live messages from Planner, Executor, Reviewer, and Merger agents will appear here.")).toBeInTheDocument();
|
||||
expect(screen.getAllByRole("form", { name: "Refinement request" })).toHaveLength(1);
|
||||
expect(screen.getAllByRole("form", { name: "Task refinement composer" })).toHaveLength(1);
|
||||
expect(screen.queryByRole("form", { name: "Refinement request" })).not.toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Chat" }));
|
||||
expect(screen.getByRole("button", { name: "Chat" })).toHaveClass("detail-tab-active");
|
||||
expect(screen.getByTestId("task-planner-chat-panel")).toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task refinement composer" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Refinement request" })).not.toBeInTheDocument();
|
||||
} finally {
|
||||
|
||||
@@ -543,15 +543,16 @@ describe("TaskDetailModal Chat task merge", () => {
|
||||
);
|
||||
|
||||
expect(screen.getByRole("tab", { name: "Live" })).toHaveAttribute("aria-selected", "true");
|
||||
expect(screen.getAllByRole("form", { name: "Steering comment" })).toHaveLength(1);
|
||||
expect(screen.getByText("Send operational guidance to the active task through steering comments.")).toBeInTheDocument();
|
||||
expect(screen.getAllByRole("form", { name: "Task activity composer" })).toHaveLength(1);
|
||||
expect(screen.queryByText(/^Steering comment$/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Send operational guidance to the active task through steering comments.")).not.toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("tab", { name: "Feed" }));
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
expect(screen.getByText("Started work")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("tab", { name: "Raw Logs" }));
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("agent-log-viewer")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("tab", { name: "Live" }));
|
||||
@@ -582,15 +583,15 @@ describe("TaskDetailModal Chat task merge", () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getAllByRole("form", { name: "Steering comment" })).toHaveLength(1);
|
||||
expect(screen.getAllByRole("form", { name: "Task activity composer" })).toHaveLength(1);
|
||||
expect(screen.getByText("No agent output yet. Live messages from Planner, Executor, Reviewer, and Merger agents will appear here.")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("tab", { name: "Feed" }));
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
expect(screen.getByText("(no activity)")).toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("tab", { name: "Raw Logs" }));
|
||||
expect(screen.queryByRole("form", { name: "Steering comment" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("form", { name: "Task activity composer" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("forwards full-detail agent fields to Chat when a sparse parent task has undefined live fields", async () => {
|
||||
|
||||
Reference in New Issue
Block a user