dsh-ptc-plus 0.4.1 → 0.4.3

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.
Files changed (103) hide show
  1. package/README.en.md +164 -78
  2. package/README.md +165 -79
  3. package/assets/dsh-ptc-plus-banner-en.webp +0 -0
  4. package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
  5. package/assets/ptc-plus-icon.svg +5 -0
  6. package/client.js +854 -336
  7. package/compiler-core.cjs +161 -157
  8. package/compiler-core.cjs.map +3 -3
  9. package/docs/README.md +4 -1
  10. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +8 -7
  11. package/docs/adr/0008-define-agent-operating-contract.md +2 -2
  12. package/docs/adr/0010-session-log-derived-recovery-tips.md +7 -0
  13. package/docs/adr/0016-archive-resolved-review-findings.md +3 -3
  14. package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
  15. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -0
  16. package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +14 -3
  17. package/docs/adr/0023-global-user-bindings.md +7 -7
  18. package/docs/adr/0025-use-versioned-logical-binding-identities.md +3 -3
  19. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +23 -7
  20. package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +9 -5
  21. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +26 -6
  22. package/docs/adr/0031-close-semantic-obligations-by-owner.md +29 -0
  23. package/docs/adr/README.md +4 -4
  24. package/docs/architecture.md +15 -10
  25. package/docs/binding-review-placement-design.md +1 -1
  26. package/docs/client-ui.md +9 -5
  27. package/docs/durability-design.md +12 -9
  28. package/docs/installation.md +27 -9
  29. package/docs/runtime-reference.md +23 -12
  30. package/docs/semantic-validation.md +7 -3
  31. package/docs/stateful-binding-updates-proposal.md +8 -4
  32. package/docs/user-bindings.en.md +10 -7
  33. package/docs/user-bindings.md +9 -6
  34. package/docs/value-wire.md +1 -1
  35. package/docs/verification-optimization-work.md +41 -0
  36. package/docs/verification.md +53 -2
  37. package/index.js +39 -34
  38. package/internal/async-local-storage-intrinsics.js +43 -0
  39. package/internal/binding-declaration-contract.js +8 -0
  40. package/internal/binding-source-analysis.js +381 -64
  41. package/internal/binding-update-policy.js +7 -1
  42. package/internal/callable-source-facts.js +37 -1
  43. package/internal/cell-analysis.js +85 -17
  44. package/internal/compiler-intrinsics.js +9 -43
  45. package/internal/compiler-module-links.js +7 -4
  46. package/internal/config-spec.js +1 -1
  47. package/internal/cordis-tools-owner.js +20 -10
  48. package/internal/dynamic-environment-integration.js +8 -4
  49. package/internal/dynamic-environment-runtime.js +24 -3
  50. package/internal/dynamic-native-calls.js +4 -1
  51. package/internal/dynamic-native-runtime.js +15 -1
  52. package/internal/edit-transport-owner.js +80 -20
  53. package/internal/execution-seam-compat.js +192 -30
  54. package/internal/failure-reporting.js +38 -30
  55. package/internal/isolated-worker.js +17 -10
  56. package/internal/kernel-worker.js +645 -393
  57. package/internal/message-sources.js +14 -0
  58. package/internal/module-compilation.js +7 -5
  59. package/internal/module-transform-contract.js +32 -2
  60. package/internal/record-utils.js +24 -15
  61. package/internal/repl-memory-projection.js +10 -0
  62. package/internal/repl-scope-normalizer.js +72 -35
  63. package/internal/repl-value-observer.js +145 -46
  64. package/internal/runtime-config.js +62 -2
  65. package/internal/runtime-intrinsics.js +104 -0
  66. package/internal/runtime-messages.js +6 -4
  67. package/internal/session-cell-executor.js +26 -2
  68. package/internal/session-journal-recovery.js +267 -67
  69. package/internal/session-journal-schema.js +30 -13
  70. package/internal/session-journal.js +485 -44
  71. package/internal/session-log-view.js +5 -4
  72. package/internal/session-runtime.js +46 -21
  73. package/internal/session-state.js +7 -29
  74. package/internal/settings-compat.js +66 -1
  75. package/internal/source-position-map.js +38 -0
  76. package/internal/stateful-root-compiler.js +3 -1
  77. package/internal/typescript-transform.js +4 -2
  78. package/internal/user-binding-console-worker.js +115 -41
  79. package/internal/user-binding-draft-projection.js +3 -2
  80. package/internal/user-bindings-owner.js +2 -1
  81. package/internal/user-bindings.js +16 -3
  82. package/internal/validated-parse-repair.js +6 -2
  83. package/internal/value-wire.js +189 -94
  84. package/internal/worker-client.js +99 -8
  85. package/internal/worker-cwd-virtualization.js +82 -54
  86. package/internal/worker-environment.js +20 -0
  87. package/internal/worker-output-capture.js +187 -0
  88. package/internal/worker-output-fence.js +26 -0
  89. package/internal/worker-realm-surfaces.js +197 -0
  90. package/internal/worker-repl-realm.js +140 -0
  91. package/package.json +37 -4
  92. package/src/client-activity.js +12 -2
  93. package/src/client-authoring-view.js +121 -62
  94. package/src/client-console.js +4 -2
  95. package/src/client-copy.js +4 -2
  96. package/src/client-feature-gates.js +7 -9
  97. package/src/client-host-compat.js +104 -27
  98. package/src/client-repl-view.js +3 -1
  99. package/src/client-styles.js +12 -1
  100. package/src/client-tool-view.js +3 -1
  101. package/src/client-transport.js +2 -2
  102. package/src/client-workbench.js +4 -3
  103. package/src/client.js +56 -17
@@ -13,7 +13,7 @@ PTC Plus 把 DSH PTC 模式的顶层 `run_code` 变成与 session 绑定的连
13
13
  | Journal / replay | PTC Plus + session log | 记录 call transcript、settlement、completion 和恢复边界 |
14
14
  | Presentation | DSH + PTC Plus | 保留 native guidance,并追加 REPL 指引与最小 explorer 声明 |
15
15
 
16
- 求值层由插件自有的 helper 进程承载:Host 只持有 `IsolatedWorker` transport,真实 `node:worker_threads` session worker 与其私有 `MessagePort` 都留在 helper 内,IPC 只传输 plain data。宿主回收卡住的计算时只强杀自己的 helper process,不再在 DSH 进程内执行已测得会落入 Node 24/26 cppgc teardown fault 的 worker 强杀;`IsolatedOwner` 只在该实例的 real exit、output close 和 cleanup 都完成后释放。kernel、console、candidate 三个入口各自拥有 owner。helper 的 `init` 携带 fork 前 snapshot 的投影环境,user Worker 及其子进程保持原 env 契约,不会继承 `NODE_V8_COVERAGE` 等宿主 instrumentation;inner Worker 的 compute budget 在每次请求提交时通过 helper 的 on-demand sample 取新鲜 `eventLoopUtilization` baseline,ready handshake 另有启动样本;采样失败按 worker-exit 有界失败且不派发 prepare/run。唯一例外由 [ADR 0024](adr/0024-repl-console-observation.md) 所有:同一 worker 已确认存在未完成的 observation 时,prepare 可先于预算启动,确认 observation 完成后才开始计时。
16
+ 求值层由插件自有的 helper 进程承载:Host 只持有 `IsolatedWorker` transport,真实 `node:worker_threads` session worker 与其私有 `MessagePort` 都留在 helper 内,IPC 只传输 plain data。宿主回收卡住的计算时只强杀自己的 helper process,DSH 进程内没有需要终止的 session worker,因此不会触达已测得会落入 Node 24/26 cppgc teardown fault 的 in-host worker 强杀路径;`IsolatedOwner` 只在该实例的 real exit、output close 和 cleanup 都完成后释放。kernel、console、candidate 三个入口各自拥有 owner。helper 的 `init` 携带 fork 前 snapshot 的投影环境,user Worker 及其子进程保持原 env 契约,不会继承 `NODE_V8_COVERAGE` 等宿主 instrumentation;Electron Host 只在 helper fork 环境覆盖 `ELECTRON_RUN_AS_NODE=1`,该启动变量不进入 user Worker。inner Worker 的 compute budget 在每次请求提交时通过 helper 的 on-demand sample 取新鲜 `eventLoopUtilization` baseline,ready handshake 另有启动样本;采样失败按 worker-exit 有界失败且不派发 prepare/run。唯一例外由 [ADR 0024](adr/0024-repl-console-observation.md) 所有:同一 worker 已确认存在未完成的 observation 时,prepare 可先于预算启动,确认 observation 完成后才开始计时。
17
17
 
18
18
  主入口接管模型直接发起的顶层 `run_code`,并通过 DSH tool registry 真实注册 `edit_run_code`。
19
19
  使用 code-only direct-tool projection 的 PTC request 始终按固定顺序暴露 `[run_code, edit_run_code]`;插件用 agent scope 的
@@ -42,7 +42,7 @@ DSH 为一个 agent composition 固定选择 `native`、`ptc` 或 `both`。首
42
42
  已执行或可能产生外部 effect 的目标,则必须依据操作 owner 的 retry/idempotence 契约和执行事实判断重跑。短 `run_code` 可以复用仍存活的 binding,但缩短源码不能证明幂等。能力和命令执行依赖当前 request
43
43
  与 execution world,模型必须先探查 live binding、实际 executable 和路径语义,不假设某个平台、shell 或 package runner。
