Commit Graph
169 Commits
Author SHA1 Message Date
Menghuan1918 606339f81e chore(release): v0.22.0——任务管理页重做(工作流图)+ DSH 0.1.7 团队/后台任务数据面
版本号 bump 到 0.22.0(含 dsh.plugin.json 与 SIDEBAR_SERVICE_VERSION 两处镜像,
tests/manifest-consistency.spec.ts 与 tests/service.spec.ts 就是守这两处的),
README / README_EN 的版本徽章、支持线表格、npm 通道说明与「最近更新」段落同步,
CHANGELOG / CHANGELOG_EN 补 v0.22.0 条目正文。

支持线**不变**:仅 DSH 0.1.7-rc.1+(peer 下限 ^0.1.7-rc.1),0.21.1 用户可直接升级。
主内容是任务管理页从「子代理拓扑」重做为工作流图(图/树双视图、双段式节点卡、
主 Agent 同款合并活动行、扫光、两组折叠聚合、两个常驻浮动窗),以及随后按真机反馈
打磨的四轮修正;团队与后台任务两个数据面按 0.1.7 删掉的 Remote 方法/自建路由改写。

验证:typecheck / lint 通过;pnpm test 1288 passed / 9 skipped;build + pack 产出
dsh-better-sidebar-0.22.0.tgz。
2026-09-27 22:33:57 +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 421fd3fde7 fix(tasks): 小条的状态词与活动行统一字体(修掉 1px 基线错位)
用户反馈「运行中和正在分析请求没对齐」。实测是字体度量差异,不是布局:
两者行盒完全一致(11px/14px、align-items: center 下同一位置),但 11px 下
sans 字族的 fontBoundingBox ascent/descent 是 11/2,mono 字族是 10/3 ——
基线低 1px。中文在 mono 栈里本来就走同一个 CJK 回退(PingFang SC),
mono 只改到句中的拉丁片段,等于半句等宽 + 整体低一像素。

修法:.barActivity 不再声明 font-family,两段文字共用小条自己的字族;
机器文本的等宽语气保留在 meta 行 / 后台任务行 / 终端输出井。
theme.spec 新增守护(.barActivity 不得声明 font-family)。

真机证据:真实运行中卡片的小条(3× DPR 截图 17-bar-real.png)两段同处一行,
两个 span 的 font-family 计算值完全相同;此前同一小条 3× 截图里蓝字明显偏低。

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

(cherry picked from commit 6816af76828a436eaf201205e385c1aa4f77dcd5)
2026-09-27 22:18:57 +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 b554665bde feat(tasks-ui): readability pass, height-budget fix and leftover sweep
The native port is finished off with the readability work the earlier rounds
left open, plus the cleanup of everything the shadcn era or the older canvas
left behind.

- Geometry: node height is now composed from named parts (chrome, two title
  lines, meta row) and per-node extras, so a teammate card that carries a task
  line no longer gets clipped by the old fixed 68px budget; the layout spec
  follows the new model and GRAPH_ROW_STRIDE stays exported for it.
- Readability: row rhythm (28-32px), three ink levels for title/meta/owner,
  truncation with title hints, current-row and hover expressed as an accent bar
  plus a hover fill (no shadows), phase frames and edges back on the l1/l2
  hairlines, control cluster uniformly 28px, drawer durations on tabular
  figures, kill action revealed on hover/focus without shifting the row, no
  horizontal overflow at 360px.
- Task window: the markdown body is pulled onto the page scale (12px body,
  12/13px headings, tightened list indent and paragraph spacing) while the
  shared MarkdownText/markdownTextProps contract is untouched.
- Cleanup: dead stylesheet rules, unused TSX exports and helpers, stale
  comments that still described the retired Variant-D canvas, zero-reference
  i18n keys across the dictionaries, and the Tailwind/shadcn/Variant-D
  narrative in the design doc, AGENTS.md and the plugin guide (kept as one
  short "why it was rolled back" section).

Verified here: typecheck and lint clean; 133 files / 1413 tests; build with no
radix-ui or --tw- strings in lib/client.js (988.9 KiB); the 70-assertion
real-browser contract at 70/70 with the 20 reference screenshots regenerated;
mount e2e 7/7.
2026-09-27 22:18:19 +08:00
Menghuan1918 a71d158f9a revert(tasks-ui): drop the shadcn/Tailwind layer and return to the plugin's own UI system
shadcn's defaults are built for a standalone app: 14px body, 36px controls,
solid primary fills and elevation read as a foreign surface next to this
plugin's own tabs (files, changes, side chat, settings), which are 12/11/10px
type, 28px controls, hairline borders and flat panels. Retuning the layer did
not converge, so the layer goes.

