Files
mnote/harness-tasks.json
T

1195 lines
58 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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 显式门控与首页 smoke3104 不可达时 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": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/components/editor/menus/CustomSideMenu.tsx src/lib/documents/tree-command-client.ts && node - <<'NODE'\nconst fs = require('fs');\nconst menu = fs.readFileSync('src/components/editor/menus/CustomSideMenu.tsx', 'utf8');\nif (menu.includes('fetch(\"/api/documents/delete\"') || menu.includes(\"fetch('/api/documents/delete'\")) throw new Error('CustomSideMenu.tsx 仍直调 /api/documents/delete');\nif (!menu.includes('deleteDocumentCommand(')) throw new Error('CustomSideMenu.tsx 未切到 shared tree command client');\nconsole.log('task-010-page-reference-delete-ok');\nNODE",
"timeout_seconds": 300
},
"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",
"claimed_by": "SESSION-3",
"lease_expires_at": "2026-04-17T16:28: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": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/lib/documents/tree-command-client.ts src/lib/documents/page-command-adapter.ts src/app/api/documents/embed/route.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 adapter = fs.readFileSync('src/lib/documents/page-command-adapter.ts', 'utf8');\nconst sidebar = fs.readFileSync('src/components/sidebar/sidebar.tsx', 'utf8');\nconst documentContent = fs.readFileSync('src/components/editor/document-content.tsx', 'utf8');\nif (!client.includes('export async function embedDocumentCommand')) throw new Error('tree-command-client.ts 缺少 embedDocumentCommand');\nif (!adapter.includes('name: \"documents.embed\"')) throw new Error('page-command-adapter.ts 未定义独立 documents.embed 命令');\nif (adapter.includes('name: \"documents.save\"') && adapter.includes('executeDocumentEmbedBridgeCommand')) throw new Error('embed 仍停留在 documents.save 过渡语义');\nfor (const [name, source] of [['sidebar', sidebar], ['document-content', documentContent]]) {\n if (source.includes('fetch(\"/api/documents/embed\"') || source.includes(\"fetch('/api/documents/embed'\")) throw new Error(name + ' 仍直调 /api/documents/embed');\n}\nconsole.log('task-011-embed-command-ok');\nNODE",
"timeout_seconds": 600
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已把 embed 从 documents.save 过渡语义切成独立 documents.embed 命令,并补齐 TS/Rust 映射与回归测试。",
"timestamp": "2026-04-17T16:15:19Z"
}
],
"completed_at": "2026-04-17T16:15:19Z",
"claimed_by": "SESSION-3",
"lease_expires_at": "2026-04-17T16:28:30Z"
},
{
"id": "task-012",
"title": "执行 Stage P1-4:把 copy-tree 收口到 shared tree command client,移除 Sidebar 中文档复制的直调 route",
"status": "completed",
"priority": "P1",
"depends_on": [
"task-011"
],
"attempts": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/lib/documents/tree-command-client.ts src/components/sidebar/sidebar.tsx src/app/api/documents/copy-tree/route.ts && 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 route = fs.readFileSync('src/app/api/documents/copy-tree/route.ts', 'utf8');\nif (!client.includes('export async function copyTreeCommand')) throw new Error('tree-command-client.ts 缺少 copyTreeCommand');\nif (sidebar.includes('fetch(\"/api/documents/copy-tree\"') || sidebar.includes(\"fetch('/api/documents/copy-tree'\")) throw new Error('sidebar.tsx 仍直调 /api/documents/copy-tree');\nif (!route.includes('name: \"documents.copy_tree\"')) throw new Error('copy-tree route 未保持 Rust bridge command 主链');\nconsole.log('task-012-copy-tree-client-ok');\nNODE",
"timeout_seconds": 600
},
"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": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/documents/page-lifecycle-command-adapter.test.ts src/lib/file-tree/dnd.test.ts && cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime kernel_project_view_query_executes_into_sidebar_projection -- --nocapture && cargo test -p bridge-runtime kernel_subtree_query_executes_into_unified_subtree -- --nocapture",
"timeout_seconds": 1200
},
"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": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/sidebar-data.test.ts src/lib/tree-projection.test.ts src/lib/file-tree/rows.test.ts && node - <<'NODE'\nconst fs = require('fs');\nconst sidebarData = fs.readFileSync('src/lib/sidebar-data.ts', 'utf8');\nconst pageSubtree = fs.readFileSync('src/lib/documents/page-subtree.ts', 'utf8');\nif (sidebarData.includes('result.kernel_sidebar_projection ??')) throw new Error('sidebar-data.ts 仍在主路径本地补 projection 真相');\nif (pageSubtree.includes('projectionId: `page_subtree:')) throw new Error('page-subtree.ts 仍本地合成 page_tree projection');\nconsole.log('task-014-kernel-projection-contract-ok');\nNODE",
"timeout_seconds": 900
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已移除主路径 projection fallback/synthetic projection idsidebar/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": 0,
"max_attempts": 3,
"started_at_commit": null,
"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 src/lib/sidebar-data.ts && 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');\nconst sidebarData = fs.readFileSync('src/lib/sidebar-data.ts', 'utf8');\nfor (const [name, source] of [['sidebar', sidebar], ['picker', picker], ['host', host]]) {\n if (source.includes('buildDocumentTree(')) throw new Error(name + ' 仍残留旧树拼装主路径');\n}\nif (sidebarData.includes('buildKernelSidebarProjection(')) throw new Error('sidebar-data.ts 仍保留主路径 synthetic kernel projection');\nconsole.log('task-015-mainpath-projection-only-ok');\nNODE",
"timeout_seconds": 600
},
"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": "P2",
"depends_on": [
"task-015"
],
"attempts": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes')\nsse = (root / 'sse.rs').read_text(encoding='utf-8')\nws = (root / 'ws.rs').read_text(encoding='utf-8')\nassert 'sse_placeholder' not in sse, 'sse.rs 仍是 placeholder'\nassert 'ws_placeholder' not in ws, 'ws.rs 仍是 placeholder'\nassert 'workspace' in sse or 'subtree' in sse, 'sse.rs 未体现 workspace/subtree stream'\nprint('task-016-rust-web-snapshot-stream-ok')\nPY",
"timeout_seconds": 1800
},
"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": "P2",
"depends_on": [
"task-016"
],
"attempts": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/tree-stream/tree-stream.test.ts src/lib/tree-stream/tree-delta.test.ts && node - <<'NODE'\nconst fs = require('fs');\nconst sidebar = fs.readFileSync('src/components/sidebar/sidebar.tsx', 'utf8');\nif (!/useTreeStream|useSidebarTreeStream|snapshot|delta|resync/.test(sidebar)) throw new Error('sidebar.tsx 未接入正式 tree stream consumer');\nconsole.log('task-017-tree-stream-consumer-ok');\nNODE",
"timeout_seconds": 1200
},
"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": "P3",
"depends_on": [
"task-017"
],
"attempts": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web kernel_projection_route_returns_sidebar_projection -- --nocapture && cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/lib/server/sidebar-data.ts src/app/(app)/documents/[id]/page.tsx src/components/editor/document-shell.tsx && cd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js",
"timeout_seconds": 1800
},
"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": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test && pnpm lint src/hooks/use-sidebar-data.ts src/hooks/use-convex-sidebar-data.ts src/lib/documents/tree-command-client.ts src/components/sidebar/sidebar.tsx src/components/editor/document-content.tsx src/components/editor/menus/CustomSideMenu.tsx src/lib/sidebar-data.ts src/lib/tree-projection.ts src/lib/file-tree/rows.ts && cd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js",
"timeout_seconds": 2400
},
"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": "P1",
"depends_on": [
"task-019"
],
"attempts": 0,
"max_attempts": 3,
"started_at_commit": null,
"validation": {
"command": "python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote')\narch = (root / 'design/tree-first-graph-convex-rust-long-term-architecture-v1.md').read_text(encoding='utf-8')\nassert '- [ ]' not in arch, '长期架构文档仍有未完成 checklist'\nassert (root / 'harness-tasks.json').exists(), 'harness-tasks.json 缺失'\nassert (root / 'harness-progress.txt').exists(), 'harness-progress.txt 缺失'\nprint('task-020-architecture-checklist-complete')\nPY",
"timeout_seconds": 180
},
"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": "P1",
"depends_on": [
"task-020"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/tree-projection-protocol-contract-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['sidebar_tree', 'page_tree', 'file_tree', 'row_id', 'node_id', 'resource_meta']:\n assert needle in text, f'missing {needle}'\nprint('task-021-tree-projection-contract-ok')\nPY",
"timeout_seconds": 180
},
"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",
"claimed_by": "SESSION-4"
},
{
"id": "task-022",
"title": "执行 TreeShell Phase A-2:落地前后端共享 projection 类型,并冻结 file_tree 扩展字段与 capability/icon/resource 语义",
"status": "completed",
"priority": "P1",
"depends_on": [
"task-021"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p core-protocol -- --nocapture && cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/tree-protocol.test.ts && python3 - <<'PY'\nfrom pathlib import Path\nfrontend = Path('/mnt/Data1T/mnote/wolai-frontend/src/lib/tree-protocol.ts').read_text(encoding='utf-8')\nassert 'resourceKind' in frontend\nassert 'assetKind' in frontend\nassert 'iconHint' in frontend\nprint('task-022-tree-protocol-types-ok')\nPY",
"timeout_seconds": 1800
},
"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": "P1",
"depends_on": [
"task-022"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/tree-command-protocol-cutover-stage2-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['tree.node.create', 'tree.node.rename', 'tree.subtree.move', 'tree.asset.attach', 'documents.create']:\n assert needle in text, f'missing {needle}'\nprint('task-023-tree-command-protocol-doc-ok')\nPY",
"timeout_seconds": 180
},
"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": "P2",
"depends_on": [
"task-023"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/tree-shell-ui-state-boundary-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['expanded', 'selected', 'focus', 'dragging', 'drop target', 'projection']:\n assert needle in text, f'missing {needle}'\nprint('task-024-tree-shell-ui-state-boundary-ok')\nPY",
"timeout_seconds": 180
},
"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": "P1",
"depends_on": [
"task-024"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/tree-protocol.test.ts src/lib/tree-projection-contract.test.ts src/lib/documents/tree-command-client.test.ts && cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_projection_contract -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\nfor rel in [\n 'wolai-frontend/src/lib/tree-protocol.test.ts',\n 'wolai-frontend/src/lib/tree-projection-contract.test.ts'\n]:\n assert Path('/mnt/Data1T/mnote', rel).exists(), rel\nprint('task-025-tree-contract-tests-ok')\nPY",
"timeout_seconds": 2400
},
"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": "P1",
"depends_on": [
"task-025"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_projection_routes -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/mod.rs').read_text(encoding='utf-8')\nfor needle in ['/api/tree/projections/sidebar', '/api/tree/projections/page', '/api/tree/projections/file']:\n assert needle in text or needle.replace('/api', '') in text, needle\nprint('task-026-tree-projection-routes-ok')\nPY",
"timeout_seconds": 2400
},
"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,先覆盖 asset/mindmap/table,减少前端 adapter 拼装真相",
"status": "completed",
"priority": "P0",
"depends_on": [
"task-026"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web file_tree_projection -- --nocapture && cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/file-tree/rows.test.ts && node - <<'NODE'\nconst fs = require('fs');\nconst rows = fs.readFileSync('/mnt/Data1T/mnote/wolai-frontend/src/lib/file-tree/rows.ts', 'utf8');\nif (/mindmap_assets|table_assets|media_assets/.test(rows)) {\n throw new Error('rows.ts 仍直接耦合旧资产数组主路径');\n}\nconsole.log('task-027-file-tree-rust-projection-ok');\nNODE",
"timeout_seconds": 2400
},
"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:扩展 Rust file_tree mapper 到 book/pdf/index/resource hint/capabilities,补齐更宽对象投影",
"status": "completed",
"priority": "P1",
"depends_on": [
"task-027"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web file_tree_projection_resource_variants -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\ntext = Path('/mnt/Data1T/mnote/design/tree-projection-protocol-contract-v1.md').read_text(encoding='utf-8')\nfor needle in ['book', 'pdf', 'index', 'icon_hint', 'capabilities']:\n assert needle in text, f'missing {needle}'\nprint('task-028-file-tree-resource-variants-ok')\nPY",
"timeout_seconds": 2400
},
"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 route 长期协议切到 tree.*,同时保留 documents.* 兼容 alias 与桥接回归",
"status": "completed",
"priority": "P1",
"depends_on": [
"task-028"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_commands -- --nocapture && cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/lib/documents/tree-command-client.test.ts && node - <<'NODE'\nconst fs = require('fs');\nconst client = fs.readFileSync('/mnt/Data1T/mnote/wolai-frontend/src/lib/documents/tree-command-client.ts', 'utf8');\nif (!/tree\\./.test(client) && !/documents\\./.test(client)) throw new Error('tree command client 未体现 tree.* / documents.* 兼容层');\nconsole.log('task-029-tree-command-alias-ok');\nNODE",
"timeout_seconds": 2400
},
"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 解析与 compat fallback 契约",
"status": "completed",
"priority": "P0",
"depends_on": [
"task-029"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_route_contracts -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes')\njoined = '\\n'.join((root / name).read_text(encoding='utf-8') for name in ['compat.rs', 'kernel.rs', 'tree.rs'])\nfor needle in ['traceId', 'requestId', 'workspaceId', 'Authorization']:\n assert needle in joined, f'missing {needle}'\nprint('task-030-tree-route-contracts-ok')\nPY",
"timeout_seconds": 2400
},
"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 侧树域只保留 transport/compat,删除残余结构真相拼装逻辑",
"status": "completed",
"priority": "P1",
"depends_on": [
"task-030"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/lib/server/sidebar-data.ts src/app/api/sidebar/route.ts src/components/sidebar/sidebar.tsx src/components/documents/move-embed-picker-dialog.tsx && node - <<'NODE'\nconst fs = require('fs');\nfor (const rel of [\n 'src/lib/server/sidebar-data.ts',\n 'src/app/api/sidebar/route.ts',\n 'src/components/sidebar/sidebar.tsx',\n 'src/components/documents/move-embed-picker-dialog.tsx'\n]) {\n const source = fs.readFileSync(`/mnt/Data1T/mnote/wolai-frontend/${rel}`, 'utf8');\n if (source.includes('buildDocumentTree(')) {\n throw new Error(`${rel} 仍残留 buildDocumentTree 主路径`);\n }\n}\nconsole.log('task-031-next-tree-transport-only-ok');\nNODE",
"timeout_seconds": 1200
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "Next 树域主路径已收口为 transport/compateslint 通过且 buildDocumentTree 主路径检查通过。",
"timestamp": "2026-04-18T00:38:02Z"
}
],
"completed_at": "2026-04-18T00:38:02Z"
},
{
"id": "task-032",
"title": "执行 TreeShell Phase C-1:在 mnote-web 内接入 Leptos 正式 tree shell 骨架,打通 loader/command dispatcher/local UI state store",
"status": "completed",
"priority": "P0",
"depends_on": [
"task-031"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_shell_leptos_scaffold -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\ncargo = Path('/mnt/Data1T/mnote/rust/crates/mnote-web/Cargo.toml').read_text(encoding='utf-8')\nassert 'leptos' in cargo.lower(), 'mnote-web Cargo.toml 未接入 leptos'\nassert Path('/mnt/Data1T/mnote/rust/crates/mnote-web/src/tree_shell').exists(), '缺少 tree_shell 模块目录'\nprint('task-032-leptos-tree-shell-scaffold-ok')\nPY",
"timeout_seconds": 3600
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "mnote-web 已接入 Leptos tree shell scaffoldtree_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,并补齐虚拟化、展开/折叠与基础行渲染",
"status": "completed",
"priority": "P0",
"depends_on": [
"task-032"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_shell_page_renderer -- --nocapture && node /mnt/Data1T/mnote/scripts/task091-tree-shell-smoke.js",
"timeout_seconds": 3600
},
"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:为正式 tree shell 接入 selection/focus/keyboard 与 DnD 状态机,收口为局部 UI state",
"status": "completed",
"priority": "P0",
"depends_on": [
"task-033"
],
"attempts": 1,
"max_attempts": 3,
"started_at_commit": "f1c1bcf0",
"validation": {
"command": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_shell_interaction_state -- --nocapture && python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/tree-shell-ui-state-boundary-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['keyboard', 'selection', 'focus', 'dragging']:\n assert needle in text, f'missing {needle}'\nprint('task-034-tree-shell-interaction-state-ok')\nPY",
"timeout_seconds": 3600
},
"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": "cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web tree_shell_filetree_picker -- --nocapture && cd /mnt/Data1T/mnote/wolai-frontend && pnpm vitest run src/components/documents/move-embed-picker-dialog.test.tsx src/lib/file-tree/rows.test.ts && python3 - <<'PY'\nfrom pathlib import Path\nroot = Path('/mnt/Data1T/mnote/rust/crates/mnote-web/src/tree_shell')\nassert root.exists(), '缺少正式 tree shell 目录'\nprint('task-035-tree-shell-filetree-picker-ok')\nPY",
"timeout_seconds": 3600
},
"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": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/components/sidebar/sidebar.tsx src/components/documents/move-embed-picker-dialog.tsx src/components/sidebar/MnoteWebTreeShell.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst sidebar = fs.readFileSync('/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx', 'utf8');\nif (sidebar.includes('<iframe') || sidebar.includes('MnoteWebTreeShell')) {\n throw new Error('sidebar.tsx 仍把实验 iframe shell 作为主路径');\n}\nconsole.log('task-036-iframe-shell-demoted-ok');\nNODE",
"timeout_seconds": 1800
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已从 sidebar.tsx 主路径移除 iframe/postMessage 实验壳依赖,Sidebar 主树先稳定回到统一 React 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": "cd /mnt/Data1T/mnote && node scripts/task097-homepage-entry-smoke.js && node scripts/task101-tree-shell-cutover-smoke.js && cd /mnt/Data1T/mnote/wolai-frontend && node - <<'NODE'\nconst fs = require('fs');\nconst runtime = fs.readFileSync('public/mnote-env.json', 'utf8');\nif (!runtime.includes('mnoteWebTreeShellEnabled')) throw new Error('缺少 tree shell runtime flag');\nconsole.log('task-037-sidebar-cutover-ok');\nNODE",
"timeout_seconds": 3600
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已完成 Sidebar 主树默认切流与快速回退护栏,task101 验证 stream 主链与 fallback 均通过。",
"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": "cd /mnt/Data1T/mnote && node scripts/task101-tree-shell-cutover-smoke.js && node scripts/task102-tree-shell-regression.js && cd /mnt/Data1T/mnote/wolai-frontend && pnpm test && pnpm lint src/components/sidebar/sidebar.tsx src/components/documents/move-embed-picker-dialog.tsx src/lib/file-tree/rows.ts src/lib/tree-projection.ts",
"timeout_seconds": 5400
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已完成 page tree / filetree / picker 默认切流与高频回归,task102、前端测试与 lint 通过。",
"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": "python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/tree-shell-cutover-performance-report-v1.md')\ntext = path.read_text(encoding='utf-8')\nfor needle in ['首包', '首次可交互', '切页延迟', '大树展开延迟', 'fallback']:\n assert needle in text, f'missing {needle}'\nprint('task-039-tree-shell-perf-report-ok')\nPY",
"timeout_seconds": 300
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已产出 tree-shell-cutover-performance-report-v1.md,记录首包、首次可交互、切页延迟、大树展开延迟与 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": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm eslint src/components/sidebar/sidebar.tsx src/lib/file-tree/rows.ts src/lib/tree-projection.ts src/components/documents/move-embed-picker-dialog.tsx && node - <<'NODE'\nconst fs = require('fs');\nconst sidebar = fs.readFileSync('/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx', 'utf8');\nfor (const needle of ['PrivateTree', 'FileTree', 'MnoteWebTreeShell']) {\n if (sidebar.includes(needle)) throw new Error(`sidebar.tsx 仍直接耦合 ${needle}`);\n}\nconsole.log('task-040-tree-cleanup-ok');\nNODE",
"timeout_seconds": 2400
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已把 page/file/picker 主路径统一到同一套 tree surface/adapter 家族,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": "cd /mnt/Data1T/mnote/wolai-frontend && pnpm test && cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web -- --nocapture && cd /mnt/Data1T/mnote && python3 - <<'PY'\nfrom pathlib import Path\npath = Path('/mnt/Data1T/mnote/design/sidebar-pagetree-filetree-rust-web-rebuild-v1.md')\ntext = path.read_text(encoding='utf-8')\nassert '- [ ]' not in text, '设计文档仍存在未完成 checklist'\nprint('task-041-sidebar-tree-rust-web-rebuild-complete')\nPY",
"timeout_seconds": 7200
},
"on_failure": {
"cleanup": null
},
"error_log": [],
"checkpoints": [
{
"step": 1,
"total": 1,
"description": "已更新架构文档 checklist,完成 task097/task101/task102、pnpm test、cargo test 与最终验收。",
"timestamp": "2026-04-18T01:37:10Z"
}
],
"completed_at": "2026-04-18T01:37:10Z"
}
],
"session_count": 5,
"last_session": "2026-04-18T01:37:10Z"
}