dsh-workspace-status 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,19 +1,59 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0 — 2026-10-25
4
-
5
- ### Added
6
-
7
- - First public release: coloured status marks on workspace rows (waiting, running,
8
- recently finished) with locale-aware labels and a settings toggle.
9
- - Declares `dsh.catalog` so plugin markets place it under UI with a real summary.
10
-
11
3
  All notable changes to this package are documented here. The format follows
12
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
13
5
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
14
6
 
15
7
  ## [Unreleased]
16
8
 
9
+ ## [0.3.0] - 2026-10-26
10
+
11
+ ### Added
12
+
13
+ - Pinned-only notifications. The pinned section watches the live status of
14
+ pinned conversations and notifies on transitions: a pinned conversation
15
+ starts waiting for you (approval, plan review or question) or finishes
16
+ unread. Running → idle with an unread completion fires once; repeated
17
+ renders, kind changes and late unread states are deduplicated, and the
18
+ first observation after a reload stays silent.
19
+ - Desktop/OS notifications when the window is in the background, plus in-app
20
+ notices inside the pinned section so a focused window still surfaces the
21
+ event. Clicking a row-shaped notice opens that pinned conversation; notices
22
+ auto-dismiss after eight seconds or via the close button.
23
+ - A bell toggle in the pinned section header turns pinned notifications on or
24
+ off and requests notification permission on first use; a speaker toggle
25
+ enables an optional two-note chime. Both preferences persist in browser
26
+ storage. The bell falls back to in-app notices when the OS blocks
27
+ notifications, and enabling notifications shows a one-off test notice.
28
+ - Notifications are only emitted for transitions while the app is running;
29
+ they are not external push and do not notify sessions outside the pin set.
30
+
31
+ ## [0.2.0] - 2026-10-26
32
+
33
+ ### Added
34
+
35
+ - Pinned conversations section above the Workspaces list. Pinned conversations
36
+ are lifted out of the regular workspace groups and rendered per workspace
37
+ with the shipped folder-header treatment, their live status dot, relative
38
+ time, current-session highlight, group counts and a filled pin icon on every
39
+ row. Clicking the pin unpins immediately.
40
+ - Section and group collapse state persisted in browser storage; the section
41
+ caps its height and scrolls independently.
42
+ - The section is driven by the registry-global `pinnedSessionIds` Workspace
43
+ feed, so pins survive restarts and stay in sync with the official browser;
44
+ unpin uses `ctx.workspaces.unpinSession`, opening a row uses
45
+ `ctx.uiWorkspace.openSession`.
46
+ - Pinned rows are hidden from the official grouped/flat tree with generated
47
+ `display:none` rules; search-result rows are untouched.
48
+
49
+ ### Changed
50
+
51
+ - Component now renders a React portal into a container inserted before the
52
+ sidebar browsing region, in addition to the emitted row stylesheet. The
53
+ official Workspace browser is still not replaced.
54
+ - The workspace-mark mount now always publishes the stylesheet and portal
55
+ anchor, so pins added while mounted appear without a reload.
56
+
17
57
  ## [0.1.0] - 2026-10-25
18
58
 
19
59
  ### Added
@@ -29,3 +69,4 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
29
69
  - Zero-fork implementation: an additive `sidebar.footer.action` entry that
30
70
  publishes row CSS keyed on `data-row-key="workspace:<id>"`, with no DOM
31
71
  writes, observers or host services.
72
+ - Declares `dsh.catalog` so plugin markets place it under UI with a real summary.
package/README.md CHANGED
@@ -1,13 +1,30 @@
1
1
  # dsh-workspace-status
2
2
 