- Removed: src/client/ui/** (21 vendored components), components.json,
  scripts/ui-css.mjs, the Tailwind/PostCSS compile step in tsdown, and the deps
  tailwindcss / @tailwindcss/postcss / postcss / radix-ui /
  class-variance-authority / tailwind-merge. (diff and simple-icons stay: they
  patch undeclared bare imports of the host primitives, unrelated to shadcn.)
- The seven page surfaces are back on the plugin's own base: *.module.css with
  --dsw-* tokens plus the host primitives (Button/Menu/Modal/Pill/Tag/Switch/
  Input/Tooltip/StateDot/MarkdownText). Behaviour, data-* hooks, aria labels,
  i18n keys and the AnchoredPopover geometry/drag/dismiss contract are
  unchanged; the non-styling fixes landed during the shadcn era (model id
  dedupe, task-window CAS, drawer arming, popover dragging, the chunk packaging
  glob) were re-applied and are covered by the existing specs.
- The tasks page returns to the core bundle: `tasks` left CHUNK_NAMES /
  CHUNKS / ChunkName, src/client/chunks/tasks.tsx is gone and tabs.tsx imports
  SubagentView directly.
- The reverted stylesheet was retuned to the plugin's measured vocabulary
  (12/11/10px, 28px controls, border-l2 with border-l1 hairlines, hover fills,
  no static shadows, --dsw-shadow-lv2/3 on floating layers only) and verified
  against a 70-assertion real-browser contract; the harness's own two
  measurement defects were fixed with a falsification test proving the
  assertions still catch injected regressions (56/70, 14 FAIL).
- Tests: ui-foundation / ui-bundle / ui-shadows (the shadcn guards) deleted,
  theme.spec scoped back to the plugin's own stylesheets, bundle-route and
  manifest-consistency chunk lists back to four. Docs: AGENTS.md and the plugin
  guide drop the Tailwind/shadcn guidance; the design doc marks those sections
  superseded and records why the layer was removed.

Verified: typecheck/lint clean; 133 files / 1410 tests; core bundle 987.3 KiB
with no radix-ui/--tw-/tailwind strings and no client-tasks.js; mount e2e 7/7;
20 real-browser screenshots at 360/720 for graph, tree, board, task window,
drawer (including armed), both popovers and the 77-node fixture.
2026-09-27 22:18:19 +08:00
Menghuan1918 5deb5285da refactor(tasks-ui): align the page with the latest shadcn/ui defaults
The previous round kept a hand-trimmed, shadow-less, 11-13px variant of the
component set. This replaces it with the registry's own defaults and the
registry's own composition primitives, keeping only the adaptations this host
actually requires.

Registry refresh (npx shadcn@latest add --overwrite): the whole vendored set is
back to upstream sources, plus label, field, input-group, item and button-group.
Re-applied adaptations (documented in the design doc):
- cn from ./utils and explicit ./x.tsx specifiers (the registry writes virtual
  aliases this repo has no resolver for);
- host IconXxx instead of lucide (skin contract);
- no dark: variants (the DSH tokens already flip) and no palette literals;
- React.forwardRef on Button (the host is React 18, so radix Slot needs it);
- tw-animate-css animation utilities stripped: installing that dependency would
  inject generic keyframes into a page we do not own.
Restored to stock: the full Button variant/size set, shadow-xs on outline,
transition-all, badge ghost/link.

Recomposition on the newest primitives (per-file, verified here):
- board: full Card composition, Item rows, ToggleGroup filter, dropdown items
  grouped, Empty for the empty state;
- task window: Card composition, FieldGroup/Field with data-invalid validation,
  ToggleGroup owner (default variant: the outline variant's hover and pressed
  states measured identically, hiding the selection), destructive-armed delete,
  FieldError for conflicts;
- popovers: both portal cards use the same Card composition, rows are Item;
- drawer/header: Item rows with ItemActions, Separator bands, Spinner, Empty;
- graph/tree: stock node recipe, outline buttons, cn() for conditional classes.

Two no-preflight traps found by rendering, not by types:
- stock Empty ships border-dashed without a width, so the UA's 3px medium dashed
  frame wrapped the whole page: border-0 on that Empty;
- <Spinner size={12}/> stayed type-clean after the refresh (size is a valid span
  attribute) while the glyph silently rendered at size-4: className="size-3".

Verified: typecheck/lint clean; 136 files / 1515 tests; build with the core and
chunk bundle guards (core 836.3 KiB, chunk 734.7 KiB); mount e2e 7/7; and the
real-host-stylesheet mirror page re-shot for graph, tree, board, task window and
the 77-node stress fixture at 360 and 720.
2026-09-27 22:18:19 +08:00
Menghuan1918 d1a9d520ae fix(tasks-ui): restore the scoped preflight subset and return the page to stock shadcn
Real-device report: the Tasks page "looks like it has no CSS at all, with
blurry borders". Two hypotheses were falsified before the real cause surfaced:
the sheet IS delivered (the chunk carries both the CSS and its injector, and
the bundle route serves it) and the cascade is NOT the problem (with the real
host stylesheet plus the real compiled sheet, a controlled sample keeps our
padding, radius, border, background and font; host CSS-module selectors only
match host nodes, and its global element rules are element-level specificity).

The cause is what we deliberately excluded: PREFLIGHT is also what normalizes
form controls. Measured on a plugin icon button that sets only an icon size,
the UA chrome survived as padding 1px 6px, border 2px outset, background
ButtonFace (#efefef) and a 13.33px system font - gray beveled buttons with a
soft double border, i.e. "no CSS".

- ui/theme.css: a .dsw-tasks-scoped preflight subset (zero margins/padding,
  border width+style, background, appearance none, inherit color/spacing,
  cursor rules) inside @layer base, written with :where() so it stays at
  (0,1,0) and utilities in the later layer still win; plus an explicit
  "@layer theme, base, components, utilities;" statement - layer order follows
  first appearance, and without it the utilities import registered utilities
  BEFORE base, so the reset beat rounded-md (measured: square buttons). The
  built chunk's order was re-checked: properties, theme, base, components,
  utilities.
- Stock shadcn restyle: static cards carry stock shadow-xs/shadow-sm again
  (floating layers keep shadow-lg), body/meta text is text-sm/text-xs instead
  of 11-13px, status uses stock Badge variants, controls use stock Button
  variants and sizes, row actions appear on hover/focus while staying keyboard
  reachable, node cards are 176x68 with shadow-xs.
- bandColsFor budgets columns at the readability floor (width / 0.78) instead
  of 1:1, so a 360px panel keeps two columns; FIT_MIN_SCALE moved into the
  layout module as GRAPH_FIT_MIN_SCALE so the fit and the column budget share
  one constant.
- Guards: tests/ui-foundation.spec.ts pins the scoped reset declarations and
  the layer-order statement; tests/ui-shadows.spec.ts now allows shadow-xs and
  shadow-sm on static panels and bans md and above; the theme guard's inert
  paint rule forced the reset to spell border-width/border-style instead of the
  "border: 0 solid" shorthand.

Verified: typecheck and lint clean; 136 files / 1505 tests; build with the
core/chunk bundle guards; mount e2e 7/7 (mount 444ms, longtasks 2 of 8); the
visual mirror page (real host stylesheet + real components) re-shot at 360 and
720 for graph, tree and the 77-node stress fixture.
2026-09-27 22:18:19 +08:00
Menghuan1918 e94da2d4e4 fix(ci): keep the mount lane on 0.1.5-rc.2 (alpha.2 pin fails on unmodified main)
Pinning the lane to 0.1.6-alpha.2 makes plugin-mount fail deterministically:
the shell boots into the new-session empty state, no session scope reaches the
sidebar, and [data-dsh-better-sidebar] [title] never attaches
(mount.e2e.ts:216 plus perf.e2e.ts:182). Falsified against this branch with a
probe: origin/main + that one-line pin, run 35484961070, same red, zero plugin
changes involved.

So the dev tree keeps alpha.2 (the line the maintainer's desktop runs) while
the lane stays on the released pin; the evidence and the follow-up (teach the
lane to activate the seeded session on the alpha line) are recorded in
AGENTS.md §2/§3 and docs/plans/2026-09-17-dsh-0.1.6-alpha.2-adaptation.md.
2026-09-27 22:18:19 +08:00
Menghuan1918 221e955c6b fix(sidechat): keep the rc line's reconnect label via a documented shim
0.1.6-alpha.2 removed ConnectionIndicator's reconnectLabel, but the peer range
(^0.1.5-rc.1) still covers the rc line, where the prop is REQUIRED and renders
the retry button's hover/focus action text. Widening the component type once
keeps both lines correct: rc renders the label, alpha.2 ignores the extra key.
The shim carries a comment naming the condition for deleting it.
2026-09-27 22:18:19 +08:00
Menghuan1918 3e4da566d8 chore(deps): pin devDeps/CI to DSH 0.1.6-alpha.2 (peer range unchanged)
The maintainer's desktop already runs the 0.1.6-alpha line while the plugin
pinned 0.1.5-rc.2 (latest/next still point there). The peer range stays
^0.1.5-rc.1, so rc.1/rc.2 users are unaffected.

Upstream delta that actually touches this plugin (primitives .d.ts diff plus a
full scan of bare imports in its lib/**/*.js):