44
44
 
45
- live `PTC-C001` 若精确落在源码 EOF,独立的 bounded analyzer 只把追加单个 `}`、`)`、`]` 的三个源码分别送入该 cell 提交时的同一 preparation context。仅当唯一候选通过、无 binding collision,现有 exact editor 能从不超过固定预算的唯一尾部物化同一源码,并且 runtime 已取得该 rejected `run_code` 的持久 call sequence 时,诊断才输出一行可直接调用的 `edit_run_code({ edits: [...], expected_target_call_seq })`。edit transport 把该 sequence 与其 call event 捕获的目标比较,目标已变化时不编辑也不派生执行。这项 validated repair 优先于长度阈值,但只证明语法/preflight 接受;插件不自动 dispatch,也不改写原始 `run_code`。非 EOF、多候选、多 token、超预算、缺少目标身份或后续 preparation 拒绝均使用 length-adaptive help。
45
+ live `PTC-C001` 若精确落在源码 EOF,独立的 bounded analyzer 只把追加由 `}`、`)`、`]` 组成、长度为一或二的 12 项候选源码分别送入该 cell 提交时的同一 preparation context。仅当唯一候选通过、无 binding collision,现有 exact editor 能从不超过固定预算的唯一尾部物化同一源码,并且 runtime 已取得该 rejected `run_code` 的持久 call sequence 时,诊断才输出一行可直接调用的 `edit_run_code({ edits: [...], expected_target_call_seq })`。edit transport 把该 sequence 与其 call event 捕获的目标比较,目标已变化时不编辑也不派生执行。这项 validated repair 优先于长度阈值,但只证明语法/preflight 接受;插件不自动 dispatch,也不改写原始 `run_code`。非 EOF、多候选、需要三个及以上闭合符、超预算、缺少目标身份或后续 preparation 拒绝均使用 length-adaptive help。
46
46
 
47
47
  稳定指引保留这些跨任务不变量和失败恢复的优先动作。长 cell 失败的短提示直接作为当前 `PTC-X001` 的结构化 `help` 输出;重复绑定失败和当前 execution world 中由诊断确认的 executable、shell 或 path 错误仍由当前 session log 派生为以 `tools:ptc-plus-tip/<trigger>/<ordinal>` 标识的独立 notice,词法失败指向可见源码与初始化,worker-owned capability 失败才指向能力探查,平台错误则提示重新确认环境。投影合并规范 PTC notice 与历史 DSH system-prompt snapshot sections,同一已投递 identity 跨两种来源只计一次,正文不参与身份判断。
48
48
  相同提示受 `tipCooldownMessages` 间隔约束,连续未解决时才升级为详细版本,成功 cell 会重置未解决计数;提示不会改变
@@ -52,11 +52,12 @@ system sections、tool schema 或 tool order,也不假设 Windows、WSL、POSI
52
52
 
53
53
  ## 设置与启用开关
54
54
 
55
- Host half 通过 DSH 公共 settings 服务注册 `ptc-plus` 命名空间,优先使用 provider-owned `installSection()`,并兼容根模块的 `installSettingsSection()`;两条路径共享同一 fallback、watch、rollback 与 disposal 语义。字段清单、默认值与校验来自 `internal/config-spec.js`。
56
- Client half 通过宿主当前代的设置座位呈现全部配置:旧代际是 `settings.plugin.item`(keyed,按 namespace),当前 DSH 是 Plugins 页面的 `plugins.row.config`(keyed,键 `<包名>#<行 id>`),两者由 `src/client-host-compat.js` 同一次发布、由声明槽位的一代渲染,页面按 `summary`/`page` 视图分别取一句描述与完整表单([ADR 0019](adr/0019-plugin-settings-and-kill-switch.md))。`enabled` 是 kill switch:关闭时保留 settings 注册、设置卡片与撤销旧 PTC 声明所需的被动 presentation cleanup;`enhancedToolView` 是默认开启的正文展示开关,关闭时只交还 DSH 原生 `run_code`/`edit_run_code` generic row,
55
+ Host half 通过 DSH 公共 settings 服务接入 `ptc-plus` 命名空间:提供 provider-owned `installSection()` 的代际直接注册,提供根模块 `installSettingsSection()` 的代际经兼容适配注册;两条路径共享同一 fallback、watch、rollback 与 disposal 语义。既不提供 section installer、又由宿主从插件导出的 `Config` 管理设置文档的代际(当前 alpha)被视为 host-owned surface:导出 schema 的全部字段带 volatile 标记,宿主据此提供表单并通过自身 config-editor 把 volatile-only 变更写入 retained handles;插件订阅宿主的 `loader/volatile-update` 事件,从同一 schema 重新解析 live 值并复用既有 reconcile、rollback 与 per-cell 配置代际语义。字段清单、默认值与校验来自 `internal/config-spec.js`。
56
+ Client half 在侧栏 **插件 → 已安装 → dsh-ptc-plus** 的插件行配置页呈现全部设置,通过 `plugins.row.config`(keyed,键 `<包名>#<行 id>`)注册;旧宿主的插件设置使用 `settings.plugin.item`(keyed,按 namespace)。`src/client-host-compat.js` 等待对应页面声明槽位,并按 `summary`/`page` 分别渲染一句描述与完整表单,不向通用设置注册。星光菜单在应用内弹窗复用完整表单与写入 owner;包元数据的 `icon` 指向随包发布的 SVG,由宿主显示在插件列表与详情页([ADR 0019](adr/0019-plugin-settings-and-kill-switch.md))。`enabled` 是 kill switch:关闭时保留 settings 注册、设置卡片与撤销旧 PTC 声明所需的被动 presentation cleanup;`enhancedToolView` 是默认开启的正文展示开关,关闭时只交还 DSH 原生 `run_code`/`edit_run_code` generic row,
57
57
  总开关关闭时不注册 runtime、执行 hook、tool surface 或 system prompt section,也不读取 binding 存储;`ptc` 与兼容 `code` preset 会话在头部单独显示 `PTC Plus` 指示器。设置卡片显示“已启用/已停用”,稳定指引不包含 UI 品牌名。
58
+ `Config` 的字段形态由 `internal/settings-compat.js` 按已安装代际的公共能力决定:仍提供 section installer 的代际保留普通描述字段,由自身文档路径提交校验后的具体默认值;只有自管设置文档的代际才加 volatile 标记,字段构建器不具备该能力的代际保持可加载。版本号不参与该判断。
58
59
  `autoDescribeRunCode` 默认开启且只控制请求绑定的本地执行策略。开启时,缺少外层 `run_code.description` 的调用使用派生参数通过本地 DSH 校验,备用摘要仅进入 presentation metadata;关闭时由 DSH 校验原始参数。两种状态的模型可见 tool schema、tool order 和 system sections 保持字节稳定并包含 required `description`;原始调用参数、cell 与嵌套 native 参数保持不变。
59
- 所有字段都由 settings watch 即时交给各自 owner,且不替换已有 session-bound binding。每个已提交 cell 固定其提交时的配置代际,timer、worker 消息、program binding bridge、结果校验和诊断共同消费该快照;重配置更新随后提交 cell 的默认值。`maxOldGenerationSizeMb` 在活动 worker 存在时因 Node 的创建期限制而拒绝并回滚。settings 服务缺失时 Host 回退到 composition config,并保持相同的运行时语义。
60
+ 在 section-installer 代际,所有字段都由 settings watch 即时交给各自 owner,且不替换已有 session-bound binding;在 host-owned 代际,宿主把 volatile-only 变更提交进导出 `Config` 的 retained handles,运行中的 fiber 经公开的 `loader/volatile-update` 事件就地 reconcile,同样保留已有 session-bound REPL、binding 与 journal。每个已提交 cell 固定其提交时的配置代际,timer、worker 消息、program binding bridge、结果校验和诊断共同消费该快照;重配置更新随后提交 cell 的默认值。`maxOldGenerationSizeMb` 在活动 worker 存在时因 Node 的创建期限制而拒绝并回滚。settings 服务缺失时 Host 回退到 composition config,并保持相同的运行时语义。
60
61
 
61
62
  `bindingUpdates` 是新配置的统一入口,默认 `stateful`,也可选择 `protected`。Host schema 保留该字段原始缺省状态,再由 `runtime-config.js` 把完整旧策略映射到相应新策略;混合旧开关保留显式 `legacyBindingSettings` 兼容态。Client 复用同一 resolver,仅在兼容态展示旧开关;用户选择统一开关时,一次 settings update 同时写入新策略并清除兼容标记。
62
63
 
@@ -64,7 +65,7 @@ Client half 通过宿主当前代的设置座位呈现全部配置:旧代际
64
65
 
65
66
  ## Global User Bindings
66
67
 
67
- `internal/user-bindings.js` 是条目、文档、请求快照和有界声明的严格规范化 owner。它从命名 value export 的 TypeScript 源码派生 symbols、binding kind、body-free declaration、durability 与 fingerprint,并封闭校验所有衍生字段;调用方不能提交一份与源码不一致的声明或 snapshot。`namespace` scope 产生一个条目名对象,`top-level` scope 产生选定导出;保留名称和启用集合中的调用标识符冲突在持久化或请求激活前拒绝。
68
+ `internal/user-bindings.js` 是条目、文档、请求快照和有界声明的严格规范化 owner。它从命名 value export 的 TypeScript 源码派生 symbols、binding kind、body-free declaration、durability 与 fingerprint,并封闭校验所有衍生字段;调用方不能提交一份与源码不一致的声明或 snapshot。源码声明保留未被遮蔽的环境类型,并收集公开签名引用的本地 interface、type alias 与 class 闭包;各条目使用独立声明 namespace,公开 class shape 包含实例字段与 constructor parameter property。无法形成自足声明的 imported type 在持久化前拒绝,不能静默替换为 `unknown`。`namespace` scope 产生一个条目名对象,`top-level` scope 产生选定导出;保留名称和启用集合中的调用标识符冲突在持久化或请求激活前拒绝。
68
69
 
69
70
  可选 `modelContext` 与源码一起持久化,包含默认开启的接口注入开关 `includeDeclaration` 和独立注入的提示词 `instructions`。声明只有源码派生这一份,不另行编写。非空 metadata 参与条目 fingerprint;旧条目省略该字段时保持原序列化与 fingerprint,存储文档无需迁移。此前保存的 `enabled` / `declaration` 字段保留规范化形式以验证旧 fingerprint,但旧自定义声明不用于展示或注入;旧关闭状态映射为声明关闭、提示词为空,下一次编辑保存使用新字段。Client 安全的结构校验和偏好映射由 `internal/user-binding-model-context.js` 复用,预算和完整 schema 见 [ADR 0023](adr/0023-global-user-bindings.md)。
70
71
 
@@ -74,7 +75,9 @@ prompt assembly 为每个 PTC request 取得一次当前启用条目快照,作
74
75
 
75
76
  配置段是全局绑定提示词与接口的唯一注入来源,不包含实现源码;成功初始化、session-local shadow 和 worker 重建本身不生成活动公告,也不触发相同配置重发。执行结果与诊断拥有实际行为证据;需要验证可用性时只对已知名称做无副作用观察。历史 `tools:ptc-plus-user-bindings` 活动段保留读取支持,下一次允许且接受的快照撤销旧活动声明一次。`tools:sdk` 与 direct-tool schema 不随条目内容改变。配置 API 不证明当前值,也不延长被 compaction 遮蔽的 session-local 状态。runtime 在 cell preflight 前把期望集合映射到 BindingCatalog,再由 worker 激活:当前覆盖粒度为 `per-name`,同名 session-local binding 只覆盖对应全局名称,同条目的其他名称继续激活;v1-v7 历史 cell 保留整条 entry 退出的旧粒度。条目级失败产生诊断并从该 cell 排除,不阻塞独立代码。失败 initializer 一旦发起 program call,整个 cell 进入 volatile,因此只包含成功条目的结果 snapshot 不会被误作该调用的 cold replay source。
76
77
 
77
- worker 对 namespace 成员和 top-level 导出保留 ECMAScript module live read;对顶层名称的赋值或重声明将该名称转换为 session-local binding,并使该名称在后续全局激活中保持 session-local 覆盖,同一条目的其他名称不受影响;v1-v7 历史 cell 仍按整条来源条目退出。binding module 使用稳定 worker-global proxy 访问当前 request 的全部 program namespace;proxy 在调用时读取 AsyncLocalStorage 中的原 cell lease,因此旧 continuation 即使恰逢下一 cell 运行也不能借用其 authority。新 namespace 可在后续 request 安装,已消失 namespace 的 proxy 不再提供 member;与任何既有 worker global 冲突时,bridge 在写入 global 前拒绝整个安装,避免覆盖 Node intrinsic 或留下部分 namespace。一个导出闭包一旦可能被普通 session binding 保存,worker 就无法证明其不可达,因此相应 synthetic-module 解析基准与已安装 proxy 保守保留到 worker 结束。worker 从未成功暴露过条目时,disabled 或 empty activation 不安装 bridge;若本次尝试全部失败,则在执行 cell 前移除本次安装的 bridge。
78
+ 每个 session kernel 和 binding workbench 各自使用所在 worker 的原生 Node realm。cell、PTC 管理模块、provided `require` 与 binding module 因而共享 intrinsic identity 和 `globalThis`;用户显式创建的 `node:vm` context 或独立运行时保留自己的 realm。
79
+
80
+ worker 对 namespace 成员和 top-level 导出保留 ECMAScript module live read;对顶层名称的赋值或重声明将该名称转换为 session-local binding,并使该名称在后续全局激活中保持 session-local 覆盖,同一条目的其他名称不受影响;v1-v7 历史 cell 仍按整条来源条目退出。当前 `stateful-module-v2` binding module 通过编译后的 logical-root resolver 取得 program namespace,并为每个 cell 建立绑定原 lease 的 namespace view。`stateful-module-v1` 与 legacy binding module 保留其记录代际的 worker-global bridge。两条路径都使旧 continuation 无法借用后续 cell 的 authority,并在后续 request 反映 namespace 的新增与移除。需要安装历史 bridge 且名称与既有 worker global 冲突时,安装在写入前整体失败,避免覆盖 Node intrinsic 或留下部分 namespace。一个导出闭包一旦可能被普通 session binding 保存,worker 就无法证明其不可达,因此相应 synthetic-module 解析基准与历史 bridge 保守保留到 worker 结束。worker 从未成功暴露过需要 bridge 的条目时,disabled 或 empty activation 不安装 bridge;若本次尝试全部失败,则在执行 cell 前移除本次安装的 bridge。
78
81
 
79
82
  配置段以消息文本直接投递,不进入 system renderer;提示词与声明中的 `{{...}}` 保持字面量,不被解释为宿主变量。投递遵守 runtime-context suppression、取消和步骤准入,解除屏蔽后的下一请求同步当前说明。worker 对同一条目 ID 只比较源码、scope、namespace 调用名和有序导出列表来决定模块复用;模型上下文、purpose 或 top-level 显示名称变化不重置模块状态,也不重复初始化。
80
83
 
@@ -101,7 +104,7 @@ Client 遇到冲突后重读 catalog、draft 和 review;只有权威空 draft
101
104
  | Replacement | 只有 DSH 拥有的 compaction 或其他显式 surface replacement 可以替换已保留历史;PTC Plus 不用 replacement 表达瞬时状态。 |
102
105
  | Independent request | 新的辅助模型调用必须单独说明 route、prefix 和 token 影响,不能用它的缓存表现证明主会话前缀稳定。当前插件不发起辅助模型请求。 |
103
106
 
104
- PTC 动态状态通过 DSH 公共 `agent/pre-step` 追加为 `source.plugin: ptc-plus` 的独立 `user/message`。未知完成状态的 rewrite feedback 与 Cordis recovery 构成有界 `snapshot`;全局绑定 API 说明使用独立 `catalog`;恢复 tip 是以 trigger/ordinal 为 identity 的 `notice`。恢复快照只替代 PTC 旧状态,空快照撤销旧状态,不替代绑定目录、authoring task、Skill、tool result 或其他 producer。PTC 更新不重发其他 owner 文本,其他 owner 的 aggregate 更新也不重发未变 PTC 信息。`systemPrompt.context` 中的空 witness 受 `includeRuntimeContext` 与 scoped suppression 管理且不渲染 aggregate 文本;assembly 捕获精确请求事实,pre-step 委托宿主 waterfall 后只对匹配且未取消的 accepted step 提议消息。已提交记录与公共 ordered surface 共同决定去重和状态重申;缺少公共 surface 时不推断可见状态,不投递。raw history 只可用于 tip identity/cooldown,不能让隐藏 binding 变成模型知识。关闭 PTC 后仅保留撤销旧声明所需的被动 presentation cleanup,不安装 runtime 或读取 binding 存储。Cordis 恢复使用规范 journal 与当前 agent/enable generation;绑定目录只描述当前启用配置,不要求激活证明。目录和恢复快照分别去重与撤销,Host aggregate 的撤销不适用于目录;暂停只限制新投递。历史快照中的绑定段由一次恢复快照退役。此类状态不得进入 `PromptAssembly.sections`,也不得通过 tool/schema/order 变化传递。来源、边界与历史兼容由 [ADR 0010](adr/0010-session-log-derived-recovery-tips.md) 拥有。
107
+ PTC 动态状态通过 DSH 公共 `agent/pre-step` 追加为 `source.kind: plugin:ptc-plus` 的独立 `user/message`。未知完成状态的 rewrite feedback 与 Cordis recovery 构成有界 `snapshot`;全局绑定 API 说明使用独立 `catalog`;恢复 tip 是以 trigger/ordinal 为 identity 的 `notice`。恢复快照只替代 PTC 旧状态,空快照撤销旧状态,不替代绑定目录、authoring task、Skill、tool result 或其他 producer。PTC 更新不重发其他 owner 文本,其他 owner 的 aggregate 更新也不重发未变 PTC 信息。`systemPrompt.context` 中的空 witness 受 `includeRuntimeContext` 与 scoped suppression 管理且不渲染 aggregate 文本;assembly 捕获精确请求事实,pre-step 委托宿主 waterfall 后只对匹配且未取消的 accepted step 提议消息。已提交记录与公共 ordered surface 共同决定去重和状态重申;缺少公共 surface 时不推断可见状态,不投递。raw history 只可用于 tip identity/cooldown,不能让隐藏 binding 变成模型知识。关闭 PTC 后仅保留撤销旧声明所需的被动 presentation cleanup,不安装 runtime 或读取 binding 存储。Cordis 恢复使用规范 journal 与当前 agent/enable generation;绑定目录只描述当前启用配置,不要求激活证明。目录和恢复快照分别去重与撤销,Host aggregate 的撤销不适用于目录;暂停只限制新投递。历史快照中的绑定段由一次恢复快照退役。此类状态不得进入 `PromptAssembly.sections`,也不得通过 tool/schema/order 变化传递。来源、边界与历史兼容由 [ADR 0010](adr/0010-session-log-derived-recovery-tips.md) 拥有。
105
108
 
