dsh-ptc-plus 0.5.1 → 0.5.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 (85) hide show
  1. package/README.en.md +10 -4
  2. package/README.md +10 -4
  3. package/client.cjs +1623 -104
  4. package/compiler-core.cjs +132 -132
  5. package/compiler-core.cjs.map +3 -3
  6. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +2 -0
  7. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +4 -2
  8. package/docs/adr/0019-plugin-settings-and-kill-switch.md +2 -2
  9. package/docs/adr/0023-global-user-bindings.md +12 -0
  10. package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +11 -1
  11. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +1 -1
  12. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +2 -2
  13. package/docs/adr/0032-own-session-log-facts-in-a-host-only-projection.md +31 -1
  14. package/docs/adr/0044-coexist-with-the-official-persistent-repl.md +4 -4
  15. package/docs/adr/0045-customize-model-visible-prompt-text.md +38 -0
  16. package/docs/adr/0046-gate-the-commit-with-the-semantic-evidence-tier.md +35 -0
  17. package/docs/adr/0047-store-journal-argument-digests-in-the-projection.md +88 -0
  18. package/docs/adr/0048-supersede-a-rewritten-cell.md +48 -0
  19. package/docs/adr/0049-prove-a-settlement-against-its-published-record.md +53 -0
  20. package/docs/adr/0050-read-host-surfaces-through-their-published-contract.md +48 -0
  21. package/docs/adr/README.md +7 -1
  22. package/docs/architecture.md +3 -3
  23. package/docs/client-ui.md +5 -2
  24. package/docs/durability-design.md +15 -2
  25. package/docs/installation.md +9 -9
  26. package/docs/releases/v0.5.2.md +91 -0
  27. package/docs/releases/v0.5.3.md +77 -0
  28. package/docs/runtime-reference.md +43 -3
  29. package/docs/unmeasured-cell-recovery-repair-proposal.md +387 -0
  30. package/docs/user-bindings.en.md +15 -0
  31. package/docs/user-bindings.md +15 -0
  32. package/docs/v0.5.3-goals.md +117 -0
  33. package/docs/verification.md +7 -3
  34. package/index.js +100 -31
  35. package/internal/binding-adoption.js +136 -0
  36. package/internal/bounded-literal.js +85 -0
  37. package/internal/capability-command-receipt.js +18 -4
  38. package/internal/capability-delivery-proof.js +70 -0
  39. package/internal/capability-environment.js +200 -11
  40. package/internal/capability-plan.js +11 -8
  41. package/internal/cell-error.js +13 -0
  42. package/internal/config-spec.js +126 -6
  43. package/internal/cordis-tools-owner.js +2 -1
  44. package/internal/direct-surface-owner.js +39 -21
  45. package/internal/edit-transport-owner.js +81 -15
  46. package/internal/execution-provider-owner.js +6 -0
  47. package/internal/execution-seam-compat.js +25 -0
  48. package/internal/host-tool-sdk.js +308 -0
  49. package/internal/isolated-worker.js +134 -17
  50. package/internal/kernel-worker.js +167 -3
  51. package/internal/legacy-cell-analysis.js +14 -2
  52. package/internal/legacy-repl-convenience.js +16 -3
  53. package/internal/official-repl-priority.js +31 -10
  54. package/internal/program-bindings.js +12 -1
  55. package/internal/projection-retention.js +238 -0
  56. package/internal/prompt-text.js +858 -0
  57. package/internal/recovery-tips.js +50 -11
  58. package/internal/rejected-cell-editor.js +3 -2
  59. package/internal/repl-memory-projection.js +21 -2
  60. package/internal/runtime-bridge-owner.js +114 -9
  61. package/internal/runtime-config.js +2 -0
  62. package/internal/runtime-contexts.js +14 -5
  63. package/internal/runtime-messages.js +48 -15
  64. package/internal/session-cell-executor.js +132 -11
  65. package/internal/session-journal-recovery.js +1204 -116
  66. package/internal/session-journal-schema.js +10 -5
  67. package/internal/session-journal.js +214 -14
  68. package/internal/session-log-view.js +133 -26
  69. package/internal/session-runtime.js +746 -38
  70. package/internal/session-state.js +27 -0
  71. package/internal/stateful-root-compiler.js +11 -0
  72. package/internal/stateful-root-runtime.js +17 -0
  73. package/internal/user-binding-console.js +7 -0
  74. package/internal/user-bindings-owner.js +112 -6
  75. package/internal/user-bindings.js +2 -2
  76. package/internal/validated-parse-repair.js +6 -1
  77. package/internal/worker-client.js +27 -4
  78. package/package.json +16 -6
  79. package/src/client-activity.js +24 -4
  80. package/src/client-capabilities-view.js +504 -27
  81. package/src/client-copy.js +187 -2
  82. package/src/client-indicator-view.js +2 -1
  83. package/src/client-repl-view.js +35 -11
  84. package/src/client-styles.js +64 -2
  85. package/src/client.js +3 -1
@@ -0,0 +1,48 @@
1
+ # Read and write the host's surface only through the contract it publishes
2
+
3
+ ## Status
4
+
5
+ Accepted (0.5.3).
6
+
7
+ ## Problem
8
+
9
+ Three of this plugin's host interactions cross a boundary the plugin does not own, and each had settled on a proof that is really an assumption about one host implementation:
10
+
11
+ 1. A transport-owning executor keeps the reserved `run_code` definition inside itself. Reading it by probing every zero-argument member identifies the surface by shape, but it *invokes* host code: an executor with `cancel()` and `flush()` had both called during prompt assembly, and an executor that publishes the definition through a reader taking an argument was judged "no executor" with no diagnostic, which silently removed every feature that needs execution.
12
+ 2. A derived edit dispatched as one model batch is handed to a host that assigns the execution identity itself. The relation was proved by comparing the parent token the plugin holds with the token on the execution the host runs — a token the host mints for itself and the batch contract never carries, so the accepted edit was admitted as its own root, the nested result arrived without an execution journal, and the model read "failed after acceptance" while the revision never applied.
13
+ 3. The user's editable `run_code` description and parameter texts were written onto the host's live definition by assignment. On a getter-only definition that write throws, so the text never reached the model and nothing reported it; on a writable one it survived disposal, leaving PTC Plus prose on a host object the plugin no longer owned.
14
+
15
+ ## Decision
16
+
17
+ Each interaction names the fact the plugin owns and the fact the host owns, and proves the relation with the former:
18
+
19
+ - **Reading an executor.** Which member may be invoked is not a shape question. Prompt assembly asks an executor exactly one declaration reader — `describe([])`, which says which reserved names it owns — and then the plugin's three contracted definition readers, `requirePtcTransport`, `requireTransport` and `transport`. No other member of a host executor is ever called. A host that declares the reserved name in `describe()` and publishes no definition through those readers is reported as *declared but unreadable* (an operator warning) instead of being folded into "this host has no executor"; the answer is recorded per executor as a property of the executor, and the readers are asked again on a later assembly because a scope can mount their service afterwards.
20
+ - **A batch-dispatched derived execution.** The dispatch records the submission on the execution object the plugin built, before the host runs it. The relation is then proved by the call id the plugin chose (which the host matches its batch result back to) together with the derived source; the parent token and root call are compared only on the registry contract, where the host runs the very object the plugin built. A batch host's own identity is never required to reproduce a token it never received.
21
+ - **Writing the editable slots.** The plugin installs an owned property definition and records the descriptor it replaced, once per definition. Both the writable and the accessor-only shape therefore carry the delivered text; a definition whose slot cannot be replaced keeps all of its own text rather than half of the plugin's; and disposal restores the recorded descriptors, so the host's own model-facing definition is exactly what it published before the attachment.
22
+
23
+ ## What this does not claim
24
+
25
+ - The reader names are the plugin's published contract with a transport-owning executor. A host that publishes the definition under another name is unreadable to this plugin until that name is added here — reported, not guessed at.
26
+ - Identifying a batch execution by its call id trusts the host to run the call it was given. The plugin already refuses a batch result that does not name the submitted id, so the alternative is refusing to relate the derived edit at all.
27
+ - Restoring a descriptor cannot succeed against a host that made the slot non-configurable after the plugin replaced it. That case keeps the last written text and is not reported as a host fault.
28
+
29
+ ## Alternatives considered
30
+
31
+ - **Probe every zero-argument member, with a denylist of lifecycle names.** Rejected: the denylist is a list of words, not a property of the members actually invoked, so any executor with an unlisted side-effecting member is executed during assembly.
32
+ - **Infer the parent token from the batch payload.** Rejected: it requires the host to adopt a field the batch contract does not define, and a host that ignores it leaves the relation unprovable — the defect returns whenever the optional executor package is a different revision.
33
+ - **Assign the slot and swallow the failure.** Rejected: silently not delivering the text the user edited is worse than a documented limitation, and it is the failure this decision exists to remove.
34
+ - **Restore the slot by writing the host's old text back.** Rejected: a host that published an accessor keeps reading its own state, so writing text back leaves a data property where an accessor was, and the model-visible definition changes shape because the plugin was unloaded.
35
+
36
+ ## Consequences
37
+
38
+ - Prompt assembly no longer invokes any host executor member beyond the declaration reader `describe([])` and the contracted definition readers, and a declared-but-unreadable transport is a visible operator warning rather than a set of features that quietly disappear.
39
+ - A derived edit settles as the root cell's derived execution on both dispatch contracts, so the deferred settlement, the pre-policy projection and the root cell's own durability decision are exercised on a batch host too.
40
+ - Disabling or unloading the plugin leaves the host's `run_code` definition with the text its owner published.
41
+ - `compat/channels.json` records every host package an install receives: a package outside the release train is pinned at the version the release's own dependency range resolves to, with that tarball's integrity, and a package the release neither publishes nor depends on is recorded as absent. A publish inside a declared range is therefore a recorded drift that the channel proof reports.
42
+
43
+ ## Related
44
+
45
+ - ADR 0017 owns tracking the newest published host surface.
46
+ - ADR 0049 owns proving a settlement against the record it published.
47
+ - [docs/runtime-reference.md](../runtime-reference.md) describes the executor reader contract.
48
+ - [docs/installation.md](../installation.md) describes the channel manifest a consumer install is proved against.
@@ -23,4 +23,10 @@ This directory records stable design constraints for PTC Plus. An ADR states a d
23
23
 