3
- Colored status marks on the **workspace rows** of the DeepSeek Harness sidebar:
4
- waiting for you, running, and just finished.
3
+ [![npm](https://img.shields.io/npm/v/dsh-workspace-status?label=npm&color=blue)](https://www.npmjs.com/package/dsh-workspace-status)
4
+ [![npm provenance](https://img.shields.io/badge/npm%20provenance-SLSA%20v1-brightgreen)](https://www.npmjs.com/package/dsh-workspace-status)
5
+ [![test](https://github.com/Stijnus/dsh-workspace-status/actions/workflows/test.yml/badge.svg)](https://github.com/Stijnus/dsh-workspace-status/actions/workflows/test.yml)
6
+ [![license](https://img.shields.io/npm/l/dsh-workspace-status)](LICENSE)
7
+
8
+ [English](./README.md) · [中文](./README.zh-CN.md)
9
+
10
+ Sidebar upgrades for DeepSeek Harness:
11
+
12
+ 1. **Workspace status marks** — colored status on the workspace (folder) row:
13
+ waiting for you, running, and just finished, aggregated from the sessions
14
+ inside it.
15
+ 2. **Pinned conversations section** — conversations pinned through the shipped
16
+ pin action leave the regular workspace groups and appear in a dedicated
17
+ section above the browsing region, grouped per workspace with the same
18
+ header treatment and a pin icon on every row.
19
+ 3. **Pinned notifications** — when a pinned conversation starts waiting for
20
+ you or finishes unread, the plugin can raise a desktop notification (when the
21
+ window is in the background) and always shows an in-app notice in the pinned
22
+ section. Bell and chime toggles sit in the section header.
5
23
 
6
24
  Harness draws a status dot on every conversation row, but nothing on the
7
- workspace (folder) row above it. Collapse a group, or scroll it out of view, and
8
- the folder row cannot tell you that an agent inside is stuck waiting for an
9
- approval or still working. This plugin gives the folder row the same kind of
10
- mark, aggregated from its sessions:
25
+ workspace row above it. Collapse a group, or scroll it out of view, and the
26
+ folder cannot tell you that an agent inside is stuck waiting for an approval or
27
+ still working. This plugin gives the folder row the same kind of mark.
11
28
 
12
29
  | Mark | Meaning | Color |
13
30
  |---|---|---|
@@ -21,6 +38,86 @@ for expanded and collapsed groups alike, and its state is described to
21
38
  screen-reader users in a hidden sentence ("Workspace activity: 2 running, 1
22
39
  waiting for you — api, web").
23
40
 
41
+ ## Pinned conversations
42
+
43
+ Pinning is the shipped Harness action (row hover button or the row **…** menu).
44
+ Once a conversation is pinned:
45
+
46
+ - its row is lifted out of the regular workspace groups and listed in a
47
+ **Pinned** section between the global panel rows and the **Workspaces**
48
+ header;
49
+ - the section is grouped per workspace, each group using the same 34px folder
50
+ row, blue active-folder color, disclosure triangle and radius as the shipped
51
+ browser, with a small count at the end;
52
+ - every pinned row shows its live status dot, relative time, current-session
53
+ highlight, and a filled **pin icon** at its trailing edge; clicking the pin
54
+ unpins the conversation immediately — no restart, and it reappears in its
55
+ workspace group;
56
+ - the Pinned header and each workspace group are collapsible, and that state is
57
+ remembered in browser storage;
58
+ - the section caps its height and scrolls on its own, so a large pin set cannot
59
+ push the browsing region away;
60
+ - the pin set is the registry-global `pinnedSessionIds` feed, persisted by the
61
+ Host in the profile workspace registry — after relaunch the same pins come
62
+ back and the section renders again;
63
+ - search is untouched: pinned conversations still appear in search results,
64
+ while the regular grouped/flat tree hides the lifted rows.
65
+
66
+ The pinned rows are hidden from the regular tree with generated
67
+ `display:none` rules. The workspace header itself stays (so its *New session*
68
+ action remains reachable), which means a workspace whose sessions are all
69
+ pinned may read as an empty group under **Workspaces** while its sessions sit in
70
+ the Pinned section.
71
+
72
+ ## Pinned notifications
73
+
74
+ The bell in the Pinned header (next to the count) controls notifications; the
75
+ speaker enables an optional two-note chime. Both preferences persist in browser
76
+ storage and default to **notifications on, sound off**.
77
+
78
+ What fires an event:
79
+
80
+ - a pinned conversation **starts waiting for you** — approval, plan review or a
81
+ question (the notification names the reason and workspace);
82
+ - a pinned conversation **finishes unread** — a running session stops and its
83
+ completion mark is still unread.
84
+
85
+ Only transitions fire, only for pinned conversations. The first observation of
86
+ a session after mount is silent, so reloading the app does not replay old
87
+ events; repeated renders of the same waiting state are quiet, while a change of
88
+ reason (approval → question) is a new event. Finished fires once per run.
89
+
90
+ Delivery:
91
+
92
+ - when the window is in the background and the platform has granted
93
+ notification permission, a **desktop/OS notification** is raised — clicking it
94
+ focuses the app and opens that conversation;
95
+ - an **in-app notice** is always added inside the pinned section (also when the
96
+ OS blocks notifications), with a status icon, title and reason; click it to
97
+ open the conversation or dismiss it with **×**. Notices auto-dismiss after
98
+ eight seconds.
99
+
100
+ The first click on the bell requests notification permission and shows a
101
+ one-off test notice. If the OS denies or blocks notifications, the plugin falls
102
+ back to the in-app notices and the bell tooltip says so. Notifications are
103
+ client-side only: they fire while the app is running and are not external push
104
+ (no email, IM or web push), and sessions outside the pin set never trigger
105
+ them.
106
+
107
+ ## Quick start
108
+
109
+ ```sh
110
+ dsh plugin --profile web add dsh-workspace-status
111
+ ```
112
+
113
+ Restart the Harness (or refresh the Web UI). Workspace rows gain a colored status
114
+ mark; pin a conversation to see the Pinned section and its bell/speaker
115
+ controls.
116
+
117
+ <sub>More from this suite: [Moodboard](https://github.com/Stijnus/dsh-moodboard) · [Composer Predictions](https://github.com/Stijnus/dsh-composer-predictions) · [Move to Workspace](https://github.com/Stijnus/dsh-move-to-workspace) · [Workspace Status](https://github.com/Stijnus/dsh-workspace-status) · [Prompt Rewrite](https://github.com/Stijnus/dsh-prompt-optimizer)</sub>
118
+
119
+ <sub>⭐ If this saves you a step, a star helps the next DSH user find it.</sub>
120
+
24
121
  ## Preview
25
122
 
26
123
  ![Four sidebar rows: api waiting (amber dot), web running (blue ring), docs recently finished (green dot), sandbox idle (no mark)](docs/preview-mock.png)
@@ -29,7 +126,7 @@ This is the plugin's own stylesheet rendered over a local reproduction of the
29
126
  sidebar row DOM and theme tokens — a design preview, not a live screenshot. The
30
127
  shipped app draws the same marks on the real rows.
31
128
 
32
- ## Rules
129
+ ## Rules for workspace marks
33
130
 
34
131
  - **Precedence matches the shipped session row:** waiting for the user beats
35
132
  running, which beats the finished reminder. A workspace therefore shows one
@@ -48,12 +145,13 @@ shipped app draws the same marks on the real rows.
48
145
  updated time only.
49
146
  - **Ungrouped sessions** mark the "Ungrouped" bucket row, which behaves like a
50
147
  workspace row in the sidebar.
51
- - **No mark when everything is idle.** The plugin renders nothing at all in
52
- that case — no stylesheet, no hidden text.
148
+ - **No mark when everything is idle.** The plugin renders nothing visible in
149
+ that case — no mark and no hidden activity sentence.
53
150
 
54
151
  The active workspace (the one containing the open conversation) is already
55
- marked natively: Harness paints the folder icon of the active chain blue. This
56
- plugin does not duplicate that.
152
+ marked natively: Harness paints the folder icon of the active chain blue. The
153
+ Pinned section mirrors that color on the group header that contains the current
154
+ conversation.
57
155
 
58
156
  ## Install
59
157
 
@@ -85,6 +183,8 @@ profile's patch layer.
85
183
 
86
184
  ## Verify
87
185
 
186
+ Workspace marks:
187
+
88
188
  1. Start a session in a workspace and collapse that group while it runs — a
89
189
  blue ring appears at the end of the folder row.
90
190
  2. Trigger an approval (or a plan review / question) in a session of another
@@ -93,42 +193,86 @@ profile's patch layer.
93
193
  hour later.
94
194
  4. Expand the group: the mark stays on the folder row; the session rows keep
95
195
  their own dots unchanged.
96
- 5. With every session idle, no extra element appears in the sidebar.
97
196
 
98
- The client half writes nothing into the sidebar DOM — it reacts to the public
99
- Workspace/Session feeds and emits CSS keyed on the row the browser already
100
- renders. If the mark is missing, check the browser console for a failed client
101
- bundle load first; nothing else in the sidebar is affected.
197
+ Pinned section:
198
+
199
+ 1. Pin any conversation from its row hover button or **…** menu — the Pinned
200
+ section appears above **Workspaces** without a restart, grouped under that
201
+ conversation's workspace, with a filled pin icon on the row.
202
+ 2. Pin a conversation from a second workspace — a second group header appears;
203
+ both groups keep the workspace header treatment and their own count.
204
+ 3. Click a pinned row — the conversation opens. Click the pin icon — the row
205
+ disappears from the Pinned section and returns to its workspace group
206
+ immediately.
207
+ 4. Collapse the Pinned header or a group — the state persists across reloads.
208
+ 5. Restart the Harness — the same pins are listed again, because the Host
209
+ persists the registry pin set in the profile workspace registry.
210
+
211
+ Pinned notifications:
212
+
213
+ 1. Click the bell in the Pinned header. On first use it requests notification
214
+ permission and shows a test notice; the bell is highlighted while enabled.
215
+ 2. Pin a conversation that is running, then let it finish without opening it —
216
+ an in-app notice appears in the Pinned section; if the app window is in the
217
+ background, a desktop notification is raised as well. Clicking either opens
218
+ the conversation.
219
+ 3. Trigger an approval, plan review or question in a pinned conversation — the
220
+ notice names the reason and workspace and remains until dismissed.
221
+ 4. Click the bell again to turn notifications off, or the **×** on a notice to
222
+ dismiss it early. Reload: the bell, speaker and notification preferences
223
+ persist.
224
+
225
+ If the plugin is missing, check the browser console for a failed client bundle
226
+ load first; nothing else in the sidebar is affected.
102
227
 
103
228
  ## How it works
104
229
 
105
- - The mount is an entry in the additive `sidebar.footer.action` seat. It renders
106
- only a `<style>` element and a visually hidden `<span>`; it is not a control
107
- and adds nothing visible at the foot.
108
- - Aggregation reads the same public data the browser uses: `useWorkspaces`
109
- (`items`, `archivedSessionIds`), `useSessions` (`byId`) and
230
+ - The mount is an entry in the additive `sidebar.footer.action` seat. It
231
+ publishes a stylesheet, a visually hidden activity description, and a portal
232
+ anchor; it adds no control of its own at the foot.
233
+ - Workspace marks read the same public data the browser uses: `useWorkspaces`
234
+ (`items`, `archivedSessionIds`, `pinnedSessionIds`), `useSessions` (`byId`) and
110
235
  `useSessionStatus` (`running`, `pendingInteraction`, `completionUnread`).
111
- - The visible mark is the workspace row's trailing pseudo-element, emitted as a
236
+ - The workspace mark is the folder row's trailing pseudo-element, emitted as a
112
237
  rule targeting `[data-row-key="workspace:<id>"]::after`.
113
- - Removing the plugin removes the mount, which removes the stylesheet; no state
114
- is written anywhere.
115
-
116
- ### The one internal dependency
117
-
118
- `data-row-key="workspace:<id>"` is an internal detail of
119
- `@deepseek-ai/dsh-client-ui-workspace`, not a public slot contract. A future
120
- Harness release could rename it, in which case the marks would silently stop
121
- appearing until this package is updated. The failure mode is deliberately
122
- **"no indicator"**, not "broken sidebar": the plugin never touches the DOM, so a
123
- stale selector can only produce a missing dot.
238
+ - The Pinned section is rendered through a React portal into a container
239
+ inserted immediately before the sidebar's `regionArea` element. The official
240
+ browser is not replaced: search, menus, drag ordering, dialogs and directory
241
+ picking stay native.
242
+ - Pinned rows are lifted by hiding their `[data-row-key="session:<id>"]` rows
243
+ with generated CSS (`display:none!important`); search-result rows carry no
244
+ `data-row-key`, so they remain visible.
245
+ - Unpin calls `ctx.workspaces.unpinSession(id)`; opening a pinned row calls
246
+ `ctx.uiWorkspace.openSession(id)`. The pin set itself comes from the
247
+ Workspace snapshot, so both the official tree and this section stay in sync.
248
+ - Collapse memories and notification preferences live in browser
249
+ `localStorage`; no plugin settings are written. Notification delivery uses the
250
+ renderer's standard `Notification` API (and Web Audio for the optional chime);
251
+ the plugin does not add a host service.
252
+ - Removing the plugin removes the mount, the stylesheet and the inserted
253
+ section container; no profile or session data is changed by the plugin.
254
+
255
+ ### Internal dependencies
256
+
257
+ Two details belong to `@deepseek-ai/dsh-client-ui-workspace` / `ui-sidebar`
258
+ rather than a public slot contract:
259
+
260
+ - `data-row-key="workspace:<id>"` / `session:<id>` for row targeting;
261
+ - the `…_regionArea` class token for the portal insertion point.
262
+
263
+ A future Harness release could rename either; the failure modes are
264
+ deliberately **"no mark / no section"**, not "broken sidebar": the plugin never
265
+ replaces the browser and its DOM writes are limited to one inserted container.
266
+ `react-dom` is a shared client platform module (the same baseline the shell
267
+ seeds for every bundle), used only for the portal.
124
268
 
125
269
  ## Compatibility
126
270
 
127
271
  - DeepSeek Harness `>=0.2.1-rc.2 <0.3.0-0` (developed and verified against
128
272
  `0.2.1-rc.3`); Web and Desktop clients.
129
273
  - Node `>=22.18.0` for the build-free package and its tests.
130
- - No runtime dependencies, no host services, no settings, no model-visible
131
- tools or prompt changes.
274
+ - No host-side services, no settings, no model-visible tools or prompt changes.
275
+ Pins are the shipped Workspace registry pin set.
132
276
 
133
277
  ## Development
134
278
 
@@ -139,8 +283,10 @@ npm test
139
283
  The suite loads the classic-script client envelope in a sandbox, drives the slot
140
284
  component with fake standard hooks, and asserts the emitted stylesheet and
141
285
  hidden description across waiting/running/finished, subagent, archived,
142
- ungrouped, expiry and selector-escaping cases. A manifest test checks the bundle
143
- patch, export map, locale parity and the loader envelope.
286
+ ungrouped, expiry, pinned grouping (workspace order, ungrouped bucket, archived
287
+ / blank / subagent exclusion), hide rules, pin precedence and selector
288
+ escaping cases. A manifest test checks the bundle patch, export map, locale
289
+ parity and the loader envelope.
144
290
 
145
291
  There is no build step: `index.js` and `client.js` are the published artifacts.
146
292
 
@@ -150,7 +296,9 @@ There is no build step: `index.js` and `client.js` are the published artifacts.
150
296
  dsh plugin --profile <profile> remove dsh-workspace-status
151
297
  ```
152
298
 
153
- Restart the Host. The sidebar returns to stock; nothing else is left behind.
299
+ Restart the Host. The sidebar returns to stock; the inserted section container
300
+ is removed with the plugin, and pins remain the shipped workspace registry
301
+ state (unpin them through the normal pin action).
154
302
 
155
303
  ## License
156
304
 
@@ -0,0 +1,83 @@
1
+ # dsh-workspace-status · 工作区状态与置顶会话
2
+
3
+ [English](./README.md) · [中文](./README.zh-CN.md)
4
+
5
+ 为 DeepSeek Harness 侧边栏增加三层能力:
6
+
7
+ 1. **工作区状态标记**:在侧边栏的**工作区(文件夹)行**上显示彩色状态——等待你处理、正在运行、刚刚完成,由该工作区内的会话聚合而来。
8
+ 2. **已置顶会话区**:通过 Harness 原生置顶操作置顶的会话,会从常规工作区分组中提取出来,显示在工作区列表上方的独立区域;按工作区分组,沿用原生工作区行的样式,并在行尾显示置顶图标。
9
+ 3. **已置顶会话通知**:置顶会话开始等待你处理或运行结束未读时,窗口在后台会发系统通知,同时置顶区内始终显示应用内提醒;通知开关与提示音按钮位于置顶区标题栏。
10
+
11
+ 侧边栏本来就会在每个会话行上显示状态点,但上方的文件夹行什么都没有。收起分组或滚动之后,就看不出里面是否还有等待审批、仍在运行的会话。本插件补上这一层,并把置顶会话集中到列表上方。
12
+
13
+ ## 功能
14
+
15
+ ### 工作区状态标记
16
+
17
+ | 标记 | 含义 | 颜色 |
18
+ |---|---|---|
19
+ | 实心点 | 有会话在等你:审批 / 计划评审 / 回答 | 琥珀 `--dsw-alias-state-warn-primary` |
20
+ | 旋转圆环 | 有会话或子代理正在运行 | 蓝 `--dsw-static-deepseek-450` |
21
+ | 实心点 | 有会话刚刚结束且尚未打开(1 小时提示窗口) | 绿 `--dsw-alias-state-success-primary` |
22
+
23
+ - 状态优先级与原生会话行一致:等待 > 运行 > 刚刚完成;一个工作区同时只显示一个主标记。
24
+ - 子代理的运行状态计入其父会话所在工作区;子代理行本身不产生标记。
25
+ - 已归档会话忽略;未分组会话落在「未分组」行。
26
+ - 标记固定在行尾时间戳的位置,不挤动标题;展开或收起都可见。
27
+ - 提供隐藏的无障碍描述(如「工作区状态:2 个运行中、1 个等待你处理 — api、web」)。
28
+
29
+ ### 已置顶会话区
30
+
31
+ - 使用 Harness 原生置顶操作(会话行悬停按钮或 **…** 菜单);置顶后无需重启即可出现在 **Pinned / 已置顶** 区域。
32
+ - 按工作区分组,每组沿用原生 34px 工作区行:文件夹图标、当前工作区蓝色高亮、折叠三角、圆角与计数。
33
+ - 每行显示实时状态点、相对时间、当前会话高亮,以及行尾的实心**置顶图标**;点击图标立即取消置顶,行会回到原工作区分组。
34
+ - Pinned 标题和各工作区分组都可折叠,折叠状态保存在浏览器本地。
35
+ - 区块限高并可独立滚动,不会把工作区列表挤走。
36
+ - 置顶集合来自 Harness 的 `pinnedSessionIds`(保存在 profile 的工作区注册表),重启后仍会显示同样的置顶会话与图标。
37
+ - 搜索不受影响:已置顶会话仍然出现在搜索结果中;常规分组列表则隐藏被提取的行。
38
+ - 常规列表中的工作区标题会保留(其「新会话」按钮仍可用),因此当某个工作区的会话全部被置顶时,常规列表里可能出现一个空分组,而会话显示在上方。
39
+
40
+ ### 已置顶会话通知
41
+
42
+ - 触发条件(仅限已置顶会话):开始等待你(审批 / 计划评审 / 提问),或运行结束且完成标记未读。
43
+ - 只对状态**变化**发通知:刷新后的第一次观察保持安静,同一等待原因不会重复提醒,原因变化(审批 → 提问)会再次提醒,完成只在每次运行结束时提醒一次。
44
+ - 窗口在后台且系统已授权时发**桌面通知**;点击通知会聚焦应用并打开对应会话。
45
+ - 置顶区**始终**显示应用内提醒(系统阻止通知时同样可用),带状态图标、标题与原因;点击打开会话,点 **×** 或等待 8 秒自动消失。
46
+ - 标题栏的铃铛开关通知并在首次点击时申请权限、显示一条测试提醒;喇叭开关可选的两声提示音。两项偏好保存在浏览器本地,默认通知开、提示音关。
47
+ - 通知是客户端行为:应用运行期间才会触发,不提供邮件 / IM / Web Push 等外部推送,也不会提醒置顶以外的会话。
48
+
49
+ ## 快速开始
50
+
51
+ ```sh
52
+ dsh plugin --profile web add dsh-workspace-status
53
+ ```
54
+
55
+ 重启 Harness(或刷新 Web 界面)。工作区行会出现状态标记;置顶任意会话即可看到上方的置顶区域与铃铛/喇叭开关。
56
+
57
+ ## 要求
58
+
59
+ - DeepSeek Harness `>=0.2.1-rc.2 <0.3.0-0`,Web 或桌面版。
60
+ - Node `>=22.18.0`(仅测试需要;无构建步骤)。
61
+ - 不修改 Host 行为、不提供 Host 设置项、不向模型注册工具或提示词;置顶状态使用 Harness 原生工作区置顶集合,通知偏好与折叠状态保存在浏览器本地。
62
+
63
+ ## 验证
64
+
65
+ 1. 在某工作区运行会话并收起分组:工作区行尾出现蓝色圆环。
66
+ 2. 在另一个工作区触发审批:即使展开,该行也显示琥珀点。
67
+ 3. 让会话跑完但不打开:出现绿点,约一小时后消失。
68
+ 4. 置顶任意会话:列表上方立即出现 Pinned 区,按工作区分组,行尾有置顶图标。
69
+ 5. 再置顶另一个工作区的会话:出现第二个分组标题。
70
+ 6. 点击行尾置顶图标取消置顶:该行立即从 Pinned 区消失并回到原工作区分组。
71
+ 7. 重启 Harness:同样的置顶会话仍在,图标也仍显示。
72
+ 8. 点击置顶区标题栏的铃铛:首次会申请通知权限并显示测试提醒;再次点击关闭。
73
+ 9. 让置顶会话结束或开始等待:置顶区出现应用内提醒;窗口在后台时还会收到系统通知。
74
+
75
+ ## 相关链接
76
+
77
+ - 英文说明(完整细节):[README.md](./README.md)
78
+ - npm:<https://www.npmjs.com/package/dsh-workspace-status>
79
+ - 更新记录:[CHANGELOG.md](./CHANGELOG.md)
80
+
81
+ <sub>同系列插件:[情绪板](https://github.com/Stijnus/dsh-moodboard) · [输入补全](https://github.com/Stijnus/dsh-composer-predictions) · [移动到工作区](https://github.com/Stijnus/dsh-move-to-workspace) · [工作区状态](https://github.com/Stijnus/dsh-workspace-status) · [提示词改写](https://github.com/Stijnus/dsh-prompt-optimizer)</sub>
82
+
83
+ <sub>⭐ 如果它帮你省了一步,点个 star 能让更多 DSH 用户发现它。</sub>