Repository navigation
Releases: DDDMUC/dsh-url-router
Release list
v0.4.5 —— 地址栏定位重做、电源四项、插件页面分区链接
地址栏定位(macOS)
- 不再"搜索哪一行是头部行":钉死一条线(top 11,与电源按钮同心)
- 左对齐 + 宽度上限 700(上一版 560),仍受"这一段空位"限制,不压右侧按钮
- 永不隐藏:没有空位退到右端一段;拉伸、全屏、退出全屏、切换界面都不消失
- 占位判定更准:穿过那条线的长段落与过宽容器不算控件;补上 svg / img 图标;右侧面板打开时以它的左缘为右边界;扫描根从 body 扩到整份文档
- 不抖:摆完复查两次(150 / 600 ms),位移与宽度都小于 8px 就不重摆
(实测下还是可能会抖一会,不过我感觉这都算暴力测试了,完全修好也难,而且又不影响使用,暂时摆了)
电源菜单(现在四项)
- 刷新 / 重启 / 定时 / 关闭全部支持:依旧是对dsh-power-menu-mac的兼容;先开它的菜单,按它发布的
data-dsh-power-action点那一项,端点只作兜底 - 打开的菜单不再写进地址栏:以前菜单一开地址栏就变
#/power,而电源插件自己的「刷新」「重启」reload 后 hash 会带回来 —— 刷新一下链接就变成#/power。已修
插件页面分区链接(配合 free-search 的七个分区)
- 契约写进
docs/panel-sections.md:页面根发布data-dsh-panel-section、每节带data-dsh-section、侧栏项是真<a>;分区数量不限 - 通用名优先、旧名
data-dsh-fs-section兼容 - 修"链接最终对、但很慢":观察器以前没盯这两个属性,页面换分区根本不唤醒它
验证
205 条测试通过;另用无头浏览器 + 真组件跑演练台(分区逐个核对、地址栏跟着滚动走)。
v0.4.3
新增
-
#/power打开电源菜单,#/power/shutdown/#/power/restart执行关机 / 重启,这些与 dsh-power-menu-mac 联动,只有安装了 dsh-power-menu-mac 才能使用。 -
地址栏可设为「悬浮才显示」。
-
设置路线支持任意层:分区 → 页签 → 子行 → 筛选 → 模型编辑卡。
-
子代理会话的链接带上父会话标题。
-
没有 ARIA 标记、只有样式类的行也能写出链接。
修复
- 设置面板打不开的几种情况。
- 设置页签层与子行读不到。
- 「打不开」误报。
- 会话视图页签被折叠进「…」时写错视图段。
Added
-
#/poweropens the power menu, and#/power/shutdown/#/power/restartperform shutdown / restart. These are integrated with dsh-power-menu-mac and are only available when dsh-power-menu-mac is installed. -
The address bar can be set to "show only on hover."
-
Settings routes support arbitrary levels: partition → tab → sub-row → filter → model editing card.
-
Links to sub-agent sessions include the parent session title.
-
Rows that have no ARIA markup and only style classes can also have links written for them.
Fixed
- Several cases where the settings panel could not be opened.
- The settings tab level and sub-rows could not be read.
- False positives for "cannot open."
- Incorrect view segment written when session view tabs are collapsed into "...".
0.4.2
相对 0.4.1:新增「首次点击全选 + 最近界面/粘贴链接列表」、「自动化任务」与「模型页提供商卡片」的链接、「兼容自检」;修复轮次跳转(rc.3 上静默失效)与 macOS 地址栏挡住页面控件的问题;并做了一轮性能优化。
新增
- 地址栏偏好(在插件管理器里本插件那一行的配置控件中调整)
- 首次点击地址栏全选链接,可关(像浏览器地址栏)
- 最近用过的界面与粘贴过的链接列表:默认 8 条,可设 0 关闭、不设上限;左键跳转、右键复制完整链接
- 自动化任务面板:
#/panel/schedules,状态筛选(全部 / 已开启 / 已结束)、任务详情、规则 / 运行记录页签都进链接 - 模型页的提供商卡片:点「编辑」展开的那张卡写进地址栏(
#/settings/<分区>/provider/<id>) - 兼容自检:官方改了 DOM 契约时不再静默失效 —— 每类只警告一次,控制台与
report().compat都能看到
修复
- 轮次跳转恢复:修掉官方 rc.3 上
loadThrough方法绑定导致的静默失效;翻页回到目标轮后自动滚到它;链接落地后不再把轮次从 URL 里抹掉 - macOS 地址栏让位:没有电源按钮的界面(插件页 / 面板页 / 设置页)按当前那一行重新量空段,不再压住页面控件(例如任务详情的页签)
- 右栏 pane:收起时不再写进链接;kind 以控制器为准,不再出现
pane/client.js这类错值 - 复制链接:右键复制给出完整 URL;剪贴板失败时的回退路径不再抢焦点、不再关掉列表
- 自动化任务:任务被当前筛选藏起来时,链接会先把筛选放宽,而不是干等到过期
性能
- DOM 通知合并到一帧一次(流式回答时不再每批重读整个页面)
- 标题行只在形状变化时重新测量;最近列表一次扫描侧栏
report().work给出 reconcile / 摆放次数,便于自查
测试 132 项通过。
Relative to 0.4.1: added "first-click select-all + recent interfaces/pasted links list", links for "automation tasks" and "provider cards on the model page", and "compatibility self-check"; fixed round jumping (silently failing on rc.3) and the macOS address bar blocking page controls; and did a round of performance optimization.
Added
- Address bar preferences (adjusted in the configuration controls for this plugin's row in the plugin manager)
- First click on the address bar selects the entire link, can be disabled (like a browser address bar)
- List of recently used interfaces and pasted links: 8 by default, can be set to 0 to disable, no upper limit; left-click to jump, right-click to copy the full link
- Automation task panel:
#/panel/schedules, status filters (all / enabled / ended), task details, and rules / run records tabs all included in the link - Provider cards on the model page: the card expanded by clicking "Edit" is written into the address bar (
#/settings/<section>/provider/<id>) - Compatibility self-check: no longer silently fails when the official DOM contract changes — warns only once per category, visible in both the console and
report().compat
Fixed
- Round jumping restored: fixed the silent failure caused by
loadThroughmethod binding on official rc.3; after paging back to the target round, automatically scroll to it; after the link lands, no longer erases the round from the URL - macOS address bar gives way: on interfaces without a power button (plugin page / panel page / settings page), remeasure the empty segment according to the current row, no longer covering page controls (e.g. tabs in task details)
- Right-column pane: no longer written into the link when collapsed; kind is based on the controller, no longer producing incorrect values like
pane/client.js - Copy link: right-click copy gives the full URL; the fallback path when the clipboard fails no longer steals focus and no longer closes the list
- Automation tasks: when a task is hidden by the current filter, the link first broadens the filter instead of waiting until it expires
Performance
- DOM notifications coalesced to once per frame (no longer re-reading the entire page for every batch during streaming responses)
- Title rows are remeasured only when the shape changes; the recent list scans the sidebar once
report().workgives reconcile / placement counts for self-checking
132 tests passed.
v0.4.1 —— macOS 兼容(地址栏落在标题行空白段)
macOS 兼容版,与 0.4.0 的 Windows 标题栏地址栏平行。
macOS 没有页面里画的标题栏 strip(标题栏是原生的),地址栏改画进会话页的常驻标题行:量出行内所有占位元素、取最宽空白段,右对齐贴住头部按钮,两侧各内缩 25px,宽度封顶 1150。
Windows 行为不变。测试 99 条通过。
macOS-compatible version, parallel to the Windows title-bar address bar in 0.4.0.
macOS has no title-bar strip drawn in the page (the title bar is native), so the address bar is instead drawn into the session page’s persistent title row: measure all inline placeholder elements, take the widest blank segment, right-align it flush against the header buttons, inset 25px on both sides, and cap the width at 1150.
Windows behavior is unchanged. 99 tests pass.
v0.4.0 - 桌面版标题栏地址栏 + 设置三层路由 + 遮挡层让路
这一版把 Windows 桌面版拉进了一等公民:桌面窗口自己没有地址栏,本插件就自己在标题栏那条空白里画一个,同时把「设置」三层纳入路由。
新增
- 桌面版标题栏地址栏(
2d46c54):只在html[data-windows-titlebar]下渲染(Web 与 macOS 上一行都不画);位置紧跟 shell 自己的菜单条、右端避开窗口按钮、高度取--dsh-windows-titlebar-height、-webkit-app-region: no-drag保证能点。它既是输入框也是反映:插件每次写地址栏都同步进这个框,Escape 还原,认不出的文本不动地址栏。 - 设置三层路由:
#/settings/#/settings/<分区>/#/settings/<分区>/<页签>。分区与页签没有对外的 id(实测导航项只有aria-current="true"、页签只有aria-selected,右侧内容区一个data-*都没有)→ 身份就是用户读到的那行字。含义:换语言或官方改文案后旧分区链接会失效,但你重新点一次,地址栏就写出新链接(自洽、不过期)。 - 落地失败会自己说明原因(
e13a26d):桌面版没有 devtools(官方把toggleDevTools设成不可见),所以框里 900ms 内按 canonical 判断有没有真落地,不落地就标红并写一行原因(例:打不开 session-…(当前 settings:通用设置,侧栏 2 行))。地址栏同时显示解码后的路由,不再是%E9%BB%98%E8%AE%A4…。
验证
- 单测 99/99(
npm test,node --test直接跑真产物 +node:vm假 DOM)。本轮新增遮挡层用例,并给假 DOM 补上document.dispatchEvent与window.KeyboardEvent——此前"向 document 派发事件"这类实现根本没被测到。每条修复都做了反向对照:未修复的那一份必须能复现故障(浮层那条修前红在"浮层还在",而env.opened已含目标会话,正好证明"动作执行了但落不了地")。 - 桌面版真机已复验(Windows 桌面窗口,重启加载 0.4.0 后三条全过):① 开着设置浮层粘会话链接 → 浮层让路、链接落地 ✓;② 开着「插件」面板粘带工作区前缀的会话链接 → 面板让开并跳过去 ✓;③ 打开设置浮层 → 地址栏跟到
#/settings/<分区>✓。
注:落地后如果地址栏写的是裸#/session/<id>(不带工作区前缀),那是正常回落——那一刻侧栏会话树没展开、DOM 里没有工作区行可读,插件"读不到就不猜"。展开侧栏再点一次行就会写出带前缀的链接。
安装 / 更新
dsh plugin --profile web add dsh-url-router@0.4.0This version brings the Windows desktop app in as a first-class citizen: the desktop window has no address bar of its own, so the plugin draws one in the blank strip of the title bar, and also folds the three levels of "Settings" into routing.
Added
- Desktop title-bar address bar (
2d46c54): renders only underhtml[data-windows-titlebar](not a single line on Web or macOS); positioned right after the shell's own menu strip, with the right end kept clear of the window buttons, height taken from--dsh-windows-titlebar-height, and-webkit-app-region: no-dragso it stays clickable. It is both an input box and a reflection: every time the plugin writes the address bar, it syncs into this box; Escape restores it; unrecognized text leaves the address bar untouched. - Three-level settings routing:
#/settings/#/settings/<section>/#/settings/<section>/<tab>. Sections and tabs have no external ids (in practice, nav items only havearia-current="true", tabs only havearia-selected, and the content area on the right has nodata-*at all) → identity is the very line of text the user reads. Implication: after changing language or an official copy edit, old section links will break, but if you click once more, the address bar writes out the new link (self-consistent and never stale). - Landing failures explain themselves (
e13a26d): the desktop app has no devtools (the official build makestoggleDevToolsinvisible), so within 900ms the box checks against canonical whether it actually landed; if not, it turns red and writes a one-line reason (e.g.Cannot open session-… (current settings: General settings, sidebar 2 rows)). The address bar also shows the decoded route, no longer%E9%BB%98%E8%AE%A4….
Verification
- Unit tests 99/99 (
npm test,node --testrunning directly against the real build artifact + a fake DOM vianode:vm). This round added occlusion-layer cases and filled indocument.dispatchEventandwindow.KeyboardEventfor the fake DOM—previously implementations like "dispatch an event to document" were not tested at all. Every fix was paired with a reverse control: the unfixed version must be able to reproduce the failure (before the fix, the overlay case failed on "the overlay is still there", whileenv.openedalready contained the target session, exactly proving "the action ran but could not land"). - Re-verified on a real desktop machine (Windows desktop window, after restarting and loading 0.4.0, all three passed): ① with the settings overlay open, paste a session link → the overlay yields and the link lands ✓; ② with the "Plugins" panel open, paste a session link with a workspace prefix → the panel yields and jumps there ✓; ③ open the settings overlay → the address bar follows to
#/settings/<section>✓.
Note: after landing, if the address bar shows a bare#/session/<id>(without a workspace prefix), that is a normal fallback—at that moment the sidebar session tree is not expanded and there is no workspace row in the DOM to read, so the plugin "doesn't guess when it can't read". Expand the sidebar and click the row again, and it will write out a link with the prefix.
Install / Update
dsh plugin --profile web add dsh-url-router@0.4.0
v0.3.2 - 侧栏扫描预算:按帧合并 + 批次过滤 + 一趟工作区遍历
这一版只做一件事:把侧栏行链接的扫描成本压下来。行为不变,链接形状、跳转、右键菜单全部照旧。
改了什么
- 观察者按帧合并:一帧内到达的多个 DOM 变更批次合并成一次扫描(
requestAnimationFrame);没有 rAF 的最小 DOM 走同步扫描,不排队、不漏行。 - 批次先过滤:只有可能带来行的节点才触发扫描(会话行 / 插件行 / 面板 slot,自身或子树命中即可);纯文本批次直接跳过 —— 流式回答、hover、工具输出整天在改 DOM,但永远不带行。空批次(拿不到记录的非标准 DOM)按"要扫"处理,宁可多扫一次也绝不漏行。
- 工作区归属一趟遍历:新增
workspaceNamesOfRows()一次建表,替掉"每行都重新走一遍[data-row-key]"的做法(O(N²) → O(N))。侧栏会话越多,差距越明显。 - 已挂锚的行跳过重挂:判据是行内
querySelector找到锚点,不是行上的标记属性 —— 视图重渲染把锚点丢掉时,下一趟扫描会自动补回来,不会永久失去修复机会。 - 面板行定位:从"遍历全文档所有
<button>再逐个查子树"改成[data-slot="sidebar.panellist"]属性查询 +closest('button')。 - 卸载收尾:取消还在排队的那一帧,不再对已销毁的 DOM 动手。
验证
- 单测
88/88(原 84 条 + 新增 4 条:批次过滤 / 帧合并 / 单趟遍历 / 锚点自愈)。 - 真机:本机 Web profile 直接加载本提交的
lib/client.js,硬刷新后实跑主路径 —— 行锚点、右键复制链接(带工作区前缀)、中键新标签、面板行、设置三层、粘贴链接落地全部正常,长回答流式输出期间侧栏不再跟着抖。
安装
dsh plugin --profile web add dsh-url-router@0.3.2安装后重启 dsh web(宿主半区为空,但客户端模块要重新下发),再硬刷新浏览器。
0.3.1 —— 轮次跳转闭环
0.3.1 · 轮次跳转闭环
npm:dsh-url-router@0.3.1 · 单测 84/84
这一版做成了什么
粘贴一个轮次链接,真的会跳到那一轮 ✓ —— 而且用的是官方已有的公开契约,没有等待任何新接缝:
#/session/<id>/turn/118
→ 打开那个会话
→ sessions.retainScope(id, 'url-router') 拿到会话控制器
→ session.projections.faceOf('turnOutline') 读到那一轮的 seq
→ session.loadThrough(seq) 把历史翻页回那一轮
→ reference.release()
→ 按官方视口同款选择器 [data-chat-turn]:not([hidden]) 滚到它
→ 落地(目标真的在视口里,才交出地址栏)
真机实测(DSH 0.2.0-rc.2,粘贴 /turn/118):地址栏稳定停在 …/turn/118 ✓ · 已载入窗口变成 118 → 121 ✓ · 目标在视口 true ✓ · 最顶可见正是 118 ✓ · 无诊断、无异常 ✓。
其余改动
inject显式声明uiConversation✓ → 视图 id 直读官方注册表(ctx.uiConversation.views.entries()),不再是"槽位顺序对齐"的推断 ✓inject显式声明sessions且probeFaces读入 faces ✓ →retainScope真机可达 ✓(此前漏读,导致翻页链路在真机上恒不可达 ✗)sameRoute的轮次落地判据改为「目标真在视口」 ✓ —— 原先按 routeKey 比,canonical 一带上轮次就判等,链接从未驱动(死锁,实测 ✗)- 虚拟列表的隐藏座位一律排除 ✓(
:not([hidden])+closest('[hidden]'))—— 未载入的轮次也会被渲染进 DOM,只查"存在"会假报就位 ✗ - reconcile 用链接快照 ✓:drive 会重入 reconcile,而重入可能已丢弃链接;现在守门后取快照,体内一律用它 ✓(此前报
Cannot read properties of undefined (reading 'inner')✗)
关于官方接缝
已在讨论 #9339 按官方建议的三句话口径发过诉求 ✓;既然公开 API 已足够打通,uiChat.scrollToTurn(sessionId, turn) 那条请求降级为锦上添花(能让插件少做一次 retain/release 与投影读取 ✓),不是阻塞项 ✓。
仍待做
- Skill Center / SSH 内页需要各自的"发布当前 id + 接受打开请求"契约(任务板已有先例 ✓)
- 会话链接只在同一台机器、同一个
DSH_HOME内有意义(id 是本机生成的 ✗)
dsh-url-router 0.3.0 —— 每个界面都有自己的链接(含右栏页签)
地址栏能表示的东西,从「对话 / 面板」扩到了 「工作区 + 对话 + 视图 + 行 + 轮次 + 设置三层 + 右栏页签」。
新增的链接
| 链接 | 是什么 |
|---|---|
#/workspace/<工作区名>/session/<会话id> |
对话,带工作区(侧栏形状;名字是装饰,写错也照样打开并自纠) |
#/session/<id>/view/<viewId> · #/workspace/<名>/session/<id>/view/<viewId> |
哪个会话视图(chat / trajectory / surface / plus2 …,id 来自 conversation.view 槽位) |
#/session/<id>/row/<类>/<作用域>/<id> |
轨迹里的某一行(row/tool/call/call_ce3a…、row/assistant/80/32) |
#/session/<id>/turn/<n> · …/turn/<n>/row/<…> |
某一轮的位置(可证明时才带轮次归属) |
#/settings · #/settings/<分区> · #/settings/<分区>/<页签> |
设置面板三层(分区/页签按标准 ARIA:aria-current / role=tab+aria-selected) |
#/session/<id>/pane/<kind> · #/panel/<面板>/pane/<kind> |
右栏页签(kind 由右栏自己注册,实测 7 种:guide / subagentchat / changes-review / plan / files / text / terminal) |
#/panel/plugins/<包名> · /<官方项id> · /<包名>/<组件id> |
插件面板的官方内置组也进地址栏 |
#/panel/task-board/task/<任务id> · /new |
任务看板的详情 / 新建表单 |
行为改进
- 链接落地即交权:视图一到链接描述的界面,地址栏立刻还给视图。
- 未落地的链接定时重试(500ms,8 秒窗口)。
- 右栏 pane 读 + 驱动 + 切换全通(真机验证:贴链接开出对应页签)。
multiple型页签(如 terminal)只开一次,不会重试一次多开一个。- pane kind 白名单:未知 kind 明确拒绝并列出已知的 7 种。
互斥与诚实声明
- 一个 URL 只有一个 fragment → 与写
#msg=的插件互斥:本插件认出外来 fragment、绝不覆盖、并明说"只能启用一个写者"(不再互相静默擦掉链接)。 - 轮次只做反映:粘贴轮次链接会打开那个对话,但不会滚到那一轮(官方把
scrollToTurn留在包内部,已在讨论 #9339 请求开缝)。 - 虚拟化下未渲染的行不会被假装滚到。
排障
Console 里 window.__dshUrlRouter.report():当前地址栏、屏幕在哪个界面、正在落地的链接与重试次数、每一层读到的钩子数、右栏 pane 真实 kind 列表、被拒绝认领的段位。
测试
npm test → 83 条(0.2.0 时 70 条)。
dsh-url-router 0.2.0 —— 每个界面都有自己的链接
地址栏能表示的东西,从「对话 / 面板」扩到了「工作区 + 对话 + 面板内部页 + 设置面板三层 + 轮次位置」。
新增的链接
| 链接 | 是什么 |
|---|---|
#/workspace/<工作区名>/session/<会话id> |
带工作区对话 |
#/session/<id> |
无工作区对话,当前版本仍接受 |
#/panel/<面板id> |
主面板(插件、任务看板、技能中心、SSH …) |
#/panel/plugins/<包名> · …/<包名>/<组件> |
已安装插件的页面与其中组件页 |
#/panel/plugins/<官方项id> |
官方内置插件页(shell / agent-loop / subagent / web-search) |
#/panel/task-board/task/<任务id> · #/panel/task-board/new |
任务详情 / 新建任务表单 |
#/settings |
设置面板本身 |
#/settings/<分区> |
设置分区(通用设置 / 模型 / 内置插件 / 已归档会话 / 皮肤 / 使用统计 …) |
#/settings/<分区>/<页签> |
分区里的页签(例如 #/settings/使用统计/Token 银行) |
#/session/<id>/turn/<轮号> |
某一轮的位置(仅反映) |
#/panel/<面板>/pane/<页签> · #/session/<id>/pane/<页签> |
右栏 pane(实验性) |
行为改进
- 链接落地即交权:视图一旦到了链接描述的界面,地址栏立刻交回给视图,不再被拽回上一层。
- 未落地的链接定时重试(每 500ms,8 秒窗口内):不再依赖"界面恰好又变了一次"。
- DOM 观察名单补全(
data-plugin-*全组、aria-current、aria-selected、任务看板两个属性):少了任何一项,对应界面切换时地址栏就会停住不动。 - 切换主面板前先
beginNavigation()(官方布局的配套动作)。 - 行链接的 href 带工作区:右键「复制链接」直接得到带归属的链接。
限制
- 设置分区 / 页签的身份是显示名:换语言或官方改文案后,旧分区链接会失效 —— 重新点击后地址栏会写出新链接。
- 轮次只做反映:粘贴轮次链接仅打开相应对话,不会滚到目标轮(目前DSH官方把跳转能力留在内部,没有对外接缝)。
- 右栏 pane 只跑过单测:本机组合里右栏没有注册任何页签,所以没有真机证据。
- 设置以外的覆盖层(例如市场 / 商店的浏览态)未纳入。
- 会话 / 工作区链接只在同机器、同
DSH_HOME有意义。
测试
npm test —— 61 条(0.1.x 时为 45 条),覆盖新增的每一个界面层与交互边界。
What the address bar can represent has expanded from "conversation / panel" to "workspace + conversation + panel internal pages + three levels of the settings panel + turn position".
New links
| Link | What it is |
|---|---|
#/workspace/<workspace-name>/session/<session-id> |
Workspace-scoped conversation |
#/session/<id> |
Conversation without a workspace; still accepted in the current version |
#/panel/<panel-id> |
Main panel (plugins, task board, skill center, SSH, …) |
#/panel/plugins/<package-name> · …/<package-name>/<component> |
Page for an installed plugin and component pages within it |
#/panel/plugins/<official-item-id> |
Official built-in plugin page (shell / agent-loop / subagent / web-search) |
#/panel/task-board/task/<task-id> · #/panel/task-board/new |
Task details / new task form |
#/settings |
The settings panel itself |
#/settings/<section> |
Settings section (General Settings / Models / Built-in Plugins / Archived Sessions / Skins / Usage Statistics, …) |
#/settings/<section>/<tab> |
Tab within a section (e.g. #/settings/使用统计/Token 银行) |
#/session/<id>/turn/<turn-number> |
Position at a certain turn (reflected only) |
#/panel/<panel>/pane/<tab> · #/session/<id>/pane/<tab> |
Right-hand pane (experimental) |
Behavior improvements
- Hand over control once the link lands: as soon as the view reaches the interface described by the link, the address bar is immediately handed back to the view and is no longer dragged back to the previous level.
- Links that have not landed are retried on a timer (every 500 ms, within an 8-second window): no longer relies on "the interface happening to change again."
- DOM observation list completed (
data-plugin-*entire group,aria-current,aria-selected, the two task board attributes): if any one is missing, the address bar will freeze when the corresponding interface switches. - Call
beginNavigation()before switching the main panel (the companion action for the official layout). - Row link hrefs include the workspace: right-click "Copy Link" to directly get a link with workspace attribution.
Limitations
- Settings sections/tabs are identified by display name: after changing the language or after the official copy changes, old section links will stop working — after clicking again, the address bar will write out the new link.
- Turns are reflected only: pasting a turn link only opens the corresponding conversation; it will not scroll to the target turn (currently official DSH keeps the jump capability internal, with no external seam).
- The right-hand pane has only been unit-tested: in this local setup, no tabs are registered in the right pane, so there is no real-machine evidence.
- Overlays other than settings (e.g. the browsing state of the marketplace / store) are not included.
- Session / workspace links are meaningful only on the same machine and the same
DSH_HOME.
Tests
npm test — 61 tests (45 in 0.1.x), covering every newly added interface layer and interaction boundary.