24
24
  - [0043: Compose Capability and Context Policies](0043-compose-capability-and-context-policies.md) — independent availability, disclosure, allocation, collection, recovery and presentation inputs with historical replay generations.
25
25
 
26
- - [0044: Coexist With The Official Persistent REPL](0044-coexist-with-the-official-persistent-repl.md) — forwarded owner release and program format, plus live-capability ownership selection between PTC Plus and the official persistent REPL.
26
+ - [0044: Coexist With The Official Persistent REPL](0044-coexist-with-the-official-persistent-repl.md) — forwarded owner release, program format and state retention, plus live-capability ownership selection between PTC Plus and the official persistent REPL.
27
+ - [0045: Customize Model-Visible Prompt Text](0045-customize-model-visible-prompt-text.md) — fixed plugin text becomes a document the user can edit per slot, with read-only segments and drafts.
28
+ - [0046: Gate The Commit With The Semantic Evidence Tier](0046-gate-the-commit-with-the-semantic-evidence-tier.md) — the change gate runs the semantic tier rather than a hand-picked file list.
29
+ - [0047: Store Journal Argument Digests In The Projection](0047-store-journal-argument-digests-in-the-projection.md) — the projection keeps argument digests so admission can reject a rewritten call.
30
+ - [0048: Supersede A Rewritten Cell](0048-supersede-a-rewritten-cell.md) — an edit with the rewrite setting on supersedes its target; the target stays in the log and its names are reported as replaced.
31
+ - [0049: Prove A Settlement Against Its Published Record](0049-prove-a-settlement-against-its-published-record.md) — a settlement carries the digest of what it asserts, so an edited record is not evidence.
32
+ - [0050: Read And Write The Host Surface Only Through Its Published Contract](0050-read-host-surfaces-through-their-published-contract.md) — contracted executor readers, the call id a batch host echoes back, and owned slot descriptors that disposal restores.
@@ -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 进程内没有需要终止的 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 完成后才开始计时。
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 另有启动样本;采样等待(`sampleBoundMs`,默认 1000ms)在把 helper 通道读空之后才下结论,阻塞期间写入通道的答复即使排在此前消息之后也不会因过期定时器被判缺失,读数上限只报告"没有观察到答复";helper 退出、断连或无法接收请求仍按 worker-exit 有界失败并重置 worker,其他无法观察到答复的采样、以及 run 帧发出之前到达的墙钟或 compute 上限,都按未测量的 no-op 结算:默认 2 时在首次保留 worker 与既有 binding,连续达到 `unmeasuredCellLimit` 个则丢弃 live worker、保留已证明 frontier 由下一 cell 重放;历史重放中无法观察的 cell 同样保留 frontier 并重试。唯一例外由 [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]`;插件用 agent scope 的
@@ -52,7 +52,7 @@ Client half 在侧栏 **插件 → 已安装 → dsh-ptc-plus** 的插件行配
52
52
  总开关关闭时不注册 runtime、执行 hook、tool surface 或 system prompt section,也不读取 binding 存储;`ptc` 与兼容 `code` preset 会话在头部单独显示 `PTC Plus` 指示器。设置卡片显示“已启用/已停用”,稳定指引不包含 UI 品牌名。
53
53
  `Config` 的字段形态由 `internal/settings-compat.js` 按已安装代际的公共能力决定:仍提供 section installer 的代际保留普通描述字段,由自身文档路径提交校验后的具体默认值;只有自管设置文档的代际才加 volatile 标记,字段构建器不具备该能力的代际保持可加载。版本号不参与该判断。
54
54
  `autoDescribeRunCode` 默认开启且只控制请求绑定的本地执行策略。开启时,缺少外层 `run_code.description` 的调用使用派生参数通过本地 DSH 校验,备用摘要仅进入 presentation metadata;关闭时由 DSH 校验原始参数。两种状态的模型可见 tool schema、tool order 和 system sections 保持字节稳定并包含 required `description`;原始调用参数、cell 与嵌套 native 参数保持不变。
55
- 在 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,并保持相同的运行时语义。
55
+ 在 section-installer 代际,除只由插件激活期读取的 `executionSeamTimeoutMs` 外,所有字段都由 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 的默认值。worker 生命周期上界(`maxOldGenerationSizeMb`、`workerReclaimMs`、`startupProbeMs`)在 worker 创建或关闭时从当前配置读取。`maxOldGenerationSizeMb` 在活动 worker 存在时因 Node 的创建期限制而拒绝并回滚。settings 服务缺失时 Host 回退到 composition config,并保持相同的运行时语义。
56
56
 
57
57
  `bindingUpdates` 是新配置的统一入口,默认 `stateful`,也可选择 `protected`。Host schema 保留该字段原始缺省状态,再由 `runtime-config.js` 把完整旧策略映射到相应新策略;混合旧开关保留显式 `legacyBindingSettings` 兼容态。Client 复用同一 resolver,仅在兼容态展示旧开关;用户选择统一开关时,一次 settings update 同时写入新策略并清除兼容标记。
58
58
 
@@ -68,7 +68,7 @@ Skill 根在当前 generation 发布绝对 composition path 时取其 sibling;
68
68
 
69
69
  `internal/user-bindings-store.js` 独占 `$DSH_HOME/ptc-plus/bindings.json`。单一 JSON 文档避免源码与 metadata 双源;进程内队列、file lock、磁盘文本比较、expected revision 和 atomic replacement 共同防止并发覆盖。每次 mutation 在替换前验证完整 enabled snapshot 的声明预算;外部写入的超限文档按损坏输入处理。损坏输入保持显式 error,不会被空文档静默覆盖。候选与正式激活的相对 import 都以该文件所在目录为基准,因此 session cwd 不会改变 helper 的依赖解析。
70
70
 
71
- prompt assembly 为每个 PTC request 取得一次当前启用条目快照,作为随后 dispatch 的期望集合。`tools:ptc-plus-user-binding-defaults` 从首轮通过追加的 PTC API catalog 展示条目提示词及按开关选择的源码派生接口,按稳定 ID 排序,只描述配置 API 与执行时初始化契约;组装不执行源码,也不读取激活状态或加入 revision。`/binding` 保存并启用、会话中途启停、删除或修改模型上下文后,下一次宿主允许且接受的步骤追加当前说明或撤销旧说明,无需等待激活。条目变化不改写 system、tool schema、顺序或旧消息;未变说明按已提交日志与公共 ordered surface 去重,重启后继续使用相同证据。停用条目不贡献内容,关闭声明且提示词为空的条目同样省略。
71
+ prompt assembly 为每个 PTC request 取得一次当前启用条目快照,作为随后 dispatch 的期望集合。快照先经该会话的 adoption 决策过滤,再作为期望集合:全局启停拥有 supply(目录里有哪些条目),会话拥有 adoption(这个会话用其中哪些),worker 拥有 materialization(实际装上了哪些),诊断与 journal 拥有 proof。adoption 是每条目的二态决定加一个缺省——未表态即使用目录提供的一切,因此“显式使用”与“从未表态”产生同一环境,是一个状态而不是两个,也不需要借用能力侧的 `automatic`(那个词表示“由宿主推导”)。adoption 只能撤回已供给条目:全局停用的条目不在目录里,会话无从命名,`/binding skip` 直接拒绝,因此“覆盖复活已删除条目”没有编码,也无须规则禁止。决策记录为一条 `binding-adoption` PTC 消息,由 session log projection 读回最新一条,重启即从日志重建,不引入第二存储或进程内缓存。`tools:ptc-plus-user-binding-defaults` 从首轮通过追加的 PTC API catalog 展示条目提示词及按开关选择的源码派生接口,按稳定 ID 排序,只描述配置 API 与执行时初始化契约;组装不执行源码,也不读取激活状态或加入 revision。`/binding` 保存并启用、会话中途启停、删除或修改模型上下文后,下一次宿主允许且接受的步骤追加当前说明或撤销旧说明,无需等待激活。条目变化不改写 system、tool schema、顺序或旧消息;未变说明按已提交日志与公共 ordered surface 去重,重启后继续使用相同证据。停用条目不贡献内容,关闭声明且提示词为空的条目同样省略。
72
72
 
73
73
  配置段是全局绑定提示词与接口的唯一注入来源,不包含实现源码;成功初始化、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。
74
74
 
package/docs/client-ui.md CHANGED
@@ -51,6 +51,7 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
51
51
  | 核心工作区 | REPL 语法 | `bindingUpdates` | 默认 `stateful`;同作用域的声明与赋值更新变量、函数、类和导入。选择 `protected` 后保护新建 const/import,并检测跨 cell 重声明。两种策略均支持静态 import/export。 |
52
52
  | 核心工作区 | 状态与恢复 | `durableReplay` / `tipsEnabled` | 默认开启;控制 worker 重启后的状态恢复与失败恢复提示。 |
53
53
  | 核心工作区 | 状态与恢复 | `tipCooldownMessages` / `tipEscalationFailures` | 同类提示间隔与详细提示阈值。 |
54
+ | 核心工作区 | 状态与恢复 | `unmeasuredCellLimit` | 连续第几个未测量 cell 触发丢弃(默认 2:第一个保留,第二个丢弃);已证明 frontier 留给下一 cell 重放。 |
54
55
  | 扩展与容错 | 工具扩展 | `userBindingsEnabled` | 默认开启,显式关闭仍有效;开启时加载跨会话 TypeScript helper,并在开关下方显示管理按钮,同时启用全局绑定工作台与 `/binding` Agent 编写入口。 |
55
56
  | 扩展与容错 | 工具扩展 | `cordisToolsEnabled` | 默认关闭;开启后为 PTC agent 加入官方 Cordis 工具、指引与精确的 `cordis-plugin-development` companion Skill,不发布同目录 sibling。 |
56
57
  | 扩展与容错 | 调用容错 | `autoDescribeRunCode` / `canonicalizeToolCalls` | 默认开启;允许缺少外层摘要的 `run_code` 执行,并修复 schema 可唯一确认的顶层 native 工具误调用。 |
@@ -61,6 +62,8 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
61
62
  | 界面与资源 | 资源限制 | `computeMs` / `maxWallMs` | 单 cell event-loop active(包括同步阻塞)与总耗时预算;前者不证明 CPU 消耗。 |
62
63
  | 界面与资源 | 资源限制 | `maxOldGenerationSizeMb` / `maxNestedRunCodeDepth` | kernel worker 内存与嵌套执行深度。 |
63
64
  | 界面与资源 | 资源限制 | `maxOutputBytes` | 单 cell 日志与返回结果的合计字节上限。 |
65
+ | 界面与资源 | 资源限制 | `sampleBoundMs` / `workerReclaimMs` | 计算基线采样等待(未观察到的采样按未测量结算;transport 报告退出/断连/无法发送时仍走 worker-exit);worker 关闭阶段上限(默认 5000ms、最小 1000ms;exit 确认与其后的输出关闭各自以此为上界):cell 触发的 session kernel exit 超时保留 helper 并阻止该会话后续 cell;startup、idle 或输出关闭路径的失败,以及 binding console 与 candidate 只保留实例并在释放时报告。 |
66
+ | 界面与资源 | 资源限制 | `startupProbeMs` / `executionSeamTimeoutMs` | worker 启动探针上限;等待宿主执行入口的上限(只在插件激活或重载时读取)。 |
64
67
  | 界面与资源 | 资源限制 | `maxValueNodes` / `maxValueEdges` / `maxValueArrayLength` / `maxValueBigIntDigits` | Value Graph 与大数组、BigInt 的返回上限;数组长度限制同时约束单数组和一份 graph 的累计槽位。 |
65
68
  | 实验性 | 能力与上下文 | `capabilityManagementEnabled` | 默认关闭;开启实验性能力管理,冻结新会话的能力方案。 |
66
69
  | 实验性 | 能力与上下文 | `capabilityBaseline` / `capabilityPolicy` | 可搜索的能力列表、常用勾选、独立可用性与说明规则;默认/类别/来源/单项覆盖,分配依据及预算分别选择。 |
@@ -75,7 +78,7 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
75
78
 
76
79
  ## enabled 开关与正文功能标记
77
80
 
78
- 保存设置后,Host 在 settings watch 中安装、卸载或重配置对应 owner。能力与上下文的独立职责输入用于新会话;已有会话保持冻结方案,执行 `/capabilities refresh` 后才同步说明、发现与执行成员。其他可重配置字段即时生效。已提交的 cell 固定使用提交时的配置快照,运行中的更新从随后提交的 cell 开始使用;这不会替换 session-bound REPL 或已有 binding。`maxOldGenerationSizeMb` 在活动 worker 存在时因 Node 的创建期限制而拒绝并回滚,其他可重配置字段照常交给 owner。关闭后唯一的宿主副作用是注册 settings 命名空间,
81
+ 保存设置后,Host 在 settings watch 中安装、卸载或重配置对应 owner。能力与上下文的独立职责输入用于新会话;已有会话保持冻结方案,执行 `/capabilities refresh` 后才同步说明、发现与执行成员。其他可重配置字段即时生效;`executionSeamTimeoutMs` 由激活期等待拥有,只在插件激活或重载时读取。已提交的 cell 的预算与策略固定使用提交时的配置快照,运行中的更新从随后提交的 cell 开始使用;worker 生命周期上界(`maxOldGenerationSizeMb`、`workerReclaimMs`、`startupProbeMs`)在 worker 创建或关闭时从当前配置读取;这不会替换 session-bound REPL 或已有 binding。`maxOldGenerationSizeMb` 在活动 worker 存在时因 Node 的创建期限制而拒绝并回滚,其他可重配置字段照常交给 owner。关闭后唯一的宿主副作用是注册 settings 命名空间,
79
82
  保证设置卡片仍然可读;此时只有 `enabled` 可写,其他控件被禁用。运行时重配置失败时回滚到上一次已应用值。
80
83
 
81
84
  `cordisToolsEnabled` 默认关闭并即时生效。它不切换 preset,而是把官方 Cordis 工具、owner guidance 与 `cordis-plugin-development` Skill 作为一个 agent-scoped mount 加入或移出同时暴露 `run_code`、`skill` 工具与 preset/Skill service 的 PTC agent;顶层仍只有 `run_code`,编辑器通过程序内的 `tools.edit_run_code` 调用,普通 agent 不继承。暴露面齐全但挂载失败时,启用会完整回滚;agent scope 缺少 companion surface 时只是延后,不报错也不发布。完整运行要求见 [运行时参考](runtime-reference.md)。
@@ -92,7 +95,7 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
92
95
 
93
96
  代码控制台直接执行当前条目的未保存源码草稿。用户可输入 `readText("./example.txt")`、声明变量或使用顶层 `await`,通过运行按钮或 Ctrl/Cmd+Enter 执行;下一条命令可继续使用临时变量。控制台通过 `console-run` 取得 Host 生成的 opaque environment handle,并以 `console-release` 释放;单次候选导出调用通过兼容的 `run` RPC 提供。控制台 worker 使用共同 root 编译与逻辑状态机制,源码草稿使用共同模块编译入口,Node REPL 承担底层求值;它不连接 Agent kernel,也不写入其 journal。模块导出可直接按名称调用,相对 import 从 binding 存储目录解析。运行、停止、重置环境、清空记录分别是独立动作;折叠不重置环境。普通语法或运行错误保留状态和此前修改,停止、超时、输出超限与 worker 故障会释放环境。执行代码具有 DSH 进程的 Node/OS 权限,这种状态隔离不构成 sandbox。
94
97
 
95
- 首次执行才创建 worker。源码草稿改动后的下一次执行、切换条目、保存修改后的源码、离开工作台或手动重置都会清空旧环境。连续 10 分钟没有执行代码时自动释放,输入输出记录保留;下一次从当前草稿开始,绝不自动重放旧命令。Host 最多保留 4 个临时环境,每个环境一次仅执行一个命令,并沿用 `maxWallMs`、`maxOutputBytes` 和 `maxOldGenerationSizeMb`。源码与单次命令各限制 1 MiB;Client 最多保留 40 条、合计 131072 个 UTF-16 code unit 的展示记录,单条最多 65536 个,截断有明确标记。关闭全局绑定功能或插件时释放全部临时环境。
98
+ 首次执行才创建 worker。源码草稿改动后的下一次执行、切换条目、保存修改后的源码、离开工作台或手动重置都会清空旧环境。连续 10 分钟没有执行代码时自动释放,输入输出记录保留;下一次从当前草稿开始,绝不自动重放旧命令。Host 最多保留 4 个临时环境,每个环境一次仅执行一个命令,并沿用 `maxWallMs`、`maxOutputBytes`、`maxOldGenerationSizeMb` 和 `workerReclaimMs`。源码与单次命令各限制 1 MiB;Client 最多保留 40 条、合计 131072 个 UTF-16 code unit 的展示记录,单条最多 65536 个,截断有明确标记。关闭全局绑定功能或插件时释放全部临时环境。
96
99
 
97
100
  每次执行的命令与输出分开展示。输出沿用会话工具结果的灰色背景、边框和 12px 圆角,带独立标签;长结果在至多 240px 高的内容区内滚动,窄屏自动换行,错误使用错误色。设置弹窗与 REPL 页复用同一输出组件。
98
101
 
@@ -106,7 +106,11 @@ SessionRuntime 创建 kernel 时完全忽略历史 nodes、head、checkpoints
106
106
  求值的 cell 无论静态分类如何都记录为 `volatile`。这是已知配置态,不是运行时降级,因此不
107
107
  发送模型可见警告;system prompt 直接告知模型 binding 仅在当前进程可复用,`repl.state(list)`
108
108
  返回同一状态。未进入 evaluator 的调用仍是 `noop`,取消、超时和 worker failure 仍是
109
- `discarded`。关闭期间不能保存 durable named state;restore 后的下一 cell 仍被强制为 volatile。
109
+ `discarded`;例外是无法测量而在 run 帧发出前结束的 cell(未观察到采样答复、墙钟或 compute 上限先到),
110
+ 它以 `noop` 结算:默认 2 时第一次保留 live worker 与既有 binding,连续达到 `unmeasuredCellLimit` 次才丢弃 live worker 并保留可重放的
111
+ 已证明 frontier;transport 报告 helper 退出、断连或无法接收请求时仍按 worker-exit 丢弃并重置 worker,见
112
+ [ADR 0027](adr/0027-run-the-session-kernel-in-a-killable-helper-process.md)。关闭期间不能保存
113
+ durable named state;restore 后的下一 cell 仍被强制为 volatile。
110
114
 
111
115
  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-与恢复)。
112
116
 
@@ -189,7 +193,8 @@ pre-execute -> tools/execute -> post-execute
189
193
  9. durable node 保存 parent link,命名状态保存 node index;
190
194
  10. `meta.dshPtcPlusRecoveryBoundaries` 在 `tool/result` event sequence 参与排序前完成规范化;损坏 boundary 被拒绝为状态证据并建立保守收缩点,合法 boundary 通过失败 call seq 选择 node,并要求记录的 frontier 恰好是该 node 的 parent;
191
195
  11. 折叠器剪除不可证明的 node、binding 与依赖后代,按剩余记录重算 checkpoints;runtime 重置 worker 并验证候选 frontier,逐级收缩到最大可重放 frontier,必要时到空 REPL;
192
- 12. 当前 cell 只在 worker 实际拥有该 frontier 后执行,成为它的新 child 或空 REPL 的新 root;当前结果持久记录本次收缩并投影一次恢复诊断。
196
+ 12. 当前 cell 只在 worker 实际拥有该 frontier 后执行,成为它的新 child 或空 REPL 的新 root;当前结果持久记录本次收缩并投影一次恢复诊断;
197
+ 13. `editRewritesHistory` 打开时,派生 cell 仍按实际派生 start 序号折叠,同时折叠器应用它记录的取代关系:修订接在被取代 node 的位置(接它的 parent),原本跟在被取代 node 之后的 node 改接修订,head 仍是最晚记录的那一格。被取代的 node 保留在记录里但离开 head 的 parent 路径,因此编辑前读到它声明的 cell 重放时看到的是修订后的环境,而不是一个已撤销的声明。收缩的修订没有 node 可接,它的后继直接改接被取代 node 的 parent。关系与日志能证明的被撤销名字随恢复结果给出(`supersessions` / `supersededBindings`),不改变 `§history` 的可枚举形状。开关关闭时折叠保持追加语义,见 [ADR 0048](adr/0048-supersede-a-rewritten-cell.md)。
193
198
 
194
199
  当前 journal 没有完整的逐 binding 读写与传递依赖图。源码存在、重放未抛错或 completion 相同,都不足以证明闭包捕获、属性 mutation、动态名称访问或运行时值与原执行一致。因此恢复不能任意挑选 unknown boundary 后看似独立的 binding;缺少机械证明时以 cell 为原子并丢弃受影响后缀。将来若要保留更细粒度状态,必须通过版本化、owner-owned 的依赖证据扩展契约,不能从名称或成功重放猜测。
195
200
 
@@ -203,6 +208,8 @@ surface replacement 是否删除状态取决于模型失去了什么,而不取
203
208
 
204
209
  该规则也约束 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。
205
210
 
211
+ 面板显示的不是“当前状态”,而是某个运行期的一次观察;投影的 wire view 因此携带产生它的运行期(`{ runtime, memory }`,`internal/repl-memory-projection.js` 的 `normalizeReplMemoryView`),让读者按数据判断而不是按对象身份猜。两件事分开:同一运行期内的投影刷新只是新鲜度问题,清单仍然有效,不该闪成“不可确认”;跨运行期的快照属于上一个进程,必须判为不可确认并说明原因(`memory.previousRuntime`)。这同时是契约用例 `repl-memory-projection` 的客户端对应面:服务端仍按 UUID generation 校验写入的快照,客户端不再用兜底把上一个运行期的清单复活。
212
+
206
213
  ## Completion 校验
207
214
 
208
215
  普通异常可能已经建立或修改 binding,所以 durable `throw` 属于语言历史。重放接受的语义结果只有:
@@ -221,6 +228,10 @@ surface replacement 是否删除状态取决于模型失去了什么,而不取
221
228
 
222
229
  基础设施失败会终止当前 worker,并把 log-only recovery boundary 放入当前已结算 `tool/result` 的私有 metadata。kernel 从失败 node 的 parent 重新重放;若该 frontier 仍失败则继续向 parent 收缩,直到最大可验证 frontier 或空 REPL。触发恢复的当前 `run_code` 在候选 frontier 验证成功前不执行,验证后在同一次请求中继续。boundary 的失败身份可为顶层 call,或已经由共享 timeline 证明两组 dispatch pairs 和根最终关联的真实派生 start 序号;原始 nested start 不足以证明该身份。收缩保留失败 node 的已证明 parent,之后独立的有效 carrier 仍可进入新 ancestry。boundary 无效或历史本身无法完整折叠时,相关记录和可能依赖它的状态不得进入 frontier;这类历史 PTC metadata 损坏本身不返回永久 recovery error,而是继续收缩,最差用空 worker 执行当前 cell,并在其最终 result 持久表达新 ancestry。已经写入旧版自定义 boundary event 的日志必须先通过显式、非破坏迁移转换为 DSH 可加载的 metadata;迁移失败时不得覆盖原始日志。
223
230
 
231
+ 记录的 diagnostics 与 completion 是同一 settlement 的两份表述:`completion.error.message` 由第一条 diagnostic 渲染得到,因此两者一致只证明这份记录内部自洽,不能证明文字未被改写(编辑 diagnostic 后重新渲染 completion 仍一致)。0.5.2 在发布 `tool/result` 私有 metadata 时写入这些 diagnostic 所述事实的摘要 `dshPtcPlusDiagnosticWording.digest`,覆盖 `message` 以及 code、severity、phase、stateEffect、dispatchState、cause、collisions;`help` 与 `source` 属于呈现(历史记录的 help 措辞和 caret 位置可来自更早 generation),不进入摘要。恢复折叠在把该记录当作证据前重算并比较摘要:摘要缺失表示记录发布于该字段引入之前,仍按旧证据规则处理;摘要存在而不再匹配时,该 cell 不能证明自己的 binding,与其它损坏 metadata 一样建立收缩点。该摘要证明记录未被部分改写,不是不可伪造的边界。0.5.3 起新记录不再写这个摘要,但仍读取带它的记录。
232
+
233
+ 0.5.3 起,发布的不是只覆盖 diagnostics 的摘要,而是一条 settlement 对自己陈述的完整证明:`dshPtcPlusSettlementProof = { version, recordedMessage }` 覆盖 status、completion(kind、`hasValue`、value 摘要、error kind 与 message)与 diagnostics 所述事实,`help`/`source` 仍属呈现。折叠重算并比较它,不一致即在该 cell 上收缩(`PTC-R002`);字段缺失表示记录发布于该证明之前,按 0.5.2 的互校规则处理,因此日志不需要迁移,两个 adjunct 可以共存于同一份历史。Host 对同一 `tool/result` 记录的 `isError` 是插件不能重算的第二份副本,折叠在它存在时要求它等于 `status === "discarded" || completion.kind === "throw"`:即使改写者按新摘要重算证明,也仍要与 Host 记下的事实一致。见 [ADR 0049](adr/0049-prove-a-settlement-against-its-published-record.md)。
234
+
224
235
  ## State Operations
225
236
 
226
237
  ```ts