106
109
  所有模型可见输入都必须能从 session log 重建。静态 system/schema 由 `request/header` 保存,动态 context 由带来源的 `user/message` 保存;进程内临时状态不能直接成为未记录的模型输入。在同一插件版本与配置下,普通执行结果、可编辑目标、诊断和其他插件拥有的运行期变化都不得改变 header;`edit_run_code` 的身份与结果由真实 call/result 表达,不生成 edit feedback context。插件升级、显式配置变化、provider/model route 变化、真实 native capability schema 变化,以及 DSH 拥有的 history replacement 可以使缓存从首个变化 token 起失效。
107
110
 
@@ -143,8 +146,10 @@ cell 的静态 import 与 remote re-export 产生有序 preload,Node 继续拥
143
146
 
144
147
  ```ts
145
148
  {
146
- version: 9,
149
+ version: 10,
147
150
  languageSemantics: "legacy-v1" | "stateful-v1" | "protected-v1",
151
+ moduleTransform: "amaro@1.1.11" | "stateful-module-v1+amaro@1.1.11" |
152
+ "stateful-module-v2+amaro@1.1.11" | "protected-module-v1+amaro@1.1.11",
148
153
  bindingPolicy: {
149
154
  variableRedeclarations: boolean,
150
155
  functionClassRedeclarations: boolean
@@ -168,7 +173,7 @@ cell 的静态 import 与 remote re-export 产生有序 preload,Node 继续拥
168
173
  }
169
174
  ```
170
175
 
171
- `languageSemantics` 选择完整编译代际;v1–v8 固定迁移为 `legacy-v1`,不能按当前新语言重新解释。`bindingPolicy`、`rewritePolicy` 与 `moduleSemantics` 保留历史细分契约;新代际从统一策略派生它们,旧代际由冻结编译器消费。`userBindingsFingerprint` 以 `null` 证明不存在 Global User Binding 输入,或以 SHA-256 绑定并行私有快照;声明存在但快照缺失或不一致时,node 形成 unknown boundary。`userBindingsShadowPolicy` 固化该 cell 的 session-local 覆盖粒度,`userBindingNames` 以按名称排序的 `{name, state}` 记录结算时的 provider/local/absent/unknown 事实,因此 cold replay 按历史粒度重放覆盖关系,不从当前实现推断 v1-v7 cell 的整条 entry 语义;provider 事实必须对应并行快照的条目 ID,并覆盖该快照公开的每个名称,否则 node 形成 unknown boundary。`calls` 只保存 global、member、PTC Value Graph 编码的 args/result 或 error,以及 settlement 序号。cold replay 校验调用名称、参数、数量和提交顺序,并按 recorded settlement order 释放 recorded result;不会重新 dispatch program binding 或重做外部 effect。该规则同样适用于 native tools、owner-provided namespace 和 `code.run`,不按名称分支。Cordis 的进程内对象不会因此被宣称已恢复;presentation 可以从已验证 transcript 派生重新检查要求,但不能改变 replay。若基础设施终止时仍有未结算 binding,heap 回滚到 durable frontier,discarded journal 以最先观察到的 `global.member` 保留 possible-effect boundary。effect、completeness 和 source metadata 属于 capability explorer,不伪装成 journal 字段。
176
+ `languageSemantics` 选择语言契约,`moduleTransform` 选择确切 parser、compiler 与 lowering generation;两者必须是允许的配对。v1–v8 固定迁移为 legacy transform,v9 按发布时映射恢复,其中 `stateful-v1` 使用 `stateful-module-v1`,不能按当前 transform 重解释。`bindingPolicy`、`rewritePolicy` 与 `moduleSemantics` 保留历史细分契约;新代际从统一策略派生它们,旧代际由冻结编译器消费。`userBindingsFingerprint` 以 `null` 证明不存在 Global User Binding 输入,或以 SHA-256 绑定并行私有快照;声明存在但快照缺失或不一致时,node 形成 unknown boundary。`userBindingsShadowPolicy` 固化该 cell 的 session-local 覆盖粒度,`userBindingNames` 以按名称排序的 `{name, state}` 记录结算时的 provider/local/absent/unknown 事实,因此 cold replay 按历史粒度重放覆盖关系,不从当前实现推断 v1-v7 cell 的整条 entry 语义;provider 事实必须对应并行快照的条目 ID,并覆盖该快照公开的每个名称,否则 node 形成 unknown boundary。`calls` 只保存 global、member、PTC Value Graph 编码的 args/result 或 error,以及 settlement 序号。cold replay 校验调用名称、参数、数量和提交顺序,并按 recorded settlement order 释放 recorded result;不会重新 dispatch program binding 或重做外部 effect。该规则同样适用于 native tools、owner-provided namespace 和 `code.run`,不按名称分支。Cordis 的进程内对象不会因此被宣称已恢复;presentation 可以从已验证 transcript 派生重新检查要求,但不能改变 replay。若基础设施终止时仍有未结算 binding,heap 回滚到 durable frontier,discarded journal 以最先观察到的 `global.member` 保留 possible-effect boundary。effect、completeness 和 source metadata 属于 capability explorer,不伪装成 journal 字段。
172
177
 
173
178
  journal 通过 `run_code.output.presentationMeta` 附着到最终 result,再由 `tools/result` 做两阶段确认。live binding catalog 在 worker 结算时随实际状态更新,下一条排队 cell 使用这份目录准备;journal 确认只推进持久历史,迟到或逆序的确认不能覆盖较新的 live 目录,也不能恢复已重置的状态。缺失、损坏或被替换的 journal 形成 unknown/volatile 边界;未进入 runtime 的 call 由后续 `confirms` 以对应 `tool/call.seq` 证明为 no-op。volatile 源码保留在原 session log,但不参与 cold replay。
174
179
 
@@ -176,7 +176,7 @@ slot 的迟到、释放、再次声明和功能开关必须测试。缺少所需
176
176
  | 日志与请求 | 展示、展开、隐藏和历史查看不新增 event、模型提示词或声明,不影响前缀稳定性、journal 或模块初始化;真实保存沿用已有 notice/catalog 契约。 |
177
177
  | 能力生命周期 | 验证既有与当前契约、迟到声明、释放、重挂载和开关。能力缺失时保留紧凑请求与明确不可用提示,没有历史写操作或无效的打开入口;恢复后沿用候选和显隐选择。审批接管不误报能力缺失,不以版本号或新造 slot 代替能力证明。 |
178
178
 
179
- 按项目 ledger 流程记录实施发现,最终在稳定树上运行 `npm run check` 和 `git diff --check HEAD --`。独立 reviewer 无缺陷、确定性测试通过、实际 UI 验收是不同证据;不能把其中任一项替代其余。提交与发布仍遵循用户授权及独立审查条件。
179
+ 按项目 ledger 流程记录实施发现,按预先声明的独立 review lanes 取得各 lane 的有效 verdict,最终在稳定树上依次运行 `npm run check`、用 `npm run review:finalize` 记录 composite verdict,再运行 `git diff --check HEAD --`。独立审查、确定性测试、实际 UI 验收是不同证据;不能把其中任一项替代其余。提交与发布仍遵循用户授权及独立审查条件。
180
180
 
181
181
  ## 公共契约与历史证据
182
182
 
package/docs/client-ui.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Client UI
2
2
 
