Repository navigation
feat(status): OSC 7501 program status — working state, exact waiting dots, heuristic fallback - #189
Merged
Conversation
…dots, heuristic fallback Support the Program Status Protocol (OSC 7501) so programs report their own state. Part 1 of #154. - terminal-init.js: OSC 7501 handler (query -> programStatusProbe, report -> programStatus) and an observe-only OSC 133 A handler (promptStart). - TerminalBridge answers the `OSC 7501 ; ?` probe with fixed, app-authored bytes, encoded as win32-input-mode key events: the inbox conhost drops OSC sequences written to the ConPTY input as plain VT (measured). - Services/ProgramStatusPayload: strict WPF-free parser/validator (alphabet, base64 + UTF-8, control chars, spec limits; bad reports dropped whole). - Services/ProgramStatusRecords: record tree with replace/clear/eviction, exit lifetime, acknowledge, and blocked > working > error > done > idle. - SessionViewModel maps the aggregate: working -> new pulsing "working · N%" indicator (sidebar + toolbar), blocked+permission -> approval, other blocked -> input, done/error -> attention badge with a rate-limited toast. AlertDetector stands down once 7501 is seen; user interaction acknowledges done/error but keeps live states. - Docs: CLAUDE.md section incl. the measured ConPTY limitation (conhost answers DA1 itself, so Claude 2.1.319's probe still settles to "no"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
… attention, re-arm Review fixes for the OSC 7501 program-status work (#154 Part 1). - Probe reply OFF by default (AppSettings.AnswerProgramStatusProbe). Under the inbox ConPTY it always loses to conhost's own DA1 answer and only reaches the program as late stdin starting with ESC. When enabled, ProgramStatusProbeGate requires an exact "?" query, win32-input-mode requested by this session's ConPTY (ESC[?9001h/l tracked on output), 1 reply per 5s, 3 per session; the write goes to the thread pool. Reports are always parsed. - Attention judged per record: a root done/error/blocked badges and toasts even while a working child holds the aggregate; the badge clears only when no record is in an attention state. - Re-arm the heuristic when the store empties via clear / prompt start / exit, plus a sidebar "Clear status" item. Not on acknowledge. - Exit race: working/blocked/idle reports after PTY exit are ignored. - Parser: id segments and app use [A-Za-z0-9_.+-]{1,32} (bad app = absent), a key over 16 bytes drops the report, format chars stripped by rune (tag block), U+2028/U+2029 rejected. - Working pulse runs only while visible (IsVisibleChanged, Loaded/Unloaded, minimize). - Acknowledge on real key events (onKey) or focus, not on every onData; allocation-free per-keystroke guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
Builds on the bundled ConPTY: OpenConsole passes OSC input through and forwards DA1 to xterm.js, so the raw reply reaches the program in order. Measured with real claude 2.1.319 behind it: programStatus=yes, and a trivial prompt produced idle -> working -> done reports. - AnswerProgramStatusProbe becomes bool?: null (default) = answer when the session's PTY uses the bundled ConPTY, not on inbox; true/false force it. - Bundled: raw ESC]7501;?ESC\ reply, no win32-input-mode requirement. Inbox (forced): win32-input-mode encoded, only after ?9001h, as before. Exact "?" query, 5s rate and 3-per-session cap kept for both. - The reply is written synchronously on the UI thread, deliberately: it must reach the PTY before xterm's DA1 answer, which the next 'input' message writes on the same thread; a pool write races it. - Tests for the enable rule, raw reply, and gating on the bundled path; CLAUDE.md, docs/shell-integration.md and README updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
…Off)
Development builds saved "AnswerProgramStatusProbe": false as a plain bool
meaning "experimental, off"; under the later nullable meaning that read as
"force off" and would have silently disabled the probe answer on the bundled
ConPTY. The setting is now AppSettings.ProgramStatusProbe, an enum
ProgramStatusProbeMode { Auto, On, Off } defaulting to Auto, so the stale key
is ignored. Tests cover the stale-key case and the round trip; CLAUDE.md
updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
Closed
5 tasks
Merged
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #154 (Part 1). Part 2, the timeline and dashboard, is still open. Replaces #187. That branch had to be rebased onto the bundled ConPTY, and force-pushing it wasn't allowed, so the rebased branch is pushed here as
-v2instead.Stacked on #188 (bundled ConPTY). The base is
feat/bundled-conpty, so the diff here shows only the status work. When #188 merges, GitHub retargets this PR tomain.Adds the Program Status Protocol (OSC 7501), so programs can report their own state: working (with progress), blocked on permission or input, done, or error. The existing regex detection stays as the fallback.
Claude Code reports out of the box (with #188)
OSC 7501 ; ?query with the raw reply. In the real app the trace shows that reply written just before xterm's DA1 answer, and Claude logsprogramStatus=yes (probe: OSC 7501 reply).idle → working → donereports.ProgramStatusProbe(Auto / On / Off, default Auto). Auto answers only on the bundled ConPTY. On the built-in ConPTY, conhost answers DA1 first, so a reply would arrive late as unsolicited input.?query is answered;What changes
clearalso removes children, there is a 256-record cap with eviction, records expire on exit and prompt start, and attention transitions are tracked per record.⟳ working · 40%in the sidebar and⟳ 40%on the toolbar, animated only while visible.donestill badges while a background child is working.state.json.Reviews
Two read-only review rounds. Fixed as a result:
done;Tests
942 unit tests pass (this branch includes #188).
Manual verification
claudesession and give it a prompt. Expect⟳ workingin the sidebar and toolbar, then the attention badge when it finishes.$e=[char]27:"$e]7501;state=working:progress=40$e\". Expect⟳ working · 40%.🤖 Generated with Claude Code
https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX