refactor: extract hovered block index helper

This commit is contained in:
lix-2026
2026-05-25 07:00:53 +08:00
parent 4eda7179cc
commit 08f9d94d8f
6 changed files with 51 additions and 31 deletions
@@ -6,7 +6,7 @@
## 1. 目标
`3-19` 已归档的基础上,继续把仍留在 Rust inline / 主壳大 runtime 中的浏览器行为切成可审计模块。Codex 维护本文件作为事实源,Reasonix 只承接短批次审计、窄范围实现或浏览器 smoke;当前 goal 下每批最多 2 个 worker。
`3-19` 已归档的基础上,继续把仍留在 Rust inline / 主壳大 runtime 中的浏览器行为切成可审计模块。Codex 维护本文件作为事实源,Reasonix 只承接短批次审计、窄范围实现或浏览器 smoke;当前 goal 下每批最多 4 个 worker。
## 2. 本轮边界
@@ -64,7 +64,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
## 6. 本轮执行记录
- 2026-05-25Codex 创建本续跑事实源。
- 2026-05-25:修正执行约束:本文件遵循当前 goal 的“每批最多 2 个 worker”;实现 worker 必须在独立 worktree 产出候选 patchCodex 复核后再选择性合入。
- 2026-05-25:修正执行约束:本文件遵循当前 goal 的“每批最多 4 个 worker”;实现 worker 必须在独立 worktree 产出候选 patchCodex 复核后再选择性合入。
- 2026-05-25:下一批只派发 Worker Blocal upload / filetree 下一刀只读审计);Worker A/C/D 暂缓。
- 2026-05-25Reasonix local upload / filetree 只读审计尝试未产生 `result.json` / `process-handoff`,且运行期间出现额外 Batch A2 runner,主控已终止进程;该结果不作为正式 handoff 采纳。
- 可参考的 transcript 结论:`fetchWithTimeout` 是低风险纯工具函数,可先迁入 `local-upload-runtime.js``uploadFileToMediaAsset` / `uploadFilesWithResolvedTarget` / `insertUploadedAssetIntoEditor` 仍与 API、editor 插入和 snapshot refresh 耦合,暂不迁。
@@ -93,7 +93,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 修改:`rust/crates/mnote-web/browser/document-conflict-panel-runtime.js``rust/crates/mnote-web/src/routes/web_shell.rs`
- 已验证:`node --check rust/crates/mnote-web/browser/document-conflict-panel-runtime.js``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web document_conflict_panel_runtime_contains_dom_helpers -- --test-threads=1``cargo test --manifest-path rust/Cargo.toml -p mnote-web mnote_browser_runtime_assets_are_explicitly_mounted -- --test-threads=1`
- 未完成:conflict merge / accept / keep 业务逻辑、document session lifecycle、secondary pane conflict smoke 仍未迁出;本轮未声称真实冲突 UI 全链路完成。
- 2026-05-25:根据用户纠正,后续实现 worker 不能在主工作区直接修改;每批最多 2 个 worker,且必须采用独立 worktree 候选 patch 或明确只读任务。Codex 读取 Hindsight recall、`process-handoff.md/json``result.json`、diff 与验证证据后再选择性合入。
- 2026-05-25:根据用户纠正,后续实现 worker 不能在主工作区直接修改;每批最多 4 个 worker,且必须采用独立 worktree 候选 patch 或明确只读任务。Codex 读取 Hindsight recall、`process-handoff.md/json``result.json`、diff 与验证证据后再选择性合入。
- 2026-05-25Codex 主控完成非本地 media upload API 小切片:`local-upload-runtime.js` 新增并导出 `uploadMediaAsset(file, plan, context)`,承接 `/api/media/upload` 的 FormData 构造、fetch 和响应解析;`layout.rs``uploadFileToMediaAsset` 仍负责 appendUploadedAssetRow、editor 插入和 `wolai:assets-changed` 事件分发,并保留完整 inline fallback。
- 修改:`rust/crates/mnote-web/browser/local-upload-runtime.js``rust/crates/mnote-web/src/ssr/pages/layout.rs`
- 已验证:`node --check rust/crates/mnote-web/browser/local-upload-runtime.js``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web local_upload_runtime_contains_editor_upload_context_helpers -- --test-threads=1``cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_upload_runtime_routes_local_markdown_assets_to_local_folder -- --test-threads=1``node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
@@ -144,7 +144,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 2026-05-25Batch J 启动 Worker C`0525-j-worker-c-3-20-filetree-dom`)与 Worker D`0525-j-worker-d-3-20-conflict-action`),并同时存在 5-29 Worker B3 个 worker 超过当时旧“每批最多 2 个 worker”口径。Reasonix run `reasonix-2026-05-24T19-14-46-740Z-b6aed1df``reasonix-2026-05-24T19-14-46-748Z-c84c5ef9` 仅有 `prompt.md` / `memory-recall.json`,无 `final.md``result.json``process-handoff.md/json`worktree diff 为空;不采纳。
- 2026-05-25Batch J Codex 复核结论:Worker C / D 对应边界已在当前 HEAD 中具备,未重复合入新 diff。Worker C 已验证 `node --check rust/crates/mnote-web/browser/filetree-runtime.js``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web filetree_runtime_contains_row_accessor_helpers -- --test-threads=1`Worker D 已验证 `node --check rust/crates/mnote-web/browser/document-conflict-panel-runtime.js``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web document_conflict_panel_runtime_contains_dom_helpers -- --test-threads=1`
- 主工作区 smoke`NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js` 通过,截图证据 `/tmp/mnote-task479-lifecycle-xlAZrs/screenshots-1779650673787/final-state.png``NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task451-local-markdown-conflict-resolution-ui-smoke.js` 通过,结果 `/mnt/Data1T/mnote/tmp/task451-local-markdown-conflict-resolution-ui-smoke/result.json`
- 2026-05-25:当前 goal 按用户最新要求明确为每批最多 2 个 worker;后续 3-20 派发以 2 个为硬上限,历史记录中超过 2 个 worker 的批次保留为异常记录
- 2026-05-25:当前 goal 按用户最新要求明确为每批最多 4 个 worker;后续 3-20 派发以 4 个为硬上限。
- 2026-05-25:用户纠正 B/C/D 等实现任务也应在新的 worktree 中修改后再由 Codex 合并;主控已采用该口径:实现 worker 一律独立 worktree,主工作区不再直接扩大实现 diff,只保留事实源、复核和最终采纳。
- 2026-05-25Batch L Worker B `reasonix-2026-05-24T19-30-30-509Z-18f62949` 只读审计 `refreshLocalFolderSidebarSnapshot`Codex 已读取 Hindsight recall、`process-handoff.md/json``result.json`,并核对 worktree diff 为空。
- 审计结论:`refreshLocalFolderSidebarSnapshot` 仍是 shell 编排,包含 workspace/root/document 状态、两条 projection fetch、render 后副作用和 watcher 标记,不应整体迁入 `filetree-runtime.js`
@@ -166,17 +166,17 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- Worker 验证:`node --check scripts/task487-local-folder-tree-live-consumer-smoke.js`、限定 `git diff --check` 通过;因当时 3000 未启动,未运行真实浏览器 smoke。
- Codex 主控验证:`node --check scripts/task487-local-folder-tree-live-consumer-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task487-local-folder-tree-live-consumer-smoke.js`。结果仍为 RED`transport=local-folder-events`、PageTree/FileTree 外部变更阶段 `navigationEvents=0`,但 `treeLiveApplied` 仍为空,说明 live consumer 证据仍未收敛到 snapshot/resync。
- 2026-05-25Batch P Reasonix 派发失败并拒收:三个输出目录 `reasonix-2026-05-24T20-21-00-338Z-53f263c7` / `reasonix-2026-05-24T20-21-00-457Z-9384a1e5` / `reasonix-2026-05-24T20-21-00-569Z-8a3585e8` 均只有 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,没有 `result.json``process-handoff.md/json``final.md`;记录中的三个 worktree 目录当前不存在,Codex 未采纳任何 diff。后续 B/C/D 等实现 worker 必须在独立 worktree 产出候选 patch,再由 Codex 读取 Hindsight recall、handoff、diff 和验证证据后选择性合入。
- 2026-05-25Batch Q 未经主控批准再次自动启动 3 个 Reasonix runner`0525-q-worker-a/b/c-*`)。该批超过当前 2-worker 上限,不满足“主控短批次明确派发 + 完整 handoff”合同;三个输出目录 `reasonix-2026-05-24T20-27-26-922Z-9f1ffa2f` / `reasonix-2026-05-24T20-27-26-933Z-6ad5f071` / `reasonix-2026-05-24T20-27-26-955Z-ff208388` 均只有 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,没有 `result.json``process-handoff.md/json``final.md`;Codex 已终止进程,删除本轮自动生成的 3 份 batch-q 草稿并移除空 worktree,不采纳任何 Reasonix 结果。
- 2026-05-25Batch Q 未经主控批准再次自动启动 3 个 Reasonix runner`0525-q-worker-a/b/c-*`)。该批超过当前 4-worker 上限,不满足“主控短批次明确派发 + 完整 handoff”合同;三个输出目录 `reasonix-2026-05-24T20-27-26-922Z-9f1ffa2f` / `reasonix-2026-05-24T20-27-26-933Z-6ad5f071` / `reasonix-2026-05-24T20-27-26-955Z-ff208388` 均只有 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,没有 `result.json``process-handoff.md/json``final.md`;Codex 已终止进程,删除本轮自动生成的 3 份 batch-q 草稿并移除空 worktree,不采纳任何 Reasonix 结果。
- 2026-05-25Codex 修复本机 Reasonix runner / skill 的协同约束:`reasonix-coding-runner.mjs` 生成 prompt 时新增“Reasonix 是叶子 worker,禁止创建 `.codex/reasonix-tasks`、启动 runner/ACP/Claude/Codex/Hermes、操作其他 worktree”的硬约束;同步更新 `reasonix-coding-worker``reasonix-parallel-coding-flow` skill,并新增 runner `--dry-run` 用于不启动 Reasonix 的 prompt 合同 smoke。
- 已验证:`node --check reasonix-coding-runner.mjs``node --check reasonix-process-extractor.mjs``node --test reasonix-process-extractor.test.mjs`、runner `--dry-run --no-memory-recall` 输出的 `prompt.md` 含叶子 worker 禁止项,且 `ps` 未出现 `reasonix` / `reasonix-coding-runner` 进程。
- 2026-05-25Codex 独立复核并采纳 Batch Q Worker A 遗留候选 patch`local_folder_events.rs``treeLive=true` 且 watcher subscribe 失败时不再返回 500,而是返回同一 SSE 响应并降级为 revision polling;初始仍发送 `snapshot`revision 变化后通过既有 `rebuild_tree_resync_payload` 发送 `resync`。客户端 `tree:snapshot` / `tree:resync` consumer 不改,避免叠加 browser double-polling。该 patch 来自无 handoff 的失控 worker,未按 Reasonix 结果直接采纳,而是由 Codex 本地阅读 diff、跑验证后作为主控修复纳入。
- 修改:`rust/crates/mnote-web/src/routes/local_folder_events.rs`
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_live_polling_resync_payload_tracks_revision_changes -- --test-threads=1``cargo test --manifest-path rust/Cargo.toml -p mnote-web local_folder_events -- --test-threads=1``git diff --check``node --check scripts/task487-local-folder-tree-live-consumer-smoke.js`、临时 `MNOTE_WEB_BIND=127.0.0.1:3002 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3002 cargo run --manifest-path rust/Cargo.toml -p mnote-web` 后运行 `MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task487-local-folder-tree-live-consumer-smoke.js`,结果 `ok:true`PageTree/FileTree 外部创建/删除均为 `treeLiveApplied=resync`,两个阶段 `navigationEvents=0`
- 2026-05-25Batch Z 曾按旧/误写口径一次派发 4 个 Reasonix worker,其中 Worker C 负责 3-20 filetree refresh helperWorker D 负责 3-20 tree live smoke;该批超过当前 2-worker 上限,四个 run 均未产出 `final.md``result.json``process-handoff.md/json`worktree diff 为空,全部拒收。
- 2026-05-25Batch Z 曾一次派发 4 个 Reasonix worker,其中 Worker C 负责 3-20 filetree refresh helperWorker D 负责 3-20 tree live smoke;该批超过当前 4-worker 上限,四个 run 均未产出 `final.md``result.json``process-handoff.md/json`worktree diff 为空,全部拒收。
- 涉及 run`reasonix-2026-05-24T22-02-32-495Z-dfd6bb89``reasonix-2026-05-24T22-02-32-511Z-ea50d6e0``reasonix-2026-05-24T22-02-32-635Z-4edc4f8a``reasonix-2026-05-24T22-02-32-644Z-1180a395`
- 额外异常:Reasonix 仍创建 `.codex/reasonix-tasks/2026-05-25-batch-x-worker-a-5-29-dnd-dom-readonly.md` 草稿,违反叶子 worker 约束;该草稿不提交。
- 本批未采纳任何 3-20 diff。主工作区仅为 5-29 block transform 候选 patch 补跑 `task479-local-folder-markdown-resource-lifecycle-smoke.js` 作为资源生命周期回归,结果 `ok:true`,截图 `/tmp/mnote-task479-lifecycle-RJDsKO/screenshots-1779660971673/final-state.png`
- 2026-05-25Batch AA 后续按用户纠正重新执行独立 worktree B/C/D 流程;该批超过当前 2-worker 上限,应视为异常历史记录。Reasonix C 无 handoff / 零 diff,拒收;独立 worktree worker C `/mnt/Data1T/mnote-worktrees/0525-aa-worker-c-3-20-filetree-refresh-helper` 产出并通过主控复核后选择性合入。
- 2026-05-25Batch AA 后续按用户纠正重新执行独立 worktree B/C/D 流程;该批超过当前 4-worker 上限。Reasonix C 无 handoff / 零 diff,拒收;独立 worktree worker C `/mnt/Data1T/mnote-worktrees/0525-aa-worker-c-3-20-filetree-refresh-helper` 产出并通过主控复核后选择性合入。
- 修改:`filetree-runtime.js` 新增并导出 `applyLocalFolderSidebarSnapshot(nextDocument, options)`,复用 `replaceSidebarTreeFromDocument`,默认应用 `sidebar-tree-root``sidebar-file-tree-root`,并支持 `onApplied` 回调;`layout.rs` 新增同名 inline fallback wrapper 和字符串断言。
- 边界:未改 `refreshLocalFolderSidebarSnapshot` 的 fetch URL、projection JSON 渲染主路径、watcher 标记、focus/selection/sidebar shell 副作用;不把 HTML snapshot 应用重新接入主刷新流程。
- Worker C 验证:`git diff --check``node --check rust/crates/mnote-web/browser/filetree-runtime.js``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web filetree_runtime -- --test-threads=1` 通过。
@@ -185,3 +185,8 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 修改:`filetree-runtime.js` 新增并导出 `markLocalFolderWatchApplied(value)``layout.rs` 的同名 wrapper 优先委托 runtimeinline fallback 保留 `data-mnote-local-folder-watch-applied="projection"` 行为。
- 边界:未改 projection fetch URL、JSON 渲染、selection/focus/sidebar shell 副作用、附件存在性刷新、tree live SSE consumer;本批只外置刷新完成证据标记。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-runtime.js``git diff --check``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/Cargo.toml -p mnote-web``cargo test --manifest-path rust/Cargo.toml -p mnote-web filetree_runtime -- --test-threads=1`
- 2026-05-25Batch AC 按用户纠正继续采用独立 worktree 流程;当前 goal 上限为每批最多 4 个 worker,本轮实际 3 个 worker,未超过上限;任务书均写入各 worktree `tmp/`,未新增主工作区 `.codex/reasonix-tasks`
- Worker C `/mnt/Data1T/mnote-worktrees/0525-ac-worker-c-3-20-conflict-action-boundary`Reasonix run `reasonix-2026-05-24T22-52-30-772Z-464df4b4`Codex 已读取 Hindsight recall、`process-handoff.md/json``result.json`,并核对 worktree `git status --short` / `git diff --stat` 为空。
- 审计结论经 Codex 复核后采纳:`acceptDiskVersion``keepCurrentEditorVersion``writeMergedConflictResult` 仍强依赖 fetch、persist、session views、Tiptap hydrate、conflict key 计算和 `setSessionStatus`,不应整体迁入 `document-conflict-panel-runtime.js`;共享的 session 状态字段重置块暂不外置,以保持 runtime=DOM/promise wrapper、shell=业务编排的边界。
- Worker D `/mnt/Data1T/mnote-worktrees/0525-ac-worker-d-smoke-regression`Reasonix run `reasonix-2026-05-24T22-52-30-854Z-dfad6786`,源码零 diff`task489``task488``task487``task451` 在 3001 均通过,其中 `task451` 覆盖 accept-disk、keep-current、merge-save、agent-conflict-source。
- 未完成:conflict action 业务逻辑仍留在 `web_shell.rs`secondary pane conflict 专项 smoke 仍可后续单独补强。
@@ -6,7 +6,7 @@
## 1. 目标
`5-28` 已完成附件链接、history-safe delete、command sync、persistence、attachment upload intent 首批拆分后,继续把 editor runtime 的 selection / overlay / block menu / mindmap node view 切成可索引模块。Codex 维护本文件作为事实源,Reasonix 只做短批次审计、窄范围实现或浏览器 smoke;当前 goal 下每批最多 2 个 worker。
`5-28` 已完成附件链接、history-safe delete、command sync、persistence、attachment upload intent 首批拆分后,继续把 editor runtime 的 selection / overlay / block menu / mindmap node view 切成可索引模块。Codex 维护本文件作为事实源,Reasonix 只做短批次审计、窄范围实现或浏览器 smoke;当前 goal 下每批最多 4 个 worker。
## 2. 本轮边界
@@ -69,7 +69,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 已迁函数:`node_is_within_root``active_editor_text_selection``has_active_text_selection``selection_summary``selection_has_rich_marks`
- 未迁:`SelectionPayload``selection_payload``send_selection_state*``selection_event_payload`,原因是仍依赖 bridge event、`HoveredBlockState` 和 runtime block id 边界。
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``task488``task489`、CodeGraph pending 0。
- 2026-05-25:执行口径修正:继续遵循当前 goal 的“每批最多 2 个 worker”;Reasonix 后续必须使用独立 worktree 或明确只读任务,完成后由 Codex 读取 handoff 并复核。
- 2026-05-25:执行口径修正:继续遵循当前 goal 的“每批最多 4 个 worker”;Reasonix 后续必须使用独立 worktree 或明确只读任务,完成后由 Codex 读取 handoff 并复核。
- 2026-05-25Batch D 额外 runner 曾自动启动 Worker A / Worker B,未经过本轮主控计划确认;主控已终止相关 runner / ACP 进程,不采纳这些未受控 run。遗留 task 草稿暂不删除,后续如继续使用必须重新生成受控任务书。
- 2026-05-25Reasonix runner 异常:后续实现 run 未写 `result.json``process-handoff.md/json`,部分 transcript 停在工具调用阶段;Codex 不采纳其文字结论,只复核实际 diff。
- 2026-05-25Reasonix overlay / block menu 只读审计尝试未产生 `result.json` / `process-handoff`,且运行期间出现额外 Batch A2 runner,主控已终止进程;该结果不作为正式 handoff 采纳。
@@ -136,7 +136,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 修改:`rust/spikes/leptos-tiptap-spike/src/lib.rs`、generated island `js/d.ts/wasm/wasm.d.ts`
- 已验证:在独立 worktree 中运行 `cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen`;主工作区复跑 `NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js` 均通过,结果分别位于 `/mnt/Data1T/mnote/tmp/task489-block-menu-delete-undo-smoke/result.json``/mnt/Data1T/mnote/tmp/task488-local-attachment-link-delete-undo-smoke/result.json`
- 未完成:`try_sync_editor_overlay_state``on_selection_change` overlay 同步、block menu signal 编排仍未迁出;本轮未扩大迁移边界。
- 2026-05-25:当前 goal 按用户最新要求明确为每批最多 2 个 worker;后续 Batch 计划和 Reasonix 派发以 2 个为硬上限,历史记录中超过 2 个 worker 的批次保留为异常记录
- 2026-05-25:当前 goal 按用户最新要求明确为每批最多 4 个 worker;后续 Batch 计划和 Reasonix 派发以 4 个为硬上限。
- 2026-05-25:用户纠正 B/C/D 等实现任务也应在新的 worktree 中修改后再由 Codex 合并;主控已采用该口径:实现 worker 一律独立 worktree,主工作区不再直接扩大实现 diff,只保留事实源、复核和最终采纳。
- 2026-05-25Batch K 只派发 1 个只读 Reasonix worker 审计 `close_editor_floating_overlays` 迁出边界,使用独立 worktree `/mnt/Data1T/mnote-worktrees/0525-k-5-29-close-overlays-readonly`run id `reasonix-2026-05-24T19-18-51-566Z-90f11977`,并显式使用 `--no-memory-recall` 降低任务串线风险。
- Codex 已读取 Hindsight recall、`process-handoff.md/json``result.json`,并核对 worktree `git status --short` / `git diff --stat` 为空。
@@ -200,14 +200,14 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 未迁/未删:`send_selection_state_to_target`、selection event dispatch、`send_selection_state``selection_event_payload``runtime_state_payload``runtime_status_payload` 等未使用 bridge/helper 函数;死代码清理后续单独切片处理。
- 2026-05-25Batch W 只派发 1 个只读 Reasonix worker 审计 selection / bridge 死代码清理边界,使用独立 worktree `/mnt/Data1T/mnote-worktrees/0525-w-worker-a-5-29-selection-deadcode-readonly`run id `reasonix-2026-05-24T21-36-28-065Z-75d6e2e8`,并显式使用 `--no-memory-recall`
- Codex 已读取 Hindsight recall、`process-handoff.md/json``result.json`,并核对 worktree `git status --short` / `git diff --stat` 为空;Reasonix 未修改源码。
- 主控发现随后残留/未授权 Reasonix runner:除本只读 worker 外还存在 Worker B/C/D runner 或 ACP 进程;该批超过当前 2-worker 上限,不满足主控明确派发与完整 handoff 合同,已终止相关进程,且不采纳被终止 worker 的任何输出。
- 主控发现随后残留/未授权 Reasonix runner:除本只读 worker 外还存在 Worker B/C/D runner 或 ACP 进程;该批超过当前 4-worker 上限,不满足主控明确派发与完整 handoff 合同,已终止相关进程,且不采纳被终止 worker 的任何输出。
- 审计结论经 Codex 复核后采纳:删除无调用方私有函数 `send_selection_state``selection_event_payload``dispatch_bridge_event``current_runtime_block_info``current_runtime_block_info_from_hovered``runtime_state_payload``runtime_status_payload`
- 保留:`send_selection_state_to_target``dispatch_selection_event_to_target``current_block_info_from_index``state_payload``status_payload`,原因是仍有真实调用方或作为当前替代链路使用。
- 修改:`rust/spikes/leptos-tiptap-spike/src/lib.rs`、generated island wasm。
- 当前执行约束同步修正:`3-20` / `5-29` checklist 均保持“当前 goal 下每批最多 2 个 worker”。
- 当前执行约束同步修正:`3-20` / `5-29` checklist 均保持“当前 goal 下每批最多 4 个 worker”。
- 已验证:`git diff --check``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js``codegraph sync .``codegraph status . --json` pending 0。
- 2026-05-25Batch X 计划只派发 1 个只读 Reasonix worker 审计 block DnD DOM 边界,任务书 `.codex/reasonix-tasks/2026-05-25-batch-x-worker-a-5-29-dnd-dom-readonly.md`worktree `/mnt/Data1T/mnote-worktrees/0525-x-worker-a-5-29-dnd-dom-readonly`
- 派发异常:启动本只读 worker 后,又出现未由主控批准的 Worker A/B/C/D runner 与 ACP 进程;该批超过当前 2-worker 上限,不满足主控明确派发与完整 handoff 合同。主控已终止全部 `reasonix-coding-runner` / `reasonix acp` / `reasonix/dist/cli/index.js acp` 进程,本批不采纳任何 Reasonix 输出。
- 派发异常:启动本只读 worker 后,又出现未由主控批准的 Worker A/B/C/D runner 与 ACP 进程;该批超过当前 4-worker 上限,不满足主控明确派发与完整 handoff 合同。主控已终止全部 `reasonix-coding-runner` / `reasonix acp` / `reasonix/dist/cli/index.js acp` 进程,本批不采纳任何 Reasonix 输出。
- Codex 主控改为本地最小机械切片:`editor_runtime/block_dnd.rs` 新增 `element_within_handle_shell(element, handle_selector)`,只封装 handle-shell DOM predicate`lib.rs``hovered_block_from_target`、editor stage click / mousemove / dragover 调用点改为委托该 helper。
- 未迁:`hovered_block_from_target``drop_indicator_from_target``drop_indicator_from_point`、拖拽 listener、block reorder 行为和 DOM -> block 状态解析链仍留在 `lib.rs`
- 修改:`rust/spikes/leptos-tiptap-spike/src/editor_runtime/block_dnd.rs``rust/spikes/leptos-tiptap-spike/src/lib.rs`
@@ -217,7 +217,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 未迁:`target_element` 仍被图片 toolbar 和事件 listener 共用;`hovered_block_from_target``drop_indicator_from_target``drop_indicator_from_point`、拖拽 listener、block reorder 行为和 DOM -> block 状态解析链仍留在 `lib.rs`
- 修改:`rust/spikes/leptos-tiptap-spike/src/editor_runtime/block_dnd.rs``rust/spikes/leptos-tiptap-spike/src/lib.rs`、generated island `js/wasm`
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 2026-05-25Batch Z 曾按旧/误写口径一次派发 4 个 Reasonix worker,均使用独立 worktreeA 只读审计 block transform、B 实现 block transform、C 实现 3-20 filetree refresh helper、D 运行 3-20 live smoke;该批超过当前 2-worker 上限。
- 2026-05-25Batch Z 曾一次派发 4 个 Reasonix worker,均使用独立 worktreeA 只读审计 block transform、B 实现 block transform、C 实现 3-20 filetree refresh helper、D 运行 3-20 live smoke;该批超过当前 4-worker 上限,但四个 run 均不满足 handoff 合同
- Reasonix run `reasonix-2026-05-24T22-02-32-495Z-dfd6bb89` / `reasonix-2026-05-24T22-02-32-511Z-ea50d6e0` / `reasonix-2026-05-24T22-02-32-635Z-4edc4f8a` / `reasonix-2026-05-24T22-02-32-644Z-1180a395` 均只有 `prompt.md``memory-recall.json``reasonix-transcript.jsonl`,无 `final.md``result.json``process-handoff.md/json`;四个 worktree diff 为空,按采纳规则全部拒收。
- 额外异常:Reasonix 仍创建 `.codex/reasonix-tasks/2026-05-25-batch-x-worker-a-5-29-dnd-dom-readonly.md` 草稿,违反叶子 worker 约束;该草稿不纳入本文件事实源、不提交。
- Codex 随后在独立 worktree `/mnt/Data1T/mnote-worktrees/0525-x-worker-b-5-29-block-transform-impl` 产出并复核候选 patch:把仍有真实调用方的 `paragraph_node``collect_plain_text``mindmap_paragraph_node` 迁入 `editor_runtime/block_menu_document.rs`,删除 `lib.rs` 中无调用方的旧 JSON transform 死链 `list_item_node``task_item_node``inline_from_first_child``extract_inline_content``turn_into_block``replace_top_level_block_kind` 及图片占位常量。
@@ -229,7 +229,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 修改:`rust/spikes/leptos-tiptap-spike/src/editor_runtime/block_menu_document.rs`
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js`
- 验证说明:复用已有 3001 长跑服务时 `task479` 连续两次卡在 missing 标记等待点;改用本批临时启动的干净 3002 服务复跑后通过,判定为长跑服务状态问题,不作为本批回归。
- 2026-05-25Batch AA 后续按用户纠正重新执行“B/C/D 必须在独立 worktree 修改后再由 Codex 合并”流程;本轮最多 3 个并行 worker,超过当前 2-worker 上限,应视为异常历史记录
- 2026-05-25Batch AA 后续按用户纠正重新执行“B/C/D 必须在独立 worktree 修改后再由 Codex 合并”流程;本轮最多 3 个并行 worker,超过当前 4-worker 上限。
- Reasonix B/C/D 分别在 `/mnt/Data1T/mnote-worktrees/0525-aa-worker-b-5-29-block-transform-finish``/mnt/Data1T/mnote-worktrees/0525-aa-worker-c-3-20-filetree-refresh-helper``/mnt/Data1T/mnote-worktrees/0525-aa-worker-d-3-20-live-smoke` 运行;B/C run 仅有空 transcript / 无 handoff / 零 diff,拒收;D run `reasonix-2026-05-24T22-26-26-122Z-62733e93` 有完整 `process-handoff.md/json``result.json` 和截图,源码零 diff。
- Codex 随后改派独立 worktree worker 完成 B/CB 的 block transform 结果已被当前主线提交 `ee81fafe` / `d59a248c` 覆盖,不再重复套旧 worktree patchC 的 3-20 helper 由主控复核后选择性合入 3-20 事实源。
- D smoke 证据:`task487-local-folder-tree-live-consumer-smoke.js` 在 3001 通过,`transport=local-folder-events`、PageTree/FileTree 外部创建/删除均为 `treeLiveApplied=resync`,主框架导航数为 0;截图位于 `/mnt/Data1T/mnote-worktrees/0525-aa-worker-d-3-20-live-smoke/tmp/task487-local-folder-tree-live-consumer-smoke/`
@@ -239,3 +239,12 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 修改:`rust/spikes/leptos-tiptap-spike/src/lib.rs`
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3002 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 本轮主控复核:`MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js` 均通过。
- 2026-05-25Batch AC 未派发 Reasonix workerCodex 复核并采纳当前工作区已有的 block DnD 小切片。
- 修改:`editor_runtime/block_dnd.rs` 新增 `direct_block_index_from_element(element, root, handle_selector)`,统一封装“排除 handle shell + 解析直接顶层块 index”;`lib.rs::hovered_block_from_target` 改为委托该 helper,仍保留 `target_element``block_state_from_index`、拖拽 listener 和 reorder 行为在壳层。
- 边界:未迁 `target_element``drop_indicator_from_target``drop_indicator_from_point`、block reorder HTML 行为、DOM event listener 或 Leptos signal 编排。
- 已验证:`cargo fmt --manifest-path rust/Cargo.toml --all --check``git diff --check``cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml`、wasm release build、`wasm-bindgen``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task489-block-menu-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task488-local-attachment-link-delete-undo-smoke.js``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3001 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 2026-05-25Batch AC 按用户纠正继续采用独立 worktree 流程;当前 goal 上限为每批最多 4 个 worker,本轮实际 3 个 worker,未超过上限;任务书均写入各 worktree `tmp/`,未新增主工作区 `.codex/reasonix-tasks`
- Worker B `/mnt/Data1T/mnote-worktrees/0525-ac-worker-b-5-29-hover-target-helper`Reasonix run `reasonix-2026-05-24T22-52-30-715Z-4b6e4d37`Codex 已读取 Hindsight recall、`process-handoff.md/json``result.json` 和 worktree diffworker 临时创建的未跟踪 `reference-code` symlink 未采纳。
- Codex 选择性合入 Worker B 的两文件候选 patch`editor_runtime/block_dnd.rs` 新增 `direct_block_index_from_element(element, root, handle_selector)`,封装 handle-shell 过滤、direct block 解析和 top-level index 查询;`lib.rs::hovered_block_from_target` 仍负责 root/target 壳层获取和 `block_state_from_index` 状态组装。
- Worker D `/mnt/Data1T/mnote-worktrees/0525-ac-worker-d-smoke-regression`Reasonix run `reasonix-2026-05-24T22-52-30-854Z-dfad6786`,源码零 diff`task489``task488``task487``task451` 在 3001 均通过,其中 `task487``transport=local-folder-events`、PageTree/FileTree 外部创建/删除均 `treeLiveApplied=resync`、导航数为 0。
- 未迁:`hovered_block_from_target` 的壳层函数、`drop_indicator_from_target`、拖拽 listener、block reorder 行为仍留在 `lib.rs`
@@ -1270,7 +1270,7 @@ function __wbg_get_imports() {
},
__wbindgen_cast_0000000000000003: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 973, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`.
const ret = makeClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hdac387fb9e511e9c);
const ret = makeClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__had771ddc65647798);
return ret;
},
__wbindgen_cast_0000000000000004: function(arg0, arg1) {
@@ -1285,7 +1285,7 @@ function __wbg_get_imports() {
},
__wbindgen_cast_0000000000000006: function(arg0, arg1) {
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 892, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hc2416b32e405336e);
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf);
return ret;
},
__wbindgen_cast_0000000000000007: function(arg0, arg1) {
@@ -1359,8 +1359,8 @@ function wasm_bindgen__convert__closures_____invoke__h396914cf76a9e7a5(arg0, arg
wasm.wasm_bindgen__convert__closures_____invoke__h396914cf76a9e7a5(arg0, arg1, arg2);
}
function wasm_bindgen__convert__closures_____invoke__hdac387fb9e511e9c(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__hdac387fb9e511e9c(arg0, arg1, arg2);
function wasm_bindgen__convert__closures_____invoke__had771ddc65647798(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__had771ddc65647798(arg0, arg1, arg2);
}
function wasm_bindgen__convert__closures_____invoke__h0abd2b2fe4652e2a(arg0, arg1, arg2) {
@@ -1371,8 +1371,8 @@ function wasm_bindgen__convert__closures_____invoke__h396914cf76a9e7a5_4(arg0, a
wasm.wasm_bindgen__convert__closures_____invoke__h396914cf76a9e7a5_4(arg0, arg1, arg2);
}
function wasm_bindgen__convert__closures_____invoke__hc2416b32e405336e(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__hc2416b32e405336e(arg0, arg1, arg2);
function wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf(arg0, arg1, arg2);
}
function wasm_bindgen__convert__closures_____invoke__h3a3182d847094e12(arg0, arg1, arg2) {
@@ -95,6 +95,18 @@ pub(crate) fn direct_block_from_element(mut element: Element, root: &Element) ->
}
}
pub(crate) fn direct_block_index_from_element(
element: &Element,
root: &Element,
handle_selector: &str,
) -> Option<usize> {
if element_within_handle_shell(element, handle_selector) {
return None;
}
let block = direct_block_from_element(element.clone(), root)?;
top_level_block_index(root, &block)
}
pub(crate) fn top_level_block_index(root: &Element, block: &Element) -> Option<usize> {
let children = root.children();
(0..children.length()).find_map(|index| {
+4 -10
View File
@@ -22,9 +22,9 @@ use web_sys::{
use editor_runtime::attachment_upload::dispatch_editor_upload_request;
use editor_runtime::block_dnd::{
direct_block_from_element, drop_indicator_from_geometry, element_within_handle_shell,
event_target_from_point, pointer_in_handle_corridor_geometry, top_level_block_index,
HandleCorridorGeometry,
direct_block_from_element, direct_block_index_from_element, drop_indicator_from_geometry,
element_within_handle_shell, event_target_from_point,
pointer_in_handle_corridor_geometry, top_level_block_index, HandleCorridorGeometry,
};
use editor_runtime::block_menu_overlay;
use editor_runtime::block_menu_document::{
@@ -4880,13 +4880,7 @@ fn trap_scroll_inside_menu(event: &WheelEvent) {
fn hovered_block_from_target(target: web_sys::EventTarget) -> Option<HoveredBlockState> {
let root = editor_root_element()?;
let element = target_element(target)?;
if element_within_handle_shell(&element, HANDLE_SHELL_SELECTOR) {
return None;
}
let block = direct_block_from_element(element, &root)?;
let index = top_level_block_index(&root, &block)?;
let index = direct_block_index_from_element(&element, &root, HANDLE_SHELL_SELECTOR)?;
block_state_from_index(index)
}