The seam's structured-clone boundary admits values JSON does not (BigInt,
Map, circulars), while tool/code-dispatch events must be JSON-appendable —
left unhandled, a sub-call could execute and then fail at logging time.
The bridge now JSON-normalizes binding arguments BEFORE dispatch (a value
that does not survive rejects that one call), so the dispatched form and
the logged form are the same JSON value by construction.
New group packages/code-runtime/ with the interface package
@deepseek-ai/dsh-code-runtime, per the Code Mode RFC: abstract CodeRuntime
service (run() resolves program failures as an error field, rejects only
for seam misuse), the CodeRunRequest/CodeBindingNamespace/CodeRunResult/
CodeLogEntry/CodeRunFailure vocabulary, and readonly language/isolation
backend descriptors. Registered in the tsconfig maps, packages/README,
architecture service map, and the doc-graph service-role classification;
catalogs regenerated.
The RFC's one forward path token to the worker package becomes an npm-name
mention until PR3 creates that directory (verify-package-paths is
drift-scoped: the now-existing group made the token checkable).
docs/architecture.md ceiling 1630 -> 1640: the doc gained a genuinely new
capability-service row; the row itself is already minimal.
Budget expiry terminated the worker but nothing cancelled an in-flight
host-side sub-dispatch, and a late dispatch could append events after
run_code returned. The bridge now owns a run-scoped AbortController
(follows exec.signal; fired on any run settlement), sub-dispatches get
the run signal, and run_code returns only after the dispatch queue
drains — no post-settlement appends, per dispose-to-quiescence.
(A1) Scope the wire-collapse guarantee honestly: systemPrompt.tools() is
a public multi-provider API, so the mode governs the registry's
contribution (the only shipped source); deliberate extra providers own
what they add, and the shipped-configuration invariant is test-pinned.
(A2) Replace pause-on-pending-RPC timeout with two independent budgets:
computeMs metered by worker.performance.eventLoopUtilization() busy time
(unfoolable by an un-awaited decoy dispatch; probe-verified) plus a
never-pausing maxWallMs ceiling.
(A3) Specify sub-call additionalContext as deliberately suppressed in
the MVP (immediate inject would break call/result adjacency; the plural
channel is named follow-up work).
(B) Orphan-process caveat vs bash-local's group kill; null-prototype
binding namespaces (__proto__/constructor names); per-PR doc artifacts
(packages/README row, architecture service map in PR2, config/tool/
persistence catalogs per owning PR); engines range corrected to
^22.19.0 || >=24.0.0.
Research finding: a SessionEventMap member is a log event — JSDoc prose
required, @mode is a hard error there, and docs/persistence-catalog.md
must be regenerated (todo/write is the log-only precedent). PR4's plan
now names both.
Own adversarial pass finding: a static inject on the registry would gate
ctx.tools (and every tool plugin) on a code runtime existing even under
mode 'native'. The RFC now names the sanctioned pattern: soft
ctx.get('codeRuntime') at use time (the agent-loop sessionPersistence
precedent) with absence failing loud in the provider thunk.
Supersedes the add-on-plugin + node:vm-stub draft in place (still proposed/):
code mode becomes a first-class ToolRegistry presentation mode
('native' | 'code' | 'both'), execution goes behind a new ctx.codeRuntime
capability seam whose shipped backend is one fresh Node worker thread per
run (type-strip, empty env, resource limits, hard terminate), at
bash-equivalent trust with no unsafe-flag ceremony. Renames the file to
2026-06-15-code-mode.md and regenerates the RFC index.