dsh-ptc-plus 0.3.1 → 0.4.1

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 (200) hide show
  1. package/README.en.md +66 -73
  2. package/README.md +66 -73
  3. package/assets/ptc-plus-bindings-en.png +0 -0
  4. package/assets/ptc-plus-bindings-zh.png +0 -0
  5. package/assets/ptc-plus-repair-en.png +0 -0
  6. package/assets/ptc-plus-repair-zh.png +0 -0
  7. package/assets/ptc-plus-repl-workspace-en.png +0 -0
  8. package/assets/ptc-plus-repl-workspace-zh.png +0 -0
  9. package/assets/ptc-plus-settings-en.png +0 -0
  10. package/assets/ptc-plus-settings-zh.png +0 -0
  11. package/client.js +30610 -722
  12. package/compiler-amaro.cjs +5 -0
  13. package/compiler-amaro.cjs.map +6 -0
  14. package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
  15. package/compiler-assets.json +3 -0
  16. package/compiler-core.cjs +554 -0
  17. package/compiler-core.cjs.map +6 -0
  18. package/compiler-platform.cjs +2 -0
  19. package/compiler-platform.cjs.map +6 -0
  20. package/compiler-typescript.cjs +388 -0
  21. package/compiler-typescript.cjs.map +6 -0
  22. package/docs/README.md +6 -0
  23. package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
  24. package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +6 -4
  25. package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +15 -3
  26. package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
  27. package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
  28. package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
  29. package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
  30. package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +9 -3
  31. package/docs/adr/0014-persist-cell-rewrite-policy.md +11 -5
  32. package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
  33. package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
  34. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
  35. package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
  36. package/docs/adr/0019-plugin-settings-and-kill-switch.md +8 -6
  37. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
  38. package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +17 -3
  39. package/docs/adr/0023-global-user-bindings.md +104 -0
  40. package/docs/adr/0024-repl-console-observation.md +33 -0
  41. package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
  42. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
  43. package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
  44. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
  45. package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
  46. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
  47. package/docs/architecture.md +82 -22
  48. package/docs/binding-review-placement-design.md +200 -0
  49. package/docs/capability-projection.md +1 -1
  50. package/docs/client-ui.md +96 -20
  51. package/docs/durability-design.md +61 -24
  52. package/docs/evaluation.md +78 -6
  53. package/docs/installation.md +41 -6
  54. package/docs/program-data-plane.md +6 -0
  55. package/docs/publishing.md +5 -3
  56. package/docs/runtime-reference.md +79 -25
  57. package/docs/semantic-validation.md +29 -0
  58. package/docs/stateful-binding-updates-proposal.md +755 -0
  59. package/docs/user-bindings.en.md +64 -0
  60. package/docs/user-bindings.md +64 -0
  61. package/docs/value-wire.md +3 -3
  62. package/docs/verification.md +57 -0
  63. package/index.js +374 -92
  64. package/internal/ast-traversal.js +5 -2
  65. package/internal/binding-descriptors.js +1 -0
  66. package/internal/binding-pattern-traversal.js +25 -0
  67. package/internal/binding-pattern.js +26 -29
  68. package/internal/binding-source-analysis.js +391 -0
  69. package/internal/binding-update-policy.js +66 -0
  70. package/internal/bounded-worker-round.js +56 -0
  71. package/internal/callable-definition-environment.js +42 -0
  72. package/internal/callable-source-catalog.js +129 -0
  73. package/internal/callable-source-encoding.js +47 -0
  74. package/internal/callable-source-facts.js +459 -0
  75. package/internal/callable-source-format.js +2 -0
  76. package/internal/callable-source-lowering.js +123 -0
  77. package/internal/cell-analysis-contract.js +25 -0
  78. package/internal/cell-analysis.js +252 -242
  79. package/internal/cell-completion.js +15 -0
  80. package/internal/cell-error.js +7 -0
  81. package/internal/cell-parser.js +66 -0
  82. package/internal/cell-rewriter.js +3 -553
  83. package/internal/commonjs-export-evidence.js +63 -0
  84. package/internal/commonjs-source-evidence.js +72 -0
  85. package/internal/compiler-amaro.cjs +2 -0
  86. package/internal/compiler-compression.js +12 -0
  87. package/internal/compiler-data.js +58 -0
  88. package/internal/compiler-descriptors.js +54 -0
  89. package/internal/compiler-dynamic-cache.js +48 -0
  90. package/internal/compiler-entry.js +35 -0
  91. package/internal/compiler-generated-names.js +17 -0
  92. package/internal/compiler-intrinsics.js +84 -0
  93. package/internal/compiler-module-links.js +34 -0
  94. package/internal/compiler-operations.js +61 -0
  95. package/internal/compiler-platform-factory.js +84 -0
  96. package/internal/compiler-platform.js +136 -0
  97. package/internal/compiler-record-roles.js +53 -0
  98. package/internal/compiler-region-output.js +259 -0
  99. package/internal/compiler-resource-lowering.js +103 -0
  100. package/internal/compiler-scope-facts.js +115 -0
  101. package/internal/compiler-service.js +109 -0
  102. package/internal/compiler-source-cache.js +32 -0
  103. package/internal/compiler-source-pieces.js +93 -0
  104. package/internal/compiler-source-regions.js +132 -0
  105. package/internal/compiler-storage-source.js +54 -0
  106. package/internal/compiler-text.js +15 -0
  107. package/internal/compiler-typescript.cjs +2 -0
  108. package/internal/config-spec.js +91 -25
  109. package/internal/cordis-tools-owner.js +130 -21
  110. package/internal/diagnostic.js +27 -1
  111. package/internal/direct-surface-owner.js +76 -23
  112. package/internal/dynamic-binding-evidence.js +16 -0
  113. package/internal/dynamic-environment-compiler.js +779 -0
  114. package/internal/dynamic-environment-integration.js +87 -0
  115. package/internal/dynamic-environment-runtime.js +362 -0
  116. package/internal/dynamic-native-calls.js +150 -0
  117. package/internal/dynamic-native-runtime.js +248 -0
  118. package/internal/dynamic-scope-analysis.js +90 -0
  119. package/internal/edit-transport-owner.js +28 -3
  120. package/internal/execution-seam-compat.js +193 -0
  121. package/internal/failure-reporting.js +118 -18
  122. package/internal/host-rpc.js +66 -0
  123. package/internal/isolated-worker.js +548 -0
  124. package/internal/kernel-child.js +139 -0
  125. package/internal/kernel-worker.js +911 -116
  126. package/internal/language-semantics.js +14 -0
  127. package/internal/legacy-binding-catalog.js +48 -0
  128. package/internal/legacy-cell-analysis.js +600 -0
  129. package/internal/legacy-cell-parser.js +50 -0
  130. package/internal/legacy-cell-rewriter.js +631 -0
  131. package/internal/legacy-repl-convenience.js +291 -0
  132. package/internal/managed-module-operations.js +170 -0
  133. package/internal/module-compilation.js +321 -0
  134. package/internal/module-runtime-platform.js +19 -0
  135. package/internal/module-transform-contract.js +12 -0
  136. package/internal/native-await-declarations.js +68 -0
  137. package/internal/native-root-compilation.js +54 -0
  138. package/internal/native-root-dynamic.js +67 -0
  139. package/internal/recovery-tips.js +27 -15
  140. package/internal/rejected-cell-editor.js +13 -8
  141. package/internal/repl-convenience.js +2 -201
  142. package/internal/repl-memory-projection.js +81 -12
  143. package/internal/repl-observation-interest.js +70 -0
  144. package/internal/repl-rewrite-contract.js +21 -0
  145. package/internal/repl-scope-normalizer.js +2091 -0
  146. package/internal/repl-value-observer.js +114 -0
  147. package/internal/rpc-contract.js +52 -0
  148. package/internal/runtime-bridge-owner.js +172 -28
  149. package/internal/runtime-config.js +48 -51
  150. package/internal/runtime-contexts.js +82 -10
  151. package/internal/runtime-messages.js +111 -0
  152. package/internal/session-cell-executor.js +455 -91
  153. package/internal/session-journal-recovery.js +684 -0
  154. package/internal/session-journal-schema.js +106 -0
  155. package/internal/session-journal.js +237 -440
  156. package/internal/session-log-view.js +42 -9
  157. package/internal/session-runtime.js +325 -80
  158. package/internal/session-state.js +249 -40
  159. package/internal/source-position-map.js +211 -71
  160. package/internal/stateful-module-compiler.js +154 -0
  161. package/internal/stateful-module-runtime.js +303 -0
  162. package/internal/stateful-root-compiler.js +598 -0
  163. package/internal/stateful-root-runtime.js +340 -0
  164. package/internal/typert-codec-compat.js +28 -0
  165. package/internal/typescript-transform.js +29 -0
  166. package/internal/user-binding-authoring.js +70 -0
  167. package/internal/user-binding-console-worker.js +184 -0
  168. package/internal/user-binding-console.js +148 -0
  169. package/internal/user-binding-draft-projection.js +335 -0
  170. package/internal/user-binding-model-context.js +31 -0
  171. package/internal/user-binding-runner.js +56 -0
  172. package/internal/user-bindings-owner.js +1065 -0
  173. package/internal/user-bindings-store.js +293 -0
  174. package/internal/user-bindings.js +353 -0
  175. package/internal/value-wire-schema.js +28 -0
  176. package/internal/value-wire.js +29 -20
  177. package/internal/worker-client.js +57 -67
  178. package/internal/worker-environment.js +45 -0
  179. package/internal/worker-output-relay.js +29 -0
  180. package/internal/worker-shutdown.js +14 -0
  181. package/package.json +81 -11
  182. package/src/client-activity.js +109 -45
  183. package/src/client-authoring-view.js +580 -0
  184. package/src/client-binding-review.js +230 -0
  185. package/src/client-bindings-data.js +29 -0
  186. package/src/client-catalog.js +127 -0
  187. package/src/client-code-editor.js +84 -0
  188. package/src/client-console.js +112 -0
  189. package/src/client-copy.js +370 -0
  190. package/src/client-feature-gates.js +62 -0
  191. package/src/client-host-compat.js +150 -0
  192. package/src/client-indicator-view.js +267 -0
  193. package/src/client-repl-view.js +292 -0
  194. package/src/client-rpc.js +20 -0
  195. package/src/client-settings-view.js +221 -0
  196. package/src/client-styles.js +106 -0
  197. package/src/client-tool-view.js +108 -0
  198. package/src/client-transport.js +159 -0
  199. package/src/client-workbench.js +521 -0
  200. package/src/client.js +233 -615
