Files
deepseek-harness/.agents/notes/implemented/feature/2026-08-24-folder-reference-pick-vs-drill.zh.md
T
Yichen Jiang dad39c8c18 feat(web): settle folder references on pick and move descent to a drill verb
A directory row in the @ menu had one verb doing two jobs: picking it
inserted literal @dir/ text and kept the menu open, so a user wanting
the folder itself never got a settled entity — the token kept its
trigger character and stayed editable, nothing like a file's atomic
chip.

Split the intents on the same row, mapped to shell-completion instincts:
row click / Enter settles the directory as an atomic folder chip (the
file chip's exact language; canonical @dir/ mention as its serialized
form — the { insert } arm the folder path never took), while Tab or the
row's trailing chevron drills: literal editable text, menu open on the
children. One new dimension carries it: candidate.drill advertises the
verb, InputTriggerPick.action reports it, ArbitrateKey gains 'tab', and
the keymap intercepts Tab only while a drill row is highlighted.

Covered by controller arbitration, MenuView chevron routing, the
ui-reference verb split, a keymap Tab-passthrough spec, and a real-
browser e2e driving all three gestures; menu golden refreshed for the
chevron and the fixture directory.
2026-08-24 16:45:34 +08:00

3.2 KiB
Raw Blame History

Agent Note: 文件夹引用 pick 即选定;下钻移交给显式 drill 动词

Status: implemented

English | 中文

问题

@ 菜单里的目录行用一个动词干两件事。pick 它会插入字面 @dir/ 文本并保持菜单打开——那是抵达文件的下钻路径——于是想要文件夹本身作为上下文的用户永远得不到一个已选定的实体:token 保留触发字符、保持可编辑(继续输入 123 会继续筛选子项),与文件 pick 产出的原子 chip 完全不是一个物种。现场反馈附上竞品截图把期望说得很具体:选中的文件夹应当与选中的文件一样"定下来"。

决策

把两个意图拆成同一行上的两个动词,键位对齐 shell 补全直觉:

  • 选定(点击行主体 / Enter):目录解析为原子 folder chip——与文件 chip 完全同语言:文件夹图标、dir/ 标签、无触发字符、整体删除一个单位——序列化与剪贴板形式为规范 @dir/ mention。实现上就是文件夹路径从未走过的 { insert } 分支;appearance: 'folder' 端到端早已支持。
  • 钻取Tab / 行尾 chevron):原行为原样保留——字面可编辑的 @dir/ 文本,菜单对子项保持打开。

管线上是一个新维度而非平行通路:InputTriggerCandidate.drill?: boolean 声明第二动词(只有 ui-reference 的目录行设置),InputTriggerPick.action: 'pick' | 'drill' 报告实际执行的是哪一个,ArbitrateKey 增加 'tab'composer keymap 经与方向键相同的仲裁 helper 注册 KEY_TAB_COMMAND——'consumed' 才 preventDefault,其余情况原生焦点遍历不受影响。MenuView 只在 drill 行渲染 chevronoption 内的 role="button" span,与行同用 mousedown 保住 composer 焦点,stopPropagation 把行主体的选定 pick 挡在外面)。

曾考虑的替代方案

  • 菜单关闭时选定(菜单消失时把字面 @dir/ 自动固化为 chip):否决——可编辑 token 变实体的时机不可见且令人意外;手敲的 mention 保持诚实文本。
  • 点击钻取、行内专用按钮选定(反向映射):否决——选定是常见意图,应占据主手势;下钻是进阶细化,与 Tab 匹配。
  • 对字面文本 CSS 覆盖触发字符而不引入实体:早先在文件夹图标修复中已因同一原因否决——Lexical 文本节点无法拆出触发字符,而且字面文本本来就不是已选定的实体。

后果

  • pick 出的文件夹与文件是同一物种:原子、带图标标签、无 @、整体删除;手敲的 @dir/ 仍是带图标前缀的纯文本引用。
  • 忽略 actiononPick 实现行为与从前完全一致(既有路径全部报告 'pick');唯一的行为变化在 ui-reference 的目录分支。
  • 只有菜单高亮在 drill 行时才拦截 Tab;其余场合浏览器保有该键,由 keymap-routing spec 钉住。
  • 覆盖:controller 仲裁(drill / 普通行 / pick action)、MenuView chevron 路由、ui-reference 动词分流,以及在真实工作区目录上驱动全部三个手势(Enter 选定、Tab 钻取、chevron 钻取)的真浏览器 e2e。