Commit Graph

29 Commits

Author SHA1 Message Date
imccyu
86965b053c feat(client): inject slot declaration lifetimes 2026-08-06 11:28:46 +08:00
Turtle
8af3babaea docs: rescan rebased documentation hierarchy 2026-08-05 16:16:57 +08:00
creatixchu
6c0ce22f59 fix(directory-picker-browse): light the whole bar, and move the view once per keystroke
The hover affordance framed only the strip right of the crumbs. The bar itself
now carries the outline and the padding in both modes, so hovering previews
exactly the field the click produces and nothing resizes when the two swap.

One keystroke moved the view twice: deleting a separator first narrowed the
pane the draft had just walked away from, then replaced it with its landing.
The tail now filters only the LAST pane — the one whose level the path names —
so a pane on its way out holds still until its landing arrives.

Also from the review round: the walk waits both legs out instead of taking the
submitted-navigation bound (a speculative scan has nothing waiting on it, and
a tail keystroke aborting a slow parent leg would otherwise strand the
two-pane view); a level keeps answering the directory text that produced it,
so `..` segments and Windows forward slashes filter and stop rescanning; the
release-on-miss rule counts displayable rows, so it survives `hidden` ever
meaning more than dot-prefixed; and the editor's 250ms rest joins the other
two constants on the remote-recalibration list.
2026-08-03 13:45:30 +08:00
creatixchu
2ceed380dd fix(directory-picker-browse): keep the typed level in the last pane
Skipping the draft-following scan whenever ANY pane happened to list the
directory was the cheaper rule and the wrong one: erasing a segment left the
level being typed on the LEFT, with its own child pane still standing to its
right, so the two panes stopped reading as "where I am, and where I came
from".

The pane arity is now the invariant the editor maintains — the last pane lists
the level the path names, its parent sits beside it, and only a display root
lists alone. Only that last pane's own tail costs no scan; every other
directory part re-lands.
2026-08-03 13:27:45 +08:00
creatixchu
c58b07833e fix(directory-picker-browse): land the draft-following walk two-pane
The draft-following scan replaced the panes with one wide level, so typing a
path collapsed the dialog's Miller view — the thing the dialog is. It now
lands through the same selection-anchored landing every navigation uses:
target and parent legs as one frame, the target re-selected in its parent
level, its children on the right. Typing a path moves the Miller view exactly
as a crumb jump does.

One landing shape, two callers: `land(path, {closeEditor, announce})` is what
`navigate` and the draft-following scan share. A submitted path closes the
editor and announces failures; the speculative scan keeps both to itself and
re-parks the focus its swap dropped.

A level a pane already lists still needs no scan at all — the filter alone
answers the draft — so erasing back into the parent's own path keeps both
panes and only moves the filter.
2026-08-03 13:08:31 +08:00
creatixchu
30f442d42e review(directory-picker-browse): re-arm the draft-following wait per keystroke
ds-review-bot round one. Keying the debounce on the directory part the draft
named left two states with no recovery until the operator crossed a separator:
a keystroke that superseded an in-flight scan never re-armed one, and an edit
after a rejected submission released the hold with no timer left to release.
The wait is now keyed on the draft itself and decides its target when it
fires, reading the panes through a ref so a landing cannot re-arm it (a host
answering with a differently spelled path would otherwise scan forever).

A landed scan that unmounts the row a keyboard operator Tabbed onto re-parks
focus on the still-open editor; the Modal has no focus trap. That a walked-to
level survives closing the editor is now stated in the README, the Agent Note,
and the module contract. The new e2e stages its own beta directory so running
it alone sees the tree its assertions describe.
2026-08-03 12:11:11 +08:00
creatixchu
79072e356c fix(directory-picker-browse): advertise the path editor and walk the panes with the draft
The Select Workspace Directory dialog hid its one route into typing a path
behind an invisible click target, and once the editor opened the panes stayed
on whatever level was listed when it opened — so the typed text and the list
under it disagreed for the whole edit.

