The agent-default-model refactor moved the headless runner off the
api-proxy create path onto a direct agents.create, which silently dropped
the preset composition the stack had put on every dsh run session: the
header lost its agentPreset and the agent ran on the host composition
alone. Resolve the default preset up front (optional service — a roster-
less composition keeps the pre-preset behavior), record it on the header,
and mount it in setup where a broken composition still fails the run.
Move the triplet to implemented/architecture/, rewrite Proposal into a
present-tense Decision, fold Acceptance criteria and Risks into
Consequences (recording what pins the result), retitle the migration
section to what the move actually touched, and repoint the seven
inbound FIXME/README links.
The task registry has run every background bash, pwsh, pty-send, and
one-shot subagent since it landed, but only the model could read it: a
human at the Web client could not see that a build was running, tell a
finished task from a stuck one, or find its outcome anywhere but the
`run_in_background` tool card that printed an id and never updated.
Task state now reaches the browser as one whole-snapshot `session/tasks`
mux frame per session, pushed at every registry commit that changes what
that session can see. `TaskService` gains `onTasksChanged`, which is
owner-granular because owner-disposal removal is a change no per-task
record can express. The carrier reads the exact owner the listener hands
it, so a push stays correct while that scope tears down, and reads the
baseline through the non-resuming `ctx.agents.get` so listing never
revives a cold session. The client keeps a last-wins mirror on
`SessionListState`, and a new `dsh-client-ui-task` package renders it
beside the subagent catalog — rendering nothing at all until the session
has a task, so an ordinary conversation grows no new chrome.
Streamed per-task output and human-initiated cancellation are separate
phases; the note records why neither has to undo this channel, and why
no Web path may call the consuming `ctx.tasks.read()`.
- restore the parent's AGENTS.md body around this branch's e2b row (the
replay had resurrected the pre-profile-CLI layout, deleting the api/,
bundle/, settings/, and credentials/ groups); the fs/lsp row
condensations stay for the word budget
- aggregate the composite rollback failure, not the original error, when
private state cleanup also fails — a surviving remote group is no
longer hidden by a later cleanup error (triple-failure regression)
- own the state directory before the makeDir RPC, matching the terminal
transaction, so a cancellation racing a committed creation still
enters cleanup
- drop the hidden pollMs parameter defaults; the schemastery default is
the one home, and tests pass the cadence explicitly
- restore spawn/spawnTerminal graceMs validation to the seam's
documented bound (the earlier removal cited subprocess-local as not
validating; it does), with rejection regressions
The linear replay carried old-lineage content over parent-owned files;
this checkpoint restores them and adapts the branch to the parent's
post-rebase seam:
- restore all pty/lsp/subprocess/code-runtime surfaces to the parent's
exact content (this branch claims none of them) and drop the net-zero
code-runtime-e2b/pty-e2b/lsp-e2b residue and its registrations
- widen serializeRemoteEnvironment to the seam's NodeJS.ProcessEnv
tombstone contract: an explicit undefined removes an ambient entry
- migrate the two E2B fixture Agent stubs to the Inbox-model interface
and Session.create
- re-apply the branch's gen-doc-graphs roles, THIRD_PARTY_NOTICES e2b
row, and packages/README group row (trimmed to the doc budget);
regenerate catalogs and re-record bilingual pairings
The linear replay carried each commit's own lineage, so this checkpoint
restores the master-owned surfaces the conflicted regions clobbered and
migrates branch-owned code to master's post-rebase APIs:
- rebuild subprocess-local spawn.ts on master's tree-exit-observer
machinery, keeping the branch's win32 childEnv key semantics and the
Linux zombie-quiescence probe; the zombie test reaps its survivor
directly since a confirmed-absent verdict is a permanent
no-more-signals boundary
- migrate pty-local test stubs to the Inbox-model Agent interface,
Session.create, runnerFailureRules, and the new turn/start payload
- implement the seam's resolveExecutable/spawnTerminal abstracts in the
new pwsh-local and tool-fs-search test fakes
- restore code-runtime, atomic-write, pwsh-local, and app-boot to
master's exact content (the net-zero code-runtime churn is pruned
from this history) and drop rename-detection graft debris
- re-apply the PR's architecture rows and execution-world paragraph,
re-record bilingual pairings, regenerate catalogs, and reconcile the
lockfile