第 7 章:规模与迷雾
一句话
探路图上的票解决的是决定,不是可交付物;分拣是给别人丢过来的生请求,不是给自己切好的工单。 两者都并入主链,都不替代追问。
核心概念
探路:找路,不是冲向目的地
/wayfinder 处理的是一会话装不下、包在雾里的大活。从这里到目的地的路还看不见。它把路画成议题跟踪上的共享图,然后一张一张做决策票(问题的决议是一个决定,不是一刀实现),直到路清了。
目的地因活而异,命名它是画图的第一件事:它给每张票定形。可能是一份要交出去的规格、规划开始前必须锁的决定、或一次就地改动(数据结构迁移)。图和领域无关:工程、课程内容,形状对就行。
默认:计划,不要做。 票决议的是决定;图在路清时结束,去做那件事之前没有未决的决定。想上手做,通常是信号:你已经走到图的边缘,该交接了。一份活可以在 Notes 里覆盖,把执行带进图;没写就产决定,不产交付物。
图是索引,不是仓库
图是跟踪器上的一条议题,标签 wayfinder:map。票是它的子议题。图列出已做的决定,并指向持有细节的票;一个决定只住在一处——它的票。图只写提要和链接,不复述。
图的正文是低分辨率、每场会话加载一次。开着的票不列在图上:它们是开着的子议题,靠查询找到。官方字段名是英文,第一次读可以对照:Destination 是目的地,Notes 是这份活的站立偏好,Decisions so far 是已关闭票的一行提要,Not yet specified 是范围内还写不锋利的雾,Out of scope 是目的地以外、永不毕业的活。
## Destination
<走到图尽头长什么样。一两行;每场会话先对准它再选票>
## Notes
<领域;每场会话该去查的 skill;这份活的站立偏好>
## Decisions so far
- [<已关闭票的标题>](link): <答案的一行提要>
## Not yet specified
<还票不了的、范围内的雾>
## Out of scope
<目的地以外的活;关闭,永不毕业>人读到的一切(叙述、已做决定)用标题指代,不用裸 id。一墙 #42, #43, #44 扫不过去;名字一眼能读。id 和 URL 包在名字里,不代替名字。
票的类型,以及迷雾
每张票的尺寸是一场约 10 万 token 的会话。认领方式:先把票派给开图的人,再干活。开着、未派的票就是未认领。阻塞用跟踪器的原生依赖,这样前沿在跟踪器自己的界面上可见。
每张票要么是 HITL(human in the loop,人在环里;人替自己说话,agent 代答追问就坏了),要么是 AFK(away from keyboard,agent 独自开)。
| 类型 | 谁开 | 做什么 |
|---|---|---|
| Research | AFK | 对着仓库外的一手材料查事实;子代理调 research |
| Prototype | HITL | 用便宜粗糙的具体物把讨论保真度抬上去;调 prototype |
| Grilling | HITL | 默认。总是同时调 grilling 和 domain-modeling |
| Task | HITL 或 AFK | 决定之前必须发生的手工:注册服务、开通权限、挪数据好看见形状。这是唯一「做」而不是「决定」的类型,靠给决定让路才配得上存在 |
迷雾是故意的不完整:还看不见的不要画。图前方是你感觉会来、但还钉不住的决定——它们挂在仍开着的问题上。决议一张票,会清开它前面的雾,把现在能写清的毕业成新票,一次一张,直到去目的地的路清了、没有票剩下。
雾还是票?测试是现在能不能把问题写精确,不是现在能不能答。
- 问题已经锋利,哪怕被阻塞、还不能动手 → 票
- 还写不到那么锋利 → 放进 Not yet specified。不要预先把雾切成票那么大:一摊雾可能毕业成好几张,也可能一张都没有
超出目的地的活不是雾,是 Out of scope。范围,不是锋利度,让它落在这里。它永不毕业。已经存在的票后来发现坐在目的地之外:关闭它,在 Out of scope 留一行。它不进 Decisions so far——范围边界不是路上的一步。
两种调用,一场会话最多决议一张
画图(用户丢来一个松的想法):
- 命名目的地(追问 + 领域建模)。目的地钉住范围,所以先定
- 再追问一次,这次先广度:铺开整个空间,不要在一条线上挖深。如果这趟问完没有雾(去目的地的路已经清、整段旅程一会话装得下),你不需要图。停,问用户想怎么走
- 建图:Destination 和 Notes 填好,Decisions so far 空,雾写进 Not yet specified
- 把现在能写清的建成子议题,第二趟再接阻塞边(议题要先有 id 才能互相指)。还写不清的留在雾里
- 把刚建的调研票派给子代理并行查
- 停:画图是一场会话的活;它自己不决议任何一张
顺着图做(用户丢来一张图):没点票时,你选下一个决定,不是用户选。加载图(低分辨率,不是每张票正文)→ 认领前沿上的第一张 → 决议 → 把答案写成决议评论、关闭、在 Decisions so far 追一条指针 → 把答案新翻出来的票建上,毕业已能写清的雾。用户可以并行跑未阻塞的票,所以预期别人的会话同时在改跟踪器。例外:调研票可以一场会话决议多张。
图清了,交接,不建造:并入主链的 /to-spec,把链上的决定收成一份可建造的计划,再 /to-tickets、/implement。把图直接丢给 /implement,等于跳过收束、把链上的细节扔掉。只有活最后其实很小,才允许直达实现。
/grill-with-docs 是单会话计划;wayfinder 是多会话计划。在范围清楚的功能上打 wayfinder,是最常见的误用。它更慢、更密。
分拣:外来请求的状态机
/triage 把议题(以及仓库若把外部 PR 当请求面,则外部 PR 也算——PR 是附带代码的议题)推过一小台状态机。
两个类别角色:bug、enhancement。五个状态角色:needs-triage、needs-info、ready-for-agent、ready-for-human、wontfix。已分拣的议题恰好一个类别、一个状态。状态冲突先问维护者,别的先别做。
状态转移:未打标签的通常先到 needs-triage;从那里到 needs-info / ready-for-agent / ready-for-human / wontfix。needs-info 在报告者回复后回到 needs-triage。
分拣一张具体议题:
- 读全文。按领域概念搜是不是已经实现(不仅按请求的措辞)。读
.out-of-scope/看是不是以前拒过 - 把类别和状态建议交给维护者,等方向
- 先核对其主张,再追问。 缺陷:按报告者的步骤复现。PR:检出 diff,跑相关测试。确认 / 失败 / 细节不够(强
needs-info信号) - 需要填肉再追问(同时调领域建模)
- 落地:
ready-for-agent贴一份 agent brief;ready-for-human同一结构,注明为什么不能委托;needs-info贴已确立的和仍要报告者回答的(问题必须具体,不是「请提供更多信息」);wontfix按原因关——已实现:指向代码,不要写进.out-of-scope/(那份知识库给的是被拒的请求,不是已做成的);拒掉的增强:写进.out-of-scope/再关
议题原文和讨论是上下文;agent brief 才是合同。议题可能在 ready-for-agent 上搁几天,仓库会改,所以 brief 要写得耐放:
- 写接口、类型、行为契约;点名该找或该改的类型和函数签名
- 不要写文件路径,不要写行号——改名第二天就废
- 写系统该做什么,不写怎么实现(「
SkillConfig接受可选的schedule: CronExpression」,不是「打开src/types/skill.ts第 42 行」) - 每条验收标准必须能单独核;「分拣应该能用」不算
- 写明不做什么,挡住镀金和邻接功能上的假定
每条评论必须以 This was generated by AI during triage. 开头。
只给不是你造的议题。 /to-tickets 产的工单已经是 agent 可拿的,不要再分拣。维护者说「把 #42 移到 ready-for-agent」,相信他们,直接改角色,跳过追问。
关键洞察
- 探路图产决定,主链产交付物。 两套票不要混。决策票问「我们选哪条路」;示踪弹工单问「这一刀让哪段端到端行为能演示」。混了,图会变成伪装成计划的待办列表。
- 雾是范围内但还不锋利;范围外是已经关掉的。 把范围外的活放进 Not yet specified,等于邀请以后的会话把它毕业成票。
- 分拣的闸在「核对」而不在「分类」。 未复现就写 agent brief,是把幻觉交给下一场会话。和诊断第 1 阶段同一类:没有会变红的信号,不准进入下一阶段。
个人思考
对照 Cookbooks 05-Agent工作流:那里用流水线 / 编排 / 评测再改约束单次调用怎么收成工作流。探路图是过程层的编排——节点是决定,边是阻塞,完成标准是「路清了」而不是「代码绿了」。下一章处理这些跨会话工件如何在窗口边界上不丢「为什么」。