Commit Graph
14 Commits
Author SHA1 Message Date
Menghuan1918 84b68e9216 feat(tasks): 任务窗内容填满高度可自然拉伸;聚合卡在成员多时报出 +N
用户两条优化:
  1. 任务详细占满上下部分,不要留空(这样能自然拉伸)
  2. 思考如何优化内容很多时的待命和完成的样式

第 1 条:描述区原本是 `max-height: 160px` 的滚动盒,窗口拉大只长空白。
FloatingWindow 新增 `bodyLayout: 'scroll' | 'fill'`(默认 scroll 不变,后台
任务输出窗仍按原样流动),fill 把 body 变成列容器、让调用方的子节点自己决定
谁吃余量;任务窗据此把余量全给描述区(编辑态给多行输入框,`flex: 1` 跟着窗
口长),头部行 / 元信息 / 负责人 / 提示行都 `flex: none`,不会跟着漂。

第 2 条:一队队友很多时,聚合卡只有一行名字却塞了十几个人,卡上看不出还有
多少。名称行现在写「前两个名字 + N」—— 用的是团队任务行已有的同一个 `+N`
约定,不是第二套;分组总数另有徽标和小条两处,所以 `+N` 只是尾巴而不是唯一
计数。图卡片与树行共用同一个 foldPreviews。

测试:新增 2 例(窗口声明 fill 布局、描述区在 body 内且编辑态换成多行框;
五个待命成员的聚合卡名称是 `m1 / m2 +3`);floating-window 既有 9 例回归通过。
pnpm test 1288 passed / 9 skipped,typecheck / lint 通过。

(cherry picked from commit 62651e731d6e5fd0378e2ecc504792cb2e3eb461)
2026-09-27 22:19:05 +08:00
Menghuan1918 11c2a16986 feat(tasks): 空闲与已完成分成两个聚合行;待命卡片补上自己的折叠按钮
用户两条反馈:
  1. 空闲和已完成分开折叠合集
  2. 空闲的无法折叠

第 2 条是纯疏漏:chevron 的出现条件写死在 `settled = done | error` 上,
「待命」的卡因此从来不画折叠按钮(跟折叠规则无关,规则早就允许手动收)。
现在 chevron 按「不在执行」(done | error | idle)出现,而 `settled` 仍只
表示完成/出错 —— 它管的是卡片该不该变淡,待命不是完成的工作。

第 1 条把上一轮那个「混合聚合」拆开:
- 一个父节点现在最多两行 —— `fold:<parent>`(已完成/出错)与
  `fold:<parent>:idle`(待命成员);
- 各自的徽标说实话:完成行仍是「✓ N 已完成」,待命行是「N 个待命」;
  完成行的条会额外报 `出错 N`(全是失败时只剩这一项),否则失败会藏在 ✓ 里;
- 待命行的条只写 `N 待命`(同组同状态,不重复计数);
- 阈值只作用于**自动**规则(≥3 待命成员才随页面级折叠一起收),手动 chevron
  永远有效,两行互不牵连 —— 想扫掉待命的成员,不必连已完成的一起带走。

新增 tasksFoldIdleGroup ×20 词典;删掉上一轮的 hasIdle 与 foldBadgeCount
(分组后它们没有意义)。

测试:新增/改写 7 例 —— 三个待命成员收进 idle 行、两个保持可见、运行中成员
达标也不收、混合场景两行各归各的、手动折叠单个待命成员落进 idle 行、
待命卡确实带 chevron 且点后只剩聚合、聚合徽标说「N 个待命」。
pnpm test 1286 passed / 9 skipped,typecheck / lint 通过。

(cherry picked from commit 0c9c8abca85e8aeb54bb2e9fcaaeed0486a56c28)
2026-09-27 22:19:05 +08:00
Menghuan1918 c0ff3d1afd feat(tasks): 空闲成员 ≥3 时自动收进聚合,聚合并如实报出状态配比
用户要求优化显示:「比如空闲时也折叠」。

在此之前,一个跑完一轮的 teammate(活体通道不报 running)映射成 idle,
而 idle 不在「已完成/出错」的可折叠集合里 —— 于是 8 人团队永远摆 8 张卡,
而同样「不在执行」的普通子代理却是 done、会折叠。同一事实两种显示,才是
这个痛点的根。

