Commit Graph
8359 Commits
Author SHA1 Message Date
Merge Sim f4a75f68b9 Floor the structured option catalog on the seed the client already holds
`structuredAgentSessionOptionCatalog` runs on the client, over a result a host of
any version published — both `use-structured-agent-session.ts` and mobile's
`use-mobile-structured-agent-options.ts` hand it straight off the
`agentSession.options` wire. It mapped `result.models` through unchanged, so an
empty list reached the snapshot, which correctly returns `[]` for an empty
catalog, and the model pill and effort pill both vanished.

On `origin/main` that was unreachable: this function unconditionally pushed
`current.model`, so the list was never empty. Withholding unofficial ids removed
that push, so the exposure is this PR's. Flooring only the host-side readers
closes it for new hosts; a new client paired with an older host still hits it,
which is the divergence `docs/reference/remote-wire-compatibility.md` covers
when a host changes what it publishes.

The floor uses `seed.models`, the catalog the client already passes in, so it
holds for Claude and any future structured agent rather than one provider. The
reader-side floors stay as defence in depth.
2026-09-09 13:47:35 -07:00
Merge Sim 1028d76add Floor the Codex model list on the seed instead of the shared snapshot
An empty `models` correctly yields an empty snapshot — that is what an empty
catalog means, and other callers rely on it. The reachable defect is narrower:
`readCodexStructuredSessionOptions` is the only producer that can return
`models: []` beside a truthy `current.model`, because its guard throws only when
no model resolves at all and `input.current.model` short-circuits it. A restored
thread whose `model/list` came back empty therefore lost the model pill and the
effort pill with it.

The Codex reader now falls back to the seed for its list, the same floor
`readClaudeStructuredSessionOptions` already applies (`discovered.length > 0 ?
discovered : seedModels()`). Scoped to the empty-list case so a thread with
neither a listed model nor a current one still raises "codex app-server returned
no available models" rather than offering five ids the account may not hold.

Reverts the earlier change to the shared snapshot function, which widened
semantics every caller shares to fix one producer's bug.

Also covers the probe mechanisms behind the timing fix, which had no tests: the
10s dispatch budget, the abandoned probe still filling the cache, one in-flight
probe shared across racing dispatches, and same-host reuse.
2026-09-09 13:39:18 -07:00
Merge Sim 668b579f00 Resolve the dispatching coordinator's worktree once per worker-start
A local `--model` dispatch resolved it twice — once to name the host the model
probe asks, once to place the worker — and each is a `showTerminal` round trip
for the same answer. The probe path now hands the id it already paid for to the
placement path, which still resolves it itself when no probe ran.
2026-09-09 13:22:45 -07:00
Merge Sim a03baf1cb1 Keep the options row when a provider lists no models at all
`buildNativeChatSessionOptionSnapshot` short-circuits on an empty model list.
That used to be unreachable with a model in play: both producers guaranteed a
row for the tracked id — the PTY path fabricated one, and the structured catalog
pushed `current.model` in. Withholding unofficial ids removed both guarantees,
and `readCodexStructuredSessionOptions` only refuses when there is no current
model, so a restored Codex thread whose `model/list` came back empty lost the
model pill and the effort pill with it.

Fixed at the one consumer rather than at each producer: the list is empty, but a
tracked id still names what the session runs, so its options row is drawn from
`unknownModelOptions`. The model pill stays neutral and offers nothing, which is
the honest reading of an empty list.
2026-09-09 13:22:26 -07:00
Merge Sim 1acf8b58c7 Reject a worker-start model only when the host actually listed one
The model authority fell back to Orca's static seed whenever the probe could
not answer inside the 10s dispatch budget, then refused anything the seed did
not carry. That made a dispatch's verdict a function of probe timing — a cold
SSH host refused `--model opus[1m]`, the id the CLI help documents, and the
byte-identical retry succeeded once the probe had cached — and it asserted "this
model does not exist" from a loss of contact, which inverts the execution-host
boundary. The Codex seed says so itself: it is deliberately short and expects
unknown ids to pass through.

