{ "version": 2, "created": "2026-04-17T07:58:16Z", "session_config": { "concurrency_mode": "exclusive", "max_tasks_per_session": 20, "max_sessions": 50 }, "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" } ], "session_count": 2, "last_session": "2026-04-17T08:56:30Z" }