@@ -2,19 +2,22 @@
2
2
 
3
3
  ## 状态
4
4
 
5
- 本文描述 `dsh-ptc-plus` 的 journal、两阶段确认和冷恢复行为。代码事实源是 `internal/session-journal.js` 与 `internal/session-runtime.js`。
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
7
  ## 恢复承诺
8
8
 
9
9
  PTC Plus 的正确承诺是:
10
10
 
11
- > **精确恢复 durable 部分,完整运行 volatile 部分,不自动重放 volatile 副作用。**
11
+ > **只把可证明状态称为已恢复;历史最差可收缩到空 REPL,但当前合法 cell 仍可继续。**
12
12
 
13
13
  - durable cell 的源码、tool transcript、结算顺序和 completion 足以精确重放;
14
14
  - volatile cell 可使用 policy 允许但无法 journal 的 Node 能力,只保证当前 worker 生命周期内延续;
15
15
  - 一旦进入 volatile,整个 live 后缀保持 volatile;
16
16
  - restore 命名的 durable 状态可以显式丢弃 volatile 后缀;
17
- - abort、timeout、worker exit、OOM 和进程恢复都回到最后一个 durable frontier;
17
+ - abort、timeout、worker exit、OOM、进程恢复和损坏的历史 PTC metadata 都收缩到最大可证明 frontier;没有非空 frontier 时从空 REPL 执行当前 cell;
18
+ - 历史恢复拒绝不可信状态证据,不因这项插件自有历史损坏而永久拒绝后续 `run_code`;当前请求自身的 DSH validation、policy、authority、approval 和 cancellation 仍可拒绝执行;
19
+ - 收缩不重新 dispatch、撤销或验证历史 effect;丢失的 binding 由一次 `PTC-R002` 明确提示模型按需重建;
20
+ - 可重建不是默认暴露 binding 的充分条件:恢复 frontier 还必须让 binding 的精确 provenance 保留在生成当前调用的模型可见 surface 中,或由显式选择的有界、模型可见结构化投影公开;不能只为延长隐藏状态而默认注入该投影,raw log 与 UI-only inventory 也不满足这项条件;
18
21
  - `durableReplay: false` 时,新 kernel 从空状态开始且所有已执行 live cell 都是 volatile,作为
19
22
  用户怀疑恢复正确性时的显式逃生模式;
20
23
  - 被跳过的源码仍保存在原始 `tool/call` 中。
@@ -23,17 +26,31 @@ PTC Plus 的正确承诺是:
23
26
 
24
27
  ## Journal
25
28
 
26
- 每个进入 CodeRuntime 的 cell 创建 mutable tentative journal:
29
+ 每个进入执行缝的 cell 创建 mutable tentative journal:
27
30
 
