Per-session live observation for owned sessions only, feeding the
upcoming client overlay:
- State model: SessionObservation (sessionId/url/action/since/
thumbnailAttachmentId/lastError), one entry per owned session;
added on start, removed on stop, cleared on dispose.
- Instrumentation: the shared runBsk wrapper begins/ends an action
(tool name mapped to a verb) around every model-facing call and tags
the child with its session id; action end triggers an immediate
thumbnail refresh.
- Thumbnail loop: 1.5s cadence while active, 8s idle downclock, x3
failure backoff, silent frame retention on errors; captures run
OUTSIDE the instrumentation (no action events, no current-pointer
movement) and land in the attachment store by reference.
- Interrupt: runner.killFor(tag) kills exactly the tagged in-flight bsk
children — chat-Stop-equivalent semantics for the current or a named
owned session; foreign ids and the no-in-flight case return false.
- Remote seam: dsh 0.1's Typert Remote pipeline and forwarded-event
allowlist are closed to out-of-tree packages, so state/events/
interrupt are served over the documented webServer route seam:
GET /bsk-observation/state, GET /bsk-observation/events (SSE),
POST /bsk-observation/interrupt; routes mount only when a webServer
service exists (headless compositions skip them).
- Config: observationEnabled (true), thumbnailIntervalMs (1500),
idleIntervalMs (8000).
Tests (+13, 72 total): state machine + event stream, cadence fast/idle/
backoff, headless no-store silence, observation-traffic isolation,
interrupt routing (default/specified/none/foreign), HTTP route
handlers, disabled-webServer no-op.