@@ -274,6 +285,8 @@ help: ...
274
285
 
275
286
  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。
276
287
 
288
+ 记录中的 rewind 与取代关系是另外两种“按记录结束”,各自有自己的诊断:`PTC-R005` 说明 rewind 结束了哪些 binding,`PTC-R007` 说明哪一格取代了哪一格,并在日志能证明时点名修订不再提供、重放也没有重新装上的名字。两者都不是恢复失败,也不把 live 缓存说成已被清空;取代关系在每个 runtime 内报告一次。同一次恢复可以既装入了记录值又取代了单元格,两个事实各自成一条诊断,不互相取舍:被取代的名字不在 missing 与 rewind 列表里,只陈述恢复会把它报告到无处。帮助对说明的是这类通知的含义,因此同一 runtime 内再次报告同一组事实时,事实照旧重复、帮助只出现一次。
289
+
277
290
  ## 失败状态语义
278
291
 
279
292
  诊断的 `stateEffect` 描述当前 cell 的 live/冷恢复状态事实,不由 severity 推断,也不表示当前 binding 是否仍可用:
@@ -2,7 +2,7 @@
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. Historical interface branches are retained through capability detection, without promising a fully verified earlier Host installation; when both generations expose competing presentation evidence, the current DSH contract wins. Compatibility follows those live extension surfaces rather than a version allowlist.
4
4
 