28
31
  ```ts
29
32
  {
30
- version: 3,
31
- bindingMode: "loose" | "strict",
33
+ version: 9,
34
+ languageSemantics: "legacy-v1" | "stateful-v1" | "protected-v1",
35
+ bindingPolicy: {
36
+ variableRedeclarations: boolean,
37
+ functionClassRedeclarations: boolean
38
+ },
32
39
  rewritePolicy: {
33
40
  autoRewriteImports: boolean,
34
41
  autoStripExports: boolean,
35
42
  autoSplitRedeclarations: boolean
36
43
  },
44
+ moduleSemantics: {
45
+ defaultExportBinding: "legacy-variable" | "live-readonly",
46
+ importExpressionBoundary: "legacy" | "statement-safe"
47
+ },
48
+ userBindingsFingerprint: string | null,
49
+ userBindingsReusePolicy: "fingerprint-v1" | "implementation-v1",
50
+ userBindingsShadowPolicy: "whole-entry" | "per-name",
51
+ userBindingNames:
52
+ | { name: string, state: "provider" | "local" | "absent" | "unknown", entryId?: string }[]
53
+ | null,
37
54
  status: "durable" | "volatile" | "discarded" | "noop",
38
55
  calls: CapabilityCall[],
39
56
  operations: StateOperation[],
@@ -50,8 +67,14 @@ PTC Plus 的正确承诺是:
50
67
  字段含义:
51
68
 
52
69
  - `durable`:创建可重放 node,推进 `durableHead`;
53
- - `bindingMode`:记录该 cell 实际采用的顶层 binding 语义;冷重放读取每个 node 的记录值,不读取恢复时的 profile 配置;
70
+ - `languageSemantics`:固定完整语言代际;新统一策略选择 `stateful-v1` 或 `protected-v1`,显式旧设置兼容态与 v1–v8 历史使用 `legacy-v1`。冷重放从该字段选择编译路径,不用当前配置替换历史声明、闭包和初始化语义;
71
+ - `bindingPolicy`:记录该 cell 实际采用的变量重声明和 function/class 重声明语义;冷重放读取每个 node 的完整记录值,并用它重建 binding 可写性,不读取恢复时的 profile 配置;
54
72
  - `rewritePolicy`:记录该 cell 解析和 lowering 时使用的三个 AST rewrite 开关;冷重放读取每个 node 的记录值,不读取恢复时的 profile 配置;
73
+ - `moduleSemantics`:保留旧模块 lowering 的独立代际;`legacy-v1` 按记录值恢复 default binding 与模块引用写入的语句边界。当前 live cell 写入 `live-readonly` 与 `statement-safe`,但新语言的可写 alias、default 关联和提交规则由 `languageSemantics` 决定,不能仅凭历史字段中的 `readonly` 推断当前 binding 不可写;
74
+ - `userBindingsFingerprint`:`null` 明确表示该 cell 没有 Global User Binding 快照;SHA-256 值要求最终 result 同时携带 fingerprint 一致的私有快照,缺失或不一致时形成 unknown boundary;
75
+ - `userBindingsReusePolicy`:记录全局绑定模块的复用代际;新 cell 写入 `implementation-v1`,按执行输入复用模块,历史 `fingerprint-v1` 则按完整条目指纹复用,保留仅修改说明或顶层显示名称时发生的初始化;
76
+ - `userBindingsShadowPolicy`:记录该 cell 的 session-local 覆盖粒度;新 cell 写入 `per-name`,只有同名 session-local binding 覆盖对应全局名称,同条目的其他名称继续激活;v1-v7 迁移的历史 node 写入 `whole-entry`,保留整条来源条目退出后续全局激活的语义;该粒度与 `userBindingsReusePolicy` 相互独立;
77
+ - `userBindingNames`:`per-name` 且 status 非 `noop`/`discarded` 时记录该 cell 结算时按名称排序的事实,state 为 `provider`、`local`、`absent` 或 `unknown`,provider 事实另带 `entryId`,必须对应并行快照的条目并覆盖快照公开的每个名称;`whole-entry`、`noop` 与 `discarded` node 为显式 `null`;
55
78
  - `volatile`:只推进 live heap,不推进 `durableHead`;
56
79
  - `discarded`:基础设施失败,calls 和 operations 必须为空;若中止时仍有未结算的 program binding call,则以首个 `global.member` 保留 `volatileReason`,恢复时不能把这个 possible-effect boundary 折叠为 no-op;
57
80
  - `noop`:程序未执行,calls 和 operations 必须为空;
@@ -69,7 +92,7 @@ SessionRuntime 创建 kernel 时完全忽略历史 nodes、head、checkpoints
69
92
 
70
93
  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-与恢复)。
71
94
 
72
- 当前实现写入 `version: 3` schema。`version: 2` 且 `confirms` 为空的 journal 可无歧义规范化为 v3;v2 中非空的 call-id confirmation 无法可靠映射到可能重复的 session event,必须形成 unknown suffix,不能猜测迁移。包括 `bindingMode`、`rewritePolicy`、`diagnostics` 在内的必需字段缺失时 journal 必须失效,否则会削弱最终持久值与 tentative journal 的严格一致性确认。profile 后续切换宽松/严格模式或 AST rewrite 开关只影响新 cell,历史 node 始终按自身记录的模式重放。
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 不能证明模块内部状态相等。
73
96
 
74
97
  ## Capability Call Transcript
75
98
 
@@ -104,7 +127,7 @@ pre-execute -> tools/execute -> post-execute
104
127
  插件采用:
105
128
 
106
129
  1. `tools/execute` 保存 execution 对象与 session context;
107
- 2. `CodeRuntime.run` 真正进入 kernel 时创建 tentative journal;
130
+ 2. 执行缝的 `run` 真正进入 kernel 时创建 tentative journal;
108
131
  3. 成功结果由 `presentationMeta` 投影 journal,失败结果由 around hook 附加;
109
132
  4. `tools/result` 规范化最终 `meta.dshPtcPlus` 与 runtime tentative journal;
110
133
  5. 两者语义完全相同时确认 tentative 状态;
@@ -117,9 +140,9 @@ pre-execute -> tools/execute -> post-execute
117
140
  | 观察 | Live 行为 | 冷恢复行为 |
118
141
  | --- | --- | --- |
119
142
  | valid journal | 按 status 提交 | 按 journal 折叠 |
120
- | 已执行,最终 journal 被删除 | cell 与后缀 volatile | unknown boundary |
143
+ | 已执行,最终 journal 被删除 | cell 与后缀 volatile | 收缩到此前可证明 frontier,继续当前 cell |
121
144
  | 未进入 runtime | pending no-op | 后续 `confirms` 存在时忽略 |
122
- | 无法判断且未被确认 | 保守处理 | 回到此前 durable frontier |
145
+ | 无法判断且未被确认 | 保守处理 | 拒绝其状态证据;必要时空 REPL,继续当前 cell |
123
146
 
124
147
  比较先严格规范化 journal,再使用 PTC value graph 的扁平 wire 表示,不对深层参数做递归遍历。额外无关 metadata 不影响确认,但 `dshPtcPlus` 自身任何可观察差异都拒绝确认。
125
148
 
@@ -133,20 +156,32 @@ pre-execute -> tools/execute -> post-execute
133
156
 
134
157
  ## 日志折叠
135
158
 
136
- 恢复按 session event 顺序处理外层 `run_code` 和带明确 derived-run metadata 的 `edit_run_code`。恢复入口先把当前 call id 解析为持久化 `tool/call.seq`,再把该序号作为 live boundary 传入折叠器;对应的在途 call event 不属于历史。每个 `edit_run_code` 在其 call event 处,根据此前已经结算的调用确定并固定可编辑目标;之后出现的 result 只影响随后发起的 edit:
159
+ 恢复以当前请求需要的 head 为目标,沿可证明 parent 关系向更早 frontier 收缩;实现可以前向折叠 event 建图,但不得把 unknown boundary 两侧的日志位置当作状态依赖证据。恢复入口先把当前 call id 解析为持久化 `tool/call.seq`,再把该序号作为 live boundary 传入折叠器;对应的在途 call event 不属于历史。每个 `edit_run_code` 在其 call event 处,根据此前已经结算的调用确定并固定可编辑目标;之后出现的 result 只影响随后发起的 edit:
137
160
 
138
161
  1. 用 `sourceEventSeqs[0]` 关联 `tool/result` 与 `tool/call`;
139
162
  2. 预收集 valid journal 中的 `confirms`;
140
163
  3. 排除与 live boundary 序号相同的在途 call,并让已确认 no-op 的无 journal call 不改变状态;
141
- 4. 缺失源码、缺失/损坏 journal 进入 untrusted suffix;
164
+ 4. 缺失源码、缺失/损坏 journal 或无法验证的 call/result/prune 关联建立 untrusted boundary,不作为旧 binding 的证据;
142
165
  5. `noop` 与不含 `volatileReason` 的 `discarded` 不改变语言状态;带 `volatileReason` 的 `discarded` 表示 heap 已回滚但外部 effect 未知,进入 untrusted suffix;
143
166
  6. `volatile` 进入 untrusted suffix,只应用可独立持久的 delete/restore 操作;
144
167
  7. `restore` 命名状态重新建立 trusted durable head;
145
- 8. untrusted suffix 后的首个 `durable` journal从当前 durable head 建立新分支,并清除旧 suffix;
168
+ 8. 只有 ancestry 或独立性有插件自有机械证据的 post-boundary durable 记录才可保留;否则整个受影响 cell 与依赖后缀收缩;
146
169
  9. durable node 保存 parent link,命名状态保存 node index;
147
- 10. `meta.dshPtcPlusRecoveryBoundaries` 在 `tool/result` event sequence 参与排序前完成规范化;任一损坏 boundary 使恢复失败,合法 boundary 再通过失败 call seq 选择 node,并要求记录的 frontier 恰好是该 node 的 parent;折叠器剪除该 node 及依赖后代,按剩余记录重算 checkpoints,再把 head 设为记录的 frontier。
170
+ 10. `meta.dshPtcPlusRecoveryBoundaries` 在 `tool/result` event sequence 参与排序前完成规范化;损坏 boundary 被拒绝为状态证据并建立保守收缩点,合法 boundary 通过失败 call seq 选择 node,并要求记录的 frontier 恰好是该 node 的 parent;
171
+ 11. 折叠器剪除不可证明的 node、binding 与依赖后代,按剩余记录重算 checkpoints;runtime 重置 worker 并验证候选 frontier,逐级收缩到最大可重放 frontier,必要时到空 REPL;
172
+ 12. 当前 cell 只在 worker 实际拥有该 frontier 后执行,成为它的新 child 或空 REPL 的新 root;当前结果持久记录本次收缩并投影一次恢复诊断。
173
+
174
+ 当前 journal 没有完整的逐 binding 读写与传递依赖图。源码存在、重放未抛错或 completion 相同,都不足以证明闭包捕获、属性 mutation、动态名称访问或运行时值与原执行一致。因此恢复不能任意挑选 unknown boundary 后看似独立的 binding;缺少机械证明时以 cell 为原子并丢弃受影响后缀。将来若要保留更细粒度状态,必须通过版本化、owner-owned 的依赖证据扩展契约,不能从名称或成功重放猜测。
175
+
176
+ 第 12 步是可用性与真实性共同的不变量:旧 unknown 调用不能被伪装成已恢复 heap,也不能在每次重启时永久吞掉所有后续 `run_code`。当前 cell 是在已经实际物化的 frontier 上重新执行,所以它可以安全建立持久新分支;这不表示被剪除 cell 的外部 effect 没有发生。
148
177
 
149
- 第 8 步是必要不变量:冷恢复已经实际丢弃 volatile/unknown heap,因此此后执行成功的 durable cell 不依赖该 heap。如果不把它作为可信重基点,旧 unknown 调用会在每次重启时永久吞掉所有后续状态。
178
+ ## 模型可知状态
179
+
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 放入模型上下文。
181
+
182
+ 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
+
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。
150
185
 
151
186
  ## Completion 校验
152
187
 
@@ -164,7 +199,7 @@ pre-execute -> tools/execute -> post-execute
164
199
  - recovery divergence;
165
200
  - durable replay 触发 volatile capability。
166
201
 
167
- 基础设施失败会终止当前 worker,并把 log-only recovery boundary 放入当前已结算 `tool/result` 的私有 metadata。kernel 从失败 node 的 parent 重新重放;若该 frontier 仍失败则继续向 parent 收缩,直到某个 frontier 验证成功或到达空 REPL。触发恢复的当前 `run_code` 在验证成功前不执行,因此可以在同一次请求中安全继续;如果 boundary 无效或历史本身无法折叠,则返回 recovery error。结构损坏的日志没有可证明的 frontier,后续调用会重新读取日志而不会接受一个无法持久表达 ancestry 的新分支。已经写入旧版自定义 boundary event 的日志必须先通过显式迁移移除该事件并把 boundary 合并到后续 `tool/result` metadata,迁移失败时不得覆盖原始日志。
202
+ 基础设施失败会终止当前 worker,并把 log-only recovery boundary 放入当前已结算 `tool/result` 的私有 metadata。kernel 从失败 node 的 parent 重新重放;若该 frontier 仍失败则继续向 parent 收缩,直到最大可验证 frontier 或空 REPL。触发恢复的当前 `run_code` 在候选 frontier 验证成功前不执行,验证后在同一次请求中继续。boundary 无效或历史本身无法完整折叠时,相关记录和可能依赖它的状态不得进入 frontier;这类历史 PTC metadata 损坏本身不返回永久 recovery error,而是继续收缩,最差用空 worker 执行当前 cell,并在其最终 result 持久表达新 ancestry。已经写入旧版自定义 boundary event 的日志必须先通过显式、非破坏迁移转换为 DSH 可加载的 metadata;迁移失败时不得覆盖原始日志。
168
203
 
169
204
  ## State Operations
170
205
 
@@ -206,7 +241,7 @@ worker 不继承 Electron 的工作目录语义。插件通过现有 `tools/exec
206
241
 