- 可折叠集合放宽到「不在执行」(done | idle | error);运行中/部署中永不折叠。
- 空闲**不无条件收**:按用户确认的阈值,一个父节点下空闲成员 ≥3 才随页面级
  折叠规则一起收(FOLD_IDLE_MIN)。1–2 个待命成员就是这个团队的工作集,
  而且它们的卡上会挂任务行,留着看;3 个以上才是「在扫名册」。
- 聚合行如实报账:聚合节点新增 doneCount/idleCount/errorCount/hasIdle,
  小条写 `✓ N 已完成 · N 待命 · 出错 N`(为零的项省略,全已完成时与原先一样短),
  徽标在**没有已完成项**时改说 `N 待命` —— 否则「✓ N 已完成」会把待命和出错
  一起算成已完成,是撒谎。图卡片与树行共用 foldTally/foldBadgeCount。
- 手动折叠(卡片 chevron)不设阈值:那是读者点名要收的节点。
- i18n:新增 tasksFoldIdle ×20 词典。

测试:新增 6 例(阈值命中收 3 个空闲成员、2 个保持可见、运行中成员即使达标也不收、
混合聚合按状态计数、页面聚合行报「3 待命」且徽标不说已完成);pnpm test
1284 passed / 9 skipped,typecheck / lint 通过。

(cherry picked from commit 39d66ffb2e93eeb4095ec1cb2ac15933cce62742)
2026-09-27 22:19:05 +08:00
Menghuan1918 d8bc6566df feat(tasks): 适配 DSH 0.1.7 的 Agent Teams(读 projection + 写路由对接真实服务)
团队功能在 0.1.7 上整条失效:team-routes.ts 当初镜像的是 0.1.6 的 Remote 词汇
(remoteView / remoteCreateTask / remoteUpdateTask),而 0.1.7 把这三个方法删掉了,
读路径改到 Lead Session 的 `agentTeam` Session projection。真机 3080 复现:
teams.view 对带团队的会话返回 400 "membership.svc.remoteView is not a function",
于是 TeamBoard 从不渲染、节点富化与任务窗连带失效。

- 读:删掉 teams.view 与 5s 轮询,改读 SessionListState.projectionsBySession[root]
  .values.agentTeam(与 subagentCatalog 同源,推送式);新增 client/team-projection.ts
  做纯适配器,成员运行状态由 subagents.live 的 running 叠加、Lead 回退 session list
  (官方 README 的 "overlays activity from Session status")。projection 缺席 =
  这里没有团队,与旧的 {available:false}/{team:null} 合并成同一静默降级。
- 写:taskCreate/taskUpdate 改调 0.1.7 的 createTask/updateTask(返回已提交的 view,
  拒绝改为抛 TeamError),TEAM_TASK_STALE_REVISION → 409 team-conflict,其余 → 400
  team-error(wire 新增 team-conflict)。api.ts 的 writeTask 把失败信封还原成
  {ok:false,code,message} —— 原先窗口永远走不到该分支(readEnvelope 是抛)。
- 任务窗:外壳换成上一轮的 FloatingWindow(可拖拽/可拉伸/只在关闭或 Esc 时消失),
  动作行下沉到 shell 的 footer,长描述不再把动作推出视野。
- 真机抓到的两个单测抓不到的问题:
  1. 队列中任务的「完成」被宿主状态机拒绝(pending → claim → in_progress →
     complete → completed → reopen)→ 动作行跟随状态,pending 出「认领」;
  2. 认领后 Tag 变「阻塞」—— ready 的语义只是「pending 且无未完成 blocker」,
     对所有非 pending 任务都是 false → 抽出唯一规则 taskBlocked/taskStatusLabel/
     taskTone/taskDotState,四处展示点全部改走它。
- i18n:新增 teamTaskClaim / taskWindowCreate / taskWindowDetail /
  tasksStateProvisioning 词条 ×20 词典。

验证:typecheck / lint 通过;pnpm test 1276 passed / 9 skipped;
pnpm test:mount 7/7(真实 DSH 0.1.7-rc.2 挂载 + tab 全扫无崩溃)。
真机 3080(0.1.7-rc.1 + Agent Teams 实验层):看板从 projection 渲染、
队列任务「认领」→「完成」全链路写通(负责人 lead / 进行中 / 已完成)、
外部点击不关窗、Escape 关窗,截图见 docs/plans/2026-09-27-agent-teams-dsh-0.1.7-adaptation.md。

(cherry picked from commit dbc524e0b350c5d3564843f4776cd15d797506d8)
2026-09-27 22:19:05 +08:00
Menghuan1918 7cce50c493 fix(tasks): 扫光改为整条完整扫过 + 折叠/展开按钮分向
用户反馈两条:

