Skip to content

feat(desktop): show automatic context compaction status during streaming - #6195

Open
faga295 wants to merge 1 commit into
apache:mainfrom
faga295:feat/cotext_compaction_progress
Open

faga295 wants to merge 1 commit into
apache:mainfrom
faga295:feat/cotext_compaction_progress

Conversation

@faga295

@faga295 faga295 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Automatic context compaction can pause streaming without explaining why. Show its progress in the turn timeline, aligned with manual compaction, and settle each attempt as completed, failed, or interrupted so no stale progress indicator remains. Track attempts by compaction ID to handle repeated compactions without duplicate rows, and preserve their state across transcript replay and session continuity.

Before: Context compaction status appears only in the system message at the top of the turn.

image

After: Context compaction status also appears in the live turn timeline, making progress visible alongside streaming output.

image

Fixes #5970

Verification

  • Full workspace test build (npm run build:test) and type checks (npm run typecheck) passed.
  • npm run lint and npm run format:check passed.
  • 16 targeted test files covering compaction/recovery, runtime context history, event mapping, Host protocol/continuity/transcripts, UI buffering/projection/materialization, CLI transcripts, and desktop trace refresh: 742 passed, 3 skipped, 0 failed.
  • UI regression coverage includes repeated attempts, failure/cancellation cleanup, and the handoff from live output to persisted history. Test command output:
tests 745
pass 742
fail 0
cancelled 0
skipped 3
  • Staged Biome, ASF license header, protocol epoch, and diff checks passed. The staged Biome check was rerun successfully with Node 24 after its Node 25 invocation stalled.
  • Before/after screenshots above show the change in status placement.
  • No full workspace test suite or interactive Electron validation was performed in the automated validation run.

Protocol compatibility

Bump the Runtime Host compatibility epoch from 225 to 226: strict older peers cannot decode the new compaction lifecycle events or the additional fields on applied events.

Open PR #6176 also claims 226 for a different wire change. This branch keeps 226; if #6176 merges first, rebase this branch and bump it to 227 before merging.

Diagnostic wording

A stop while waiting for the turn ledger now records failOpenReason: 'interrupted' instead of ledger_wait_aborted in context-budget diagnostics; the corresponding skippedReasonCounts key also changes to interrupted. Consumer detachment still records ledger_wait_aborted. Neither path opens a compaction timeline row, so this changes telemetry vocabulary without changing the UI. Telemetry queries that group or filter by these reasons should account for the updated classification.

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex assisted with implementation, tests, conflict resolution, validation, and this PR description. Preserve the existing Generated-by: Codex trailer in the final squash commit.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Regression tests were run successfully; they were not rerun against an implementation with the feature removed.

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@github-actions github-actions Bot added the effort/XXL Over 2500 readable lines label Oct 20, 2026

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

Reviewed 8f29da74e73083c5f971bb815294d51c89809bc5 against main dc4515cd6e7637e8267d59cd4f71ad53f403f9e7, including the merged #6177 changes. I found no P0–P2 issue in the reviewed scope. The current trial merge is clean, and exact-head CI run 39413132017 passes.

I checked the automatic compaction lifecycle from runtime events through durable notes, Host validation/replay, and the conversation timeline. Failure and cancellation settle the attempt; terminal turns and loss of live observation stop the spinner; returning to an inactive session preserves its result. Persisted notes replace the live row without duplicating it. Manual compaction and older notes retain their separate handling. In six backend probes covering success, summarizer failure, and checkpoint-write failure with immediate and delayed event consumption, lifecycle notes stayed hidden from provider prompts and active request context appeared exactly once per request.

P3 — coordinate protocol epoch before merging. The new started/failed events and mandatory applied-event fields require the bump from 225 to 226, which passes the epoch guard. Open #6176 at 467e16e6f80c6a2759831df41837fedd8365d3a2 also claims 226 for a different wire change. Whichever merges second should use the next unused epoch after checking main.