207
242
  ## 恢复通知
208
243
 
209
- 构造 kernel 时若折叠结果含 volatile/unknown suffix,或本次重放产生 recovery boundary,第一次实际执行的 `run_code` 记录并投影 `PTC-R002`。它只统计当前 call 之前实际跳过的历史 cell:
244
+ 构造 kernel 时若折叠结果含 volatile/unknown boundary、模型可见 surface 收缩,或本次重放产生 recovery contraction,第一次实际执行的 `run_code` 记录并投影 `PTC-R002`。它只统计当前 call 之前实际未恢复的历史 cell,并明确旧 binding 可能需要重新声明:
210
245
 
211
246
  ```text
212
247
  warning[PTC-R002]: restored the durable head and skipped N unreconstructable historical cells
@@ -215,7 +250,7 @@ state: ...
215
250
  help: ...
216
251
  ```
217
252
 
218
- 通知进入正常 CodeRuntime logs,结构化值进入当前 journal,因此成功结果和错误结果都能呈现并从 session log 重建。每个 kernel 只发送一次,避免污染后续上下文。
253
+ 通知进入正常执行缝 logs,结构化值进入当前 journal,因此成功结果和错误结果都能呈现并从 session log 重建。收缩边界随当前 result 持久化,后续 cold start 从新分支恢复,不重复撞击同一损坏历史;每个 kernel 只发送一次,避免污染后续上下文。
219
254
 
220
255
  live kernel 首次进入 volatile 只更新 journal 的 `status` / `volatileReason` 和 `repl.state(list)`,不向模型投影 warning/note。该转换不要求当前任务采取行动;只有 cold recovery 已实际跳过 volatile、unknown 或 replay-abandoned 历史时才发送 `PTC-R002`。worker 在首次观察到直接 Node/OS 边界时立即通知主线程,因此后续 hard abort、timeout 或 worker exit 仍能把原因写入 discarded journal。
221
256
 
@@ -229,6 +264,8 @@ live kernel 首次进入 volatile 只更新 journal 的 `status` / `volatileReas
229
264
  - 冷恢复丢弃不可信后缀使用 `rolled-back`;
230
265
  - 只有已知外部 dispatch 发生但 completion 无法确定时才使用 `unknown` 并附 `dispatchState: "unknown"`,插件不得在宿主未提供该事实时猜测。
231
266
 
267
+ `PTC-N001` collision 诊断另带 `collisions`:每条记录为 `{name, kind, reason, start, end}`。`reason` 由判定冲突的编译器 owner 记录(`reserved-program-binding-not-shadowable`、`protected-root-redeclaration`、`import-binding-redeclaration`、`redeclaration-splitting-disabled`,以及既有的重声明策略值),渲染只消费已记录的原因,不从请求描述符重新推导保留名或保护策略。
268
+
232
269
  模型可见文本与 `diagnostics` 必须由同一个结构确定性生成。恢复不通过解析既有 message 重建诊断;session export/import 和 replay 均保留结构化 code、cause、dispatch state 与 state effect。源码 frame 使用 `@babel/code-frame` 的无色投影。
233
270
 
234
271
  ## 插件边界
@@ -237,14 +274,14 @@ live kernel 首次进入 volatile 只更新 journal 的 `status` / `volatileReas
237
274
 
