Wallflower(壁花白板)
AI 负责准备,而团队负责思考。你的工作是设定对话的起点:整理好材料,将重要的关系清晰呈现,但不要给出看起来已经定论的结论。之后,回顾团队对该白板的操作,因为那才是他们真实判断的记录。
设置
wallflower(或其简写 wf)来自 wallflower-board npm 包:npm install -g wallflower-board,或者使用 npx wallflower-board 代替 wallflower 前缀命令。白板默认会发送到公共服务器 board.byenzyme.com,除非用户已设置其他服务器(wallflower server 会显示当前使用的服务器)。无需启动任何额外服务。
对于本地服务器(--server local),请先在后台启动本地服务器:
(nohup wallflower serve > /tmp/wallflower.log 2>&1 &)
在仓库的检出目录中,npm run dev 会以热重载 UI 的方式运行本地服务器。
完整的命令接口:
wallflower new "Title" [--id ID] 创建一个白板并将其设为当前白板
wallflower put plan.json|- 添加或更新分组和卡片;打印布局、警告和布局问题
wallflower view 显示布局图,然后显示每个卡片及其位置
wallflower diff 显示自首次接触以来团队所做的更改
wallflower wait [--timeout SECONDS] 阻塞直到有人按下“再做一轮”;打印该轮的结果
wallflower url [--name Name] 返回白板的链接,并附带用户名
wallflower share 返回供他人使用的链接;在 stderr 上显示他们是否能访问
wallflower delete [id] 删除你创建的白板(对所有人生效)
wallflower server 显示新白板默认发送到哪个服务器
wallflower list | wallflower use <id>
wallflower url 会打印白板打开的地址。本地服务器只能在本机上响应;不要将其暴露给外部。新白板默认发送到 board.byenzyme.com,或用户自己设置的服务器(配置在 ~/.config/wallflower/config.env 或 WALLFLOWER_URL 和 WALLFLOWER_TOKEN 环境变量中);wallflower server 会显示当前使用的是哪个。board.byenzyme.com 上的白板在 90 天无活动后会被删除。--server <url> 可以将任何命令指向其他服务器,而 --server local 则指向本机:如果需要创建仅供用户本人查看且包含私有材料的白板,请使用此选项(除非另有说明)。将其传递给 wallflower new 或 wallflower use;后续对该白板的命令会沿用其服务器,无需再次指定。托管的白板的链接是其唯一密钥:任何持有该链接的人都可以编辑和读取白板,因此请仅将其分发给应该参与讨论的人,不要将其粘贴到公共场合。如果要处理他人创建的白板,请从其链接中获取 id(?board=<id>),然后运行 wallflower use <id>;无需令牌。
0. 确定白板的用途
在开始收集材料之前,先明确三件事。如果你无法推断出来,请向用户询问。
- 这个讨论的目的是评价什么? 每次会议都存在一个属于与会者的核心任务:选择、优先级排序、评估、命名。你的解读应到此为止。
- 参与者是谁? 这将决定哪些内容可以出现(参见隐私)。
- 这个白板将展示哪些原始资料中没有的信息? 用一句话写下来。如果答案是“以卡片形式呈现的相同笔记”,那么这个白板就没有存在的必要。通常的答案是:单个原始资料中无法体现的材料之间的关系(三个人的相同想法、一个决定与后续某人言论的关联、两个工作涉及同一件事)。
当受众只有一个人时(如私人复盘、周回顾),他/她参加了所有会议,阅读了所有笔记。摘录对他/她毫无意义。请根据来自不同来源的模式来构建白板,每个模式用两三个来自不同地方的卡片组合在一起,再加上一张介绍当前状况的定向卡片(待办事项、谁欠谁什么)。期待更少但更强有力的卡片。
| 场景 | 到此为止(不要做) | 值得注意的地方 |
|---|---|---|
| 面向 Agent 的站会或计划会 | 需要人工处理的事项、优先级、谁负责 | Agent 间的冲突;Agent 相互矛盾;规格与实现结果不符 |
| 设计评审或评议会 | 品味:哪些该保留 | 跨版本出现的相同反馈;意见相左的评审者 |
| 研究综合 | 主题与洞察 | 异常值;一词多义;言行不一 |
| 战略或创始人会议 | 做出选择并承诺 | 重新讨论已解决的问题;声明的优先级与时间投入不符 |
| 私人复盘 | 个人评估 | 不同人重复提供的反馈;偏离既定标准;未解决的问题 |
这些行来自少数真实案例的推断。让后续的回顾来修正它们。
1. 收集
直接使用你手头的搜索工具:使用全文搜索(rg -il)搜索名字、项目关键词和标签,按日期排序以获得最新结果,然后根据锚点跟踪链接。如果笔记支持语义搜索(如 Enzyme 的 enzyme petri / enzyme catalyze 或类似工具),请使用它来查找概念。对于 Agent 的工作,请阅读 Agent 的对话记录和 git 日志;对于通话,请阅读转录稿。
第一轮语义搜索通常会返回笔记中最常见的主题,而非本次会议的材料。在编写计划前,请检查:
- 锚点。 列出 3 到 6 个会议明显依赖的原始资料(范围说明、最新通话、其延续的决定)。你是否完整阅读了它们?
- 新近信息。 材料是否包含过去一周关于该主题的工作?
- 声音。 相关人员的言论是否以他们自己的话呈现?
如果不是,请用用户的语言重新表述,精确搜索,跟踪链接,或向用户提出一个具体的问题。在使用文件之前,请先阅读它们;片段会误导人。当存在提炼过的笔记(会议总结、之前的摘要)时,请记住它们已经进行过一些梳理。引用其中人物的原话,而不是他们的结论,并寻找将各点联系起来的东西。
隐私
共享白板上的任何内容都必须来自房间内所有人都能看到的来源。个人反思、私人笔记以及任何标记为私人的内容,即使相关,也不应出现在共享白板上。提炼过的笔记(总结、摘要)通常混合了所述内容与作者私下的解读:只有可说部分是可共享的。请将观点表述为一个开放性问题,或者干脆省略。这包括卡片携带的预览(如下所示):其来源中约有 200 字会随着卡片一起进入白板。
2. 编写计划
手动编写计划 JSON,放入文件或标准输入中,然后一次性提交:分组、卡片及其放置位置一起提交。不要构建生成器脚本,也不要编写验证器:wallflower put 会进行布局、截断超出预算的文本,并检查结果。
{
"title": "回顾发布评审",
"groups": [
{ "id": "g1", "col": 0, "why": "两位评审者共同的担忧" },
{ "id": "next", "label": "推进到下周", "col": 2, "zone": true }
],
"cards": [
{ "id": "rosa", "kind": "quote", "title": "Rosa 对引导流程的看法", "body": "我不知道它想让我做什么",
"source": { "label": "发布评审,3月4日", "file": "/…/notes/2026-03-04 review.md", "url": "obsidian://open?…", "author": "Rosa", "date": "Mar 4" },
"place": { "in": "g1" }, "why": "与 Kim 对空白状态的疑问类似" },
{ "id": "kim", "kind": "quote", "title": "Kim 问了两遍", "body": "我首先应该做什么?",
"source": { "author": "Kim", "date": "Mar 6" }, "place": { "near": "rosa", "side": "right", "overlap": true } }
]
}
wallflower put plan.json
计划可以是部分的。再次提交相同的 id 可以编辑或移动卡片,而 { "id": "x", "delete": true } 可以删除它。任何使用 id 的位置,都可以用卡片的编号代替("#17"),这是轮次和 wallflower view 显示人们便签的方式。分组位于网格上(col,row);你无需计算像素。保持分组未命名,因为命名是团队的工作;why 是为回顾准备的,而非白板本身。区域是个例外:给它们贴上标签("已决定","推进到下周"),因为区域的名称就是指示。
在有人接触到白板之前,每次 put 都会根据你的放置重新布局整个白板,因此移动一个分组到另一个 row 或移动一张卡片到另一个分组只是重新布局而已。之后,任何人放置的任何内容都会保留在原位:你新增的卡片会围绕它放置,只有你未触碰的分组会移动以腾出空间。
put 会以文本形式打印布局,然后进行检查。layout check: no overlaps, every card in its group, no cut-off text 表示已完成。否则,每个 problem: 行都会通过 id 指出有问题的卡片或分组(分组重叠或过于接近、卡片看起来属于错误的分组、卡片相互覆盖、标题超过三行、浏览器报告文本被截断);请修正计划并再次提交。wallflower view 会在最后列出相同的问题。人们创建的重叠是他们的,永远不会被报告。请勿截取白板截图来检查布局。
放置
place | 用途 |
|---|---|
{ "in": "g1" } | 属于一起的材料(分组会扩大) |
{ "near": "c1", "side": "right", "overlap": true } | 将两张卡片视为一个整体:分歧、偏离、跨人员的重复 |
{ "around": "c1" } | 扩展邻域:每张卡片落在 c1(一张卡片或一个人的便签)周围的一个松散环上,方向不同,在其分组内 |
{ "near": "c1", "side": "below" } | 将一张卡片放在另一张旁边,不重叠;它留在伙伴的分组内,分组会扩大 |
{ "edge": "g1", "side": "right" } | 异常值,或者你不确定是否属于该分组的内容 |
{ "at": { "x": 0, "y": -200 } } | 提示和少数手动放置的位置 |
卡片类型
每种类型的宽度固定,高度随内容变化。
| kind (类型) | 用途 | title (标题) | body (正文) |
|---|---|---|---|
quote | 任何逐字记录的要点,无论口语或书面;source.author = 谁说/写的 | 要点,≤90 字符 | 要点,≤200 字符(目标 120 以下) |
note | 一个对象(文档、工单、PR、会话),或执行以下某项工作的笔记 | ≤90 字符 | ≤300 字符 |
prompt | 白板上的标记文本:起始卡片、一个开放性问题 | ≤160 字符 | ≤200 字符 |
sticky | 人们添加的内容(你很少应该添加) | ≤140 字符 | 无 |
当广度很重要时,设置 people(一个名称数组,["Rosa", "Kim", "Lee"]);它会渲染为“来自 3 人”。仅基于一两个声音的模式应该看起来很单薄。仅当房间内所有人都能打开时才在 source.url 中添加链接(共享文档、工单、PR);切勿链接到私人笔记,这对他们没用,还会泄露你的文件位置。对于文件,请使用 source.file(如下所示),它保留在你的机器上。
来源预览。 为每个来自文件的卡片提供其 source.file(绝对路径;file:// URL 也适用)。wallflower put 会读取你机器上的文件,并附加卡片引用周围约 200 字的文本,人们可以通过双击卡片或单击其来源行来打开。引用是引用卡片的 body;在笔记卡片上,设置 source.quote 为文件中的逐字短语,否则预览将是文件的开头。文件本身永远不会离开你的机器。永远不要自己编写预览:put 会忽略计划中的任何 source.passage。对于非文件的来源(电子邮件、工单),请使用 shell 重定向保存其原始文本(gog … > /tmp/src-1.md),并将 source.file 指向该文件。如果 put 警告未找到引用,则说明引文不是逐字记录的:请修复引文,而不是忽略警告。
编写卡片
白板的内容应该一目了然,人们会跳转去查看吸引他们的内容。大多数卡片应在两秒内可读。
- 标题 = 要点:用简单的话语说明这是什么,最多约 60 个字符。是描述,不是结论。
- 正文 = 引文:仍能传达要点的最短逐字片段。优先选择奇特、具体或生动的句子。逐字记录并不意味着整个段落。
每一段文本都必须回答一个问题:这段文字能让读者注意到什么、记住什么,或者调查什么? 唯一作用是解释你为何包含某内容(例如解释卡片是证据的卡片、描述白板的笔记)的文本是你自己在叙述准备过程。将它删掉。来源归属可以安静地位于下方。
一张笔记卡片凭完成以下一项工作来获得其位置,大致按它们帮助团队理清思路的程度排序:
- 将两件事结合在一起,以便可以调查、争论或拆解它们之间的关系。
- 暴露缺失的部分:证据不足的地方(“客户实际上看到了你们做出的决定吗?”)
- 恢复一个顺序,而单个引用无法承载。
- 提供对某事的另一种解读,特别是当某件事过于草率地被定了性时。在私人白板上,这优先级更高;在团队白板上,大部分留给团队。
- 带回归期(计划了什么)与实际情况对比。
- 为预演留出空间,通常是在团队理清思路之后。
通常,正确的笔记是“无”:两张放置得当的卡片已经完成了工作 1。包含真实信息的状态笔记(待办事项、谁欠谁什么)是可以的;解释白板的笔记则不行。
问题适用于执行工作 2 或 4 的一两张笔记卡片。一连串第二人称的标题问题是在替团队提问,读起来像是机器写的,就像它替换掉的自我解释文本一样。标题保持为要点。
停留在含义层面。不要命名分组,不要写“这显示了……”“关键见解”或“这里的主题是……”,也不要为为什么两张卡片放在一起添加说明。放置位置本身就表达了观点,有人可以通过移动卡片来质疑放置。也不要给每张卡片都加上保留意见:附注只属于它影响的唯一一张卡片。
| 不要这样写 | 请这样写 |
|---|---|
| 标题“定价笔记,7月23日”,正文:280 字摘录 | 要点“共享链接带来不留存的访客”,引文“他们读完一次就离开” |
| 标题“Kim,支持电话”,正文:关于导出的完整句子 | 要点“Kim 将所有内容导出到电子表格”,引文“我只想通过...(截断) |