3
- PTC Plus 提供**插件设置卡片**。卡片座位由宿主代际决定:旧代际在 DSH Web/Desktop 的 Settings → Plugin configuration 中以 `settings.plugin.item` 渲染,当前 DSH 在侧栏 Plugins 页面以 `plugins.row.config`(键 `<包名>#<行 id>`)渲染该 bundle 自己的配置;`src/client-host-compat.js` 同时发布到两个座位,由声明了槽位的那一代决定哪个生效,卡片按座位提供的 `summary`/`page` 视图分别渲染一句描述与完整表单。输入框旁的星光菜单还直接打开复用同一表单的应用内设置窗口,不依赖宿主页面的局部导航状态;菜单项悬浮提示保留原生设置座位的路径。
3
+ 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` 视图分别渲染一句描述与完整表单。输入框旁的星光菜单还直接打开复用同一表单的应用内设置窗口,不依赖宿主页面的局部导航状态;菜单项悬浮提示保留原生设置座位的路径。
4
4
 
5
- Client 根入口只依赖 `settingsScope`、`slots`、`locale`、`connection` 和 `remote`。头部贡献直接消费公开 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 或自行重建会话状态。
5
+ Client 根入口只依赖 `slots`、`locale`、`connection` 和 `remote`;settings transport 由当前代的 `configForms` 或上一代的 `settingsScope` 可选注入提供。头部贡献直接消费公开 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
6
 
7
7
  组件通过 renderer 提供的 `useProjection`、旧宿主的公开 `useSessions` 和注入 `hooks` 读取外部状态,设置写入与 RPC 由 apply 层注入 callback。业务组件不自行构造 external-store hook。设置、slot、provider 与插件释放共同拥有注册和订阅的生命周期;开关关闭时撤销相关贡献。
8
8
 
@@ -26,7 +26,7 @@ Host half 通过 DSH 公共 `settings` 服务注册命名空间 `ptc-plus`。字
26
26
  | REPL 语法 | `bindingUpdates` | 默认 `stateful`;同作用域的声明与赋值更新变量、函数、类和导入。选择 `protected` 后保护新建 const/import,并检测跨 cell 重声明。两种策略均支持静态 import/export。 |
27
27
  | 状态与恢复 | `durableReplay` / `tipsEnabled` | 默认开启;控制 worker 重启后的状态恢复与失败恢复提示。 |
28
28
  | 状态与恢复 | `tipCooldownMessages` / `tipEscalationFailures` | 同类提示间隔与详细提示阈值。 |
29
- | 工具扩展 | `userBindingsEnabled` | 默认关闭;开启后加载跨会话 TypeScript helper,并在开关下方显示管理按钮,同时启用全局绑定工作台与 `/binding` Agent 编写入口。 |
29
+ | 工具扩展 | `userBindingsEnabled` | 默认开启,显式关闭仍有效;开启时加载跨会话 TypeScript helper,并在开关下方显示管理按钮,同时启用全局绑定工作台与 `/binding` Agent 编写入口。 |
30
30
  | 工具扩展 | `cordisToolsEnabled` | 默认关闭;开启后为 PTC agent 加入官方 Cordis 工具、指引与精确的 `cordis-plugin-development` companion Skill,不发布同目录 sibling。 |
31
31
  | 界面显示 | `enhancedToolView` | 默认开启;关闭后注销 PTC Plus 的两个 keyed tool view,恢复 DSH 原生 generic row。 |
32
32
  | 界面显示 | `replViewEnabled` | 默认开启;控制顶级 REPL 页签,关闭时释放观察订阅,不影响设置中的全局管理入口。 |
@@ -34,7 +34,7 @@ Host half 通过 DSH 公共 `settings` 服务注册命名空间 `ptc-plus`。字
34
34
  | 资源限制 | `computeMs` / `maxWallMs` | 单 cell event-loop active(包括同步阻塞)与总耗时预算;前者不证明 CPU 消耗。 |
35
35
  | 资源限制 | `maxOldGenerationSizeMb` / `maxNestedRunCodeDepth` | kernel worker 内存与嵌套执行深度。 |
36
36
  | 资源限制 | `maxOutputBytes` | 单 cell 日志与返回结果的合计字节上限。 |
37
- | 资源限制 | `maxValueNodes` / `maxValueEdges` / `maxValueArrayLength` / `maxValueBigIntDigits` | Value Graph 与大数组、BigInt 的返回上限。 |
37
+ | 资源限制 | `maxValueNodes` / `maxValueEdges` / `maxValueArrayLength` / `maxValueBigIntDigits` | Value Graph 与大数组、BigInt 的返回上限;数组长度限制同时约束单数组和一份 graph 的累计槽位。 |
38
38
 
39
39
  旧配置的五个开关(`looseTopLevelRedeclarations`、`looseTopLevelFunctionClassRedeclarations`、`autoRewriteImports`、`autoStripExports`、`autoSplitRedeclarations`)先由共享 resolver 迁移。完整策略映射到 `stateful` 或 `protected`;混合选择保留显式兼容态,只有该状态才显示旧控件。兼容态的统一策略控件显示“沿用旧版设置(尚未迁移)”,可直接选择“允许重声明和覆盖”或“启用名称保护”;选择后一次写入同时保存 `bindingUpdates` 并清除兼容标记,随后执行和模型指引采用相同的新语言策略,设置页恢复统一开关。仅查看设置不触发写入。
40
40
 
@@ -81,6 +81,10 @@ PTC session 的头部弹窗在功能启用时增加 Session 与 Global 页签。
81
81
 
82
82
  `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
83
 
84
+ 星光入口的四个动作(编写新绑定、修改绑定、管理全局绑定、PTC Plus 设置)始终由插件自己的动作区承载——`Agent 编写` 分组标题加两列网格,再一行工具入口——而不是宿主的列表行。该动作区优先放进公共 `Menu` 的 `children` 区域。这个区域不是所有已发布 Client 都会渲染的输入:较早的实现接受 `children` 属性却不挂载任何节点。`src/client-host-compat.js` 因此以已挂载输出而不是版本号判定该契约:首个 composer 入口挂载时渲染一次隐藏、非 portal 的 `Menu`,读取其中是否出现插件自己的哨兵子节点,随后在同一次提交内丢弃探测;答案在单个 Client 生命周期内只记录第一次结果,后续会话入口复用该答案、不再渲染探测。未渲染 `children` 时插件不把“未回答”当作结论,也不退化成宿主行:同一份动作区改由该 `Menu` 一向渲染的 pinned 区域承载(入口类型为 label,内容仍是插件自己的网格),因此分组、分组分隔线、两列布局、文案、顺序和设置座位提示在所有代际一致;渲染 `children` 的 Client 不再追加 pinned 副本,避免同一动作出现两次。pinned 载体只抵消自身的外边距和上边框,避免与宿主 footer 的 hairline 叠成两条;分组分隔线位于 `Agent 编写` 网格与工具入口之间,不会与它重复。已发布的 Client 至少渲染 pinned 区域;两处都不渲染的代际没有可承载这四个动作的宿主插槽,插件不以自有浮层替换宿主菜单,也不因此伪造宿主能力。探测挂载失败时不记录任何结论,入口保持原有渲染路径。
85
+
86
+ 悬浮窗里的条目启停不改变列表的可用性:写入由 catalog source 串行化、重复请求被丢弃,因此请求期间行不会被禁用(宿主会给禁用行降透明度)也不会插入“正在保存”行,避免整个悬浮窗在每次切换时闪一下;只有尚无目录可操作或读取失败时行才不可用。
87
+
84
88
  `autoDescribeRunCode` 的设置名称是“允许执行缺少摘要的 run_code”,默认开启并即时生效。缺少外层 `run_code.description` 时,调用使用派生参数通过本地 DSH 校验,备用摘要仅进入 presentation metadata;关闭时由 DSH 校验原始参数。两种状态的模型请求保持字节稳定并包含 required `description`,原始调用参数、已有摘要、cell 源码和嵌套 native 工具参数保持不变。
85
89
 
86
90
  设置卡片、正文 tool view 与 REPL 可复用 binding 卡片的全部文案都注册到 DSH client locale 的 `settings.ptcPlus` 命名空间,随当前界面语言在中文与 English 之间切换;字段名称与说明的两种语言文本同样来自 `internal/config-spec.js`(`label`/`labelEn`、`description`/`descriptionEn`,某一字段的说明要么两种语言都有,要么都没有),展示 chrome 文案由 client half 拥有。稳定 REPL 指引不承载 UI 品牌名。启用且会话选择 `ptc` 或兼容的 `code` preset 时,`conversation.session.header.actions` 以稳定 id `ptc-plus-active` 显示简洁的 `PTC Plus` 标识;视口不超过 560px 时隐藏该可选标识,为原生页头操作留出空间,会话绑定继续从 REPL 页签访问。preset 与 binding inventory 优先读取 session slot 的公共 `useProjection`;只有 preset 在缺少 projection 时可读取旧宿主公开会话摘要,binding inventory 不回退。关闭时不注入任何 PTC 指引或工具 surface。
@@ -93,7 +97,7 @@ PTC session 的头部弹窗在功能启用时增加 Session 与 Global 页签。
93
97
 
94
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` 路径把运行/失败/中断状态、摘要和已证明的功能标记放进同一行始终可见的单行预览;完成态由标题与摘要表达,运行/失败/中断状态由文字 chip 承担并保持可访问。预览间距由插件自有类对称提供,并按单行内容布局,不依赖 Host primitive 的行内几何;源码、结果和 Inspect 只出现在展开主体。结果内容与原生 ioCard 采用相同的灰色圆角背景(`--dsw-alias-markdown-code-block` 加 12px 圆角与边框),失败态使用错误色文字;代码块的语言/复制栏保持原生 CodeBlock 的常亮可见;`检查调用` 入口采用原生 inspectButton 同款胶囊样式,默认 opacity 0,仅在卡片 `:hover` 或 `:focus-visible` 时淡入(opacity .1s),不触发任何布局位移。窄屏下回退路径的摘要允许换行。
95
99
 
96
- 功能标记不是计数,也不把“插件已启用”冒充成一次功能收益。Client 只在完整 v1-v9 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`;任一缺失或畸形都不产生功能标记。进程保留或 discarded 状态不作为正文功能标记。普通变量或 function/class 重声明、顶层 native 调用是否来自 canonicalizer、`cordis_*` 成员是否由官方可选 Cordis mount 提供,以及是否实际选择了 prompt 恢复提示没有独立的 Client-only 事实,因此不根据可复制的代码形状、工具名前缀或设置默认值推测;恢复边界本身不展示。
100
+ 功能标记不是计数,也不把“插件已启用”冒充成一次功能收益。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 事实,因此不根据可复制的代码形状、工具名前缀或设置默认值推测;恢复边界本身不展示。
97
101
 