238
275
  - `tools/execute`;
239
276
  - `tools/result`;
240
- - `CodeRuntime.run`;
241
- - 当前 `CodeRuntime.run` request 的 public bindings 与 signal;
277
+ - 执行缝的 `run`;
278
+ - 当前执行缝 request 的 public bindings 与 signal;
242
279
  - `run_code.output.presentationMeta`;
243
280
  - 标准 `tool/call` 与 `tool/result.meta`。
244
281
 
245
282
  以上是当前已实现的 PTC journal 协议。native `tools.*` 保持 owner contract;cell program binding 不得变成新的模型 transport。
246
283
 
247
- 任何公共扩展面无法持久确认的状态都必须收缩为 volatile/unknown 边界。修改或 fork DSH、patch 私有
284
+ 任何公共扩展面无法持久确认的状态都必须收缩为 volatile/unknown 边界,但边界否定的是旧状态证明,不是当前合法调用的可用性;最大可证明 frontier 为空时,插件仍应让当前 cell 从空 REPL 建立新分支。修改或 fork DSH、patch 私有
248
285
  scheduler、复制 policy/event protocol 或伪造事件不属于本协议。若上游以后提供 owner-declared
249
286
  typed binding,它可以使用 DSH nested dispatch,但不得伪装成 journal confirmation,也不得绕过
250
287
  scope、policy 或 settlement。
@@ -256,10 +293,10 @@ scope、policy 或 settlement。
256
293
  - volatile live continuation、冷恢复跳过和 durable 重基;
257
294
  - post-execute metadata 删除与 pre-dispatch no-op 确认;
258
295
  - hard abort、冷 worker 启动取消和未结算 program binding 的 possible-effect boundary;
259
- - replay timeout fail closed;
296
+ - replay timeout 逐级收缩到可验证 frontier;
260
297
  - Math intrinsic、局部 ambient 名称、CWD 相关 `node:path`;
261
298
  - 命名状态 save/restore/delete 与 volatile restore;
262
299
  - 深层 graph value、own `__proto__` key、`undefined`、special number、BigInt、hole、alias 与 cycle;
263
- - 宽松变量重声明与严格/混合名称 collision preflight;
300
+ - 独立的变量与 function/class 重声明 policy、不可写目标 preflight、声明位置替换及 cold replay;
264
301
  - runtime throw、invalid output 和真实 recovery 的结构化诊断与模型可见投影;普通 volatile transition 保持安静;
265
302
  - 未修改 DSH 的真实公共扩展面,并在全新 session runtime 中从日志恢复。
@@ -4,7 +4,26 @@
4
4
 
5
5
  The model-backed runners support native Windows paths and WSL repositories mounted as `/mnt/<drive>/...`. They invoke the Windows DSH installation through `pwsh.exe`; the Windows process environment must resolve `dsh --version` and a drive-qualified `DSH_HOME` or user-profile `.dsh` directory. Native Linux and macOS DSH execution are not supported by these runners.
6
6
 
7
- Both entrypoints validate path conversion, PowerShell startup, the installed DSH command, and the Windows DSH home before creating artifacts, scratch directories, or installing the development plugin. A failure uses the `PTC-EVAL-PREREQ` diagnostic and leaves the evaluation workspace unchanged.
7
+ Both entrypoints validate path conversion, PowerShell startup, the installed DSH command, and the Windows DSH home before creating evaluation artifacts or installing the development plugin. A public Node preload runs a keyless real-worker probe before the DSH version command: it checks persistent bindings, syntax rejection, synchronous and awaited exceptions, and explicit return. The probe owns and cleans its worker scratch directory. A failure uses `PTC-EVAL-PREREQ` and prevents model work.
8
+
9
+ The actual `process.version`, `process.execPath`, DSH JavaScript entry, and observed release are recorded in manifests; subsequent DSH invocations use that exact Node executable and entry. Do not launch a probe through `npm exec node`, which can resolve a different runtime. The release is evidence, not a behavior selector or compatibility gate. Keep the selected installation and repository DSH dependencies current.
10
+
11
+ ## Configuration Preflight
12
+
13
+ Model-backed evaluation requires explicit authorization and an explicit provider, model, and credential-variable name. Run it in an isolated DSH home and workspace. Resolve the selected provider from the user's existing DSH configuration, then copy only its validated API, endpoint, model list, and provider-specific routing fields into the isolated settings. Keep the credential variable name unchanged and let the child process resolve its value from the inherited environment; never read, print, serialize, or store credential values.
14
+
15
+ Generate a fresh routing/session header for providers that require one, and use the same resolved provider configuration for every comparison arm. If the normal profile lacks a required provider field, repair the isolated copy or use the repository's existing isolated audit driver. Do not weaken the provider check or edit the normal profile.
16
+
17
+ After configuring the selected runner's route, set its configuration-only variable to `1` before invoking the command:
18
+
19
+ | Command | Configuration-only variable |
20
+ | --- | --- |
21
+ | `npm run test:expensive` | `DSH_PTC_ACCEPTANCE_CONFIG_ONLY` |
22
+ | `npm run test:ab` | `DSH_PTC_AB_CONFIG_ONLY` |
23
+
24
+ Each runner reads its own configuration-only variable; the names are not interchangeable. When that variable is set to `1`, the runner returns after its isolated configuration checks. Preflight may create local artifacts and isolated configuration; it does not invoke the model. A successful preflight establishes configuration readiness, not model behavior or semantic correctness. Remove the configuration-only setting only when proceeding to the explicitly authorized paid run.
25
+
26
+ Inspect only redacted session-log and report artifacts, and record model usage without request headers or credential material. Both commands invoke the configured model and consume quota when run without their configuration-only setting.
8
27
 
9
28
  ## Stable ordinary-task A/B fixture
10
29
 
@@ -27,7 +46,7 @@ The paired run uses the latest installed DSH release, a configured model, PTC mo
27
46
 
28
47
  Resolved configurations are identical except for `ptc-plus.disabled`. Agent instructions, skills, auxiliary title generation, and local identity extensions are disabled. The model route, permission mode, neutral persona, injected initial context, fixture bytes, and resolved tool surface stay paired within each run.
29
48
 
30
- The generated overlay explicitly owns and the preflight validates `tools.mode`, `sandbox-policy.mode`, and `approval.policy`. The runners do not rely on child-process environment variables to project these policies across the WSL-to-Windows execution boundary.
49
+ The shared overlay selects `tools.mode: ptc` and explicitly projects `sandbox-policy.mode` and `approval.policy`. Before any model work, both runners validate the resolved tools row with the public `ToolRuntime.Config` schema from `@deepseek-ai/dsh-tools`, then check the selected evaluation policy. A successful config dump alone does not validate plugin settings; agreement with a runner-supplied expected string cannot bypass the Host schema. `CONFIG_ONLY` also performs this zero-model schema check. The runners do not rely on child-process environment variables to project these policies across the WSL-to-Windows execution boundary.
31
50
 
32
51
  Each arm executes in an independently named, opaque scratch tree outside the evaluator artifact tree. Treatment names are confined to evaluator-owned records. Blind packets replace the session workspace in descriptions, source, results, and final answers, including Windows, forward-slash, and JSON-escaped spellings, before the arm map is written.