1) 扫光只有「部分」:第一版是 45% 宽的窄带 + background-position 位移,
   亮带始终只覆盖小条的一部分(峰值 22.5%→77.5%,两端扫不到),看起来像
   中间游走的一块光斑。改为与小条等宽的渐变带 + transform
   translateX(-100%) → translateX(100%):光带从左外侧进入、中途覆盖整条、
   再向右外侧离开,行程用条宽本身表达(任意条宽成立),末 1/3 周期停在
   右侧外侧留白。theme.spec 新增守护钉住该形状(宽度 100%、transform 行程、
   不再有 background-position/size 位移)。

2) 折叠按钮与展开按钮长得一样:三处控件原本共用向下箭头(控制条的折叠开关
   更是无论折叠还是展开都画同一个清单图标)。现按动作方向区分——
   卡片小条的逐节点按钮 = chevron up(收进聚合),聚合卡片 = chevron down
   (展开),控制条开关随状态在两者之间切换(并复用同一个折叠图标)。
   组件守护见 tasks-page.spec 的「draws COLLAPSE and EXPAND with different
   glyphs」。

真机证据(3080,真实运行中的后台任务):242px 小条上每 90ms 采样 ::after 的
matrix 平移量得到 [-23,32,85,131,163,-139,-94,-46,9,64,114,152,179,188]
(左侧 -139 → 右侧 +188,跨度超过一个条宽,单调推进);三处 svg 比对
expandVsCollapse / clusterMatchesExpand / clusterFlips / clusterCollapseMatchesCard
全部为 true。

验证:typecheck / lint ✅;pnpm test 1256 passed / 9 skipped(新增 2 例)。

(cherry picked from commit 0bb8228e6a7acb4302d9a8a9881d2df04a285152)
2026-09-27 22:18:57 +08:00
Menghuan1918 d38fefe55d feat(tasks): 任务输出常驻浮动窗 + 节点卡去竖线 + 手机设置
三件事一起落地(用户 brief),各自独立可验证:

1) 后台任务输出改为常驻浮动窗
   - 新增 src/client/FloatingWindow.tsx + .module.css:可复用组件,标题栏(拖拽手柄 +
     复制/关闭)、内容区(自滚动,长输出不再跑出视口)、可选底部行、三个拉伸柄
     (右/下/右下)。生命周期与 AnchoredPopover 相反:外部点击、失焦、锚点离屏都不关,
     只有关闭按钮与 Escape 结束;尺寸只在挂载时量一次(流式输出帧不会挪动读者摆好的窗);
     拖拽保持整窗在视口内(放不下才退化到保留 48px 可达);视口变化时夹回。
   - 手势复用既有范式:移动走 window 级 pointermove(同 AnchoredPopover),拉伸走
     setPointerCapture + createFrameBatcher(同 EditorHost 的面板拉伸)。
   - JobOutputPopoverContent → JobOutputWindow;顺带修掉「跟随最新」从不滚动的 bug
     (原先滚的是 TerminalBlock 外面那个永不滚动的 div),并清掉随旧弹窗死掉的
     .popPre / .jobPopPre 规则。节点/工作流详情与任务窗保持原样。

2) 节点卡统一
   - 删除两条左侧竖条(层级条 .cardTop::before、当前会话条 .nodeCurrent::before);
     层级改由上段极淡底色承担(7/5/3.5/2.5% → 9/7/5/3.5% 补偿对比度);
     当前会话改为 2px accent 描边(「边框加粗高亮」)。
   - 圆角 4px → 8px(与浮动窗同一家族);成员/工作流/聚合按用户选择保留类型区分。
   - 2px 而非 1.5px:真机 recon 发现 Chromium 在 DPR 1 下把亚像素边框向下取整,
     1.5px 的「加粗」完全看不出(实测 borderTopWidth: "1px")。几何不受影响
     (border-box + min-height,卡片外框 247×134 与预算逐像素一致)。

3) 手机设置
   - 两个新偏好 mobileNoAutoOpen / mobileDefaultTree(默认都开),落到 prefs-shared、
     PrefsSchema(volatile 自动)、parsePrefs 校验与设置页新增的「手机」分组。
   - 窄屏(沿用 768px 断点)时:新子代理与新后台任务都不再自动激活任务页;
     任务页默认树状图(页内切换仍是临时覆盖)。宽屏或开关关掉后行为完全不变。
   - 5 条词条 ×20 份词典;外部插件指南的 PrefsSchema 键清单同步。

