{ "version": 2, "created": "2026-04-17T07:58:16Z", "session_config": { "concurrency_mode": "exclusive", "max_tasks_per_session": 12, "max_sessions": 120 }, "tasks": [ { "id": "task-001", "title": "执行 Stage A-1:固定首页与 /api/sidebar 主路径只走 Convex/Rust 主链,禁止默认回落到 mnote-web compat/sidebar,并把 tree shell 默认运行态切成显式开关", "status": "completed", "priority": "P0", "depends_on": [], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/app/api/sidebar/route.ts src/lib/runtime-config.ts src/components/sidebar/sidebar.tsx src/components/sidebar/MnoteWebTreeShell.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst route = fs.readFileSync('src/app/api/sidebar/route.ts', 'utf8');\nconst runtime = fs.readFileSync('src/lib/runtime-config.ts', 'utf8');\nconst sidebar = fs.readFileSync('src/components/sidebar/sidebar.tsx', 'utf8');\nconst shell = fs.readFileSync('src/components/sidebar/MnoteWebTreeShell.tsx', 'utf8');\nconst envJson = JSON.parse(fs.readFileSync('public/mnote-env.json', 'utf8'));\nif (/fetchSidebarDatasetFromMnoteWeb|getMnoteWebBaseUrl\\(/.test(route)) throw new Error('route.ts 仍残留 mnote-web compat 主路径');\nif (!runtime.includes('parseRuntimeBoolean(cfg.mnoteWebTreeShellEnabled) ?? false')) throw new Error('runtime-config.ts 未把 tree shell 默认值固定为 false');\nif (!sidebar.includes('mnoteWebTreeShellEnabled === true')) throw new Error('sidebar.tsx 未收紧为显式开关');\nif (!shell.includes('mnoteWebTreeShellEnabled === true')) throw new Error('MnoteWebTreeShell.tsx 未收紧为显式开关');\nif (envJson.mnoteWebTreeShellEnabled !== false) throw new Error('public/mnote-env.json 未默认关闭 tree shell');\nconsole.log('task-001-boundary-ok');\nNODE", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [], "completed_at": "2026-04-17T08:03:15Z" }, { "id": "task-002", "title": "执行 Stage A-2:收紧 move/embed picker 的实验壳边界,tree shell 关闭时不再额外请求 viewer/tree-shell 依赖,空查询路径继续只消费稳定 projection 数据", "status": "completed", "priority": "P0", "depends_on": [ "task-001" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/components/documents/move-embed-picker-dialog.tsx src/components/documents/move-embed-picker-host.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst dialog = fs.readFileSync('src/components/documents/move-embed-picker-dialog.tsx', 'utf8');\nif (!dialog.includes('const treeShellEnabled =')) throw new Error('picker 未显式计算 treeShellEnabled');\nif (!dialog.includes('enabled: Boolean(workspaceId) && isEmptyQuery && treeShellEnabled')) throw new Error('viewerQuery 仍会在 tree shell 关闭时触发');\nconsole.log('task-002-picker-boundary-ok');\nNODE", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [], "completed_at": "2026-04-17T08:06:06Z" }, { "id": "task-003", "title": "执行 Stage A-3:新增并跑通 3000 首页入口 smoke,验证在 3104 不可用时首页主链仍可进入 /auth 或已登录文档页,不因实验壳阻塞", "status": "completed", "priority": "P0", "depends_on": [ "task-001", "task-002" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "cd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js", "timeout_seconds": 600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [], "completed_at": "2026-04-17T08:12:27Z" }, { "id": "task-004", "title": "执行 Stage B-1:继续收缩前端树域真相泄漏,确认主路径 consumer 只消费 kernel projection,兼容 helper 不再回到运行时主链", "status": "completed", "priority": "P1", "depends_on": [ "task-001", "task-002" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/components/sidebar/sidebar.tsx src/components/documents/move-embed-picker-dialog.tsx src/components/documents/move-embed-picker-host.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst sidebar = fs.readFileSync('src/components/sidebar/sidebar.tsx', 'utf8');\nconst picker = fs.readFileSync('src/components/documents/move-embed-picker-dialog.tsx', 'utf8');\nconst host = fs.readFileSync('src/components/documents/move-embed-picker-host.tsx', 'utf8');\nfor (const [name, source] of [['sidebar', sidebar], ['picker', picker], ['host', host]]) {\n if (source.includes('buildDocumentTree(')) throw new Error(name + ' 仍残留 buildDocumentTree 主路径依赖');\n}\nconsole.log('task-004-tree-truth-mainpath-ok');\nNODE", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [], "completed_at": "2026-04-17T08:11:55Z" }, { "id": "task-005", "title": "执行 Stage B-2:梳理 sidebar/page/filetree 的 create/rename/move 命令入口,给出并落第一批 Rust command envelope 收口边界,避免前端继续扩散树语义", "status": "completed", "priority": "P1", "depends_on": [ "task-004" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote')\npath = root / 'design/tree-command-envelope-cutover-stage1-v1.md'\ntext = path.read_text(encoding='utf-8')\nassert 'sidebar.tsx' in text\nassert 'create / rename / move' in text or 'create/rename/move' in text\nprint('task-005-command-cutover-doc-ok')\nPY", "timeout_seconds": 120 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 2, "description": "已审计 sidebar/document-content/CustomSideMenu 与 create/title/move route,确认第一批 tree command 已接入 envelope,但入口与部分树策略仍散落在前端组件层。", "timestamp": "2026-04-17T08:32:00Z" }, { "step": 2, "total": 2, "description": "已新增共享 tree command client,并产出 design/tree-command-envelope-cutover-stage1-v1.md 固定第一批 cutover 边界与顺序。", "timestamp": "2026-04-17T08:40:10Z" } ], "completed_at": "2026-04-17T08:40:10Z" }, { "id": "task-006", "title": "执行 Stage C-1:为 Rust Web 正式实时树事件流补方案与接缝说明,明确 Convex substrate 与 Rust semantic owner 的订阅职责划分", "status": "completed", "priority": "P2", "depends_on": [ "task-003", "task-005" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote')\npath = root / 'design/rust-web-tree-realtime-event-stream-v1.md'\ntext = path.read_text(encoding='utf-8')\nassert 'Convex substrate' in text or 'Convex' in text\nassert 'Rust semantic owner' in text or 'Rust' in text\nprint('task-006-realtime-doc-ok')\nPY", "timeout_seconds": 120 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已产出 design/rust-web-tree-realtime-event-stream-v1.md,明确 Convex substrate、Rust semantic owner、Rust Web SSE/WS transport 与前端 projection consumer 的职责划分。", "timestamp": "2026-04-17T08:42:00Z" } ], "completed_at": "2026-04-17T08:42:00Z" }, { "id": "task-007", "title": "执行 Stage C-2:回写新的 harness 批次状态、阶段完成度与长期口径,明确哪些已进入稳定主链,哪些仍属于实验壳/后续阶段", "status": "completed", "priority": "P1", "depends_on": [ "task-003", "task-004", "task-005", "task-006" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote')\nassert (root / 'harness-tasks.json').exists()\nassert (root / 'harness-progress.txt').exists()\nprint('task-007-harness-sync-ok')\nPY", "timeout_seconds": 120 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已回写 harness 状态与进度,并验证修复 dev server 的 Convex HTTP 代理后,3000 首页基线恢复:/auth 返回 200,/ 根路径稳定进入 /auth。", "timestamp": "2026-04-17T08:56:30Z" } ], "completed_at": "2026-04-17T08:56:30Z" }, { "id": "task-008", "title": "执行 Stage P0-1:补首页/sidebar/tree shell 主链回归护栏,固化 3000 首屏、Convex live 优先与实验壳显式开关约束", "status": "completed", "priority": "P0", "depends_on": [ "task-007" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/hooks/use-sidebar-data.ts src/hooks/use-convex-sidebar-data.ts src/components/sidebar/sidebar.tsx src/components/sidebar/MnoteWebTreeShell.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst useSidebarData = fs.readFileSync('src/hooks/use-sidebar-data.ts', 'utf8');\nconst useConvexSidebarData = fs.readFileSync('src/hooks/use-convex-sidebar-data.ts', 'utf8');\nconst sidebar = fs.readFileSync('src/components/sidebar/sidebar.tsx', 'utf8');\nconst shell = fs.readFileSync('src/components/sidebar/MnoteWebTreeShell.tsx', 'utf8');\nif (!useSidebarData.includes('!convexSidebar.hasLiveSubscription && convexSidebar.canUseHttpFallback')) throw new Error('use-sidebar-data.ts 丢失 Convex live 优先护栏');\nif (!useConvexSidebarData.includes('const hasLiveSubscription = shouldFetch')) throw new Error('use-convex-sidebar-data.ts 丢失 live subscription 判定');\nif (!sidebar.includes('runtimeConfig.mnoteWebTreeShellEnabled === true')) throw new Error('sidebar.tsx 未显式门控 tree shell');\nif (!shell.includes('readyTimerRef.current = window.setTimeout')) throw new Error('MnoteWebTreeShell.tsx 缺少超时 fallback 护栏');\nconsole.log('task-008-guardrails-ok');\nNODE\ncd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js", "timeout_seconds": 900 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已验证 Convex live 优先、tree shell 显式门控与首页 smoke;3104 不可达时 3000 仍稳定回到 /auth。", "timestamp": "2026-04-17T15:54:10Z" } ], "completed_at": "2026-04-17T15:54:10Z", "claimed_by": "SESSION-3", "lease_expires_at": "2026-04-17T16:22:02Z" }, { "id": "task-009", "title": "执行 Stage P1-1:把 delete/restore/purge 收口到 shared tree command client,并让 Sidebar/DocumentContent 退出对应直调 route", "status": "completed", "priority": "P1", "depends_on": [ "task-008" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/lib/documents/tree-command-client.ts src/components/sidebar/sidebar.tsx src/components/editor/document-content.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst client = fs.readFileSync('src/lib/documents/tree-command-client.ts', 'utf8');\nconst sidebar = fs.readFileSync('src/components/sidebar/sidebar.tsx', 'utf8');\nconst documentContent = fs.readFileSync('src/components/editor/document-content.tsx', 'utf8');\nfor (const name of ['deleteDocumentCommand', 'restoreDocumentCommand', 'purgeDocumentCommand']) {\n if (!client.includes(`export async function ${name}`)) throw new Error(`tree-command-client.ts 缺少 ${name}`);\n}\nfor (const [name, source] of [['sidebar', sidebar], ['document-content', documentContent]]) {\n if (source.includes('fetch(\"/api/documents/delete\"') || source.includes(\"fetch('/api/documents/delete'\")) throw new Error(name + ' 仍直调 /api/documents/delete');\n if (source.includes('fetch(\"/api/documents/restore\"') || source.includes(\"fetch('/api/documents/restore'\")) throw new Error(name + ' 仍直调 /api/documents/restore');\n if (source.includes('fetch(\"/api/documents/purge\"') || source.includes(\"fetch('/api/documents/purge'\")) throw new Error(name + ' 仍直调 /api/documents/purge');\n}\nconsole.log('task-009-tree-command-client-delete-restore-purge-ok');\nNODE", "timeout_seconds": 600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补 shared tree command client 的 delete/restore/purge,并移除 Sidebar/DocumentContent 对应 route 直调。", "timestamp": "2026-04-17T15:58:30Z" } ], "completed_at": "2026-04-17T15:58:30Z", "claimed_by": "SESSION-3", "lease_expires_at": "2026-04-17T16:24:10Z" }, { "id": "task-010", "title": "执行 Stage P1-2:处理 pageReference 删除路径,移除 CustomSideMenu 中对 /api/documents/delete 的直调", "status": "completed", "priority": "P1", "depends_on": [ "task-009" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已让 CustomSideMenu 的 pageReference 删除改走 shared tree command client。", "timestamp": "2026-04-17T15:58:30Z" } ], "completed_at": "2026-04-17T15:58:30Z" }, { "id": "task-011", "title": "执行 Stage P1-3:为 embed 定义独立 Rust page-tree command,并让 Sidebar/DocumentContent 改走 shared embed client", "status": "completed", "priority": "P1", "depends_on": [ "task-010" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已把 embed 收口为独立 documents.embed 命令,并补齐 TS/Rust 映射与测试。", "timestamp": "2026-04-17T16:15:19Z" } ], "completed_at": "2026-04-17T16:15:19Z" }, { "id": "task-012", "title": "执行 Stage P1-4:把 copy-tree 收口到 shared tree command client,移除 Sidebar 中文档复制的直调 route", "status": "completed", "priority": "P1", "depends_on": [ "task-011" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已确认 copy-tree 继续走 shared tree command client 与 Rust bridge command 主链,Sidebar 不再直调 route。", "timestamp": "2026-04-17T16:15:19Z" } ], "completed_at": "2026-04-17T16:15:19Z" }, { "id": "task-013", "title": "执行 Stage P2-1:把 targetParentId / sortOrder / subtree move legality 收口到 Rust/bridge 主链,并补回归测试", "status": "completed", "priority": "P2", "depends_on": [ "task-012" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补 page-lifecycle-command-adapter 测试并收口 move/copy-tree 的 targetParentId、sortOrder 与 subtree move legality 归一化。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-014", "title": "执行 Stage P2-2:统一 sidebar/page/file 的 kernel projection 契约,逐步移除前端本地 synthetic projection/fallback 真相", "status": "completed", "priority": "P2", "depends_on": [ "task-013" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已移除主路径 projection fallback/synthetic projection id,sidebar/page/file 的 projection 契约改为只认上游 kernel 输出。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-015", "title": "执行 Stage P2-3:清理 compat/fallback 与实验壳重复树拼装,确保主路径 consumer 只消费统一 projection", "status": "completed", "priority": "P2", "depends_on": [ "task-014" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已确认 Sidebar/picker/host 主路径不再残留旧树拼装,sidebar-data 主路径不再本地合成 kernel projection。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-016", "title": "执行 Stage P3-1:把 Rust Web SSE/WS 从 placeholder 升级为 workspace/subtree snapshot stream", "status": "completed", "priority": "P3", "depends_on": [ "task-015" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已把 Rust Web SSE/WS 升级为 workspace/subtree snapshot stream,并复用统一 snapshot/stream support。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-017", "title": "执行 Stage P3-2:接入 snapshot + delta + resync 协议与前端 tree stream consumer,逐步切 Sidebar/filetree/page subtree", "status": "completed", "priority": "P3", "depends_on": [ "task-016" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已接入 useSidebarTreeStream 正式 consumer,并补齐 snapshot/delta/resync 协议与 reducer 测试。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-018", "title": "执行 Stage P4-1:让 Rust Web 接住正式 SSR 页面壳与 server-first projection 分发,前端退回必要 islands", "status": "completed", "priority": "P4", "depends_on": [ "task-017" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已验证 Rust Web kernel projection SSR 路由、前端 server data lint 与首页 smoke,主链仍不依赖 3104 可用。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-019", "title": "执行 Stage QA-1:统一跑前端测试并修复必须修复的 bug,确保架构收口后的主链交互与关键回归稳定", "status": "completed", "priority": "P0", "depends_on": [ "task-018" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已跑通前端全量测试并修复必须修复 bug:AiAgentPanel 过期断言与 tree stream 连接错误路由。", "timestamp": "2026-04-17T16:35:06Z" } ], "completed_at": "2026-04-17T16:35:06Z" }, { "id": "task-020", "title": "执行 Stage P4-2:回写长期架构文档与 harness 状态,勾选 design/tree-first-graph-convex-rust-long-term-architecture-v1.md 全部 checklist", "status": "completed", "priority": "P0", "depends_on": [ "task-019" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "aa6ee384", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已回写长期架构文档并清空全部 checklist,harness 状态已完成收尾。", "timestamp": "2026-04-17T16:36:54Z" } ], "completed_at": "2026-04-17T16:36:54Z" }, { "id": "task-021", "title": "执行 TreeShell Phase A-1:产出共享 tree projection contract 文档,冻结 sidebar_tree/page_tree/file_tree 共用字段与差异字段", "status": "completed", "priority": "P0", "depends_on": [ "task-020" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已产出共享 tree projection contract 文档,并冻结 sidebar_tree/page_tree/file_tree 的共享字段、row_id 与 resource_meta 口径。", "timestamp": "2026-04-17T23:18:26Z" } ], "completed_at": "2026-04-17T23:18:26Z" }, { "id": "task-022", "title": "执行 TreeShell Phase A-2:落地前后端共享 projection 类型,并冻结 file_tree 扩展字段与 capability/icon/resource 语义", "status": "completed", "priority": "P0", "depends_on": [ "task-021" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补齐前后端共享 projection 类型与 file_tree 扩展字段,并跑通 core-protocol 与 tree-protocol 目标测试。", "timestamp": "2026-04-17T23:18:30Z" } ], "completed_at": "2026-04-17T23:18:30Z" }, { "id": "task-023", "title": "执行 TreeShell Phase A-3:固定树域 command protocol 长期命名面,并给出 documents.* 到 tree.* 的兼容迁移文档", "status": "completed", "priority": "P0", "depends_on": [ "task-022" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已冻结 tree.* 长期命名面,并把 documents.* 到 tree.* 的兼容映射与 cutover 顺序写入设计文档。", "timestamp": "2026-04-17T23:18:34Z" } ], "completed_at": "2026-04-17T23:18:34Z" }, { "id": "task-024", "title": "执行 TreeShell Phase A-4:明确 projection 状态与本地 UI 状态边界,并形成 Rust/前端共享的状态约束文档", "status": "completed", "priority": "P0", "depends_on": [ "task-023" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已固定 projection truth 与本地 UI state 的边界,并锁定 expanded、selected、focus、dragging、drop target 不进入 projection。", "timestamp": "2026-04-17T23:18:38Z" } ], "completed_at": "2026-04-17T23:18:38Z" }, { "id": "task-025", "title": "执行 TreeShell Phase A-5:补齐 projection/command protocol fixtures 与 contract tests,锁死后续 Phase B-D 的协议基线", "status": "completed", "priority": "P0", "depends_on": [ "task-024" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已新增 projection/command protocol contract tests,并跑通前端 fixtures 与 mnote-web tree_projection_contract 验证。", "timestamp": "2026-04-17T23:18:42Z" } ], "completed_at": "2026-04-17T23:18:42Z" }, { "id": "task-026", "title": "执行 TreeShell Phase B-1:在 mnote-web 补正式 sidebar_tree/page_tree/file_tree projection route 族,退出“只靠 kernel sidebar 兼容入口”阶段", "status": "completed", "priority": "P0", "depends_on": [ "task-025" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补齐 mnote-web 的 sidebar/page/file projection route 族,并重新验证 tree projection routes。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-027", "title": "执行 TreeShell Phase B-2:让 Rust 直接输出 file_tree projection 的 document/index/asset 行语义,前端退出同类 synthetic row 真相", "status": "completed", "priority": "P0", "depends_on": [ "task-026" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "Rust 已直接输出 file_tree projection 的 document/index/asset 行语义,前端 rows 测试通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-028", "title": "执行 TreeShell Phase B-3:继续扩充 file_tree projection 到 book/pdf/index/iconHint/capabilities,收缩前端 adapter 责任", "status": "completed", "priority": "P1", "depends_on": [ "task-027" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "Rust file_tree mapper 已扩展到 book/pdf/index/iconHint/capabilities,并验证资源变体测试。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-029", "title": "执行 TreeShell Phase B-4:把树域 command 主协议切到 tree.*,保留 documents.* alias 与迁移护栏", "status": "completed", "priority": "P1", "depends_on": [ "task-028" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "树域 command 主协议已切到 tree.*,同时保留 documents.* alias 与共享 client 回归通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-030", "title": "执行 TreeShell Phase B-5:补齐树域 route 的 trace/workspace/auth 边界与契约测试,防止主链继续依赖页面私有约定", "status": "completed", "priority": "P1", "depends_on": [ "task-029" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "树域 route 契约已补齐 trace/workspace/auth 边界,tree_route_contracts 测试通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-031", "title": "执行 TreeShell Phase B-6:收口 Next 树域 consumer,只保留 transport/compat 边界,退出前端主路径拼树时代", "status": "completed", "priority": "P1", "depends_on": [ "task-030" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "Next 树域主路径已收口为 transport/compat,eslint 通过且 buildDocumentTree 主路径检查通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-032", "title": "执行 TreeShell Phase C-1:为 Rust Web 正式树域 UI 壳补 Leptos scaffold、loader/dispatcher/state 骨架与 route 接缝", "status": "completed", "priority": "P0", "depends_on": [ "task-031" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "mnote-web 已接入 Leptos tree shell scaffold,tree_shell 模块与 loader/dispatcher/state 骨架测试通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-033", "title": "执行 TreeShell Phase C-2:补正式 page_tree renderer 与交互通路,打通 create/rename/move/navigate 到真实网页 smoke", "status": "completed", "priority": "P0", "depends_on": [ "task-032" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "page_tree renderer 与真实网页 smoke 已跑通;task091 创建/重命名/移动/导航链路通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-034", "title": "执行 TreeShell Phase C-3:补 selection/focus/keyboard/dragging 的本地 UI state 机理,明确不回写 projection truth", "status": "completed", "priority": "P0", "depends_on": [ "task-033" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "selection/focus/keyboard/dragging 的局部 UI state 已落地并通过 Rust 测试与文档检查。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-035", "title": "执行 TreeShell Phase C-4:补正式 tree shell 的上下文菜单、基础动作、file_tree renderer 与 picker 轻量模式", "status": "completed", "priority": "P0", "depends_on": [ "task-034" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "正式 tree shell 的 filetree/picker 轻量模式已补齐,新增 move-embed-picker-dialog 前端测试并通过。", "timestamp": "2026-04-18T00:38:02Z" } ], "completed_at": "2026-04-18T00:38:02Z" }, { "id": "task-036", "title": "执行 TreeShell Phase C-5:去掉主路径对 iframe/postMessage 实验壳的依赖,把旧 tree shell 降回 compat/debug 用途", "status": "completed", "priority": "P0", "depends_on": [ "task-035" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f1c1bcf0", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已从 sidebar.tsx 主路径移除 iframe/postMessage 实验壳依赖,Sidebar 主树回到统一 surface。", "timestamp": "2026-04-18T01:37:10Z" } ], "completed_at": "2026-04-18T01:37:10Z", "claimed_by": "SESSION-4" }, { "id": "task-037", "title": "执行 TreeShell Phase D-1:在 Next 正式挂载新 tree shell,并完成 Sidebar 主树默认切流与快速回退护栏", "status": "completed", "priority": "P0", "depends_on": [ "task-036" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已完成 Sidebar 主树默认切流与 fallback 护栏,task101 网页 smoke 通过。", "timestamp": "2026-04-18T01:37:10Z" } ], "completed_at": "2026-04-18T01:37:10Z" }, { "id": "task-038", "title": "执行 TreeShell Phase D-2:完成 filetree/page tree/picker 默认切流,并补高频路径回归 smoke", "status": "completed", "priority": "P0", "depends_on": [ "task-037" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已完成 page/filetree/picker 默认切流与高频回归,task102 与前端测试通过。", "timestamp": "2026-04-18T01:37:10Z" } ], "completed_at": "2026-04-18T01:37:10Z" }, { "id": "task-039", "title": "执行 TreeShell Phase D-3:记录树域切流性能指标与真实流量回退结果,形成 cutover/perf 报告", "status": "completed", "priority": "P1", "depends_on": [ "task-038" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补性能报告,记录首包、首次可交互、切页延迟、大树展开延迟与 fallback。", "timestamp": "2026-04-18T01:37:10Z" } ], "completed_at": "2026-04-18T01:37:10Z" }, { "id": "task-040", "title": "执行 TreeShell Phase E-1:删除剩余 page/file 特殊拼装逻辑,继续拆分 Sidebar 超大组件,并统一 page/file/picker renderer 家族", "status": "completed", "priority": "P1", "depends_on": [ "task-039" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已统一 page/file/picker renderer surface,sidebar.tsx 不再直接耦合旧树组件名。", "timestamp": "2026-04-18T01:37:10Z" } ], "completed_at": "2026-04-18T01:37:10Z" }, { "id": "task-041", "title": "执行 Final QA:回写架构文档与 harness 状态,勾选 design/sidebar-pagetree-filetree-rust-web-rebuild-v1.md 全部 checklist 并完成最终验收", "status": "completed", "priority": "P0", "depends_on": [ "task-040" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "4538f85d", "validation": { "command": "true", "timeout_seconds": 60 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已更新设计文档 checklist 并跑通最终 smoke、pnpm test、cargo test。", "timestamp": "2026-04-18T01:37:10Z" } ], "completed_at": "2026-04-18T01:37:10Z" }, { "id": "task-042", "title": "执行 Kernel Phase 7-1:把文档页 pageSubtree 固化为服务端首包与 /api/documents/content 稳定响应契约,减少前端读链即时拼装", "status": "completed", "priority": "P0", "depends_on": [ "task-041" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/documents/page-subtree-response.test.ts && pnpm eslint src/app/api/documents/content/route.ts src/app/'(app)'/documents/[id]/page.tsx src/components/editor/document-content.tsx", "timeout_seconds": 1800 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已把 pageSubtree 固化为 SSR 首包与 /api/documents/content 响应契约,并补齐共享归一化 helper 与单测。", "timestamp": "2026-04-18T02:00:05Z" } ], "completed_at": "2026-04-18T02:00:05Z" }, { "id": "task-043", "title": "执行 Kernel Phase 7-2:让 DocumentContent/DocumentReadView 优先消费服务端 pageSubtree,仅在本地编辑偏离后回退到前端重建", "status": "completed", "priority": "P0", "depends_on": [ "task-042" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test && pnpm eslint src/components/editor/document-content.tsx src/components/editor/document-read-view.tsx", "timeout_seconds": 3600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已让 DocumentContent 优先消费服务端 pageSubtree 快照,仅在标题或内容偏离服务端快照时才本地重建。", "timestamp": "2026-04-18T02:00:05Z" } ], "completed_at": "2026-04-18T02:00:05Z" }, { "id": "task-044", "title": "执行 Kernel Phase 7-3:补文档页 read-view/pageSubtree 回归测试,并验证 3000 首页与文档页在 3104/Convex 现状下不挂起", "status": "completed", "priority": "P0", "depends_on": [ "task-043" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js && timeout 8s curl -fsS 'http://127.0.0.1:3000/documents/test?workspaceId=test' >/dev/null || true && cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/documents/page-subtree-response.test.ts", "timeout_seconds": 1800 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补 pageSubtree 响应单测,跑通前端全量测试、首页 smoke,并确认当前 3000 主链未因 3104/Convex 挂起。", "timestamp": "2026-04-18T02:00:05Z" } ], "completed_at": "2026-04-18T02:00:05Z" }, { "id": "task-045", "title": "执行 Kernel Phase 7-4:把 pageSubtree/read_view 真正下沉到 bridge-runtime 与 mnote-web 输出边界,退出前端 projection 生成主路径", "status": "completed", "priority": "P0", "depends_on": [ "task-044" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime && cargo test -p mnote-web", "timeout_seconds": 3600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 2, "description": "已为 documents.content.get 补齐 Rust page_subtree 输出、mnote-web /api/documents/content route 与对应测试,cargo test -p bridge-runtime / mnote-web 通过。", "timestamp": "2026-04-18T03:33:58Z" }, { "step": 2, "total": 2, "description": "已切除前端 pageSubtree 主路径 fallback,文档页现在只消费 Rust 输出契约;pnpm vitest / pnpm test 通过。", "timestamp": "2026-04-18T03:38:08Z" } ], "completed_at": "2026-04-18T03:38:08Z" }, { "id": "task-046", "title": "执行 Kernel Phase 7-5:让 Next 文档页 SSR 与 /api/documents/content 优先消费 Rust 输出契约,移除前端 pageSubtree 主路径 fallback", "status": "completed", "priority": "P0", "depends_on": [ "task-045" ], "attempts": 0, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/app/api/documents/content/route.ts src/app/'(app)'/documents/[id]/page.tsx src/components/editor/document-content.tsx src/components/editor/document-read-view.tsx && pnpm vitest run src/lib/documents/page-subtree-response.test.ts", "timeout_seconds": 3600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已让 page-subtree-response、DocumentContent、DocumentReadView 退出 pageSubtree 主路径 fallback,SSR/API 只透传 Rust 输出契约。", "timestamp": "2026-04-18T03:38:08Z" } ], "completed_at": "2026-04-18T03:38:08Z" }, { "id": "task-047", "title": "执行 Kernel Phase 7-6:补文档页 read-view/outline/backlinks/AI context 回归,确认 read-path 收口后的读态契约稳定", "status": "completed", "priority": "P0", "depends_on": [ "task-046" ], "attempts": 0, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test", "timeout_seconds": 5400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已跑通 pnpm test,确认文档读态、outline、AI context 与现有 backlinks 面板在 read-path 收口后仍稳定。", "timestamp": "2026-04-18T03:38:08Z" } ], "completed_at": "2026-04-18T03:38:08Z" }, { "id": "task-048", "title": "执行 BlockEditor Phase 0-1:盘点现有 BlockNote 自定义块、读写耦合与第一阶段迁移范围,冻结必须做/后补/延期清单", "status": "completed", "priority": "P0", "depends_on": [ "task-047" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-phase0-baseline-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['heading', 'advancedTodo', 'pageReference', 'blockReference', 'media', 'progressMeter', 'mindmap', 'onlineTable']:\n assert needle in text, needle\nprint('task-048-phase0-baseline-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已冻结 BlockNote 自定义块、读写耦合与第一阶段迁移范围,产出 phase0 baseline 文档。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-049", "title": "执行 BlockEditor Phase 0-2:盘点 mnote-next 交互样例并沉淀新 editor core 回归样例集,只把它当内部样本不当 benchmark", "status": "completed", "priority": "P1", "depends_on": [ "task-048" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-interaction-samples-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['单块编辑', '插入同级块', '空块退格合并上一块', '单块删除', '上移下移', '有限缩进', '行内页面引用', '块引用占位插入', '不作为主 benchmark']:\n assert needle in text, needle\nprint('task-049-interaction-samples-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已从 mnote-next 提取单块编辑、拆块合并、有限缩进、引用插入等内部交互样例,沉淀回归样例集。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-050", "title": "执行 BlockEditor Phase 0-3:冻结 edita-core/blocks/kode/leptos-tiptap 采用矩阵,并把第一阶段能力边界回写主设计文档", "status": "completed", "priority": "P1", "depends_on": [ "task-049" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\nmain_text = Path('/mnt/Data1T/mnote/design/blocknote/ai-first-rust-block-editor-baseline-v1.md').read_text(encoding='utf-8')\nmatrix_text = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-adoption-matrix-v0.md').read_text(encoding='utf-8')\nassert 'AI-first 的轻量块 Markdown 编辑器' in main_text\nassert '先复用参考层,只有缺口才自研胶水' in main_text\nfor needle in ['edita-core', 'blocks', 'kode', 'leptos-tiptap', '采用', '不采用', '部分采用']:\n assert needle in matrix_text, needle\nprint('task-050-adoption-matrix-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已冻结 edita-core/blocks/kode/leptos-tiptap 采用矩阵,并把第一阶段能力边界回写主设计文档。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-051", "title": "执行 BlockEditor Phase 1-1:完成 edita-core 最小 spike 与适配性评估,明确 Editor/Block/Command/无头执行边界的可复用面", "status": "completed", "priority": "P0", "depends_on": [ "task-050" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-edita-spike-v0.md').read_text(encoding='utf-8')\nfor needle in ['Editor', 'Block', 'Command', '无头执行', '胶水']:\n assert needle in text, needle\nprint('task-051-edita-spike-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已完成 edita-core 最小 spike 与适配性评估,明确 Editor/Block/Command/无头执行边界与胶水范围。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-052", "title": "执行 BlockEditor Phase 1-2:完成 blocks 最小 spike 与 Markdown/history/diff-merge 适配性评估,记录可直接采用与缺口", "status": "completed", "priority": "P0", "depends_on": [ "task-051" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-blocks-spike-v0.md').read_text(encoding='utf-8')\nfor needle in ['Markdown', 'round-trip', 'history', 'diff', 'merge', '缺口']:\n assert needle in text, needle\nprint('task-052-blocks-spike-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已完成 blocks 最小 spike 与 Markdown/history/diff-merge 适配性评估,记录可直接采用能力与缺口。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-053", "title": "执行 BlockEditor Phase 1-3:定义首批 Rust block type、BlockProps、reference token 策略与 content_node 载荷格式,退出 BlockNote JSON 长期依赖", "status": "completed", "priority": "P0", "depends_on": [ "task-052" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-model-v0.md').read_text(encoding='utf-8')\nfor needle in ['paragraph', 'heading', 'bullet_list_item', 'todo', 'page_reference', 'block_reference', 'BlockProps', 'content_node']:\n assert needle in text, needle\nprint('task-053-block-model-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已定义首批 Rust block type、BlockProps、reference token 策略与 content_node 载荷格式,并产出模型文档。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-054", "title": "执行 BlockEditor Phase 1-4:定义 editor command 列表、editor 到 kernel command 映射与 Markdown import/export 边界,产出阶段 1 采用矩阵 v0", "status": "completed", "priority": "P0", "depends_on": [ "task-053" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-command-contract-v0.md').read_text(encoding='utf-8')\nfor needle in ['replace_block', 'insert_block_after', 'delete_block', 'split_block', 'merge_with_previous', 'move_block', 'indent_block', 'outdent_block', 'toggle_heading_collapse', 'attach_reference_token', 'detach_reference_token', 'Markdown import', 'Markdown export']:\n assert needle in text, needle\nprint('task-054-command-contract-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已定义 editor command 列表、editor 到 kernel command 映射与 Markdown import/export 边界,产出命令契约文档。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-055", "title": "执行 BlockEditor Phase 2-1:在 Rust workspace 搭建最小 block editor core crate,落地 block document 内存模型与只读结构树派生", "status": "completed", "priority": "P0", "depends_on": [ "task-054" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-editor-core document_model", "timeout_seconds": 3600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已在 Rust workspace 搭建最小 block editor core crate,落地 block document 内存模型与只读结构树派生。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-056", "title": "执行 BlockEditor Phase 2-2:实现最小 command executor,覆盖 replace/insert/delete/split/merge/move/indent/outdent/toggle collapse", "status": "completed", "priority": "P0", "depends_on": [ "task-055" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-editor-core command_executor", "timeout_seconds": 3600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已实现最小 command executor,覆盖 replace/insert/delete/split/merge/move/indent/outdent/toggle collapse,并补纯 Rust 测试。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-057", "title": "执行 BlockEditor Phase 2-3:实现 undo/redo 与 Markdown import/export,优先复用 blocks 或明确缺口清单", "status": "completed", "priority": "P0", "depends_on": [ "task-056" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-editor-core history && cargo test -p mnote-editor-core markdown", "timeout_seconds": 3600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已实现 undo/redo 与 Markdown import/export,优先复用最小 blocks 风格历史与转换边界,测试通过。", "timestamp": "2026-04-18T04:01:11Z" } ], "completed_at": "2026-04-18T04:01:11Z" }, { "id": "task-058", "title": "执行 BlockEditor Phase 2-4:补纯 Rust 回归测试与 CLI 入口,沉淀从 mnote-next 抽取的交互样例集", "status": "completed", "priority": "P1", "depends_on": [ "task-057" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-editor-core && cargo test -p mnote-cli", "timeout_seconds": 5400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补纯 Rust 回归测试、CLI editor 入口,并沉淀 mnote-next 交互样例集;cargo test -p mnote-editor-core 与 cargo test -p mnote-cli 通过。", "timestamp": "2026-04-18T05:32:17Z" } ], "completed_at": "2026-04-18T05:32:17Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:17Z" }, { "id": "task-059", "title": "执行 BlockEditor Prototype 3-1:在 mnote-web 搭建最小 Rust 文档壳 prototype 与 feature flag,文档页先走双路径切换", "status": "completed", "priority": "P0", "depends_on": [ "task-058" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web && cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/app/'(app)'/documents/[id]/page.tsx src/components/editor/document-content.tsx", "timeout_seconds": 5400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已在 mnote-web /document 落地最小 Rust 文档编辑壳,文档页通过 runtime flag 保持双路径切换;cargo test -p mnote-web 与 eslint 通过。", "timestamp": "2026-04-18T05:32:18Z" } ], "completed_at": "2026-04-18T05:32:18Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:18Z" }, { "id": "task-060", "title": "执行 BlockEditor Prototype 3-2:完成 kode/kode-leptos 策略评估,固定 block list/focus/selection/hover prototype 外壳", "status": "completed", "priority": "P0", "depends_on": [ "task-059" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web block_editor_shell", "timeout_seconds": 5400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已固定 block list / focus / selection / hover 壳策略,当前采用 Rust shell + 最小 DOM 交互语义,kode 保持为块内输入器参考层;cargo test -p mnote-web block_editor_shell 通过。", "timestamp": "2026-04-18T05:32:19Z" } ], "completed_at": "2026-04-18T05:32:19Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:19Z" }, { "id": "task-061", "title": "执行 BlockEditor Prototype 3-3:在 document shell prototype 中落地 slash 菜单、heading 折叠、有限缩进与 [[page]]/((block)) 最小引用交互", "status": "completed", "priority": "P0", "depends_on": [ "task-060" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web editor_interactions && cd /mnt/Data1T/mnote/wolai-frontend && pnpm test", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已落地 slash 菜单、heading 折叠、有限缩进、[[page]] / ((block)) 最小引用交互;cargo test -p mnote-web editor_interactions 与 pnpm test 通过。", "timestamp": "2026-04-18T05:32:20Z" } ], "completed_at": "2026-04-18T05:32:20Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:20Z" }, { "id": "task-062", "title": "执行 BlockEditor Prototype 3-4:补 prototype 浏览器回归链并确保新 UI 壳首屏不依赖 HocuspocusProvider/Yjs/comments/旧 BlockNoteView", "status": "completed", "priority": "P0", "depends_on": [ "task-061" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补浏览器回归链,默认新壳首屏不依赖旧 BlockNote/Yjs/comments;task103 与 pnpm test 通过。", "timestamp": "2026-04-18T05:32:21Z" } ], "completed_at": "2026-04-18T05:32:21Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:21Z" }, { "id": "task-063", "title": "执行 BlockEditor Phase 4-1:定义 AI/CLI 共用的 Rust editor command tool contract,禁止 AI 再模拟 DOM/UI", "status": "completed", "priority": "P0", "depends_on": [ "task-062" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-ai-tool-contract-v0.md').read_text(encoding='utf-8')\nfor needle in ['insert_block_after', 'replace_block', 'delete_block', 'move_block', 'set_block_type', 'indent_block', 'outdent_block', 'toggle_heading_collapse', 'CLI', 'AI']:\n assert needle in text, needle\nprint('task-063-ai-tool-contract-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已冻结 AI/CLI 共用的 Rust editor command tool contract,并明确 AI 不再模拟 DOM/UI。", "timestamp": "2026-04-18T05:32:22Z" } ], "completed_at": "2026-04-18T05:32:22Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:22Z" }, { "id": "task-064", "title": "执行 BlockEditor Phase 4-2:打通纯文本导入、AI 结构化成块与按目标重写文档链路,并补 command 审计信息", "status": "completed", "priority": "P0", "depends_on": [ "task-063" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-editor-core ai_pipeline && cargo test -p mnote-cli ai_pipeline", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已打通纯文本导入、AI 结构化成块与按目标重写文档链路,并补齐审计与 change report;ai_pipeline 测试通过。", "timestamp": "2026-04-18T05:32:23Z" } ], "completed_at": "2026-04-18T05:32:23Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:23Z" }, { "id": "task-065", "title": "执行 BlockEditor Phase 4-3:补 AI 回归样例,覆盖 markdown 草稿结构化、会议记录转待办、长段落提炼标题与页面重排", "status": "completed", "priority": "P1", "depends_on": [ "task-064" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-cli ai_regression && cd /mnt/Data1T/mnote/wolai-frontend && pnpm test", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补 ai_regression_* 回归样例,覆盖会议记录转待办、长段落提炼标题、页面重排;cargo test -p mnote-cli ai_regression 与 pnpm test 通过。", "timestamp": "2026-04-18T05:32:24Z" } ], "completed_at": "2026-04-18T05:32:24Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:24Z" }, { "id": "task-066", "title": "执行 BlockEditor Phase 5-1:盘点 BlockNote 入口、依赖与内容格式迁移策略,形成主路径退场与 compat/debug 保留方案", "status": "completed", "priority": "P0", "depends_on": [ "task-065" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/rust-block-editor-blocknote-migration-v1.md').read_text(encoding='utf-8')\nfor needle in ['@blocknote/core', 'blocknote-editor.tsx', 'schema.ts', 'HocuspocusProvider', 'Yjs', 'compat', 'debug']:\n assert needle in text, needle\nprint('task-066-blocknote-migration-ok')\nPY", "timeout_seconds": 300 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已完成 BlockNote 入口、依赖与内容格式迁移策略盘点,并保留 compat/debug 方案文档。", "timestamp": "2026-04-18T05:32:25Z" } ], "completed_at": "2026-04-18T05:32:25Z", "claimed_by": "SESSION-9", "lease_expires_at": "2026-04-18T06:02:25Z" }, { "id": "task-067", "title": "执行 BlockEditor P0-0:冻结新的 Tiptap/Leptos/Rust 迁移基线,确认官方 notion-like 模板只作为体验 benchmark,mnote-web runtime shell 继续只保留 debug/prototype 边界", "status": "completed", "priority": "P0", "depends_on": [ "task-066" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-leptos-rust-migration-checklist-v1.md').read_text(encoding='utf-8')\ntext2 = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-notion-like-template-adoption-v1.md').read_text(encoding='utf-8')\nassert 'notion-like-editor' in text\nassert 'leptos-tiptap' in text\nassert 'runtime shell' in text\nassert '体验 benchmark' in text2\nprint('task-067-migration-baseline-frozen')\nPY2", "timeout_seconds": 600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已冻结新的 Tiptap/Leptos/Rust 迁移基线:notion-like 模板仅作体验 benchmark,leptos-tiptap 作为运行时接入层,mnote-web runtime shell 继续只保留 debug/prototype。", "timestamp": "2026-04-18T17:51:55Z" } ], "claimed_by": "SESSION-11", "lease_expires_at": null, "completed_at": "2026-04-18T17:51:55Z" }, { "id": "task-068", "title": "执行 BlockEditor P0-1:补齐 leptos-tiptap 的 task_list/task_item Rust 暴露、运行时注册与 spike 真 schema 验证,替换当前 todo HTML 占位", "status": "completed", "priority": "P0", "depends_on": [ "task-067" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo +1.89.0 check --manifest-path /mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/Cargo.toml && cd /mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike && env -u NO_COLOR trunk build --release && node - <<'NODE'\nconst fs = require('fs');\nconst cargo = fs.readFileSync('/mnt/Data1T/mnote/design/blocknote/reference-code/leptos-tiptap/Cargo.toml', 'utf8');\nconst ext = fs.readFileSync('/mnt/Data1T/mnote/design/blocknote/reference-code/leptos-tiptap/src/api/extensions.rs', 'utf8');\nconst ffi = fs.readFileSync('/mnt/Data1T/mnote/design/blocknote/reference-code/leptos-tiptap/src/runtime/ffi.rs', 'utf8');\nconst reg = fs.readFileSync('/mnt/Data1T/mnote/design/blocknote/reference-code/leptos-tiptap/src/runtime/registration.rs', 'utf8');\nif (!cargo.includes('task_item') || !cargo.includes('task_list')) throw new Error('Cargo features 未补 task_list/task_item');\nif (!ext.includes('TaskItem') || !ext.includes('TaskList')) throw new Error('extensions.rs 未暴露 TaskItem/TaskList');\nif (!ffi.includes('register_task_item') || !ffi.includes('register_task_list')) throw new Error('ffi.rs 未暴露 task 注册');\nif (!reg.includes('register_task_item') || !reg.includes('register_task_list')) throw new Error('registration.rs 未注册 task 扩展');\nconsole.log('task-068-tasklist-bridge-ok');\nNODE", "timeout_seconds": 10800 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已补齐 leptos-tiptap 的 task_list/task_item Rust 暴露与运行时注册,修复 list_item/task_item 命令冲突,并在 8123 spike 页面通过网页 smoke 验证 taskList/taskItem 真 schema。", "timestamp": "2026-04-18T17:51:55Z" } ], "completed_at": "2026-04-18T17:51:55Z" }, { "id": "task-069", "title": "执行 BlockEditor P0-2:把 leptos-tiptap spike 从调试展示页推进为最小产品页壳,去掉重 debug 侧栏布局,保留真实 Tiptap surface 与常用块体验", "status": "completed", "priority": "P0", "depends_on": [ "task-068" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo +1.89.0 check --manifest-path /mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/Cargo.toml && cd /mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike && env -u NO_COLOR trunk build --release", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已把 leptos-tiptap spike 收敛为最小产品页壳:主视觉切到单页编辑体验,调试输出降为折叠抽屉,不再以双栏 debug panel 作为主界面。", "timestamp": "2026-04-18T17:51:55Z" } ], "completed_at": "2026-04-18T17:51:55Z" }, { "id": "task-070", "title": "执行 BlockEditor P0-3:按官方 notion-like 模板交互模型实现最小 slash 菜单,只保留 paragraph、heading1/2/3、bullet、ordered、todo、blockquote、code block、divider", "status": "completed", "priority": "P0", "depends_on": [ "task-069" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo +1.89.0 check --manifest-path /mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/Cargo.toml && python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/src/main.rs').read_text(encoding='utf-8')\nfor needle in ['heading', 'blockquote', 'code block', 'Todo', 'Slash']:\n assert needle.lower() in text.lower(), needle\nprint('task-070-slash-minimal-ok')\nPY2", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已在 8123 spike 实现真正由 “/” 触发的最小 slash 菜单,覆盖 paragraph、heading1/2/3、bullet、ordered、todo、blockquote、code block、divider,并通过网页 smoke。", "timestamp": "2026-04-18T17:51:55Z" } ], "completed_at": "2026-04-18T17:51:55Z" }, { "id": "task-071", "title": "执行 BlockEditor P0-4:按官方 notion-like 模板交互模型实现最小浮动工具条,保留 bold、italic、strike、code、link、highlight、turn into、undo/redo", "status": "completed", "priority": "P0", "depends_on": [ "task-070" ], "attempts": 1, "max_attempts": 3, "started_at_commit": "f9a45e89", "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo +1.89.0 check --manifest-path /mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/Cargo.toml && python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/src/main.rs').read_text(encoding='utf-8')\nfor needle in ['bold', 'italic', 'strike', 'highlight', 'undo', 'redo']:\n assert needle.lower() in text.lower(), needle\nprint('task-071-floating-toolbar-minimal-ok')\nPY2", "timeout_seconds": 7200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [ { "step": 1, "total": 1, "description": "已在 8123 spike 实现最小浮动工具条并以常驻方式先打通 P0 验证链,包含 bold、italic、strike、code、link、highlight、turn into、undo/redo,网页 smoke 通过。", "timestamp": "2026-04-18T17:51:55Z" } ], "completed_at": "2026-04-18T17:51:55Z" }, { "id": "task-072", "title": "执行 BlockEditor P0-5:明确并打通 Tiptap JSON 到 Rust 文档真相的保存边界,禁止引入 runtime shell 专用格式,并完成 reload 不丢结构", "status": "pending", "priority": "P0", "depends_on": [ "task-071" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web && python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-leptos-rust-migration-checklist-v1.md').read_text(encoding='utf-8')\nassert 'Tiptap JSON 作为运行时输入,Rust 侧导出统一文档真相' in text\nprint('task-072-save-boundary-doc-ok')\nPY2", "timeout_seconds": 10800 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-073", "title": "执行 BlockEditor P0-6:对齐 EditorBlockType 与 P0 schema,至少覆盖 Paragraph、Heading、BulletListItem、NumberedListItem、Todo、Quote、CodeBlock", "status": "pending", "priority": "P0", "depends_on": [ "task-072" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/rust/crates/core-protocol/src/editor/model.rs').read_text(encoding='utf-8')\nfor needle in ['Paragraph', 'Heading', 'BulletListItem', 'NumberedListItem', 'Todo', 'Quote', 'CodeBlock']:\n assert needle in text, needle\nprint('task-073-editor-blocktype-p0-ok')\nPY2", "timeout_seconds": 1200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-074", "title": "执行 BlockEditor P0-7:对齐 EditorCommand 与 P0 交互,至少覆盖 split、merge、insert、replace、indent/outdent 与保存级 toggle heading collapse 语义", "status": "pending", "priority": "P0", "depends_on": [ "task-073" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/rust/crates/core-protocol/src/editor/command.rs').read_text(encoding='utf-8')\nfor needle in ['Split', 'Merge', 'Insert', 'Replace', 'Indent', 'Outdent', 'ToggleHeadingCollapse']:\n assert needle in text, needle\nprint('task-074-editor-command-p0-ok')\nPY2", "timeout_seconds": 1200 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-075", "title": "执行 BlockEditor P0-8:用真实网页回归验证 P0 主编辑器最小可写闭环,标准改为接近 Tiptap/Wolai 页面体验,而不是 shell 标题加 textarea", "status": "pending", "priority": "P0", "depends_on": [ "task-074" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test && cd /mnt/Data1T/mnote/rust && cargo test && python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-leptos-rust-migration-checklist-v1.md').read_text(encoding='utf-8')\nassert '不是 runtime shell' in text\nassert '不是 textarea 壳' in text\nprint('task-075-p0-qa-baseline-ok')\nPY2", "timeout_seconds": 14400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-076", "title": "执行 BlockEditor P1-1:引入稳定 block id 策略与 UniqueID 对齐,为引用、拖拽、局部更新和审计打基础", "status": "pending", "priority": "P1", "depends_on": [ "task-075" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-leptos-rust-migration-checklist-v1.md').read_text(encoding='utf-8')\nassert '稳定 block id' in text\nassert 'UniqueID' in text\nprint('task-076-block-id-plan-ok')\nPY2", "timeout_seconds": 600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-077", "title": "执行 BlockEditor P1-2:增加普通块缩进、页面引用/块引用、拖拽块 handle、块菜单与 turn into,按官方 notion-like 交互分类做 Leptos 自建桥接", "status": "pending", "priority": "P1", "depends_on": [ "task-076" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web && python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-leptos-rust-migration-checklist-v1.md').read_text(encoding='utf-8')\nfor needle in ['缩进', '页面引用 / 块引用', '拖拽块 handle', 'Turn Into']:\n assert needle in text, needle\nprint('task-077-p1-interactions-plan-ok')\nPY2", "timeout_seconds": 10800 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-078", "title": "执行 BlockEditor P1-3:增加 Markdown 导入导出回归、heading collapse 树语义对齐,并完成新的正式主编辑器阶段 QA", "status": "pending", "priority": "P1", "depends_on": [ "task-077" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-editor-core && cargo test -p mnote-web && cd /mnt/Data1T/mnote/wolai-frontend && pnpm test", "timeout_seconds": 14400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-079", "title": "执行 BlockEditor P2-1:接入 Rust outline projection 驱动目录、图片/附件桥接、轻量表格评估、移动端工具条与 Rust AI 命令入口", "status": "pending", "priority": "P2", "depends_on": [ "task-078" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "python3 - <<'PY2'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/blocknote/tiptap-leptos-rust-migration-checklist-v1.md').read_text(encoding='utf-8')\nfor needle in ['outline projection', '图片块与附件桥接', '移动端工具条', 'AI 编辑命令入口']:\n assert needle in text, needle\nprint('task-079-p2-plan-ok')\nPY2", "timeout_seconds": 600 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] }, { "id": "task-080", "title": "执行 BlockEditor Cleanup:在 P0/P1 主编辑器稳定后,再清理 BlockNote/Yjs/Mantine 依赖、旧自定义块主线耦合,并在最后统一协调 3000/3104/Convex 接入边界", "status": "pending", "priority": "P1", "depends_on": [ "task-078" ], "attempts": 0, "max_attempts": 3, "started_at_commit": null, "validation": { "command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test && pnpm lint && cd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js", "timeout_seconds": 14400 }, "on_failure": { "cleanup": null }, "error_log": [], "checkpoints": [] } ], "session_count": 11, "last_session": "2026-04-18T17:51:55Z" }