Only a `live` answer may now refuse an id; a seed fallback carries no membership
and lets the agent CLI report the error. This also disarms two ways the probe
silently fails (a folder workspace, an unknown worktree), which previously
surfaced as a model error for a worktree fault.

Two more divergences between a cold and a warm dispatch go with it:

- Effort is a flag Orca emits, not a host fact, so the catalog decides it on
  both paths again. The probe reports one generic level list for every Codex
  model, so narrowing to it refused `--effort ultra` on `gpt-5.6-sol` — which
  the seed path and the picker both accept.
- Membership now runs through the same three-way policy the picker uses
  (`resolveDiscoveredCatalogModels`), so `worker-start` cannot refuse a seeded
  id the picker offers in the same session.

The probe cache is re-keyed on the executing host (`local` / `wsl:<distro>` /
`ssh:<id>`) instead of the calling worktree, so N worktrees on one machine run
one probe for one fact, and expired entries are swept rather than retained.
2026-09-09 13:22:09 -07:00
Merge Sim 880d8a3021 Key the model-authority cache with a space, not a NUL byte
A literal NUL in the template made git treat the module as binary, hiding
6.5 kB of new validation logic from review. Agent ids never contain a
space, so the scope key stays unambiguous.
2026-09-08 22:44:04 -07:00
Merge Sim 91480bbaa3 Show only official model names in native chat and require them for worker-start --model
The composer echoed any tracked model id verbatim: a fabricated catalog row was
appended for ids no list carried (shared snapshot, and the structured-route
readers in main for Claude and Codex), so a worker launched with --model
claude-opus-5 rendered that string as a model and lost its effort picker.

Now no layer fabricates a row. A tracked id outside the discovered and seed
lists renders the neutral Model pill, while its effort picker stays available
from the catalog's unknown-model options so the running session remains
adjustable. Legitimately picked models are unaffected: main already maps the
init frame's resolved id (claude-opus-5[1m]) back to the listed opus[1m].