33
52
 
@@ -39,24 +58,77 @@ Acceptance metrics follow durable session-log semantics. `modelRequests` counts
39
58
 
40
59
  Stable-header acceptance canonicalizes empty fields by DSH rules and compares the exact system value and ordered complete tool-schema JSON across every header epoch. Any unapproved change fails with the first differing field. `headerPolicy.allowedTransitions` names the exact epoch and route, configuration, or capability condition; `headerPolicy.historyReplacements` declares an exact replacement count and never permits header drift. Hashes remain diagnostic report data rather than the correctness test.
41
60
 
61
+ The shared Host contract recognizes `series` as an unchanged request header beginning a distinct message series, not a new schema or an inferred provider call. Usage evidence supports both historical standalone `assistant/chunk` events and compact streams in `assistant/message` or `assistant/attempt`. An embedded stream's last usage agrees with its message's accounting; formally linked duplicate storage is counted once, conflicting evidence fails, and reported usage from attempts without a surface message remains part of quota consumption. Logical steps, header epochs and physical attempts remain distinct. Missing usage is not a zero-cost claim.
62
+
63
+ Runtime-context audits track the binding catalog independently of recovery snapshots. They detect unchanged binding text repeated inside an otherwise changed snapshot, while allowing one reassertion after a formal surface replacement removed its evidence. Model-authored ambient declarations are not plugin catalog injections.
64
+
65
+ ### Focused Program Work
66
+
67
+ The typed program-surface descriptor owns `expect.programWork`: `inspectionSymbols` limits schema expansion, and each `callLimits` entry declares a namespace/member's `maxCalls` and optional `maxCallsPerArguments`. Counts include unsuccessful calls. The fixed fixture is immutable during this task, so its native read is limited to one observation; the parent passes the observed marker into the isolated child as source data. Tree retrieval is limited to one, and find/inspect counts are bounded without requiring one exact source or cell sequence.
68
+
69
+ The shared trajectory collector validates the journal and decodes nested arguments as `args` for in-memory use. JSON reports preserve `argsWire`, a canonical PTC Value Graph that retains undefined, omitted object properties, explicit null, bigint, and cycles. Auditing decodes this evidence and uses structured equality, independent of source spelling or object-key order; missing or corrupt evidence fails. `programWork.observations` reports call counts and `repeatedArgumentCalls` separately from `machineMetrics.repeatedSourceCalls`. A workload needing fresh observations must explicitly allow its counts; these limits never suppress runtime calls or establish effect idempotence.
70
+
71
+ ### Guarded Edit Acceptance
72
+
73
+ Every edit is validated by the canonical editor against the target reconstructed at dispatch from the session log. Both literal and regex deltas accept an optional valid `expected_target_call_seq`; successful edits must preserve the captured target and the editor's exact derived source and description. Scenario-specific literal deltas and source privacy remain separately checked by `editTransports`.
74
+
75
+ `expect.guardMismatchEdits` lists the one-based edit ordinals intentionally targeting a different call. Such an edit passes only with the structured `{ edited: false, reason }` result and no journal or derived execution metadata. Other edits still require their execution journal. Deterministic tests execute diagnostic-generated EOF closures and reject stale guards through the existing Host tool pipeline; the default paid cohort stays at five workflows.
76
+
77
+ ## Recorded paired observation
78
+
79
+ One identity-blinded paired experiment used `opencode-go/deepseek-v4-flash`, the same versioned fixture, task prompts and permissions in both arms, and two repetitions of each of nine tasks: 18 sessions per arm.
80
+
81
+ | Nine tasks, two repetitions | PTC Plus | DSH PTC mode without PTC Plus | Observed difference |
82
+ | --- | ---: | ---: | ---: |
83
+ | Model requests | 66 | 88 | 25.0% fewer |
84
+ | Tool calls | 50 | 79 | 36.7% fewer |
85
+ | Token traffic | 729,642 | 942,901 | 22.6% lower |
86
+ | Identity-blinded rubric score | 138 / 162 | 118 / 162 | 12.3 percentage points higher |
87
+
88
+ In the module-syntax task, PTC Plus completed each repetition in one `run_code`. The other arm failed the static-import requirement in both repetitions, using eight tool calls in total. This stochastic observation is not a performance guarantee. Two PTC Plus sessions and five sessions in the other arm exceeded preset machine budgets, so the overall matrix did not pass machine acceptance. Token traffic includes input, cache-read, cache-write and output tokens. These measurements describe that experiment, not acceptance of subsequent plugin changes.
89
+
42
90
  ## Reporting
43
91
 
44
- Both runners require an explicit model route and credential-variable name before any host probing or artifact creation. The referenced credential variable must also contain a value:
92
+ ### Binding Workflow
93
+
94
+ `scripts/binding-workflow-scenario.json` owns the constant-helper authoring, user save, and availability scenario. `scripts/binding-files-workflow-scenario.json` separately covers a file helper with write/delete capabilities and a pre-existing directory and sentinel. `test/binding-workflow.test.js` runs both through public CommandRuntime, AgentLoop, ToolRuntime, Session, and prompt assembly with a deterministic adapter. It checks saving, availability observation, preservation of pre-existing content, and rejection of write/delete probes. The constant workflow also checks ordinary history, stable system/tools, and restart. These fixtures prove the Host and audit contracts, not stochastic model behavior or provider cache gains.
95
+
96
+ The deterministic authoring test additionally keeps one command turn active across several real REPL cells: an in-memory comparison exposes a wrong result, corrected source passes assertions, and that exact source is submitted as a disabled draft without a store write. It checks the generated task's test scope and final-source review guidance alongside stable system text and tool schemas. This proves the execution path is available, not that an unconstrained model chooses it.
97
+
98
+ For model-backed authoring evaluation, include both new and edit requests, normal and edge inputs, and a helper whose external integration must remain untested. Inspect submitted source, tool calls and results for tests before acceptance, correct use of feedback, unnecessary discovery, external effects and unsupported completion claims. Compare first-call latency, total time, request count and token usage under the same explicit route; a shorter reasoning block or more calls alone is not a quality criterion. Use concise result evidence when reviewing final answers, not reasoning transcripts as correctness proof.
99
+
100
+ The packed Client can also be checked in a real isolated DSH Web profile without model requests:
101
+
102
+ ```sh
103
+ npm run test:client:web -- --dsh-entry <installed-dsh-cli-js> --binding-workflow
104
+ ```
105
+
106
+ Use `--browser-channel <channel>` when testing with an installed Chromium browser. The local adapter drives public command and tool execution; Playwright saves and discards drafts through the UI, checks English and Chinese lifecycle labels, refreshes saved source, and measures settled desktop and narrow layouts including dark mode. Screenshots and measurements are written to `artifacts/client-web-smoke`; the temporary Host and home are cleaned up. `npm run test:client:layout` separately checks focused card, list, and REPL-tab geometry.
107
+
108
+ For an explicitly authorized model check, use an isolated DSH home and workspace with the selected provider, model, and credential-variable configuration. Run the keyless worker probe with the same resolved Node executable before starting DSH. First send an ordinary message, then run the scenario command, review the generated source, choose Save and enable in the binding review dock above the composer, and send its status question. Export that session log for `auditBindingWorkflow(events, scenario)` in `scripts/acceptance-contract.mjs`; `inspectLog` accepts the same descriptor as `expect.bindingWorkflow`. This interactive workflow remains separate from the five default paid scenarios because the headless single-task runner cannot perform the user save action.
109
+
110
+ The audit owns completeness: matching command and successful admission, accepted candidate and its successful SDK transcript, a formally linked save before the exact status question, settled calls, and a completed answer must all exist. Results distinguish `incomplete`, `unproved`, and `machine-passed`; all nonpassing results include failures. Final prose always retains `semantic-review-required` and must be checked against actual model-visible facts.
111
+
112
+ The oracle rejects routine host/storage scanning and checkpoint reflection. `constantExports` optionally proves only nullary synchronous exports returning declared primitive literals, from the exact accepted source, save relation, and the status cell's validated active snapshot and journal fingerprint. A bounded AST proof tracks local values and only marks catch unreachable after proving its try body cannot throw. Unsupported syntax, object coercion, source mismatch, and shadowing remain insufficient evidence; a name allowlist cannot authorize calls. Export metadata alone does not prove a runtime value's type. Reports distinguish `recorded-dispatch`, `potential-source`, and `unreachable-source`; neither potential source nor insufficient evidence claims an effect happened. The next real user message ends the status scope. These rules belong solely to acceptance, not runtime permission or interception.
113
+
114
+ An effectful follow-up test needs separate task authorization. Its fixture must acquire an exclusive temporary directory with the platform primitive, preserve any pre-existing same-name directory and unrelated sentinel, and clean only its owned directory. For a status-only workflow any write/delete test is a failure, regardless of cleanup success. Historical logs can be audited offline; stochastic model quality and cache improvements remain unmeasured until an explicitly configured model run is performed.
115
+
116
+ Both runners require an explicit model route and credential-variable name before any host probing or artifact creation. The referenced credential variable must already be available in the inherited environment. These configuration-only examples name it without reading or assigning its value:
45
117
 
