Skip to content

fix(core): permission prompts and the agent indicator (#148) - #150

Merged
Maxaubert merged 5 commits into
mainfrom
fix/148-permission-indicator
Oct 10, 2026
Merged

Maxaubert merged 5 commits into
mainfrom
fix/148-permission-indicator

Conversation

@Maxaubert

Copy link
Copy Markdown
Owner

Closes #148.

Core change, so a change to Prism too. It reaches Prism with the core bump (core 0.28.0 to 0.28.1). Prism passes no claudePluginDir, so none of its sessions is hooked and nothing it shows changes until it ships the plugin. App 0.35.0 to 0.35.1.

What was measured

A real claude.exe 2.1.296 in a ConPTY pty with our plugin (report: research/prism-terminal/2026-10-10-permission-indicator.md):

UserPromptSubmit                         -> OSC working
PreToolUse (Bash)                        -> OSC working        (+0 ms)
title becomes idle "✳ ..."               (13-15 ms BEFORE the question OSC)
PermissionRequest                        -> OSC question       (+63-77 ms after PreToolUse; +361 ms when a hook asks)
Notification:permission_prompt           -> OSC question       (6.0-8.8 s later, only if not answered by then)
[user answers]                           -> NO HOOK AT ALL
title spinner again                      (34 ms after Yes; 2.7 s in case E), a frame about every 960 ms while the tool runs
PostToolUse                              -> OSC working        (only when the tool ENDS: 26 s later for a 25 s sleep)
Stop                                     -> OSC done

Two gaps: (1) after Yes no hook fires until the tool ends, and a hooked session ignored every spinner title, so the tab showed nothing for 26 s (the owner's 33 s command); (2) subagents' hooks write the same signal, so a sibling's tool call or the main turn's Stop took a pending Question down 1 to 4 s after it went up (case G2).

What changes (core/renderer/lib)

  • agentHookState: a new working-title step. In phase question or stopped it is Working and takes the Question down; in working, done, failed or no phase it changes nothing. Never from the answer key (Enter on No is Enter on Yes; after No or Esc the title stays ✳).
  • agentHookState: hookStep(prev, ev, seen?) and screenDecides. With a Question pending and the box still on screen (looksLikeQuestion), working and working-title change nothing, and done raises Finished UNDER the Question.
  • useAgentIndicator: a hooked session's spinner title sends working-title; the screen is read only when screenDecides says so; a spinner held by the box is read again 250 ms later, since the first spinner came 6 ms before the repaint that erased the box.
  • No plugin change: hooks.json and hook.cmd are byte for byte the same, so Stable's copy stays valid.
  • Docs: docs/regression-rules.md (#claude-hooks, #finished-and-question), CLAUDE.md item 9, the spec now records the owner's approval.

Decisions (owner, 2026-10-10, the recommended answers)

  1. Working after Yes comes from Claude's spinner title, not the key.
  2. A pending Question holds while its box is on screen. The plugin stays as it is.
  3. Finished too early while background subagents still run is out of scope: Agent indicator: Finished shows while background subagents still run #149.
  4. Auto mode's prompts from ask rules and asking hooks (cases C, E) count as the classifier criterion. On 2.1.296 the classifier never prompts: it denies, then Stop (C3).

Proof: red before, green after

e2e agentHooks, extended with case A's and G2's byte sequences, on the code before the fix (commit 43cff34):

  pass  a permission prompt raises the Question line
  FAIL  the spinner after the answer is Working again
  FAIL  Working holds through the long tool, with no hook (["question",...,"question",null,null,null,null])
  FAIL  and Stop on a background tab is Finished
  pass  a subagent asks: the Question line
  FAIL  other agents' signals leave it up while the box shows (["working","working","working","working",null,null,null,null])
agentHooks            37      4 117.9

After the fix: agentHooks 37 0.

Unit: agentHookState.timelines.test.ts replays the measured timelines A, B, C, D, E, G2 and C3 (agentHookTimelines.ts, the box state rendered from the captured bytes). On the old rules 5 of 7 fail (A, C, D, E: expected null to be 'working'; G2: at 26167 ms: expected 'working' to be 'question'); B and C3 pass both ways, as they should. The new hookStep tests: 6 of 21 fail on the old rules. All pass after.

Gates

  • npm run typecheck, npm run lint (0 errors), npm test (109 files, 1555 tests): green.
  • e2e, one at a time: agentHooks 37/0, attention 25/0, indicator 12/0, indicatorStyles 74/0. The attention and failed-line screenshots look unchanged.

Hands-on, for the owner

  • A real gh pr merge prompt: the blue line at once; Yes, and the working mark within about a second, held while the merge runs; Finished at the end on another tab.
  • The same with background agents running ("← N agents"): the blue line stays until you answer.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t

Maxaubert and others added 5 commits October 10, 2026 04:43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t
… while its box shows (#148)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t
@Maxaubert
Maxaubert merged commit 792a63b into main Oct 10, 2026
2 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 10, 2026
* docs: spec and plan for permission prompts and the agent indicator (#148)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t

* chore: bump core 0.28.1 and app 0.35.1 (#148)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t

* test(e2e): permission prompt timelines from #148 (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t

* fix(core): Working after a permission is granted, and a Question held while its box shows (#148)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t

* docs: the permission prompt rules (#148)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHHaWKR4M5QtW7Wecyuk4t

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent indicator: permission prompts often miss the Question line, and no Working mark after approving

1 participant