98
102
  正文工具行和头部 Session 清单不检查或改写宿主 DOM,不调用 Host、不主动加载历史。头部卡片只展示随结果持久化的名称与定义源码,不使用值预览;全局管理操作单独使用前述管理 Remote。这些展示不改变 canonical result、tool schema、system prompt、runtime context、journal schema 或迁移器,也不向模型公开状态。未知 journal 版本、未知 metadata 字段和损坏 metadata 只会让对应功能标记或 binding 列表缺席,不会隐藏源码或结果;无法脱离 session call identity 解析非空 v1 `confirms` 时同样只省略标记,不触发历史读取或迁移。因此 UI 是否安装、能否渲染以及用户是否悬浮、聚焦或展开正文行,都不会改变模型请求或会话继续语义,也不能作为在模型 surface 收缩后继续保留 runtime binding 的证据。
99
103
 
@@ -30,8 +30,10 @@ PTC Plus 的正确承诺是:
30
30
 
31
31
  ```ts
32
32
  {
33
- version: 9,
33
+ version: 10,
34
34
  languageSemantics: "legacy-v1" | "stateful-v1" | "protected-v1",
35
+ moduleTransform: "amaro@1.1.11" | "stateful-module-v1+amaro@1.1.11" |
36
+ "stateful-module-v2+amaro@1.1.11" | "protected-module-v1+amaro@1.1.11",
35
37
  bindingPolicy: {
36
38
  variableRedeclarations: boolean,
37
39
  functionClassRedeclarations: boolean
@@ -67,7 +69,8 @@ PTC Plus 的正确承诺是:
67
69
  字段含义:
68
70
 
69
71
  - `durable`:创建可重放 node,推进 `durableHead`;
70
- - `languageSemantics`:固定完整语言代际;新统一策略选择 `stateful-v1` 或 `protected-v1`,显式旧设置兼容态与 v1–v8 历史使用 `legacy-v1`。冷重放从该字段选择编译路径,不用当前配置替换历史声明、闭包和初始化语义;
72
+ - `languageSemantics`:固定语言契约;新统一策略选择 `stateful-v1` 或 `protected-v1`,显式旧设置兼容态与 v1–v8 历史使用 `legacy-v1`;
73
+ - `moduleTransform`:固定确切 parser、compiler 与 lowering generation。冷重放直接使用该字段,不从 `languageSemantics` 或当前配置反推;
71
74
  - `bindingPolicy`:记录该 cell 实际采用的变量重声明和 function/class 重声明语义;冷重放读取每个 node 的完整记录值,并用它重建 binding 可写性,不读取恢复时的 profile 配置;
72
75
  - `rewritePolicy`:记录该 cell 解析和 lowering 时使用的三个 AST rewrite 开关;冷重放读取每个 node 的记录值,不读取恢复时的 profile 配置;
73
76
  - `moduleSemantics`:保留旧模块 lowering 的独立代际;`legacy-v1` 按记录值恢复 default binding 与模块引用写入的语句边界。当前 live cell 写入 `live-readonly` 与 `statement-safe`,但新语言的可写 alias、default 关联和提交规则由 `languageSemantics` 决定,不能仅凭历史字段中的 `readonly` 推断当前 binding 不可写;
@@ -92,7 +95,7 @@ SessionRuntime 创建 kernel 时完全忽略历史 nodes、head、checkpoints
92
95
 
93
96
  journal、diagnostic、source、cause、call、operation、completion 和 completion error 都使用封闭字段集合;未知、symbol 或非枚举自有字段会使 journal 无效。capability-call `args`/`value` 与 return completion `value` 都是封闭、规范化的 `ptc-value-graph/v1` envelope。诊断结构、source frame 依赖和稳定代码见[架构说明](architecture.md#journal-与恢复)。
94
97
 
95
- 当前实现只写入 `version: 9` schema。v9 必须携带 `languageSemantics`,其值为 `legacy-v1`、`stateful-v1` 或 `protected-v1`;v1–v8 固定迁移为 `legacy-v1`,由冻结历史编译器重放,不能因当前配置或新 lowering 改变隐藏状态([ADR 0025](adr/0025-use-versioned-logical-binding-identities.md))。v1-v8 作为封闭 predecessor 输入规范化为 v9:v1-v3 的旧 `bindingMode` 精确映射到 `bindingPolicy.variableRedeclarations`,而 `functionClassRedeclarations` 固定为 `false`,因为旧 pipeline 不具备该语义;`moduleSemantics.defaultExportBinding` 固定迁移为 `legacy-variable`,使 loose 历史保留旧的可写生成 binding、strict 历史保留旧的 const 行为;v1-v6 的 `moduleSemantics.importExpressionBoundary` 固定迁移为 `legacy`,使历史写入沿用其记录时的语句 lowering,v7 保留自身记录的边界代际。v1 仍使用三个 rewrite 开关全关的历史默认值,并只在 session log 唯一证明 call identity 时迁移字符串 confirmation;v2/v3 保留自身 `rewritePolicy`。v4/v5 保留已有 binding/rewrite/module 语义;v6 与 v7 保留其记录的 `userBindingsReusePolicy`。v1-v4 的 `userBindingsFingerprint` 固定为 `null`,v5 及之后的代际保留自身记录的快照指纹;v1-v5 的 `userBindingsReusePolicy` 固定为 `fingerprint-v1`。v1-v7 的 `userBindingsShadowPolicy` 固定迁移为 `whole-entry`,`userBindingNames` 固定为 `null`,因此历史 node 继续按整条条目退出,只有 v8 起的 cell 使用 `per-name` 名称证据。无法表示为非负 event sequence 的 confirmation 必须形成 unknown boundary 并触发状态收缩。包括 `languageSemantics`、`bindingPolicy`、`rewritePolicy`、`moduleSemantics`、`userBindingsFingerprint`、`userBindingsReusePolicy`、`userBindingsShadowPolicy`、`userBindingNames`、`diagnostics` 在内的当前必需字段缺失或策略未知时 journal 必须失效,否则会削弱最终持久值与 tentative journal 的严格一致性确认;失效 journal 不证明旧 binding,但也不单独成为后续当前调用的 availability gate。profile 后续切换任一 binding 或 AST rewrite 开关只影响新 cell,历史 node 始终按自身记录的 policy 和 module semantics 重放。新旧全局绑定复用策略与覆盖粒度可共存于同一历史,重复规范化不能把旧策略或旧粒度升级为当前值;没有返回值的 completion 不能证明模块内部状态相等。
98
+ 当前实现只写入 `version: 10` schema。v10 必须携带 `languageSemantics` 与匹配的 `moduleTransform`。v1–v8 固定迁移为 `legacy-v1` 和 legacy transform;v9 保留其语言字段,并按该版本发布时的映射补入 transform:`stateful-v1` 使用 `stateful-module-v1`,`protected-v1` 使用 `protected-module-v1`,`legacy-v1` 使用 legacy transform。当前代际新提交的源码可把 `import.meta` lowering 为记录 session module base 的 cell-local metadata;`legacy-v1` 仍使用冻结 parser 并保留历史拒绝,且此前不可能成功记录的 MetaProperty 不能被恢复时重新解释。恢复不能因当前配置或新 lowering 改变隐藏状态([ADR 0025](adr/0025-use-versioned-logical-binding-identities.md))。v1-v9 作为封闭 predecessor 输入规范化为 v10:v1-v3 的旧 `bindingMode` 精确映射到 `bindingPolicy.variableRedeclarations`,而 `functionClassRedeclarations` 固定为 `false`,因为旧 pipeline 不具备该语义;`moduleSemantics.defaultExportBinding` 固定迁移为 `legacy-variable`,使 loose 历史保留旧的可写生成 binding、strict 历史保留旧的 const 行为;v1-v6 的 `moduleSemantics.importExpressionBoundary` 固定迁移为 `legacy`,使历史写入沿用其记录时的语句 lowering,v7 保留自身记录的边界代际。v1 仍使用三个 rewrite 开关全关的历史默认值,并只在 session log 唯一证明 call identity 时迁移字符串 confirmation;v2/v3 保留自身 `rewritePolicy`。v4/v5 保留已有 binding/rewrite/module 语义;v6 与 v7 保留其记录的 `userBindingsReusePolicy`。v1-v4 的 `userBindingsFingerprint` 固定为 `null`,v5 及之后的代际保留自身记录的快照指纹;v1-v5 的 `userBindingsReusePolicy` 固定为 `fingerprint-v1`。v1-v7 的 `userBindingsShadowPolicy` 固定迁移为 `whole-entry`,`userBindingNames` 固定为 `null`,因此历史 node 继续按整条条目退出,只有 v8 起的 cell 使用 `per-name` 名称证据。无法表示为非负 event sequence 的 confirmation 必须形成 unknown boundary 并触发状态收缩。包括 `languageSemantics`、`moduleTransform`、`bindingPolicy`、`rewritePolicy`、`moduleSemantics`、`userBindingsFingerprint`、`userBindingsReusePolicy`、`userBindingsShadowPolicy`、`userBindingNames`、`diagnostics` 在内的当前必需字段缺失或策略未知时 journal 必须失效,否则会削弱最终持久值与 tentative journal 的严格一致性确认;失效 journal 不证明旧 binding,但也不单独成为后续当前调用的 availability gate。profile 后续切换任一 binding 或 AST rewrite 开关只影响新 cell,历史 node 始终按自身记录的 policy、module semantics 与 transform 重放。新旧全局绑定复用策略与覆盖粒度可共存于同一历史,重复规范化不能把旧策略或旧粒度升级为当前值;没有返回值的 completion 不能证明模块内部状态相等。
96
99
 
97
100
  ## Capability Call Transcript
98
101
 
@@ -158,7 +161,7 @@ pre-execute -> tools/execute -> post-execute
158
161
 
159
162
  恢复以当前请求需要的 head 为目标,沿可证明 parent 关系向更早 frontier 收缩;实现可以前向折叠 event 建图,但不得把 unknown boundary 两侧的日志位置当作状态依赖证据。恢复入口先把当前 call id 解析为持久化 `tool/call.seq`,再把该序号作为 live boundary 传入折叠器;对应的在途 call event 不属于历史。每个 `edit_run_code` 在其 call event 处,根据此前已经结算的调用确定并固定可编辑目标;之后出现的 result 只影响随后发起的 edit:
160
163
 
161
- 1. 用 `sourceEventSeqs[0]` 关联 `tool/result` 与 `tool/call`;
164
+ 1. 用 `sourceEventSeqs[0]` 关联 `tool/result` 与 `tool/call`;若 result 同时带有 `message.source.callId`,两种身份必须指向同一个 call,否则该 call 建立 untrusted boundary。每个 ordinary result 在 journal 解析前闭合一次 call settlement;同一 call 的第二个 ordinary result 被拒绝。经过结构校验的 prune replacement 是唯一不占用第二次 ordinary settlement 的替代表示;
162
165
  2. 预收集 valid journal 中的 `confirms`;
163
166
  3. 排除与 live boundary 序号相同的在途 call,并让已确认 no-op 的无 journal call 不改变状态;
164
167
  4. 缺失源码、缺失/损坏 journal 或无法验证的 call/result/prune 关联建立 untrusted boundary,不作为旧 binding 的证据;
@@ -177,11 +180,11 @@ pre-execute -> tools/execute -> post-execute
177
180
 
178
181
  ## 模型可知状态
179
182
 
180
- DSH session 同时提供两个不同投影:append-only event log 保存审计、journal 与 replay evidence;ordered surface/derived request history 是模型请求实际可见的消息历史。PTC Plus 的默认状态 frontier 是“结构可重建”和“模型可知”的交集,不能用 raw log 的存在替代 surface evidence。模型可知只采用外部可验证事实,不猜模型内部记忆:精确声明源码仍在当前 request surface,或插件/宿主通过有界结构把准确 binding identity 与 provenance 放入模型上下文。
183
+ DSH session 同时提供两个不同投影:append-only event log 保存审计、journal 与 replay evidence;ordered surface/derived request history 是模型请求实际可见的消息历史。PTC Plus 的默认状态 frontier 是“结构可重建”和“模型可知”的交集,不能用 raw log 的存在替代 surface evidence。模型可知只采用外部可验证事实,不猜模型内部记忆:可见 assistant tool-call block 必须以相同 call id、tool name 和原始 JSON arguments 精确对应 raw dispatch,或插件/宿主通过有界结构把准确 binding identity 与 provenance 放入模型上下文。只匹配 call id、可见 `tool/result`、result source relation 或 raw log 不能证明声明源码可见。若 ordered surface 缺失、格式错误或不可读取,就没有历史 executable provenance 可证明,恢复必须收缩到空 frontier;这只否定历史 binding 证据,当前有效 cell 仍从空 REPL 正常执行。
181
184
 
182
185
  surface replacement 是否删除状态取决于模型失去了什么,而不取决于是否出现 `compaction/prune` 这个名字。只替换过长 tool result、仍保留 assistant `run_code`/`edit_run_code` 调用及源码时,模型仍知道该 cell,可继续使用其 journal。若 replacement 或 summary 遮蔽了声明 provenance,raw journal 即使完整也不能让 binding 默认继续存在;自然语言 summary 不解析为依赖或 binding 证明。当前没有模型可见的完整 binding inventory,因此缺少精确 provenance 时按 cell 与依赖后缀收缩。
183
186
 
184
- 该规则也约束 live worker。runtime 在下一 cell 前观察 DSH public surface generation;发生 replacement 后,若现存 binding 超出模型可知 frontier,先重置 worker、重建交集 frontier,再执行当前 cell。Client header card 的 `dshPtcPlusBindings` 只帮助用户检查,不进入模型上下文,也不延长 binding 生命周期;相同 contraction 应让 UI inventory 进入不可确认状态。未来若新增模型可见状态投影,它必须由用户、模型或明确配置选择,有固定 schema、硬预算、append-only runtime-context 证据和明确清除条件,不能仅为延长隐藏状态而默认注入,也不能污染稳定 prompt prefix。
187
+ 该规则也约束 live worker。structured host session 的 runtime 在每个后续 cell 前都重新读取 DSH public ordered surface,并验证所有现存 live call 的精确 assistant provenance;`replaceGeneration` 没有变化不构成继续复用的证明。generation 改变、缺失或不可读取也进入同一验证。若现存 binding 超出模型可知 frontier,先重置 worker、重建交集 frontier,再执行当前 cell。只有不带 host session 的内部 primitive session id 明确使用 live-only 连续性。Client header card 的 `dshPtcPlusBindings` 只帮助用户检查,不进入模型上下文,也不延长 binding 生命周期;相同 contraction 应让 UI inventory 进入不可确认状态。未来若新增模型可见状态投影,它必须由用户、模型或明确配置选择,有固定 schema、硬预算、append-only runtime-context 证据和明确清除条件,不能仅为延长隐藏状态而默认注入,也不能污染稳定 prompt prefix。
185
188
 
186
189
  ## Completion 校验
187
190
 
@@ -223,7 +226,7 @@ type StateOperation =
223
226
 
224
227
  静态分类器理解 top-level、block、function、catch 和 loop binding。它只把实际未绑定的 ambient reference 作为降级候选;属性键和局部同名变量无影响。
225
228
 
226
- 运行时对以下访问标记 volatile。归因依据是 worker 当前 active execution,不使用异步回调继承的 `AsyncLocalStorage` store。active execution 从开始求值持续到 capability calls 结算、返回值 PTC value graph 编码或异常归一化全部完成;这些阶段的 getter、Proxy 或字符串转换仍可能执行用户代码。最终 durability 必须在转换后采样,纯 wire message 构造完成后才在最外层 `finally` 清除 active execution。只有此后发生的访问才暂存 reason 并使下一 cell volatile:
229
+ 运行时对以下访问标记 volatile。durability 归因依据是 worker 当前 active execution,不使用异步回调继承的 `AsyncLocalStorage` store。active execution 从开始求值持续到 capability calls 结算、返回值 PTC value graph 编码或异常归一化全部完成;这些阶段的 getter、Proxy 或字符串转换仍可能执行用户代码。最终 durability 必须在转换后采样,纯 wire message 构造完成后才在最外层 `finally` 清除 active execution。只有此后发生的访问才暂存 reason 并使下一 cell volatile:
227
230
 
228
231
  - Date、performance、fetch、WebSocket、crypto、Intl;
229
232
  - setTimeout、setInterval、setImmediate;
@@ -231,12 +234,12 @@ type StateOperation =
231
234
  - `Math.random()`;
232
235
  - durable allowlist 之外的 dynamic import,包括 `node:path`。
233
236
 
234
- 普通 `Math` intrinsic 保持完整。`process.stdout/stderr.write` 被捕获为 cell log,不因输出本身降级。
237
+ 普通 `Math` intrinsic 保持完整。`console` 与 `process.stdout/stderr.write` 使用私有 `AsyncLocalStorage` 保留其调度 cell 的日志归属;该 cell 关闭后的结构化输出产生诊断并重置 worker,不静默丢弃。直接 fd 1/2 与继承的 child stdio 没有调度身份,Host 以每轮 stdout/stderr start/end fence 的物理到达窗口捕获;窗口内字节计入该轮预算。窗口外第一笔字节立即关闭 capture 并触发重置;若当时没有 active cell,Host 保留一次失败并让下一次执行显式失败,而不是继续无界 drain。stdout、stderr 和结构化日志各自保持顺序,合并结果不声称跨通道全序。该日志规则与上段 durability 归因分别拥有输出交付和恢复分类,不能互相替代。
235
238
 
236
239
  worker 不继承 Electron 的工作目录语义。插件通过现有 `tools/execute` context 读取不可变的 `agent.session.header.cwd` 并注入 session worker;`process.cwd()` 返回该值且保持 durable。header 未记录 cwd 时才回退宿主值并在运行时标记 volatile。
237
240
  同一 session 中,`child_process` 的 `exec`、`execFile`、`fork`、`spawn` 及同步变体在未提供 `options.cwd` 时以该 cwd 启动;显式 cwd 保持调用方选择。worker 保留 Node、package manager 和 shell 所需的宿主环境变量,仅将 `TEMP`、`TMP` 和 `TMPDIR` 覆盖为该 session 的 scratch 目录。`node:fs`、`node:fs/promises` 和 glob 的相对入口统一以 session cwd 解析,绝对路径与显式路径选项保持原生语义。
238
241
 
239
- 直接访问 `worker_threads` 或 `cluster` 的常见 import/require 形式会被拒绝。直接 `process`、`require`、dynamic import 与 static import 取得的 `process.exit/abort/kill/chdir` 共享同一组拒绝函数,因为这些操作暴露或破坏 worker lifecycle control。该 gate 只维护 REPL 生命周期,不是恶意
242
+ 直接访问 `worker_threads` 或 `cluster` 的 static import、dynamic import 和未遮蔽 `require` 会在 cell 任何语句执行前的 preflight 阶段被拒绝,因此外围 `try`/`catch` 不能捕获该拒绝。直接 `process`、`require`、dynamic import 与 static import 取得的 `process.exit/abort/kill/chdir` 共享同一组拒绝函数,因为这些操作暴露或破坏 worker lifecycle control。该 gate 只维护 REPL 生命周期,不是恶意
240
243
  代码安全沙箱;native tool 的安全依赖 DSH policy,ambient Node 的安全依赖进程隔离和操作系统权限。
241
244
 
242
245
  ## 恢复通知
@@ -24,14 +24,14 @@ The plugin attaches to whichever program-execution service the installed DSH reg
24
24
 
25
25
  Every installation path uses an unmodified official DSH distribution. Local plugin development packages this checkout; it does not build, patch, or substitute 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.
26
26
 
27
- The Client root requires `settingsScope`, `slots`, `locale`, and `connection`. 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 the preceding 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.
27
+ The Client root requires `slots`, `locale`, `connection`, and `remote`; it resolves the installed generation's settings transport (`configForms` on the current alpha, `settingsScope` on the preceding RC) through an optional injection. 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 the preceding 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.
28
28
 
29
29
  ## npm Release
30
30
 
31
31
  Use this form after the selected version is available from the npm registry:
32
32
 
33
33
  ```sh