5
- The package declares `engines.dsh: "*"` for DSH's plugin compatibility preflight. This keeps release-number gating open while public capability checks and packed Host contracts establish compatibility; it does not claim that every historical or future Host has been tested. Host-owned service packages remain required peers.
5
+ The package declares `engines.dsh: "*"` for DSH's plugin compatibility preflight. This keeps release-number gating open while public capability checks and packed Host contracts establish compatibility; it does not claim that every historical or future Host has been tested. Host-owned service packages are peers of the plugin because the host supplies them; the PTC tool executor is an optional peer, because a host that keeps tool presentation in its registry does not publish that package at all.
6
6
 
7
7
  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.
8
8
 
@@ -20,7 +20,7 @@ Install the plugin into the profile that actually runs the target DSH surface. D
20
20
 
21
21
  `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.
22
22
 
23
- The optional `cordisToolsEnabled` integration requires the current DSH installation to provide its shipped `cordis` preset plus the public preset, Skill, Cordis, settings, and tool-runtime services. PTC Plus declares the shared service packages as unrestricted required peers instead of installing private runtime copies. For a pathless preset it asks the Host's `pluginPackages.packageOf` service for the active generation's official preset package and requires the exact `cordis-plugin-development/SKILL.md` before mounting it; an older generation with no package service may resolve only its historical plural preset package relative to the Host's `ctx.baseUrl`. This compatibility path is disabled whenever `pluginPackages` exists, so packages merely reachable from the plugin profile cannot override an active Host result. Runtime capability validation owns compatibility, and CI checks the packed plugin against frozen official `latest`, `next`, and newest published release graphs. Each result applies only to the tested cohort. That load step mounts the pathless Cordis companion from a separated active-host resource while a resolvable stale package is present beside the packed plugin, runs `scripts/dsh-execution-seam-smoke.mjs` to exercise public provider composition around the execution service the installed tool runtime uses, and runs `scripts/dsh-rpc-contract-smoke.mjs` to register the packed Remote descriptors with the installed TYPERT registry and evaluate the decoder that generation reads ([ADR 0030](adr/0030-serve-both-typert-codec-generations-from-one-codec.md)); an import alone cannot distinguish a loaded plugin from one whose injection is unsatisfied, because Cordis leaves the latter pending without an error, and it cannot show that the Host accepts a wire contract it validates only at registration. The same suite round-trips argument diagnostics through the selected Host's compressed JSONL Session persistence. Service packages retain the dependency graph selected by their Host distribution rather than independently selecting each service's release tag. DSH's profile module fallback must resolve the peers, while `pluginPackages` identifies the official preset resource from an active installation that publishes the service. Do not copy `SKILL.md` or add the Cordis preset's Skill directory to global roots. If the host surface is incomplete, plugin activation or enabling the setting fails instead of loading a second DSH core.
23
+ The optional `cordisToolsEnabled` integration requires the current DSH installation to provide its shipped `cordis` preset plus the public preset, Skill, Cordis, settings, and tool-runtime services. PTC Plus declares the shared service packages as unrestricted required peers instead of installing private runtime copies. For a pathless preset it asks the Host's `pluginPackages.packageOf` service for the active generation's official preset package and requires the exact `cordis-plugin-development/SKILL.md` before mounting it; an older generation with no package service may resolve only its historical plural preset package relative to the Host's `ctx.baseUrl`. This compatibility path is disabled whenever `pluginPackages` exists, so packages merely reachable from the plugin profile cannot override an active Host result. Runtime capability validation owns compatibility, and CI checks the packed plugin against the blocking host channels resolved from `compat/channels.json`. Each result applies only to the tested cohort. That load step mounts the pathless Cordis companion from a separated active-host resource while a resolvable stale package is present beside the packed plugin, runs `scripts/dsh-execution-seam-smoke.mjs` to exercise public provider composition around the execution service the installed tool runtime uses, and runs `scripts/dsh-rpc-contract-smoke.mjs` to register the packed Remote descriptors with the installed TYPERT registry and evaluate the decoder that generation reads ([ADR 0030](adr/0030-serve-both-typert-codec-generations-from-one-codec.md)); an import alone cannot distinguish a loaded plugin from one whose injection is unsatisfied, because Cordis leaves the latter pending without an error, and it cannot show that the Host accepts a wire contract it validates only at registration. The same suite round-trips argument diagnostics through the selected Host's compressed JSONL Session persistence. Service packages retain the dependency graph selected by their Host distribution rather than independently selecting each service's release tag. DSH's profile module fallback must resolve the peers, while `pluginPackages` identifies the official preset resource from an active installation that publishes the service. Do not copy `SKILL.md` or add the Cordis preset's Skill directory to global roots. If the host surface is incomplete, plugin activation or enabling the setting fails instead of loading a second DSH core.
24
24
 
25
25
  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.
26
26
 
@@ -32,11 +32,11 @@ The Client root requires `slots`, `locale`, `connection`, and `remote`; it adopt
32
32
 
33
33
  ### Compatibility Evidence
34
34
 
35
- The frozen dependency graphs are installation cohorts, not proof of distinct capability generations. `compat/latest/package-lock.json`, the root `package-lock.json`, and `compat/current/package-lock.json` record the latest-tag, next-tag, and newest published-release cohorts respectively; their recorded provenance does not prove live registry availability or untested compatibility. The latest/next cohorts exercise `ptcRuntime`, `configForms`, `plugins.row.config`, volatile configuration and `codec.create()`. `npm run host:baseline:verify` checks frozen graph consistency, not every historical fallback or current registry availability.
35
+ Support is expressed as channels, not versions. `compat/channels.json` records, per channel, the host release each official dist-tag resolves to and the tarball integrity of every host package whose published surface the plugin probes. `latest` and `next` are the blocking channels; `alpha` is a pre-adaptation that reports without blocking. A probed package the release does not publish is recorded at the version and integrity its own declared dependency range resolves to, so a publish inside that range is a recorded drift; a probed package the release neither publishes nor depends on is recorded as absent, and the install proof rejects a graph that contains one. The recorded versions do not prove live registry availability or untested compatibility, and behaviour never branches on them: presentation, transport ownership and state retention are detected from the host's published shapes. `npm run host:channels:verify` checks the tracked manifest offline; `npm run host:channels:update` is the only command that resolves it from the registry.
36
36
 
37
37
  | Retained interface | Evidence and consequence of removal |
38
38
  | --- | --- |
39
- | `retainedBy.mainView`, `plugins.row.config`, volatile updates, `codec.create()`, composer props carrying their own `sessionId` | Required by the frozen graphs; these are current paths, not optional historical fallbacks. |
39
+ | `retainedBy.mainView`, `plugins.row.config`, volatile updates, `codec.create()`, composer props carrying their own `sessionId` | Required by the installed channel graphs; these are current paths, not optional historical fallbacks. |
40
40
  | `settingsScope`, `settings.plugin.item`, section-installer variants | Historical, unfrozen Host shapes, covered with fixtures. Removal loses their live settings, card seat or reconfiguration path. |
41
41
  | `snapshot.current`, bare summary `agentPreset` | Historical, unfrozen selection and preset shapes. Removal can strand their session-specific views or PTC eligibility. Binding and draft evidence never use the preset fallback. |
42
42
  | Historical icon names and missing primitives | Fixtures establish component fallback, not a complete earlier Client. Removal of icon candidates loses native glyphs; usable text/component fallbacks must remain. |
@@ -47,14 +47,14 @@ The frozen dependency graphs are installation cohorts, not proof of distinct cap
47
47
  | `sessionQuery.observeSession` and host-only `sessionProjections` | Current history and presentation owners; missing services are diagnosed, not treated as empty recovery evidence. The projection publishes no Client wire view. |
48
48
  | Legacy session event arrays and V0 boundary migration | Read-only fixtures preserve historical ancestry and file conversion through the shared event transition. Removal can discard reconstructable older sessions; malformed arrays are diagnosed, and format conversion does not prove a complete older Host's live behavior. |
49
49
 
50
- Capabilities select behavior, never a release number. Historical fixture success is not packed-Host evidence. Full Host smoke is bounded to its selected graph, and a clean build is not live browser activation. Public provider composition supports frozen original execution instances without changing their descriptors. The result bridge requires mutable registered tool definitions ([ADR 0028](adr/0028-attach-to-the-host-ptc-execution-seam.md)); frozen tool definitions remain unsupported. The public admission boundary uses DSH's published `ptc` mode: `run_code` is the sole top-level transport, and the agent-scoped editor is invoked through `tools.edit_run_code` inside a program ([ADR 0005](adr/0005-temporary-rejected-cell-edit-transport.md#public-integration-status)). Packed lifecycle evidence covers actual nested admission, derived execution, persisted recovery and provider handback on its frozen official Host graph; an internal fixture or provider seam probe alone does not establish that compatibility. Proven native miscalls are normalized before Host dispatch; an unnormalized root call can reach approval before the plugin rejects it.
50
+ Capabilities select behavior, never a release number. Historical fixture success is not packed-Host evidence. Full Host smoke is bounded to its selected graph, and a clean build is not live browser activation. Public provider composition supports frozen original execution instances without changing their descriptors. The result bridge requires mutable registered tool definitions ([ADR 0028](adr/0028-attach-to-the-host-ptc-execution-seam.md)); frozen tool definitions remain unsupported. The public admission boundary uses DSH's published `ptc` mode: `run_code` is the sole top-level transport, and the agent-scoped editor is invoked through `tools.edit_run_code` inside a program ([ADR 0005](adr/0005-temporary-rejected-cell-edit-transport.md#public-integration-status)). Packed lifecycle evidence covers actual nested admission, derived execution, persisted recovery and provider handback on its installed channel host graph; an internal fixture or provider seam probe alone does not establish that compatibility. Proven native miscalls are normalized before Host dispatch; an unnormalized root call can reach approval before the plugin rejects it.
51
51
 
52
52
  ## npm Release
53
53
 
54
54
  Use this form after the selected version is available from the npm registry:
55
55
 
56
56
  ```sh
