dsh-ptc-plus 0.4.3 → 0.4.10
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/README.en.md +15 -3
- package/README.md +15 -3
- package/client.js +1157 -533
- package/cordis.patch.yml +12 -2
- package/docs/README.md +2 -0
- package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +60 -4
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +5 -1
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +14 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0023-global-user-bindings.md +1 -1
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +82 -18
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +3 -3
- package/docs/adr/0032-own-session-log-facts-in-a-host-only-projection.md +27 -0
- package/docs/adr/0033-gate-client-visual-usability-in-a-browser.md +23 -0
- package/docs/architecture.md +6 -4
- package/docs/binding-review-placement-design.md +29 -21
- package/docs/client-ui.md +20 -8
- package/docs/client-visual-contract.md +48 -0
- package/docs/durability-design.md +12 -0
- package/docs/installation.md +48 -9
- package/docs/publishing.md +4 -4
- package/docs/release-notes.md +109 -0
- package/docs/runtime-reference.md +8 -2
- package/docs/user-bindings.en.md +2 -2
- package/docs/user-bindings.md +3 -3
- package/docs/verification-optimization-work.md +26 -0
- package/docs/verification.md +7 -1
- package/index.js +28 -7
- package/internal/compiler-platform.js +5 -3
- package/internal/compiler-service.js +2 -9
- package/internal/cordis-tools-owner.js +75 -16
- package/internal/direct-surface-owner.js +333 -7
- package/internal/edit-transport-owner.js +8 -5
- package/internal/execution-provider-owner.js +157 -0
- package/internal/execution-seam-compat.js +69 -113
- package/internal/isolated-worker.js +12 -8
- package/internal/recovery-tips.js +50 -21
- package/internal/rejected-cell-editor.js +11 -21
- package/internal/runtime-bridge-owner.js +88 -57
- package/internal/runtime-contexts.js +13 -13
- package/internal/session-events.js +40 -4
- package/internal/session-journal-recovery.js +678 -181
- package/internal/session-log-view.js +189 -43
- package/internal/session-runtime.js +58 -10
- package/internal/settings-compat.js +12 -2
- package/internal/user-bindings-owner.js +6 -5
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +18 -13
- package/src/client-authoring-view.js +222 -141
- package/src/client-binding-review.js +2 -0
- package/src/client-code-editor.js +6 -0
- package/src/client-copy.js +10 -0
- package/src/client-feature-gates.js +12 -5
- package/src/client-host-compat.js +23 -2
- package/src/client-primitives.js +249 -0
- package/src/client-repl-view.js +3 -3
- package/src/client-settings-view.js +2 -29
- package/src/client-styles.js +92 -33
- package/src/client-tool-view.js +8 -3
- package/src/client-workbench.js +9 -7
- package/src/client.js +72 -46
- package/assets/ptc-plus-bindings-en.png +0 -0
- package/assets/ptc-plus-bindings-zh.png +0 -0
- package/assets/ptc-plus-repair-en.png +0 -0
- package/assets/ptc-plus-repair-zh.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Binding 草稿在当前输入框上方展示
|
|
2
2
|
|
|
3
|
-
状态:完整草稿由已发布的 `conversation.input.dock`
|
|
3
|
+
状态:完整草稿由已发布的 `conversation.input.dock` 承载;历史命令位置只保留请求和只读来源。面板由公开 dock 内的零高度锚点悬浮承载,放大使用公共 Modal,不读取宿主内部几何结构,验收以正式打包后的浏览器实际行为为准。
|
|
4
4
|
|
|
5
5
|
## 产品目标与分发边界
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ PTC Plus 必须独立安装到未经修改的官方 DSH,不能修改宿主源
|
|
|
25
25
|
原生回答尾部、文件产物与操作
|
|
26
26
|
──────────────────────────
|
|
27
27
|
当前输入区
|
|
28
|
-
PTC Plus
|
|
28
|
+
PTC Plus 零高度草稿锚点(预览向上悬浮,不占正文高度)
|
|
29
29
|
名称、用途、导出信息
|
|
30
30
|
完整源码与模型上下文(默认展开,内部可滚动)
|
|
31
31
|
保存为停用 / 保存并启用 / 丢弃
|
|
@@ -33,14 +33,16 @@ PTC Plus 必须独立安装到未经修改的官方 DSH,不能修改宿主源
|
|
|
33
33
|
用户输入框
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
插件以独立 id `ptc-plus-binding-review`
|
|
36
|
+
插件以独立 id `ptc-plus-binding-review` 注册,`order: -30` 将本贡献置于普通 dock 卡片之前。自有锚点留在公开 slot 中但高度为零,面板在 Portal 内从锚点向上 fixed 展开;展开或折叠不改变对话或输入框几何。其他贡献保持各自顺序与布局,预览可覆盖其上方的历史内容,但不向下覆盖普通 dock 卡片或输入框。插件在预览可见时逐帧读取自有锚点,只有几何变化时更新位置与高度预算;只读取 visualViewport 和自有节点,不探测普通 composer 的祖先或宿主滚动容器。CSS 有效预算容不下实际标题、操作行和最小正文时仅呈现标题及放大、关闭按钮;若连完整标题也放不下,则让出预览,保留输入区和历史请求的审阅入口;用户从入口打开时直接放大,关闭放大后焦点回到输入区入口。扩大视口后按原有展示选择恢复。
|
|
37
|
+
|
|
38
|
+
“放大查看绑定草稿”通过公共 Modal 或既有回退组件展示同一候选与动作。该模式仅是 review controller 的展示选择,不新增 RPC、写资格或候选来源。弹窗正文独立滚动,标题和底部动作保持可见;Escape、遮罩或缩小按钮恢复展开预览,已确认保存或丢弃则关闭全部当前展示。
|
|
37
39
|
|
|
38
40
|
该落点不参与 Chat 节点排序,不占用 `turnTail` 的 chain,也不需要调用原生 renderer 再拆解其结果。宿主继续拥有正文、原生尾部、文件产物、分支和滚动容器;插件拥有面板内部渲染与样式。不得用额外的虚假事件把 UI 布局写进 session log。
|
|
39
41
|
|
|
40
42
|
| 方案 | 适用性与本次选择 |
|
|
41
43
|
| --- | --- |
|
|
42
|
-
| `conversation.input.dock`
|
|
43
|
-
|
|
|
44
|
+
| `conversation.input.dock` 中的悬浮预览 | 已发布的 session list 提供会话生命周期和输入区锚点;零高度锚点消除展开对对话高度的影响,内部滚动保留完整内容。 |
|
|
45
|
+
| 公共 Modal 的 Portal | 放大审阅采用此路径;仅在当前输入入口可见时打开,宿主接管时隐藏,保留同一候选与展示选择。 |
|
|
44
46
|
| 替换公开 renderer,再组合公开组件 | 公共契约支持时可以使用;本需求无需接管原生回答渲染。没有公开的“下一个 renderer”入口时,不假定可以组合任意注册项。 |
|
|
45
47
|
| 独立 Conversation 节点 | 适合需要历史位置的业务内容;当前目标不需要,而且同轮尾部节点可能改变原生分支资格。 |
|
|
46
48
|
| 命令位置或原生操作行 | 前者位置过早,后者是紧凑操作区;不作为当前完整审阅的落点。 |
|
|
@@ -79,7 +81,7 @@ PTC Plus 必须独立安装到未经修改的官方 DSH,不能修改宿主源
|
|
|
79
81
|
| 没有可展示的当前候选或已确认回执 | dock 不占空间;历史请求及其已有候选仍可只读查看,不从历史挑一份升级为当前草稿。 |
|
|
80
82
|
| 编写中 | 原命令条目保留已有编写状态;dock 不重复展示一份编写请求,也不把上一份草稿冒充本次结果。 |
|
|
81
83
|
| 已接受,正在确认操作资格 | 新候选首次在 dock 展开,操作按钮暂不可用并说明正在载入。目录读取慢不应让已知源码消失;用户主动折叠或关闭后,读取完成不强制展开。 |
|
|
82
|
-
| 当前草稿可用 |
|
|
84
|
+
| 当前草稿可用 | 按用户选择保持展开、放大、折叠或关闭;展开时显示完整内容和模型上下文,保留保存为停用、保存并启用、丢弃及既有 revision 冲突处理。 |
|
|
83
85
|
| 保存或丢弃成功 | 确认精确候选的处理结果后自动关闭面板;历史保留精确候选和有证据的 action。保存不等于会话已激活。 |
|
|
84
86
|
| 编写失败或旧草稿恢复 | 原请求只显示上述证据规则支持的状态;缺少证据时显示编写结果未知。没有已接受候选就不产生完整 dock 卡片。Host 恢复旧草稿时沿用该候选的展示选择,不自行改变 fallback 规则。 |
|
|
85
87
|
| 资格撤销、Host 重启或只剩历史证据 | 对仍能证明属于当前显示内容的候选保留只读查看;撤下写操作。没有当前身份时不把历史重新挑成活动草稿。 |
|
|
@@ -87,7 +89,7 @@ PTC Plus 必须独立安装到未经修改的官方 DSH,不能修改宿主源
|
|
|
87
89
|
| 切换会话、断线重连、分支或 seed | 按新会话 projection 重建;加载期间禁止沿用旧会话内容和写权限。历史可见性与当前资格分别判断。 |
|
|
88
90
|
| 禁用功能、释放 slot 或卸载插件 | 释放本功能拥有的订阅、计时器和面板;不自动保存、丢弃或执行候选。 |
|
|
89
91
|
|
|
90
|
-
同一会话只保留一个当前完整审阅 controller,按会话、请求、版本和 locator 隔离异步读取与动作。`conversation.chat.commandview` 的 `binding` key 继续渲染原有编写请求,不能因 dock 已注册、已出现或被关闭而返回空内容。保留 `BindingCommandCard`
|
|
92
|
+
同一会话只保留一个当前完整审阅 controller,按会话、请求、版本和 locator 隔离异步读取与动作。`conversation.chat.commandview` 的 `binding` key 继续渲染原有编写请求,不能因 dock 已注册、已出现或被关闭而返回空内容。保留 `BindingCommandCard` 的请求外观和状态区,只移走候选详细内容及写操作。所需展示能力可用且该请求精确对应尚未处理的当前候选时,必须提供“打开草稿”入口,直接进入同一候选的放大审阅,不重新执行 `/binding`;隐藏编写按钮的设置不影响该入口。历史主动查看仍可展开只读源码,但接受候选不得自动展开历史详情,也不能在历史中恢复保存或丢弃按钮。
|
|
91
93
|
|
|
92
94
|
现有页头 popover 的候选展示与保存/丢弃入口也应收拢:保留状态与管理入口,不再创建第二套当前草稿写入流程。历史只读内容可以复用展示组件,但不能恢复控制器或写权限。
|
|
93
95
|
|
|
@@ -95,49 +97,51 @@ PTC Plus 必须独立安装到未经修改的官方 DSH,不能修改宿主源
|
|
|
95
97
|
|
|
96
98
|
写操作仍使用 `save-draft` / `discard-draft`,传递现有 capability、version 及适用的 expected revision。请求切换、组件卸载或资格变动后的迟到响应不能恢复旧按钮;一次失败读取不证明候选已被撤销。待决写入按精确候选隔离:同一候选不重复提交,接受新候选后可独立读取资格和操作,旧响应不能阻塞新候选或清除其 busy 状态。已有必要的资格刷新可以复用,但不能为确定位置或等待回答结束新增轮询、事件订阅或第二套状态机。
|
|
97
99
|
|
|
98
|
-
##
|
|
100
|
+
## 折叠、展开、放大、关闭与重新打开
|
|
99
101
|
|
|
100
|
-
|
|
102
|
+
预览标题栏由折叠/展开按钮、独立放大按钮和独立关闭按钮组成。标题、状态与箭头属于同一个原生折叠/展开按钮,Enter 和 Space 使用原生按钮语义;放大和关闭动作不属于该切换区域,两个操作间距为 12px。放大窗口保留独立的缩小与关闭按钮:缩小恢复预览,关闭隐藏整个草稿面板。展开时箭头朝下表示收起,折叠时朝上表示展开,状态与 `aria-expanded` 一致,并遵循减少动画的系统偏好。完整内容默认展开不等于禁止用户收起。
|
|
101
103
|
|
|
102
104
|
| 用户操作 | 展示结果与草稿状态 |
|
|
103
105
|
| --- | --- |
|
|
104
|
-
| 折叠 |
|
|
106
|
+
| 折叠 | 悬浮预览保留名称、状态、展开、放大和关闭按钮,收起正文及保存/丢弃操作;不改变候选或编写事务。 |
|
|
105
107
|
| 展开 | 未处理候选在原 dock 位置恢复完整内容;已处理候选仅从历史请求查看。写操作仍以当前 Host 证据为准。 |
|
|
108
|
+
| 放大 | 公共 Modal 或既有回退组件显示同一候选;标题和操作保持可见,正文独立滚动。Escape、遮罩或缩小按钮明确恢复展开预览;预览无法完整显示时将焦点返回自有输入区入口。 |
|
|
106
109
|
| 关闭 | 隐藏整个 dock 面板,不保存、不丢弃、不取消编写,也不删除历史请求。 |
|
|
107
|
-
| 重新打开 |
|
|
110
|
+
| 重新打开 | 输入框星光按钮的草稿菜单或当前历史请求的“打开草稿”直接进入同一当前候选的放大审阅;不依赖隐藏期间缓存的预览几何,不重新发命令、生成候选或创建第二个操作 controller。 |
|
|
108
111
|
| 丢弃草稿 | 仅明确点击“丢弃”才调用既有 Host RPC;它与关闭面板是不同操作。 |
|
|
109
112
|
|
|
110
|
-
公开 `conversation.input.left` 只注册一个星光图标,统一插件设置快捷访问、全局绑定管理、编写与当前草稿访问。图标在悬浮或聚焦时以插件署名提示说明来源与用途,有未处理候选时改为提示草稿状态。首条消息前即可通过悬停、点击或方向键打开官方 `Menu
|
|
113
|
+
公开 `conversation.input.left` 只注册一个星光图标,统一插件设置快捷访问、全局绑定管理、编写与当前草稿访问。图标在悬浮或聚焦时以插件署名提示说明来源与用途,有未处理候选时改为提示草稿状态。首条消息前即可通过悬停、点击或方向键打开官方 `Menu`;设置条目直接打开复用完整设置表单的应用内窗口,悬浮提示保留宿主原生设置路径;全局绑定展示名称、用途及启用状态,点击条目切换对所有会话生效的启用配置,并可打开既有完整工作台。有未处理候选时显示数量角标,菜单中单独分组,按名称与状态选择候选后直接放大审阅。菜单中的“编写新绑定”沿用既有命令可用性与输入保护;“修改绑定”是同一个 `Menu` 的第二个步骤,列出已有全局条目,选择后以相同保护预填 `/binding edit <id> `。当前 Host 每会话只保留一份当前草稿,因此角标为 `1`,不把历史候选计为待处理草稿。草稿访问不依赖命令服务;隐藏编写快捷入口时保留已有草稿的星光图标,但不显示全局目录、管理与新建操作。插件与全局绑定功能开关仍统一控制整个入口。
|
|
111
114
|
|
|
112
|
-
|
|
115
|
+
当前宿主菜单使用公共 Portal 和 `getAnchorRect`,以触发按钮自身为锚点定位,按按钮上沿之上的实际可用空间限制插件内容节点的高度;插件通过公开 `Menu.children` 将绑定列表放入可收缩的独立滚动区,新建、修改、管理与设置操作留在不收缩的固定底栏;修改步骤的“返回”也放在底栏,不向宿主菜单节点写入样式。启用、停用分组显示数量,启用项优先,停用项每次打开菜单时默认折叠且隐藏行不渲染。短视口隐藏编写区的文字标题,保留可访问名称和全部按钮。悬停停留 150ms 的意图延迟后才打开菜单,指针扫过输入区不弹出菜单;点击与方向键路径不受延迟影响。菜单由外部点击或 Escape 关闭。悬停打开的菜单在指针离开触发器与列表 200ms 后关闭,重新进入列表或触发器即取消;该宽限覆盖指针短暂离开整个菜单的瞬间,因此越过输入区选择条目仍然可行。点击打开的菜单保持到显式关闭。点击与方向键打开时聚焦首个可用操作,Tab 可到达新建、修改和管理操作;进入“修改绑定”步骤后焦点移到第一个条目。候选变化、会话切换、功能关闭、卸载或普通输入区被接管时关闭菜单;普通刷新不关闭菜单。菜单选择必须向同一 review controller 传递精确候选,不能把旧项点击重定向到新候选。星光菜单和原请求的手动草稿入口直接放大审阅,避免依赖预览关闭期间的旧几何事实;返回预览明确选择 `expanded`,不会重新打开弹窗。原请求条目中的入口也只能打开其精确对应的当前候选;旧请求只允许查看自己的只读历史。展示能力暂不可用时,不提供实际无法打开面板的操作。
|
|
113
116
|
|
|
114
|
-
全局目录由现有 `list` Remote
|
|
117
|
+
全局目录由现有 `list` Remote 按菜单打开动作读取,不轮询;读取在后台进行,期间菜单沿用上一次已确认的目录并保持条目可操作。显式“重新加载”调用 `reload` 重新读取存储文件并清除已修复的读取错误。启停沿用 `enable`/`disable` 与 `expectedRevision`。catalog source 串行化写入并丢弃重复请求,写入期间行保持可用,关闭菜单不取消已发出的操作。启停后条目归入对应分组;菜单仍持有焦点时跟随原条目,原条目进入折叠停用组时回到组按钮。焦点已移出或菜单已关闭时不抢焦点。焦点资格由当前菜单的实际焦点事件拥有,不能沿用待决操作发起时的旧快照;待决写入期间重开菜单后取得的新焦点仍可恢复。打开、步骤切换和归组恢复共用自有列表内的显示操作:适合滚动区的目标靠近最近边缘显示,短窗口下更高的目标居中,只调整自有目录的 `scrollTop`,不滚动底栏或宿主对话。冲突或失败后撤下过期目录,用户重新读取后再决定是否重试,不自动重发写入。重连和组件释放使旧响应失效;菜单读取、显示和启停配置不执行绑定源码。菜单明确区分全局启用配置与待处理草稿,角标只统计草稿。
|
|
115
118
|
|
|
116
|
-
展示选择以 `(sessionId, requestId, candidateVersion)`
|
|
119
|
+
展示选择以 `(sessionId, requestId, candidateVersion)` 归属,包含 `expanded`、`enlarged`、`collapsed`、`hidden` 四种本地状态。当前 Client 内切换会话再返回、RPC 刷新、重连、普通消息追加以及审批临时接管,不重置同一候选的选择;真正接受的新候选默认展开,并从该候选的内容顶部开始阅读;同一候选的普通刷新保留滚动位置。刷新页面或重新加载插件后按当前有效候选恢复默认展开,不要求把展示偏好写入持久存储。共享此选择只协调插件视图,不承载 locator 或 Host 事务资格,也不增加 session log、模型消息或管理 RPC。
|
|
117
120
|
|
|
118
121
|
显隐选择不影响业务操作;精确候选一旦确认保存或丢弃成功,当前面板自动关闭。失败或结果待确认时保留用户的显隐选择:
|
|
119
122
|
|
|
120
123
|
| 结算时的展示选择 | 保存或丢弃已确认成功 | 写入失败或结果待确认 |
|
|
121
124
|
| --- | --- | --- |
|
|
122
125
|
| `expanded` | 自动关闭;回执与精确源码从原请求只读查看。 | 保留完整面板并展示错误或待确认状态;仅在重新证明可写后允许手动重试。 |
|
|
126
|
+
| `enlarged` | 释放弹窗;回执与精确源码从原请求只读查看。 | 保留放大窗口,错误和重试入口随正文滚动;仅在重新证明可写后允许手动重试。 |
|
|
123
127
|
| `collapsed` | 自动关闭;原请求显示处理结果。 | 保持折叠,标题提示有错误或结果待确认,允许用户展开查看。 |
|
|
124
128
|
| `hidden` | 保持关闭,不弹回执;原请求展示有证据的处理结果。 | 保持关闭,保留就近重新打开入口并提示有待查看状态,不自动展开或重试。 |
|
|
125
129
|
|
|
126
130
|
关闭或折叠待决操作中的面板不取消已发出的保存/丢弃 RPC;操作结算仍由同一 controller 接收。未确认处理结果时保留当前候选的访问入口,但入口不证明可以再次写入;一次网络错误不能触发重新提交。已确认保存或丢弃后移除两个当前草稿打开入口,结果和精确候选继续从原历史请求只读查看。确认结果统一由当前 controller 收敛:保存响应、精确 review RPC 或 projection 回执均关闭匹配候选,普通刷新不能重新打开;旧候选的迟到结果不能关闭新草稿。locator 撤销本身不证明处理成功。
|
|
127
131
|
|
|
128
|
-
|
|
132
|
+
用户关闭时,焦点移到就近且可见的星光按钮,聚焦本身不弹出菜单;按钮缺席时使用仍可见的插件自有入口。当前公开契约没有 composer 焦点接口,焦点恢复只操作这些自有返回目标;入口不可用时不查找宿主编辑器。成功后自动关闭仅在面板原本持有焦点时恢复焦点,不能打断用户在其他区域的操作。异步成功移除当前聚焦的打开入口时也应保持合理焦点,不能将其留在已移除节点;宿主接管时不从审批界面抢焦点。折叠按钮提供 `aria-expanded`,被隐藏的内容不得继续接受键盘焦点。
|
|
129
133
|
|
|
130
134
|
## 输入区接管与布局边界
|
|
131
135
|
|
|
132
136
|
官方普通 composer 是 `conversation.composer` chain 的 fallback。当前实现使用 `overlay: true`:其他 contribution 被选中时,fallback 保持挂载但被 `display:none` 隐藏,因此 input dock 也会隐藏。**注册成功不等于任何时候都可见;隐藏也不等于已卸载。**
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
审批或其他宿主交互接管输入区时,草稿区和重新打开入口随普通输入框一起暂时让位。放大弹窗由输入入口的自有 IntersectionObserver 可见性证明控制 open,入口不可见时释放 Portal 展示,但保留放大选择;不会把保存按钮强行叠到审批上。PTC Plus 的 REPL 视图接管 composer 时也按此规则隐藏;回到普通输入区后恢复同一份有效草稿及其原有展开、放大、折叠或关闭选择。重建时读取 projection 和 RPC,不依靠隐藏 DOM 保留权限。长驻 controller 必须能处理隐藏期间的撤销;用于刷新资格的任务仍受功能和会话生命周期约束,不能只依赖 unmount 清理。
|
|
135
139
|
|
|
136
140
|
普通对话中的正文继续流式输出、产生工具结果或开始下一轮,不是隐藏卡片的理由。所需边界是“普通输入区是否被宿主接管”,不能把 `input` 的任意 busy 状态当作隐藏条件,也不要求用户等待真实轮次结束。
|
|
137
141
|
|
|
138
|
-
|
|
142
|
+
面板采用不透明主题底色、细边框与阴影,明确表达临时浮层;插件拥有的标题、滚动正文和操作区以分隔线区分。名称只在标题出现,正文保留导出信息、用途、完整源码及模型上下文;丢弃与保存动作分置两侧,窄屏允许换行。预览以 dock 的插件自有零高度锚点为基准,宽度不超过 `44rem`;普通宽度两侧留 `16px`,窄屏两侧留 `8px`。预览通过 Portal 挂到 `document.body`,使用自有锚点与 visual viewport 的坐标定位;不读取或修改宿主祖先。
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
长内容必须保留完整文本并在内部滚动,不能以截断源码换取高度。预览以 `min(440px, 45dvh, 锚点上方可用高度)` 为上限;正文伸缩,保留至少 `40px` 的滚动窗口并以 `20rem` 为上限。CSS 拥有有效高度预算,以实际标题及面板边框判定预览是否可展示,不能为保留标题向下跨越锚点;正文最小高度计入分隔边框,保证至少 40px 的可滚动内容高度。若预算容不下标题、最小正文和实际操作行,预览只显示标题及放大、关闭入口,隐藏内容不可聚焦。放大弹窗使用独立的大尺寸预算,不继承预览和 `20rem` 限制;标题、操作行固定,完整源码、上下文及错误消息在正文内滚动。短视口使用更小外部留白,操作按钮按实际宽度换行。展开与折叠只改变零高度锚点上的插件浮层,不为定位读取宿主祖先、滚动容器或私有 CSS。隐藏、处理成功和卸载释放插件自己的交互状态,不持续滚动正文。浏览器验收同时检查实际点击命中、小视口下输入框与其他 dock 的可达性,不能仅凭注册成功或静态截图证明可用。
|
|
141
145
|
|
|
142
146
|
源码和模型上下文默认展开。历史详情和 dock 共用只读模型上下文区,以“接口声明”状态标签说明是否向模型提供,并单独呈现完整提示词或空状态;不使用禁用的表单控件表示配置。当前卡片不采用 hover 才显现的布局,不自动抢焦点或持续调用 `scrollIntoView`。键盘可进入内容滚动区和所有动作,窄屏操作行允许换行,动态视口下仍能访问输入框与审批。共享 list 的顺序只管理本插件贡献,不重排其他插件。
|
|
143
147
|
|
|
@@ -164,9 +168,9 @@ slot 的迟到、释放、再次声明和功能开关必须测试。缺少所需
|
|
|
164
168
|
| --- | --- |
|
|
165
169
|
| 官方安装 | 正式 tarball 安装成功,Host 源码和安装文件不变,实际加载最终插件 bundle。测试 fixture 自行声明 slot 不能替代此项。 |
|
|
166
170
|
| 请求与位置 | `/binding new`、`edit` 发出时保留历史中原有的绑定编写请求样式;接受后只更新请求状态,完整详情和写操作首次在 dock 展开,原条目不消失也不变成完整操作卡片。 |
|
|
167
|
-
| 展示控制 | 点击折叠态的标题文字即可展开,Enter/Space
|
|
171
|
+
| 展示控制 | 点击折叠态的标题文字即可展开,Enter/Space 同样可用,箭头随状态变化;展开/折叠不改变锚点、composer 和对话滚动范围;放大后正文具有更大阅读高度、独立滚动和固定动作,缩小返回预览,独立关闭按钮隐藏面板;浏览器验收比较完整 composer 几何与对话高度,并确认输入框、其他 dock 和面板操作可达。正文滚动范围继续由宿主布局决定。关闭仅隐藏,输入框旁与当前请求都能重新打开;同一候选的 RPC 更新、重连、普通消息和审批接管不覆盖用户选择,新候选首次展开。 |
|
|
168
172
|
| 内容与操作 | 精确源码和模型上下文默认可读;保存为停用、保存并启用、丢弃、busy、冲突、失败及回执正确。 |
|
|
169
|
-
| 结算与显隐 |
|
|
173
|
+
| 结算与显隐 | 保存或丢弃过程中分别保持展开、放大、折叠和关闭,验证成功、失败及结果待确认组合。已确认成功自动关闭面板并释放弹窗;已处理后的两个当前入口移除,回执与源码从原请求只读访问。 |
|
|
170
174
|
| 请求状态证据 | A 已有草稿,B 命令成功准入后未接受候选,projection 回到 A;B 在重新挂载、分页和重连后显示准入成功及编写结果未知,不能冒用 A 的 ready 或推断失败。命令处理错误、匹配 projection 的 failed、接受及 action 各自只归到对应请求。 |
|
|
171
175
|
| 候选与异步 | 新请求、旧请求恢复、跨会话、迟到 RPC、断线、重启、分支和 seed 不串候选,不以历史或旧 locator 恢复写权限。 |
|
|
172
176
|
| 唯一控制器 | 命令处和页头不再同时出现另一套当前保存控件;折叠或关闭期间的写操作不会丢失结算或重复提交。主动展开历史仅只读,分页不重新挂载活动控制器。 |
|
|
@@ -178,6 +182,10 @@ slot 的迟到、释放、再次声明和功能开关必须测试。缺少所需
|
|
|
178
182
|
|
|
179
183
|
按项目 ledger 流程记录实施发现,按预先声明的独立 review lanes 取得各 lane 的有效 verdict,最终在稳定树上依次运行 `npm run check`、用 `npm run review:finalize` 记录 composite verdict,再运行 `git diff --check HEAD --`。独立审查、确定性测试、实际 UI 验收是不同证据;不能把其中任一项替代其余。提交与发布仍遵循用户授权及独立审查条件。
|
|
180
184
|
|
|
185
|
+
悬浮预览可能随多行输入或其他 dock 而被宿主可视区域裁剪。预览只读取自有零高度锚点与 visualViewport,定位独立 Portal 并收紧自有 `max-block-size`,不遍历或读取宿主祖先来推算剩余空间。
|
|
186
|
+
预览关闭、放大、输入入口不可见或卸载时释放动画帧跟踪。
|
|
187
|
+
放大弹窗不沿用预览的尺寸预算,使用 Modal 的视口限额和内部 flex 正文。这种自有尺寸治理不声明可以重新布局其他贡献,也不取得宿主滚动权限。
|
|
188
|
+
|
|
181
189
|
## 公共契约与历史证据
|
|
182
190
|
|
|
183
191
|
已核对官方源码中的 slot 声明、原生根布局和贡献实例,以及已安装官方包的类型声明与实际 Client bundle 中的 dock 渲染。它们证明接口存在及设计落点可用,尚不证明 PTC Plus 面板已实现或完成浏览器验收。
|
package/docs/client-ui.md
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
# Client UI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
标准 `verify`、`check` 与 CI 的 `verify:ci` 均执行 `test:client:visual`,在一次 Client 测试生成的实际 renderer 夹具上检查关键控件的尺寸、可读性、悬停、键盘焦点、禁用反馈及布局。浏览器准备、覆盖清单、故障反例与官方宿主验收边界见 [Client visual contract](client-visual-contract.md)。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
PTC Plus 提供**插件设置卡片**。卡片座位由宿主代际决定:更早、未冻结的代际在 DSH Web/Desktop 的 Settings → Plugin configuration 中以 `settings.plugin.item` 渲染,当前代际在侧栏 Plugins → Installed 页面以 `plugins.row.config`(键 `<包名>#<行 id>`)渲染该 bundle 自己的配置;General 设置不是本卡片的座位,`src/client-host-compat.js` 只发布到这两个插件配置座位,由声明了槽位的那一代决定哪个生效,卡片按座位提供的 `summary`/`page` 视图分别渲染一句描述与完整表单。输入框旁的星光菜单还直接打开复用同一表单的应用内设置窗口,不依赖宿主页面的局部导航状态;菜单项悬浮提示保留原生设置座位的路径。
|
|
6
|
+
|
|
7
|
+
Client 根入口只依赖 `slots`、`locale`、`connection` 和 `remote`;settings transport 由当前代的 `configForms` 或更早未冻结兼容支的 `settingsScope` 可选注入提供,两者都缺席时不再等待某个名字出现:插件以 `internal/config-spec.js` 的默认值参与订阅,transport 出现时自动接管,因此改名或裁剪设置传输只会降级设置面,不会让根入口在注册任何贡献之前挂起。功能资格只被显式关闭:可读快照按字段判定,不可读快照按同一份默认值判定,`enabled: false` 才关闭。头部贡献直接消费公开 session slot 提供的 `useProjection`;REPL 注册另依赖 `sessions` 的当前选择和 projection face。命令卡片等待公开 command slot,composer 管理入口直接消费现有管理 Remote;其中的编写动作再等待 `remote.commands` 与公开输入 hooks,不依赖已改名的 conversation registry 或未使用的 `ui-session` 模块。缺失、卸载或迟到的 slot/provider 只影响需要它的贡献;没有 `useProjection` 时不挂载依赖它的会话视图,命令卡片保留宿主结果但不提供草稿操作。没有输入 hooks 时不显示编写动作,已有全局绑定仍可查看和启停。preset 优先读取 `agentPreset` projection,缺失时依次读取会话公开摘要里的 projection 值与旧宿主的 `agentPreset` 字段;binding 值和草稿资格不采用该回退。当前会话身份取宿主已发布的选中证据:更早未冻结的选择形状在会话列表上投影 `current`,当前代际把视图选择留在 controller 之外、以主视图持有的会话表达。两者都不读取私有 store。设置和独立正文 tool view 继续可用,不读取私有 store 或自行重建会话状态。
|
|
6
8
|
|
|
7
9
|
组件通过 renderer 提供的 `useProjection`、旧宿主的公开 `useSessions` 和注入 `hooks` 读取外部状态,设置写入与 RPC 由 apply 层注入 callback。业务组件不自行构造 external-store hook。设置、slot、provider 与插件释放共同拥有注册和订阅的生命周期;开关关闭时撤销相关贡献。
|
|
8
10
|
|
|
11
|
+
设置 transport 各自拥有 injection registration 和订阅,即使两者返回同一个 preference face 也不共享释放身份。`configForms` 优先,仍存活的 `settingsScope` 保持备用;优先项移除后读写回到备用项,不以默认开启覆盖其显式关闭值。移除备用项不得撤销当前项,插件释放回收所有订阅。
|
|
12
|
+
|
|
9
13
|
REPL 对 composer 的接管优先使用当前公开 `sessionId`/`pendingInteraction` 参数;旧宿主仅在 `session.sessionId` 匹配且 `interactions` 为空数组时允许接管。审批、提问和无法确认的交互状态继续显示宿主 composer,不通过 DOM 隐藏输入框。
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
冻结 Host 图只证明当前成员;更早回退的 fixture 证据和误删后果见[安装:兼容证据](installation.md#compatibility-evidence)。这些接口形状差异由 `src/client-host-compat.js` 集中处理:组件使用 `useSessionPreset`,注册层使用 `watchCurrentSessionPreset` 跟随当前会话及其 projection,并用 `isIdleSessionComposer` 判断 composer 资格。适配模块负责证据优先级与订阅切换、释放;`src/client.js` 负责设置开关、PTC 功能资格和 slot 生命周期。当前会话变化时重新读取公共能力,不缓存全局宿主版本或会话能力。
|
|
16
|
+
|
|
17
|
+
Client 按数据、传输、注册与视图分文件,沿用既有 `createX(React, deps)` 工厂:`src/client-copy.js` 拥有双语字典,`src/client-styles.js` 拥有样式数据、样式表的 DSH 归属(创建时即写 `data-plugin`/`data-plugin-css`,因此不会被后物化的插件认领,也不会随别的插件被删除)以及对依赖方挂载的全局样式表(CodeMirror 的 style-mod)的收编,`src/client-primitives.js` 拥有“宿主 primitive → 可用组件”的唯一解析与缺失兜底,`src/client-rpc.js` 与 `src/client-transport.js` 拥有 Remote 调用和观察传输,`src/client-feature-gates.js` 拥有“设置快照 → 功能资格”的唯一映射与受门控注册,`src/client-catalog.js` 拥有全局目录读取,`src/client-workbench.js` 拥有工作台状态迁移与视图,`src/client-settings-view.js`、`src/client-tool-view.js`、`src/client-repl-view.js`、`src/client-authoring-view.js`、`src/client-indicator-view.js` 各自拥有一个 slot 的视图。`src/client.js` 只做装配与注册,不持有业务状态。设置快照到功能布尔只有一个纯函数(`featureEnabled`),受门控贡献共用一个“订阅 → 判定 → 注册/注销 → 回滚”实现(`registerGated`);preset、projection 和公共能力仍由各自 owner 判定,在调用点与设置资格组合。
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
## 缺失组件回退
|
|
20
|
+
|
|
21
|
+
回退菜单和弹窗的输入法 guard 覆盖 compositionstart 到 compositionend 后的 closing key;该 key 被消费或 keyup/window blur 释放后,独立普通 Escape 才能关闭。每次按下 Escape 只关闭一层,repeat 事件仍被消费但不再次关闭外层弹窗。该边界与原生 primitive 的生命周期一致,保留尚未保存的草稿。
|
|
22
|
+
|
|
23
|
+
缺失 primitive 包或 `Menu.children` 时,插件自有菜单保留入口的正常布局,列表通过 React DOM 基线 portal 到 `document.body`,只用公开 `getAnchorRect` 与 viewport 为自己的列表定位和限制高度。自有 Modal 的普通与 `headless` 模式共用 portal、mask 和焦点层;`headless` 只移除默认标题与正文装饰,不取消模态遮罩。`npm run test:client:fallback` 在隔离 Chromium fixture 中验证小视口菜单操作、背景 pointer 阻挡与关闭后的焦点返回;它不替代 packed Host 的完整浏览器验证。
|
|
14
24
|
|
|
15
25
|
## 设置命名空间
|
|
16
26
|
|
|
17
|
-
Host half
|
|
27
|
+
当前 Host half 的 `Config` 文档由 DSH 公共 `settings` 服务按 owning Loader entry 的 profile ID 寻址;更早 section installer 兼容支仍注册 `ptc-plus` 命名空间。失败补偿由 settings compatibility owner 绑定同一写入身份,不把固定 namespace 当作 profile entry ID。字段清单、默认值和校验来自 `internal/config-spec.js`,
|
|
18
28
|
由 `index.js` 的 `Config` schema 与设置注册共用;client half 构建时把同一份字段清单打进 bundle,不在 UI 中复制默认值。`CONFIG_GROUPS` 独立拥有按用途排列的展示顺序:插件总开关单独置顶,其后为“调用容错”“REPL 语法”“状态与恢复”“工具扩展”“界面显示”“资源限制”。每个字段只展示一次,各组使用独立标题、留白与分隔线。
|
|
19
29
|
|
|
20
30
|
## 可用设置
|
|
@@ -47,7 +57,7 @@ Host half 通过 DSH 公共 `settings` 服务注册命名空间 `ptc-plus`。字
|
|
|
47
57
|
|
|
48
58
|
## 全局用户 Binding 工作台
|
|
49
59
|
|
|
50
|
-
`/binding new` 和 `/binding edit` 的历史命令处保留原始需求、状态和错误说明。候选被接受后,完整源码、模型上下文与保存/启用/丢弃操作由官方 `conversation.input.dock`
|
|
60
|
+
`/binding new` 和 `/binding edit` 的历史命令处保留原始需求、状态和错误说明。候选被接受后,完整源码、模型上下文与保存/启用/丢弃操作由官方 `conversation.input.dock` 在当前输入框上方承载;历史条目只提供该请求自己的只读来源。公开 dock 内的零高度自有锚点定位 Portal 内的 fixed 悬浮预览,避免宿主裁切与层叠覆盖;只在预览可见时跟踪自有锚点和 visualViewport 的几何变化,可用高度不足时收为标题栏,仍可放大审阅,不测量或改写宿主祖先与滚动容器;展开和折叠不改变对话或输入框高度。该贡献排在普通 dock 内容之前,预览向上展开。放大通过公共 Modal 或既有回退弹窗承载同一个候选内容与操作区;正文独立滚动,标题与底栏保持可达,Escape、遮罩或独立缩小按钮返回预览,关闭按钮则隐藏面板;尺寸切换和关闭按钮之间留有间距。弹窗只在当前输入入口可见时显示,宿主接管时隐藏并保留展示选择。整条标题按钮支持点击与 Enter/Space,箭头随折叠状态变化;菜单条目与焦点恢复只操作插件自有内容节点,定位由公开 Menu 的 anchor/getAnchorRect/portal 契约承担;没有 children 的历史 primitive 使用自有菜单兜底。设置窗口的初始焦点使用 `data-modal-autofocus`,焦点回环交给 Modal;没有 composer 焦点接口时返回自有入口,不寻找宿主编辑器。输入框只保留一个星光入口:首轮前即可通过官方 Menu 悬停、点击或键盘查看全局绑定、切换启停及打开完整工作台;设置条目直接打开复用设置卡片表单的应用内窗口,关闭后将焦点还给仍可用的星光按钮;编写命令可用时显示“编写新绑定”,并在同一个 Menu 内提供“修改绑定”第二步来选择已有条目。该入口与头部标识、REPL 页签同属 PTC surface:只在当前会话使用 `ptc` 或兼容 `code` preset 时注册,其他 preset 既不显示入口也不读取该会话的命令目录。该入口以插件署名提示说明来源与用途,有草稿时改为提示待处理草稿。有草稿时显示数量角标,草稿在独立分组中选择。当前 Host 每会话只保留一份候选,菜单不列出过期历史;隐藏编写快捷入口或命令服务缺席不影响已有草稿的访问。关闭和重新打开只改变展示,不撤销候选或待决 RPC。保存或丢弃确认成功后面板自动关闭;失败和结果待确认时保持用户的显隐选择。候选身份、写资格和异步结算由一个 Client review controller 复用 draft projection 与现有 RPC owner,页头不再提供第二套当前写操作。实现细节与验收证据见[Binding 审阅位置设计](binding-review-placement-design.md)。
|
|
51
61
|
|
|
52
62
|
`userBindingsEnabled` 关闭时不渲染任何 Global User Binding 管理界面,Host 也不注册对应 RPC 或 Agent 命令。开启后,REPL 页签中的“全局绑定”和设置管理按钮打开的大尺寸应用内弹窗复用同一个 `UserBindingsWorkbench`。设置卡片保留开关与管理按钮,不嵌入编辑器。普通管理不依赖当前存在 PTC 会话;Agent 辅助编写仍使用当前可用会话的 `/binding` 入口。
|
|
53
63
|
|
|
@@ -81,7 +91,9 @@ PTC session 的头部弹窗在功能启用时增加 Session 与 Global 页签。
|
|
|
81
91
|
|
|
82
92
|
`enhancedToolView` 默认开启并即时生效。开启时 PTC Plus 通过公共 keyed tool-view surface 为 `run_code` 与 `edit_run_code` 提供增强行,并在可用时使用 DSH 公共 `DisclosureRow`/`CodeBlock` primitive,缺少某项 capability 时使用插件自有的等价降级;关闭时立即注销这两个 keyed view,由 DSH 原生 generic row 负责布局、状态、代码高亮和输入/输出卡片。该开关只影响 Client 展示,不改变工具、prompt、runtime 或 session 语义。composer 星光入口使用公共 `Menu`、`Tooltip`、`Toast`、`Modal` 和 `IconSparkle16`;设置窗口复用设置卡片的完整表单与写入 callback,星光菜单的“修改绑定”第二步继续使用同一公共 `Menu` 的条目、滚动与键盘语义。缺失 `IconSparkle16` 时降级为纯文本按钮,缺失 `Toast` 时使用插件自有的内联状态提示;缺失 `Tooltip` 时悬浮说明由原生 `title` 承载。
|
|
83
93
|
|
|
84
|
-
|
|
94
|
+
星光菜单的自有内容根拥有 13px/18px 基础字号与行高,停用组标题和绑定名称使用 13px,说明使用 12px、启停状态使用 11px;通过 portal 挂载后也不继承宿主的字号与行高。长名称和说明保留单行省略及完整 `title`。星光菜单通过公开 `Menu.children` 将目录滚动区与不收缩的底部操作区分开;只有目录滚动,四个操作和修改步骤的“返回”保持可见。启用条目优先显示,启用与停用标题带数量,停用组每次打开默认折叠;折叠行不渲染。启停后焦点跟随同一条目,条目进入折叠停用组时返回该组按钮,菜单关闭或外部已有焦点时不抢焦点。菜单实际获取和离开焦点的事件拥有恢复资格,待决请求期间关闭再重开也遵循当前资格;初次打开、步骤切换和归组恢复共用自有目录内的焦点显示操作,只调整该目录的 `scrollTop`,不调用祖先 `scrollIntoView`。短视口隐藏底栏的编写文字标题,保留分组的可访问名称和按钮。星光入口的四个动作(编写新绑定、修改绑定、管理全局绑定、PTC Plus 设置)由插件自己的动作区承载:`Agent 编写` 分组标题、两列网格及工具入口。公开 `Menu` 能挂载 `children` 时,该动作区放入其 `children`;缺少 Menu primitive 或已确认不挂载 `children` 时,同一份动作区交给 `src/client-primitives.js` 的自有 `MenuFallback`。列表通过 React DOM portal 呈现,以公开 `getAnchorRect` 和视口预算定位,保留分组、文案、顺序、设置座位提示与可用操作。
|
|
95
|
+
|
|
96
|
+
`src/client-host-compat.js` 以实际挂载输出判定 `children` 能力:首个 composer 入口在隐藏、非 portal 的 Menu 中放入插件自己的哨兵子节点,读取后丢弃探测。答案只记录一次,后续会话入口复用;未挂载或探测失败时不记录能力结论。该探测只读取插件创建的节点,fallback 的定位、滚动与焦点也由自有节点承担,具体边界见前述 primitive 降级契约。
|
|
85
97
|
|
|
86
98
|
悬浮窗里的条目启停不改变列表的可用性:写入由 catalog source 串行化、重复请求被丢弃,因此请求期间行不会被禁用(宿主会给禁用行降透明度)也不会插入“正在保存”行,避免整个悬浮窗在每次切换时闪一下;只有尚无目录可操作或读取失败时行才不可用。
|
|
87
99
|
|
|
@@ -95,7 +107,7 @@ PTC session 的头部弹窗在功能启用时增加 Session 与 Global 页签。
|
|
|
95
107
|
|
|
96
108
|
投影通过 DSH 正式的 `tool/call.data.callId` / `tool/result.data.message.source.callId` 身份配对 `run_code` 与 `edit_run_code`,不依赖可选 `sourceEventSeqs`。它只接受当前 runtime generation 的 envelope,并在 `session/end-seed` 清除旧 lifecycle 的 live 证明;缺少、损坏、其他 generation 的 metadata、无关 tool result 与不影响 binding provenance 的 result-only replacement 都不能覆盖仍有效的最后已证明清单。若 surface replacement 遮蔽了声明 provenance,runtime 与 projection 共用的 model-visible frontier 判定会让相关 inventory 失效。缺少有效 metadata、projection service 或兼容 registration contract 时只显示不可确认,不主动读取历史、不迁移日志,也不影响继续会话。来源跳转要求 Host 提供打开 tool call 或 source location 的公共 capability;缺少该 capability 时,卡片只提供内联检查,不访问私有 store 或宿主 DOM。
|
|
97
109
|
|
|
98
|
-
`enhancedToolView` 开启且插件启用时,Client 通过公共 keyed `tool.call.toolview` 注册 `run_code` 与 `edit_run_code`;任一开关关闭时实时 dispose 两个注册,让 owner 恢复 DSH 原生 fallback。这个正文 slot 只依赖 Host 提供的 key、`toolName`、`sessionId`、`useSessions`、运行中/已结算 `block` 与 `inspect` 公共契约。增强行保留 Code / Code edit 标题、可展开的原始源码(`arguments` 与 `argsRaw` 任一公共形态均可读)、结果、可见且可访问的运行/失败/中断状态和 Inspect 入口;在提供时优先使用公共 `DisclosureRow` 与 `CodeBlock`,缺少 `DisclosureRow` 时回退到插件自有行,缺少 `CodeBlock` 时回退为纯文本源码。`DisclosureRow`
|
|
110
|
+
`enhancedToolView` 开启且插件启用时,Client 通过公共 keyed `tool.call.toolview` 注册 `run_code` 与 `edit_run_code`;任一开关关闭时实时 dispose 两个注册,让 owner 恢复 DSH 原生 fallback。这个正文 slot 只依赖 Host 提供的 key、`toolName`、`sessionId`、`useSessions`、运行中/已结算 `block` 与 `inspect` 公共契约。增强行保留 Code / Code edit 标题、可展开的原始源码(`arguments` 与 `argsRaw` 任一公共形态均可读)、结果、可见且可访问的运行/失败/中断状态和 Inspect 入口;在提供时优先使用公共 `DisclosureRow` 与 `CodeBlock`,缺少 `DisclosureRow` 时回退到插件自有行,缺少 `CodeBlock` 时回退为纯文本源码。`DisclosureRow` 路径把运行/失败/中断状态、摘要和已证明的功能标记放进始终可见的预览区,摘要可换行,功能标记独立排列在其下方;完成态由标题与摘要表达,运行/失败/中断状态由文字 chip 承担并保持可访问。插件通过公共 class 槽位让标题行按内容高度伸展,标题和图标与预览首行顶端对齐,摘要与功能标记之间保留 4px 间距;Host 继续拥有展开交互。源码、结果和 Inspect 只出现在展开主体。结果内容与原生 ioCard 采用相同的灰色圆角背景(`--dsw-alias-markdown-code-block` 加 12px 圆角与边框),失败态使用错误色文字;代码块的语言/复制栏保持原生 CodeBlock 的常亮可见;`检查调用` 入口采用原生 inspectButton 同款胶囊样式,默认 opacity 0,仅在卡片 `:hover` 或 `:focus-visible` 时淡入(opacity .1s),不触发任何布局位移。窄屏下回退路径的摘要允许换行。
|
|
99
111
|
|
|
100
112
|
功能标记不是计数,也不把“插件已启用”冒充成一次功能收益。Client 只在完整 v1-v10 journal 和对应附属 metadata 能证明时显示:自动改写 import(附模块名)、自动剥离 export、自动拆分混合重声明(附已有 binding)、带完整 target/derived-run/non-noop/可选恢复边界关系且与调用目标前置条件一致的安全编辑执行、成功的 `code.run`、由 `PTC-R002` 的 `warning/recover/rolled-back` 语义元组证明本次确实发生的持久重放,以及 `repl.state` 操作。Client 对 v4 同时封闭校验 `bindingPolicy`、`rewritePolicy` 与 `moduleSemantics`,对 v5 还要求 `userBindingsFingerprint`,对 v6 进一步要求 `userBindingsReusePolicy` 为 `fingerprint-v1` 或 `implementation-v1`,对 v7 还要求 `moduleSemantics` 携带可识别的 `importExpressionBoundary`(v1-v6 的 `moduleSemantics` 保持只含 `defaultExportBinding` 的封闭字段集),对 v8 还要求 `userBindingsShadowPolicy` 与 `userBindingNames` 通过封闭校验,对 v9 进一步要求已知的 `languageSemantics`,对 v10 还要求 `moduleTransform` 与语言契约匹配;任一缺失或畸形都不产生功能标记。进程保留或 discarded 状态不作为正文功能标记。普通变量或 function/class 重声明、顶层 native 调用是否来自 canonicalizer、`cordis_*` 成员是否由官方可选 Cordis mount 提供,以及是否实际选择了 prompt 恢复提示没有独立的 Client-only 事实,因此不根据可复制的代码形状、工具名前缀或设置默认值推测;恢复边界本身不展示。
|
|
101
113
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Client visual contract
|
|
2
|
+
|
|
3
|
+
The Client must expose readable, distinguishable and reachable computation controls. DOM classes and functioning RPC handlers do not establish that obligation. `scripts/client-visual-contract.mjs` owns a bounded browser oracle used by deterministic fixtures and packed official-Host acceptance. This is a usability contract, not a pixel snapshot of DSH.
|
|
4
|
+
|
|
5
|
+
## Gate and prerequisites
|
|
6
|
+
|
|
7
|
+
Install the lockfile dependencies and the matching Playwright browser before verification:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npx playwright install --with-deps chromium
|
|
11
|
+
npm run test:client:visual
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`test:client:visual` runs the Client suite once, exporting actual renderer DOM and current plugin, public primitive and CodeMirror CSS to a newly created ignored directory. The layout runner consumes that invocation's fixtures; missing fixtures, unavailable browsers and failing children fail the command. Its temporary HTML is removed afterwards. The standalone layout entry also removes its own directory after fixture failure, browser-launch failure or completion; an explicitly supplied fixtures directory remains owned by its caller. Screenshots and measurements remain under ignored `artifacts/binding-layout` and `artifacts/button-styles` as diagnostics; screenshots alone are not acceptance assertions. `verify`, `check` through `verify`, and every `verify:ci` matrix entry include this command. CI installs Chromium explicitly and does not download browsers inside the gate. An installed compatible Chromium channel can be selected for focused diagnostics with `--browser-channel msedge`.
|
|
15
|
+
|
|
16
|
+
## Coverage
|
|
17
|
+
|
|
18
|
+
All fixture families exercise light and dark reference palettes, English and Chinese, and widths 320, 390 and 1440 px. Reference tokens deliberately exercise both foreground polarities; they do not claim to reproduce official or customized themes. The separate model-free packed acceptance uses DSH's public theme settings on an unmodified official Host, reuses the oracle for dock actions and the global workbench, and retains its existing actual editor, permission, session-log and layout assertions.
|
|
19
|
+
|
|
20
|
+
| Surface | Actual controls | Visual states and evidence |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| Settings and settings dialog | Disclosure, action, numeric input, select, checkbox switch | Normal, keyboard focus, disabled feedback; hover for commands/disclosure; dialog containment |
|
|
23
|
+
| Global workbench and dialog | Selection, enable switch, icon commands, action buttons, input, instructions, search | Normal, focus, hover where the control or its owner supplies it, disabled feedback, long-label geometry |
|
|
24
|
+
| Draft dock and enlarged review | All three actions, disclosure, separate resize/close icon controls, author attention badge | Native and absent-Button fallback matrix; normal, hover, focus, disabled, actual busy rendering; Enter saves exactly once; combined 320×240/320/400 short-width cases with long source and RPC errors, expanded reading thresholds and near-top anchors |
|
|
25
|
+
| REPL | Observation selection, search, tabs, definition disclosure, four binding-name kinds | Normal and keyboard focus, definition hover, light/dark name readability, long inventory and source geometry |
|
|
26
|
+
| Sparkle menu | Binding rows, disabled-group disclosure, authoring/revision/management/settings and fixed Back | 48 mixed entries; enabled-first counts and default collapse; native/fallback, English/Chinese, light/dark at 390×600, 320×420 and 320×240; independently scrolling catalog, fixed footer, actual action hits and keyboard access; single disabled entry with long purpose, 14px/21px and 24px/36px carrier typography |
|
|
27
|
+
| Command card | Action and native source disclosure | Readable/reachable actions, focus, disabled feedback; saved card remains compact |
|
|
28
|
+
| Tool row | Official DisclosureRow and fallback summary, inspection action, running/error/stopped status and description | Typography hierarchy, long descriptions, absent/multiple feature labels and long details; text containment, nonoverlap, preview spacing and separation from the following message; Enter expansion and inspection, focused inspection becomes visible |
|
|
29
|
+
|
|
30
|
+
Tool previews may contain multiple lines. The plugin's public DisclosureRow class slots size the header to its content and align the title with the first preview line; the Host retains the component and interaction behavior. The browser oracle measures text ranges against the card, header and clipping ancestors within the card, rejects intersecting text and requires a readable gap before feature labels. Horizontal ellipsis remains valid for descriptions and feature details; it does not allow vertical text clipping or lost titles, states or feature names. Injected fixed-height clipping and removed preview spacing must fail on the real renderer. Packed acceptance with `--binding-workflow` produces recorded import/export features through the official execution pipeline and checks the actual collapsed and expanded tool row at narrow and wide widths. The default packed smoke's synthetic typography probe establishes only that the shipped CSS is installed.
|
|
31
|
+
|
|
32
|
+
The oracle requires actionable button padding of at least 10 px and height of at least 28 px, other controls of at least 16 px height, viewport containment and center hit reachability after scrolling. Enabled text (including nonempty input/textarea values and selected options) and relevant icon foregrounds must have at least 3:1 contrast against the alpha-composited ancestor background; primary actions must retain a nontransparent fill. Hover feedback must change a painted foreground, background, border or shadow without resizing. Keyboard focus must establish `:focus-visible` and a contrasted outline, a changed contrasted border or solid outer shadow ring of at least 1 px (zero offset and blur, positive spread), or the search owner's contrasted `:focus-within` outline. Disabled controls must change opacity/color, retain the disabled cursor and reject focus. Presentation probes restore the previous disabled property without dispatching business events. The dynamic dock additionally obtains disabled state from its real busy view; recorded callbacks prove the probes do not save or inspect accidentally.
|
|
33
|
+
|
|
34
|
+
Each declared responsibility must occur in the generated layout inventory. Repeated rows share one style owner and are sampled; four REPL name kinds are checked individually. Selected binding rows may retain their selected background on hover, while readability and geometry remain required; an unselected row independently exercises hover feedback. Padding removal, primary-fill removal, same foreground/background, zero opacity, removed hover/focus cues and removed disabled feedback are injected into the real fallback action DOM without replacing its classes or handlers. Each fault must fail its corresponding assertion and is removed afterwards. Additional real-control probes reject white-on-white input values, unreadable selected-row hover and transparent focus outlines and transparent, inset or negative-spread shadows; a contrasted shadow remains a legal focus cue. Error and stopped tool summaries use the public state-error-primary and state-warn-primary tokens; the shared warning foreground mixes the latter with label-primary for light/dark readability, and attention badges use the theme background as foreground; reference palettes do not supply the unsupported danger/warning aliases.
|
|
35
|
+
|
|
36
|
+
The draft oracle measures the CSS-owned preview budget and compact header controls separately from expanded content. Compact body/actions remain measurable for stable classification but are hidden and inert. When the full header cannot fit above the owned anchor, the preview is hidden and inert; manual review always opens the enlarged surface independently of hidden-period geometry, closing returns to the owned entry, and a neighboring native dock action must retain its actual center hit. Expanded previews retain at least 40 px of source space; enlarged reviews retain at least 24 px even in the narrow/short cases, with larger reading areas at normal viewport sizes. Source scrolling must leave footer actions fixed, and all visible header/footer controls must pass actual hit testing. Resize and close remain separate header controls with at least 12 px between their hit targets; shrink returns to preview while close hides the panel. Return-focus tests interleave exact cloned candidate refresh with modal closure and retain stale, hidden, completed, unreachable and disposed counterexamples.
|
|
37
|
+
|
|
38
|
+
The sparkle-menu typography oracle requires a plugin-owned 13px/18px content base, 13px disclosure captions and binding names, 12px purposes and 11px states, all with 18px line-height and the inherited font family. It measures text ranges within their row for vertical clipping and checks the caret center against the caption line center, rather than its potentially stretched flex box; injected caption stretching must fail. Horizontal name/purpose ellipsis remains valid. Native/fallback fixtures reproduce a single disabled binding under larger carrier typography, preserve the full purpose title, reject injected inherited font-size and line-height, and accept a smaller carrier. The mixed-catalog root and revision paths and packed official-Host acceptance share the same oracle.
|
|
39
|
+
|
|
40
|
+
The sparkle-menu oracle requires at least 24 px of catalog reading space, viewport containment, nonoverlapping catalog and footer, no outer scrolling, and fully reachable footer actions of at least 24 px height. Scrolling the expanded mixed catalog and the revision list in both directions must leave footer geometry unchanged. Injecting a shared outer scroll container must fail the oracle; restoring the layout must pass. Actual catalog writes must retain a focused control whose center is inside the catalog clip and passes hit testing: collapsed disable, expanded enable, revision Back, and pending close/reopen are covered. Removing the reveal by resetting only the catalog scrollTop must fail this focus oracle; restoring it must pass. Page scroll and footer geometry remain unchanged. Packed official-Host acceptance repeats the mixed-catalog checks through the isolated profile and exercises actual management and settings actions.
|
|
41
|
+
|
|
42
|
+
## Limits
|
|
43
|
+
|
|
44
|
+
Static DOM exports establish presentation, not live RPC, editor, switch or permission behavior; Client interaction tests and packed acceptance own those facts. Disabled presentation is sampled on supported HTML form controls; tabs, disclosures and read-only observations have no disabled/busy product state. Native tool hover remains the official DisclosureRow's responsibility and is not required to paint the plugin fallback title. Static settings/workbench fixtures use public native primitives; the shared ActionButton fallback is tested dynamically in the dock, while fallback menu/modal keyboard, portal, mask, composition and focus-return behavior remain in the same browser runner. Dynamic busy checks cover draft actions and a pending workbench catalog reload. Workbench buttons may retain full opacity when a readable status and wait cursor identify the pending request; they must still reject focus. Request sequencing remains covered by Client interaction tests.
|
|
45
|
+
|
|
46
|
+
The 3:1 floor detects loss of readability and does not claim full WCAG conformance. Empty input placeholder paint and native select popups are outside this bounded text oracle. Shadow evidence is limited to contrasted solid outer rings; arbitrary blur, offset and inset effects are not accepted as proof of visible focus. No pixel baseline freezes typography, animation, every CodeMirror token, offscreen content, antialiasing, arbitrary third-party themes or future CSS properties. New controls or new state owners require updating the responsibility inventory and executable evidence. Backend coverage cannot substitute for this browser contract, and fixture success cannot substitute for official-Host delivery evidence.
|
|
47
|
+
|
|
48
|
+
Draft review checks measure viewport bounds, header/body/action separation, actual control hit targets, independently scrolling source, and the enlarged reading height. Packed Host acceptance compares composer geometry and transcript extent across disclosure and enlargement; native/fallback fixtures exercise the same layout oracle.
|
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
本文拥有 `dsh-ptc-plus` 的 journal、两阶段确认和冷恢复契约;`internal/session-journal-schema.js` 拥有封闭字段集合与版本常量,`internal/session-journal.js` 拥有校验、迁移与创建,`internal/session-journal-recovery.js` 拥有事件关联与分支折叠,`internal/session-runtime.js` 拥有 live kernel;它们提供实现证据。
|
|
6
6
|
|
|
7
|
+
## 日志读取与派生事实
|
|
8
|
+
|
|
9
|
+
当前 Host 的历史读取由 `sessionQuery.observeSession` 提供。runtime bridge 为一次顶层调用取得一个不可变 event/cursor/header 切点,释放 observation lease 后仍消费其不可变 events;派生 edit 把该切点传给内层执行,恢复、call identity、provenance 和 no-op 确认不在运行中重读变化的 live log。观察切点与当前 surface 不同时,按该切点的公开 surface operations 重建顺序,而不是用较新的 replacement 撤销较早观察的证据。生产路径不调用 `snapshotEvents`、`eventAt` 或 `ownEvents`。
|
|
10
|
+
|
|
11
|
+
同步 presentation 从 host-only `ptcPlusSessionLog` 单元读取。该单元与批量 journal fold 共用单事件 timeline 转移;checkpoint 仅保存关联所需的最小 call、规范 journal、身份及当前/历史 runtime records,不复制原始事件日志。pruned result 的非 content 身份保存为确定性 SHA-256 摘要。提示的已见身份、最高 ordinal、cooldown 和成功后的未解决计数在事件进入时更新;装配不扫描历史提示。checkpoint 是可丢弃的派生缓存,不证明 model knowledge、成功 initialization 或 cold replay。状态版本、schema 和 Host 的 watermark/restore 规则共同限定缓存使用,损坏或过时缓存必须重新折叠原日志。
|
|
12
|
+
|
|
13
|
+
旧 array-backed session 使用同一转移的批量读取回退。缺少当前公开 reader/投影或历史 events 不是数组时明确诊断,不静默宣称空历史;不存在 session 的非会话调用仍委托其原 owner。投影注册随插件/controller 生命周期释放,运行时关闭后只保留日志事实以撤回旧 PTC 消息,不保留 worker、工具或默认模型状态投影。具体决策见 [ADR 0032](adr/0032-own-session-log-facts-in-a-host-only-projection.md)。
|
|
14
|
+
|
|
15
|
+
结果的 content-only 重发布保留原 settlement 的位置与规范证据,不重新结算 edit claim,也不生成新的成功或编辑目标。原结果缺失时,已有 call 位置限制重建事实的 chronology,不能越过较新的执行。提示身份保留原投递位置,因此后获知的较早成功不能清空其后的未解决提示。
|
|
16
|
+
|
|
17
|
+
checkpoint 准入由 timeline 表示 owner 校验 typed payload、call/entry 对应、edit claim、规范 journal、派生 run 与 transcript 计数,再由投影复用。损坏嵌套状态在 suffix apply 前拒绝;Host 的水位不能替插件证明这些内容。
|
|
18
|
+
|
|
7
19
|
## 恢复承诺
|
|
8
20
|
|
|
9
21
|
PTC Plus 的正确承诺是:
|
package/docs/installation.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
-
PTC Plus requires Node.js `^22.19.0 || >=24.0.0` and targets the latest available DSH release with TypeScript PTC mode.
|
|
3
|
+
PTC Plus requires Node.js `^22.19.0 || >=24.0.0` and targets the latest available DSH release with TypeScript PTC mode. Historical interface branches are retained through capability detection, without promising a fully verified earlier Host installation; when both generations expose competing presentation evidence, the current DSH contract wins. Compatibility follows those live extension surfaces rather than a version allowlist.
|
|
4
4
|
|
|
5
5
|
The worker uses the Host's Node executable. Startup verifies native REPL framing, imports, syntax failures, synchronous throws, awaited rejections, and original return values. The adapter combines public eval callbacks with domain error events before REPL formatting; a source-end witness distinguishes empty completion from falsy rejection. A failed or timed-out probe reports a runtime prerequisite failure before user code executes. The engine range follows DSH; CI exercises Node 22.19, 24, and 26, without claiming that untested future releases have already passed.
|
|
6
6
|
|
|
@@ -18,20 +18,41 @@ Install the plugin into the profile that actually runs the target DSH surface. D
|
|
|
18
18
|
|
|
19
19
|
`danger-full-access` is the primary supported experience. The worker isolates the REPL lifecycle; it is not a malicious-code sandbox. DSH continues to own native-tool scope, policy, approval, cancellation, sandboxing, and scheduling. Narrower profiles expose only their available capabilities; PTC Plus does not simulate missing authority or add another permission system.
|
|
20
20
|
|
|
21
|
-
The optional `cordisToolsEnabled` integration requires the current DSH installation to provide its shipped `cordis` preset plus the public preset, Skill, Cordis, settings, and tool-runtime
|
|
21
|
+
The optional `cordisToolsEnabled` integration requires the current DSH installation to provide its shipped `cordis` preset plus the public preset, Skill, Cordis, settings, and tool-runtime services. PTC Plus declares the shared service packages as unrestricted required peers instead of installing private runtime copies. For a pathless preset it asks the Host's `pluginPackages.packageOf` service for the active generation's official preset package and requires the exact `cordis-plugin-development/SKILL.md` before mounting it; an older generation with no package service may resolve only its historical plural preset package relative to the Host's `ctx.baseUrl`. This compatibility path is disabled whenever `pluginPackages` exists, so packages merely reachable from the plugin profile cannot override an active Host result. Runtime capability validation owns compatibility, and CI loads the packed plugin against frozen official `latest` and `next` DSH graphs. That load step mounts the pathless Cordis companion from a separated active-host resource while a resolvable stale package is present beside the packed plugin, runs `scripts/dsh-execution-seam-smoke.mjs` to exercise public provider composition around the execution service the installed tool runtime uses, and runs `scripts/dsh-rpc-contract-smoke.mjs` to register the packed Remote descriptors with the installed TYPERT registry and evaluate the decoder that generation reads ([ADR 0030](adr/0030-serve-both-typert-codec-generations-from-one-codec.md)); an import alone cannot distinguish a loaded plugin from one whose injection is unsatisfied, because Cordis leaves the latter pending without an error, and it cannot show that the Host accepts a wire contract it validates only at registration. The same suite round-trips argument diagnostics through the selected Host's compressed JSONL Session persistence. Service packages retain the dependency graph selected by their Host distribution rather than independently selecting each service's release tag. DSH's profile module fallback must resolve the peers, while `pluginPackages` identifies the official preset resource from an active installation that publishes the service. Do not copy `SKILL.md` or add the Cordis preset's Skill directory to global roots. If the host surface is incomplete, plugin activation or enabling the setting fails instead of loading a second DSH core.
|
|
22
22
|
|
|
23
23
|
The plugin attaches to whichever program-execution service the installed DSH registers, and it presents the capabilities of the execution it performs ([ADR 0028](adr/0028-attach-to-the-host-ptc-execution-seam.md)). Cells run in the session kernel under the session's configured budgets, so `run_code` advertises neither a per-call deadline nor a file sandbox, and DSH rejects `timeoutMs` and `sandbox_permissions` with its own message instead of the plugin accepting an input it would then ignore.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Install the complete `cordis.patch.yml` bundle, not only its main plugin row. The bundle preserves the original `ptc-runtime` module and configuration, isolates its `ptcRuntime` service as `ptc-plus-original`, and adds the independent `dsh-ptc-plus/execution-provider` row before the main row. A custom composition must set that provider row's `originalEntryId` to its actual source row ID relative to the provider row's Loader tree (the profile Include subtree in standard installations) and its `isolation` to the same value as the source row's `isolate.ptcRuntime`; keep PTC Plus runtime settings on the main row. The adapter registers its own public provider and never writes to the original instance. Disabling the main row restores native delegation through the adapter; removing the complete bundle also restores the original global service. An uncomposed original produces an explicit composition diagnostic rather than a mutation fallback.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Supported installations use an unmodified official DSH release. Local plugin development packages this checkout. The release development launcher uses the published Host; the opt-in [upstream source launcher](#upstream-source-development-launcher-windows) builds the unmodified official repository for testing unreleased changes. Neither path patches the Host. Missing public layout interfaces remain a feature limitation, not an instruction to customize DSH. See [ADR 0017](adr/0017-track-the-latest-dsh-public-surface.md) for distribution and acceptance requirements.
|
|
28
|
+
|
|
29
|
+
The Client root requires `slots`, `locale`, `connection`, and `remote`; it adopts whichever public settings transport the installed Host exposes (`configForms` or `settingsScope`) through an optional injection and keeps its shipped `CONFIG_FIELDS` defaults while neither is available, so a renamed or withdrawn transport degrades the settings surface instead of suspending activation. Feature eligibility follows those defaults: only an explicit `enabled: false` withdraws a contribution. Contributions wait for their public slots and consume the supplied session hooks; the composer action additionally requires `remote.commands`. Neither an unused `ui-session` module nor a renamed conversation registry gates activation. Preset selection prefers `agentPreset` projection evidence, falling back only to a historical public session summary field when that projection is absent. Binding values and draft capabilities always require their own projections. No private store or raw-log fallback is used. Slot and provider disposal withdraw the contributions they own.
|
|
30
|
+
|
|
31
|
+
### Compatibility Evidence
|
|
32
|
+
|
|
33
|
+
The two frozen dependency graphs are installation cohorts, not proof of two distinct capability generations. `compat/latest/package-lock.json` and the root `package-lock.json` record the releases each smoke actually installs; their channel names do not prove the live npm dist-tags or compatibility with an adjacent earlier release. Both recorded cohorts exercise `ptcRuntime`, `configForms`, `plugins.row.config`, volatile configuration and `codec.create()`. `npm run host:baseline:verify` checks frozen graph consistency, not every historical fallback or current registry availability.
|
|
34
|
+
|
|
35
|
+
| Retained interface | Evidence and consequence of removal |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `retainedBy.mainView`, `plugins.row.config`, volatile updates, `codec.create()`, composer props carrying their own `sessionId` | Required by the frozen graphs; these are current paths, not optional historical fallbacks. |
|
|
38
|
+
| `settingsScope`, `settings.plugin.item`, section-installer variants | Historical, unfrozen Host shapes, covered with fixtures. Removal loses their live settings, card seat or reconfiguration path. |
|
|
39
|
+
| `snapshot.current`, bare summary `agentPreset` | Historical, unfrozen selection and preset shapes. Removal can strand their session-specific views or PTC eligibility. Binding and draft evidence never use the preset fallback. |
|
|
40
|
+
| Historical icon names and missing primitives | Fixtures establish component fallback, not a complete earlier Client. Removal of icon candidates loses native glyphs; usable text/component fallbacks must remain. |
|
|
41
|
+
| Menu without a `children` region | Rendering probe plus a plugin-owned fallback. Removal makes binding actions unreachable on that historical primitive; JSX is not passed through the Host's string-only label field. |
|
|
42
|
+
| `codec.schema` | Historical, unfrozen registry shape. Removal rejects Remote registration on schema-only Hosts. The factory and schema share one decoder. |
|
|
43
|
+
| `codeRuntime.run(request)` | Historical, unfrozen execution shape. Removal leaves that Host without a session REPL attachment. Fixture tests preserve it; both frozen graphs exercise resolve/run instead. |
|
|
44
|
+
| Plural preset-package layout and Host-anchored resolution | Historical Hosts without `pluginPackages` need this companion-resource path. Removal breaks their Cordis companion; it must never override an available active-Host package service. |
|
|
45
|
+
| `sessionQuery.observeSession` and host-only `sessionProjections` | Current history and presentation owners; missing services are diagnosed, not treated as empty recovery evidence. The projection publishes no Client wire view. |
|
|
46
|
+
| Legacy session event arrays and V0 boundary migration | Read-only fixtures preserve historical ancestry and file conversion through the shared event transition. Removal can discard reconstructable older sessions; malformed arrays are diagnosed, and format conversion does not prove a complete older Host's live behavior. |
|
|
47
|
+
|
|
48
|
+
Capabilities select behavior, never a release number. Historical fixture success is not packed-Host evidence. Full Host smoke is bounded to its selected graph, and a clean build is not live browser activation. Public provider composition supports frozen original execution instances without changing their descriptors. Two integration boundaries are accepted: the result bridge requires mutable registered tool definitions ([ADR 0028](adr/0028-attach-to-the-host-ptc-execution-seam.md)), and the two-tool model projection retains a complete native registry and SDK through scoped `both` presentation plus assembly projection ([ADR 0005](adr/0005-temporary-rejected-cell-edit-transport.md)). Proven native miscalls are normalized before Host dispatch; an unnormalized root call can reach approval before the plugin rejects it. Frozen tool definitions remain unsupported. Acceptance preserves current behavior and DSH governance; it does not claim that the missing public metadata or independent direct-admission contracts have been implemented.
|
|
28
49
|
|
|
29
50
|
## npm Release
|
|
30
51
|
|
|
31
52
|
Use this form after the selected version is available from the npm registry:
|
|
32
53
|
|
|
33
54
|
```sh
|
|
34
|
-
dsh plugin --profile <profile> add dsh-ptc-plus@0.4.
|
|
55
|
+
dsh plugin --profile <profile> add dsh-ptc-plus@0.4.10
|
|
35
56
|
dsh --profile <profile> --dump-config
|
|
36
57
|
```
|
|
37
58
|
|
|
@@ -68,7 +89,7 @@ pnpm dsh --profile <profile> --dump-config
|
|
|
68
89
|
|
|
69
90
|
```sh
|
|
70
91
|
npm pack
|
|
71
|
-
dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.4.
|
|
92
|
+
dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.4.10.tgz
|
|
72
93
|
dsh --profile <profile> --dump-config
|
|
73
94
|
```
|
|
74
95
|
|
|
@@ -89,14 +110,32 @@ On Windows, `--browser-channel msedge` can use the existing Edge installation. T
|
|
|
89
110
|
|
|
90
111
|
## Isolated latest-DSH development launcher
|
|
91
112
|
|
|
92
|
-
To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It
|
|
113
|
+
To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It orders all published DSH releases by semantic version, prereleases included, and selects the newest release whose complete dependency cohort npm can install, rather than following a dist-tag that a release can leave behind. If a newly published root package still has missing exact-version dependencies, the launcher warns and tries the preceding release; an explicit `DSH_DEV_VERSION` remains exact and fails instead of falling back. It installs only when the selected cached version changes, creates the shipped `web` profile inside an isolated `DSH_HOME`, installs this checkout, and starts DSH. When no port is supplied, the default Web profile reuses its cached loopback port while that port is available; an invalid cache entry or occupied port is replaced with a free port. This keeps browser authentication stable across ordinary restarts without blocking another DSH on port 3080. The launched Host receives a 64 KiB HTTP request-header limit while retaining existing Node options to accommodate development authentication cookies and the combined Client plugin request during Web boot. The launcher does not modify the repository or your normal DSH home.
|
|
93
114
|
|
|
94
115
|
The launcher defaults to `https://registry.npmjs.org/` for version queries, npm installs and DSH's pnpm subprocesses, including the `@deepseek-ai` scope. This avoids mirror synchronization gaps where a new DSH package is available before its dependencies. It prints the selected registry and refreshes version metadata online; an unavailable version query can still reuse the previously cached version. Set `DSH_DEV_REGISTRY` to an absolute HTTP(S) registry URL to select another source explicitly. The choice applies only to the launcher process and its children; npm configuration files and persistent environment settings are unchanged. Other explicitly configured package scopes retain their own registries.
|
|
95
116
|
|
|
96
|
-
The default cache is `%LOCALAPPDATA%\dsh-ptc-plus-dev`. It contains the isolated `DSH_HOME`, DSH installations, immutable plugin snapshots, and a pnpm store. Cleanup aims to retain three DSH versions and plugin snapshots, always including the selected installation and snapshot even when another directory has a newer timestamp. Locked directories warn and remain for a later cleanup attempt; their installation marker is removed before deletion so partially deleted installations cannot be reused. Failed pnpm store pruning also warns and continues startup.
|
|
117
|
+
The default cache is `%LOCALAPPDATA%\dsh-ptc-plus-dev`. It contains the isolated `DSH_HOME`, DSH installations, immutable plugin snapshots, and a pnpm store. Cleanup aims to retain three DSH versions and plugin snapshots, always including the selected installation and snapshot even when another directory has a newer timestamp. Locked directories warn and remain for a later cleanup attempt; their installation marker is removed before deletion so partially deleted or failed installations cannot be reused. Failed pnpm store pruning also warns and continues startup. Failure of every published candidate, or of an explicitly selected version, stops the launcher. Set `DSH_DEV_CACHE` to move the cache, `DSH_DEV_PROFILE` to change the profile name, `DSH_DEV_VERSION` to pin an npm dist-tag or version instead of the newest installable published release, `DSH_DEV_PORT` to choose a fixed Web port, or `DSH_DEV_MAX_VERSIONS` to change the retention count (1-10).
|
|
97
118
|
|
|
98
119
|
The Windows launchers normalize the process, machine, and user `PATH` values in memory, remove duplicate entries, and add the Node/cache directories they need. They do not create drive mappings, junction trees, or persistent environment changes. If a genuinely unique PATH is still too long for `cmd.exe`, the launcher stops before npm or DSH runs and asks you to shorten the relevant PATH value.
|
|
99
120
|
|
|
121
|
+
### Upstream source development launcher (Windows)
|
|
122
|
+
|
|
123
|
+
Double-click `scripts\run-upstream-dsh.cmd` to test unreleased official DSH code with this plugin checkout. Git, Node.js and npm must be on the Windows PATH. The launcher fetches the official repository's default-branch HEAD, prints its full commit, installs the exact pnpm declared by that commit, and follows the official `pnpm install --frozen-lockfile`, `pnpm run build`, and `pnpm run dsh` source workflow. It does not patch upstream source. First startup can take several minutes and substantial disk space; upstream build prerequisites and failures remain visible.
|
|
124
|
+
|
|
125
|
+
The source launcher shares plugin packaging, profile selection and port handling with `run-dev-dsh.cmd`, but uses an `upstream` subdirectory of the development cache. Its DSH home, profiles, authentication, pnpm store and build snapshots are separate from the release launcher and your normal DSH installation. `DSH_DEV_CACHE`, `DSH_DEV_REGISTRY`, `DSH_DEV_PROFILE`, `DSH_DEV_PORT`, and `DSH_DEV_MAX_VERSIONS` apply; `DSH_DEV_VERSION` does not select source commits. For example:
|
|
126
|
+
|
|
127
|
+
```bat
|
|
128
|
+
scripts\run-upstream-dsh.cmd web --no-open
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Each build cache key includes the full commit, Node version/platform/architecture/ABI, upstream pnpm declaration, registry and inherited `DSH_CLIENT_*` / `DSH_BUILD_*` environment. A successful build is marked only after its CLI version check succeeds. Unchanged inputs reuse that build; failed builds have no completion marker and are retried. Tracked changes or a different HEAD in a completed checkout stop startup instead of overwriting edits. An interrupted initial checkout can be recreated on the next run.
|
|
132
|
+
|
|
133
|
+
A failed fetch warns and uses the last fetched commit if available; it never labels that fallback as current upstream HEAD. A failed install or build stops startup instead of silently launching an older successful revision. The launcher holds an exclusive OS file lock through Host shutdown, so another launch using the same cache fails clearly. The lock releases when the process exits; the remaining `source.lock` file is harmless and should not be removed to bypass a running process.
|
|
134
|
+
|
|
135
|
+
Cleanup retains the configured number of build snapshots and plugin tarballs (three by default), including the selected ones. Locked cleanup targets warn and are retried later. Git objects, exact pnpm runtimes and the shared pnpm store are retained to speed later revisions; their size is not bounded by the snapshot count. With this source launcher stopped, delete `upstream\builds` to force fresh builds while retaining downloads; remove `upstream\pnpm-store` as well to reclaim the shared download cache. The generated CMD shims use launcher-process environment variables to preserve Unicode paths and are not standalone entry points. Do not delete `upstream\dsh-home` unless you intend to remove this test environment's settings and sessions.
|
|
136
|
+
|
|
137
|
+
This is an opt-in upstream test environment. Published-release compatibility remains the plugin's supported delivery target.
|
|
138
|
+
|
|
100
139
|
## DSH Desktop
|
|
101
140
|
|
|
102
141
|
On Windows or macOS, choose **Open DSH Terminal** from the Desktop tray. Bare commands in that terminal target the active profile:
|
|
@@ -106,7 +145,7 @@ dsh plugin add github:muyuanjin/dsh-ptc-plus#main
|
|
|
106
145
|
dsh --dump-config
|
|
107
146
|
```
|
|
108
147
|
|
|
109
|
-
After an npm release, the package spec may instead be `dsh-ptc-plus@0.4.
|
|
148
|
+
After an npm release, the package spec may instead be `dsh-ptc-plus@0.4.10`. For a local package, use its absolute tarball path. Restart DSH Desktop after installation. Linux Desktop is not a current DSH Desktop release target; use DSH CLI/Web on Linux.
|
|
110
149
|
|
|
111
150
|
## Upgrades
|
|
112
151
|
|
package/docs/publishing.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
npm 发布遵循 [ADR 0022](adr/0022-stage-npm-releases-with-oidc.md),使用 `.github/workflows/release.yml` 声明的 Trusted Publisher,不向 GitHub 保存 npm write token。npm package settings 必须把 publisher 精确绑定到 `muyuanjin/dsh-ptc-plus`、workflow filename `release.yml` 和 environment `npm-release`,且只允许 `npm stage publish`。Publishing access 选择页面中最严格且标记为 recommended 的 2FA 选项;npm 文档称其为 `Require two-factor authentication and disallow tokens`,当前 npm 页面也可能显示 `Require two-factor authentication and disallow bypass 2fa tokens (recommended)`。不要从滚动变化的标签推断账户中已不存在传统 token。OIDC 只把经过验证的 tarball 放入 npm staging,维护者仍须在 npm CLI 或 npmjs.com 检查 staged package 并以 2FA approve,包才会进入公开 registry。
|
|
22
22
|
|
|
23
|
-
普通 `CI`
|
|
23
|
+
普通 `CI` 只在 `main` push 或 pull request 包含非纯文档变更时运行:只改动 `**.md`、`assets/**` 或 `LICENSE` 的提交不触发矩阵。发布 commit 因包含 `package.json` 与 `package-lock.json` 变更必然产生一次 `main` push run,Release workflow 仍要求该 commit 有成功的 run 才继续。发布前创建 annotated `v<package.version>` tag,原子推送 release commit 与 tag,等待该 commit 的 `CI` 成功,然后以该 tag 作为 ref 显式运行 `Release` workflow。workflow 不接受另一个 tag input,并会重新证明 dispatch 的 `GITHUB_REF`、`GITHUB_SHA`、annotated tag target、checkout HEAD、manifest 版本和成功 CI 的 SHA 完全一致;release job 使用 GitHub-hosted Node `24.15.0`、npm `12.0.2`、无 package-manager cache 和最小 `id-token: write` 权限,构建一个 tarball、执行 clean-consumer smoke,再对同一文件执行 `npm stage publish`。`package.json#allowScripts` 显式拒绝当前不需要的 `esbuild` install script;`replace-registry-host=always` 让 release install 将 lockfile 中的 registry tarball 路由到显式 npm 官方 registry,而不放宽 npm 12 的 Git/remote dependency 默认拒绝。
|
|
24
24
|
|
|
25
25
|
```powershell
|
|
26
26
|
git tag -a "v$((Get-Content package.json | ConvertFrom-Json).version)" -m "v$((Get-Content package.json | ConvertFrom-Json).version)"
|
|
@@ -42,13 +42,13 @@ npm.cmd stage approve '<stage-id>' --registry=https://registry.npmjs.org/
|
|
|
42
42
|
|
|
43
43
|
## Release checklist
|
|
44
44
|
|
|
45
|
-
1. 在 Linux Node `22.19.0`、24.x
|
|
46
|
-
2. 运行 `npm audit`、`npx publint`、`git diff --check`、Markdown local-link check 和 `npm pack --silent --dry-run --json
|
|
45
|
+
1. 提交前在稳定工作树上运行完整 `npm run check`,生成 coverage 与 review proof。仓库 CI 在 Linux Node `22.19.0`、24.x、26.x,以及 Windows 与 macOS Node 24.x 的干净安装上运行 `npm run verify:ci`,检查构建、Client 与跨平台关键运行契约;Ubuntu Node 24.x 另运行打包后的 `latest` / `next` Host contracts。CI 不重复收集 coverage 或执行穷尽式后端套件。
|
|
46
|
+
2. 运行 `npm audit --omit=dev`、`npx publint`、`git diff --check`、Markdown local-link check 和 `npm pack --silent --dry-run --json`。audit 检查随包安装的 production 依赖图;宿主 DSH 及其开发依赖不进入插件 tarball,由冻结宿主契约和 CI 单独验证。确认 tarball 只包含发布白名单内的运行时代码、文档和展示资产,不含凭据、本地路径、开发脚本或测试夹具,并从 tarball 安装到空目录执行 ESM import smoke。机器读取 `npm pack --json` 时保持 `--silent`,避免 lifecycle 输出混入 JSON stream。
|
|
47
47
|
3. 更新到最新可用 DSH release 并记录 `dsh --version`。分别从 npm 包、固定 Git commit、源码 checkout 和 tarball 安装到临时 profile,再执行 `dsh --profile <profile> --dump-config`,确认只新增 `ptc-plus` row。每个上游 release 都重新验证公共扩展面、CLI/Web 集成和 profile 装配,不设置版本白名单。
|
|
48
48
|
4. 在 Windows 与 Linux 运行无模型调用的 `npm run test:client:web -- --dsh-entry <latest-installed-dsh/lib/bin.js>`,验证 tarball 安装后的真实 Web Client、设置与对话 surface;浏览器前置条件见 [安装指南](installation.md)。`build:check`、Host ESM import 和 factory smoke 均不能替代浏览器激活验收。macOS 由原生 runner 验证 CLI/Web;Windows 与 macOS Desktop 从托盘打开当前 profile 的 DSH Terminal 安装,重启 Desktop 后做一次 PTC 模式 smoke。Desktop 当前发布平台不包括 Linux。
|
|
49
49
|
5. 只有在明确授权模型消耗后才运行 `npm run test:expensive` 与 `npm run test:ab`。发布结论以结构化测试结果为准,不把一次模型样本推广为普遍保证。
|
|
50
50
|
6. 确认 npm 包名可用、待发布版本高于 registry 版本、README 截图来自真实 DSH 会话,并核对 repository、homepage、bugs、license 与 `dsh-plugin` topic。
|
|
51
|
-
7. 最后检查 `npm pack --silent --json` 的名称、版本、大小与文件列表,创建 annotated release tag,并确认 tag commit 已通过 `CI`。运行 `Release` workflow 将同一源码产生的 tarball送入 npm staging;人工检查并以 2FA approve 后,等待 registry 扫描完成,再创建 GitHub Release。
|
|
51
|
+
7. 最后检查 `npm pack --silent --json` 的名称、版本、大小与文件列表,创建 annotated release tag,并确认 tag commit 已通过 `CI`。运行 `Release` workflow 将同一源码产生的 tarball送入 npm staging;人工检查并以 2FA approve 后,等待 registry 扫描完成,再创建 GitHub Release。Release notes 的内容取舍与风格由 [release-notes.md](release-notes.md) 拥有。
|
|
52
52
|
|
|
53
53
|
远程仓库、registry、签名凭据、目标平台运行状态和模型额度都属于发布时事实,不能由本地 manifest 推断。
|
|
54
54
|
|