# 4-44 FileTree Action Layer Paste / Drop / Delete Checklist v1

> 状态：done
>
> 日期：2026-05-20
>
> Owner：File Tree actions / preflight / smoke semantics

## 1. 目标

补齐 P1：delete、paste、right-click paste、external drop 的动作层仍分散，缺少 dirty / readonly / undo / fallback 的统一动作合同。目标是先把现有行为收口成可测试的轻量 action layer，不一次性照搬 VSCode `IBulkEditService`。

## 2. 允许修改范围

- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
- `rust/crates/mnote-web/src/routes/tree.rs`
- `rust/crates/mnote-web/src/tree_shell/*` 中仅限 preflight / action contract
- `scripts/task430-vscode-explorer-stage7-smoke.js`
- `scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- 可新增聚焦 smoke：`scripts/task47*-filetree-action-layer-smoke.js`

## 3. 禁止事项

- 不删除旧 media / mindmap / table fallback route。
- 不把默认删除改成永久删除。
- 不绕过 readonly preflight。
- 不破坏多选 `data-selected` 语义。

## 4. Checklist

- [x] 提炼前端 File Tree action helper，统一记录 action、target、preflight、fallback、失败项。
- [x] delete 对 local folder 资源统一走 archive tree command，并暴露可观测 undo/fallback 占位状态。
- [x] right-click paste 使用当前菜单目标，而不是只能依赖 focused row。
- [x] paste / drop 对 readonly 目标有一致阻断提示和 DOM 标记。
- [x] external drop 二进制文件继续进入上传链路，失败时不清空 selection。
- [x] smoke 增加至少一个语义断言：目标 row、action 名、fallback/readonly/undo 状态之一。

## 5. 验收

- [x] `cargo test -p mnote-web layout -- --test-threads=1`
- [x] `cargo test -p mnote-web tree_command_local_folder -- --test-threads=1`
- [x] `node scripts/task430-vscode-explorer-stage7-smoke.js` — 2026-05-21 实跑通过，结论 `PASS_WITH_KNOWN_GAPS`：workspace bootstrap、F2 rename、cut/paste move、DnD preflight guard 通过；FileTree `data-active`、Open Editors、`Paste Into` 菜单与 readonly/重名冲突矩阵仍作为后续缺口记录。
- [x] `node scripts/task471-local-folder-bulk-resource-trash-smoke.js` — 2026-05-21 实跑通过，全部断言成功：多选两个资源行、确认文案含附件数、双 archive command、trash index 含两项、DOM 记录 `bulk-delete`/`archived`/触发 row。
- [ ] 如新增 smoke：`node scripts/task47*-filetree-action-layer-smoke.js`

## 5.1 本轮执行记录

- 已合入：`recordFileTreeAction` / `recordFileTreeActionStatus`，为 delete、paste、open-right、new-window 等现有路径暴露稳定 DOM 状态。
- 已合入：右键 `paste-into` 使用菜单触发 row，不再只能靠 focused row。
- 本轮追加：`layout.rs` 为 filetree projection row 暴露 `data-capabilities`，新增 `ensureFileTreeWritableTarget` / `blockReadonlyFileTreeAction`，paste 与内部 drop 在执行前复用 `/api/tree/filetree/drop-preflight`；readonly 目标统一写入 `data-mnote-filetree-last-action-status=blocked`、`data-mnote-filetree-readonly-blocked`、`data-mnote-filetree-readonly-message` 与目标 row 标记，并沿用 `alert` fallback 提示。
- 本轮追加：`task471-local-folder-bulk-resource-trash-smoke.js` 增加语义断言，覆盖 bulk-delete 的 action 名、触发 row 与 `archived` undo 状态；未修改 `task430` 的隔离 workspaceId 前置条件，避免把环境准备失败误判为业务回归。
- 2026-05-21 Reasonix Worker B 实跑：`node scripts/task471-local-folder-bulk-resource-trash-smoke.js` 通过，所有断言成功，无业务语义改动；更新验收 checklist 标记为 `[x]`。
- 2026-05-21 Codex 与 Reasonix Browser Worker 复核：`task430` / `task471` 均可在当前 3000 环境实跑。`task430` 的 Open Editors 与 active row 只记录现状，不作为本阶段业务失败；`task471` 的多选资源删除链路有截图与 JSON 证据。

## 6. 非目标

- 不实现完整 undo stack。
- 不实现 cloud object storage drop executor。