57
- dsh plugin --profile <profile> add dsh-ptc-plus@0.5.1
57
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.5.3
58
58
  dsh --profile <profile> --dump-config
59
59
  ```
60
60
 
@@ -91,7 +91,7 @@ pnpm dsh --profile <profile> --dump-config
91
91
 
92
92
  ```sh
93
93
  npm pack
94
- dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.5.1.tgz
94
+ dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.5.3.tgz
95
95
  dsh --profile <profile> --dump-config
96
96
  ```
97
97
 
@@ -159,7 +159,7 @@ dsh plugin add github:muyuanjin/dsh-ptc-plus#main
159
159
  dsh --dump-config
160
160
  ```
161
161
 
162
- After an npm release, the package spec may instead be `dsh-ptc-plus@0.5.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.
162
+ After an npm release, the package spec may instead be `dsh-ptc-plus@0.5.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.
163
163
 
164
164
  ## Upgrades
165
165
 
@@ -172,7 +172,7 @@ dsh --profile <profile> --dump-config
172
172
 
173
173
  For a tarball or a different pinned Git revision, replace the `add` argument with the absolute tarball path or `github:muyuanjin/dsh-ptc-plus#COMMIT_SHA`. This updates the profile dependency spec; the Loader module name remains `dsh-ptc-plus`. `dsh plugin --profile <profile> update dsh-ptc-plus` updates within its saved dependency constraint, so it cannot move an exact pinned revision to a different revision. Bare commands in Desktop's **Open DSH Terminal** target its active profile.
