Render reconstructable system prompts at each request-series boundary, preserve series declarations through pre-step wrappers, and keep the presentation and replay snapshots aligned across clients.
Browser acceptance of the activity panel surfaced the product problem: a
background bash registers in both planes, so the header grew two near-
identical popovers — "background jobs" with lifecycle and duration,
"activities" with live output — listing the same work twice.
The service planes stay orthogonal (jobs: model-visible control with a
consuming read cursor; activities: transient non-consuming observation).
The join happens per row in the UI projection instead:
- dsh-client-ui-activity renders the single merged "tasks" list. Each
jobsBySession row joins the activity carrying its correlation.jobId —
the job supplies identity, lifecycle (stopping exists only there),
duration, and the model-visible detail; the activity supplies the
expandable live-output panel. Standalone activities (workflow runs)
keep their own rows; without the activity registry, job rows still
render and the control degrades to the old job list exactly.
- dsh-client-ui-jobs is deleted (pre-release, no shim); the merged entry
takes its slot order. The job locale namespace folds into activity.
- User-facing copy says "task" (任务): N tasks running / N 个任务进行中.
- Hierarchy: live rows first as two lines (label over kind badge and
status, ticking duration), a Finished divider when both sections
exist, settled rows compacted to one de-emphasized line, and the
output panel hangs behind a spine under its row.
Deliberately not joined: subagent rows stay bare (the subagent panel is
their surface) and foreground commands stay in tool cards.
Both web e2e scenarios now assert one Tasks list; the background-job
scenario's row gained a live-output panel, proving the join end to end.
Agent Note: 2026-08-25-unified-task-list.
Add the activity capability seam: ctx.activities is a pure observation
plane where long-running work (background bash/pwsh, workflow runs) opens a
handle, appends transient output into a byte-offset ring buffer, and settles
exactly once. Nothing model-visible changes: reads are non-consuming and
lossy-by-design (absolute UTF-8 offsets survive eviction and report gaps),
correlation carries {callId, jobId}, and visibility is owner-fenced like jobs.
The seam is strictly optional. Producers tap it through ctx.get('activities')
and contain every observation failure, so an unregistered or broken registry
never affects the underlying job (proven by broken-registry tests).
Ship the full path in one change:
- @deepseek-ai/dsh-activity: Service Definition, pumpActivityOutput pull
substrate, invariant companion; dsh-activity-local: ring-buffer provider
with retention config and owner cleanup.
- shell: ShellProcess.observed exposes non-consuming stdout/stderr readers;
tool-bash/tool-pwsh mirror background jobs into activities.
- tool-workflow: phase/log/agent lines mirrored as a workflow activity.
- api-activity-controller: Typert Remote control (roster baseline+buckets)
and observe (opened/output/status frames, coalesced and byte-capped)
streams plus the client feed service with reference-counted observation.
- ui-activity: session-header action rendering live output through
TerminalBlock, which now shows output while a command is still running.
Docs: activity subsystem page, architecture row, regenerated catalogs, and
the Agent Note (2026-08-24-activity-observation-seam), all bilingual. A
keyless web e2e replays a real run_in_background stream to ARIA goldens.
Run the GitHub Windows runtime leg under the runner’s native PowerShell instead of inheriting the POSIX Bash body. POSIX and Windows now own explicit output resolution, virtual-environment setup, environment scrubbing, and keyless/live black-box commands, while portable build commands continue to use each runner’s default shell.
Put the pinned uv installation on the GitLab Windows job PATH before either the smoke or release builder invokes it. Reject a runtime executable whose basename does not match the selected platform manifest, and reject Intel macOS at platform selection instead of reporting a misleading missing artifact.
Add a complete PowerShell path to the published Python tutorial and record the three-phase shutdown-time bound in the Windows runtime decision. Workflow, Python, and bilingual documentation tests pin the resulting behavior.