The edit zone now carries a pencil glyph at the bar's right edge and lights in
the editor's own footprint on hover/focus (the bar keeps one height across the
swap). While editing, the panes follow the draft: a directory part no pane
lists is scanned after a 250ms rest and lands in place, so typing deeper
descends and erasing segments steps back up without leaving the editor, and a
final segment nobody matches releases the prefix filter instead of emptying
the pane it is being spelled into. The draft-following scan is speculative and
silent on failure; Enter still owns the view from submission until landing and
remains the only path that surfaces an error.
2026-08-03 11:24:35 +08:00
creatixchu
7b22a3b454 feat(directory-picker-browse): quiet navigation — one-frame landings and a slow-scan loading pill
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.
2026-07-30 11:50:16 +08:00
creatixchu
b46dcb16cb revert: restore the reviewer-approved tree (97a192d7b)
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.
2026-07-30 09:22:16 +08:00
creatixchu
df313b7531 fix(host,client): review round 23 — create-path contract at every client declaration; close-edge resets; NFD tripwire; canonical double join 2026-07-30 03:17:30 +08:00
creatixchu
de24461b91 fix(host): review round 22 — note enumeration includes the create path; cross-method equality pinned; NFD-volume boundary recorded 2026-07-30 02:53:45 +08:00
creatixchu
eac3b378fa fix(host): review round 6 — progressive selection-anchored landing; anchor on actual parent entries; focus-flag hygiene 2026-07-29 21:34:30 +08:00
creatixchu
a1d752f799 feat(host): navigations land selection-anchored — crumb jumps step back a pane instead of collapsing 2026-07-29 21:12:04 +08:00
creatixchu
355d505b89 fix(host): review round 3 — card-scope escape/focus-leave cancel, pick refocus; record display-policy trade-offs 2026-07-29 15:10:35 +08:00
creatixchu
998a5f3381 fix(host): review round — host-derived separator, click-safe blur cancel, dead wide prop 2026-07-29 14:27:01 +08:00
creatixchu
7714c9fa8b doc(host): document the show-hidden toggle and path-draft prefix filter; snapshot the flow 2026-07-29 13:52:44 +08:00
creatixchu
48141b0007 Merge remote-tracking branch 'origin/feat/directory-picker' into feat/workspace-directory-browser
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.i18n.yaml
#	packages/host/directory-picker-browse/README.i18n.yaml
2026-07-29 04:42:57 +08:00
creatixchu
7503390590 fix(host): cancellable listing scans and O(log window) insertion
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.
2026-07-29 04:42:13 +08:00
creatixchu
deb37b8edf Merge remote-tracking branch 'origin/feat/directory-picker' into feat/workspace-directory-browser
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.i18n.yaml
#	packages/host/directory-picker-browse/README.i18n.yaml
#	packages/host/directory-picker-browse/package.json
#	pnpm-lock.yaml
2026-07-29 04:12:44 +08:00
creatixchu
da970ea269 fix(host,client): stream bounded listings, declare schemastery, guard Choose again
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.
2026-07-29 04:11:41 +08:00
creatixchu
02c142e536 Merge remote-tracking branch 'origin/feat/directory-picker' into feat/workspace-directory-browser
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.i18n.yaml
#	packages/host/directory-picker-browse/README.i18n.yaml
2026-07-29 03:46:15 +08:00
creatixchu
5245182db2 fix(host): bound listDirectory levels at a configurable maxEntries
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.
2026-07-29 03:45:26 +08:00
creatixchu
95a8e3f949 fix(client,doc): address review — flow-open busy gating, seam on the architecture map, browse gap documented
- While a picking flow is open (native chooser pending, browse dialog up) or
  its pick is being adopted, every other menu action disables: a late outcome
  must not race a concurrent selection or creation (ds-review-bot warning).
- ctx.directoryPicker joins the architecture Capability Services map (both
  languages); neighboring rows condensed to keep the doc inside its ceiling.