验证:typecheck / lint ✅;pnpm test 1254 passed / 9 skipped(新增 14 例);
挂载 lane 7/7(真实 DSH 0.1.7-rc.2);3080 真机自测通过(长输出窗口内部滚动
5459px/449px、拖拽 424→304、拉伸 1008×540→918×480、外部点击不关、Escape 关、
卡片 8px/2px/无竖条、窄屏不自动弹出且默认树状图)。

(cherry picked from commit 7d9b428c6c34d28ad2d60c2086496eb533902273)
2026-09-27 22:18:57 +08:00
Menghuan1918 5ea2f2d6ec 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)
2026-09-27 22:18:49 +08:00
Menghuan1918 48294d336e refactor(tasks): 后台任务改读宿主客户端 jobs 服务,删除自建三条路由
- 新增 src/client/jobs-client.ts:结构探测 ctx.jobs(watchRows / observe /
  state / kill),引用计数的按会话 roster 订阅、只观测展开的那一行、
  跨树去重(无主任务归到承载它的被观测会话,树外 owner 丢弃)。
- 抽屉与输出浮窗改读该服务:行来自推送 roster(状态 / 时长 / owner / 进度),
  输出面换 TerminalBlock 显示宿主为观察者流的保留输出(gapBefore → 截断提示、
  error → 失败提示),kill 走 jobs.kill(owner, jobId),两击确认不变。
- 自动激活(use-host-feeds)改骑同一条推送 roster;detectNewJob 增加
  「观测起点时钟」参数,避免「页面打开时已在跑的任务」被当成新工作。
- 删除 src/jobs-routes.ts(+ tests/jobs-routes.spec.ts)、index.ts 的三条路由、
  api.jobsList/jobOutput/jobKill 与 JobOutputResult、context-types 的
  SidebarJobsService(换成 SidebarClientJobsService/SidebarJobsSnapshot/
  SidebarObservedJob 镜像,SidebarJobView 补 owner/progress)、
  页面里的 jobs.list 轮询与 collectTreeJobs。
- 三个 spec 改用假 ctx.jobs 服务(jobs-view 14 例 / 自动激活 12 例 /
  页面 20 例):观测只在展开行、切换与关闭释放观测、watch 隐藏时不建立、
  卸载时全部释放、无服务时不渲染任务面。

验证:typecheck / lint 通过;pnpm test 1240 passed / 9 skipped;pnpm build + pack 通过。

(cherry picked from commit 7d9b82e73190218f05910433ed520cb90e4d4ab2)
2026-09-27 22:18:35 +08:00
Menghuan1918 f584b67813 feat(tasks): 图节点改为双段式卡片 + 折叠聚合 + 窄栏可读性
图模式(主显示模式)换成新的卡片语言,树模式保持不变:

- 卡片 = 上段(类型徽章 + 相位徽标 + 名称两行 + mono 元信息 + 团队任务行)
  + 下段小条(状态点 + 状态词 + 主 Agent 同款合并活动 + 完成后的折叠 chevron)。
  类型徽章用页面自己的词汇(主代理 / 子代理 / 成员 / 工作流 / ✓N 已完成)。
- 分组色(层级):按树深度取 4 档令牌色阶(color-mix 混 --dsw-alias-state-business-primary),
  作用于左描边与上段极淡底色;相位徽标走 ink 色族,两套分组不撞色。
  相位虚线框保留但改用同色极淡描边,卡片徽标承担「这是哪个阶段」。
- 执行态:小条 `data-running` + 从左到右扫光(1.5s,末 1/3 停顿,
  prefers-reduced-motion 关闭);合并活动行来自宿主 chat 词条,缺失时回退插件文案。
- 折叠:已完成节点的 chevron 把该节点「收进已完成聚合」(模型新增 foldedIds,
  与全局 folded 走同一组守卫:只在已结算叶子、非当前会话、非团队成员时生效);
  聚合节点点击 = 全部展开(清空手动集 + 关闭全局折叠);控制条仍只管全局规则。
