Commit Graph
30 Commits
Author SHA1 Message Date
Turtle a27efdef36 docs: make technical prose concrete 2026-08-10 16:34:20 +08:00
Tianyi Cui 25dcd7293c docs: purge chain-of-thought leakage from prose
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
2026-08-09 21:10:59 +08:00
_Kerman 63ba836bce fix(client): address CI and review findings on blank-session reuse
- docs: fix cross-class note links (../feature/...), mirror the membership
  reuse criterion in README.zh.md and the connectWorkspace architecture
  note (EN/ZH/sidecars re-recorded)
- test(client): stray + member blank at the same path — the scan skips the
  stray and reuses the member
- test(web): re-registration after delete now mints a fresh blank session
  (the old cwd-only reuse is gone), so the account is no longer empty;
  assert the retained seeded session is still not re-adopted
2026-08-05 12:21:09 +08:00
creatixchu 95826603cb review(web): poll the pane-arity assertions in the path-editor e2e
A bare count can observe a landing mid-commit on a loaded runner, and the
arity is the invariant this scenario exists to pin.
2026-08-03 13:57:20 +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
Tianyi Cui ce04a85d80 Merge origin/master into same-basename workspace fix
# Conflicts:
#	packages/client/ui-workspace/README.i18n.yaml
2026-07-31 18:42:20 +08:00
Tianyi Cui 678ad97f9a Allow same-basename Workspace paths 2026-07-31 18:37:34 +08:00
creatixchu 31e467e744 Merge remote-tracking branch 'origin/master' into worktree-session-hover-menu-fix
# Conflicts:
#	apps/web/tests/workspace-management.e2e.ts
#	packages/client/ui-workspace/README.i18n.yaml
2026-07-31 17:56:06 +08:00
creatixchu 0f3c821b38 test(web): assert hover-card dismissal directly 2026-07-31 16:46:29 +08:00
creatixchu 8997afb3e5 fix(web): preserve hover-card selection and feedback 2026-07-31 16:13:12 +08:00
creatixchu d6231007af cleanup(web): give adding a Workspace one route
Both Workspace surfaces offered "Open local folder…" and "Create a new
workspace" for one outcome. The browse occupant already carries its own
New folder affordance, so picking a directory covered creating one; the
name dialog only added a second vocabulary and a create target the
operator could neither see nor choose.

The surviving entry is named after the outcome — "Add workspace…" — and a
menu now appears only where there is something to choose between: with no
Workspace listed (the add-only sidebar header, or an empty hero list) the
anchor gesture raises the directory flow directly instead of a one-row
popover. An empty list counts as final only after the list baseline lands,
and a composition with no directory-flow occupant hides the sidebar button
rather than offering a dead one.

WorkspaceCreateFlow becomes WorkspacePickFlow (createOnly -> addOnly) and
the injected createWorkspace narrows to { path }. The host's
workspace.create({ name }) branch and `dsh web --workspace-root` lost their
last product consumer; both are marked at the call site for a follow-up.
2026-07-31 15:47:40 +08:00
creatixchu 8714952c85 feat(web): copy values from hover cards 2026-07-31 15:38:22 +08:00
creatixchu 6ca3b78e55 Merge remote-tracking branch 'origin/master' into worktree-session-hover-menu-fix
# Conflicts:
#	apps/web/tests/workspace-management.e2e.ts
2026-07-31 15:14:05 +08:00
imccyu d3e8f17a54 fix: review follow-ups for the session archive set
- WorkspaceRegistry.archiveSession no longer wraps persistence-listing
  failures as WorkspaceUnknownSessionError: only a definite miss (live
  lookup, header index, then a fresh list) maps to session-not-found;
  storage faults propagate as internal errors, with a negative test.
- The archived-current sweep moves from the unary path into the
  projection: any install path (local echo, another tab's frame, a
  reconnect baseline) clears a selection that landed in the archive set.
- An archive set installed while workspace.list is in flight supersedes
  the stale baseline's set instead of being rolled back by it.
- The workspace-management e2e anchors the archived row by its session
  actions button and asserts the single-stray fixture assumption loudly.
- Drop the stale touchSession rows from the workspace READMEs (the
  method was removed with its Agent Note).
2026-07-31 14:08:13 +08:00
imccyu e235be2bac feat(ui-workspace): archive session from the row menu
The visual-only Delete session placeholder becomes a wired Archive
session action: no confirmation dialog (non-destructive), failures stay
console diagnostics. tree.ts hides archived sessions in every
derivation (workspace groups, Ungrouped, search, flat list) through the
sessionVisible predicate. The workspace-management e2e pins the archive
round trip across reload.
2026-07-31 14:08:13 +08:00
creatixchu 2cac565383 fix(web): let the pointer reach hover cards and row menus
The workspace browser's two hover-raised popups both died on the way to
them. HoverCard closed on the first pointerleave and rendered its card
pointer-events:none, but the card sits 8px off the anchor, so every path
to it crossed ground belonging to neither. The row action menus put
closeOnPointerLeave's handler on the portaled list, so aiming back at the
... trigger that opened it, or overshooting a list edge, closed it with no
window to come back.

usePointerGrace owns one cancelable delayed close (200ms) shared by both
atoms: leaving arms it, returning cancels it. The hover card becomes
hit-testable so resting on it holds it open, and Menu moves pointer-leave
dismissal to the wrapper span, where React's enter/leave traversal makes
trigger and portaled list one region.

Both gestures are pinned in the real browser lane; each fails without the
corresponding fix.
2026-07-30 20:25:02 +08:00
imccyu f87692a5c3 test(web): anchor the group section above the HoverCard wrapper
The workspace header row is now wrapped by its HoverCard anchor span
(0b4a6196f), so the row's immediate parent no longer holds the session
subtree; the delete scenario anchors on the groupSection ancestor
instead. The flat-view and dwell failures were downstream of this one
(shared page state).
2026-07-30 16:54:43 +08:00
imccyu d9fa79a1e1 test(web): pin browser replay locale 2026-07-30 11:39:11 +08:00
creatixchu 459128dfb6 fix(web): root USERPROFILE for the browser golden; re-record it against fresh bundles
- homedir() reads USERPROFILE on Windows: the golden's home collapse now
  sets and restores both variables, keeping the artifact machine-independent
  on every platform (ds-review-bot).
- The committed golden is re-recorded against freshly built bundles: the
  earlier recording ran with a stale dist that predated the navigation
  landmark and the button-in-listitem markup, which is why refreshes had
  looked byte-identical.
2026-07-29 01:57:19 +08:00
creatixchu 6cd63f741c fix(host): address review — Escape scoping, relist gating, crumb overflow, aria golden
- Escape (and the mask) now reaches only the topmost dialog: while the
  nested New-folder dialog is up the browser ignores its own Modal close,
  and the nested dialog's in-flight fence keeps both open during creation.
- New folder disables while any listing loads, so a slow post-create
  relist/select sequence cannot host a second create against a target the
  pending listing is about to change.
- Deep ancestry scrolls inside a dedicated crumb trail whose tail is pinned
  into view; the path-edit zone keeps its reserved width instead of being
  clipped by the card, preserving cross-drive path entry.
- The workspace-management e2e records a directory-browser aria golden at a
  staged tree (host HOME pointed at the scaffold cwd collapses ancestry into
  the Home crumb, keeping the artifact machine-independent), and the keyless
  snapshot's row targeting goes through visible label text — listitem
  accessible-name computation differs across dom-accessibility-api
  environments (the CI-only miss).
2026-07-28 23:21:27 +08:00
creatixchu 006a6655ee feat(web): in-app workspace-directory browser as the shipped picking default
The Open-local-folder flow now branches on the Host's advertised picker
interaction (host.describe.directoryPicker, read per menu open; unknown
kinds hide the entry): dialog keeps the native-chooser flow, and browse
opens the new in-app directory browser (figma Harness 802-56979) —
breadcrumbs rooted at a localized Home crumb, a click-to-edit path zone
right of the crumbs, host-flagged hidden entries filtered client-side,
an inline New-folder row, and Open adopting the listed directory
through the existing workspace-creation error surface. Dialog copy is
localized (ctx.locale, namespace 'workspace'); the plugin re-registers
its entries on locale/change.

apps/cli flips the composed backend from -dialog to -browse, so the
picker works for remote deployments out of the box; -dialog stays a
composable alternative. The workspace-management e2e drops its native
picker monkey-patch and drives the real modal end-to-end via the
path-edit affordance.
2026-07-28 17:15:39 +08:00
ZiyaZhang fef928a7e1 feat(gui): add native workspace folder picker 2026-07-27 03:50:22 -07:00
NI0317 4701373fc2 fix(workspace): remove transient duplicate warning 2026-07-27 15:52:35 +08:00
NI0317 7bd96af5eb fix(workspace): make deletion recoverable 2026-07-27 14:37:04 +08:00
NI0317 187cf6f804 feat(web): delete workspace registrations 2026-07-27 12:38:11 +08:00
Tianyi Cui e2882f486b fix(review): harden web replay verification
Validate replay sidecars and cross-copy failure facts, make browser console tripwires and macOS temp paths deterministic, and wait for asynchronous TUI resume details. Keep the owning docs, translations, and generated catalog aligned.
2026-07-26 22:38:33 +08:00
Tianyi Cui f8342b0a8e test(web): cover the settings surface and workspace management
Two new keyless scenarios for the functionality master gained since this
lane's base (#644 websettings, #643 workspace browser rework), both zero
model calls:

- settings-chrome: the modal shell (sidebar-foot trigger aria states,
  role=dialog, aria-current section switch to the deliberately empty
  Models, Escape + close-button paths, dialog aria golden); the Appearance
  row as the REAL theme gesture — retiring lifecycle-chrome's
  TODO(web-theme-gesture): clicking 深色 runs aria-pressed -> persisted
  dsh.theme -> body[data-ds-dark-theme] -> alias-token flip, survives
  reload, and 'system' follows the emulated OS scheme both ways; the
  Language row switches the settings-scoped copy to English (dsh.locale
  persisted, survives reload) and restores zh. Intentional reloads tear
  the SSE stream, so the spec drains exactly its own reconnect warnings —
  the tripwire still fails on unexpected connection loss.
- workspace-management: create-by-name twice through the region-header
  dialog (host-durable via ctx.workspace.list()); rename end to end —
  hover-revealed row menu (the button is display:none until the row
  hovers), duplicate-name pre-check (inline role=alert + disabled primary
  before any wire call), then workspace.rename through the real RPC,
  row update, host durability, reload survival; the flat 'In one list'
  view (section label flips, group headers drop, dsh.workspace.view
  persists across reload, grouped restored); the session hover card
  (dwell to open, closes on pointer leave). The one session row reuses
  seeded-history's committed seed — no new recording. Deliberately not
  driven: the inert menu rows and drag reorder (deferred in the note
  with re-entry triggers).

Agent Note gains scenarios 8-9 and the drag-reorder deferred item in both
languages; llm-replay README's zh side catches up with the { patches }
paragraph; pairings re-recorded.
2026-07-26 20:38:36 +08:00