Skip to content

feat: a band above the prompt shows the guard's own state - #54

Open
rbartoli wants to merge 1 commit into
mainfrom
feat/guard-state-band
Open

rbartoli wants to merge 1 commit into
mainfrom
feat/guard-state-band

Conversation

@rbartoli

Copy link
Copy Markdown
Owner

This is steal (8), the top one, from the 2026-10-23 competitor check (internal note, Q3). Every rival that acts shows its state live; this guard showed it only in /agent-guard status.

While agents run on this machine, or the guard is asking, holding or has just refused something, a line above the prompt (the AbovePrompt band) shows it:

Usage guard · 3 of 4 agents running · 5 of 12 started in the last 10 min · last refusal 14:22: concurrency

What it shows

  • Agents running and started across every session on the machine, against their limits.
  • An open question ("asking you about starting agents" or "asking you about the context size").
  • "new agents declined until …", "agent spawns paused until …" (the fuse), and the last refusal in the window, with its rule.

How it behaves

  • Style: dim normally, bold once a limit is reached or something is held, and gone when there's nothing to say. Claude Code's [-] collapses it.
  • Stays current in a quiet session: a timer redraws it when a start, refusal, decline or pause ages out.
  • Shares the slot: it draws its line and keeps whatever the engine or other plugins draw beneath. It yields to a survey (hasSurvey).
  • Interactive only: headless sessions draw nothing.
  • Status line unchanged: plan windows and context stay there.

How it's built

  • Core: bandLine() and bandExpiry() in core/status.ts stay pure. Each Denial now records its rule, so the band can name it.
  • Adapter: refreshStatus writes the line to $.state (agent-usage-guard.band, declared in the new types/index.d.ts contract named in plugin.json) only when it changed. A ui.render hook on AbovePrompt draws from it with plain h() calls, so the module stays .ts. The band also refreshes when the session publishes its counts and when a question opens or closes.
  • Test harness: stands in for the engine's empty band, and gains questionHeld to keep a question open while a test looks.

Distribution step once this ships: a short clip of the band filling during a burst.

Test plan

  • New tests/band.test.ts, on terminal and desktop: nothing shows with nothing to say; 2 local + 1 peer agents show as "3 of 4 running · 3 of 12 started"; an open question shows while it's asked, then the decline and last refusal; it clears by itself 10 minutes later in a quiet session; a headless session draws nothing
  • claude plugin test . on 2.1.310: 108 pass. With the code stashed, the three band tests that expect a line fail.
  • claude plugin validate . --strict lists the hook and the agent-usage-guard.band state reads and writes against the contract; tsc is clean
  • Live in the real UI (2.1.310, tmux, --plugin-dir, installed copy switched off, a seeded peer record in the dev store, restored afterwards): Usage guard · 2 of 4 agents running · 2 of 12 started in the last 10 min drew above the prompt with the engine's [-]. No model turn ran.
  • CI is green

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.

1 participant