- IconSendOutline16 was removed (the only icon drop) -> IconSendOutline14.
- TerminalBlockLabels gained a REQUIRED noExitCode label -> new
  sideChatBlockNoExitCode copy across all 20 dictionaries.
- ConnectionIndicator dropped reconnectLabel -> prop removed.
- Menu/Modal changed only in docs/keyboard semantics; new exports
  (Checkbox/isDarwinDesktop/MarkdownDelegateProvider) are additive.
- dsh-tools no longer peers on dsh-code-runtime, and that package was never
  published at alpha.2 -> its devDependencies hoist is removed instead of
  mixing an rc.2 package into an alpha.2 tree.
- the primitives bundle still declares zero dependencies but now bare-imports
  'diff' (DiffBlock) and 'simple-icons' -> hoisted as diff@^9.0.0 (matching the
  host) and simple-icons@^15.0.0; missing them failed six jsdom suites at
  vite's import-analysis stage.

Verified: pnpm install + peers check clean; typecheck/lint 0; 136 files /
1503 tests; build green with the core/chunk bundle guards; mount e2e 7/7 on
0.1.6-alpha.2 (longtasks 2/8, and /sidebar/bundle/tasks.js really downloads).

Also recorded: origin/main is an ancestor of this branch (nothing to rebase in
git terms), and README's published-version wording is left to release time.
2026-09-27 22:18:19 +08:00
Menghuan1918 f6cf73c4cf feat(tasks-ui): migrate the Tasks page to shadcn/ui (Tailwind v4 + radix, lazy chunk)
Visual base replacement for the Tasks page after the 'hard shadows make a
dense graph unreadable' review. Behaviour, hooks, aria labels and i18n are
unchanged; the base layer is not.

- FOUNDATION: Tailwind v4 wired into tsdown's css-inline plugin (theme +
  utilities ONLY — preflight is excluded because the plugin's stylesheet is a
  global <style data-plugin> tag and would repaint the host page), shadcn
  tokens bridged to --dsw-* so the DSH theme keeps flipping light/dark with no
  dark: overrides, cn() util, components.json for the CLI, src/client/ui/.
- COMPONENTS: shadcn's component source vendored into src/client/ui (button,
  card, badge, separator, input, textarea, tooltip, popover, dropdown-menu,
  scroll-area, collapsible, toggle-group, skeleton, spinner, empty) with a
  documented local diff: lucide-react replaced by host IconXxx (no new icon
  dep), shadow-* dropped from non-floating variants, unused variants pruned,
  and React.forwardRef restored on Button — the host runs React 18, where
  radix's Slot cannot hand a ref to a plain function component (dev warns,
  production silently mis-anchors the floating layer).
- SHADOWS: static panels are now hairline + surface tiers with hover:bg-muted;
  shadows exist only on floating layers. Settled nodes recede by ink
  (text-muted-foreground/foreground-3) instead of opacity.
