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.
This commit is contained in:
creatixchu
2026-08-03 12:11:11 +08:00
parent 79072e356c
commit 30f442d42e
9 changed files with 124 additions and 23 deletions

View File

@@ -407,8 +407,11 @@ describe('web e2e: workspace management (create / rename / flat view / hover aff
it('walks the panes with the typed path: deeper past a separator, back up on erase, whole on a miss', async () => {
// The panes must track the draft without leaving the editor, so the
// typed text and what is listed under it never disagree.
// Staged by this scenario itself (mkdir is recursive and idempotent), so
// running it alone through -t sees the same tree the assertions describe.
const staged = join(scaffold.workspaceCwd, 'browse-golden')
await mkdir(join(staged, 'alpha', 'only-under-alpha'), { recursive: true })
await mkdir(join(staged, 'beta'), { recursive: true })
const dialog = await browseTo(staged)
await expect.poll(() => dialog.getByText('alpha', { exact: true }).count(), { timeout: 10_000 }).toBe(1)
await dialog.getByRole('button', { name: 'Edit path' }).click()