- directory-picker-browse documents that its client half lands in the next
  stacked PR: a -browse composition today hides the picking affordance (the
  documented empty-hole default) rather than misbehaving (ds-review-bot
  critical; the dialog itself ships in #821).
2026-07-28 22:29:34 +08:00
creatixchu
4822622cb7 feat(host,client): ship the in-app directory browser as the browse package's client half
directory-picker-browse becomes dual-face: its browser half fills
ui-workspace's two directory-flow holes with the Select Workspace Directory
dialog (figma Harness 813-23126 family — Miller two-column view, breadcrumb
with click-to-edit path zone, nested New-folder dialog), driving the node
half's host.listDirectory/host.createDirectory and owning its locale
namespace (directory-browser, zh default / en). The dialog moves here from
ui-workspace wholesale — the trigger surfaces keep only the flow-hole owner
conversation.

apps/cli flips its one directory-picker row -native -> -browse, swapping the
host backend and the client interaction together; picking now works for
remote deployments out of the box. The keyless workspace-flow snapshot boots
the browse bundle and drives menu -> dialog -> Documents -> project -> Open
against the fixture tree.
2026-07-28 22:22:14 +08:00
creatixchu
5579b13503 refactor(host): rename the directory-picker dialog backend and kind to native
The browse interaction also presents a dialog (the in-app modal), so 'dialog'
failed to discriminate the two capability kinds; 'native' names where the
chooser runs. Package directory-picker-dialog -> directory-picker-native, kind
'dialog' -> 'native', with every seam/gateway/client/doc reference updated and
the seam Agent Note's naming rationale rewritten to match.
2026-07-28 21:07:28 +08:00
creatixchu
987ecc2ec2 fix(host): require complete UNC forms in the fully-qualified path check
ds-review-bot round 5: '\\' and '\\server' satisfy win32.isAbsolute and
the previous two-separator test, yet resolve() collapses them to
drive-relative roots. The UNC arm now requires server and share components;
incomplete prefixes reject with the business codes, covered per-platform.
2026-07-28 18:27:26 +08:00
creatixchu
b211a80b1f fix(host,client): require fully qualified browse paths; clear the picker kind on close
ds-review-bot round 4. On Windows, isAbsolute admits rooted drive-less
forms (\foo, /foo) that resolve() then rebases onto the process's current
drive; both browse primitives now gate on a fullyQualified check (drive
letter or UNC on win32, POSIX-absolute elsewhere) with a platform test
seam, per-platform unit cases, and the contract wording updated on the
seam, the backend README pair, and the error messages.

The picker-kind effect also kept a resolved 'dialog' across close, so a
backend swapped while the menu was closed could paint the stale entry for
one frame on reopen; the close arm now clears the state, pinned by a
reopen-under-pending-read race test.
2026-07-28 18:13:20 +08:00
creatixchu
cd7aa3c7d8 fix(host,client): gate the picker affordance on the advertised kind; reject non-absolute browse paths
ds-review-bot round 2. The workspace UI never consulted the advertised
directoryPicker kind: under a browse (or merge-added) backend it still
rendered 'Open local folder…' and called pickDirectory(), which the host
answers with directory-picker-unavailable. The create flow now reads
directoryPickerKind() per menu open and renders the dialog affordance only
under 'dialog' — browse (until its in-app browser UI lands) and unknown
kinds hide the entry, realizing the seam's documented default; a keyless
workspace-flow snapshot pins the hidden entry over the browse fixture.

The browse backend also resolved wire paths, silently rebasing '' or
relative parents under the host process cwd; both primitives now reject
non-absolute explicit paths with their business codes, and the seam JSDoc
carries the contract.
2026-07-28 17:39:15 +08:00
creatixchu
7fd2abd828 feat(host): directory-picker capability seam with dialog and browse backends
The web GUI's folder picking was hardwired to one interaction: a native
OS chooser compiled into the gateway, unusable for remote deployments
and swappable only by editing apiproxy source.

Directory picking becomes a three-package capability seam in
packages/host: ctx.directoryPicker returns a discriminated capability —
dialog (the extracted native chooser; host-display only) or browse
(new: one-level listing + child creation over Node stdlib, hidden flags
host-stamped, symlinks followed, ancestry crumbs; remote-capable). The
gateway injects the seam, advertises the kind via
host.describe.directoryPicker, serves host.listDirectory /
host.createDirectory under browse, and answers
directory-picker-unavailable across kinds. cordis.yml is the swap
point; apps/cli keeps dialog mounted, so behavior is unchanged until
the in-app browser PR flips the default. The connection fixture serves
a deterministic browse tree; WorkspacesService gains the browse calls
the browser UI will drive. Decision record:
.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.md
2026-07-28 15:44:53 +08:00