Lifecycle and safety fixes from the external review:
- Observe abort while awaiting the initialize handshake, so a server that never
replies can't defeat the tool-timeout signal.
- On an aborted request the server won't cancel, tear the instance down after a
bounded grace instead of releasing the serialized queue with work still live
(prevents overlapping document lifecycles).
- Re-check provider disposal after the canonicalize/read awaits so a query can't
spawn an unowned server after disposeAll().
- Read the source through one open handle (stat + read on the same fd) to close
the realpath-vs-read TOCTOU; decode with a fatal UTF-8 decoder so a legitimate
U+FFFD is not misclassified as invalid.
- Validate and read the source BEFORE spawning a server (pre-start rejection).
- Require an explicit openClose for option-form textDocumentSync.
- Reject nonpositive teardown budgets and non-executable absolute commands at
load; surface unsupported operations as structured LSP_UNSUPPORTED_OPERATION.
- Retain the stderr tail (fatal diagnostics land at exit), not the prefix.
- Catalog the seam vocabulary in docs/core-data-structures/lsp.md.
toolPairingBalancedAfter previously answered by resolving a cached
positional successor and reading its before-balance, with a null-successor
depth fallback. Both queries are the same prefix property sampled at
adjacent cuts, so the cache now holds one per-cut balance sequence
(N nodes -> N+1 cuts) plus a seq->position index; before/after differ
only by a cut offset. The successor map, the duplicate rebuild/extend
fold loops, and the non-null assertion are gone, and the running counter
is named inProgressToolCalls. Docs describing the successor mechanism
are updated in place.
Run every ordered group through the same rolling pool: an exclusive call is a
pool of one (a barrier), dropping the separate runExclusive path and the
redundant post-grouping executionMode re-query. Behavior is unchanged — the
parallel-tool-calls snapshot and the full scheduler unit suite (barriers, cap,
abort, model-order results) stay green.
Add AgentLoop.Config.maxParallelToolCalls as a factory-wide default applied to
every agent create/createAgent/resume mints (per-agent option overrides it),
forwarded through agent-core so it reaches front doors that expose no cap field
of their own. Trim the isConcurrencySafe JSDoc to the local contract and link
the parallel-tool-call RFC for the full rationale; document the field on the
canonical core-data-structures page.
The public kill result used the awkward phrase already-terminal. Rename it to already-finished and keep the model-facing response aligned; not-alive would be inaccurate because a force-failed registry record can still correspond to orphaned producer work.
Task kinds were open strings even though producer namespaces are an extension point. Add the merge-extensible TaskKindMap and derived TaskKind, cover consumer declarations in task and bundle tests, and retain the runtime non-empty check for untyped callers.
With exactOptionalPropertyTypes, owner?: Agent | undefined allowed an explicit undefined value that no caller needs. Tighten the property to owner?: Agent so unowned work is expressed by omitting it.
Record the requested task-service/backend split as a follow-up, using a systemd-backed runtime as a concrete candidate without guessing its durability and ownership contract in this PR. Regenerate the type and Cordis catalogs so public docs match the declarations.
The background-task change repeated its lifecycle design across implemented RFCs, package READMEs, JSDoc, test commentary, and model-visible schemas. That repetition obscured the contracts that maintainers must preserve and added avoidable prompt tokens.
Rewrite the implemented RFCs around the current design, keep authorization, exact-owner cleanup, wait/abort ordering, producer quiescence, and teardown-failure guarantees at their owning surfaces, and remove peer surveys, review history, control-flow narration, and emphatic restatement.
Shorten the task and subagent schema wording, synchronize the bilingual tool cookbook, and regenerate the config, service, RFC, tool, and replay snapshot derivatives. Runtime behavior is unchanged; test edits update prose-only assertions and descriptions.
Move the agent-spine bundle and the stdio/ACP/JSON-RPC app packages out of
core/ and ui/ into a new packages/examples/ group, renamed with a -demo
suffix so the npm name marks them as non-product surface:
core/agent-core -> examples/agent-spine-demo (dsh-agent-spine-demo)
ui/stdio-agent -> examples/stdio-demo (dsh-stdio-demo)
ui/acp-agent -> examples/acp-demo (dsh-acp-demo)
ui/jsonrpc-agent -> examples/jsonrpc-demo (dsh-jsonrpc-demo)
Update every code/config/test reference and reference-only doc mentions, and
regenerate module-graph, config-catalog, and doc-graphs. The jsonrpc bin
(dsh-jsonrpc-agent) and single-file exe (dsh-jsonrpc-agent-pkg) keep their
names; the SDK runtime-startup surface is reconciled separately.