Validation completed:

  • Normal clean root test build, workspace type checks, Desktop renderer build, lint, formatting, ASF headers, and diff checks passed.
  • Eighteen relevant original test files: 761 passed, three skipped, no failures. These cover compaction/history/request context, protocol, Host projection/continuity/transcript paging, UI buffers/materialization, CLI transcript, and trace refresh.
  • Sixty Chromium scenarios passed across English, Simplified Chinese, and Traditional Chinese at 1280px and 480px widths, including repeated attempts, observation loss, session switches, background completion/failure/cancellation, and durable reconciliation. Replacing only the UI projection/materialization with main's versions removes the new timeline row as expected.

The browser checks used production conversation components and Desktop event handling with controlled events. They do not cover native Electron, Windows, paid model calls, or the full repository suite. Chinese strings and state were checked in the DOM; this environment lacks CJK fonts for a typography assessment.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

Reviewed range: dc4515cd6 (merge-base = current main, includes #6177) .. 8f29da74e73083c5f971bb815294d51c89809bc5 (single commit, 36 files). First review of this head from this agent; no prior findings of mine to carry forward.

Verdict: no P0–P2 defects found.

What I checked:

  • Runtime lifecycle. presentCompactionAttempt opens a row only when the summarizer is actually called (and only if the turn hasn't already been aborted), settles it at most once, and makes every callback fail-open. Failures that happen before the summarizer runs (ledger wait/read, head anchor) and the summarizerFailure latch open no row, so you don't get one row per over-window step. The thrown-exception path settles an open row as interrupted/unexpected_error. The new abort checks after planning and before the checkpoint write mean a cancelled fold is not persisted or applied, and a user stop is no longer latched as summarizer_failed. Proactive, pre-turn (step 0) and reactive overflow paths all share one CompactionLifecycle. Explicit compaction (kernel) now tags its notes scope: 'turn', which keeps them out of the timeline marker reader.
  • No prompt leakage or duplicate context. The started/failed/applied events map to system_note RuntimeEvents with modelVisibility: 'hidden'. buildRuntimeEventModelReplayPlan skips hidden events, and isHistoryCompactContentEvent excludes them from fold coverage and currency checks. So the started note that lands in the turn ledger during summarize cannot change coverage or source digests. #6177's runtime-context replay only reaches host text events that carry runtimeContextName, so the two changes don't interact. The usage-boundary readers (compactionAppliedAtBefore, desktop latest-request-usage) still key on context_compaction_applied/context_compacted only.
  • Duplicate failure notes. The mid-turn failed event writes its failed_open note when the failure is decided and raises the settlement flag, so the once-per-send fallback does not write a second one. A priorReplay failure and a later step failure produce two distinct notes. The renderer suppresses only the step-scoped one (matched by attempt id) and keeps the other, which is correct.
  • Host persistence, forwarding and replay. Root-turn forwarding admits step starts. The continuity projector drops events that have no attempt identity. The Host projector seeds running attempts from the transcript filtered to the root Turn, re-emits them in seedActive, and clears them when a terminal frame arrives, a new Turn starts, or the Turn terminates. The shared transcript exposes only scope/compactionId/failOpenReason (there is a test for this).
  • Renderer. Durable and live rows are deduplicated by the compaction\0<id> key. A terminal state never downgrades back to running. A running row on a recorded terminal Turn settles from the Turn status. Live-turn release waits until the durable markers match. Compaction rows are excluded from answer selection in foldTimeline.
  • i18n. contextCompactionInterrupted is added to en, zh-CN and zh-TW; contextCompacting already existed in all three. The CLI note text is updated to match.

Findings:

  • P3 (coordination): compatibility epoch collision. This PR bumps RUNTIME_HOST_COMPATIBILITY_EPOCH from 225 to 226, which is justified: the closed decoders gain two event types and two required fields on the applied frame, and a new stored system-note kind. However, open PR #6176 also sets 226. Whichever lands second needs to rebase to 227.
  • P3 (behaviour note): changed diagnostic reason on stop. A stop during the ledger wait now records failOpenReason: 'interrupted' in the context-budget diagnostic instead of ledger_wait_aborted; a detached consumer still records ledger_wait_aborted. No row is opened in this case, so nothing changes in the UI. It is a telemetry vocabulary change worth calling out in the PR description.

Mergeability and CI: GitHub reports MERGEABLE (merge state BLOCKED, awaiting review). audit, label and test all pass on this head. The base equals current main, so no rebase is needed apart from the epoch coordination above.

@Astro-Han

Copy link
Copy Markdown
Contributor

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

Heads-up on the Runtime Host compatibility epoch: #6176 has merged, so main is now at 226 (RUNTIME_HOST_COMPATIBILITY_EPOCH = 226 on 6104132). This PR changes the Host protocol and currently declares 226, so it needs the next unused value (227 at the time of writing; #6195, #6206, #6091 and #6163 are all in the same position, and whichever merges first takes 227). Please rebase, bump the epoch and add the history comment in packages/runtime-host/src/protocol/index.ts.

Track compaction attempts through start, apply, failure, and interruption, and preserve their state across transcript replay and session continuity.

Generated-by: Codex
@faga295
faga295 force-pushed the feat/cotext_compaction_progress branch from 8f29da7 to 4f9a876 Compare October 21, 2026 14:16
@faga295

faga295 commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

@Astro-Han Thanks for your review! All comments have been addressed:

  • P3 (coordination): Bumped the compatibility epoch to 227 to resolve the collision.
  • P3 (behaviour note): Documented that stopping records interrupted, while detachment retains ledger_wait_aborted. Telemetry only; no UI change.

@faga295
faga295 requested a review from Astro-Han October 21, 2026 15:14

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.

Incremental review at 4f9a8762469721463b24a24b629f77e083f755c1, following 8f29da74e73083c5f971bb815294d51c89809bc5. I found no new P0–P2 issue. The rebase now includes main's epoch 226, preserves its existing protocol entries and assigns 227 to the compaction wire change. The static merge with current main 0d19f242336a31e8aeb300372d3d3c896b1e99ef is clean.

I separated the author's changes from main with git range-diff and file comparison. Of the 37 paths in the old/new PR changes, 34 are byte-identical to the previously reviewed version. The remaining files are the epoch/comment update, an assistant README epoch reference, and materialize.ts. Applying only main's three root-user/steering edits to the old feature file reproduces the new materialize.ts byte-for-byte; the compaction implementation itself is preserved.

Validation on this head:

  • The normal clean root test build, normal production renderer build, Biome on 36 applicable changed files, git diff --check, and the protocol guard passed. The guard reports 226 → 227.
  • 19 original test files: 772 passed, three skipped, no failures. These cover runtime compaction/context history, event mapping, Host protocol/projection/continuity/transcript paging, UI buffers/materialization/steering order, CLI transcripts and Desktop trace refresh.
  • All six actual-backend prompt checks passed again: success, summarizer failure and checkpoint-write failure, each with immediate and delayed event consumption. Lifecycle notes stay hidden from provider prompts, and the active request context appears exactly once per request.
  • All 60 Chromium scenarios passed across English/Simplified Chinese/Traditional Chinese and 1280px/480px widths, using production conversation components and Desktop event handling with controlled events. They cover repeated attempts, observation loss, Session switching, background outcomes and durable reconciliation. Replacing only UI projection/materialization with current main's implementations removes the new attempt timeline row, as expected.
  • Nine additional resumed-Turn checks combine the inherited steering fix with completed/failed/interrupted compaction in all three locales. The steering message stays at its event position, with no synthetic opening prompt or duplicate compaction row.

P3 — coordinate epoch 227 before merging. Current open #6091 (efbe29e6), #6192 (07c7a8bb) and #6197 (0bcb095a) also claim 227. Whichever protocol change lands first consumes that value; later ones need the next unused epoch and another check. The PR description's 225→226 / open-#6176 explanation is now stale and should describe the current 226→227 situation.

Exact-head CI test passes. The separate dependency audit fails on the existing MCP client/server, follow-redirects and Hono versions. The dependency versions, lockfile and audit script match current main; this is not a demonstrated new dependency regression, and I do not describe all checks as green.

I did not build the merged tree, repeat the full workspace type-check command, run native Electron/Windows or authenticated paid providers, or execute the complete repository suite. The browser checks establish DOM text, state and geometry; this environment's missing CJK fonts prevent a typography assessment. The previously documented telemetry-reason change remains outside this rebase increment.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XXL Over 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(desktop): show automatic context compaction status during streaming, consistent with manual compaction

2 participants