docs(tasks): 工作图打磨的设计文档与真机验证证据;卡片细节两处修正

- 新增 docs/plans/2026-09-27-tasks-graph-polish.md:本轮问答结论、架构与文件、
  关键设计(卡片两段 / 合并活动 / 扫光 / 折叠聚合 / ctx.jobs / 布局与窄栏)、
  移植与丢弃清单、实施偏差记录、验证证据(含 3080 真机逐项目击记录与截图路径)、
  未在真机复现的两项与已知取舍。
- 2026-09-14 图分支设计文档加「本轮打磨」小节指向新文档;README 任务页条目
  与 AGENTS §1/§3.1#4 同步(后台任务改读宿主客户端 ctx.jobs,不再自建回放路由)。
- 卡片两处修正(真机截图暴露):
  ① 小条的钩子从 `data-state` 改为 `data-card-bar` —— 宿主自己的 primitive 也在
     发 `data-state`(菜单分隔、编辑器等),同名属性让「卡片内恰好一条小条」的
     断言与用户 CSS 都不可靠;
  ② 上段的 mono 行改由新的 `agentIdentity()` 产出(只讲「是谁」),根节点返回空
     —— 原先复用 `agentMeta()` 会把状态词印两遍(徽章下方 + 小条),正是用户
     反馈的「节点内信息太密」。可访问名继续用含状态的 `agentMeta()`。

验证:typecheck / lint 通过;pnpm test 1240 passed / 9 skipped;
挂载 lane 7/7(真实 DSH 0.1.7-rc.2);3080 真机自测通过(见文档表格)。

(cherry picked from commit 338a54820799c26ab91141e8d98c673b8d474610)
This commit is contained in:
Menghuan1918
2026-09-27 22:18:49 +08:00
parent 48294d336e
commit 5ea2f2d6ec
7 changed files with 210 additions and 11 deletions
+2 -2
View File
@@ -40,7 +40,7 @@ import {
type GraphBox,
} from './tasks-graph-layout.ts'
import {
agentMeta, foldPreviews, TaskLine, WorkflowGlyph, workflowMeta,
agentIdentity, agentMeta, foldPreviews, TaskLine, WorkflowGlyph, workflowMeta,
} from './tasks-shared.tsx'
import { CardBar, CardTop, phaseClass, type CardKind } from './tasks-card.tsx'
import { doneActivityTitle, liveActivityLabel } from './process-labels.ts'
@@ -574,7 +574,7 @@ function renderAgentNode(
depth={node.depth}
{...(node.phase === undefined ? {} : { phase: node.phase })}
name={node.label}
meta={agentMeta(node)}
meta={agentIdentity(node)}
>
<TaskLine tasks={node.tasks} onOpenTask={onOpenTask} />
</CardTop>
+4 -2
View File
@@ -99,7 +99,9 @@ export function CardTop(props: {
)}
</span>
<span className={clsx(css.cardName, props.extraClass)} title={props.name}>{props.name}</span>
{props.meta !== undefined && <span className={css.cardMeta} title={props.meta}>{props.meta}</span>}
{props.meta !== undefined && props.meta !== '' && (
<span className={css.cardMeta} title={props.meta}>{props.meta}</span>
)}
{props.children}
</span>
)
@@ -125,8 +127,8 @@ export function CardBar(props: {
return (
<span
className={css.cardBar}
data-card-bar={state}
data-running={running === true ? 'true' : undefined}
data-state={state}
>
{props.children ?? (
<>
+18
View File
@@ -121,6 +121,24 @@ export function agentMeta(node: TasksAgentNode): string {
return mode === undefined ? state : `${mode} · ${state}`
}
/**
* The CARD's mono meta line: WHO the node is, never its state.
*
* The state belongs to the card's bottom bar (the state word sits next to the
* state dot there), so repeating it here would print "已完成" twice inside one
* 190px card — the densest complaint the readability pass had to fix. The
* accessible name keeps {@link agentMeta} (state included), because a screen
* reader never sees the bar's dot.
*/
export function agentIdentity(node: TasksAgentNode): string {
// The root's badge already reads 主代理: an identity line would repeat it.
if (node.parentId === undefined) return ''
if (node.team?.role === 'teammate' && node.team.model !== undefined && node.team.model !== '') {
return node.team.model
}
return modeLabel(node.mode) ?? ''
}
/** The mono meta line of a workflow run card: status · member tally. */
export function workflowMeta(node: TasksWorkflowNode): string {
const { run } = node