- 布局与窄栏(用户反馈 a–f):卡片高度预算按新行重算(徽章 + 两行标题 + 元信息 +
  小条 = 103px,任务行 +18),宽度 176 → 190;fit 按内容包围盒双轴居中、
  FIT_MAX_SCALE 1.15 → 1.30;缩放范围 0.4–2.0 并归一化 wheel deltaMode;
  平移加边界夹取(至少 72px 内容留在视口内);空画布双击重新适配并恢复自动 fit;
  连线改「垂直出线 stub + 贝塞尔」并加粗到 1.5px。

验证:typecheck / lint 通过;pnpm test 1253 passed / 9 skipped(含新增双段结构、
data-running、chevron → 聚合、聚合 → 全部展开、工作流相位徽标 5 例)。

(cherry picked from commit aee571e50beb5dc979995f0841cffd0a575f2173)
2026-09-27 22:18:35 +08:00
Menghuan1918 2a39a0c8b2 chore: adapt the tasks/workflow/teams work to DSH 0.1.7-rc.1 (rebase onto v0.21.1)
Rebases the whole branch onto main's new 0.1.7-rc.1 baseline and lands the
adaptation the new host contract requires: the ui-primitives icon family rename
(Icon<Name><14|16> -> Icon<Name>Regular/Medium, with the 14px defaults pinned
back explicitly) and the StateDot redraw, the rewritten dsh-settings surface
(entry-id namespace, DSH schemastery with collected volatile returns,
configure auto:false), session format v4 (producer-owned source kind plus the
rewritten tool-result shape, parsers accepting both), the client snapshot move
to projectionsBySession.subagentCatalog with the jobs.list route behind it, the
^0.1.7-rc.1 peer floor with vendor and bare-import devDeps, the reduced chunk
set mirrored in all eight places, and the capability hand-backs (read-only
previews, terminal, browser).

Verified: typecheck and lint clean; 119 files / 1200 tests; build with no old
contract residue in the bundles; mount e2e 7/7; the tasks page still passes its
70-assertion real-browser contract.
2026-09-27 22:18:19 +08:00
Menghuan1918 7cbfc766a1 feat(tasks-ui): one task window everywhere, cards are their own detail entry
Round-three review feedback:

- NO PER-CARD DETAIL BUTTON: the ellipsis control is gone from graph cards
  and tree rows — the card IS the affordance, and clicking it opens the
  detail window (the transcript jump moved inside as the primary button).
  Fold aggregates keep click-to-expand.
- ONE TASK WINDOW: every task surface (board row, agent node task line, the
  node detail list, and creating a task) now opens the same non-fullscreen
  DRAGGABLE window (TaskWindow.tsx + its TaskPopover shell): markdown
  description by default, 编辑 switches the same card to multi-line editing,
  plus owner reassignment, complete/reopen and a two-step delete. The board
  lost its overflow menu and its Modal entirely; create uses the same window
  in create mode.
- REUSE: TaskPopover (4 call sites), MultilineField (the plugin's own
  multi-line input — the host primitive set has none), OwnerPicker,
  TaskCreateButton, and the shared glyph/TaskLine helpers across both modes.
- 3 new copy keys across zh/en/ja and the 18 third-language dictionaries.

Tests: the node-click spec now asserts the detail window (and that the jump
button inside it navigates), a new spec pins 'no nested control inside a
card', and two more cover the shared window: markdown-first view then
multi-line edit posting an 'edit' with the current revision, and immediate
owner reassignment. Full suite 1406 passed / 133 files.
2026-09-27 22:18:19 +08:00
Menghuan1918 e41f10afc9 feat(tasks-ui): tasks on their owner nodes, host-primitive controls, icon glyphs, draggable output
Round-two review feedback, all three points:

- TASKS ON NODES: the model maps each shared task (ownerName -> member name
  -> member session id) onto its owner's node; graph cards and tree rows
  render a fourth line (icon + subject + status + '+N'), and the node detail
  popover lists every owned task.
- TEAM BOARD: member Pills double as the owner filter; each task row is a
  status dot + subject + owner + status Tag + ONE overflow Menu (complete /
  reopen / edit / reassign submenu / delete with a two-step arm). Creating
  and editing moved into a real Modal with labeled Inputs and owner Pills —
  the narrow strip is no longer where you type.
- HOST PRIMITIVES ONLY: the board and the jobs drawer now use Menu / Modal /
  Input / Button / Pill / Tag / Switch / StateDot; no native select or input
  remains (guarded by a spec).
- ICONS, NOT HAND-DRAWN GLYPHS: every text glyph (circle/diamond/triangle/
  check/chevrons/i/house) is replaced by a host icon — agent preset, user
  (teammate), branch (workflow run), checklist (fold + tasks), tree corner,
  fullscreen (fit), ellipsis (node details), copy/stop (jobs). The live line
  now shows the tool's own icon + name + args without the drawn box.