34
- dsh plugin --profile <profile> add dsh-ptc-plus@0.4.1
34
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.4.3
35
35
  dsh --profile <profile> --dump-config
36
36
  ```
37
37
 
@@ -68,7 +68,7 @@ pnpm dsh --profile <profile> --dump-config
68
68
 
69
69
  ```sh
70
70
  npm pack
71
- dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.4.1.tgz
71
+ dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.4.3.tgz
72
72
  dsh --profile <profile> --dump-config
73
73
  ```
74
74
 
@@ -89,7 +89,7 @@ On Windows, `--browser-channel msedge` can use the existing Edge installation. T
89
89
 
90
90
  ## Isolated latest-DSH development launcher
91
91
 
92
- To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It resolves the newest published DSH release by semantic version over all published versions, prereleases included, rather than following a dist-tag that a release can leave behind; it installs that exact version only when the cached version changes, creates the shipped `web` profile inside an isolated `DSH_HOME`, installs this checkout, and starts DSH. If no port is supplied, it selects a free loopback port automatically, so another DSH on port 3080 does not block the test instance. The launcher does not modify the repository or your normal DSH home.
92
+ To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It resolves the newest published DSH release by semantic version over all published versions, prereleases included, rather than following a dist-tag that a release can leave behind; it installs that exact version only when the 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
93
 
94
94
  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
95
 
@@ -106,20 +106,38 @@ dsh plugin add github:muyuanjin/dsh-ptc-plus#main
106
106
  dsh --dump-config
107
107
  ```
108
108
 
109
- After an npm release, the package spec may instead be `dsh-ptc-plus@0.4.1`. 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.
109
+ After an npm release, the package spec may instead be `dsh-ptc-plus@0.4.3`. 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
+
111
+ ## Upgrades
112
+
113
+ PTC Plus upgrades independently of the host. Replace the installed package with the new release the same way it was installed — `npm install dsh-ptc-plus@latest`, a new tarball, or an updated pinned Git revision in the profile patch — and restart the host so every profile reloads the plugin. The plugin never patches DSH and never requires a custom host build, so a host upgrade keeps the plugin working as long as the public surfaces it needs are still published.
114
+
115
+ Your settings document and session logs are not rewritten by an upgrade. A release that adds a configuration field applies its documented default until you choose a value. A release that raises the Session format generation requires the migration below before an older log is opened by the new Host; the plugin reports that condition instead of rewriting history on its own.
116
+
117
+ ## Troubleshooting
118
+
119
+ Start from the exact diagnostic: every message below names the surface that is missing, and the plugin keeps the rest of its behavior intact while the condition holds.
120
+
121
+ - `ptc-plus: no host execution seam (ptcRuntime or codeRuntime) is registered` — the profile publishes no DSH code runtime, or that entry failed to activate. Repair or enable the runtime row and reload; the plugin attaches as soon as the service appears.
122
+ - PTC Plus says the settings service is unavailable, and its indicator and sparkle button are missing — a retained plugin dependency may lack the schema capability required by the current Host. Reinstall the current plugin package and restart DSH; the dependency range requires a builder that supports live settings. The development launcher performs that installation on its next launch. This message alone does not prove that runtime execution is disabled. A missing required `volatile()` builder now produces an explicit dependency diagnostic during plugin loading.
123
+ - `ptc-plus: Cordis companion tooling withdrew from an agent scope` — an exposed companion service, preset, Skill or child fiber failed its required contract. Repair the specific cause attached to the warning, or disable `cordisToolsEnabled` if that integration is unavailable. A scope missing optional companion surfaces instead waits silently and retries when its tool surface changes or its next prompt is assembled.
124
+ - A commit is refused with a verification or proof error — follow [deterministic verification](verification.md): resolve any incomplete lanes shown by `npm run review:status`, run `npm run check` on the frozen tree, then `npm run review:finalize`. Stage that verified candidate and retry. Use `npm run hooks:install` if the hook is missing; never bypass it.
125
+ - A historical PTC session cannot be resumed — follow the Session format upgrade below, keep the original log, and report the exact refusal message.
110
126
 
111
127
  ## Session format upgrades
112
128
 
113
129
  The public DSH Session format catalog can renumber events when converting historical assistant streams. It treats plugin result metadata as opaque, so its automatic conversion alone cannot preserve PTC sequence references. Before opening historical PTC sessions in the new Host, stop the processes using that profile and retain a backup of each original log.
114
130
 
115
- From this source checkout, convert a source artifact with the destination Host's public catalog:
131
+ From this source checkout, convert a standalone source artifact with the destination Host's public catalog. An empty child set must be explicit:
116
132
 
117
133
  ```sh
118
- npm run session:migrate -- --dsh-entry /path/to/dsh/lib/bin.js --input /backup/session.jsonl --output /staging/session.v2.jsonl
134
+ npm run session:migrate -- --dsh-entry /path/to/dsh/lib/bin.js --no-children --input /backup/session.jsonl --output /staging/session.v2.jsonl
119
135
  ```
120
136
 
137
+ For a parent session, pass `--child-facts /backup/child-facts.json` instead. The JSON file must be the complete array of direct-child evidence produced through the selected Host's public historical catalog and child-fact APIs. Do not use `--no-children` merely because child artifacts are unavailable: newer format migrations use those facts to preserve or reconstruct the parent's child catalog and deliberately refuse to guess. Current-format inputs need neither option because no historical body migration runs.
138
+
121
139
  The output header and command report identify the actual target **Session format**, independent of the DSH package version. Use the corresponding canonical filename `session.v<N>.jsonl` in that session's existing directory. Match the persistence provider's encoding: `.zstd` input/output uses the `zstd` executable, with separate header and event frames. The example names format 2; use the format reported by the selected catalog. Only place the validated output in the stopped profile after inspecting it. Keep the predecessor artifact for rollback; do not continue editing the same history through old and new Hosts in parallel.
122
140
 
123
- The converter verifies that ordered tool records retain their identities, maps journal confirmations, edit targets and recovery boundaries, and revalidates the output. It leaves original model arguments, source, results and recorded effects unchanged. Input files are never overwritten, including through hard links; existing destinations require explicit `--force`. A current-format source needs no output. A Host without the public catalog cannot perform Host format conversion.
141
+ The converter verifies that ordered tool records retain their normalized call arguments, result content, error status, PTC metadata, and recorded effects while allowing the public Host migration to update generation-specific message envelopes. It maps journal confirmations, edit targets and recovery boundaries, then revalidates the output. Input files are never overwritten, including through hard links; existing destinations require explicit `--force`. A current-format source needs no output. A Host without the public catalog cannot perform Host format conversion.
124
142
 
125
- Already converted logs with stale PTC references cannot be repaired from their numeric values alone: use the original predecessor or backup. Preserve any newer activity separately. Logs containing retired `ptc-plus/recovery-boundary` events are refused by Host format conversion; the existing command without `--dsh-entry` remains the separate retired-event converter, whose output needs validation before a further upgrade. The migration tool does not modify a running persistence queue or silently repair unproved history.
143
+ Already converted logs with stale PTC references cannot be repaired from their numeric values alone: use the original predecessor or backup. Preserve any newer activity separately. Logs containing retired `ptc-plus/recovery-boundary` events are refused by Host format conversion; the existing command without `--dsh-entry` remains the separate retired-event converter. That converter accepts only Session format 0 with a contiguous zero-based source log and, before writing, validates PTC recovery plus every sequence relation in that frozen Host vocabulary, including surface replacements, command sources, title sources and compaction shadows. It also subtracts removed boundary events from a seeded session's exact inherited-prefix cut. A different source format, missing, removed, forward, duplicate, wrong-kind or semantically inconsistent relation leaves the source unchanged and produces no output. Run the retired-event conversion first, then use its validated output as the input to any Host format upgrade. The migration tool does not modify a running persistence queue or silently repair unproved history.