# Runtime Reference ## Cell Semantics Each top-level `run_code` executes a JavaScript/TypeScript cell with top-level `await`, ordinary control flow and a session root that continues across cells. Static import/export syntax is part of the language. TypeScript runtime forms such as enums and namespaces are transformed before execution. Returned and printed values form the result; binding state is independent of its presentation. With the default `bindingUpdates: 'stateful'`, declarations and assignments update one logical identity in the same scope and activation, including local const bindings. An existing closure observes later updates, while a saved function value keeps its own identity. Separate block, function and iteration scopes stay separate. A bare `let x`, `var x` or `const x` preserves an existing value and creates undefined when new. Each declarator publishes its complete candidate only after its initializer and binding pattern succeed. Earlier declarators and ordinary assignment effects remain real if a later operation fails. Unreached lexical declarations do not reserve a name for future cells. An import alias follows its module until an actual successful assignment or declaration supplies a local value. Re-importing switches that same identity back to the module, so existing new-generation closures observe the change. Named default declarations associate `__default` with the local identity until independently overwritten. Static dependencies link before the body and keep their effects even if a later dependency fails. `bindingUpdates: 'protected'` retains native local restrictions, rejects cross-cell redeclarations, and protects newly created const/import bindings. Switching policy neither resets the worker nor freezes earlier writable identities. Historical cells replay under their recorded language generation; earlier closures retain that generation's behavior. See [ADR 0025](adr/0025-use-versioned-logical-binding-identities.md) for the ownership and compatibility contract. New protected modules retain these native protections and the current callable source reflection contract. Their compilation generation is distinct from historical modules, including when a policy change imports the same source again. Every program namespace is leased to one cell. Namespace objects or member functions captured in the REPL expire when that cell ends. A reusable REPL helper must look up the current namespace inside its body. Global User Binding modules use a dynamic bridge: even a module-captured member resolves the current implementation when invoked by a new cell; a removed member fails until it is available again. Continuations retain their originating cell identity and cannot borrow a later cell's lease. 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`. It recognizes the current Host's `tools:ptc-only` owner section and the preceding Host's `tools:code-only` alias, with the current section authoritative if both appear. The latter tool 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 and an optional `expected_target_call_seq` precondition. Invalid, unavailable, or mismatched-target edits return `{ edited: false, reason }` without executing source or consuming the target. `regex_edits[].replacement` is a JavaScript replacement template: captures are referenced as `$1`, `$2`, ... or `$`, a literal dollar sign is written `$$`, and backslash forms such as `\1` are emitted literally rather than resolved as captures. `pattern` values are JavaScript regular-expression sources without delimiters. `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. When a live parse error occurs exactly at the cell EOF, PTC Plus checks the three single-closing-token corrections `}`, `)`, and `]` with the same preparation context. If exactly one correction succeeds, the existing editor can express it from a bounded unique suffix, and the rejected call has a persistent event identity, `PTC-C001` includes a directly callable `edit_run_code({ edits: [...], expected_target_call_seq })` invocation. The guard must match the target captured when the edit call is persisted, so a later editable cell suppresses execution even when the same literal replacement would match it. The plugin does not apply or execute the correction automatically; ambiguous, broader, and unbound repairs keep the ordinary length-adaptive guidance. Use `return` for an explicit result and `console` for logs. Native expression completion can also supply a result value: ```ts const records = [{ id: 1 }, { id: 2 }] return records.map(record => record.id) ``` Parse, filter, and aggregate large results before returning them. Aggregate log/return overflow terminates the worker and discards the cell; its bindings are not available for a later reduction. An encoding-budget rejection (`PTC-O001`, `invalid-output`) instead keeps the worker live, so an already initialized binding can be reduced in a later cell. Neither path undoes external effects. 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. ## Capability Discovery The default SDK declares `capabilities.tree/find/inspect` directly, so exploring the explorer's own contract is unnecessary. `find` uses case-insensitive lexical matching, prioritizing exact `namespace.member` symbols, namespace names, and member names before complete identifier or description tokens. CamelCase and punctuation separate tokens; multiple query tokens must be contiguous. Prefer a short query such as `read` over a prose request such as `read file content`. A miss means no lexical match, not proof that a capability is unavailable. `tree()` returns namespace entries whose `members` are strings, not a flat symbol list. Form symbols with `tree.flatMap(entry => entry.members.map(member => `${entry.namespace}.${member}`))`. Reuse an observed tree within the current capability view and inspect only relevant symbols; do not infer completeness or effect guarantees from discovery. Exact symbols in examples are conditional on the live view. The advanced `repl.state` and `code.run` schemas remain behind inspection: ```ts const matches = await capabilities.find('session') return capabilities.inspect({ symbols: matches.slice(0, 8).map(item => item.symbol), budget: 8, }) ``` 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. 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. ## Configuration 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. `enhancedToolView` defaults to `true` and controls only the browser presentation of `run_code` and `edit_run_code`. Turning it off unregisters PTC Plus's keyed tool views so DSH's native generic row renders the calls; turning it on restores the compatibility renderer without changing execution, prompt, or session behavior. `autoDescribeRunCode` defaults to `true` and appears as “Allow run_code execution without a summary.” When enabled, a call that omits the outer `run_code.description` uses derived arguments for local DSH validation, and the fallback summary enters presentation metadata only. When disabled, DSH validates the original arguments. Both states expose byte-identical model requests with the required `description` declaration; original call arguments, existing summaries, cell source, and nested native-tool JSON remain unchanged. ```yaml - id: ptc-plus name: dsh-ptc-plus config: enabled: true enhancedToolView: true canonicalizeToolCalls: true autoDescribeRunCode: true bindingUpdates: 'stateful' durableReplay: true tipsEnabled: true cordisToolsEnabled: false userBindingsEnabled: false computeMs: 60000 maxWallMs: 600000 maxOldGenerationSizeMb: 512 maxNestedRunCodeDepth: 8 maxOutputBytes: 67108864 maxValueNodes: 100000 maxValueEdges: 1000000 maxValueArrayLength: 1000000 maxValueBigIntDigits: 100000 tipCooldownMessages: 3 tipEscalationFailures: 2 ``` The five legacy binding and module switches remain migration inputs. Complete enabled/protected choices map to the corresponding new policy; mixed old choices retain their effective controls until the user explicitly selects the new switch. The Host schema preserves an omitted `bindingUpdates` value until migration, and the settings card resolves the same policy. Selecting the switch also clears the compatibility marker. `enabled: false` is the settings-based kill switch: the Host keeps the settings namespace, client card, and passive cleanup that can withdraw old PTC declarations at the next permitted accepted step. It removes execution hooks, prompt sections, and tool surfaces without reading binding storage. 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. `cordisToolsEnabled: true` atomically mounts the official `@deepseek-ai/dsh-tool-cordis` plugin and exactly the shipped `cordis-plugin-development` companion Skill in PTC agent scopes. PTC Plus resolves the official `cordis` preset through DSH's public preset service, lets the maintained filesystem provider own its Skill root, and filters that provider at the public registration boundary so sibling Skills are never published to the PTC scope. It does not copy the Skill or switch the agent's preset. The first request waits until the Cordis tool fiber, owner guidance, exact 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. Keep large Cordis host or client source in a top-level binding before calling a Cordis tool. If that call rejects while the worker stays live, an initialized binding can be reused in a short continuation. Decide whether to retry from the operation owner's retry/idempotence contract and available execution facts; a thrown call or a smaller cell does not prove that no effect occurred. Cordis Plugins and Runs are process-local. On a resumed agent or after Cordis is re-enabled, normalized journal calls can restore their recorded return values but do not prove that prior IDs, approvals, Runs, or Inspect observations are live. The fixed `tools:ptc-plus-cordis-recovery` context remains present until a new successful `cordis_inspect*` call is settled. Use that live read-only inspection before a stateful Cordis decision; do not rerun a recorded mutating call merely to rebuild state. ## Global User Bindings `userBindingsEnabled` defaults to `false`. While disabled, PTC Plus does not read binding storage, add new declarations, inject values, register the management RPC or `/binding` command, or render Global User Binding controls. The next permitted accepted step can withdraw previously delivered declarations. Enabling it loads the single document at `$DSH_HOME/ptc-plus/bindings.json`; writes use a file lock, atomic replacement, owner-only file permissions, and an expected process-local revision. A stale revision or an external file change rejects the mutation and requires reload rather than overwriting newer content. A damaged document produces an explicit catalog error and remains unwritable until the user repairs it and reloads. Each entry has a stable `id`, display `name`, `namespace` or `top-level` scope, selected symbols, one-line purpose, enabled state, and TypeScript source. A namespace name must be a JavaScript identifier; a top-level entry uses its exported symbols as call identifiers and keeps `name` for display. Source must provide named value exports; default exports and re-exports are rejected. An omitted symbol list derives every named value export, while an explicit list limits the exposed API; clearing the Settings symbol field requests fresh derivation from the edited source. The parser derives declaration kinds, parameter and return annotations, bounded inferred types, and model-visible declarations from the selected source exports. A `namespace` entry contributes one object binding under its name, while a `top-level` entry contributes each selected export. Reserved REPL names and duplicate active identifiers fail validation. The document accepts at most 64 entries, 65,536 UTF-16 code units per source, 262,144 across all sources, and 16,384 across active declarations. Mutations validate the complete enabled declaration set before atomic replacement; an externally written document that exceeds the limit is reported as damaged storage and contributes no active entries. The current enabled snapshot is the desired input for the next cell. The independent binding API catalog represents `tools:ptc-plus-user-binding-defaults` and supplies configured prompts and selected source-derived interfaces from the first permitted request. One header identifies use inside `run_code` and replacement of the previous global binding API reference, followed only by entry labels and selected documentation. It does not prove successful activation. Successful activation, session-local shadowing and worker reconstruction do not themselves append a new binding context. Unchanged documentation is deduplicated against retained model-visible history; changed or compacted-away configuration is supplied again. Historical configuration and `tools:ptc-plus-user-bindings` snapshot sections remain readable and are withdrawn once by the next permitted accepted recovery snapshot; the current API catalog is delivered separately. The stable `tools:sdk` prefix and direct-tool schemas do not change with binding contents. A request-owned program namespace or error class takes precedence over a same-name user entry; that entry produces an activation diagnostic and is omitted from the settled snapshot without blocking independent code. If a failed initializer issued a program call, the cell becomes volatile because the successful-entry snapshot is not complete replay source for that call transcript. Namespace members and top-level exports preserve ECMAScript module live reads until assignment or a permitted redeclaration creates a session-local shadow. A shadow is not written to the global document and suppresses only the shadowed name from subsequent global activation while the entry's other names keep activating; journals migrated from versions 1 through 7 keep their recorded whole-entry suppression. Updates, disablement, and removal affect unshadowed names from the next submitted cell. Entry imports resolve from the directory containing `bindings.json` during both candidate evaluation and session activation, independently of the session cwd. Binding modules can use program namespaces present in the current request through a stable bridge; new namespace names are installed as they appear, absent namespaces expose no members, and each invocation uses its originating cell lease. A namespace that has the same name as any existing worker global fails explicitly before bridge installation, so Node intrinsics cannot be replaced and a failed installation cannot leave a partial bridge. Once an exported value may have escaped into an ordinary session binding, its synthetic-module resolution base and installed bridges remain available for that worker lifetime. When no user binding has ever been exposed, disabled or empty activation installs no bridge; if every attempted activation fails, any bridge installed for that attempt is removed before the cell executes. The REPL tab and Settings management modal share a workbench for source editing, validation, declaration preview, revision-checked persistence, import of a local `.ts` file as a disabled entry, enablement, removal, and code execution. The code console evaluates the current unsaved source draft in a separate bounded Node REPL worker. Named exports can be called directly from TypeScript commands, with top-level `await` and variables retained across executions. It does not access the Agent session kernel or enter its journal. The compatible `run` RPC separately provides single-use candidate evaluation with an optional exported-function name and JSON argument array. Both execution paths retain DSH process authority: source and imports may create irreversible Node/OS effects before cancellation, timeout, or failure. Console controls and resource limits are documented in [Client UI](client-ui.md#全局用户-binding-工作台). Session value previews use a separate bounded observation path. A visible inventory without observations can request one read from the existing settled worker through the authenticated Host observation Remote. The read shares the cell queue, verifies the catalog and surface generation, and waits at most 250 ms without creating a worker, replaying history or changing the journal. Only worker-confirmed observation may defer the next cell's execution budgets; sending a request does not exempt background blocking from timeout recovery. The Client discards responses for replaced inventories, including an assignment that changes a binding's recorded source without changing its name. Committed ordinary values in the logical root can be read directly without invoking source getters. The legacy native-storage path additionally requires an actual evaluator probe for await lexical previews; function-local await does not suppress outer declarations. Primitive values and five fixed array slots can be displayed without getters, Proxy traps or complete object enumeration. Arrays always retain an incomplete marker because additional own properties remain uninspected. BigInt conversion is capped at 128 digits. Missing observations remain distinct from unreadable values; details belong to [ADR 0024](adr/0024-repl-console-observation.md). In an enabled PTC session, `/binding new ` and `/binding edit ` append a complete authoring task and start a normal Agent turn. The task gives the current `requestId`, field definitions, namespace invocation examples, and the dependency resolution base. Edit also supplies the exact stored entry and preserves its stable ID. The Agent submits from `run_code` through `code.submitBindingDraft({requestId, entry})`, a stable internal SDK member under enabled configuration. The first valid submission becomes one memory draft with `enabled: false`. The Host checks the captured request, exact Agent, generation, and cell lease; duplicate, concurrent, late, or mismatched submissions fail. Acceptance, turn stop, error, cancellation, replacement, disablement, or disposal revokes eligibility. Starting and ending a request does not register or unregister tools or Skills. The Agent cannot persist or execute candidates through this API. The authoring task permits small REPL cells with in-memory fixtures and assertions, including temporary variables and correction from observed results. It starts with a focused core check, uses `node:assert/strict`, and summarizes bulk checks with totals and representative failures. Tests must not modify external files or services. File and network integrations use in-memory substitutes to verify forwarding and error propagation; unknown-effect imports and initializers are reviewed without execution. Before submission, the final source, exports, types and usage prompt are checked against the requirement and tested behavior. The answer distinguishes helper failures from test-harness failures and reports untested integration. A usage prompt can be empty when the source-derived interface suffices. These instructions neither enforce an effect sandbox nor expose management RPC to the model. See the [user guide](user-bindings.en.md) for the interactive workflow. The accepted outer result carries an opaque draft locator plus complete accepted source and command identity in private metadata. Authenticated Client RPC uses that locator, never a payload session ID. Saving atomically claims the draft before revision-checked persistence; concurrent discard reports busy, and new drafts use create-only storage. Save and enable writes `enabled: true` in the same mutation. Catalog conflicts refresh authoritative state and keep still-valid drafts available for manual retry. Saving or discarding consumes writable access, while `draft-review` and the log projection retain the exact historical source. A public, structured action notice references the accepting result and exposes only the completed persistence fact to later model requests; notice failure does not repeat or undo storage. Agent/session disposal, feature disablement, and owner disposal revoke live locators and reviews, while historical source never restores save eligibility. Cold replay returns recorded submission values without another handoff. Stored, enabled, and successfully activated are distinct facts. Global UI state reports the catalog's enabled flag. Configured model documentation and a save notice prove no activation; results and diagnostics report actual execution. `repl.state` is a checkpoint function and its `list` names are checkpoint names, not bindings. Availability questions use execution results or a side-effect-free observation of a known name, without write/delete smoke tests. Effectful verification must be authorized by the task and use exclusively created resources whose ownership is established before cleanup. Every completed cell records the exact source-derived active snapshot in private result metadata, and its normalized journal records the shadow granularity plus the per-name `provider`/`local`/`absent`/`unknown` evidence of that settlement. Cold recovery validates that snapshot again, checks the name evidence against it, and replays the cell with its recorded granularity; it never substitutes the current `bindings.json` or the current per-name rule for a historical cell. Malformed or incomplete binding metadata invalidates the affected historical node and contracts recovery under the ordinary fail-closed frontier rules. An entry that fails activation is excluded from that cell's active snapshot and produces a bounded diagnostic without preventing independent `run_code` work. `durableReplay: false` starts new kernels without recorded REPL state while preserving live bindings in the current process. It does not delete session logs. With `durableReplay: true`, recovery claims only bindings backed by both verified journal ancestry and exact provenance available to the model that produced the current call. DSH's append-only event log proves reconstructability; its ordered model-visible surface proves awareness. Raw events shadowed from that surface and UI-only `dshPtcPlusBindings` metadata do not make a binding model-knowable. A result-only replacement may retain a cell when the assistant call containing its source remains visible. If compaction shadows that call, the live worker and cold recovery contract the affected state unless an explicitly selected bounded structured projection exposes the exact bindings in model context. Such a projection is not injected by default merely to retain hidden state. Natural-language summaries are not parsed as state evidence. An invalid historical association, prune replacement, or recovery boundary is also rejected as evidence for its bindings; it is not by itself a reason to reject every later valid `run_code`. Recovery takes the intersection of the model-knowable and structurally verified frontiers, then discards cells and bindings that may depend on an unknown boundary. Because the current journal does not contain a complete per-binding dependency graph, the conservative unit is an affected cell and suffix unless stronger owned evidence exists. If no non-empty frontier is provable, the worker starts from an empty REPL and executes the current cell as a new root. The first continued cell reports `PTC-R002` once so the model can redeclare any missing bindings, and its result persists the contraction for later cold starts. Recovery never redispatches, reverses, or certifies effects from discarded history. This availability fallback applies only to historical PTC Plus recovery data; validation, policy, authority, approval, cancellation, and other failures of the current request retain their normal DSH behavior. PTC dynamic messages carry `source: { kind: 'plugin', plugin: 'ptc-plus', form: 'snapshot' | 'catalog' | 'notice' }`. Current-state snapshots replace only earlier PTC state, including historical PTC aggregate sections; they do not replace the binding API catalog, tasks, Skill instructions, tool results, or other producers. Only a later binding catalog replaces an earlier catalog, and an explicit empty catalog withdraws its API documentation. Host runtime-context clearance does not invalidate the catalog; suppression gates new delivery. Empty snapshots withdraw earlier state claims. Delivery uses the public accepted pre-step decision and honors `includeRuntimeContext`, scoped suppression, and cancellation through an empty assembly witness. Committed messages and the public ordered surface drive deduplication and reconciliation after compaction or resume. Proposals do not count as delivery; raw history does not establish model knowledge. Recovery tips are disabled with `tipsEnabled: false`. When enabled, a bounded independent PTC notice identified by `tools:ptc-plus-tip//` 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 committed PTC notices and canonical historical DSH snapshot sections; each identity counts once across both sources, and visible wording does not advance 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. Static and dynamic imports retain Node's resolver from the session cwd, falling back to the worker cwd when none was recorded. Relative files, bare packages, conditional exports, URLs and attributes retain their Node meaning. A missing requested export fails at static linking before that target module evaluates. Namespace property writes still follow the namespace object's own contract; updating an alias does not mutate the namespace. A managed namespace's members are readonly: a member write is refused and leaves the member's live value unchanged, while reflection continues to report that live value. `Reflect.set` returns `false`, and `Object.defineProperty` with a different value throws `TypeError`; a direct assignment from a non-strict cell body is silently discarded, exactly as for any other readonly property. Cell export modifiers retain local declarations; remote re-exports retain dependency loading, type-only exports are erased, and default values use the ordinary `__default` identity. Real modules expose their actual export names through a stable PTC-managed namespace. Member reads follow live sources until actual local override and return original function/object values. A namespace retained by an external function continues to provide live reads. Its readonly properties do not make it a native module namespace object. Opaque code independently using native import on the raw compiled URL, or its own native createRequire, can see the transport representation and does not receive PTC's writable-export interface. PTC-provided imports and require, binding modules, workbench commands and `code.run` children share the managed interface with independent state and lifecycle. The complete contract and acceptance conditions belong to [ADR 0025](adr/0025-use-versioned-logical-binding-identities.md#managed-module-interface). User-selected dynamic compilers retain their native syntax goals and results. Their environments remain part of the source contract: direct eval resolves the caller's logical scope, while indirect eval and Function constructors use their owning realm's root. Environment adaptation must preserve those relationships, ordinary shadowed functions and actual effects. A valid call failing because it sees generated storage names is an implementation defect. This also applies when native or opaque code invokes a supplied eval or Function constructor: after `const value=41`, `["typeof value"].map(eval)` returns `["number"]`. Function.prototype.toString, including a bound callback or module observer, returns compiler-proved original JavaScript source for compiled user functions. Recompilation preserves the source's own dependencies and function values keep their canonical identity. User overrides and separately created realms retain their own behavior. Intrinsic interfaces belong to their source generation. Source selects the owning realm's interface when reading intrinsic values, including property reads and results from native or asynchronous operations. Actual global and prototype properties stay native, including Function.prototype.toString. Legacy root source receives a stable interface after its frozen declaration lowering; its dynamic code uses the native REPL environment, while module results use the same managed namespace interface as other PTC entries. Existing closures retain their saved identities and environments across mode changes and asynchronous or module continuations. Uncompiled VM source continues to observe native engine source when it independently fetches native toString; an opaque observer can receive the PTC source interface as a callable argument. Rewrites are recorded as `meta.dshPtcPlusRewrites` on the tool result (parallel to the journal, a closed schema). Settled rewrites do not emit redundant runtime context: failures already carry execution and retry guidance in their result. Only when the rewritten cell has no valid journal does `tools:ptc-plus-rewrite-info` describe unknown completion in the next model request. `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. ## Diagnostics | Code | Meaning | State effect | | --- | --- | --- | | `PTC-C001` | The cell cannot be parsed | Not executed; REPL unchanged; a uniquely validated and target-bound single-token EOF closure includes a directly callable declared `edit_run_code` repair; otherwise retry a short corrected cell with `run_code`, use edit for a localized long-cell correction, and resend with `run_code` for broad, ambiguous, or unbound repairs | | `PTC-C002` | Preflight rejected a kernel-control import | Not executed; REPL unchanged | | `PTC-N001` | Top-level binding conflict | Not executed; REPL unchanged | | `PTC-O001` | Unsupported or over-budget output | Cell executed; earlier mutations may exist | | `PTC-X001` | Uncaught runtime exception, located at the cell source line | Mutations before the throw may exist | | `PTC-R002` | Cold recovery discarded volatile, unconfirmed, damaged, or replay-abandoned history | Continued from the greatest verified frontier, possibly an empty REPL; missing bindings may need redeclaration | | `PTC-W001` | The same cell failed 3 consecutive times with an identical binding error | Supplemental warning carries the primary failure's conservative state effect, or `unknown` when unavailable | | `PTC-W002` | The same cell failed 3 consecutive times with another identical error | Supplemental warning carries the primary failure's conservative state effect, or `unknown` when unavailable | Durability describes recovery after a kernel restart; it does not certify that a failed cell is safe to execute again. A failing cell can mutate bindings or produce an external effect before the exception. Continuation follows the operation owner's retry/idempotence contract and available execution facts; there is no universal status-query prerequisite. Host tool calls restore the DSH initiator boundary, so tools that require the exact live calling agent work through `tools.*`. Repeated lexical errors direct the model to visible source, scope, and initialization. Worker-owned lease failures direct continuation to the current namespace; proved missing members recommend capability discovery. Error text cannot impersonate that provenance. The warning threshold is three consecutive identical failures, independently of tip cooldown and escalation. Platform tips consume bounded multiline message/stderr facts when no structured owner cause exists; a generic command exit alone does not establish a platform error. Cold replay reuses validated recorded `PTC-X001` and `PTC-O001` diagnostic wording for the same actual failure before comparing the complete completion and transcript. Historical help text therefore cannot discard otherwise verified bindings merely because current guidance changed. A real failure-message, completion, or transcript mismatch still contracts recovery; no historical call is redispatched. 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. 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. ## Named State `capabilities.inspect({ symbols: ['repl.state'] })` exposes the optional state API and its timing contract. A save/restore/delete return value acknowledges an accepted operation. Save checkpoints the final settled cell frontier, not the statement where `save` was called. Restore takes effect after settlement for the next cell; reads and writes after awaiting restore still use the current cell's state. Tentative saves can be discarded when the cell becomes volatile or discarded. These operations neither reverse external effects nor certify retry safety. ## Limits `computeMs` measures worker event-loop active time, including synchronous blocking operations such as `execSync`; it is not a measurement proving CPU consumption. Asynchronous waits are instead bounded by `maxWallMs`. Either timeout terminates the worker and resumes later work from verified recovery state. It does not establish child-process cancellation or external-effect rollback; use an asynchronous process API when waiting on external work. - The runtime is identified as `typescript`. Stateful and protected cells erase type-only syntax and lower enums, namespaces, parameter properties, and decorators through maintained TypeScript and decorator transforms. JSX is outside the cell syntax. Historical cells retain their recorded language generation. - `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`. - 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. - 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. - 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. - Cold recovery replays journals from the session log; there are no compressed checkpoints or worker-LRU eviction. - DSH services or plugin APIs not exposed as a native tool or owner-provided program binding are not made callable through name-based reflection.