46
118
  ```sh
47
119
  DSH_PTC_ACCEPTANCE_PROVIDER=<provider> \
48
120
  DSH_PTC_ACCEPTANCE_MODEL=<model> \
49
121
  DSH_PTC_ACCEPTANCE_API_KEY_ENV=PROVIDER_API_KEY \
50
- PROVIDER_API_KEY=<credential> \
122
+ DSH_PTC_ACCEPTANCE_CONFIG_ONLY=1 \
51
123
  npm run test:expensive
52
124
 
53
125
  DSH_PTC_AB_PROVIDER=<provider> \
54
126
  DSH_PTC_AB_MODEL=<model> \
55
127
  DSH_PTC_AB_API_KEY_ENV=PROVIDER_API_KEY \
56
- PROVIDER_API_KEY=<credential> \
128
+ DSH_PTC_AB_CONFIG_ONLY=1 \
57
129
  npm run test:ab
58
130
  ```
59
131
 
60
- `npm run test:ab` writes `report.json`, `report.md`, per-session trajectory artifacts, and blind-review packets under `artifacts/ab-trajectories/`. Both commands invoke the configured model and consume quota.
132
+ For the authorized model run, remove the corresponding configuration-only assignment after preflight succeeds. `npm run test:ab` then writes `report.json`, `report.md`, per-session trajectory artifacts, and blind-review packets under `artifacts/ab-trajectories/`. Both commands invoke the configured model and consume quota outside configuration-only mode.
61
133
 
62
134
  Token traffic is the sum of input, cache-read, cache-write, and output tokens. Model behavior is stochastic, so comparable new results establish a reproducible observation rather than a universal performance claim.
@@ -2,6 +2,8 @@
2
2
 
3
3
  PTC Plus requires Node.js `^22.19.0 || >=24.0.0` and targets the latest available DSH release with TypeScript PTC mode. Compatibility with the preceding Host contract is retained through public capability detection; 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
+ 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
+
5
7
  Install the plugin into the profile that actually runs the target DSH surface. Do not assume a profile named `default` is active.
6
8
 
7
9
  ## Compatibility and Authority
@@ -16,14 +18,20 @@ Install the plugin into the profile that actually runs the target DSH surface. D
16
18
 
17
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.
18
20
 
19
- 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 packages. PTC Plus declares those host-owned DSH packages as unrestricted required peers instead of installing private runtime copies; runtime capability validation owns compatibility, and CI imports the packed plugin against both the current and preceding release channels. DSH's profile module fallback must resolve the peers from the active installation. 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.
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 packages. PTC Plus declares those host-owned DSH packages as unrestricted required peers instead of installing private runtime copies; runtime capability validation owns compatibility, and CI loads the packed plugin inside complete stable and alpha DSH installations. That load step runs `scripts/dsh-execution-seam-smoke.mjs`, which reads the execution service the installed tool runtime reads and requires the plugin to take it over, and `scripts/dsh-rpc-contract-smoke.mjs`, which registers the packed Remote descriptors with the installed TYPERT registry and evaluates 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. 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 from the active installation. 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
+
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
+
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
+
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.
20
28
 
21
29
  ## npm Release
22
30
 
23
31
  Use this form after the selected version is available from the npm registry:
24
32
 
25
33
  ```sh
26
- dsh plugin --profile <profile> add dsh-ptc-plus@0.3.1
34
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.4.1
27
35
  dsh --profile <profile> --dump-config
28
36
  ```
29
37
 
@@ -60,7 +68,7 @@ pnpm dsh --profile <profile> --dump-config
60
68
 
61
69
  ```sh
62
70
  npm pack
63
- dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.3.1.tgz
71
+ dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.4.1.tgz
64
72
  dsh --profile <profile> --dump-config
65
73
  ```
66
74
 
@@ -70,11 +78,22 @@ Windows development checkouts can create and install an immutable content-addres
70
78
  scripts\install-dev.cmd <profile>
71
79
  ```
72
80
 
81
+ Installation and a successful Host import do not prove browser activation. Run the model-free packed Web smoke from this checkout with the latest DSH installed, its `pnpm` available, and a Playwright browser:
82
+
83
+ ```sh
84
+ npx playwright install chromium
85
+ npm run test:client:web -- --dsh-entry /absolute/path/to/dsh/lib/bin.js
86
+ ```
87
+
88
+ On Windows, `--browser-channel msedge` can use the existing Edge installation. The script packs the current source, installs the tarball through `dsh plugin` into a temporary `DSH_HOME`, starts Web on a free loopback port, and opens the conversation and PTC Plus settings surfaces. It closes its browser/Host and removes the temporary profile; screenshots and release evidence remain under ignored `artifacts/client-web-smoke/`. It makes no model request and does not use or update the normal profile. `npm run test:client` supplies the deterministic provider, renderer, projection, and disposal tests included in `verify`/`check`.
89
+
73
90
  ## Isolated latest-DSH development launcher
74
91
 
75
- To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It resolves the current `@deepseek-ai/dsh@alpha` dist-tag, 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. 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.
93
+
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.
76
95
 
77
- The default cache is `%LOCALAPPDATA%\dsh-ptc-plus-dev`. It contains the isolated `DSH_HOME`, DSH installations, immutable plugin snapshots, and a pnpm store. Only the newest three DSH versions and plugin snapshots are retained, and the dedicated pnpm store is pruned after each install. Set `DSH_DEV_CACHE` to move the cache, `DSH_DEV_PROFILE` to change the profile name, `DSH_DEV_VERSION` to select another npm dist-tag or version, `DSH_DEV_PORT` to choose a fixed Web port, or `DSH_DEV_MAX_VERSIONS` to change the retention count (1-10).
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. Installation errors still stop 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 published release, `DSH_DEV_PORT` to choose a fixed Web port, or `DSH_DEV_MAX_VERSIONS` to change the retention count (1-10).
78
97
 
79
98
  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.
80
99
 
@@ -87,4 +106,20 @@ dsh plugin add github:muyuanjin/dsh-ptc-plus#main
87
106
  dsh --dump-config
88
107
  ```