worker-start --model now accepts only ids the agent CLI lists on the executing
host, probed through the same discovery the chat picker uses (bounded wait,
per-scope cache, seed ids as the fallback), and the rejection names the
accepted ids and which list answered.
2026-09-08 22:26:26 -07:00
Brennan BensonandMerge Sim 852495d35c fix(native-chat): unify launch routing and support structured worker placement (#19431)
* fix(orchestration): let worker-start actually produce a structured chat

`orchestration.workerStart` reads the user's "open agent tabs in chat"
default, but two placement checks downgraded a structured-preferring
worker to a PTY terminal agent for the two flags a routine dispatch
always passes:

  --worktree new-child / new-top-level  -> worktree_creation
  --model / --effort                    -> launch_preferences

so in practice a structured worker never happened.

launch_preferences was stale. PR #19040 gave AgentSessionAttachParams
`options` and added resolveStructuredLaunchSeedOptions, which narrows a
saved selection to exactly `model` and `effort` — the two ids both
structured providers accept as strings. --model/--effort now go through
that same narrowing (extracted as narrowStructuredLaunchSeedOptions) and
seed the worker's session instead of forcing a terminal. An option set
that narrows to nothing resolves to undefined, never `{}`, which would
fail the record's bounded-string guard under a code that is not a wire
refusal and strand the launch with no fallback.

worktree_creation was a consequence of createWorkerWorktree creating
agent-first: its startup terminal WAS the worker, so the structured
branch below it was unreachable for any new worktree. A structured
worker now creates the worktree with no startup agent and creates its
session for the worktree afterwards — the order the renderer's own
structured worktree create already uses. Because the executing host can
only answer agentSession.createSupport for a workspace that exists, that
verdict moved after creation: a refusal (WSL, and the rest) becomes a
terminal agent in the worktree just created, never a failed start.

--on and --terminal still downgrade, with their reasons intact, and
every remaining downgrade still states itself in the mode receipt.

The wait-for-setup gate is preserved explicitly. A PTY worker got it for
free — agent-first creation sequences the agent's startup command behind
the setup runner, so tui-idle could not arrive until setup exited. A
structured session has no startup command to sequence, so the gate is
now awaited directly, bounded by the start's own timeout.

Split out worker-worktree-creation.ts and worker-start-agent-placement.ts
rather than growing two files that were both pinned at the max-lines cap.

* refactor(native-chat): make shared feasibility authoritative for launch routing

* Type the structured setup gate's absent blocked reason so the wait union stays property-typed

The type-aware audit rejected the blocked-reason template literal: narrowing the
wait union with an 'in' check left the field typed unknown. Declaring that a
structured setup gate never carries a blocked reason restores the direct read.

---------

Co-authored-by: Merge Sim <sim@local>
2026-09-08 21:40:23 -07:00
98df62d8ff perf: reuse normalized task-page repository selection (#19454)
* perf: reuse normalized task-page repository selection

* test(task-page): cover ineligible persisted repo IDs in initial selection

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:55:25 -07:00
eedaf2bdfc perf: check backfill date cardinality before expanding ranges (#19456)
* perf: check backfill date cardinality before expanding ranges

* test(codex): pin the backfill cardinality gate to the enumerated range

Differential coverage at maxDates === length and length - 1 across leap days,
century rules, year rollover and DST switch dates.

* test(codex): type the backfill cardinality table as date tuples

Untyped it.each rows widen to string[], which tsc rejects when cast to the
3-tuple CodexSessionBackfillDate.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
2026-09-08 19:53:24 -07:00
2558bf1b17 perf: count command-line escapes without regex match arrays (#19499)
* perf: count command-line escapes without regex match arrays

* test(windows): pin command-line budget counting against the regex oracle

Covers every BMP code unit, astral and lone-surrogate adjacency, trailing
backslashes, %VAR% and carets, plus randomized quote-heavy command lines.

* perf(windows): count command-line escapes by seeking, not scanning

Counting every character regressed the shape this estimator actually guards: a multi-KB WSL script with almost no escapes went 25-38x slower on Windows. Seek escapes with indexOf so the cost tracks their count, and hand the rest to a plain scan once they are dense enough to pay for it.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:46:30 -07:00
6d2d63104a perf: reuse naturally ordered unique Codex trust ranges (#19492)
* perf: reuse naturally ordered unique Codex trust ranges

* test(codex): pin the trust-range ordering the dedup removal relies on

Removing the pairwise dedup+sort is only sound while the scanner emits
strictly ascending, non-overlapping spans. Guard that precondition so a
future scanner change cannot silently widen or drop a trust block.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:44:31 -07:00
e373c89536 perf: cache update timestamps for Linear and Jira result sorting (#19473)
* perf: cache update timestamps for Linear and Jira result sorting

* perf(issues): build updatedAt key map without an intermediate tuple array

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <neil@stably.ai>
2026-09-08 19:44:13 -07:00
5f63b850a5 perf: select checks-panel workspace attribution in one pass (#19471)
* perf: select checks-panel workspace attribution in one pass

* perf(checks-panel): normalize candidate paths only after the cwd filter

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <neil@stably.ai>
2026-09-08 19:43:59 -07:00
f74222d82c perf: cache AI-vault project attribution by host and cwd (#19470)
* perf: cache AI-vault project attribution by host and cwd

* test(ai-vault): guard both halves of the project attribution cache key

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:48 -07:00
063c1caa6f perf: reuse AI-vault path matchers and query and sort keys (#19469)
* perf: reuse AI-vault path matchers and query and sort keys

* test(ai-vault): add cross-platform path and sort-key differentials

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:36 -07:00
0f4bca26d4 perf: index usage session breakdowns during aggregation and merge (#19487)
* perf: index usage session breakdowns during aggregation and merge

* test(usage): cover key injectivity and merge-index freshness

Also restore both module docstrings to the top of their files.

Quote/backslash location and model keys prove the JSON tuple key stays
injective, and a second source carrying a location/model the merge itself
appended must fold into that row rather than duplicate it.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:25 -07:00
4a502d2e19 perf: index terminal neighbor order and remaining membership (#19453)
* perf: index terminal neighbor order and remaining membership

* test(session): prove indexed terminal close picks the pre-index neighbor

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:10 -07:00
8b7b670c40 perf: validate terminal adoption MRU membership with group sets (#19482)
* perf: validate terminal adoption MRU membership with group sets

* test(runtime): pin orphan-adoption group membership cardinality

Covers empty tab order, a tab claimed by two groups, duplicate group ids, an uncovered claimed tab, omitted/empty recentTabIds and both valid two-tab splits. The two-groups case is mutation-verified: swapping the global no-duplicate rule for the new per-group set fails it.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:06 -07:00
35bbc5ce5c perf: skip folder-scope construction for separate repository imports (#19452)
* perf: skip folder-scope construction for separate repository imports

* refactor(project-groups): share one mode flag between scope skip and root guard

Also cover the separate-import path with real repo paths, which the throwing
getter test no longer exercises.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:02 -07:00
782c4618fd perf: index observable skill installations by locked name (#19451)
* perf: index observable skill installations by locked name

* fix(skills): stop the convergence gate reading snapshots off Object.prototype

Lock names come straight from a JSON file on disk, so a skill directory named 'constructor' or 'toString' made knownSnapshots[name] resolve to a prototype function and threw TypeError out of the whole freshness inventory.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:42:51 -07:00
8983e026f7 perf: prune metadata caches only when an entry can expire (#19450)
* perf: prune metadata caches only when an entry can expire

* fix(metadata-cache): gate next sweep on the oldest capacity-eviction survivor

Capacity eviction drops the oldest entries after nextCacheExpiryAt is
computed, so the gate pointed at an expiry that no longer existed and
forced one needless full sweep.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:42:41 -07:00
60456107e6 perf: index closed browser page IDs during focus cleanup (#19449)
* perf: index closed browser page IDs during focus cleanup

* perf(browser): omit closed page focus keys instead of rebuilding the records

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:42:32 -07:00
f242c99af4 perf: scope activation inventory to the owning host and workspace (#19447)
* perf: scope activation inventory to the owning host and workspace

* fix(activation): keep an unscoped census fallback when the owning host is unnameable

Scoping the activation inventory made resolveActivationPtyListScope throw for
paired-runtime workspaces and made a detached relay reject the scoped list, and
both collapse to a 'blocked' gate. 'blocked' skips the sleeping-agent resume and
the caller's reseed, so an SSH target on the bounded offline floor lost its
initial pane and peer workspaces stopped resuming.

Fall back to the unscoped inventory that shipped in exactly those two cases; the
scoped fast path still covers local, folder and attached-SSH workspaces. Also OR
the host-reported worktreeId with the id-prefix match instead of preferring it,
because a relay seeds worktreeId from the host's own ORCA_WORKTREE_ID and a
session dropped from the census is one the gate forks a second writer onto.

* test(activation): update forkbomb fakes to the scoped session.tabs.list shape

The gate now asks the host for one workspace's snapshot instead of the whole session.tabs.listAll inventory and refuses an answer that does not name its scope, so the old snapshots-array fakes made it block instead of resume.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:42:25 -07:00
44eb95fc6b perf: bound tool pairing and avoid unused attribution arrays (#19468)
* perf: bound tool pairing and avoid unused attribution arrays

* test(native-chat): cover mobile pair-limit shapes and group allocation tests

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:42:18 -07:00
1dcd792649 perf: index selected skills when reporting bundle failures (#19481)
* perf: index selected skills when reporting bundle failures

* refactor(skills): reuse the shared renderer collator for delete-plan roots

src/renderer/src/lib/locale-text-collators.ts already memoises a base-sensitivity collator for six renderer modules; building another one per call in skill-delete-copy duplicated it and paid ICU setup on every summary render. Also pin dedup/order parity for the Set-based selected-skill filter.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:42:02 -07:00
126a69367c perf: drop oversized diagnostic records before retaining serialized text (#19445)
* perf: drop oversized diagnostic records before retaining serialized text

* fix(observability): leave a marker where an oversized trace record was dropped

Oversize records were discarded silently, leaving an unexplained gap in the
trace. Emit a tiny timestamped placeholder naming the span instead.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:58 -07:00
f0c210a906 perf: index Resource Manager labels and accumulated workspace rows (#19480)
* perf: index Resource Manager labels and accumulated workspace rows

* fix(status-bar): always build the resource tab-label index

The includeTabLabels flag left tabsByIdByWorktree empty for the orphan-count caller while the type declared it present, so a future reader would silently lose session labels. The only non-merge caller is memoized behind panel-open. Adds parity tests for the first-wins tab id and duplicated-worktree row rules the removed linear scans relied on.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:52 -07:00
ee2faa5a2d perf: index selected ancestor coverage during sidebar drag (#19443)
* perf: index selected ancestor coverage during sidebar drag

* test(sidebar): pin nested and sibling lineage expansion invariants

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:50 -07:00
db5df2f6f6 perf: index selected-host SSH leases by PTY (#19467)
* perf: index selected-host SSH leases by PTY

* perf(ssh): build lease index lazily and cover pty id normalization

* style(ssh): restore repository oxfmt formatting

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:44 -07:00
Neil c3a415487b perf(terminal): avoid quadratic status-marker scans in output bursts (#19373)
* perf(terminal): reuse forward OSC status terminator searches

* test(terminal): pin cached OSC terminator reuse across BEL frames

Document that forward match reuse requires a monotonic search offset and cover a distant ST held across many intervening BEL frames.
2026-09-08 19:41:42 -07:00
d872a5a8b8 perf: avoid repeated pending SOCKS payload copies (#19439)
* perf: avoid repeated pending SOCKS payload copies

* test(browser): cover pipelined SOCKS request-tail ordering in pending buffer

Also document takeBuffer's view-not-copy contract and restore node: import order.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:37 -07:00
d7162ef570 perf: reuse collators when scanning Warp themes (#19441)
* perf: reuse collators when scanning Warp themes

* perf(warp-themes): filter before collating and skip trivial sorts

Warp discovery collated every entry in the user's home or %APPDATA%\\warp before discarding the non-Warp ones; filter first so ICU only sees candidate names (order is unchanged: filtering commutes with a stable total-order sort). Also skip the collator entirely for 0/1-entry directories and single-file dialog picks, and drop the sort that ran only to be thrown away when the preview budget expired.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:15 -07:00
a0ea66a13d perf: reuse collators when sorting discovered skills (#19440)
* perf: reuse collators when sorting discovered skills

* perf(skills): share the discovery-source label sorter

Both native and WSL discovery built the same one-off source collator inline; hoist it next to sortDiscoveredSkills with the same <2 short-circuit, and pin ordering parity against the per-call comparator over a wide collation corpus.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:11 -07:00
400f70b006 perf: index tab membership when rebasing authoritative sessions (#19510)
* perf: index tab membership when rebasing authoritative sessions

* fix(runtime): drop host-removed tab ids from rebased group recents

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:07 -07:00
b68d2c46f6 perf: skip fuzzy ranking when exact file matches fill the window (#19509)
* perf: skip fuzzy ranking when exact file matches fill the window

* test(tab-bar): pin exact-match ordering against the pre-skip rank-then-slice pipeline

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:41:02 -07:00
b38c1313c4 perf: index discovered skill IDs and names for batch selection (#19507)
* perf: index discovered skill IDs and names for batch selection

* perf(skills): index only the selectors a share request asked for

Indexing every discovered skill made the common one-or-two-selector share slower than the linear scan it replaced (200 skills / 1 ID selector: 0.04us -> 38us). Scoping both indexes to the requested selector set keeps the O(selectors x skills) collapse and beats the unscoped index at every size measured, including 512x512 (5547us old, 176us unscoped, 64us scoped).

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:57 -07:00
de771ae4af perf: concatenate only carried JSONL line prefixes (#19506)
* perf: concatenate only carried JSONL line prefixes

* perf(ai-vault): avoid per-line carry reset and sweep every JSONL chunk boundary

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:51 -07:00
e0cac96772 perf: measure sidebar row geometry once before sorting delete anchors (#19503)
* perf: measure sidebar row geometry once before sorting delete anchors

* test(sidebar): prove the hoisted measure picks the same delete anchor

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:46 -07:00
5f2127ad12 perf: group chat history sequences lazily within result windows (#19501)
* perf: group chat history sequences lazily within result windows

* test(agent-session): prove lazy sequence grouping matches eager at every window edge

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:41 -07:00
8413a5b33c perf: cache same-axis pane subtree weights during equalization (#19500)
* perf: cache same-axis pane subtree weights during equalization

* test(pane-manager): prove cached equalize weights match the uncached walk

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:36 -07:00
6a9c5d8ce3 perf: replay pending chat asks with a FIFO cursor (#19496)
* perf: replay pending chat asks with a FIFO cursor

* perf(native-chat): track the pending-ask FIFO with counters instead of a queue

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:30 -07:00
96216601bc perf: retire exhausted buckets from host-balanced listings (#19493)
* perf: retire exhausted buckets from host-balanced listings

* test(listing): guard the bucket-retirement invariant and starvation fix

Document why in-place compaction keeps bucket[round] defined and preserves
first-appearance host order, and cover cap-exact filling plus small-host
representation so a drifting retirement predicate cannot emit blank rows.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:25 -07:00
814d3525d4 perf: lazily index workspace tabs during terminal binding replay (#19466)
* perf: lazily index workspace tabs during terminal binding replay

* test(persistence): cover same-worktree duplicate tab ids in binding replay

* style(persistence): restore repository oxfmt formatting

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:21 -07:00
2c5cd845a2 perf: append to owned project source lists without repeated copying (#19465)
* perf: append to owned project source lists without repeated copying

* docs(projects): record draft-ownership rule for in-place project merge

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:40:10 -07:00
96b33d7725 perf: index unified tabs for browser palette entries (#19464)
* perf: index unified tabs for browser palette entries

* test(palette): pin the duplicate-workspace guard the tab index relies on

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:39:58 -07:00
df8a43724f perf: index document history workspace and path identities (#19461)
* perf: index document history workspace and path identities

* docs(browser): note doc-history dedupe must mirror location equality

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:39:42 -07:00
86fe80da25 perf: preserve store state on unchanged document titles (#19459)
* perf: preserve store state on unchanged document titles

* fix(browser): compare every doc-history field before skipping a title refresh

A hand-listed title check would silently swallow any field added to
WorkspaceDocHistoryEntry later. Cover the over-cap trim path too.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:39:27 -07:00
c69d4d4f8b perf: track pane alias singleton or ambiguity without copying buckets (#19479)
* perf: track pane alias singleton or ambiguity without copying buckets

* test(persistence): pin pane-alias ambiguity cardinality parity

Covers 0/1/2/3/4 rows per tab plus a mixed ordering case, so a regression from has() to a truthy check would resurrect an ambiguous tab and fail.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:39:26 -07:00
Brennan BensonandMerge Sim e80fae0c4d Summarize turn file changes and preserve resolved prompt receipts (#19229)
* feat(chat): summarize turn changes and retain resolution receipts

* fix(chat): defer turn diff details and localize resolution times

* fix: complete approval projection test fixture

* Align turn diff disclosure chevron and indent details

---------

Co-authored-by: Merge Sim <sim@local>
2026-09-08 17:50:51 -07:00