# 画布 intake —— 从「审计 / 工程分析」到高质量画布 ## 触发与含义 用户说"建个项目的 canvas / 看板 / 画布 / 画板 / 项目文档 / dashboard"时,host 的 **意图入口**(`agent/pre-step` hook)会把这份 intake 的摘要注入当前步骤。含义固定: > **把项目的审计结论与工程现状,结构化、可下钻、可回写地呈现出来。** 不是写一篇散文,也不是把一个 markdown 换个皮。直接产出一个只有标题 + 状态的薄看板,等于没接住这个入口。 **不该走本流程**:单条结论(写在回复里)、短任务(`todo_write`)、append-only 日志(普通文件)、机器要读的数据(JSON / CSV)、"要不要继续下一轮"(`goal`)。 ## 第一步:先对齐,不要先写文件 把下面 7 条摆给用户。**每条都给一个可用的默认值**:用户不反对就用默认;用户已经说清楚的照抄,不要重复问。 | # | 问题 | 默认 / 例子 | |---|---|---| | 1 | 这张画布要支撑的**决定**是什么(一句话) | 「把 X 迁移对齐到 v2,并决定何时冻结接口」 | | 2 | **行**的单位是什么 | 任务 / 门禁 / 模块 / 迁移单元 / 轮次 | | 3 | **状态模型与分组** | `pending / in_progress / blocked / completed / cancelled`;lane = 工作流 | | 4 | 每行必须具备的**字段** | 见下表「字段清单」 | | 5 | 要派生的**分析** | 加权进度、WIP 超限、陈旧、超估算、分组完成度、下一步 3 条、风险清单 | | 6 | 人要在面板上做的**动作** | 标记进行中 / 完成 / 阻塞、认领、豁免、打开文件、起回合 | | 7 | **更新与归档**节奏 | 谁在什么事件后更新 `DATA`;已完成超过一个窗口就移出 | ### 字段清单(缺一个,跟踪就断一条) | 字段 | 回答的问题 | 缺失的后果 | |---|---|---| | `status` | 到哪一步 | 看板退化成清单 | | `progress` + `estimate` + `actual` | 还要多少、已经花了多少 | 看不出是在推进还是原地打转 | | `startedAt` / `updatedAt` / `completedAt` | 停了多久、多久没动过 | 陈旧条目永远不会浮出来 | | `blocker` | 卡在哪、在等谁 | 阻塞只能靠人复述 | | `next` | 下一步动作 | 人和 agent 各自猜下一步 | | `acceptance` | 怎样算完成(可核对) | "完成"变成主观判断 | | `evidence` | 文件:行 / 测试名 / 运行号 | 结论不可复核 = 伪造证据 | | `lane` / `priority` / `owner` | 分组、排序、认领 | 无法分工与排期 | 再加一个快照字段:`asOf`(数据快照日)。所有「多少天没动」都相对它算,**不要在画布里有"当前时间"这种会漂的状态**。 ## 第二步:把 intake 回执给用户确认 压缩成一段,不要长篇。模板: ~~~text 我理解这次要的是:<一句话决定> - 行:<单位>,预计 条(在办窗口内) - 状态:pending / in_progress / blocked / completed / cancelled - 分组: - 每条:状态 · 进度(估/实) · 日期 · 阻塞 · 下一步 · 验收 · 证据 · 改动位置 - 分析:加权进度 · WIP · 陈旧 · 超估算 · 分组完成度 · 下一步 3 条 - 人的动作:标记状态 / 认领 / 打开文件 / 起回合 - 更新:<谁在什么之后更新>;完成后超过一个窗口移出 确认后我建 (kind: board)。 ~~~ 只问一次。用户说"你看着办"就用默认,并在画布上用 `Text` 写明口径(而不是默默猜)。 ## 第三步:产出顺序(不要跳步) 1. intake 确认(或用户明确说不用确认); 2. `canvas_new(path, kind)` —— 不要手写空文件,会漏元数据头与 `DATA` 形状; 3. **只填** `export const DATA`(纯字面量)。这一步不要动渲染代码; 4. `canvas_check(path)` 自检; 5. 把文件路径 + 「人机怎么共用这份状态」告诉用户。 ## 质量门槛(不满足就不算交付) - **只内联当前窗口**(在办 + 最近完成);历史外置到普通文件或另一张画布。 - **每个数字都能追溯**:来自 `DATA` 字段或真实运行输出。禁止把断言 / 计数手抄进 `DATA`。 - **结论性文字用引用**:`crates/x.rs:306` 或「见 T-3」;`note` 超过约 120 字就该改成引用。 - **人的改动走 `useCanvasOverlay`**(落 sidecar,agent 下一轮 `canvas_read` 可见)。筛选器等纯 UI 态才用 `useCanvasState`。 - **分析从数据现算**,不手抄结论(加权进度、风险、下一步都在渲染期算)。 - **明细表有证据列**;看板有派生风险与「下一步」。 - 触发软阈值(源码 128 KB / 1500 行 / `DATA` 512 KB)时把它当必须处理的信号。 ## 反模式 | 反模式 | 为什么坏 | 正确做法 | |---|---|---| | 没做 intake 就写文件 | 行单位/字段错了,返工就是重写 | 先给 7 条 + 默认值,一次确认 | | 只有标题 + 状态 | 不是审计/分析,是清单 | 补齐字段清单与分析 | | 状态写在 `note` 里 | agent 与面板都算不出来 | `status` / `blocker` 是字段 | | 把全部历史内联 | 长成第二个巨型 markdown | 只留当前窗口 | | 手抄门禁/测试数字 | 数字先于现实过期,不可复核 | 由 harness / agent 写回 `DATA` | | 人在面板上的改动进 `useCanvasState` | agent 看不见,等于人白点 | `useCanvasOverlay` | ## 参考 - 套件完整 API:[kit.md](kit.md) - 四类范式(看板 / 门禁 / 时间线 / 对比):[patterns.md](patterns.md) - 可直接起步的看板:[`templates/board.canvas.tsx`](../templates/board.canvas.tsx) - 诊断码逐条修法:[troubleshooting.md](troubleshooting.md)