The route was still resolved at seven callers, each also calling the settle
loop; two census tests only stopped an eighth. planAgentSessionLaunch is now
the one production caller of the resolver and its launch() the one caller of
the settle loop, and both censuses pin exactly that file.
The funnel is two-phase because three sites need the route before the
workspace exists and quick create persists its request for recovery: a plan
exposes route before creation and launches with the created worktree id;
a persisted quick-create request carries the verdict as data and re-enters
through adoptAgentSessionLaunchVerdict without re-resolving. Delivery mode
is fixed on the request once, so route and launch cannot disagree.
A failed or unknown structured settlement returned false after the fork
worktree already existed, so the dialog stayed open and a second click
created another worktree. Unknown now closes the dialog (the launch badge
already reports it); failed copies the context the way a null launch does.
- Claim a refusal fallback only when the caller supplies one, so vault
resume no longer reports a terminal fallback it never opened.
- A failed or cancelled direct work-item launch returns no tab id, so the
caller never pastes the prompt into a setup shell.
- Terminal fork activates with providesInitialSurface for structured
launches and gates its toast on the settlement; the draft blocker
deletion made fork route structured too.
- A failed launch clears its draft seed. The failure toast moves to its own
module to keep the launch-state file under the line cap.
- Ratchet for settle-loop callers; cancel-during-fallback documented.
- Restore the local agent label lookup that the pane-agent identity
inventory expects instead of the inventoried helper.
Route order asked the default-view-mode question first, and that decider
applies the terminal mirror gate (a TUI cannot clear more than forty lines
of prefilled draft), so a PR body over forty lines reached the plain
terminal before structured eligibility was checked. Structured eligibility
now comes first; the mirror gate applies only on the legacy branch.
The structured draft seed writes the launch-draft store directly with no
mirror gate, since a structured session has no terminal copy to fall back
on. Closing a settled structured tab clears an unadopted seed. The
structured session treats idle and loading as unsettled so the adoption
hook takes its baseline from the loaded transcript. Each caller passes one
delivery-mode value to both the route builder and the settle loop.
The structured session component test is split with a shared harness so
it stays under the test file line cap.
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>
* 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.
* 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>
* 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>
* 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>
* 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>
* 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>
* 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>