docs: design model activity signal filter
This commit is contained in:
@@ -0,0 +1,108 @@
|
|||||||
|
# Model Activity Signal Filter Design
|
||||||
|
|
||||||
|
**Date:** 2026-07-15
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Keep the left **Model activity** panel useful without exposing low-level execution chatter. The
|
||||||
|
panel must show the user's prompt, genuine model reasoning when the provider emits it, meaningful
|
||||||
|
status messages, and reviewer gates. It must not show assistant narration, tool lifecycle rows, or
|
||||||
|
turn lifecycle rows.
|
||||||
|
|
||||||
|
## Current behavior and root cause
|
||||||
|
|
||||||
|
`sessionStore` intentionally builds a complete chronological `activityLog` containing prompt,
|
||||||
|
thinking, assistant, tool, gate, status, and lifecycle entries. `ModelActivityPanel` currently
|
||||||
|
renders every entry in that array. As a result, a non-reasoning model can fill the panel with rows
|
||||||
|
such as `tool / completed / bash`, `lifecycle / Turn end`, and assistant narration such as
|
||||||
|
"Let me try...".
|
||||||
|
|
||||||
|
Those events are useful to workflow state, replay, the central transcript, and diagnostics, but
|
||||||
|
they are not all suitable for the user-facing activity panel.
|
||||||
|
|
||||||
|
## Visibility contract
|
||||||
|
|
||||||
|
The panel uses an explicit allowlist:
|
||||||
|
|
||||||
|
| Activity kind | Visible | Purpose |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `prompt` | Yes | Shows the question or reviewer input that started the work. |
|
||||||
|
| `thinking` | Yes | Shows genuine reasoning/COT when the configured provider emits it. |
|
||||||
|
| `status` | Yes | Shows meaningful informational, warning, and error milestones. |
|
||||||
|
| `gate` | Yes | Shows that the workflow reached a reviewer decision point. |
|
||||||
|
| `assistant` | No | Avoids exposing operational narration; user-facing assistant text remains in the central transcript. |
|
||||||
|
| `tool` | No | Avoids repetitive implementation details such as `bash completed`. |
|
||||||
|
| `lifecycle` | No | Avoids transport/turn noise such as `Turn end`. |
|
||||||
|
|
||||||
|
This is a strict kind-based contract. The UI must not guess whether a particular assistant sentence
|
||||||
|
is "internal" or "final" by matching text. Such heuristics would be language-dependent and brittle.
|
||||||
|
|
||||||
|
## Architecture and data flow
|
||||||
|
|
||||||
|
The filter belongs at the rendering boundary in `ModelActivityPanel`:
|
||||||
|
|
||||||
|
1. `SessionBridge` continues to sanitize and emit tool/system events.
|
||||||
|
2. `sessionStore` continues to fold every event into the complete in-memory `activityLog` and to
|
||||||
|
update transcript, current phase, pending gate, and agent-active state exactly as today.
|
||||||
|
3. `ModelActivityPanel` derives `visibleActivity` from the allowlisted kinds and renders only that
|
||||||
|
projection.
|
||||||
|
|
||||||
|
Keeping ingestion unchanged preserves the existing SSE/replay, tool correlation, end-of-turn,
|
||||||
|
resume, and diagnostic contracts. It also keeps the central transcript independent: hiding an
|
||||||
|
`assistant` entry from the left panel does not remove it from `transcript`.
|
||||||
|
|
||||||
|
The visibility predicate should be a small exported pure function or a named exported kind set so
|
||||||
|
the contract can be tested directly without duplicating conditions in test code.
|
||||||
|
|
||||||
|
## Interaction details
|
||||||
|
|
||||||
|
- The empty state is based on `visibleActivity.length`, not the raw log length. If only hidden
|
||||||
|
events have arrived, the panel displays `No activity yet.` instead of a visually empty viewport.
|
||||||
|
- Automatic bottom-following reacts only when the visible tail changes. The effect must depend on
|
||||||
|
the identity of the last visible entry (and the visible count), not merely on a newly allocated
|
||||||
|
filtered array. Hidden tool, assistant, or lifecycle events therefore cannot move a reader's
|
||||||
|
scroll position, while appended or streamed visible entries still follow correctly.
|
||||||
|
- Phase, level, Markdown rendering, accessibility labels, close behavior, and the 48 px
|
||||||
|
near-bottom threshold remain unchanged for visible rows.
|
||||||
|
- No new toggle, preference, expansion control, or raw-details view is introduced.
|
||||||
|
|
||||||
|
## Error and edge-case behavior
|
||||||
|
|
||||||
|
- Unknown future activity kinds are hidden by default because they are not allowlisted.
|
||||||
|
- Warning and error status rows remain visible and retain their textual severity labels.
|
||||||
|
- A provider that emits no `thinking` still shows prompt/status/gate milestones; the panel does not
|
||||||
|
synthesize reasoning from assistant narration or tool names.
|
||||||
|
- Closing and reopening the panel does not mutate the underlying complete log or the visible
|
||||||
|
projection.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Frontend tests must prove:
|
||||||
|
|
||||||
|
1. A mixed F1 sequence renders prompt, thinking, status, and gate rows but does not render
|
||||||
|
assistant narration, tool names/statuses, or lifecycle text.
|
||||||
|
2. A hidden-only sequence produces the `No activity yet.` state.
|
||||||
|
3. Assistant output still exists in the central transcript/store after being excluded from the
|
||||||
|
activity panel.
|
||||||
|
4. Hidden-only updates do not trigger bottom-follow scrolling; visible updates retain the existing
|
||||||
|
near-bottom behavior.
|
||||||
|
5. Warning/error labels, Markdown, closing/reopening, and the complete store fold remain covered by
|
||||||
|
the existing regression suite.
|
||||||
|
|
||||||
|
The implementation follows RED/GREEN TDD and runs the focused panel/store tests, the complete
|
||||||
|
frontend suite, TypeScript, the production build, and `git diff --check`.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
Only the frontend is expected to change. Rebuild and force-recreate the frontend container, then
|
||||||
|
restart only `omics_portal-web-1` if the Vite entry hash changes. Verify the running asset, container
|
||||||
|
state, and a live Qwen no-COT session showing prompt/status/gate information without assistant,
|
||||||
|
tool, or lifecycle rows.
|
||||||
|
|
||||||
|
## Out of scope
|
||||||
|
|
||||||
|
- Changing backend event emission or the sanitization boundary.
|
||||||
|
- Removing entries from `activityLog`.
|
||||||
|
- Reclassifying assistant text through content heuristics or an LLM.
|
||||||
|
- Changing the central transcript or workflow state machine.
|
||||||
|
- Redesigning the panel layout beyond the visibility and empty/scroll behavior described above.
|
||||||
Reference in New Issue
Block a user