dsh-ptc-plus 0.2.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/README.zh.md +137 -0
  4. package/assets/dsh-ptc-plus-banner.webp +0 -0
  5. package/assets/ptc-plus-repair.png +0 -0
  6. package/assets/ptc-plus-settings.png +0 -0
  7. package/client.js +366 -0
  8. package/cordis.patch.yml +5 -0
  9. package/docs/README.md +21 -0
  10. package/docs/adr/0001-delegate-governance-to-dsh.md +3 -0
  11. package/docs/adr/0002-limit-work-map-scope.md +3 -0
  12. package/docs/adr/0003-prefer-native-program-surfaces.md +3 -0
  13. package/docs/adr/0004-declare-program-bindings-at-the-host.md +5 -0
  14. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +129 -0
  15. package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +45 -0
  16. package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +39 -0
  17. package/docs/adr/0008-define-agent-operating-contract.md +25 -0
  18. package/docs/adr/0009-bound-expensive-acceptance-default.md +39 -0
  19. package/docs/adr/0010-session-log-derived-recovery-tips.md +26 -0
  20. package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +20 -0
  21. package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +23 -0
  22. package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +21 -0
  23. package/docs/adr/0014-persist-cell-rewrite-policy.md +25 -0
  24. package/docs/adr/0015-preserve-source-positions-through-rewrites.md +25 -0
  25. package/docs/adr/0016-archive-resolved-review-findings.md +43 -0
  26. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +23 -0
  27. package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +25 -0
  28. package/docs/adr/0019-plugin-settings-and-kill-switch.md +32 -0
  29. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +36 -0
  30. package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +68 -0
  31. package/docs/adr/README.md +18 -0
  32. package/docs/architecture.md +134 -0
  33. package/docs/capability-projection.md +48 -0
  34. package/docs/client-ui.md +47 -0
  35. package/docs/durability-design.md +265 -0
  36. package/docs/evaluation.md +62 -0
  37. package/docs/installation.md +82 -0
  38. package/docs/program-data-plane.md +61 -0
  39. package/docs/publishing.md +37 -0
  40. package/docs/runtime-reference.md +119 -0
  41. package/docs/value-wire.md +61 -0
  42. package/index.js +532 -0
  43. package/internal/ast-traversal.js +20 -0
  44. package/internal/binding-descriptors.js +95 -0
  45. package/internal/binding-pattern.js +54 -0
  46. package/internal/builtin-esm-sync.js +9 -0
  47. package/internal/cell-analysis.js +467 -0
  48. package/internal/cell-rewriter.js +520 -0
  49. package/internal/config-spec.js +179 -0
  50. package/internal/cordis-tools-owner.js +363 -0
  51. package/internal/diagnostic.js +133 -0
  52. package/internal/direct-surface-owner.js +326 -0
  53. package/internal/edit-transport-owner.js +287 -0
  54. package/internal/failure-reporting.js +139 -0
  55. package/internal/kernel-worker.js +484 -0
  56. package/internal/module-policy.js +46 -0
  57. package/internal/program-bindings.js +187 -0
  58. package/internal/record-utils.js +53 -0
  59. package/internal/recovery-tips.js +81 -0
  60. package/internal/rejected-cell-editor.js +328 -0
  61. package/internal/repl-convenience.js +201 -0
  62. package/internal/runtime-bridge-owner.js +417 -0
  63. package/internal/runtime-config.js +77 -0
  64. package/internal/runtime-contexts.js +31 -0
  65. package/internal/sdk-projection.js +88 -0
  66. package/internal/session-cell-executor.js +612 -0
  67. package/internal/session-journal.js +889 -0
  68. package/internal/session-log-view.js +80 -0
  69. package/internal/session-runtime.js +536 -0
  70. package/internal/session-state.js +45 -0
  71. package/internal/source-position-map.js +224 -0
  72. package/internal/tool-call-canonicalizer.js +339 -0
  73. package/internal/value-wire.js +421 -0
  74. package/internal/worker-client.js +218 -0
  75. package/internal/worker-cwd-virtualization.js +155 -0
  76. package/package.json +100 -0
  77. package/src/client.js +165 -0