- DENSITY: node cards widened 132 -> 150px with a two-line clamped title
  (13px text in a 132px card left ~7 CJK characters), reserved height 46 -> 60.
- CHUNK: the whole page (graph, tree, task window, board, drawer, shadcn/radix
  layer and its stylesheet) moved into the lazy 'tasks' chunk. Core bundle
  988.5 -> 835.6 KiB (-153 KiB); the 709.8 KiB UI payload loads only when the
  Tasks tab opens.
- MODEL: workflow members whose childId is already a real node elsewhere are
  no longer synthesized into a duplicate id (React keys/edges), with a
  last-resort per-id dedupe.
- GUARDS: tests/ui-foundation.spec.ts, tests/ui-bundle.spec.ts (core/chunk
  split + size budget + no preflight/oklch/lucide), tests/ui-shadows.spec.ts,
  extended tests/theme.spec.ts (no colour literal / palette class in
  src/client/ui/** and the migrated files).
- REVIEW FIXES: portal popovers re-scoped under .dsw-tasks, graph loading
  state, 11px floor, error nodes no longer tint a whole border, TeamBoard's
  delete item is neutral (the window owns the two-step confirm).

Verified: typecheck / lint / 136 files 1502 tests / build bundle assertions /
mount e2e 7-7; browser harness 65-65 checks with 0 console errors.
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 317299e161 docs(plans): record verification results for the tasks page rework 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 b1bfaf8730 docs: tasks page redesign plan + README/guide sync
- docs/plans/2026-09-14-tasks-graph-workflow-teams-design.md: data-source
  facts, degradation matrix, tradeoffs, and the implementation-deviation
  record (diagnostics banner, mount-e2e desktop-shim pitfall, portal
  assertions).
- README feature list/table + external-plugin-guide tab registry row now
  describe the workflow-graph page, team task board, and jobs drawer.
- guideDescSubagent reworded in zh/en/ja (third-language retranslations
  follow separately).
2026-09-27 22:18:19 +08:00
Menghuan1918 ab2246da47 chore(release): cut v0.21.1 as the stable adapter for DSH 0.1.7-rc.1
The rc.1 adapter first went out as 0.21.0-rc.1, but DSH 0.1.7-rc.1 is
upstream's release batch, so the plugin that targets it must not sit on a
prerelease channel. Re-cut it as v0.21.1: the version is now free of `-`,
so release.yml publishes it under npm's `latest` instead of `alpha`.

Version literals only — package.json, dsh.plugin.json and
SIDEBAR_SERVICE_VERSION (tests/service.spec.ts still pins the last two
together). No code change: the peer floor stays ^0.1.7-rc.1 and the
support line stays "DSH 0.1.7-rc.1 and later".

Docs follow the channel move: README/README_EN/guide drop the "alpha
channel" framing, the install command becomes @latest, and every older
DSH line now gets an explicitly pinned command in the version table
(@0.19.1 and so on) because `latest` no longer covers them. The rc.1
design record keeps its history and gains a §8 for the re-cut.
2026-09-23 23:58:59 +08:00
Menghuan1918 6805ab51a2 docs: record the 0.1.7-rc.1 adaptation and resync the user docs
New design record `docs/plans/2026-09-23-dsh-0.1.7-rc.1-adaptation.md`
(method, the version-bump-only delta, the code-card break and the mermaid
regression it exposed, the over-yield recovery, the live 3080 upgrade with
its boot-log findings, and the evidence — including the note that the
mount lane first ran against a stale tarball because `e2e_resolve_tarball`
picks the newest existing one instead of packing).

AGENTS.md §3 gains the rc.1 rules: the boot-time peer preflight (a new
§3.4 item 12) with its four gotchas, the vendor hoist lesson, and the
code-card/toolbarLabels contract. Two claims are corrected while we are
here: the guide's four-entry description cap was attributed to rc.1 but
`GuideBody.tsx` and the host's terminal guide entry are byte-identical
across alpha.1 / alpha.2 / rc.1, and the icon surface is 25 named imports
plus a type-only `IconProps`, not 26.

README / README_EN / guide: version, badges, peer floor, the pinned-DSH
advice (`alpha` is now 0.1.7-alpha.2 while rc.1 rides `next`), the reduced
refusal list, and the correction that npm `latest` is 0.1.5-rc.3.
2026-09-23 22:36:05 +08:00
Menghuan1918 97ef21fe09 docs: record the live 3080 upgrade findings (profile artifacts, install short-circuit, dead disabled-plugins.json) 2026-09-22 17:37:25 +08:00
Menghuan1918 6586e3e2d3 feat: adapt to DSH 0.1.7-alpha.1 and yield the read-only previews
DSH 0.1.7-alpha.1 is 1299 commits past 0.1.6-alpha.2 and rewrites four
contracts this plugin was built on. The peer floor moves to
^0.1.7-alpha.1 (semver's prerelease rule means ^0.1.6-alpha.2 can never
match a 0.1.7 prerelease); 0.1.6-alpha.2 and earlier stay on v0.19.1.
Released as 0.21.0-alpha.1 (dist-tag alpha).

Hard breaks:
- dsh-settings was rewritten: register(ns, schema) is gone, a form is
  addressed by the plugin row's Loader entry id and read from the
  module's exported Config. The preferences are merged into Config and
  marked volatile — which requires DSH's own schemastery, because only
  that build wraps a volatile field in the cosmokit reference the
  loader's volatile commit walks. With the public package a settings
  write reports success and revision 1 while the effective value never
  changes.
- ui-primitives renamed its whole icon family (IconXxx14/16 ->
  IconXxxRegular/Medium): 26 imported symbols, 17 files. The failing
  mode is render-time, not load-time. Five call sites that relied on the
  old 14px default now pass size={14} explicitly.
- Session format v4 rejects source.kind === 'plugin'; the side-chat
  boundary injection now writes plugin:dsh-better-sidebar, the same kind
  DSH's own v3->v4 migration produces, so historical threads survive.
  Tool results moved to role 'tool' with top-level content/isError; all
  four parsers accept both shapes.
- The client session snapshot dropped subagentsByParent/jobsBySession
  and the on-demand subagent-catalog observation API. The Tasks page
  reads projectionsBySession and a new jobs.list route.

Yields and convergence:
- The read-only previews go to DSH's documentpreview (Office->PDF, a
  spreadsheet worker, zoom, per-directory refresh); editor.canOpen
  refuses those 26 extensions. Markdown, HTML (with its sandbox
  switches) and the editable code buffer stay.
- The host browser kind is desktop-profile-only now, so the web e2e
  lanes expect no browser entry and assert its absence.
- Link takeover claims only urlTarget links and passes the rest to the
  host, fixing a regression from the 0.1.6 round: the fallback pointed
  at a 'browser' type the plugin no longer registers, so http links in
  its own markdown did nothing.

Also fixed, found along the way:
- The file tree refreshes live (new directory watch over the plugin's
  own socket), since the plugin owns the `files` kind.
- ctx.sessions.list has no `current` field at either tag; the three
  readers were dead. They now use ctx.sidebarRight.mounted.
- package.json.files was missing lib/client-locale.js.
- Two genuinely dead call sites: sessions.openSubagent/open/
  refreshSubagents do not exist on the current baseline, so the
  topology click, the jump-back and the retry were all no-ops.
- The test harness window shim lacked addEventListener, which the 0.1.7
  primitives call at module-evaluation time; and the e2e token exchange
  needs Playwright's request stack, not Node's fetch.
2026-09-22 17:09:08 +08:00
Menghuan1918 de99fd4cfb docs: record the 0.1.6-alpha.2 adaptation and resync the user docs
Adds the per-version adaptation record (docs/plans/2026-09-21-…-adaptation.md),
rewrites AGENTS.md §3 for the new baseline (the two silent contract breaks, the
terminal/browser handoff, the new official plugin-manager surface, the three
ui-primitives breaks, the widened primitives bare-import set), and updates both
READMEs and the integration guide for the v0.20.0 feature set.

Also retires the support text the terminal deletion made false: the install
flow is one step again (no build-script approval), the FAQ's two node-pty rows
collapse into one pointing at DSH's own terminal, the platform note no longer
promises prebuilt native binaries (there are no native deps left), and the
installers drop the -Repair mode and their allowBuilds writes along with
pnpm-workspace.yaml's now-empty allowBuilds block. Removes the dead
browserNoSandboxWarning locale key (its setting went with the plugin's browser)
and tightens theme.spec's capsule guard so a literal colour fails it.

The e2e resolver now refuses a PATH  that is not on the baseline line:
this machine's PATH  is 0.1.6-alpha.1, and running the mount lane against
it fails at 'the bundle was not registered' with a zero exit from the CLI —
a misleading dead end worth one explicit error instead.
2026-09-21 21:00:09 +08:00
HuanLinOTO 5e15942449 docs: scope the createTab seed-ignore rule to the bottom workbench
Copilot review: the openTab JSDoc claimed createTab descriptors ignore
title/path/id, but that is only the bottom-workbench landing (the
factory mints the tab wholesale there). On the native right Sidebar the
seed fields are forwarded as navigation params (createTab values as
defaults, seed wins) and only the id is host-minted. State both
landings so consumers do not drop path seeds.
2026-09-11 21:19:00 +08:00
HuanLinOTO d6a816a374 fix(native): keep component tabs' path seeds on the page open (#632)
The native openTab branch rerouted EVERY path seed into openResource (a
dsh-resource://file/... open) without looking at seed.type, so any
component tab opened with a path landed in the editor (the only
dsh-resource://file/** claimant) and its registered component never
mounted. This also contradicted the guide, whose TabDescriptor/openTab
contract and WebDocsView example document path-seed component tabs.

Route by type instead: only the editor kind (the only registration with
dsh-resource://file/** patterns) turns its path seeds into resource
opens; every other kind keeps the page open and carries the path in the
navigation params, which NativeTabRecords.ensure already merges back
onto the synthetic record's tab.path for the component. The bottom
workbench path is untouched, editor opens behave exactly as before, and
onOpen still receives the synthetic tab with the path seed.
2026-09-11 21:12:15 +08:00
Menghuan1918 238ba52ab9 docs(plans): backfill the merge, release and icon-PR wrap-up for v0.19.1 2026-09-11 16:58:29 +08:00
Menghuan1918 d725e54608 docs(plans): record the outline revert (only the terminal size was asked for) 2026-09-11 16:20:58 +08:00
Menghuan1918 0c18e492cf docs(plans): record the icon rework feedback and the green single-fork Windows runs 2026-09-11 15:59:13 +08:00
Menghuan1918 1ef2192a44 docs(plans): record the two green single-fork Windows runs 2026-09-11 15:53:06 +08:00
Menghuan1918 4fe67e3965 fix(ci): run the Windows suite in a single fork (the bounded pool was not enough)
The `--maxWorkers=2` fix from the previous commit was falsified by real CI:
run 34574847774 still ended with `[vitest-pool]: Worker forks emitted error /
Worker exited unexpectedly` while reporting 126 of 127 files passed and zero
FAIL lines. The worker that died was the one running
tests/native-surface.spec.ts — it produced NO results at all, which is the
same shape as the two earlier crashes (125/126 and 123/124: N-1 files
reported plus a silent worker exit at teardown).

So the consistent signature across all four crashes is a worker-recycling
race, not a test failure. `test:windows` now runs the whole suite in ONE fork
(`--maxWorkers=1`), which removes recycling entirely; the cost is wall-clock
(14 s -> 41 s locally, and the Windows step stays well inside its 30-minute
budget) and the signal is unchanged. Retries are still deliberately not used —
they would hide a real regression instead of removing the race.

The CI comment now records both Windows failure classes with their evidence,
so the next person can tell what this flag is for.
2026-09-11 15:43:22 +08:00
Menghuan1918 6317dde7c0 docs(icons): record the host-artwork decision and update the rules that cite it
- docs/plans/2026-09-11-file-icons-and-tab-glyphs.md: the design record —
  what the two stacked PRs did, the measured upstream facts that made their
  colored implementation redundant (rc.2's `FileTypeIcon`/`CodeFileIcon` with
  the host's own palette, the classifier never returning a folder, the native
  tab definition having no icon field while its title slot IS the chip), the
  three merge conflicts and how each was resolved, what was deleted, the
  catch-all semantics change, and the verification evidence.
- docs/plans/2026-09-10-dsh-0.1.5-rc.2-adaptation.md: cross-link it from the
  change table.
- docs/external-plugin-guide.md: the file-icon fallback chain now ends at the
  host's artwork, with the catch-all caveat spelled out; §12 loses its "one
  exemption" paragraph entirely — the plugin draws no color of its own any
  more (file icons are host pixels, tab glyphs ride tokens).
- AGENTS.md §5: replaces the icon-theme exemption with the two new rules
  (file-icon chain + catch-all hazard, and where the colored tab glyphs live
  plus the fact that the native chip glyph is drawn by the plugin inside the
  host's title slot).
- README.md / README_EN.md: the v0.19.1 entry gains the icon section
  (#611 / #531 / #594) with the dataset deletion and the new public API.
2026-09-11 15:32:07 +08:00
Menghuan1918 a4e94c976e Merge the file-icon theme shell from #594 (feat/file-icon-theme)
Brings in the theme plumbing around #531's API — the `fileIconTheme` pref
thread, the settings row, the 20 dictionaries' keys and the theme loader's
test — so the working tree is a complete, green starting point before the
colored implementation is replaced.

Conflicts (three; resolved by taking this line's side where it had moved on):

- src/client/service.ts: the import block keeps `baseName, extOf` (the
  `isNarrowWidth` import the theme branch needed belongs to its own
  fresh-session seeding, which main has since rewritten) and the feature-list
  doc comment keeps main's "v0.19.0 REMOVED 'floatWindows'" note while
  adopting the sharper `fileIcons` wording (matched by exts / names /
  folderNames).
- tests/plugin-shape.spec.ts and tests/prefs.spec.ts: main DELETED the store
  seeding tests these files used to hold and rewrote the schema assertions
  (the `SIDEBAR_PREFS_DEFAULTS` destructuring), so this line's side wins —
  the theme branch's re-added blocks describe behaviour main no longer has.

Next commit removes `fileIconTheme` again along with the 563-entry dataset and
its lazy chunk: DSH 0.1.5-rc.2 exports the official `FileTypeIcon` artwork, so
the plugin renders the host's icons instead of shipping its own color table.
2026-09-11 15:14:47 +08:00
Menghuan1918 1d05e39be2 Merge the file-icon API from #531 (feat/file-icons-api) into the rc.2 line
Brings in the plugin-side file-icon feature (issue #611): the public
`registerFileIcon` API plus the resolver chain the tree, the editor tab and
the external-plugin surface all read.

Conflicts (three, all comment/list unions — resolved by union, verified green):

- src/client/service.ts: main's "v0.19.0 REMOVED 'floatWindows'" note stays
  (the capability is gone and must not come back); the feature list gains
  'fileIcons'.
- src/client/Sidebar.tsx: one comment above `tabIconOf`; both sides' wording
  is kept (the editor-with-path special case and the descriptor fallback).
- docs/external-plugin-guide.md: the `features` list comment keeps main's
  "additive only, the one exception being floatWindows" wording plus the new
  'fileIcons' entry.

Notes on what this merge does NOT bring in: #594 (feat/file-icon-theme) is
stacked on this branch and lands next, but its colored-theme implementation
(563-entry react-icons dataset in a 255 kB lazy chunk plus a `fileIconTheme`
switch) is being replaced — DSH 0.1.5-rc.2 exports the official
`FileTypeIcon`/`CodeFileIcon` artwork from ui-primitives, so the plugin does
not need to ship its own color dataset.

Gates on the merge result: pnpm typecheck clean, pnpm test 127 files /
1331 passed / 9 skipped.
2026-09-11 15:09:32 +08:00
Menghuan1918 d5bbb52c89 docs(plans): record the two consecutive green Windows runs (rc.2 baseline)
ci-windows is green twice on 5451f5c — the PR-triggered run 34561189320 and a
follow-up workflow_dispatch run 34561457067, both 126 files / 1318 passed /
3 skipped with zero `Unhandled Errors` and zero `Worker exited unexpectedly`
(the window that motivated this work saw two of the latter). plugin-mount is
green twice as well: `added 521 packages in 24s` with no ERESOLVE lines
against 3062 in the historical OOM run, mount smoke 7 passed, aggregate lane
passed.

Also records the falsification this PR went through — the first cut still
failed on real CI in two places (the third 5000 ms default victim,
tests/git.spec.ts:85 at 9607 ms, and `--legacy-peer-deps` breaking the CLI
install with ERR_MODULE_NOT_FOUND) — and states plainly that two green runs
do not prove the worker-death root cause, only that it stopped reproducing
once concurrency was bounded and the timeout budgets were corrected.
2026-09-11 12:18:34 +08:00
Menghuan1918 5451f5c699 fix(ci): raise the global testTimeout and drop --legacy-peer-deps (real-CI feedback)
The first run of this PR against real Windows and real npm found two things
the local macOS pass could not:

1. ci-windows lost a THIRD file to vitest's 5000 ms default —
   `tests/git.spec.ts:85` ("caps status entries at the truncation limit")
   took 9607 ms building a pathological untracked set with real git calls.
   Three different files (git / powershell / agent-pty), one root cause, so
   per-file timeouts were whack-a-mole: vitest.config.ts now sets a global
   `testTimeout: 15_000`. The two heaviest suites keep their own 30 s budgets
   and a genuinely hung case still fails.

2. `--legacy-peer-deps` made the mount lane's CLI install broken instead of
   robust: it skips exactly the peers a global install has to supply, and
   `@deepseek-ai/cordis-plugin-group` — required at boot by
   `@deepseek-ai/dsh-app-boot` — is a peer, not a dependency, so the CLI died
   with ERR_MODULE_NOT_FOUND (`Cannot find package
   '@deepseek-ai/cordis-plugin-group'`) before the smoke could start. The
   flag is removed; the pin to a fully-published rc.2 (no ETARGET) plus the
   4 GB heap (no resolver OOM) is the whole fix.

Verified locally: a plain `npm install -g @deepseek-ai/dsh@0.1.5-rc.2` into a
scratch prefix (with NODE_OPTIONS=--max-old-space-size=4096) resolves the peer
(`dsh/node_modules/@deepseek-ai/cordis-plugin-group` present), that CLI reports
0.1.5-rc.2, and `DSH_CMD` pointed at it runs the mount lane green — 7 passed.
`pnpm test` stays green with the new timeout: 126 files / 1312 passed / 9 skipped.

Docs (plan §C, AGENTS.md §2, both READMEs' v0.19.1 entries) record the rejected
middle step and why, so nobody re-adds it.
2026-09-11 12:10:16 +08:00
Menghuan1918 62c83ff611 docs(plans): record the 3080 deployment (plugin 0.19.1 on DSH rc.2) with route evidence 2026-09-11 12:03:53 +08:00
Menghuan1918 112f151c04 docs(plans): link PR #626 and record the local rc.2 mount-smoke evidence 2026-09-11 12:03:07 +08:00
Menghuan1918 787cff4319 docs(plans): add the DSH 0.1.5-rc.2 adaptation and CI-failure plan 2026-09-11 12:02:45 +08:00
Menghuan1918 e567bf6924 docs: record the rc.2 baseline (README badges, guide, AGENTS, plan)
- docs/plans/2026-09-10-dsh-0.1.5-rc.2-adaptation.md: the adaptation plan —
  the upstream rc.1 -> rc.2 delta per affected area, why there is no
  plugin-side code change, and the CI failure taxonomy (A real Windows
  timeouts, B the two silent worker deaths, C the mount lane's npm
  ETARGET/OOM) with the evidence and the fix for each.
- AGENTS.md §2/§3: CI pins rc.2, the mount lane's npm flags and their reason
  (floating transitives + staged prerelease publishing), the Windows lane's
  bounded pool and why, and the primitives-dependencies note extended to rc.2.
- README.md / README_EN.md: support badge (v0.19.1, verified on rc.2), the
  install section's stable-release note (rc.1 hosts need no upgrade — the peer
  floor is unchanged) and a v0.19.1 changelog entry covering the two CI fixes.
- docs/external-plugin-guide.md: baseline line -> v0.19.1 / DSH 0.1.5-rc.1+,
  verified on rc.2.
- Comment-only: `DSH 0.1.5-rc.1` -> `0.1.5-rc.1+` where the note describes a
  behaviour that arrived in rc.1 and is unchanged in rc.2 (native guide
  description rendering, in src/client/native/index.ts, src/client/service.ts
  and the three specs that assert it).
2026-09-11 12:02:44 +08:00
Menghuan1918 7f2674ab70 docs+test: 对齐等待 banner 的注释/设计口径并钉住 skip-wait 的 404 契约
v0.19.0 发版前 review 发现两处「文档与实现互相矛盾」(均不改运行时行为):

- use-host-feeds.ts 的 effect 注释仍写「terminal tab 类型禁用时 pushes are
  ignored」,而 mirrorAgentWaits 恰恰改成了不忽略(只跳过 tab 增删 reconcile)。
  注释改为如实描述;
- 设计文档 §1 写「轮询每圈优先检查 skipped」,实现是 aborted → exited →
  skipped。维持实现现状(pty 已死是客观事实,两种顺序下用户可见结果——banner
  消失 / skipWait 归零 / 等待结束——完全相同,只有 kind 文案不同),设计原文
  同步为「退出优先」,并在实施偏差记录写清未采纳「用户意图优先」的理由与日后
  改动点;
- src/index.ts 的 agent-pty.skip-wait 注释把「无活动等待 → 0」泛化成了
  「幂等」,收窄为「无活动等待返回 {skipped:0};未知 uuid 走 expect → 404,
  客户端 .catch 容忍并等下一次推送收敛」。

另把 skipWait 未知 uuid 的既有断言从「只校验 /not found/ 文案」升级为
「SidebarError + status 404 + code not-found」——HTTP 层 writeError 直接把
status 映射成响应码,此前这条契约没有测试守护(把 404 改成 410 时新断言即
失败,已验证)。

验证:pnpm test 126 files / 1312 passed / 0 failed,tsc --noEmit 与 eslint
均 exit 0;改动面仅 5 个文件,src/client/service.ts、builtins/ 与
external-plugin-guide.md 继续零改动。
2026-09-10 22:26:02 +08:00
HuanLinOTO 22a0452a59 Merge origin/main into feat/wait-banner: resolve use-host-feeds import overlap
Conflict: src/client/sidebar/use-host-feeds.ts
- ours: import { mirrorAgentWaits, ... } from '../state.ts'
- theirs: same line + new import { isNarrowWidth } from '../breakpoints.ts'
Resolution keeps both imports; the two sides' semantic changes are in
disjoint regions (ours: tab-disabled wait mirroring; theirs:
activateTasksPage native-landing) and both survive intact.
2026-09-10 22:04:13 +08:00
HuanLinOTO 70a150794b fix: address Copilot review round 3 (code-point truncation, a11y live status, disabled-tab wait mirroring, test unmount, concurrent-wait test) 2026-09-10 21:28:22 +08:00
HuanLinOTO ccb89fd91b Merge origin/main into feat/wait-banner: resolve floats retirement + openTabInBottomPane 2026-09-10 18:21:09 +08:00
Menghuan1918 17db3cf014 docs(plans): record the auto-activation landing regression
The v0.19.0 regression, its root cause in 223b254, the four decisions
(native landing, narrow-viewport park, jump-back always expands, bottom
workbench keeps its own flows), the change list, and the evidence — including
the environment trap that the PATH `dsh` on this machine is 0.1.2-rc.1 and
cannot register the `file:` tarball into a scratch profile.
2026-09-10 17:13:32 +08:00
Menghuan1918 a0bbfa0089 docs(plans): record the rc.1 merge and v0.19.0 release 2026-09-10 14:54:19 +08:00
Menghuan1918 725b2f7cec feat(dsh): adapt to DSH 0.1.5-rc.1 and restore the guide description
Baseline moves to DSH 0.1.5-rc.1 — the 0.1.5 line's first release
candidate, and the npm `latest` dist-tag now: peer floor ^0.1.5-rc.1,
devDependency pins, the CI mount-lane pin and dsh.plugin.json engines
all follow. 0.1.5-alpha.2 users stay on v0.19.0-alpha.1.

The upstream delta from alpha.2 is small: 373 changed files, mostly
version bumps, sidebar preview polish and test snapshots. Exactly two
changes touch this plugin, and only one needs work:

- `SidebarRightGuideEntry.description` is back (optional). The native
  guide renders it only while it lists at most 4 entries; a longer list
  drops every description. The plugin restores `TabDescriptor.description`
  and the six built-in `guideDesc*` lines (20 dictionaries) verbatim from
  0b6ac5d^, but deliberately does NOT restore the old generic
  `nativeGuideDesc` fallback: the host has no fallback of its own, so a
  descriptor that declares none now ships no `description` field at all
  and renders as a clean title-only capsule.

  Consequence worth knowing: the plugin contributes six guide entries, so
  the default composition is over the 4-entry limit and shows titles only.
  The mount lane proves the restored field end to end by shrinking the
  enabled set to three types through the plugin's own settings route
  (scratch profile only) and requiring the Files capsule to grow its line.

- The built-in `files` type declares a guide description again and uses a
  coloured folder glyph; the plugin owns that kind, so nothing to do.

Verified unchanged from alpha.2 (so nobody re-checks them): the global
main-panel model, the file address grammar (util/workspace-path changed
only its package.json), the native tab-body host contract (.paneBody is
still a block scroller with a definite height), the core/agent/session/
subagent host APIs and the ui-primitives export surface.

Restore caveat fixed in the lane: the settings route merges patches
key-wise, so undoing a temporary `tabsEnabled` change by posting the
original (empty) map leaves the disabled keys behind — the e2e restores
every key it touched explicitly.
2026-09-10 14:41:16 +08:00
Menghuan1918 036a747c80 docs(plans): record the alpha.2 merge and v0.19.0-alpha.1 release 2026-09-10 00:14:45 +08:00
Menghuan1918 bec90212f5 docs(plans): record the alpha.2 verification evidence 2026-09-09 23:17:13 +08:00
Menghuan1918 0b6ac5d267 feat(dsh): adapt to DSH 0.1.5-alpha.2
Baseline moves to DSH 0.1.5-alpha.2 only (peer floor ^0.1.5-alpha.2,
CI pin, manifest engines); alpha.1 users stay on v0.19.0-alpha.0.

Host-contract changes handled:
- the native guide entry lost its `description` field (entries are
  icon+title capsules now): `TabDescriptor.description` and the six
  `guideDesc*` keys plus the `nativeGuideDesc` fallback are removed.
- the file address grammar changed: `fileAddressFor` always returns a
  session-scoped address (absolute paths keep their leading `/`),
  `parseFileAddress` is prefix-based and strips `?`/`#`. The plugin's
  purity-gated mirror follows.
- global main panels replaced the `conversation` root slot with the
  keyed `main` slot (`main.conversation`): the bottom workbench's
  center-column locator now accepts both keys and skips
  `display: contents` slot hosts.

Fixes a pre-existing fill bug the alpha.2 probe made obvious: the native
tab body host is a block scroller with a definite height, so tab roots
that only declared `flex: 1` collapsed to content height and the side
chat composer drifted off the pane bottom. The native adapter now wraps
every tab body in a `height: 100%` column flex host.

Also promotes the dependencies `dsh-client-ui-primitives@0.1.5-alpha.2`
dropped from its manifest (anser / shiki / mdast-util-* / micromark-* /
katex / @shikijs/langs) and the newly unmet `dsh-session-persistence`
peer into devDependencies.
2026-09-09 23:09:48 +08:00