89
108
 
90
- After an npm release, the package spec may instead be `dsh-ptc-plus@0.3.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.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.
110
+
111
+ ## Session format upgrades
112
+
113
+ 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
+
115
+ From this source checkout, convert a source artifact with the destination Host's public catalog:
116
+
117
+ ```sh
118
+ npm run session:migrate -- --dsh-entry /path/to/dsh/lib/bin.js --input /backup/session.jsonl --output /staging/session.v2.jsonl
119
+ ```
120
+
121
+ 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
+
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.
124
+
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.
@@ -49,6 +49,12 @@ return source.length
49
49
 
50
50
  普通已知程序优先 argv spawn;只有命令本身需要 shell 语义时才使用 shell。shell 不是权限系统,也不是 REPL 前置条件;PTY/ConPTY 只用于交互进程。Windows、WSL 与 POSIX 环境的 executable、路径、resolver、signal 和 TTY 必须分别探查,不能由一个 execution world 推断另一个。
51
51
 
52
+ ## Stateful visibility
53
+
54
+ journal 值、模型请求和 Client 展示是三种不同的数据面。append-only session log 中存在完整 journal,只能证明插件有材料尝试重建;DSH ordered surface/derived request history 才证明生成当前调用的模型看到过哪些声明。Client 的 `meta.dshPtcPlusBindings` inventory 只对用户展示,不进入模型上下文;当前 `repl.state(list)` 只描述命名 checkpoint 与 durability mode,也不让隐藏 binding 自动变成模型可知状态。
55
+
56
+ 因此默认 REPL frontier 必须同时可重建且模型可知。result-only 剪裁若仍保留带精确源码的 assistant call,不改变该 cell 的模型 provenance;若 compaction 遮蔽了声明 call,raw journal 不足以继续暴露其 binding。插件不解析自然语言 summary 推断名称、值或依赖,而是收缩相关 cell 与依赖后缀,必要时从空 REPL 继续当前 cell。未来可以用显式选择、有界、结构化的 model-visible state projection 保留被压缩的状态,但它必须从 session log 重建、进入实际 request context,并遵守稳定 prompt prefix;不能仅为延长隐藏状态而默认注入,UI metadata 也不能替代它。
57
+
52
58
  ## Metadata boundaries
53
59
 
54
60
  能力 explorer 分别报告:
@@ -2,6 +2,8 @@
2
2
 
3
3
  本仓库是普通 DSH bundle:`package.json` 声明 `dsh.bundle.patch`、入口、依赖、Node 范围和发布白名单,`cordis.patch.yml` 只插入 `dsh-ptc-plus`。插件自带的运行时依赖由 npm 包声明;必须与宿主共享实例的 DSH service 包声明为 peer dependencies,并由宿主按 `inject` 装配。
4
4
 
5
+ `npm run build` 生成 Client bundle,以及私有编译器使用的 `compiler-core.cjs`、`compiler-platform.cjs`、按需加载的 `compiler-amaro.cjs`、`compiler-typescript.cjs` 和对应 source maps。依赖中的大型字符串参数由构建提取为 `compiler-asset-*.txt`,`compiler-assets.json` 拥有精确加载清单,避免 WASM 等数据同时驻留于源码与字面量池。这些编译器产物由 `scripts/compiler-bundle.mjs` 从源码紧凑生成,并列入发布白名单;不能手工修改生成文件。构建同时核验编译器源码所导入的必需平台成员。`npm run build:check` 同时比较 Client、编译器和资源产物,`prepack` 通过该检查阻止陈旧产物进入 tarball。源码验证还须把私有 realm 的执行映射回原始编译器文件,不能只统计调用服务的外层代码。
6
+
5
7
  ## 命名约定
6
8
 
7
9
  项目在不同集成层使用不同名称:
@@ -40,10 +42,10 @@ npm.cmd stage approve '<stage-id>' --registry=https://registry.npmjs.org/
40
42
 
41
43
  ## Release checklist
42
44
 
43
- 1. 在 Node `22.19.0` 与 Node 24.x 上运行 `npm ci`、`npm run build:check` 和 `npm run check`;Node 24.x 还应覆盖 Windows、Linux 与 macOS。仓库 CI 定义同一矩阵。
45
+ 1. 在 Linux Node `22.19.0`、24.x 与 26.x,以及 Windows 与 macOS Node 24.x 上运行 `npm ci`、`npm run build:check` 和 `npm run check`。仓库 CI 定义同一矩阵。
44
46
  2. 运行 `npm audit`、`npx publint`、`git diff --check`、Markdown local-link check 和 `npm pack --silent --dry-run --json`。确认 tarball 只包含发布白名单内的运行时代码、文档和展示资产,不含凭据、本地路径、开发脚本或测试夹具,并从 tarball 安装到空目录执行 ESM import smoke。机器读取 `npm pack --json` 时保持 `--silent`,避免 lifecycle 输出混入 JSON stream。
45
47
  3. 更新到最新可用 DSH release 并记录 `dsh --version`。分别从 npm 包、固定 Git commit、源码 checkout 和 tarball 安装到临时 profile,再执行 `dsh --profile <profile> --dump-config`,确认只新增 `ptc-plus` row。每个上游 release 都重新验证公共扩展面、CLI/Web 集成和 profile 装配,不设置版本白名单。
46
- 4. 在 Windows 与 Linux CLI/Web 实机启动临时 profile。macOS 由原生 runner 验证 CLI/Web;Windows 与 macOS Desktop 从托盘打开当前 profile 的 DSH Terminal 安装,重启 Desktop 后做一次 PTC 模式 smoke。Desktop 当前发布平台不包括 Linux。
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。
47
49
  5. 只有在明确授权模型消耗后才运行 `npm run test:expensive` 与 `npm run test:ab`。发布结论以结构化测试结果为准,不把一次模型样本推广为普遍保证。
48
50
  6. 确认 npm 包名可用、待发布版本高于 registry 版本、README 截图来自真实 DSH 会话,并核对 repository、homepage、bugs、license 与 `dsh-plugin` topic。
49
51
  7. 最后检查 `npm pack --silent --json` 的名称、版本、大小与文件列表,创建 annotated release tag,并确认 tag commit 已通过 `CI`。运行 `Release` workflow 将同一源码产生的 tarball送入 npm staging;人工检查并以 2FA approve 后,等待 registry 扫描完成,再创建 GitHub Release。
@@ -52,7 +54,7 @@ npm.cmd stage approve '<stage-id>' --registry=https://registry.npmjs.org/
52
54
 
53
55
  ## Permission disclosure
54
56
 
55
- PTC Plus 自身不配置外部 endpoint,也不读取 API key。它让模型代码使用当前 request 的 DSH native tools,并在 worker 进程和操作系统实际允许时直接使用 Node.js filesystem、process、network 与 child process API。DSH 负责 native-tool policy;ambient Node/OS access 不经过该 policy。worker thread 是生命周期隔离,不是恶意代码安全沙箱。
57
+ PTC Plus 自身不配置外部 endpoint,也不读取 API key。它让模型代码使用当前 request 的 DSH native tools,并在插件自有 helper/worker 进程和操作系统实际允许时直接使用 Node.js filesystem、process、network 与 child process API。DSH 负责 native-tool policy;ambient Node/OS access 不经过该 policy。会话 worker 运行在插件自有 helper 进程内,但 worker/helper 边界是生命周期隔离,不是恶意代码安全沙箱。
56
58
 
57
59
  DSH 当前公共 bundle surface 未定义供插件使用的机器可读 permission-disclosure contract,因此这些权限边界记录在人类可读文档中。
58
60