dsh-workflow-map 0.0.0-stage → 0.3.4
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 +184 -0
- package/LICENSE +21 -0
- package/README.en.md +458 -0
- package/README.md +436 -2
- package/client.js +9685 -0
- package/cordis.patch.yml +11 -0
- package/docs/OPEN-SOURCE-GUIDE.md +256 -0
- package/docs/host-compatibility.md +320 -0
- package/docs/screenshot-detail.png +0 -0
- package/docs/screenshot.png +0 -0
- package/icon.svg +6 -0
- package/index.js +12 -0
- package/lib/index.js +974 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +81 -4
- package/src/client/Branches.js +241 -0
- package/src/client/FlowColumn.js +572 -0
- package/src/client/FlowEffects.js +677 -0
- package/src/client/HotInject.js +628 -0
- package/src/client/MainFlow.js +359 -0
- package/src/client/NodeCard.js +545 -0
- package/src/client/NodeDetail.js +569 -0
- package/src/client/ProgressUnder.js +216 -0
- package/src/client/RightPage.js +285 -0
- package/src/client/Settings.js +212 -0
- package/src/client/StepColumn.js +479 -0
- package/src/client/StepDetail.js +250 -0
- package/src/client/export.js +280 -0
- package/src/client/panel.js +1911 -0
- package/src/client/pulse.js +126 -0
- package/src/client/store.js +1090 -0
- package/src/client/theme.js +1176 -0
- package/src/fold.mjs +2763 -0
- package/src/orchestrator.mjs +444 -0
- package/src/route.js +621 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
`dsh-workflow-map` 的所有重要变更记录在此。
|
|
4
|
+
格式遵循 [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),版本号遵循 [SemVer](https://semver.org/)。
|
|
5
|
+
|
|
6
|
+
## [0.3.4] - 2026-10-30
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **宿主要求改由 `engines.dsh` 声明**:`>=0.2.1-rc.1 <0.3.0-0`,覆盖 `0.2.1` 全系列(`rc.1` 至 `rc.5`)与 `0.2.1` 正式版。
|
|
11
|
+
该区间由宿主在安装与启用期读取(`dsh-app-boot` 的 `evaluatePluginCompatibility()`),不满足即拒绝加载。
|
|
12
|
+
- **删除非标准 `dsh.host` 字段**:宿主包仍由 `peerDependencies` 声明(均为可选 peer),版本闸门只看 `engines.dsh`。
|
|
13
|
+
- **中英 README 增加宿主要求块**:逐版本核验方式与结论、区间写法说明,区间字符串与 `package.json` 的 `engines.dsh` 逐字符一致。
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **`docs/host-compatibility.md`**:区间判据、206 包闭包比对、九个契约点的逐版本证据,以及 `0.2.1-rc.3`(实机运行)
|
|
18
|
+
与 `0.2.1-rc.1` / `rc.2` / `rc.4` / `rc.5`(契约核验)的区别。
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **计划行自带的步骤文件名不再被当成标题的一部分**。PAE 会把计划行渲染成 `1. 标题(限定语)(step-01-x.md)`,
|
|
23
|
+
折叠时连行尾的文件名一起收进标题,于是这一步的标题比待办表里那一行多一个括号组:`foldTodos` 拿步骤键
|
|
24
|
+
与表比对时判定「无变化」,视图里留下一条对话正文并不存在的分步(`audit-real` 约束 ①)。
|
|
25
|
+
现在解析计划行时就剥掉行尾的 `.md` / `.json` 等文件名标注;计划标题改写时同步更新步骤键,
|
|
26
|
+
旧键归档进 `aliasKeys`(与改名同一条路径),已挂在旧键上的节点随之迁移。
|
|
27
|
+
- **`docs/` 与两份 README 的口语化表述收敛为陈述句**:删去带日期的括号注、第一人称示例与破折号转折,
|
|
28
|
+
内容不变。
|
|
29
|
+
- **浅色主题下分步卡与背景同色**。宿主在浅色主题里把 `--dsw-alias-bg-layer-1` 与 `-2` 都解析到
|
|
30
|
+
`--dsw-static-neutral-bluish-00`(即 `#fff`),与 `--dsw-alias-bg-base` 同一个值;分步卡当时只填 `bg-layer-2`
|
|
31
|
+
且边线是 `transparent`,于是整块卡面在白底上不可见。现在卡面带自己的抬升墨色
|
|
32
|
+
(`--wf-lift` / `--wf-lift-2`,深色主题另行覆盖),边线改用 `--dsw-alias-border-l2`,分步、节点、
|
|
33
|
+
单元三类卡面与悬停/选中态一致。
|
|
34
|
+
- **待办表是步骤生命周期的唯一依据**。`todo/write` 每次重写整张表,但视图同步把行“配对”到旧记录时
|
|
35
|
+
沿用了那条记录的旧状态:表中写 `pending` 的行显示成 `done`/100%,表中写 `in_progress` 的行显示成
|
|
36
|
+
`pending`(同一会话里两种都出现过)。现在配对后一律按行本身的状态落值,未命名、从未开始、又不拥有
|
|
37
|
+
任何节点的 `pending` 行会被丢弃,会话不再因为改写过表格而长出空卡。
|
|
38
|
+
- **非运行中的分步不再显示百分比**。`percentFor()` 在进入各条测算路径(自报 / 待办比值 / 基线)之前先判状态:
|
|
39
|
+
只要不是 `running` 就不出数字。此前 74 步待办(5–99%)带着一个没人更新过的旧数字,看着像停滞。
|
|
40
|
+
- **回合结束时关闭该回合的运行步**。`foldTurnEnd` 以前只翻 `turnActive` 标志,运行步会一直是 `running`;
|
|
41
|
+
现在按结束时刻补时长并结束该步,唯一的例外是待办表此刻仍标 `in_progress`(那一步确实跨回合继续做)。
|
|
42
|
+
- **检查点版本 3 → 4**:旧检查点里的步骤台账按旧映射生成(错误状态、残留空行、带有不应存在的百分比),
|
|
43
|
+
按既有契约丢弃后从日志重建。
|
|
44
|
+
- **量测脚本不再依赖 `--dump-dom`**。Edge 156.0.4314.50 的启动器会在毫秒内以退出码 0 退出、把真正的浏览器进程
|
|
45
|
+
甩成独立进程,于是 `--dump-dom` 写进一个没人持有的 stdout,落盘文件恒为 0 字节(`--version` 也无输出)。
|
|
46
|
+
新增 `tools/cdp-dump.mjs`:自己拉起无头浏览器、从 `DevToolsActivePort` 拿调试端口、连页面 target、
|
|
47
|
+
`Page.enable` + `Runtime.evaluate(document.documentElement.outerHTML)` 取 DOM,失败必抛;
|
|
48
|
+
10 个 `tools\measure-*.ps1` 全部改为调它,并新增 `tools\patch-measure-cdp.mjs` 留证改法。
|
|
49
|
+
|
|
50
|
+
### Tests
|
|
51
|
+
|
|
52
|
+
- **离线自测 10 套 / 1533 条断言**全部通过,退出码全 0(0.3.3 为 1515 条)。本轮新增 13 条:`selftest-fold`
|
|
53
|
+
的 `(r)` 用例 8 条(待办表改回 `pending` 必须降级、改写表后的 `pending` 行不得顶替运行步、
|
|
54
|
+
`in_progress` 行对应的记录即使原来是 `pending` 也要转为运行、未命名空行被丢弃、回合结束仍保留表中
|
|
55
|
+
`in_progress` 的步、非运行行不出数字……),`selftest-panel` 的浅色主题针脚 5 条(抬升变量、深色覆盖、
|
|
56
|
+
卡面抬升、卡面边线取 token、悬停抬升)。
|
|
57
|
+
- **真实会话日志**:`check-real-injects` 折叠 147 个会话、识别出 19 条热注入记录、failures 0;
|
|
58
|
+
`audit-real` 折叠 148 个会话、629 个步骤,约束 ①(分步必须存在于待办表)与 ②(同一时刻只有一个
|
|
59
|
+
running 步)各 0 违规;`done` 步显示 <100% 的数量为 **0**,非运行步带数字的数量为 **0**(修前 74 条)。
|
|
60
|
+
- **浏览器量测 10 套 / 323 条断言**全部通过,退出码全 0(0.3.3 为 308 条):
|
|
61
|
+
`panel 21 · timing 20 · inject 43 · dock 14 · flow 20 · effects 28 · branches 15 · detail 50 · settings 56 · main 56`。
|
|
62
|
+
`main` 从 41 增至 56 的 15 条是本轮新增的主题对比检查:浅色帧的页面底色确实是宿主真值 `#fff`、
|
|
63
|
+
两种主题下 `--wf-lift` 各自生效、单元卡边线 alpha 与抬升渐变俱在、14 px 颗星徽标靠自身颜色边线可见
|
|
64
|
+
(实测 light/dark 均为 `rgba(…,1)`)。旧的 `card` / `node`(遗留组件)不在单页上,按「不存在不记失败」处理,
|
|
65
|
+
它们的边线与抬升由 `selftest-panel` 的样式表针脚守住。
|
|
66
|
+
- **`0.2.1-rc.5` 隔离实机**:`--dump-config` 退出码 0、stdout 1234 行、零告警;
|
|
67
|
+
`/dsh-workflow/state`、`/steer`、`/unsteer` 按本插件契约应答(`404 unknown session`、缺参 `400`)。
|
|
68
|
+
记录与复跑命令见 `docs/host-compatibility.md` §3.1。
|
|
69
|
+
|
|
70
|
+
## [0.3.3] - 2026-10-29
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
|
|
74
|
+
- **编号清单的序号不再丢失,地图不再重复显示步骤**。模型把待办表从 7 行无编号换成 14 行带 `1. `–`14. ` 前缀后,`syncToTodos` 把序号从**已经剥掉前缀的标题**上再解析一次,
|
|
75
|
+
于是 `planIndexOf` 永远返回 null;创建出的行丢了序号,而 `foldTodos` 按位置配对时又不回写序号,
|
|
76
|
+
旧行继续带着上一份计划的 `planIndex`。`applyPlanToView` 随后按这个错序号把计划步骤 2/3/4 的标题和状态
|
|
77
|
+
盖到别的行上。用户看到的是第 3–7 步各出现两次,跑动中的那一格也不是真正的当前步。
|
|
78
|
+
修法:`planIndex` 从**原始 content** 解析;配对到旧行时把序号按当前表回写;槽位配对遇到序号冲突时让位给按序号匹配。
|
|
79
|
+
复现判据:修前的视图里 14 行有 5 组标题重名,修后 `planIndex` 1–14 连续且无重名。
|
|
80
|
+
- **计划自带的确认点不再丢失**。`orchestrator.json` 里 `requiresConfirmation: true` 的步骤(该会话第 2/12/13 步)
|
|
81
|
+
在地图上一个「需确认」标记都没有:`applyPlanToView` 的注释说宿主会合并这一半,但代码里没有这段合并。
|
|
82
|
+
现在由 `applyPlanToView` 补上,标记的 `kind` 为 `plan`;已 done/failed 的步骤不带标记(与日志侧规则一致),
|
|
83
|
+
重复应用同一份计划不会叠加。
|
|
84
|
+
|
|
85
|
+
### Tests
|
|
86
|
+
|
|
87
|
+
- `tools/selftest-fold.mjs` 新增 8 条断言:`(o1)`/`(o2)` 编号清单换表后序号连续、标题不重名、
|
|
88
|
+
行不继承邻居标题;`(p)` 计划确认点只落在该落的步骤、`kind` 为 `plan`、重复应用不重复、已完成步骤不带标记。
|
|
89
|
+
- 离线自测 **10 套 / 1515 条断言**全部通过(0.3.2 为 1507 条)。
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## [0.3.1] - 2026-10-28
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- **`soft` 配色的同类残留**。0.3.0 已让 `brand` 配色下运行中卡片的外框跟随品牌色,
|
|
97
|
+
但 `soft` 配色的规则仍只认单页改版之前的选择器(`.wf-step-item > .wf-step-card` / `.wf-node`),
|
|
98
|
+
于是切到 `soft` 时运行中单元的外框仍是默认彩虹渐变、状态环仍停在品牌蓝、
|
|
99
|
+
卫星圆点与连线的流光也没换色。现在 `soft` 与 `brand` 一样同时命名现役选择器
|
|
100
|
+
(`.wf-unit[data-status='running']>.wf-unit-center>.wf-unit-card::after`、`.wf-unit-ring`、
|
|
101
|
+
`.wf-sat[data-live='true']::after` 与 `.wf-sat-row[data-live='true'] .wf-sat-line`),
|
|
102
|
+
三处一并跟随 `--wf-soft-1` / `--wf-soft-2`。
|
|
103
|
+
- 对应的浏览器量测从「记录缺陷」改为「断言修复」:`settings.soft.keepsRainbowRing`
|
|
104
|
+
换成 `settings.soft.frameMigrated` 与 `settings.soft.ringColor`,两者都用期望色
|
|
105
|
+
`rgb(127, 147, 184)` 比对;同一份期望里也存了它的十六进制写法 `#7f93b8`。
|
|
106
|
+
|
|
107
|
+
### Changed
|
|
108
|
+
|
|
109
|
+
- `docs/screenshot.png`(1400×900)与 `docs/screenshot-detail.png`(1500×950)
|
|
110
|
+
用当前代码重新渲染,替换为修复后的界面。
|
|
111
|
+
|
|
112
|
+
### Tests
|
|
113
|
+
|
|
114
|
+
- 离线自测 **10 套 / 1507 条断言**、浏览器量测 **10 套 / 308 条断言**,全部通过。
|
|
115
|
+
|
|
116
|
+
### Notes
|
|
117
|
+
|
|
118
|
+
- 仅改浏览器半(`src/client/*.js` 与重建的 `client.js`)与文档,**宿主半未改动**:
|
|
119
|
+
升级后 **F5 刷新页面**即可,不需要重启 DSH 进程。
|
|
120
|
+
|
|
121
|
+
## [0.3.0] - 2026-10-27
|
|
122
|
+
|
|
123
|
+
首个公开发布版本。相比内部迭代期,这一版把面板从「开发中的实验界面」收敛成可日常使用的形态。
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- **热注入的完整撤回链路**:历史行在「待会话拾取」状态时出现「撤回」按钮,走 `POST /dsh-workflow/unsteer`
|
|
128
|
+
→ 宿主的 `agent.inbox.remove(messageId)`;`/steer` 的响应同时带回它写下的 `messageId`。
|
|
129
|
+
撤回后刷新页面状态依然正确:折叠会重放宿主的收件箱变动(`agent/inbox/spliced` 记录的是**位置**,
|
|
130
|
+
所以需要维护一份收件箱台账才能定位到具体是哪一行)。旧检查点按契约丢弃重建。
|
|
131
|
+
- **会话标签栏入口**:在会话区顶部标签栏新增一个席位,与左栏图标、主内容区共用同一份面板、
|
|
132
|
+
同一份轮询、同一份设置。
|
|
133
|
+
- **热注入入口常驻化**:页头入口改为醒目的品牌色按钮;右页注入器底部新增可回车直发的常驻输入条,
|
|
134
|
+
不必先展开面板才能发。
|
|
135
|
+
- **进度估算的诚实化**:只要待办清单有已完成行,百分比就取该实测比值,模型自报不再参与显示值计算
|
|
136
|
+
(自报仅作为无实测行时的备选);时间基线冷启动时改用计划自身的步序推算,避免首个进行中的步只剩一条空流光。
|
|
137
|
+
|
|
138
|
+
### Fixed
|
|
139
|
+
|
|
140
|
+
- **多个分步同时显示为「进行中」**:折叠时取「第一个 running 行」,而规划阶段的合成步要等到
|
|
141
|
+
计划开启才收尾,导致它长期占用 running 状态、后续每一步再叠一个。现在每个折叠事件后
|
|
142
|
+
收敛为唯一 running 行;进度上报也归属到待办表里真正 `in_progress` 的那一行。
|
|
143
|
+
- **地图分步与对话里的待办表不一致**:折叠只增不删,重新规划或改写标题后旧行会残留。
|
|
144
|
+
现在视图严格按最新待办表产出分步,表里已不存在的行与其节点一并移除。
|
|
145
|
+
- **已完成的步显示「0 工具 0 文件」**:三个叠加的问题。按标题匹配导致改写文案后旧行变孤儿、
|
|
146
|
+
新建行未写入步骤键、全局节点上限按「丢弃最老」执行而最老的恰属已完成步。
|
|
147
|
+
现已改为就地改名并迁移节点、统一赋值步骤键、并从节点最多的步开始淘汰(单步永不被清空)。
|
|
148
|
+
- **被拒绝的审批仍标「需确认」**:审批被拒时该行仍需人工处理,原实现把任何「已决议」都当成已结束。
|
|
149
|
+
现改为「已询问,或已决议但未放行」都算未决;同时修掉了状态修复函数遗漏 `outcome` 字段的问题
|
|
150
|
+
(否则一次重启就会把这个语义抹掉)。
|
|
151
|
+
- **唯一流光**:只有唯一那一行的进度条与连接线跑动画,其余即使状态是 running 也只是静态填充。
|
|
152
|
+
|
|
153
|
+
### Changed
|
|
154
|
+
|
|
155
|
+
- **面板布局改为单页**:原先的左右双列(分步列 + 流程列)合并为一个视图。串行主流程在中间,
|
|
156
|
+
每步两侧以圆形接口表示该类工具/文件,点击后在右页展开详情。两列之间的跨列曲线随之移除。
|
|
157
|
+
- **移除「预计剩余时间」**:进度条第二行只保留「N 分钟前估计」(这个数字有多旧),
|
|
158
|
+
不再预测还需要多久。宿主侧相应的计算与字段一并移除。
|
|
159
|
+
- **移除实验性的输入框覆盖层**:该方案多轮实测无法稳定覆盖宿主渲染的输入框,
|
|
160
|
+
改为在会话标签栏席位用样式规则让位,切回对话页自动恢复。
|
|
161
|
+
|
|
162
|
+
### Tests
|
|
163
|
+
|
|
164
|
+
- 离线自测 **10 套**,合计 **1505 条断言**。
|
|
165
|
+
- 浏览器量测 **10 套**,合计 **308 条断言**(真实 CSS + 真实事件,覆盖几何、动画、剪贴板、
|
|
166
|
+
键盘与降级路径)。
|
|
167
|
+
- 真实日志只读回归:批量折叠历史会话日志、零失败;另有四条硬约束审计。
|
|
168
|
+
|
|
169
|
+
### Known issues
|
|
170
|
+
|
|
171
|
+
- 品牌配色的「运行中卡片外框」仍沿用默认彩虹渐变(选择器未迁移)。仅影响外观,
|
|
172
|
+
进度条与其余元素已正确换色。
|
|
173
|
+
- 类型页副标题会原样印出未替换的 `{count}` 占位符。仅影响文案。
|
|
174
|
+
|
|
175
|
+
### Notes
|
|
176
|
+
|
|
177
|
+
- **宿主半改动需要重启 DSH 进程**;浏览器半改动 **F5 即生效**(profile 使用符号链接安装时)。
|
|
178
|
+
- 输入框(composer)由宿主渲染,不属于本插件;插件只在会话标签页席位让它让位。
|
|
179
|
+
|
|
180
|
+
## 更早的内部迭代
|
|
181
|
+
|
|
182
|
+
0.3.0 之前的版本为内部迭代,未对外发布,因此不在此列出逐条记录。
|
|
183
|
+
所涉及的能力(会话投影、计划读取、HTTP 视图路由、面板骨架、进度条、节点详情、设置与导出)
|
|
184
|
+
均已并入 0.3.0。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-workflow-map contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# dsh-workflow-map
|
|
2
|
+
|
|
3
|
+
English · [**简体中文**](README.md)
|
|
4
|
+
|
|
5
|
+
A DeepSeek Harness plugin that renders the current session as an interactive step-by-step workflow map.
|
|
6
|
+
|
|
7
|
+
> **Host requirement**
|
|
8
|
+
>
|
|
9
|
+
> - **DSH kernel**: `engines.dsh` = `>=0.2.1-rc.1 <0.3.0-0`, covering the whole `0.2.1` series (`0.2.1-rc.1` through `0.2.1-rc.5`) and the `0.2.1` release.
|
|
10
|
+
> - **Node.js**: `>=20` (`engines.node`).
|
|
11
|
+
> - Host packages are declared as `peerDependencies` (all optional peers, same range as `engines.dsh`); the host is not bundled. Hosts below `0.2.1-rc.1`, or at `0.3.0` and above, are outside the declared range.
|
|
12
|
+
> - Range note: `>=0.2.1-rc.1 <0.3.0-0` carries an explicit prerelease tag on the `0.2.1` tuple, which is what makes it match `0.2.1-rc.x`; a start of `>=0.1.0-rc.1` silently excludes every `0.2.1` prerelease. The upper bound `<0.3.0-0` sorts below every prerelease of `0.3.0`, so the whole `0.3` line (including `0.3.0-rc.1`) stays outside the range.
|
|
13
|
+
|
|
14
|
+
Per-version method and result:
|
|
15
|
+
|
|
16
|
+
| Host version | How it was checked | Result |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `0.2.1-rc.3` | Run on a real host: plugin load, panel injection, view routes | Baseline |
|
|
19
|
+
| `0.2.1-rc.1` / `0.2.1-rc.2` / `0.2.1-rc.4` / `0.2.1-rc.5` | Cross-version contract check: closure metadata, per-file SHA-256, contract anchor windows | All nine contract points unchanged |
|
|
20
|
+
|
|
21
|
+
A contract check is not a real-host run: the last four versions were compared against published artifacts and contract anchors only, and never booted. Method and evidence: [`docs/host-compatibility.md`](docs/host-compatibility.md).
|
|
22
|
+
|
|
23
|
+
Three entry points share one data source and one set of components: the sidebar panel item
|
|
24
|
+
(`sidebar.panellist`), the main content area (`main`), and the session tab bar (`conversation.view`).
|
|
25
|
+
The panel folds session events into a step sequence, showing each step's status, progress, tool calls
|
|
26
|
+
and file operations, and can inject prompts into the next step of a running session.
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
*Left: the selected sidebar entry. Centre: the serial main flow (one unit card per step, round interfaces
|
|
31
|
+
on both sides for tool/file types; the running unit is highlighted with a flowing frame). Right: the page
|
|
32
|
+
opened for a step (type list, step detail). Bottom: the persistent injection bar.*
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 1. What problem it solves
|
|
42
|
+
|
|
43
|
+
Long tasks grow session logs to thousands of events. Answering "which step is it on", "what did this
|
|
44
|
+
step do" and "how much is done" means scrolling back through those logs. This plugin presents those
|
|
45
|
+
three facts on one screen, with every data source and decision rule traceable.
|
|
46
|
+
|
|
47
|
+
### Layout
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
┌──────────────────────────────┬───────────────────┐
|
|
51
|
+
│ session 4/10 · 46% ⚙ │
|
|
52
|
+
├──────────────────────────────┼───────────────────┤
|
|
53
|
+
│ ◯─┐ 01/10 skeleton and registration │ step 5 detail │
|
|
54
|
+
│ │ ▓▓▓▓▓▓▓▓▓▓ 100% reported │ ──────────────── │
|
|
55
|
+
│ │ │ files this step used │
|
|
56
|
+
│ ◯─┘ 02/10 host projection │ ● md type 4 calls │
|
|
57
|
+
│ │ ▓▓▓▓▓▓▓▓▓▓ 100% reported │ ● js type 2 calls │
|
|
58
|
+
│ │ │ ● pwsh type 2 calls │
|
|
59
|
+
│ ◯─┐ 05/10 browser shell <- running (highlighted) │
|
|
60
|
+
│ │ ▓▓▓▓▓░░░░░ ~58% estimated │ step 5 detail │
|
|
61
|
+
│ │ estimated 3 min ago │ what it delivered │
|
|
62
|
+
│ │ │ ● done │
|
|
63
|
+
│ ◯─┘ 06/10 step cards and rail │ 12 tools 12 files │
|
|
64
|
+
│ ▓▓▓░░░░░░░ ~36% estimated │ ──────────────── │
|
|
65
|
+
│ │ inject [........] │
|
|
66
|
+
└──────────────────────────────┴───────────────────┘
|
|
67
|
+
main flow (one unit per step, round type interfaces on both sides) right page (opens on click)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> Diagram, not a screenshot; see the screenshot above for the real UI.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. Capabilities
|
|
75
|
+
|
|
76
|
+
The four capabilities below map onto four regions of the UI: injection (header button and the right
|
|
77
|
+
page input), progress (the rail under each card), layout (main flow and side interfaces), and state
|
|
78
|
+
encoding (animation and colour).
|
|
79
|
+
|
|
80
|
+
### 2.1 Hot injection (steer / unsteer)
|
|
81
|
+
|
|
82
|
+
**Write semantics**: `POST /dsh-workflow/steer` calls the host's `agent.steer(message)`; the message
|
|
83
|
+
enters the session inbox queue `next-step` and is claimed by the next step **after the current turn
|
|
84
|
+
ends**. The call does not trigger `cancel`, so the running turn is not interrupted.
|
|
85
|
+
|
|
86
|
+
| Endpoint | Method | Semantics |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `/dsh-workflow/steer` | POST | Write one prompt to `next-step`; the response returns the generated `messageId` |
|
|
89
|
+
| `/dsh-workflow/unsteer` | POST | Call `agent.inbox.remove()` with the `messageId`, removing a message that is **not yet claimed** |
|
|
90
|
+
|
|
91
|
+
**State determination** (mutually exclusive, all derived from the log, never guessed by the UI):
|
|
92
|
+
|
|
93
|
+
| State | Determined by |
|
|
94
|
+
|---|---|
|
|
95
|
+
| Awaiting pickup | `agent/inbox/spliced` exists and no `user/message` with the same id |
|
|
96
|
+
| Picked up | A `user/message` with the same id exists (the turn claimed it) |
|
|
97
|
+
| Revoked | `agent/inbox/spliced { outcome: "canceled" }` exists and the id was never claimed |
|
|
98
|
+
|
|
99
|
+
HTTP 200 only means the message reached the inbox; it does **not** mean the session has read it. The
|
|
100
|
+
"awaiting pickup" versus "picked up" distinction comes from the log events above. A revoke's durable
|
|
101
|
+
record is the splice **position**, not the message id, so the fold keeps an inbox ledger (replaying
|
|
102
|
+
splices with the host's own `inboxProjectionDefinition` semantics) to identify which row was removed.
|
|
103
|
+
|
|
104
|
+
Failure semantics: document-level errors always return JSON and never throw into the HTTP layer.
|
|
105
|
+
Common codes: `400` missing field / non-JSON body, `404` unknown session, `409` session not running or
|
|
106
|
+
message already claimed, `413` text over 2000 chars or body over 64 KiB, `503` the host does not expose
|
|
107
|
+
the capability.
|
|
108
|
+
|
|
109
|
+
### 2.2 Progress estimation
|
|
110
|
+
|
|
111
|
+
Each step's percentage is resolved by the following **priority** (`percentFor` in `src/fold.mjs`):
|
|
112
|
+
| Priority | Source | Rule | Cap |
|
|
113
|
+
|---|---|---|---|
|
|
114
|
+
| 1 | Todo table `todos` | `round(completed / total * 100)`; when a self-report exists, this measured value is still what is returned | 99 |
|
|
115
|
+
| 2 | Model self-report `model` | Only when the todo table has no countable rows: the **larger** of the `stepProgress/report` percentage and the self-report high-water mark | 100 |
|
|
116
|
+
| 3 | Time baseline `baseline` | `elapsed / median(finished-step durations in this session) * 100` | 90 |
|
|
117
|
+
| 4 | Plan ordinal `baseline:steps` | Cold start with `current step / total steps * 100` when no durations exist | 90 |
|
|
118
|
+
| - | `none` | None of the four is available | No number shown |
|
|
119
|
+
|
|
120
|
+
Constraint: an unfinished step never shows 100 %; a finished (done or failed) step is pinned to 100 %.
|
|
121
|
+
|
|
122
|
+
The choice follows verifiability: the todo table is an objective count, a model self-report is not. So
|
|
123
|
+
whenever the todo table has completed rows, the percentage is that measured ratio (both branches of that
|
|
124
|
+
`percentFor` expression yield `measured`); the self-report is a fallback only when no row can be measured.
|
|
125
|
+
The high-water record `step.maxPercent` is still kept and never rolled back, but it no longer takes part in
|
|
126
|
+
computing the displayed value.
|
|
127
|
+
|
|
128
|
+
A second line under the rail reads `estimated N minutes ago`, i.e. `view.asOf - step.lastEstimateAt`.
|
|
129
|
+
It describes how **stale** the number is, distinguishing "being updated" from "unchanged for a long time".
|
|
130
|
+
The line is not rendered when the field is absent.
|
|
131
|
+
|
|
132
|
+
### 2.3 Single-page layout
|
|
133
|
+
|
|
134
|
+
One vertical main flow, one unit per step; each unit carries round interfaces on both sides, one per
|
|
135
|
+
tool or file type.
|
|
136
|
+
|
|
137
|
+
| Dimension | Rule |
|
|
138
|
+
|---|---|
|
|
139
|
+
| Side assignment | Read-type (`read` / `grep` / `glob` / path queries) on the left; write and execute (`edit` / `write` / `pwsh`) on the right |
|
|
140
|
+
| Capacity per side | 2 interfaces |
|
|
141
|
+
| Overflow | Extra types are not drawn; the unit states "N more types are not drawn on the sides" |
|
|
142
|
+
| Connector | A straight line between interface and unit |
|
|
143
|
+
| Details | Click an interface -> the right page lists that type's calls; click a unit -> the right page shows that step's record |
|
|
144
|
+
|
|
145
|
+
A single page was chosen over columns for continuity: switching steps in a two-column layout moves two
|
|
146
|
+
scroll regions at once, whereas here the main flow does not shift when the right page opens or closes.
|
|
147
|
+
|
|
148
|
+
### 2.4 Visual state encoding
|
|
149
|
+
|
|
150
|
+
The running unit and the single connector pointing at it use a flowing gradient; every other unit stays
|
|
151
|
+
statically filled even when its status is `running` (for example, when it is not the live one). Durations
|
|
152
|
+
and thresholds live in `src/client/theme.js`:
|
|
153
|
+
|
|
154
|
+
| Element | Implementation | Period |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| Running unit frame | `::after` multi-stop linear gradient plus a position animation | 2.6 s |
|
|
157
|
+
| Running unit ring | Opacity pulse | 1.6 s |
|
|
158
|
+
| Progress fill | Background position | 1.5 s |
|
|
159
|
+
| Activity dots | Three dots breathing out of phase | 1.2 s |
|
|
160
|
+
|
|
161
|
+
`data-motion="static"` (the "reduce motion" setting, or the OS `prefers-reduced-motion: reduce`) sets
|
|
162
|
+
every animation inside the panel to `none`, and `document.getAnimations()` returns an empty set;
|
|
163
|
+
`data-idle="1"` (session idle) sets animations to `paused` while keeping the current frame. The two are
|
|
164
|
+
not the same thing.
|
|
165
|
+
|
|
166
|
+
### 2.5 One implementation, three seats
|
|
167
|
+
|
|
168
|
+
All three entries register the same component, the same polling and the same preferences record - there is
|
|
169
|
+
no second implementation. The session-tab entry additionally carries a box-less marker so a `:has()` rule
|
|
170
|
+
can collapse the host's composer on that page; switching back unmounts the view and the composer returns.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## 3. Installation
|
|
175
|
+
|
|
176
|
+
> **Prerequisites for installing from the market**: two conditions must both hold. (1) `dsh-workflow-map`
|
|
177
|
+
> is published on npm (currently `0.3.4`). (2) The `awesome-dsh-plugin` PR is merged **and** the market index
|
|
178
|
+
> (`dsh-plugin-catalog`, served via jsDelivr) has refreshed and picked up the entry.
|
|
179
|
+
> Once both hold, install from the **DSH market** (Plugins > Discover) by searching `workflow`, no terminal needed.
|
|
180
|
+
> If it is not indexed yet, use the command line below (3.2) to install the same package; both routes are equivalent.
|
|
181
|
+
|
|
182
|
+
### 3.1 Install through the agent
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
install dsh-workflow-map with plugin_manager, path is <absolute path to the plugin>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
A returned `application: applied` means it took effect; no other value does.
|
|
189
|
+
|
|
190
|
+
### 3.2 Command line
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
cd "$HOME/.dsh/profiles/desktop"
|
|
194
|
+
pnpm add dsh-workflow-map
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```powershell
|
|
198
|
+
# One command into the desktop profile (the bundled DSH CLI forwards the rest to that profile's pnpm; use the full path if it is not on PATH)
|
|
199
|
+
dsh plugin --profile desktop add dsh-workflow-map
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Then append `"dsh-workflow-map"` to the `dsh.profile.bundles` array in that directory's `package.json`.
|
|
203
|
+
|
|
204
|
+
### 3.3 Local source
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
cd "$HOME/.dsh/profiles/desktop"
|
|
208
|
+
pnpm add "dsh-workflow-map@link:/path/to/dsh-workflow-map"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`link:` creates a symlink, so source edits are reflected on disk immediately.
|
|
212
|
+
|
|
213
|
+
### 3.4 Verify the install
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# 1) the package is on disk
|
|
217
|
+
ls "$HOME/.dsh/profiles/desktop/node_modules/dsh-workflow-map"
|
|
218
|
+
|
|
219
|
+
# 2) the host view endpoint works (expect HTTP 200 and a JSON body)
|
|
220
|
+
curl -i "http://127.0.0.1:<GUI port>/dsh-workflow/state?sessionId=<session id>"
|
|
221
|
+
|
|
222
|
+
# 3) the UI: a clickable sidebar icon, a panel in the main area, a same-named tab in the session tab bar
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 4. How changes take effect
|
|
228
|
+
|
|
229
|
+
The plugin has two halves with different load times:
|
|
230
|
+
|
|
231
|
+
| Half | Contains | Takes effect | Why |
|
|
232
|
+
|---|---|---|---|
|
|
233
|
+
| Browser half | `client.js` (built from `src/client/*.js`) | **Page refresh (F5)** | Front-end code loads per request |
|
|
234
|
+
| Host half | `lib/index.js`, `src/fold.mjs`, `src/route.js` | **Restart the DSH process** | ESM module cache cannot be replaced in-process |
|
|
235
|
+
|
|
236
|
+
Restart once after the first install; afterwards UI-only changes need no restart.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 5. Data boundary
|
|
241
|
+
|
|
242
|
+
### 5.1 What is read
|
|
243
|
+
|
|
244
|
+
- **Session event log**: `todo/write`, `tool/call`, `tool/result`, `step/start|end`, `turn/start|end`,
|
|
245
|
+
`stepProgress/report`, `user/message`, `assistant/message`, `approval/*`, `agent/inbox/*` and others.
|
|
246
|
+
Event types not listed return the same state reference with no copy.
|
|
247
|
+
- **PAE plan file**: `<project>/.pae/<sessionId>/orchestrator.json`. Read-only, cached by `mtime:size` and
|
|
248
|
+
re-parsed only when the file changes; the parsed result is deep-frozen. A missing file, a partial write or
|
|
249
|
+
malformed fields yield `null` and degrade to the todo table only, never throwing.
|
|
250
|
+
|
|
251
|
+
### 5.2 What is not read
|
|
252
|
+
|
|
253
|
+
- **File bodies**. Fields such as `content`, `old_str` and `new_str` never enter the state, so how much
|
|
254
|
+
the agent writes does not grow the panel's state.
|
|
255
|
+
- **The network**. The plugin makes no outbound requests; all data comes from local processes and files.
|
|
256
|
+
|
|
257
|
+
### 5.3 Truncation and limits
|
|
258
|
+
|
|
259
|
+
| Item | Limit | On overflow |
|
|
260
|
+
|---|---|---|
|
|
261
|
+
| Arguments / result text | 200 characters each | The UI states "host cap 200 characters" |
|
|
262
|
+
| Nodes per step | 300 | Keep head and tail, drop the middle into `truncated.stepNodes` |
|
|
263
|
+
| Nodes per session | 1200 | Evict starting from the step with the most nodes; no step is ever emptied |
|
|
264
|
+
| Injection history | 40 rows | Keep the newest |
|
|
265
|
+
| Approval records | 40 rows | Keep the newest |
|
|
266
|
+
| Titles | 120 characters | Truncated with an ellipsis |
|
|
267
|
+
|
|
268
|
+
Eviction deliberately does not start with the oldest: the oldest nodes usually belong to finished steps,
|
|
269
|
+
so time-based eviction would empty historical steps.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## 6. Interaction
|
|
274
|
+
|
|
275
|
+
| Action | Result |
|
|
276
|
+
|---|---|
|
|
277
|
+
| Click a unit | The right page shows that step's record (report, artifacts, stats) |
|
|
278
|
+
| Click a round interface | The right page lists that type's calls |
|
|
279
|
+
| Click a call row | Expand the full arguments, result and error in place |
|
|
280
|
+
| `Esc` | Close the right page, not the panel |
|
|
281
|
+
| Gear | Open settings: palette, motion, detail depth, node limit |
|
|
282
|
+
| Copy control | Copy path / command / snapshot, with a receipt that restores after 1.5 s |
|
|
283
|
+
|
|
284
|
+
Settings:
|
|
285
|
+
|
|
286
|
+
| Item | Values | Effect |
|
|
287
|
+
|---|---|---|
|
|
288
|
+
| Palette `palette` | `rainbow` / `brand` / `soft` | Switches accent colours and gradients |
|
|
289
|
+
| Motion `motion` | `full` / `always` / `static` | `full` follows session activity; `always` plays even when idle; `static` turns everything off |
|
|
290
|
+
| Detail depth `detail` | `summary` / `title` | `title` hides the rail's second line |
|
|
291
|
+
| Node limit `nodeLimit` | 30 / 60 / 120 / 0 | `0` means unlimited |
|
|
292
|
+
|
|
293
|
+
Preferences live in one `localStorage` record; a corrupted or outdated record degrades field by field to the
|
|
294
|
+
defaults without blocking rendering.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 7. Export
|
|
299
|
+
|
|
300
|
+
The gear offers four exports: copy / download times Markdown / JSON. The exported snapshot contains the
|
|
301
|
+
steps, their status, the percentage source, the node list and the report artifact paths - never file bodies.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 8. Compatibility and constraints
|
|
306
|
+
|
|
307
|
+
- **DeepSeek Harness**: the `engines.dsh` range `>=0.2.1-rc.1 <0.3.0-0` (relies on session projections and `webServer` route registration); `0.3.0` and newer are not supported.
|
|
308
|
+
- **Node.js**: `>=20`.
|
|
309
|
+
- The three endpoints mount on the host's existing port; **no new listener** is opened.
|
|
310
|
+
- The composer is rendered by the host and is not part of this plugin. The plugin neither replaces nor
|
|
311
|
+
overlays it; it only yields space on the session-tab page through a stylesheet rule.
|
|
312
|
+
- The fold path never reads a clock: every time value in the view comes from event timestamps, so the same
|
|
313
|
+
event sequence always yields the same view (replayable).
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 9. Development
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# after editing src/client/*.js, rebuild the browser half
|
|
321
|
+
node tools/build-client.mjs
|
|
322
|
+
|
|
323
|
+
# offline self-tests (10 suites, 1533 assertions)
|
|
324
|
+
node tools/selftest-fold.mjs # fold semantics
|
|
325
|
+
node tools/selftest-host.mjs # registration, schema, projection wiring
|
|
326
|
+
node tools/selftest-orchestrator.mjs # plan file reading and merging
|
|
327
|
+
node tools/selftest-shape.mjs # package shape, config, files whitelist
|
|
328
|
+
node tools/selftest-panel.mjs # render tree, styles, interaction
|
|
329
|
+
node tools/selftest-detail.mjs # node and step details
|
|
330
|
+
node tools/selftest-effects.mjs # animation and motion fallback
|
|
331
|
+
node tools/selftest-settings.mjs # settings and export
|
|
332
|
+
node tools/probe-route.mjs # HTTP routes (real loopback)
|
|
333
|
+
node tools/probe-steer.mjs # injection / revoke channel
|
|
334
|
+
|
|
335
|
+
# read-only regression over real logs
|
|
336
|
+
node tools/check-real-injects.mjs # fold historical logs in bulk
|
|
337
|
+
node tools/audit-real.mjs # four-constraint audit
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Browser measurements (needs a Chromium; the scripts auto-detect Chrome / Edge; 323 assertions, light/dark theme contrast included):
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
pwsh -File tools/measure-panel.ps1
|
|
344
|
+
pwsh -File tools/measure-timing.ps1
|
|
345
|
+
pwsh -File tools/measure-inject.ps1
|
|
346
|
+
pwsh -File tools/measure-dock.ps1
|
|
347
|
+
pwsh -File tools/measure-flow.ps1
|
|
348
|
+
pwsh -File tools/measure-effects.ps1
|
|
349
|
+
pwsh -File tools/measure-branches.ps1
|
|
350
|
+
pwsh -File tools/measure-detail.ps1
|
|
351
|
+
pwsh -File tools/measure-settings.ps1
|
|
352
|
+
pwsh -File tools/measure-main.ps1
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
`client.js` is a build artifact (its first line carries a GENERATED marker) and must not be edited by hand.
|
|
356
|
+
`tools/retired/` holds historical scripts for removed UI; they are not part of the verification chain.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## 10. Key constants
|
|
361
|
+
|
|
362
|
+
Every threshold is defined once and asserted by the tests, so this table cannot drift from the code:
|
|
363
|
+
|
|
364
|
+
| Constant | Value | Location | Meaning |
|
|
365
|
+
|---|---|---|---|
|
|
366
|
+
| `NODES_PER_STEP` | 300 | `src/fold.mjs` | Nodes per step |
|
|
367
|
+
| `NODES_TOTAL` | 1200 | `src/fold.mjs` | Nodes per session |
|
|
368
|
+
| `TEXT_LIMIT` | 200 | `src/fold.mjs` | Argument and result text |
|
|
369
|
+
| `TITLE_LIMIT` | 120 | `src/fold.mjs` | Titles |
|
|
370
|
+
| `INJECT_LIMIT` | 40 | `src/fold.mjs` | Injection history retained |
|
|
371
|
+
| `APPROVAL_LIMIT` | 40 | `src/fold.mjs` | Approval records retained |
|
|
372
|
+
| `WF_SIDE_SLOTS` | 2 | `src/client/theme.js` | Interfaces per side |
|
|
373
|
+
| `WF_STEP_RAIL` | 6 | `src/client/theme.js` | Progress rail height (px) |
|
|
374
|
+
| `WF_FLOW_CAP` | 60 | `src/client/theme.js` | Default call-list window |
|
|
375
|
+
| Request body | 2000 chars / 64 KiB | `src/route.js` | Injection request limit |
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 11. Known issues
|
|
380
|
+
|
|
381
|
+
Both defects recorded in 0.3.0 are closed:
|
|
382
|
+
|
|
383
|
+
| Original # | Symptom | Status |
|
|
384
|
+
|---|---|---|
|
|
385
|
+
| 1 | With the brand palette the running unit's frame used the default gradient | Fixed (`8bf6f2c`); the same residue under the `soft` palette was fixed in 0.3.1 |
|
|
386
|
+
| 2 | The type page subtitle showed an unsubstituted `{count}` placeholder | Fixed (`8bf6f2c`) |
|
|
387
|
+
|
|
388
|
+
There are no known functional defects at present. Changes to the host half need a DSH process restart;
|
|
389
|
+
that is how activation works, not a defect.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## 12. Layout
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
dsh-workflow-map/
|
|
397
|
+
├─ index.js package entry (re-exports lib/index.js)
|
|
398
|
+
├─ lib/index.js host half: session projection + three HTTP endpoints
|
|
399
|
+
├─ src/
|
|
400
|
+
│ ├─ fold.mjs events -> state -> view (pure, no clock, no IO)
|
|
401
|
+
│ ├─ orchestrator.mjs read-only PAE plan file
|
|
402
|
+
│ ├─ route.js /state · /steer · /unsteer
|
|
403
|
+
│ └─ client/ browser-half sources (inlined into one file at build)
|
|
404
|
+
├─ client.js build artifact
|
|
405
|
+
├─ cordis.patch.yml mount declaration
|
|
406
|
+
├─ locale/{zh,en}.json dictionaries
|
|
407
|
+
├─ docs/ release guide
|
|
408
|
+
└─ tools/ self-tests · probes · browser measurements
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## 13. FAQ
|
|
414
|
+
|
|
415
|
+
**Can it show several sessions at once?**
|
|
416
|
+
The panel shows the current session only. Switching sessions switches the content; nothing is merged or tiled.
|
|
417
|
+
|
|
418
|
+
**Does it slow DSH down?**
|
|
419
|
+
The fold is pure with no IO; the view is derived from state, and state has hard limits (300 nodes per step,
|
|
420
|
+
1200 per session). Polling compares `rev` first and returns 304 without rebuilding when nothing changed.
|
|
421
|
+
File bodies never enter the state.
|
|
422
|
+
|
|
423
|
+
**Why does the percentage sometimes stay still for a long time?**
|
|
424
|
+
The number only moves when new events arrive. When neither the todo table nor the report updates, the time
|
|
425
|
+
baseline creeps up but is capped at 90 %. The second line ("estimated N minutes ago") states how stale it is.
|
|
426
|
+
|
|
427
|
+
**Why does an unfinished step never reach 100 %?**
|
|
428
|
+
The todo table caps at 99 and the time baseline at 90; only a done/failed status pins 100 %. This keeps
|
|
429
|
+
"nearly there" from being confused with "already there".
|
|
430
|
+
|
|
431
|
+
**Does it upload user code?**
|
|
432
|
+
No. The plugin makes no network requests; it reads only the local session log and the `.pae` plan file.
|
|
433
|
+
|
|
434
|
+
**Can I install only the UI and skip the host half?**
|
|
435
|
+
No. Both halves belong to one package: `dsh.profile.bundles` registers the host row, and the browser half is
|
|
436
|
+
loaded by that row.
|
|
437
|
+
|
|
438
|
+
**Can I turn animation off?**
|
|
439
|
+
Set motion to `static` in the settings, or enable "reduce motion" in the OS; both set every animation inside
|
|
440
|
+
the panel to `none`.
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## 14. License
|
|
445
|
+
|
|
446
|
+
MIT. Commercial use, modification and redistribution are permitted; keep the copyright notice.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## 15. Reporting an issue
|
|
451
|
+
|
|
452
|
+
The following helps locate a problem:
|
|
453
|
+
|
|
454
|
+
1. DSH version and plugin version (`version` in `package.json`);
|
|
455
|
+
2. The response body of `GET /dsh-workflow/state?sessionId=<id>` - **it contains task titles and file
|
|
456
|
+
paths, so redact before posting**;
|
|
457
|
+
3. A screenshot of the panel where it goes wrong;
|
|
458
|
+
4. For fold-related issues, include the relevant event sequence from that session log.
|