@@ -0,0 +1,119 @@
1
+ # Runtime Reference
2
+
3
+ ## Cell Semantics
4
+
5
+ Each top-level `run_code` input is parsed as an async function body using modern JavaScript and erasable TypeScript syntax. Top-level bindings survive across cells, block scope and top-level `await` work normally, and only explicit `return` or printed values appear in the result. Static `import` and `export` declarations are adapted when their corresponding `auto*` options are enabled; named and default imports remain live, read-only bindings across later cells. Otherwise use dynamic `import()` or `require()` and omit module declarations.
6
+
7
+ The default loose binding mode lets a complete top-level `const` or `let` declarator replace existing names. New declarators create bindings. With `autoSplitRedeclarations` enabled, mixed new/existing destructuring is split while preserving its assignment semantics; disabling that option, function/class redeclaration, or any redeclaration in strict binding mode is rejected before execution.
8
+
9
+ Every capability namespace is leased to one cell. Captured `tools`, `capabilities`, `repl`, `code`, or member functions expire when that cell ends.
10
+
11
+ For PTC mode requests using the code-only direct-tool projection, PTC Plus presents two tools in stable order: `run_code` and `edit_run_code`. The latter edits the most recent eligible cell visible when the edit call is dispatched, including a cell that completed successfully but needs a small adjustment. That target remains fixed while the call is in flight; later tool settlements cannot retarget it. The edit accepts exactly one atomic `edits` or `regex_edits` array; invalid or unavailable edits return `{ edited: false, reason }` without executing source or consuming the target.
12
+
13
+ `edit_run_code` is a real registered tool call. Session history and later model requests retain its original name and delta arguments. The plugin executes the materialized source as a host-derived `run_code`, returns only the edit status, value, and logs to the model, and keeps the complete source plus journal in private replay metadata. It does not rewrite assistant history or emit edit-specific runtime context.
14
+
15
+ Only values explicitly returned or printed appear in a cell result:
16
+
17
+ ```ts
18
+ const records = [{ id: 1 }, { id: 2 }]
19
+ return records.map(record => record.id)
20
+ ```
21
+
22
+ Parse, filter, and aggregate large results in the cell before returning them; oversized output is truncated by the host, so expose only what the next step needs.
23
+
24
+ Prefer executing work directly in the current cell; reserve `code.run` for source already held as data. When nested source must be written inline, escape quotes, backslashes, and newlines exactly — its parse errors point only at the generated text, not at a position in the outer cell.
25
+
26
+ ## Capability Discovery
27
+
28
+ The default SDK keeps navigation compact. Use `capabilities.tree/find/inspect` when the required member is not already visible:
29
+
30
+ ```ts
31
+ const matches = await capabilities.find('session')
32
+ return capabilities.inspect({
33
+ symbols: matches.slice(0, 8).map(item => item.symbol),
34
+ budget: 8,
35
+ })
36
+ ```
37
+
38
+ Discovery covers current `tools` plus the advanced `repl` and `code` namespaces. It is read-only and does not grant authority. Calls still use the typed member declared by the capability owner. Use ordinary Node.js and current-cell `tools.*` directly; reserve isolated `code.run` for source already held as data.
39
+
40
+ For commands, prefer project-declared scripts and use an available typed tool. When direct host process access is more appropriate, inspect the executable that is actually installed and invoke it through Node.js `child_process`. Child processes inherit the recorded session cwd when `options.cwd` is omitted, while an explicit `cwd` remains authoritative; the worker preserves the host execution environment needed to resolve package runners and shells. Add a shell or package runner only when the command requires its syntax or resolution; do not assume a particular shell exists.
41
+
42
+ ## Configuration
43
+
44
+ The configuration uses `ptc-plus` as the DSH plugin ID and `dsh-ptc-plus` as the package name. The distinction is intentional: the former is the runtime/settings identity, while the latter is the repository and npm package identity.
45
+
46
+ ```yaml
47
+ - id: ptc-plus
48
+ name: dsh-ptc-plus
49
+ config:
50
+ enabled: true
51
+ cordisToolsEnabled: false
52
+ computeMs: 60000
53
+ maxWallMs: 600000
54
+ maxOutputBytes: 67108864
55
+ maxOldGenerationSizeMb: 512
56
+ maxValueNodes: 100000
57
+ maxValueEdges: 1000000
58
+ maxValueArrayLength: 1000000
59
+ maxValueBigIntDigits: 100000
60
+ maxNestedRunCodeDepth: 8
61
+ canonicalizeToolCalls: true
62
+ looseTopLevelRedeclarations: true
63
+ durableReplay: true
64
+ autoRewriteImports: true
65
+ autoStripExports: true
66
+ autoSplitRedeclarations: true
67
+ tipsEnabled: true
68
+ tipCooldownMessages: 3
69
+ tipEscalationFailures: 2
70
+ ```
71
+
72
+ `enabled: false` is the settings-based kill switch: the Host keeps only the settings namespace and client card, and removes every runtime hook, prompt section, and tool surface. Every setting is applied live when its owner can reconcile it. A submitted cell retains one configuration snapshot through preflight, execution, binding calls, completion validation, and diagnostics; an update accepted while it runs applies to cells submitted afterward. Node fixes a worker's V8 old-generation limit at creation, so changing `maxOldGenerationSizeMb` while a session worker is active is rejected and rolled back rather than reported as applied. Other non-`enabled` updates reconfigure existing owners without replacing session-bound bindings. The settings card is available under Settings → Plugin configuration, shows “已启用” or “已停用”, and disables every control except `enabled` while the plugin is off. If a live enable or reconfiguration cannot install a complete runtime, PTC Plus unwinds or restores every owner and persists the last applied settings; a failed compensating settings write is surfaced as an activation diagnostic. The TypeScript language check is deferred until runtime activation, so a non-TypeScript host can load the plugin in disabled mode but cannot enable it.
73
+
74
+ `cordisToolsEnabled: true` atomically mounts the official `@deepseek-ai/dsh-tool-cordis` plugin and the shipped `cordis-plugin-development` companion Skill in PTC agent scopes. PTC Plus resolves the official `cordis` preset through DSH's public preset service and publishes only that preset's Skill directory through the maintained filesystem provider; it does not copy the Skill or switch the agent's preset. The first request waits until the Cordis tool fiber, owner guidance, Skill provider, and scoped Skill load are all ready. A missing or broken preset, Skill/tool service, declared Cordis service, inconsistent inspect manifest, or rejected activation fails the setting change and removes every provisional contribution. Disable and agent/runtime disposal remove both fibers. Native agents inherit neither the resulting `tools.*` members nor the Skill, and the code-only direct-tool projection remains `[run_code, edit_run_code]`. Agents whose `run_code` surface appears after creation are retried on the DSH tools-change signal. Cordis can evaluate model-written plugins against the live runtime, so enabling it grants shell-equivalent trust.
75
+
76
+ Keep large Cordis host or client source in a top-level binding before calling a Cordis tool. A parse or validation rejection is a runtime failure, so bindings assigned before it remain live for a short retry cell; reuse the binding instead of resending the source.
77
+
78
+ `durableReplay: false` starts new kernels without historical REPL state while preserving live bindings in the current process. It does not delete session logs.
79
+
80
+ Recovery tips are disabled with `tipsEnabled: false`. When enabled, a bounded runtime context in the reserved `tools:ptc-plus-tip/<trigger>/<ordinal>` name family may appear after a repeated binding failure or a diagnostic that identifies an executable, shell, or path problem in the current execution world. The trigger and per-trigger ordinal are reconstructed from canonical named system-prompt snapshots; repeated aggregate copies and visible wording do not advance the history. A tip is subject to `tipCooldownMessages` and becomes detailed only after `tipEscalationFailures` unresolved matches; it never changes the code-only direct-tool list or schema. `edit_run_code` does not emit a runtime context because its real call and result already carry the relevant fact.
81
+
82
+ The three `auto*` toggles control text-level AST rewriting applied before cell wrapping, all on by default:
83
+
84
+ - `autoRewriteImports` adapts static `import` declarations (`import x from 'm'`, named, namespace, side-effect, mixed, and type-only forms) through worker-preloaded module namespaces. Static and dynamic imports use Node's ESM resolver from the session cwd, or the worker process cwd when the session has no recorded cwd; relative project files, bare packages, conditional exports, URL imports, and import attributes retain Node semantics. Modules resolve in source order before the cell body is compiled, and a missing requested export fails during linking before that target module evaluates. Named and default aliases keep live reads and reject assignment; a later explicit loose-mode declaration may replace an alias for future cells while closures compiled earlier retain the import. Unsupported destructuring, loop, and delete writes are rejected before execution. Direct `eval` and `with` are unavailable while value import aliases are active because their dynamic name resolution cannot be preserved by alias rewriting; rejection occurs before module preload. Indirect or locally shadowed eval, `with` without active value aliases, and cells containing only type imports retain ordinary JavaScript behavior.
85
+ - `autoStripExports` strips top-level `export` modifiers: declarations survive without the keyword, `export default` becomes a local `__default` binding, re-exports become side-effect imports, and type-only exports are erased. A cell that separately declares the fixed public name `__default` and also has a default export is rejected before execution; a default function or class already named `__default` needs no alias.
86
+ - `autoSplitRedeclarations` allows a top-level destructuring declaration to mix existing and new names. The original pattern runs under native JavaScript initialization semantics, then existing names are committed and fresh names remain available to later cells.
87
+
88
+ Rewrites are recorded as `meta.dshPtcPlusRewrites` on the tool result (parallel to the journal, a closed schema). Successful rewrites do not emit runtime context. If the rewritten cell fails or has no valid journal, `tools:ptc-plus-rewrite-info` describes the recovery boundary in the next model request.
89
+
90
+ `require(...)` is classified exactly like a dynamic import: allowlisted builtins (`node:assert`, `node:buffer`, `node:querystring`, `node:string_decoder`, `node:stream`, `node:util`, `node:url`, `node:zlib`) stay durable, other modules are volatile, `node:worker_threads`/`node:cluster` are rejected before execution (`PTC-C002`), and non-literal arguments are dynamic module resolution.
91
+
92
+ ## Diagnostics
93
+
94
+ | Code | Meaning | State effect |
95
+ | --- | --- | --- |
96
+ | `PTC-C001` | The cell cannot be parsed | Not executed; REPL unchanged |
97
+ | `PTC-C002` | Preflight rejected a kernel-control import | Not executed; REPL unchanged |
98
+ | `PTC-N001` | Top-level binding conflict | Not executed; REPL unchanged |
99
+ | `PTC-O001` | Unsupported or over-budget output | Cell executed; earlier mutations may exist |
100
+ | `PTC-X001` | Uncaught runtime exception, located at the cell source line | Mutations before the throw may exist |
101
+ | `PTC-R002` | Cold recovery skipped volatile, unconfirmed, or replay-abandoned history | Restored the last reconstructable durable frontier |
102
+ | `PTC-W001` | The same cell failed 3 consecutive times with an identical binding error | One-shot binding-recovery warning appended to the failing cell's logs; no state change |
103
+ | `PTC-W002` | The same cell failed 3 consecutive times with another identical error | One-shot cause-specific warning appended to the failing cell's logs; no state change |
104
+
105
+ Durability describes how the session can recover after a kernel restart; it does not certify that a failed cell is side-effect-free or safe to execute again. A failing cell can mutate bindings or produce an external effect before the exception, so inspect the current state and retry only work whose execution status is known. Host tool calls from inside a cell restore the DSH initiator boundary, so tools that require the exact live calling agent (for example goal tracking) work through `tools.*`.
106
+
107
+ Known top-level native calls outside the declared direct surface may be normalized into `run_code` when the live schema proves the intended tool. The canonicalizer parses arguments once: ordinary JSON is embedded as JavaScript, while values with own `__proto__` keys use safe literals, so the derived cell needs no `JSON.parse` and keeps execution semantics. The normalization adds no provenance or correction text visible to the model. Unknown, malformed, or internally inconsistent calls remain on the DSH host diagnostic path. The two declared direct tools, `run_code` and `edit_run_code`, are never renamed by this recovery path.
108
+
109
+ Inside a cell, omitting the JavaScript argument of a native `tools` member is accepted only when DSH's live object schema validates `{}`. The worker canonicalizes that omission to `{}` before encoding, so dispatch, the durable call transcript, and cold replay observe the same arguments. This supports natural calls such as `tools.cordis_inspect_list()` without a tool-name exception. Passing `undefined` explicitly, omitting required input, or calling another program namespace retains its existing behavior.
110
+
111
+ ## Limits
112
+
113
+ - The runtime is identified as `typescript`. Type annotations, interfaces, and type aliases are erased before executable JavaScript analysis. TypeScript syntax that requires JavaScript generation, including enums, namespaces, and parameter properties, remains unsupported; JSX and decorators are also rejected.
114
+ - `tools.read` is a bounded inspection window in the current DSH tool contract. Whole-file computation in `danger-full-access` should use `node:fs/promises.readFile` or streams and becomes `volatile`.
115
+ - Relative Node filesystem entry points, including `node:fs/promises` helpers and globbing, resolve from the recorded session cwd. Absolute paths and explicit filesystem options remain unchanged; sessions without a recorded cwd use the worker's native cwd and are classified as volatile when the access is ambient.
116
+ - The durable import allowlist is `node:assert`, `node:buffer`, `node:querystring`, `node:string_decoder`, `node:stream`, `node:url`, `node:util`, and `node:zlib`. Other Node imports remain usable but make the cell volatile.
117
+ - Direct `node:worker_threads` and `node:cluster` imports are rejected inside the worker. Calls to `process.exit`, `process.abort`, `process.kill`, and `process.chdir` are rejected through direct `process`, `require`, and dynamic or static `node:process` imports.
118
+ - Cold recovery replays journals from the session log; there are no compressed checkpoints or worker-LRU eviction.
119
+ - DSH services or plugin APIs not exposed as a native tool or owner-provided program binding are not made callable through name-based reflection.
@@ -0,0 +1,61 @@
1
+ # PTC Value Graph V1
2
+
3
+ ## 三个投影
4
+
5
+ PTC runtime value、持久 wire 与模型文本是三个不同契约:
6
+
7
+ ```text
8
+ JavaScript value
9
+ -> ptc-value-graph/v1 envelope worker IPC / journal / replay identity
10
+ -> structured JSON or TS-like text outer CodeRuntime projection
11
+ ```
12
+
13
+ wire 从不使用 `eval` 或 `Function` 解码,模型文本也从不作为可执行序列化读取。
14
+
15
+ ## 支持域
16
+
17
+ `PTCValueV1` 支持:
18
+
19
+ - `null`、boolean、string、普通 finite number;
20
+ - `undefined`、`NaN`、正负 Infinity、`-0`、BigInt;
21
+ - plain object 的 enumerable string-keyed data values;
22
+ - 普通 array,包括 hole;
23
+ - cycle 与 shared reference,identity 在 hydrate 后保持。
24
+
25
+ 以下值明确拒绝:function/closure、Promise、WeakMap/WeakSet、symbol value 或 symbol key、accessor、arbitrary class prototype、Date、Map、Set、RegExp、ArrayBuffer、typed array 和其他 live/executable resource。encoder 读取 property descriptor,不调用 getter。writable/configurable flags 不属于 PTC Value V1 的值图语义,hydrate 后统一成为普通 data property;Proxy 仍属于 worker 隔离与执行预算问题,不因 codec 自动变安全。
26
+
27
+ ## Canonical envelope
28
+
29
+ 持久值使用封闭 JSON-safe envelope:
30
+
31
+ ```ts
32
+ {
33
+ codec: "ptc-value-graph/v1",
34
+ root: Atom,
35
+ nodes: Node[]
36
+ }
37
+ ```
38
+
39
+ `Atom` 是 JSON primitive,或封闭 tag:`undefined`、special number、BigInt、node reference。object node 保存有序 `[key, Atom]` entries;array node 保存 `length` 与有序 `[index, Atom]` entries,因此 hole 与显式 `undefined` 不同。decoder 拒绝未知/额外字段、重复 key/index、越界或 dangling reference、不可达 node 和非 canonical 编码;`__proto__` 通过 data descriptor hydrate,不触发 setter。
40
+
41
+ graph 发现顺序与 ECMAScript own-key 顺序共同确定唯一编码。plain JSON tree 保持线性;shared object 只编码一次。结构预算为 `maxValueNodes`、`maxValueEdges`、`maxValueArrayLength` 和 `maxValueBigIntDigits`,总 IPC/journal/render byte ceiling 继续由 `maxOutputBytes` 约束。
42
+
43
+ ## Completion 与外层投影
44
+
45
+ worker completion 显式携带 `hasValue`,协议字段缺失不能与已编码的 JavaScript `undefined` 混淆。显式 `return undefined` 有值;自然无输出的声明 cell 仍保持无值。
46
+
47
+ DSH 的公共 `CodeRuntime`/tool output 只接受 JSON-safe structured value。为保持社区插件边界:
48
+
49
+ - dense、无 shared identity 的 plain JSON tree 继续作为 structured result 返回;
50
+ - 包含 `undefined`、special number、BigInt、hole、shared identity 或 cycle 的合法 PTC value 使用确定性、有 byte ceiling 的 TS-like renderer,作为 string result 进入外层 CodeRuntime;
51
+ - 外层投影是 untagged overlapping union:plain JSON 根值本身也可以是 string,调用方不能用 `typeof value === "string"` 判断是否经过 renderer;
52
+ - renderer 只是模型展示,不参与 hydrate;需要继续计算时应保留 live REPL binding;
53
+ - journal 保存 canonical graph envelope,不保存 renderer 反解析结果,也不把 decoded rich value 交给外层 `JSON.stringify`。
54
+
55
+ unsupported value 或预算超限继续使用 `PTC-O001`,但帮助文本只要求返回受支持的 PTC value 或缩小结果;`undefined` 不再是错误,也不要求模型用 `null` 替换。
56
+
57
+ cell program binding 的参数和结果经过同一 graph IPC,因此 owner-provided binding 可以接收和返回
58
+ 完整 `PTCValueV1` 支持域,包括 `undefined`、special number、BigInt、hole、shared identity 与 cycle。
59
+ 跨 worker 后得到的是 hydrate 的值图,不是同一个 live object;function、class instance、Promise、
60
+ accessor 和其他不在支持域内的资源会在 dispatch 前或返回 cell 前被拒绝。journal 保存相同的 canonical
61
+ envelope,cold replay 以 recorded value 重建结果而不重新调用 owner binding。