From df0c204d734dbdb0dda42f1fd12af25a870b9f07 Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Thu, 16 Jul 2026 08:19:43 -0700 Subject: [PATCH] docs(rfc): reconcile Live-to-Final assistant-reply contracts with shipped behavior (#6144) (#6147) Docs-only reconciliation of the Stable Assistant Turn Anchors / Live-to-Final RFCs + CONTRACTS.md + Phase 0 inventory from proposed/scaffold to accepted/implemented framing. No runtime/CI change; one comment-header fix in static/assistant_turn_anchors.js. Remaining hardening tracked under #3400. Co-authored-by: nesquena-hermes Co-authored-by: franksong2702 --- CHANGELOG.md | 4 ++ docs/CONTRACTS.md | 14 +++++-- .../stable-assistant-turn-anchor-phase0.md | 16 ++++--- docs/rfcs/README.md | 17 ++++---- docs/rfcs/live-to-final-assistant-replies.md | 42 ++++++++++++++++++- docs/rfcs/stable-assistant-turn-anchors.md | 35 +++++++++++++++- docs/rfcs/transparent-stream-activity-mode.md | 31 +++++++++++--- .../webui-run-state-consistency-contract.md | 18 +++++++- static/assistant_turn_anchors.js | 10 ++--- 9 files changed, 156 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bec8aa2..c402851f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ ## [Unreleased] +### Changed + +- **Docs: reconciled the assistant-reply lifecycle RFCs/contracts with shipped behavior.** The Stable Assistant Turn Anchors and Live-to-Final RFCs, `docs/CONTRACTS.md`, and the Phase 0 architecture inventory were updated from "proposed/scaffold" framing to "accepted/implemented" to match what actually ships (single assistant-turn owner projecting one `activity_scene_v1` into Compact Worklog / Transparent Stream / Final answer). Documentation-only — no runtime behavior or CI-gate change; the one code touch is a corrected comment header in `static/assistant_turn_anchors.js`. Remaining hardening stays tracked under #3400. Thanks @franksong2702. (#6144) + ### Fixed - **Models selected from a list-shaped custom-provider allowlist now route to the right provider.** A `custom_providers[].models` allowlist can be written as either a mapping or a list, and the model picker accepted both — but runtime routing only read mapping keys, so a model chosen from a *list*-shaped allowlist could silently stay on the active/default provider instead of its own. The supported-model-ID extraction is now centralized in one helper used by both catalog construction and routing, so the picker and runtime can no longer drift. Existing mapping-shaped and list-of-strings configs are unaffected. Thanks @franksong2702. (#6127, #6121) diff --git a/docs/CONTRACTS.md b/docs/CONTRACTS.md index 0094a5c2..e7bcc6fc 100644 --- a/docs/CONTRACTS.md +++ b/docs/CONTRACTS.md @@ -29,13 +29,19 @@ contributor guidance; it does not change runtime behavior or CI gates. repairs. Start here for narrow fixes that keep the existing WebUI execution path. - [`docs/rfcs/live-to-final-assistant-replies.md`](rfcs/live-to-final-assistant-replies.md): - proposed product model for long-running assistant replies, live process text, + accepted product model for long-running assistant replies, live process text, tool activity, recovery, terminal outcomes, and final-answer boundaries. Start here for UI/UX changes to running-session assistant reply rendering. +- [`docs/rfcs/stable-assistant-turn-anchors.md`](rfcs/stable-assistant-turn-anchors.md): + implemented presentation/reconciliation model that attaches live, settled, + replayed, and recovered activity to one assistant-turn owner and projects one + `activity_scene_v1` into Compact Worklog, Transparent Stream, or Final answer + only. Remaining hardening stays tracked under #3400. - [`docs/architecture/stable-assistant-turn-anchor-phase0.md`](architecture/stable-assistant-turn-anchor-phase0.md): - current Phase 0 inventory for the Stable Assistant Turn Anchors work under - #3926. Use this before wiring anchor helpers into live SSE, replay, - settlement, `INFLIGHT`, or `renderMessages()` paths. + cumulative implementation inventory for the Stable Assistant Turn Anchors + work under #3926. Use it to distinguish shipped wiring from historical slice + boundaries before changing live SSE, replay, settlement, `INFLIGHT`, or + `renderMessages()` paths. - [`docs/rfcs/canonical-session-resolution.md`](rfcs/canonical-session-resolution.md): proposed contract for resolving URL routes, query parameters, localStorage, sidebar rows, and compression-lineage IDs to one canonical visible session diff --git a/docs/architecture/stable-assistant-turn-anchor-phase0.md b/docs/architecture/stable-assistant-turn-anchor-phase0.md index b09ef65a..ceea2023 100644 --- a/docs/architecture/stable-assistant-turn-anchor-phase0.md +++ b/docs/architecture/stable-assistant-turn-anchor-phase0.md @@ -1,12 +1,16 @@ # Stable Assistant Turn Anchors Phase 0 Inventory -This inventory implements the first non-visual slice of -[`stable-assistant-turn-anchors.md`](../rfcs/stable-assistant-turn-anchors.md). -It documents the current per-turn state layers and the event-shape contract that -future anchor phases must consume. It does not claim that anchors are wired into -streaming or rendering yet. +This inventory began as the first non-visual slice of +[`stable-assistant-turn-anchors.md`](../rfcs/stable-assistant-turn-anchors.md) and +now records the shipped phase progression. Current `master` wires Anchor-owned +`activity_scene_v1` data into live and settled Compact Worklog, Transparent +Stream, journal hydration, session re-entry, and transcript-backed persistence. -## RFC Phase Progress +The slice-by-slice sections below are retained as implementation history. +Present-tense statements such as “unwired” or “future phase” describe the point +when that slice landed; they do not override the current coverage summary above. + +## Shipped RFC Phase Progress - The #3962 Phase 0 scaffold shipped through #3977 / v0.51.359: inventory the current state layers, encode the owner seed, and pin the source classification diff --git a/docs/rfcs/README.md b/docs/rfcs/README.md index 921bb2d4..d728461d 100644 --- a/docs/rfcs/README.md +++ b/docs/rfcs/README.md @@ -47,16 +47,17 @@ First-time contributor RFCs should be discussed in an issue before opening a PR. replay, compression, and session metadata coherent during active and recovered WebUI runs. - [`live-to-final-assistant-replies.md`](live-to-final-assistant-replies.md) - — #3400 product model for long-running assistant replies, live process prose, - tool activity, recovery, terminal outcomes, and the final-answer boundary. + — #3400 accepted product model for long-running assistant replies, live + process prose, tool activity, recovery, terminal outcomes, display + projections, and the final-answer boundary. - [`transparent-stream-activity-mode.md`](transparent-stream-activity-mode.md) - — #3820 opt-in display mode for power users who need a transparent, - chronological Thinking / progress / tool-call stream alongside the default - Compact Worklog model. + — #3820 implemented opt-in display mode for power users who need a + transparent, chronological Thinking / progress / tool-call stream alongside + the default Compact Worklog and opt-in Final answer only projections. - [`stable-assistant-turn-anchors.md`](stable-assistant-turn-anchors.md) — #3926 - proposed frontend presentation/reconciliation model for anchoring live - assistant activity, settled final answers, replay, and Compact/Transparent - render modes to one assistant turn. + implemented frontend presentation/reconciliation model for anchoring live + assistant activity, settled final answers, replay, and all activity display + modes to one assistant turn; remaining hardening is tracked under #3400. - [`canonical-session-resolution.md`](canonical-session-resolution.md) — #2361 focused contract for resolving URL, query parameter, localStorage, sidebar, and compression-lineage session IDs to one canonical visible chat target. diff --git a/docs/rfcs/live-to-final-assistant-replies.md b/docs/rfcs/live-to-final-assistant-replies.md index 68e8093d..6564390e 100644 --- a/docs/rfcs/live-to-final-assistant-replies.md +++ b/docs/rfcs/live-to-final-assistant-replies.md @@ -3,6 +3,7 @@ - **Status:** Accepted (parent contract; implementation tracked in [#3400](https://github.com/nesquena/hermes-webui/issues/3400)) - **Author:** @franksong2702 - **Created:** 2026-06-03 +- **Updated:** 2026-07-16 - **Tracking issue:** [#3400](https://github.com/nesquena/hermes-webui/issues/3400) ## Background: Long-Running Sessions Are The Anchor @@ -204,6 +205,43 @@ Requirements: - Very long final answers remain complete and readable. They should not be hidden inside the activity summary or replaced by a progress/status artifact. +### Activity display and disclosure addenda + +The accepted lifecycle now has three presentation strategies over the same +assistant-turn activity data: + +- **Compact Worklog** remains the default. Its top-level Worklog is expanded + while live so progress remains visible, and the user may collapse or reopen it. + Nested tool/reasoning detail remains progressively disclosed. +- **Transparent Stream** is opt-in and renders the same ordered activity as + chronological rows. It does not create a second live or settled owner. +- **Final answer only** is opt-in (`hide_all_activity` in persisted settings). + It suppresses activity rows without deleting the persisted Anchor scene or + changing the final-answer owner. + +For normal completed turns, the settled Compact Worklog remains collapsed by +default. When a terminal error-family turn has actual Worklog content, the +Worklog defaults open so readable partial work is not hidden behind the error +outcome. The current disclosure error family is `error`, `no_response`, +`degraded`, `connection_lost`, `tool_limit_reached`, and +`compression_exhausted`; cancelled turns and the parent `interrupted` terminal +outcome keep their separate semantics. An explicit user disclosure choice wins +over these defaults and may be restored across a render rebuild. + +`degraded` and `connection_lost` are Anchor-level reconstruction/transport +outcomes defined in +[`stable-assistant-turn-anchors.md`](stable-assistant-turn-anchors.md), not +additional canonical product states in the table below. In this parent +contract, `connection_lost` is the transport-specific Anchor form of an +interruption, while `degraded` is the explicit recovery-state counterpart to the +restoring/degraded path. They use error-family disclosure only because they can +leave readable partial Worklog content without a normal final answer. + +These are presentation and disclosure rules only. They do not change reply +ownership, terminal classification, durable transcript truth, or the requirement +that all three strategies converge across live, settle, reload, session switch, +and reconnect. + ### Recovery and replay Refresh, reconnect, session switching, and replay should preserve the same @@ -473,7 +511,9 @@ for current open/merged/superseded status. | Track | Scope | Current vehicle | | --- | --- | --- | | Parent product RFC | Define the long-running live-to-final assistant reply lifecycle and review checklist. | This RFC; tracking issue [#3400](https://github.com/nesquena/hermes-webui/issues/3400). | -| First reply lifecycle implementation | Live process prose, quiet tool activity, settled activity summary above final answer, replay/reattach consistency, live-only compression status, supporting stream ownership fixes. | [#3401](https://github.com/nesquena/hermes-webui/pull/3401). | +| First reply lifecycle implementation | Live process prose, quiet tool activity, settled activity summary above final answer, replay/reattach consistency, live-only compression status, supporting stream ownership fixes. | [#3401](https://github.com/nesquena/hermes-webui/pull/3401), absorbed through [#3741](https://github.com/nesquena/hermes-webui/pull/3741). | +| Activity display projections | Compact Worklog by default, opt-in Transparent Stream, and opt-in Final answer only over the same assistant-turn data. | [#3820](https://github.com/nesquena/hermes-webui/issues/3820), [`transparent-stream-activity-mode.md`](transparent-stream-activity-mode.md), tracking issue [#3400](https://github.com/nesquena/hermes-webui/issues/3400). | +| Assistant-turn presentation ownership | Normalize live, settled, replayed, and recovered activity into one Anchor / `activity_scene_v1`, with legacy rendering limited to historical or non-anchor compatibility. | [#3926](https://github.com/nesquena/hermes-webui/issues/3926), [`stable-assistant-turn-anchors.md`](stable-assistant-turn-anchors.md); core implementation shipped through the #4411/#4564 and #5242/#5243 capstones. | | Terminal/no-final stabilization | Compression exhausted, tool-tail/no-final transcript shape, context-compaction marker suppression, terminal error routing. | [#3315](https://github.com/nesquena/hermes-webui/issues/3315), [#3316](https://github.com/nesquena/hermes-webui/pull/3316). | | Cancel ownership hardening | Frontend cancel should close its own SSE source and clear only its own busy state. | [#3344](https://github.com/nesquena/hermes-webui/issues/3344), [#3345](https://github.com/nesquena/hermes-webui/pull/3345). | | Early-cancel startup race | Backend cancel should still interrupt the worker when the SSE registry detached before startup fully settled. | [#3475](https://github.com/nesquena/hermes-webui/issues/3475), [#3476](https://github.com/nesquena/hermes-webui/pull/3476). | diff --git a/docs/rfcs/stable-assistant-turn-anchors.md b/docs/rfcs/stable-assistant-turn-anchors.md index 7fea9e30..9c522519 100644 --- a/docs/rfcs/stable-assistant-turn-anchors.md +++ b/docs/rfcs/stable-assistant-turn-anchors.md @@ -1,12 +1,35 @@ # Stable Assistant Turn Anchors for Live-to-Final Rendering -- **Status:** Proposed +- **Status:** Implemented - **Author:** @franksong2702 - **Created:** 2026-06-10 +- **Updated:** 2026-07-16 - **Tracking issue:** [#3926](https://github.com/nesquena/hermes-webui/issues/3926) - **Parent contract:** [Live-to-Final Assistant Replies](./live-to-final-assistant-replies.md) ([#3400](https://github.com/nesquena/hermes-webui/issues/3400)) - **Related RFCs:** [Transparent Stream](./transparent-stream-activity-mode.md), [Hermes Run Adapter Contract](./hermes-run-adapter-contract.md), [WebUI Run State Consistency Contract](./webui-run-state-consistency-contract.md), [Turn Journal](./turn-journal.md), [Pending Intent Controls](./webui-pending-intent-controls.md) +## Implementation Status + +The RFC's core presentation/reconciliation path is implemented. Current +`master` includes the event normalizer and registry, settled final-answer +projection, ordered `activity_scene_v1`, live Compact Worklog rendering, +Transparent Stream rendering, run-journal hydration, session re-entry, +transcript-backed scene persistence, and explicit fallback ownership for +historical or non-anchor transcripts. + +`Implemented` does not mean every adjacent hardening item is complete. The +remaining work is tracked under [#3400](https://github.com/nesquena/hermes-webui/issues/3400) +and should land as separate slices: + +- replace presentation-layer text/prefix de-echo heuristics with provenance or + event identity without deleting legitimate repeated model output; +- make newer journal/replay evidence explicitly outrank stale `INFLIGHT` + first-paint state; +- finish stable `run_id` versus transport `stream_id` separation; +- complete the Phase 6 Artifact/side-effect ownership path; +- remove each legacy fallback only after its historical transcript shape can + hydrate an Anchor reliably. + ## Problem The Live-to-Final redesign made the user-facing product model clearer: @@ -763,6 +786,11 @@ Implementation PRs may combine adjacent low-risk phases when they preserve behavior and include coverage. Settlement, reconstruction, and display-mode changes should remain independently reviewable. +Implementation reconciliation (2026-07-16): the core Phase 0-5 path has shipped. +Phase 6 and the hardening items listed in **Implementation Status** remain +follow-up work; the phase descriptions below are retained as the rollout +contract that produced the current implementation. + ### Phase 0: RFC and inventory - Land this RFC as design guidance. @@ -902,6 +930,11 @@ Any implementation PR against this RFC should answer: ## Open Questions +The first-slice and Transparent Stream sequencing questions below are retained +as historical implementation rationale. Current open hardening questions are +identity fallback depth, Artifact/side-effect ownership, and how far active-turn +DOM rebuilds can be reduced without weakening recovery compatibility. + ### First implementation slice size Should the first implementation PR stop at hidden anchor scaffolding, or should diff --git a/docs/rfcs/transparent-stream-activity-mode.md b/docs/rfcs/transparent-stream-activity-mode.md index c844b578..9909c634 100644 --- a/docs/rfcs/transparent-stream-activity-mode.md +++ b/docs/rfcs/transparent-stream-activity-mode.md @@ -1,12 +1,31 @@ # Transparent Stream — A Chronological Activity Display Mode -- **Status:** Accepted (direction confirmed by @nesquena; RFC merged via [#3862](https://github.com/nesquena/hermes-webui/pull/3862)) +- **Status:** Implemented (opt-in display mode; follow-up hardening tracked in [#3400](https://github.com/nesquena/hermes-webui/issues/3400)) - **Author:** @franksong2702 - **Created:** 2026-06-09 -- **Updated:** 2026-06-09 +- **Updated:** 2026-07-16 - **Tracking issue:** [#3820](https://github.com/nesquena/hermes-webui/issues/3820) - **Parent contract:** [Live-to-Final Assistant Replies](./live-to-final-assistant-replies.md) ([#3400](https://github.com/nesquena/hermes-webui/issues/3400) / #3401 / #3741) +## Current projection family + +The shipped `chat_activity_display_mode` setting now has three explicit values: + +- `compact_worklog` — default, results-first presentation; +- `transparent_stream` — opt-in chronological activity rows; +- `hide_all_activity` — opt-in **Final answer only** presentation. + +All three are render strategies over the same Assistant Turn Anchor and +`activity_scene_v1`; they do not create separate activity ownership or change +the final-answer boundary. Final answer only suppresses activity presentation +while preserving the persisted scene so another mode, settle, or reload can +reconstruct the same turn. + +The original proposal and rollout notes below are retained as design history. +Statements describing a missing selector, missing settled branch, or unwired +live/replay renderer describe the tree when this RFC was written, not current +`master`. + ## Problem After the live-to-final redesign (#3401/#3741), the execution trace of a turn @@ -104,21 +123,22 @@ Plus two boundaries: - **Not full transcript virtualization.** Performance hardening for very long transparent transcripts (#3714) is acknowledged but scoped to a later slice. -## Proposal +## Implemented proposal ### 1. A new, dedicated preference -A new preference, independent of `simplified_tool_calling`: +The shipped preference is independent of `simplified_tool_calling`: ```python # api/config.py preferences -"chat_activity_display_mode": "compact_worklog", # | "transparent_stream" +"chat_activity_display_mode": "compact_worklog", # | "transparent_stream" | "hide_all_activity" ``` - Default `compact_worklog` — existing users see no change. - Surfaced in Settings as an explicit **segmented choice** (not a checkbox): - **Compact Worklog** — default; results-first, supporting activity quiet. - **Transparent Stream** — advanced; every step shown chronologically. + - **Final answer only** — activity hidden; final answer remains visible. - The legacy `Compact tool activity` checkbox is marked deprecated. It is not the seam for this feature. @@ -128,6 +148,7 @@ predicate used everywhere: ```js function chatActivityMode(){ return window._chatActivityDisplayMode || 'compact_worklog'; } function isTransparentStream(){ return chatActivityMode() === 'transparent_stream'; } +function isFinalAnswerOnlyMode(){ return chatActivityMode() === 'hide_all_activity'; } ``` ### 2. Decouple "event sequence" from "grouping strategy" diff --git a/docs/rfcs/webui-run-state-consistency-contract.md b/docs/rfcs/webui-run-state-consistency-contract.md index 6a3c839f..a14bc520 100644 --- a/docs/rfcs/webui-run-state-consistency-contract.md +++ b/docs/rfcs/webui-run-state-consistency-contract.md @@ -3,8 +3,9 @@ - **Status:** Proposed - **Author:** @franksong2702 - **Created:** 2026-05-16 +- **Updated:** 2026-07-16 - **Tracking issue:** [#2361](https://github.com/nesquena/hermes-webui/issues/2361) -- **Related architecture:** [#1925](https://github.com/nesquena/hermes-webui/issues/1925), [`hermes-run-adapter-contract.md`](hermes-run-adapter-contract.md) +- **Related architecture:** [#1925](https://github.com/nesquena/hermes-webui/issues/1925), [`hermes-run-adapter-contract.md`](hermes-run-adapter-contract.md), [`stable-assistant-turn-anchors.md`](stable-assistant-turn-anchors.md) ## Problem @@ -46,6 +47,21 @@ while WebUI still has multiple overlapping state stores. - Do not reopen already-fixed narrow bugs. - Do not make this a catch-all for unrelated UI polish. +## Current implementation relationship + +Stable Assistant Turn Anchors now implement the presentation/reconciliation +portion of this contract for one assistant turn. The run journal and settled +transcript provide durable observations; the Anchor registry and +`activity_scene_v1` reconcile those observations into Compact Worklog, +Transparent Stream, or Final answer only; `S.messages`, `INFLIGHT`, renderer +caches, and DOM remain projections or recovery caches rather than independent +semantic owners. + +This RFC remains `Proposed` because its broader cross-layer contract also covers +model-context reconstruction, compression handoff, session metadata, and future +runtime-adapter migration. Shipped Anchor coverage strengthens invariants 2, 3, +and 5; it does not mark every run-state boundary implemented. + ## State Layers | Layer | Purpose | Source-of-truth expectation | Must not do | diff --git a/static/assistant_turn_anchors.js b/static/assistant_turn_anchors.js index 7c11ca1f..17c69ba0 100644 --- a/static/assistant_turn_anchors.js +++ b/static/assistant_turn_anchors.js @@ -1,9 +1,9 @@ -// Stable Assistant Turn Anchors scaffold (#3926). +// Stable Assistant Turn Anchors implementation (#3926 / #3400). // -// This file defines the current ownership inventory, event classifications, and -// small owner helpers. It does not register anchors globally. The only renderer -// wiring in this slice is settled assistant final-answer projection; live -// streaming, replay hydration, tools, and DOM ownership remain unwired. +// This file defines the ownership inventory, event normalization, registry, and +// activity-scene projection consumed by current live, settled, replay-hydration, +// and session-reentry paths. Runtime execution and transport remain outside the +// Anchor's presentation/reconciliation ownership boundary. (function(){ const ROOT=(typeof window!=='undefined')?window:globalThis;