diff --git a/.changeset/fix-task-chat-ephemeral-agent-working.md b/.changeset/fix-task-chat-ephemeral-agent-working.md
new file mode 100644
index 0000000000..6842db64aa
--- /dev/null
+++ b/.changeset/fix-task-chat-ephemeral-agent-working.md
@@ -0,0 +1,5 @@
+---
+"@runfusion/fusion": patch
+---
+
+Fix the task detail chat always showing "No agent is working on this task" for in-progress tasks. The active-session check required a persistent `assignedAgentId`/`checkedOutBy`, but in the default ephemeral-agents mode the scheduler never sets those fields, so an actively-executing task always read as idle. An assignment is now sufficient-but-not-necessary: a non-blocked, non-`queued` in-progress task counts as a live agent session on its own (`queued` stays assignment-gated, in-review is unchanged).
diff --git a/packages/dashboard/app/components/TaskChatTab.tsx b/packages/dashboard/app/components/TaskChatTab.tsx
index ac5d77d10b..3d8421e85f 100644
--- a/packages/dashboard/app/components/TaskChatTab.tsx
+++ b/packages/dashboard/app/components/TaskChatTab.tsx
@@ -172,8 +172,20 @@ function isActiveAgentSession(task: Task | TaskDetail, opts: { sessionLive?: boo
const statusAllowsReviewSteering = !task.status || REVIEW_STEERABLE_STATUSES.has(task.status);
const columnAllowsSteering = (task.column === "in-progress" && statusAllowsProgressSteering)
|| (task.column === "in-review" && statusAllowsReviewSteering);
+ // In the default ephemeral-agents mode the scheduler never writes
+ // `assignedAgentId`/`checkedOutBy` — those are only set when
+ // `ephemeralAgentsEnabled === false` (scheduler.ts). An actively-executing
+ // in-progress task therefore has no assignment field yet IS being worked, so
+ // requiring `hasAssignedAgent` made the chat always show "no agent is working"
+ // for default-mode tasks. Treat assignment as sufficient-but-not-necessary:
+ // a non-blocked, non-`queued` in-progress task is a live session on its own.
+ // `queued` is the documented waiting/blocked marker (self-healing.ts), so it
+ // stays assignment-gated; in-review keeps requiring an assignment.
+ const inProgressExecuting = task.column === "in-progress"
+ && statusAllowsProgressSteering
+ && task.status !== "queued";
return columnAllowsSteering
- && hasAssignedAgent;
+ && (hasAssignedAgent || inProgressExecuting);
}
function isToolLikeEntry(entry: AgentLogEntry): boolean {
diff --git a/packages/dashboard/app/components/__tests__/TaskChatTab.test.tsx b/packages/dashboard/app/components/__tests__/TaskChatTab.test.tsx
index 0d043c7a8d..ea046c0cba 100644
--- a/packages/dashboard/app/components/__tests__/TaskChatTab.test.tsx
+++ b/packages/dashboard/app/components/__tests__/TaskChatTab.test.tsx
@@ -1802,6 +1802,40 @@ describe("TaskChatTab", () => {
expectComposerSendableAfterDraft();
});
+ it.each([undefined, "planning", "merging", "merging-fix"])(
+ "treats an actively-executing in-progress task as an active session even without an assignment (ephemeral mode): %s status",
+ (status) => {
+ // In the default ephemeral-agents mode the scheduler never writes
+ // assignedAgentId/checkedOutBy, so a running in-progress task has no
+ // assignment field yet IS being worked. It must NOT show the idle
+ // "no agent is working" hint.
+ render(
+ ,
+ );
+
+ expectActiveSessionCopy();
+ expect(screen.getByLabelText("Message active agent session")).not.toBeDisabled();
+ },
+ );
+
+ it("keeps a queued (waiting) unassigned in-progress task idle in ephemeral mode", () => {
+ render(
+ ,
+ );
+
+ expectIdleSessionHint();
+ });
+
it.each(["busy", "ready", "starting", "waitingOnInput"] as const)("treats %s CLI sessions as live", (agentState) => {
expect(isCliSessionLive(makeCliSession(agentState))).toBe(true);
});