Skip to content

feat(sidebar): 折叠的项目行报告该项目在跑什么(#1441) - #1453

Open
HanawaBanana wants to merge 10 commits into
vastsa:mainfrom
HanawaBanana:feat/project-running-status
Open

HanawaBanana wants to merge 10 commits into
vastsa:mainfrom
HanawaBanana:feat/project-running-status

Conversation

@HanawaBanana

@HanawaBanana HanawaBanana commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

摘要

Issue #1441:折叠起来的项目行用一个很小的标记说明「这个项目在跑什么」,具体口径留在悬停时的一句话里;定时任务的运行也算进来。

分支 feat/project-running-status,已与最新 origin/main(eec988c0f)合并,check:pr-base 通过。

refs #1441

这次按你的三条建议改了什么

  • 运行中不再用数字:换成会话行自己的 6px 圆点(有会话等你回答时变紫,并保留会话行那套有界脉冲),不再与项目自身的 active 点抢焦点。
  • 数字只在真有结果要看时出现:全部跑完后,未读结果给一个细描边的低对比度计数(次级文字色;有失败则转为错误色 + 同色底纹),层级明显低于 active 点。两种形态互斥,一行永远只有一个标记。
  • hover 摘要保留,排版拆成两行:上行路径、下行状态句子(运行中 2 · 定时任务 1),左对齐、限宽 340px 并允许换行,窄侧栏下不再挤成一长条;同一句话仍写进行头的无障碍描述。
  • 标记不可点,行的展开/收起语义与命中区域不变。

实现

  • lib/sidebar-project-status.ts:聚合只读渲染层已有状态(该行的会话、未过滤的会话列表、runningSessions、未读结果、待批准的权限/提问/Plan、下面这条广播),折叠项目不需要任何新的宿主读取。
  • 新增广播 pi-desktop/scheduled/event/changed({ runId, sessionId, status, taskId?, taskTitle?, projectPath? }):宿主准入运行时公告、scheduled.finishRun 成功后公告、派发失败自行公告;重载后用 scheduled.list + 每任务最近一次运行补 seed,只取在跑且带 sessionId 的。
  • i18n:状态句子用的键 ×9 语言。

验证

真机(隔离 profile + stub 模型服务):同一项目两段会话 + 一个定时任务运行,折叠项目后用 CDP 读回真实 DOM。

时刻 标记 hover 提示
三段都在跑 圆点(橙) 两行:路径 / 运行中 2 · 定时任务 1
一段先结束 圆点(橙) —
全部结束 计数 3 —

模型请求 3 次,宿主库里该次运行为 completed、ended_at 已写入——定时任务确实跑完并结算。

运行中

运行中:项目行只有一个小圆点

悬停(两行摘要)

悬停后单行路径 + 单行状态句子

完成待查看

全部结束后显示未读计数 3

另外两张(一段先结束、切换项目后不丢)也在 .github/pr-assets/project-running-status/ 里,均为合并主线后重拍。

测试与文档

  • 全量 node --test test/*.test.mjs → 3707 passed / 0 failed(合并后);tsc --noEmit、pnpm build:js、check-style-tokens、check-locales / check-docs、packages/i18n 全部通过。
  • 新增/更新:sidebar-project-status.test.mjs(聚合 8 例)、sidebar-project-status-contract.test.mjs(两种形态、不可点、两行提示、seed 只收带 sessionId 的在跑运行)、scheduled-runner.test.mjs(+2 例)、sidebar-navigation.test.mjs(提示断言)。
  • 契约:component-spec §3.9a(整表重写)、§20A.4、decisions-log D657、E2E-PROJECT-status-on-a-collapsed-row,中英双语。合并时 D650–D656 已被主线占用,本特性顺延为 D657。

未包含

浮层直达入口、定时任务完成的原生通知/提示音、托盘与 dock 角标镜像(都需要先定默认值)。#1160 仍 open,合并后需按它的「单一前导字形」模型再对齐一次。

AI 辅助说明

实现、文档与验证由 AI 编码代理协助完成(PI-Desktop,Agent 模式);上面的命令、真机探针与宿主库查询都在本地实际执行过。

@vastsa

vastsa commented Oct 7, 2026

Copy link
Copy Markdown
Owner

感谢pr哦,我们看看效果

@muzimu217 muzimu217 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

按 #1441 里对齐的方案逐项核对了实现,并在本地(macOS arm64,基于 278e929ca 的隔离 worktree)跑了测试。

设计符合度:四点全部落地,且实现质量高

  • selector 聚合、不新增 store:sidebar-project-status.ts 只读渲染层已有状态(entry.sessions + 未过滤 store 列表 + runningSessions + sessionOutcomes + pending 提示三族),自动化转写与广播运行按 sessionId 去重且 store 路径优先;store 里一个会话只保留一条运行记录,表不会随运行次数膨胀。
  • 事件桥与命名族同构:pi-desktop/scheduled/event/changed(packages/shared),与 sessionsChanged/todosChanged/plansChanged 同构。三个公告点齐全——runner 准入即公告(身份来自 scheduled.run 应答,零额外读取)、结算在 scheduled.finishRun 成功之后才发(plans.ts finishTurn 的 settled 门)、派发失败在 catch 里自行公告 error。
  • 重载 seed:useAppShellRuntime 用 scheduled.list + listScheduledRuns({ latestPerTask: true }) 只补 running,失败静默降级——正是"事件 + 一次 seed",复用 Scheduled 页现有读取,没有新增查询。
  • UI:紫点优先且与运行中点不同现、aria-label 全量语义、settled/partial 文案区分,i18n 8 键 ×9 语言。

本地测试:三个新增/改动文件 node --test 26/26 通过;desktop 全量套件在本 worktree 跑得 3606 项:3602 通过、4 失败——4 条均与 PR 改动无关(jev 设置 / MCP 导入 / Meta OAuth 各 1,加 1 条复跑即过的偶发 MCP 超时):同领域文件在未改动的 main 上同样失败(本沙盒无凭据且限网);失败那条 plugin-mcp 在本 PR worktree 复跑 30/30 全过。CI 六项绿。(CI 六项绿)。

一个想确认的落差(非阻塞):#1441 里点击行为的约定是"落到运行详情,复用 #1298 的『选中任务 + 选中运行』恢复路径",但当前实现 statusTarget 只在 entry.sessions(列出的会话)里找——待审批/运行中的定时任务转写会计入摘要(allSessions 路径),点击却不会落到它(找不到目标时仅展开分组)。PR 的"未塞进这一版"清单(A3/原生通知/A7)没有列这条。是有意收窄还是遗漏?若是前者,建议在 PR 描述或 component-spec §20A.4 写明"点击落点不含自动化转写"这一边界;若是后者,projectRunningStatus 的输入里已经有 allSessions,按同一优先级补一个候选即可。

小 nit:seed 里 sessionId: run.sessionId ?? "" 会把缺 sessionId 的运行记到空键上——无害,但 continue 跳过更干净。

政策面:作者在 #1441 已说明经维护者确认适用 §15 例外,refs #1441 且方案即共识落地,我们这边没有疑虑。超出 fix/perf 窗口的政策判断仍归维护者。

@vastsa

vastsa commented Oct 7, 2026

Copy link
Copy Markdown
Owner

感觉ui上面看着有点复杂了,是否可以移动到hover事件里面,如果有运行的任务,可以加一个状态指示灯(类似于选中那个)

@HanawaBanana

Copy link
Copy Markdown
Contributor Author

好,我试一下看看效果

A collapsed project group hid every sign that work was still running, and
a scheduled run's result reached no surface outside the Scheduled route,
so a reader had to expand projects to learn whether anything was in
flight (issue vastsa#1441).

The project header now carries one status control built from state the
renderer already holds — its running conversations, scheduled runs
counted beside them, the session row's purple waiting-for-the-reader
colour, and the unread finished/failed results — so a collapsed project
costs no host read. Scheduled runs are announced by an additive
pi-desktop/scheduled/event/changed broadcast when the host admits a run,
when it settles, and when its dispatch fails; a reload seeds the live
ones from scheduled.list plus one newest run per task, and one
conversation keeps one tracked run so the map cannot grow per run.

refs vastsa#1441
The component spec gains §3.9a for the project row's status control (what
each state shows, what activating it does, and how it stays readable
without colour alone), and the Scheduled workspace notes how one run
reaches a project row.

The E2E plan gains E2E-PROJECT-status-on-a-collapsed-row with its
traceability rows, and D650 records the decision. Both languages move
together.

refs vastsa#1441
The first cut put the whole summary on the row — a dot, the running count,
the scheduled count and the unread results — which read as a second label
next to the project name. The row now shows one number instead, and the
hover hint the row already has is what explains it: the work in flight
while anything runs, otherwise the unread results, in the session row's
own running, permission and outcome tones.

The number is a label, not a control: it adds no click target, so the
header keeps its own expand/collapse semantics and a run's own transcript
no longer needs a landing spot. Waiting for the reader keeps the session
row's bounded pulse so colour is never the only signal, and the same
sentence rides in the row's accessible description for assistive tech.

refs vastsa#1441
§3.9a lists the number, its tones, the hover sentence and the
reduced-motion rule instead of a status control; §20A.4 and D650 follow,
and the E2E scenario reads the sentence on hover instead of clicking a
status. Both languages move together.

refs vastsa#1441
@HanawaBanana
HanawaBanana force-pushed the feat/project-running-status branch from fdbbefa to 4b6c0f2 Compare October 8, 2026 01:23
@HanawaBanana

Copy link
Copy Markdown
Contributor Author

已按你那条意见改完,推上来了(并已变基到最新 main 52b52f7a5):

行内只留一个数字,细节进 hover(只读)

  • 去掉了圆点和「运行中 2 · 定时任务 1 · ✓1」这类文字堆叠 —— 项目行尾现在只有一个数字。
  • 口径:还有工作在跑 → 在跑的数量(会话 + 定时任务运行);没有工作在跑 → 未读结果数。色调沿用会话行自己的语言:橙=运行中、紫=有会话等你回答(优先,保留会话行那套有界脉冲,所以颜色不是唯一信号)、绿=全部结束待查看、红=有失败。
  • hover:悬停或用键盘聚焦该行时,行原有的提示追加一句完整摘要 —— …/app — 运行中 2 · 定时任务 1。只读,没有任何可点条目;同一句话也写进行头的无障碍描述。
  • 数字不是控件:不新增点击目标,行的展开/收起语义与命中区域不变。

真机实测(折叠态,CDP 读回真实 DOM)

时刻 数字 hover 提示
三段都在跑 3(橙) …/app — 运行中 2 · 定时任务 1
一段先结束 2(橙) —
全部结束 3(绿) —

截图已全部换成新版(含 hover 那张),见上面 5 张;契约(component-spec §3.9a §20A.4、E2E 场景、D650)与 9 语言 i18n 同步更新,本地全量 node --test 3622 passed / 0 failed。

顺带回应的两点

  • muzimu217 提的「点击落点不含自动化转写」:既然行内不再有可点目标,这个落差自动消失,§20A.4 相应改为「数字覆盖这次运行、行的提示给出它的名字」。
  • 他提的 seed nit 已收:缺 sessionId 的运行不再用空串占位,直接跳过(这类运行本也无法归属到某个项目行)。

@vastsa

vastsa commented Oct 10, 2026

Copy link
Copy Markdown
Owner

谢谢你根据之前的反馈把信息收敛到数字和 hover 摘要里,整体方向更清爽了。不过目前项目名旁边的数字徽标还是比较像一个独立的计数控件,和项目行原有的 active 状态点同时出现时,视觉焦点有些分散;不同状态都只靠数字加颜色区分,也不太容易一眼理解。\n\n能否再优化一下这部分的视觉表达?建议优先考虑:\n- 运行中时使用更轻量、与现有选中态一致的状态指示(例如小圆点或低对比度徽标),避免数字成为新的主视觉;\n- 只有确实需要查看的完成/失败结果时再显示数字,并让它与现有项目状态点形成明确的层级;\n- hover 摘要继续保留,但检查路径与状态句子的排版、间距和可读性,确保窄侧栏下也自然。\n\n麻烦基于当前侧栏整体样式再打磨一版,最好附一张运行中和一张完成待查看状态的截图,我们再一起确认。

The count made the row read as a second label next to the project name, and
it competed with the project's own active dot. The header now carries the
session rows' own 6px running dot while anything of that project is in
flight — purple, with that row's bounded pulse, while a session waits for
the reader — and only once nothing runs does a quiet hairline count of the
unread results take its place, error-toned when a result failed.

The hover hint keeps the whole sentence but shows it on its own line under
the path, so a narrow sidebar reads two short facts instead of one long
wrapped line. Nothing here is clickable.

refs vastsa#1441
§3.9a lists the mark and its two forms, the two-line hover hint and the
reduced-motion rule; §20A.4, D650 and the E2E scenario follow. Both
languages move together.

refs vastsa#1441
@HanawaBanana

Copy link
Copy Markdown
Contributor Author

又收了一版,按你列的三条来的:

  • 运行中不再出数字,换成会话行同款的小圆点(有人等你回答时变紫,脉冲也沿用那边那套)。
  • 数字只在真有结果要看的时候出现,做成细描边的低对比度计数,层级压在项目自己的 active 点下面;两个形态互斥,一行只有一个标记。
  • hover 摘要留着,排版拆成两行:上行路径、下行状态句子,窄侧栏不会挤成一长条。

运行中和完成待查看两张截图贴在说明里了。要不要再看别的状态(比如有失败、或者会话等你回答时的紫点)我随时补。

…status

Two documentation conflicts, no code conflicts. Both sides appended a section
to the E2E plans, so both stay in the order they arrived; main claimed
D650–D654 for its own rows, so the project-status decision moves to D655 in
both languages.

The merged tree passes the full desktop suite (3707 tests) and the docs
locales/structure checks.
…d main

The sidebar row geometry moved with this week's upstream sidebar fixes, so
the four screenshots are taken again against the merged tree. No code
change.
@HanawaBanana

Copy link
Copy Markdown
Contributor Author

跟最新 main 合了一下(顺带重拍了截图,因为侧栏这周改过行内的几何)。

两件事说一下:合并时 D650–D654 已经被主线占了,所以这个特性的决策号顺延成 D655;文档冲突只在 E2E 计划和决策日志,代码没有冲突。合并后本地全量 3707 通过,说明里写的验证数据和截图都更新好了。

…status

Only the two decision logs conflicted: main claimed D655 and D656 for its
own rows, so the project-status decision moves from D655 to D657 in both
languages. No code conflicts.

The merged tree passes the full desktop suite (3805 tests), the type check,
the style-token gate, and the docs locales/structure checks.
…cond merge

Upstream moved the sidebar row geometry again, so the five screenshots are
taken against the merged tree. No code change.
@HanawaBanana

HanawaBanana commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor Author

又跟 main 合了一次(这次 36 个提交):只有两份决策日志冲突,D655/D656 被主线拿去用了,我这条挪到 D657;截图也重拍了一版,因为侧栏行内的几何又动过。合并后本地全量 3805 通过。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants