Commit Graph
13091 Commits
Author SHA1 Message Date
Brennan Benson e4cd14d914 Remove legacy OS file-drop routing (STA-6940 PR6/6) (#26385)
* feat(file-drop): add element owner preparation plumbing

* Fix terminal and chat file drop destination ownership

* fix runtime terminal drop ownership and queued chat retries

* fix(file-drop): preserve feedback acceptance and destination ordering

* fix(file-drop): attach chat and composer files at the drop surface

* fix(file-drop): preserve project destinations and live chat availability

* fix(file-drop): keep path resolution in filesystem namespace

* test(file-drop): use filesystem path bridge in PR3 fixtures

* fix(file-drop): bind terminal drops to pane elements

* fix(file-drop): compare terminal pane identity across public views

* test(file-drop): align composer lifecycle with element-owned drops

* Fix interrupted chat composition and refuse unused quick-create drops

* Type the quick-create drop regression transfer

* fix(file-drop): let the explorer, project sidebar, tab strip and editor own OS drops

STA-6940 PR5. The file explorer tree, the project sidebar, each editor
group's tab strip and its editor area now take OS file drops on their own
element through the shared owner hook, with identity from their own render
(the explorer's shown workspace and target row, the tab strip's and editor
group's worktree and group) instead of the active worktree. The explorer and
sidebar broadcast subscribers and their legacy drop markers are deleted;
editor-open moves out of useGlobalFileDrop into editor-dropped-file-open,
which the legacy unmarked-chrome route still uses until PR6.

* fix(file-drop): keep editor delivery tied to its destination group

* fix(file-drop): guard delayed opens and share floating ownership

* fix(file-drop): remove legacy OS drop routing (STA-6940 PR6/6)

* test(file-drop): finish owner test and comment cleanup

* Clarify dropped-file default editor destination

* Retain UI test namespace for terminal resume coverage
2026-10-07 23:11:37 -07:00
Brennan Benson 2caea6ce93 feat(omp): open OMP in the structured chat over ACP (#26401)
* feat(omp): open OMP in the structured chat over ACP

OMP joins Grok and OpenCode on the ACP lane: `omp acp`, with the user's
environment passed through and the chat pinned to PI_CODING_AGENT_DIR
(default ~/.omp/agent), the directory OMP's terminal chats read. A create
and every launch ask `omp --version` of the binary the Command setting
resolves to; stable releases from 17.0.5 run the chat, older ones keep the
terminal-backed chat. Like every ACP agent it runs only with the updated
structured native chat setting on.

* fix(omp): show a shell command's output and exit code in its row

OMP's ACP server sends a command's result as rawOutput {content, details}
with a non-zero exit at details.exitCode, and repeats it as content behind
a "$ <command>" echo. The shared reader takes content text first, so the
row's output began with the command and carried no exit code. The OMP
dialect drops the echo, moves the result text to stdout without OMP's
"Wall time" and "Command exited with code N" notice lines, and maps
details.exitCode. Recordings of omp acp 17.0.5 (exit 3, exit 0, Stop
mid-command) replay through the adapter.
2026-10-07 23:10:30 -07:00
Brennan Benson b1e0092d5d feat(opencode): open OpenCode 2.x in the structured chat too (#26395)
* feat(opencode): run OpenCode 2.x in the structured chat too

`opencode acp` on stable 2.x starts its own private `opencode serve --stdio`
child with the chat's environment and ends it when stdin closes, so the
chat's account pin reaches it just as it does on 1.x. Admit stable 2.x from
2.0.14 beside stable 1.x from 1.18.31; pre-releases, older releases, and
other major lines keep the terminal chat. The `opencode2` agent is unchanged.

Restart recovery already reads a 2.x session's own tables first; tests now
cover a database an upgrade left with both generations, and one whose 2.x
message table has an unknown shape (nothing found, no error).

* fix(opencode): show OpenCode's own permission option names

* test(opencode): run the 2.x recovery tests with the real-SQLite Node project
2026-10-07 23:09:40 -07:00
Brennan BensonandClaude 4bd4f8cf06 feat(native-chat): show each interrupted chat's workspace as its read-only sidebar card (#25652)
* feat(native-chat): show each interrupted chat's workspace as its read-only sidebar card

The resume-on-restart dialog listed workspaces as a bare name and glyph, so users could not
tell their sessions apart. It now renders each workspace with the sidebar's own WorktreeCard
in a new read-only mode, with the offered chats in place of its live agent rows, and nests
child workspaces under a listed parent the way the sidebar does. The dialog is wider and the
chat rows use the sidebar's compact agent row layout.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(native-chat): name the nesting helper for what it returns

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(native-chat): resume dialog cards show no status

The dialog's cards stand in for the chats before the restart, so the sidebar's live status
(Failed, now Interrupted) read as a verdict on chats the dialog offers to resume. A read-only
card shows no status, and in the new card style its PR joins the badges because the status
lane that normally holds it is gone.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(sidebar): a read-only card is inert and shows no live state, whatever its caller passes

A read-only card stayed inert only because each control checked `readOnly` on its own and the
caller left out the handlers that would turn the rest on: passing `onLineageToggle` put a live
child-workspaces toggle on it. It also still painted live state over the resume dialog's chat
rows: the sleep dim, the "Queued for deletion" overlay (which blocked unticking a pre-ticked
chat) and the prompt-cache countdown.

WorktreeCard now reduces a read-only card's props to what it pictures (every handler, selection
and active flag dropped), and the controller resolves `readOnly` once into what the views
already read: card properties without status, ports or live agents (and with the host), no
sleep or delete state, no cache countdown, and one `interactive` flag for its own controls.
A contract test renders a read-only card with every feature and handler on in all three card
styles and fails on any control outside the caller's rows or any live state.

* fix(native-chat): nest and indent the resume dialog's child workspaces as the sidebar does

A child workspace whose parent has older metadata with no host id stayed at the top of the
dialog, though the sidebar nests it: the dialog copied a strict same-host filter, while the
sidebar treats a hostless row as belonging to the host. The nesting rule now lives in one
sidebar lineage helper, getWorktreeLineageAncestorsOnHost, which scopes by host the way the
sidebar's lineage inputs do.

In the legacy card style a nested child was inset for its parent's depth instead of its own,
so it sat one sidebar step too far left (0px instead of 14px), outdented into the parent's
padding. Each child is now inset for its own depth, as a sidebar row is.

A groups-level test renders real sidebar cards from the store, with the child nested under a
hostless parent, and checks every offered chat's checkbox renders and the legacy inset.

* fix(native-chat): the resume dialog places every workspace even if lineage loops

Nesting followed each workspace's parent chain, so two workspaces listed as each other's
ancestors (possible only when two hosts report opposite lineage for the same ids) were placed
under no top-level entry and vanished, while their pre-ticked chats would still be resumed.
The loop is now cut where the walk first comes back, so every workspace renders.

* fix(native-chat): keep "Don't ask again" above the resume dialog's buttons when narrow

Below the small breakpoint the footer stacks bottom-up, so the option moved into it rendered
under Resume and Dismiss all. It now reads top to bottom: the option, then the actions; wider
windows keep the single row.

* test(sidebar): import the card statically in the read-only contract test

Its dynamic import ran in a beforeAll with a 20 s timeout, below the suite's 60 s hook timeout,
and timed out under parallel load, which skipped all six contract tests.

* fix(sidebar): legacy lineage children step in as far without a status lane

Legacy cards outdent their nested child list by 1.125rem to pull it back over the 22px status
lane. A card without that lane (a read-only card in the resume dialog, or the sidebar with the
Status property off) kept the outdent, so a child's title sat 3px right of its parent's instead
of 25px. Without a lane the list now sits at ml-1, which gives the same 25px step (39px at depth
2). Cards with a status lane, the default sidebar, render exactly as before.

* fix(native-chat): nest resume dialog children by the sidebar's own row rule

Round one nested a child under a parent whenever either had no host id, but the sidebar's row
builder looks a parent up on the child's own host, so a row with no host id nests only under a
parent with none either. The dialog showed a parent/child pair nested that the sidebar shows side
by side.

The row builder's parent lookup is now one function, getSidebarLineageParent, and the dialog
walks ancestors with it (getSidebarLineageAncestors) over the same non-archived rows and cycle
set. The chat's workspace is still found on its host, falling back to a row with no host id.
A test checks the four host pairings against the real row builder, and the dialog test renders
each pairing with every chat's checkbox.

* test(sidebar): pin child-workspace indent with and without a status lane

Covers legacy, compact and new card styles with the Status property on and off. With Status on,
the legacy and compact sidebar keep their outdent unchanged; with it off they now step children
in by the same amount; the new card style is identical either way. The file now imports the
card statically, since its 15 s per-test dynamic import timed out under load.

* fix(sidebar): a read-only card's child workspaces step in as the sidebar's do

The legacy outdent on a card's child list cancels its status lane, which in the sidebar is the
unread button plus the row gap: 1.125rem, exactly the outdent, not the 22px the previous fix
assumed. Its ml-1 for a card with no lane put the resume dialog's children 4px deeper per level
than the sidebar's (25px against 21px). With no lane there is now nothing to cancel and no
margin, which gives the sidebar's 21px (35px at depth 2).

Status is a fixed card property, so every live card has the lane: only a read-only card takes
this branch, and the live sidebar is unchanged. The tests now pin the outdent for live legacy
and compact cards and no margin for a read-only one, instead of an unreachable Status-off state.

* test(sidebar): a read-only card never carries main's multi-selected marker

Main now styles a multi-selected card through data-worktree-card-selected. The contract test
passes isMultiSelected, so it now asserts the marker stays off a read-only card, and drops the
context-menu event constant main removed from that module.

* fix(sidebar): preserve quiet read-only card geometry

* fix(native-chat): match resume cards to sidebar rows

* fix(sidebar): preserve passive SSH identity on read-only cards

* fix(native-chat): keep resume focus and folder host identity

* fix(native-chat): remove resume dialog list border

* fix(sidebar): keep passive SSH pills static

* fix(native-chat): align resume card vertical spacing

* fix(native-chat): preserve cache-only card header spacing

* fix(native-chat): lay the resume dialog out as a checkbox-column list

Every row of the resume list (Select all, workspace, chat) now keeps its
checkbox in one left column; nesting indents only the content after it,
and a divider separates every row. A workspace checkbox is tri-state over
its own chats and those of the workspaces nested under it; Select all
heads the list with an "N of M selected" count. Failures a retry cannot
fix stay out of both. Up/Down move between the list's checkboxes.

The dialog no longer renders the sidebar's WorktreeCard, so the read-only
card mode and the sidebar changes that only served it are reverted to
main. The sidebar lineage helpers stay: the dialog still nests child
workspaces by the sidebar's own rule.

* fix(native-chat): name SSH hosts by their saved label in the resume dialog

The workspace row's host chip spelled an SSH host with its raw target id
(e.g. ssh-1728291234567-abc12d) because it never got the sidebar's host
labels. It now takes them from useSidebarHostScopeOptions, as the delete
dialog does, so the chip reads "devbox" like the sidebar.

Also translates the dialog's five new strings in es, fr, ja, ko and zh.

* fix(native-chat): group the resume list in bands and let a project select its chats

The resume list now follows the common grouped-list pattern: each
workspace heads its chats with a full-width tinted band (lighter for a
nested child, at its own indent), chats are split by plain hairlines, and
groups meet without gaps or rounded row corners.

The project row gets a checkbox in the same left column, tri-state over
every eligible chat in the project (nested workspaces included, failures
a retry cannot fix left out) with an "x of y" count, on a band a step
stronger than a workspace's.

The list takes arrow keys, so it is now a named group (role="group").

* fix(native-chat): no project row for workspaces the resume list cannot place

Workspaces the store cannot place in a repo were grouped under a header
with an empty name, so the new project checkbox was announced as "Select
all chats in ". Main and the earlier heads showed that header as a bare
folder glyph with no name, and there is no id to fall back to. Those
workspaces now get no project row; their own rows and Select all still
cover their chats.

* fix(native-chat): lay the resume list out as nested workspace boxes

Brennan chose the nested-box layout without row dividers. A project is a
tinted band; each workspace is a bordered, rounded box one step in from
its project, holding its header band and its chats, and a child
workspace's box sits inside its parent's, after the parent's chats, at
the parent's chat indent. The boxes are drawn in the content area only,
so every checkbox stays in the one left column outside them. Rows carry
no dividers; the box border is the only line.

* fix(native-chat): show the resume list as a tree

Brennan chose the Resume Tree. The list is now a tree: machine, then
project, then workspace (a child workspace is a node inside its parent,
after the parent's chats), then the chats. Every row keeps its checkbox
in one left column, then an 18px indent per level, a disclosure arrow
(an empty slot on a leaf), the icon and label, and its count. Levels read
apart by icon and weight; there are no boxes, bands or row dividers, only
the divider under Select all.

The machine level shows only when the machine is not obvious (a remote
host, or chats on more than one), named with the sidebar's host labels
and an SSH chip; it replaces the per-workspace host chip. Chats are
grouped per machine first, so one workspace id on two hosts stays two
nodes.

Every node is tri-state over the eligible chats under it, through the
existing per-chat onToggle. Nodes start expanded; collapsing is local to
this opening and keeps the selection. The list is a role="tree" of
leveled treeitems: Up/Down move between checkboxes, Left collapses and
Right expands the focused node.

* refactor(native-chat): read each resume chat through one key helper

Every per-chat read in the resume tree (its tick, its toggle, its
failure, and each group's coverage) now goes through chatState, so a
later change of chat key stays in one function. Tests pin the machine
level's host rules: a runtime host gets a machine node but no SSH chip.

* fix(native-chat): make the resume tree's keys work from its Tab stop and after a click

Tab lands on the tree itself, where the arrow keys did nothing. Down and
Home now enter at the first checkbox, Up and End at the last; Home and End
also jump to the ends from a row.

Clicking an arrow with the mouse left focus on the arrow, where no tree
key works. After a collapse or expand click, focus now moves to that
row's checkbox, or to the tree when the checkbox is disabled.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-07 23:06:45 -07:00
Brennan Benson 4da1324b5a test: isolate hook fixture connections from fake timers (#26369) 2026-10-07 23:01:12 -07:00
Neil 10a2a6c2af perf: reuse Markdown fence scans across sibling toggles (#26324) 2026-10-07 22:53:01 -07:00
Neil 665fbc4a83 Release clipboard previews when the chat composer closes (#26234)
* Release native chat clipboard previews when the composer unmounts

* Assert late previews retire before explicit cleanup
2026-10-07 22:50:09 -07:00
Neil b41e2730db Persist multiple workspace references with atomic edits 2026-10-07 22:44:25 -07:00
Neil d9ab505ea5 perf: skip assembling deferred Codex text checkpoints (#26199) 2026-10-07 22:44:17 -07:00
Neil b4e99fcea2 perf: group Space decision inputs by workspace (#26297) 2026-10-07 22:42:14 -07:00
Neil 8155e2e69f perf: preserve unrelated authorization roots after desktop removal (#26294) 2026-10-07 22:42:11 -07:00
Neil 9f64453943 Release feedback requests after response handling completes (#26274) 2026-10-07 22:42:08 -07:00
Neil 408aa1383a fix(explorer): reject foreign watch events before deferring (#26265) 2026-10-07 22:42:05 -07:00
Neil 8060ca5bfa perf: persist completed notebook runs in one document update (#26254) 2026-10-07 22:42:01 -07:00
Neil 8e22ad2d0a Scope completed worktree removal authorization refresh to its repository (#26253) 2026-10-07 22:41:58 -07:00
Neil 4d7193c34d perf: skip image prewarming parse for image-free markdown (#26240) 2026-10-07 22:41:55 -07:00
Neil ad0a5ad7f7 Abort rejected optional OpenCode billing requests (#26236) 2026-10-07 22:41:52 -07:00
Neil 2d1ab8b7cc Avoid refreshing GitHub accounts for repository name edits (#26228) 2026-10-07 22:41:49 -07:00
Neil c5767f0277 perf(skills): index placements within each deletion plan (#26223) 2026-10-07 22:41:46 -07:00
Neil 7e60664ced fix(browser): retire cookie snapshots when preparation fails (#26218) 2026-10-07 22:41:43 -07:00
Neil efb071b286 Release completed agent-browser helper drain timers (#26210) 2026-10-07 22:41:40 -07:00
Neil 602e7a3176 Stop repeated GitLab detail requests on mobile (#26197)
* Stop unchanged GitLab task detail replies from refetching

* Reuse approved RPC fixture for task detail tests
2026-10-07 22:41:36 -07:00
Neil 761092081d Avoid rebuilding committed mobile files while typing (#26196) 2026-10-07 22:41:33 -07:00
Neil f4c7121545 Use browser crypto to speed up mobile image fingerprints (#26170)
* perf(mobile): use browser crypto for image fingerprints

* Document web image fingerprint platform override

* fix(mobile): share the image fingerprint domain
2026-10-07 22:41:30 -07:00
Neil 727921007f fix(skills): cancel unread package download responses (#26169) 2026-10-07 22:41:27 -07:00
Neil a6c853ab6b perf(chat): size recovery batches without prefix serialization (#26160) 2026-10-07 22:41:23 -07:00
Neil 7c0e76cb1a perf(mobile): release closed Markdown document cache entries (#26159) 2026-10-07 22:41:19 -07:00
Neil 586e6bc2e7 perf: scan only new text for live agent log record boundaries (#26132) 2026-10-07 22:41:16 -07:00
Neilandm4air e86239406e Abort failed runtime downloads after cleanup (#26269)
* fix(ssh): abort runtime download requests after failure

* Keep region correction fixtures past initial control grace

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
2026-10-07 22:28:57 -07:00
Neil 61de2d8ec8 test: load GitHub operations from their public modules (#26384)
* test: load GitHub operations from their public modules

* fix: sync required English entries after branch toast removal
2026-10-07 21:44:12 -07:00
Neil 00a82505c4 test: speed terminal comparisons and retry policy checks (#26396) 2026-10-07 21:01:48 -07:00
Jinjing 265c62645d Allow large markdown documents with HTML in rich mode (#26331)
* Allow large markdown documents with HTML to open in rich mode

Documents over 50,000 characters that contained HTML were always blocked from rich mode, because the round-trip check that proves the HTML survives is too slow to run synchronously on large files. Large documents now get a cheaper check that encodes HTML as passthrough nodes and validates the result without DOM parsing, so anchors, tables and other HTML in big notes stay editable. Large documents that need DOM parsing, such as editable toggles, still fall back to the block.

- Move the raw HTML node definitions into raw-markdown-html-nodes.ts so the passthrough check can reuse them without an import cycle.
- Add getRichMarkdownPassthroughOutput, which parses and serializes without creating an EditorView.
- Compute markdown fence ranges once per document and share them across details matches, instead of rescanning for each block.
- Keep line-start tracking correct after inline and details passthrough, so block HTML that follows them is still recognized.

* improve code
2026-10-07 21:00:19 -07:00
Neil 8b20d21138 Remove local branch deletion success toast (#26422) 2026-10-07 20:52:21 -07:00
Jinwoo Hong d0e729ca01 fix(claude): drop the repeated sign-in line in the account menu and name the right Settings page (#26405) 2026-10-07 23:38:52 -04:00
Kelvin AmoabaandBrennan Benson 4f4f021f8a feat(native-chat): quote a selection from an agent reply into the composer (#26018)
* feat(native-chat): quote a selection from an agent reply into the composer

* fix(native-chat): label the selection action "Add to chat"

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-07 20:08:08 -07:00
Brennan Benson 8fdad2a3af fix(claude): activate account profiles and remove credential replay (Step 4 of 4) (#24434)
Each saved Claude account now runs in its own CLAUDE_CONFIG_DIR folder, so Claude renews each login itself and switching no longer replays a copied credential. A claude shell function routes every launch to the selected account; the terminal daemon protocol moves to 42 so new terminals get it. After updating, each saved account signs in once: typed claude shows Claude's own sign-in, old terminals show an in-app banner, chats and the status-bar menu offer Sign in, and a one-time toast explains it. Orca prints nothing into terminals.
2026-10-07 22:51:34 -04:00
Brennan Benson 7c13552c93 Label a message stopped before the agent began on it plainly as "Stopped" (#26381)
* fix(native-chat): label a message stopped before the agent began on it plainly as "Stopped"

* fix(native-chat): word the row after a stopped message "Stopped manually"
2026-10-07 19:46:33 -07:00
Neil 316822f2eb ci: skip cache warming for cache-test-only changes (#26399) 2026-10-07 19:46:10 -07:00
Neil acd298a263 feat(runtime): isolate the server behind a compatibility launcher (#26374)
* feat(runtime): isolate the server behind a compatibility launcher

* fix(runtime): preserve server crash exit semantics
2026-10-07 19:32:58 -07:00
Neil 0d246a68d1 Use native Base64 encoding for mobile image bytes when available (#26165) 2026-10-07 19:30:26 -07:00
Neil 7cd92a3d9d Avoid rescanning accumulated notebook stream output (#26123) 2026-10-07 19:27:51 -07:00
Neil 846caf0cec Scan Markdown inline-code spans once when highlighting links (#26126) 2026-10-07 19:23:51 -07:00
Neil 5a59710699 Skip repeated ANSI parsing scans for plain notebook output (#26124) 2026-10-07 19:23:19 -07:00
Neil 5fb18f33d8 Run only the intended performance contract suites (#26121) 2026-10-07 19:22:57 -07:00
Neil 56017af779 Avoid repeatedly extracting source text for the copy-context hint (#26115) 2026-10-07 19:22:22 -07:00
Neil b0fbcfd6a7 test: age relay correction controls through live heartbeats (#26389) 2026-10-07 18:52:30 -07:00
Kelvin AmoabaandBrennan Benson 7c88ab7dd5 feat(native-chat): number keys and auto-advance for questions (#26288)
* feat(native-chat): number keys and auto-advance for questions

A single-select pick moves on after a short beat, on desktop and phone.
Structured chats hold the card while a response is with the host.

* test(mobile): compare mocked host components by name so the ask test typechecks

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-07 18:30:47 -07:00
Brennan Benson d1e7d15f4c fix(file-drop): explorer, project sidebar, tab strip and editor own OS file drops (STA-6940 PR5) (#26133)
* feat(file-drop): add element owner preparation plumbing

* Fix terminal and chat file drop destination ownership

* fix runtime terminal drop ownership and queued chat retries

* fix(file-drop): preserve feedback acceptance and destination ordering

* fix(file-drop): attach chat and composer files at the drop surface

* fix(file-drop): preserve project destinations and live chat availability

* fix(file-drop): keep path resolution in filesystem namespace

* test(file-drop): use filesystem path bridge in PR3 fixtures

* fix(file-drop): bind terminal drops to pane elements

* fix(file-drop): compare terminal pane identity across public views

* test(file-drop): align composer lifecycle with element-owned drops

* Fix interrupted chat composition and refuse unused quick-create drops

* Type the quick-create drop regression transfer

* fix(file-drop): let the explorer, project sidebar, tab strip and editor own OS drops

STA-6940 PR5. The file explorer tree, the project sidebar, each editor
group's tab strip and its editor area now take OS file drops on their own
element through the shared owner hook, with identity from their own render
(the explorer's shown workspace and target row, the tab strip's and editor
group's worktree and group) instead of the active worktree. The explorer and
sidebar broadcast subscribers and their legacy drop markers are deleted;
editor-open moves out of useGlobalFileDrop into editor-dropped-file-open,
which the legacy unmarked-chrome route still uses until PR6.

* fix(file-drop): keep editor delivery tied to its destination group

* fix(file-drop): guard delayed opens and share floating ownership
2026-10-07 18:27:11 -07:00
Jinwoo Hong 3062b9d8d0 fix(relay): refuse host hellos fast when the database pool is timing them out; renewals jump the queue (#26362)
* fix(relay): refuse host hellos fast when the database pool is saturated; renewals jump the queue

A reconnect herd (2026-10-06 18:34Z, 1,046 asia-east2 hosts dropped by the
load balancer at once) queued hundreds of host hellos behind each cell's
16-connection pool. They timed out after 2 s, the desktops redialled into
the same queue, and control-lease renewals starved behind them.

- Host control upgrades get an immediate 503 (Retry-After: 2) once 32
  callers wait for a pooled connection. Shipped desktops already treat
  that as a connect error and back off with jittered exponential retry.
- General work now queues in PostgresPoolPressure instead of pg-pool, so
  renewal statements (priority lane) take the next released connection.
- A renewal batch that never got a connection no longer fans out into
  one statement per host.
- hostHellosShedDelta counts refusals in the runtime metrics.

* fix(relay): shed host hellos on the pool's oldest wait, not its queue length

asia-east2 queues of 50-196 waiters are routine and keep moving, so a
32-waiter limit would refuse hellos that were going to succeed. Shed only
while the oldest pool waiter has waited 1.5 s of the 2 s acquire timeout,
when a new hello would time out anyway; a refused desktop gets the same
connect error and backoff it gets today, 2 s sooner. Rebinds over a live
control (lease rotation) are never refused.

* fix(relay): shed hellos only when a full pool queue has aged 1 s

Per review: require both an oldest waiter of at least 1 s and a pool's worth
of waiters, so one slow waiter cannot trip it, and state the real baseline
(p99 of 2 waiters on 10-07).
2026-10-07 21:18:26 -04:00
github-actions[bot] c61d0bc16f Update README downloads badge 2026-10-08 01:07:05 +00:00