Skip to content

Arm queued gates' display-dependent timers only once shown - #407

Merged
TheGreatAxios merged 1 commit into
mainfrom
cl-5664-queued-gate-timers-and-operator-safety-net
Aug 8, 2026
Merged

Arm queued gates' display-dependent timers only once shown#407
TheGreatAxios merged 1 commit into
mainfrom
cl-5664-queued-gate-timers-and-operator-safety-net

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • The permission gate's goal-mode timeout and the operator gate's own new timeout/abort safety net used to arm at event-arrival instead of at display, so a gate queued behind another overlay could burn its timeout — or the run could abort it — before the operator ever saw it. Both timers now arm inside each gate's own open() callback, which runs only once the shared overlay host actually shows it.
  • ask_operator and MCP-TOFU questions previously had no timeout, no abort signal, and no auto-cancel at all, unlike the permission gate. They now get the same treatment via a shared attachApprovalBudget helper.
  • Operator gates had no queue module to register with (unlike permission requests via permissionQueue), so a gate still queued at session teardown was dropped without ever resolving. wireGates now tracks each outstanding operator gate and settles it on dispose.

Fixes CL-5664 items 1 and 3 (items 2 and 5 were already fixed in PRs #374 and #382).

Test plan

  • bun run typecheck
  • bun run build
  • bun run test (full suite via lock script) — 4179 pass, 1 pre-existing unrelated fail (lsp-availability.test.ts, missing typescript-language-server binary in this worktree)
  • New/updated coverage in src/tui-opentui/gate-wire.test.ts: queued-gate timeout deferred to display (permission + operator), operator auto-cancel on timeout/abort, queued operator gate settled on run-abort, dispose settling a still-queued operator gate, exactly-one-transcript-row invariant
  • New coverage in src/tui/request-approval.test.ts for the shared attachApprovalBudget helper
  • Five-reviewer pass (greybeard, critique, gaasbot, neckbeard, intern) — greybeard initially blocked on the dispose gap above; fixed and re-verified as ship-ready

The permission gate's goal-mode timeout and the operator gate's own
new timeout/abort safety net both used to start (or, for the
operator gate, not exist at all) the moment a request was raised,
even while it sat behind another overlay on the shared host. A
request queued behind others could burn its entire timeout, or the
run could abort, before the operator ever saw it, presenting as a
hung session with commands firing but no visible response.

The timeout now arms inside each gate's own open() callback, which
only runs once the shared overlay host actually displays it; the
abort-signal listener stays registered immediately, since a tool
having already finished is true whether or not its gate is on
screen. The operator gate gains the same abort/timeout/auto-cancel
treatment the permission gate already had, including the goal-mode
timeout and the ALS tool-budget signal, via a shared
attachApprovalBudget helper used by both the permission gate and
every operator-gate emission site (ask_operator, MCP TOFU).

Unlike the permission gate, operator gates had no queue module to
register with, so a gate still queued behind another overlay at
session teardown was dropped without ever settling its awaited
promise. wireGates now tracks each outstanding operator gate's
teardown callback and cancels every one of them on dispose, the
same guarantee permissionQueue.drain() already gives permission
requests.
@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown

CL-5664

@TheGreatAxios
TheGreatAxios merged commit 11d4c0e into main Aug 8, 2026
3 checks passed
TheGreatAxios added a commit that referenced this pull request Aug 8, 2026
Rebasing onto main picked up #407's rewrite of gate-wire.ts (display-
gated timers, onOperator safety net, attachApprovalBudget). Two of
its new comments and one test fixture still said "goal-mode timeout"
/ "goal mode" — composed correctly with this branch's removal in
substance (the timeout is generic plumbing either way) but stale in
wording now that there's no goal subsystem to name. Reworded only;
no logic changed.
@TheGreatAxios TheGreatAxios mentioned this pull request Aug 8, 2026
5 tasks
TheGreatAxios added a commit that referenced this pull request Aug 8, 2026
Rebasing onto main picked up #407's rewrite of gate-wire.ts (display-
gated timers, onOperator safety net, attachApprovalBudget). Two of
its new comments and one test fixture still said "goal-mode timeout"
/ "goal mode" — composed correctly with this branch's removal in
substance (the timeout is generic plumbing either way) but stale in
wording now that there's no goal subsystem to name. Reworded only;
no logic changed.
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