- .loadingFloat moved after the .status/.error block (its padding was
losing the same-specificity race) and re-anchored bottom-right: the
truncated/error rows own the bottom left and keep rendering through a
scan, so the pill can never cover them; confirmCreate's relist now
clears the stale failure text like every other scan launch.
- The close edge resets loading, so the slow-scan effect disarms while
hidden and a reopened dialog waits out a fresh silence window
(regression test added).
- The truncated note's survival through a scan is now asserted in the
slow-scan test; the wait-bound test moved to fake timers with the
200ms bound explicit.
- select()'s exemption from the one-frame rule and the constants' local
calibration premise are recorded in JSDoc and the capability-seam
Agent Note; the themed-scrollbars note's rebinding enumeration is
replaced by a pointer to the mechanical gate (it had drifted twice).
Both pairs re-recorded.
Navigations keep the previous view rendering while scanning: target and
parent legs land as one two-pane frame when the parent leg settles within
a 200ms wait bound (past it the target lands alone and the late leg
upgrades in place; Escape inside the landing window withdraws the
navigation). The loading indicator floats over the content on the card
background and appears only once a scan outlives a 300ms silence window,
so navigation never shifts the columns or flashes an intermediate frame.
The truncated note now describes the on-screen panes instead of hiding
during scans.
ZiyaZhang approved 97a192d7b; the subsequent bot-review rounds (7-24)
landed after that approval and were not requested by a human reviewer.
This commit restores the approved tree verbatim as a forward commit
(pushed history stays intact). git diff 97a192d7b is empty.
Supersession (newer navigation, path editing, closing, unmount) now
aborts the in-flight listing's request instead of only discarding its
result: the browser mints an AbortController per listing, the signal
rides the workspace face (IWorkspaces.listDirectory gains an optional
signal) onto the fetch carrier, and the Host scan stops with it (817's
cancellation chain). apps/cli keeps both picker packages as dependencies
so the documented one-row cordis.yml swap to the native backend resolves
at boot.
Same contract as the path editor: trim only rejects an all-whitespace
draft, and the Host receives the original spelling — the backend accepts
any non-blank single segment verbatim, so trimming here would create and
select a different sibling.
Trim now only detects a blank draft; the original text navigates — a
real directory name may end in whitespace, and trimming would list its
sibling or adopt the wrong workspace.
The aborted exit no longer awaits close (Node queues it behind any
in-flight read, chaining the departed caller back onto the very stall
the abort escaped) — the abandoned close's failure is swallowed, it has
no consumer. Symlink stat probes race the signal too, with a
per-candidate abort check between probes, so a stalled probe target
cannot keep a departed request alive. The deferred handle cleanup after
a lost opendir race now consumes its own close failure instead of
leaking it as an unhandled rejection.
Every filesystem await in the browse scan (opendir and each read) now
races the signal through raceAbort, so a stalled network open/read stops
with a departed caller and an already-aborted request rejects even for
an empty level; the abandoned settlement is swallowed and an abandoned
open that still mints a handle is closed, never leaked. apiproxy maps an
aborted listing to the cancelled wire code, matching pickDirectory and
command.execute, instead of reporting a false internal failure. The
fixture spec call sites gain the wire signal argument the previous
commit's static lane flagged.
Escape canceling a path edit opened before any level listed relaunches
the home listing instead of stranding a blank picker (the editor had
superseded the initial request while parent was still null). The card's
height clamps to the viewport (min(420px, 100dvh - 32px)); header and
footer are flex-none and the columns scroll, so Open/Cancel stay
reachable on landscape phones and short embedded windows.
capability.list gains an optional AbortSignal threaded from the RPC
carrier's request signal (the pickDirectory pattern): a disconnected or
timed-out caller stops the opendir loop instead of the scan outliving
its caller, and the abort surfaces as its own reason rather than a
directory-unreadable dressing. boundedInsert rejects a full window's
at-or-beyond-tail candidate on one comparison and binary-inserts
retained candidates, so an oversized level no longer pays a window scan
per dirent.
The browse level now streams through opendir into a name-sorted window of
maxEntries + 1 candidates (boundedInsert), so memory stays O(maxEntries)
no matter how many children a directory holds and enterability probing
touches only windowed candidates; a windowed broken symlink is not
backfilled since the eviction already marks the level truncated.
schemastery joins the package's runtime dependencies (the source launcher
and isolated installs failed to resolve the value import). The
folder-error dialog's Choose again goes inert while the flow hole is
empty, and the withdrawal effect also keys on the open transition, so a
flow can never open over a hole nobody serves.
The Miller row now scrolls horizontally with the child pane pinned into
view when its preview lands, so descent stays reachable when the dialog
is narrower than two fixed panes. The dialog also says when a visible
level was cut at the backend's complete-result bound (817's maxEntries)
instead of letting the tail of a huge directory go silently missing.
One list call now materializes at most maxEntries child rows (config,
default 1000 - GitHub's web-UI directory-listing bound). Candidates sort
before probing so a cut level keeps the name-sorted head and symlink
probing stops with the bound, and DirectoryListing carries a required
truncated flag on the seam and the wire so clients can state
incompleteness instead of silently missing tail entries.
- Escape in the path editor now supersedes a navigation the editor already
launched (request-sequence bump + loading reset), so a late success cannot
jump to the cancelled path; the single-pane fallback keeps covering a
superseded selection preview (ds-review-bot).
- The browse flow's pair registration rides ui-slots' new
deferGroupRegistration (one occupant, both holes, as a unit — construction
or late rival conflicts roll back wholesale and fail loud), mirroring
-native and deleting the would-be clone.
BrowseDirectoryFlow and its injected face move to the package-internal
src/client/flow.ts, mirroring -native: ./client exports only the Loader
surface and the same-package spec imports the internal module directly.
A navigation settling between the Edit-Path click and the first keystroke
executed navigate's draft reset and closed the editor underneath the user;
the click now bumps the request sequence like draft edits do
(ds-review-bot).
- The browse client half mirrors -native's rollback: a pair construction
that throws halfway (declared-but-occupied second hole) disposes the
earlier deferral before rethrowing, so no orphaned slot subscription
outlives the failed fiber (ds-review-bot).
- The TestWorkspaces browse methods gain the coverage CI's per-file gate
requires (defaults + stub overrides, recorded like their siblings).