174
174
 
175
- Restart the selected Host after the package transaction and verify its selected package and full bundle in the plugin page and `--dump-config`; installing dependencies alone does not replace already loaded JavaScript. Preserve the bundle's existing enabled/disabled choice. A source-checkout `npm ci` only prepares developer dependencies, and Windows build-cache preparation only prepares a tarball: neither upgrades a profile. Avoid `npm install` in an unrelated shell directory and do not edit Loader module names to encode revisions. The plugin never patches DSH or requires a custom Host build. Compatibility claims require the current published cohort's packed acceptance evidence.
175
+ Restart the selected Host after the package transaction and verify its selected package and full bundle in the plugin page and `--dump-config`; installing dependencies alone does not replace already loaded JavaScript. Preserve the bundle's existing enabled/disabled choice. A source-checkout `npm ci` only prepares developer dependencies, and Windows build-cache preparation only prepares a tarball: neither upgrades a profile. Avoid `npm install` in an unrelated shell directory and do not edit Loader module names to encode revisions. The plugin never patches DSH or requires a custom Host build. Compatibility claims require the resolved channel release's packed acceptance evidence.
176
176
 
177
177
  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.
178
178
 
@@ -0,0 +1,91 @@
1
+ [中文](#cn-v052) | [English](#en-v052)
2
+
3
+ <h3 id="cn-v052">宿主适配</h3>
4
+
5
+ * 目标发行仍是当前官方 DSH,插件继续使用它的公共扩展面(设置卡片座位、会话投影和公共 `Menu`),本版本不要求宿主侧改动
6
+ * 升级前写下的会话日志检查点会按新格式重新折叠,旧会话照常恢复,不需要先清空会话或配置
7
+
8
+ <h3>新增</h3>
9
+
10
+ * 「能力与上下文 → 提示文本」可以逐句改写插件写给模型的固定提示:每一行标明所属通道、存在条件、字节数和只读原因,只读段落与宿主段落(系统提示与工具说明)只展示、不能改
11
+ * 提示文本是一张紧凑表格,点一行展开该行的编辑区;编辑先进草稿,**保存**才生效,**取消**丢弃,保存前可以看到逐条差异及其生效时机(下一次请求、新会话或下次触发)
12
+ * 检查点的保留窗口在设置里可调:保留最近单元格数(8–512,默认 8)、保留载荷预算(1 MiB–16 MiB,默认 8 MiB,最坏情况约 32 MB)、单元格簇上限(默认与保留单元格数一致,`0` 表示只由载荷预算约束)
13
+ * 计算基线采样、worker 回收、启动探针与宿主执行入口的等待上限,以及连续未测量 cell 的丢弃阈值,都可以按机器情况调整
14
+
15
+ <h3>稳定性</h3>
16
+
17
+ * 表面重发布(例如切换工作目录、能力观测、宿主重渲染)不再重建内核:只要 worker 还活着,绑定就在原地保留,视图变化不影响计算状态
18
+ * 恢复提示只在真的需要时出现:完整恢复不再发通知,只有确实无法恢复的绑定才被点名(`PTC-R002`),曾被宣布可用之后消失的绑定另有 `PTC-R006` 点名
19
+ * 编辑命令是追加语义:被接受的编辑新增一次调用,原有单元格与其绑定保持不变;改写历史是可选的未来能力,默认关闭
20
+ * 长会话实测:163 个 run_code 单元格的会话中恢复类诊断数为 0
21
+
22
+ <h3>修复</h3>
23
+
24
+ * 会话日志检查点的体积由窗口与预算决定,不再随会话累计写入量无限增长:窗口按条数与字节双重上限把旧结算折成摘要记录,超出预算的单个单元格整簇移除。以每格 20 KB 代码加 20 KB 写入的会话实测,450 格为 0.62 MB、900 格为 0.83 MB
25
+ * 被移出检查点的单元格在需要时从会话日志重新折叠,因此仍可编辑和查看;日志无法提供时,编辑会提示「该单元格超出保留窗口,已不可编辑」
26
+ * 单个单元格本身就超过载荷预算时,它会连同参数原文一起移出检查点并提示「最新单元格超出保留预算,已从检查点移除」,而不是让检查点无限变大
27
+ * 提示文本面板里的原因码与槽位种类按界面语言显示,中文界面不再出现内部代码;只读槽位的说明与按钮样式与设置页其余部分一致
28
+ * 选中提示文本的某一行后,编辑区会滚动到可见位置,不再出现「点了行却没看到编辑器」
29
+ * REPL 绑定面板在会话投影刷新时保留最后一次确认的清单,不再短暂显示后变成「当前绑定状态尚不可确认」
30
+ * 依赖安全:`zod` 解析到 4.6.7(GHSA-mrhx-c7xc-m3w5,high)
31
+
32
+ <h3>升级</h3>
33
+
34
+ * 需要 Node.js `^22.19.0 || >=24.0.0`;升级插件后请重启 DSH
35
+ * 现有配置不需要迁移:没有显式设置的保留参数使用上述默认值,已有配置里的其它字段照旧生效
36
+
37
+ ```sh
38
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.5.2
39
+ ```
40
+
41
+ <h3>致谢</h3>
42
+
43
+ * 感谢 @smter 的 #11:定位了「宿主事件循环停顿后,已经到达的采样回复被当成超时丢弃」的竞态,并贡献了随本版本合入的回归用例
44
+
45
+ ---
46
+
47
+ <h3 id="en-v052">Host Compatibility</h3>
48
+
49
+ * This release targets the current official DSH release and keeps using its public extension surfaces (the settings card seat, the session projection and the public `Menu`); no host-side change is required
50
+ * Session-log checkpoints written before this version are refolded in the new format, so existing sessions keep recovering without clearing the session or the configuration
51
+
52
+ <h3>New Features</h3>
53
+
54
+ * **Capabilities & context → Prompt text** now lets you rewrite, sentence by sentence, the fixed text the plugin writes for the model. Each row states its channel, when it applies, its byte size and why it is read-only; read-only and host-owned sections (system prompt and tool descriptions) are shown only
55
+ * The prompt text surface is a compact table: select a row to expand its editor. Edits stay in a draft, **Save** applies them, **Cancel** discards them, and the pending diff with its effect time (next request, new session or next trigger) is visible before saving
56
+ * The checkpoint retention window is configurable: retained recent cells (8–512, default 8), retained payload budget (1 MiB–16 MiB, default 8 MiB, worst case about 32 MB) and the retained cluster limit (defaults to the retained cells; `0` means the payload budget is the only bound)
57
+ * The bounds for compute-baseline sampling, worker reclamation, the startup probe and the host execution seam, plus the threshold for consecutive unmeasured cells, can be tuned for the machine
58
+
59
+ <h3>Stability</h3>
60
+
61
+ * A surface republish (working-directory change, capability observation, host re-render) no longer rebuilds the kernel: while the worker is alive the bindings stay where they are, and a change of view does not change computation state
62
+ * Recovery notices appear only when they are needed: a complete restore is silent, a binding that truly cannot be restored is named (`PTC-R002`), and one that was announced live and later vanished is named separately (`PTC-R006`)
63
+ * An accepted edit appends a call: the original cell and its bindings stay unchanged; rewriting history remains a future opt-in, off by default
64
+ * Measured on a long session: 163 run_code cells produced zero recovery diagnostics
65
+
66
+ <h3>Fixes</h3>
67
+
68
+ * The session-log checkpoint is bounded by the window and the budget instead of growing without limit with what the session writes: a count and byte window folds older settlements into summary records and removes a single cell that exceeds the budget on its own. Measured on sessions writing 20 KB of code plus 20 KB per cell: 0.62 MB at 450 cells and 0.83 MB at 900
69
+ * A cell removed from the checkpoint is refolded from the session log when it is needed, so it stays editable and readable; when the log cannot provide it, editing reports "This cell is outside the retention window and can no longer be edited"
70
+ * A single cell larger than the payload budget is removed with its argument text and reported as "The newest cell exceeded the retention budget and was removed from the checkpoint", instead of letting the checkpoint grow without bound
71
+ * The reason codes and slot kinds in the prompt text surface follow the interface language, so Chinese users no longer see internal identifiers; read-only slot descriptions and buttons match the rest of the settings page
72
+ * Selecting a prompt text row scrolls its editor into view, so a selected row always shows the editor it expands
73
+ * The REPL binding panel keeps the last confirmed inventory when the session projection refreshes, instead of briefly showing it and then falling back to "Current binding state cannot be confirmed"
74
+ * Dependency security: `zod` resolves to 4.6.7 (GHSA-mrhx-c7xc-m3w5, high)
75
+
76
+ <h3>Upgrade</h3>
77
+
78
+ * Requires Node.js `^22.19.0 || >=24.0.0`; restart DSH after upgrading the plugin
79
+ * No configuration migration is needed: retention fields that are not set use the defaults above, and other configured fields keep their values
80
+
81
+ ```sh
82
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.5.2
83
+ ```
84
+
85
+ <h3>Thanks</h3>
86
+
87
+ * Thanks to @smter for #11: they located the race where a buffered sampling reply was discarded as a timeout after a host event-loop stall, and contributed the regression case that ships with this release
88
+
89
+ ---
90
+
91
+ Full Changelog: https://github.com/muyuanjin/dsh-ptc-plus/compare/v0.5.1...v0.5.2
@@ -0,0 +1,77 @@
1
+ [中文](#cn-v053) | [English](#en-v053)
2
+
3
+ <h3 id="cn-v053">宿主适配</h3>
4
+
5
+ * 装在较新的官方 DSH 上照常可用:宿主把 PTC 的工具呈现交给工具执行器后,`run_code` 不再是注册的工具定义。插件向"实际发布它的那一面"要它——注册表注册了就问注册表,执行器拥有它就问执行器——两种形态都不按版本判断。本版本的阻塞通道 `latest` 与 `next` 发布的是注册表形态;执行器形态属于 `alpha` 线,按该线发布的形状适配并只报告结果
6
+ * 状态保留按宿主声明读取:宿主的运行期提供方声明是否为同一个状态所有者保留环境时,插件照它说的报告,不会把一个有状态的程序环境说成无状态;"让位给官方 REPL"也因此看这份声明,而不是看某种源码形式
7
+ * 插件自己的会话执行、`edit_run_code` 改写与其结算证据在新的派发契约上照旧成立:一次工具派发按宿主发布的形式提交(单次调用或整批),改写后的单元格仍读得到新值
8
+ * 宿主若在提示装配之后才声明模型可见的工具,那份声明归宿主所有;插件只在它自己拥有的层面(程序内绑定、SDK、供给规则)继续生效,不会假装替换了宿主未交给它的声明
9
+ * 支持的宿主线用通道表达而不是版本:`latest`(最新发布)、`next`(在途候选)与 `alpha`(尚未发布的那条线)各自对应一条宿主线,插件按每条线发布的形状安装与运行。`latest` 与 `next` 是阻塞通道,本版本的安装与运行证据以它们为准;`alpha` 是提前适配,只报告、不阻塞发布。插件行为不按宿主版本分支
10
+ * 目标发行仍是当前官方 DSH,插件继续使用它的公共扩展面(设置卡片座位、会话投影、能力探测与公共 `Menu`),本版本不要求宿主侧改动
11
+ * 旧版本写下的会话日志照常恢复:本版本之前的结算记录没有新的自证字段,恢复按旧规则读取它们,不需要清空会话或配置
12
+
13
+ <h3>新增</h3>
14
+
15
+ * 绑定取用变成会话自己的决定:`/binding status` 列出全局提供的条目,`/binding use <id>` 与 `/binding skip <id>` 决定这个会话用不用,`/binding reset` 回到缺省。没有表态就是全部取用,所以升级后不设置也没有行为变化;决定记在会话里,重启后从日志重建
16
+ * 全局删掉的条目不能在会话里被"救回来":它已不在目录里,取用只可能收窄,不存在覆盖复活这条路径
17
+ * 设置里新增开关「编辑时替换原单元格」(`editRewritesHistory`,默认关闭)。打开后,已接受的 `edit_run_code` 修订取代目标单元格:后续单元格读到修订的值,目标单元格仍留在日志里但不再参与环境重建,修订不再声明的名字以"被取代"报告(`PTC-R007`),而不是当作丢失
18
+ * 能力设置的收据与本面板的面板把三件事分开说:已保存(全局设置记录了这项选择)、已投递(模型可见目录里已出现该项)、已可用(本会话有完成的执行真的取到了它)。保存或发布都不构成"已可用",没有证据时如实说未证明
19
+
20
+ <h3>修复</h3>
21
+
22
+ * 被事后改动的历史记录不再能充当证据:每个结算在发布时留下自己陈述的摘要,恢复折叠会重算并比较它。status、completion 或诊断措辞被改过的单元格会被判为不可信、被跳过并点名(`PTC-R002`),而不是重放一个从未发生过的单元格;判定是终态,不会进入重试
23
+ * 打开「编辑时替换原单元格」时,被取代单元格的绑定以专门诊断点名,而不是静默消失
24
+ * 取代关系不再取决于修订自己怎么结算:修订读到时间、随机数等 live 状态时按记录值安装,被收缩时干脆不在环境里,但两种情况都仍然取代目标单元格
25
+ * 修订接在被编辑单元格的位置,原本跟在其后的单元格改从修订继续:在编辑之前读到该单元格声明的 cell 不再于冷恢复时丢掉这个声明,恢复也不再因此收缩回被编辑前的值
26
+ * 一次恢复既装入了记录值又取代了单元格时,取代关系照旧报告,不再因为已经发了恢复通知而被丢掉
27
+ * REPL 绑定面板说明清单来自哪个运行期:同一运行期内的投影刷新仍然保留清单;上一个进程留下的快照显示为不可确认,并给出原因,不再静默续用
28
+
29
+ <h3>升级</h3>
30
+
31
+ * 需要 Node.js `^22.19.0 || >=24.0.0`;升级插件后请重启 DSH
32
+ * 不需要配置迁移:新开关默认关闭,其它字段沿用既有配置;旧会话日志不需要清理或重写
33
+
34
+ ```sh
35
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.5.3
36
+ ```
37
+
38
+ ---
39
+
40
+ <h3 id="en-v053">Host Compatibility</h3>
41
+
42
+ * It runs on a newer official DSH: once the host hands PTC tool presentation to a tool executor, `run_code` is no longer a registered tool definition. The plugin asks whichever surface actually publishes it — the registry when one registers it, the executor when one owns it — and neither shape is decided by a version. The blocking channels of this release, `latest` and `next`, publish the registry shape; the executor shape belongs to the `alpha` line, which this release adapts to and reports on without blocking
43
+ * State retention follows the host's declaration: when the host's program runtime declares whether it keeps an environment per state owner, the plugin reports what it says instead of describing a stateful environment as stateless, and handing execution over to the official REPL follows that declaration rather than one source form
44
+ * The plugin's own session execution, its `edit_run_code` revisions and their settlement evidence still hold on the new dispatch contract: one tool dispatch is submitted in the form the host publishes (a single call or a complete batch), and a rewritten cell still reads the revised value
45
+ * When a host declares the model-facing tools after prompt assembly, that declaration belongs to the host; the plugin keeps its own layers (program bindings, SDK, supply rules) and does not claim to have replaced a declaration it was never given
46
+ * Supported host lines are expressed as channels, not versions: `latest` (newest release), `next` (in-flight candidate) and `alpha` (a line the host has not released yet) each name one host line, and the plugin installs and runs on the shape each line publishes. `latest` and `next` are the blocking channels this release's install and run evidence comes from; `alpha` is an early adaptation that reports without blocking a release. Plugin behaviour never branches on a host version
47
+ * This release targets the current official DSH release and keeps using its public extension surfaces (the settings card seat, the session projection, capability probing and the public `Menu`); no host-side change is required
48
+ * Session logs written by earlier versions keep recovering: settlements recorded before this version carry none of the new self-proof fields, and recovery reads them by the older rules, so no session or configuration has to be cleared
49
+
50
+ <h3>New Features</h3>
51
+
52
+ * Binding adoption is now the session's own decision: `/binding status` lists the globally supplied entries, `/binding use <id>` and `/binding skip <id>` decide whether this session uses one, and `/binding reset` returns to the default. Saying nothing means every entry is used, so upgrading without touching it changes nothing; the decision lives in the session and is rebuilt from the log after a restart
53
+ * An entry deleted globally cannot be revived from a session: it is no longer in the catalog, adoption can only narrow what is supplied, and there is no override that brings it back
54
+ * New setting **Replace the edited cell in place** (`editRewritesHistory`, off by default). When it is on, an accepted `edit_run_code` revision supersedes its target: later cells read the revision's value, the target keeps its place in the log but no longer rebuilds the environment, and names the revision no longer declares are reported as superseded (`PTC-R007`) instead of being treated as lost
55
+ * A capability receipt and the capability pane now state three facts separately: saved (the global setting records the choice), delivered (the model-visible catalog lists it) and usable (a completed execution in this session actually reached it). Neither saving nor publishing proves usability, and without evidence the pane says so
56
+
57
+ <h3>Fixes</h3>
58
+
59
+ * A historical record edited after the fact can no longer serve as evidence: every settlement records a digest of what it published, and the fold recomputes and compares it. A cell whose status, completion or diagnostic wording changed is treated as untrusted, skipped and named (`PTC-R002`) instead of replaying a cell that never ran; the decision is terminal and never becomes a retry
60
+ * With history rewriting on, the bindings of a superseded cell are named by their own diagnostic instead of disappearing silently
61
+ * Supersession no longer depends on how the revision itself settled: a revision that read live state (a clock, a random source) is installed from its recorded values, and one the fold contracts is not in the environment at all, but both still replace their target
62
+ * A revision takes the edited cell's place in the recorded order and the cells that followed it continue from the revision: a cell that read a binding of the edited cell before the edit no longer loses it during cold recovery, and recovery no longer contracts back to the value the edit replaced
63
+ * A recovery that also installed recorded values still reports the relation it adopted instead of dropping it because a restore notice already existed
64
+ * The REPL binding panel states which runtime its inventory came from: a projection refresh inside the same runtime keeps the inventory, while a snapshot left by a previous process reads as unconfirmed with its reason instead of being reused silently
65
+
66
+ <h3>Upgrade</h3>
67
+
68
+ * Requires Node.js `^22.19.0 || >=24.0.0`; restart DSH after upgrading the plugin
69
+ * No configuration migration is needed: the new switch is off by default and other fields keep their values; existing session logs need no cleanup or rewrite
70
+
71
+ ```sh
72
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.5.3
73
+ ```
74
+
75
+ ---
76
+
77
+ Full Changelog: https://github.com/muyuanjin/dsh-ptc-plus/compare/v0.5.2...v0.5.3