- JOBS UX: the output popover is DRAGGABLE (offset clamped to the viewport,
  double click re-anchors, controls do not start a drag), defaults to 380px,
  and gains copy-output, a follow-latest switch, kind/status Tags and a drag
  hint; the drawer highlights the open row.
- 19 new copy keys across zh/en/ja and the 18 third-language dictionaries.

Tests: 4 new specs (task rendered on its node, no native select/input +
menu-driven board, create-through-dialog posts the CAS-free create, job
popover drag moves the card). Full suite 1404 passed / 133 files.
2026-09-27 22:18:19 +08:00
Menghuan1918 490e96080a fix(tasks-ui): postmodern chrome, working clicks, adaptive layout, lean cards
Review feedback from the live 3384 install, fixed at the root:

- COLORS: the new stylesheet used var(--dsw-alias-accent) in 17 places — a
  token the DSH theme does NOT define, so every declaration was dropped
  (older files only survived because they carry fallbacks); container edges
  used border-l1 (4% black, invisible). Accent now rides
  --dsw-alias-state-business-primary, container edges --dsw-alias-border-l4.
- CLICKS: the canvas called setPointerCapture on pointerdown, which
  retargets the derived click to the container and killed every node (and
  ⓘ) interaction; jsdom cannot see this, a real browser can. Capture is
  gone and panning only starts from the background.
- LAYOUT: fit gave up silently at zero container size and never retried,
  centered only horizontally, and capped at 100% while a five-child level
  scaled to 35%. Now: ResizeObserver + first non-zero fit, both axes
  centered, a 0.78 readability floor, and layoutTasksGraphForWidth picks
  the flattest sibling arrangement that still meets that floor.
- CARDS: title (one line) + mono meta + live line only; display title,
  team role, full model id and latest text moved into the ⓘ popover.
- PANEL: metrics follow the approved 360x660 mockup (132x46 cards, 112 row
  stride), explicit line-heights, user-select:none, horizontal control
  cluster with a labelled mode button, always-visible team board strip.
- Tokens for two new popover headings across all 20 dictionaries.

Tests: 3 new page-interaction specs (click after background pointerdown,
node gestures never pan, team board visible without a click) and a
rewritten 9-case layout suite (band wrap, row reservation, width solver,
reserved live row). Full suite 1400 passed / 133 files.
2026-09-27 22:18:19 +08:00
Menghuan1918 6448d8bad9 feat(client): workflow-graph Tasks page with teams board and jobs drawer
The Subagent page becomes the Tasks page per the approved Variant-D design:

- tasks-model.ts feeds BOTH modes from one pre-order node list: graph
  canvas (TasksGraph: layered nodes over bezier edges, drag-pan,
  wheel-zoom-to-cursor, phase frames, bottom-right control cluster) and
  the classic tree (TasksTree: keyboard navigable) — the view toggle and
  fold toggle stay reachable in both modes.
- Workflow runs (workflows.list) hang under their origin agent; member
  agents re-parent under the run node, missing ones synthesize from run
  data; completed leaf agents fold into per-parent aggregate nodes
  (click or cluster toggle to expand/re-collapse).
- Agent Teams (experimental): roster enriches nodes; a header chip opens
  the shared task board popover with basic CAS operations (complete /
  reopen / delete / reassign / create / edit); no experimental layer →
  the whole block hides (structural degradation).
- Background jobs move into a bottom drawer that auto-collapses at 8+
  agents (manual toggle wins); job output opens as an anchored popover
  (event replay, never the model's cursor); two-click kill preserved.
- Live activity lines render as glyph + tool + args (tool-icons map onto
  host primitive icons).
- Node click jumps to the transcript; ⓘ opens the detail popover;
  popovers follow the selection-popup dismissal contract (Escape /
  outside click / anchor off-screen via IntersectionObserver).
- tasksViewMode pref (graph default) with a select row in settings;
  58 new copy keys across zh/en/ja + 18 third-language dictionaries;
  dead CSS from the old tree/dock pruned.
- Tests: 6 new page-interaction specs (auto-collapse, both-mode toggle,
  jump, fold, popover); jobs-view suite re-pointed at the popover;
  prefs/builtins/smoke lock tests updated for the new pref.
2026-09-27 22:18:14 +08:00