| name | wayfinder |
| description | 把一大块工作——超过单个 agent 会话所能容纳的量——规划成 issue 跟踪器上一张共享的决策工单地图,并逐个解决它们,直到通往目的地的道路清晰可见。 |
| disable-model-invocation | true |
一个粗略的想法到来了——大到一个 agent 会话装不下,且笼罩在迷雾中:从此处通往目的地的道路尚不可见。寻路关乎找到那条路,而不是径直冲向目的地。这个技能把道路绘制成仓库 issue 跟踪器上的一张共享地图,然后逐个处理它的决策工单——那些其解决结果是一个决策、而不是一次构建中待执行的切片的问题——直到路线清晰。
目的地因每项工作而异,为它命名是绘图的第一步——它塑造每一张工单。它可能是一份要移交并迭代的规格说明、一个要在规划开始前锁定的决策,或者一次就地做出的改动,比如一次数据结构迁移。这张地图与领域无关——工程工作、课程内容,凡是契合这种形态的都行。
规划,而不是执行
Wayfinder 默认是规划:每张工单解决一个决策,当道路清晰时地图即完成——在有人去做那件事之前,没有什么剩下要决定的了。想要直接干活的那股拉力,通常正是你已到达地图边缘、该移交了的信号。一项工作可以在它的 Notes 中覆盖这一点——把执行带进地图本身——但在没有这样做的情况下,产出的是决策,而非交付物。
以名称指代
每张地图和工单都是一个 issue,所以它有一个名称——它的标题。在人所阅读的一切中——叙述、地图的 Decisions-so-far——都以那个名称指代它,绝不用一个裸的 id、编号或 slug。一堵 #42, #43, #44 的墙无法辨读;名称一眼即读。id 和 URL 不会消失——名称包裹着它的链接——但它们藏在名称内部,绝不取代名称。
地图
地图是本仓库 issue 跟踪器上的单个 issue,标注 wayfinder:map——那件标准产物。它的工单是地图的子 issue。
地图是一个索引,不是一个存储库。它列出已做出的决策,并指向持有其细节的工单;一个决策恰好存在于一个地方——它的工单——所以地图从不复述它,只给出要点并链接。
地图、它的子工单、阻塞以及前沿查询在物理上存放于何处,是特定于跟踪器的。 issue 跟踪器应该已经提供给你了——如果没有,运行 /setup-matt-pocock-skills。查阅跟踪器文档的"Wayfinding operations"小节,了解本仓库如何表达它们。如果没有提供跟踪器,就默认使用本地 markdown 跟踪器。
地图正文
整张地图的低分辨率版本,每个会话加载一次。未关闭的工单不被列出——它们是未关闭的子 issue,通过查询找到。
## Destination
<what reaching the end of this map looks like — the spec, decision, or change this effort is finding its way to. One or two lines; every session orients to it before choosing a ticket.>
## Notes
<domain; skills every session should consult; standing preferences for this effort>
## Decisions so far
<!-- the index — one line per closed ticket: enough to judge relevance, then zoom the link for the detail the ticket holds -->
- [<closed ticket title>](link) — <one-line gist of the answer>
## Not yet specified
<!-- see "Fog of war": in-scope fog you can't ticket yet; graduates as the frontier advances -->
## Out of scope
<!-- see "Out of scope": work ruled beyond the destination; closed, never graduates -->
工单
每张工单是地图的一个子 issue;跟踪器的 issue id 就是它的身份。它的正文是那个问题,大小以一个 100K token 的 agent 会话为准:
## Question
<the decision or investigation this ticket resolves>
每张工单带有一个 wayfinder:<type> 标签——research、prototype、grilling、task 之一(见 Ticket Types)。
一个会话通过把工单指派给驱动地图的开发者来认领它,这要最先做、在任何工作之前,这样并发的会话就会跳过它。那个指派人就是认领:一个未关闭、未指派的工单即未认领。
阻塞使用跟踪器的原生依赖关系——这至关重要,因为它在跟踪器自己的 UI 中可视化地渲染出前沿,所以人不用打开地图就能看到什么是可取的。只有缺乏原生阻塞的跟踪器才回退到正文约定。当阻塞它的每张工单都关闭时,一张工单即解除阻塞;前沿是那些未关闭、未阻塞、未认领的子项——已知的边缘。
答案不是正文的一部分——它在解决时记录(见 Work through the map)。解决一张工单时创建的资产从 issue 链接出去,而不是粘贴进来。
工单类型
每张工单要么是 HITL——human in the loop,与一个为自己发声的人一起处理——要么是 AFK,由 agent 独自驱动。一张 HITL 工单只有通过那场实时交流才能解决;agent 绝不代替人的那一方(一个自问自答的 grilling agent 就破坏了这一点)。
- Research(AFK):阅读文档、第三方 API 或本地资源(如知识库),以浮现出一个决策所等待的事实。由一个
/research 子 agent 解决。当需要当前工作目录之外的知识时使用。
- Prototype(HITL):通过制作一个廉价、粗糙、具体、可供反应的产物来提高讨论的保真度——一份提纲、一个粗略的尝试、一个桩,或经由 /prototype 技能的 UI/逻辑代码。把原型作为资产链接。当"它应该长什么样"或"它应该如何行为"是关键问题时使用。
- Grilling(HITL):经由 /grilling 和 /domain-modeling 技能进行对话,一次一个问题。默认情形。
- Task(HITL 或 AFK):在能够做出一个决策之前必须发生的手工工作——没有什么要决定、做原型或研究的,但讨论在它完成之前一直被阻塞。注册一个服务好让它的 API 能被评判、开通访问权限、搬移数据好让它的形态能被看到。这是唯一一个做事而非决策的类型——它凭借解除一个决策的阻塞、而非交付目的地来赢得自己的位置。agent 在能独自驱动的地方独自驱动它(AFK);否则它交给人一份精确的清单(HITL)。工作完成时即解决;答案记录做了什么以及后续工单所依赖的任何由此产生的事实(凭据位置、新 URL、行数)。
战争迷雾
地图是刻意不完整的:不要绘制你还看不见的东西。在活跃的工单之外躺着战争迷雾——对那些你能感觉到即将到来、但还无法钉住的决策和调查的朦胧视野,因为它们悬于仍未关闭的问题之上。解决一张工单会清除它前方的迷雾,把如今可界定的东西升格为新鲜的工单——一次一个,直到通往目的地的道路清晰、没有工单剩下。
地图的 Not yet specified 小节就是那个朦胧视野被写下来的地方:疑似的问题、稍后要重访的区域。它是朝向目的地的、尚未被发现的前沿——这里的一切都在范围内,只是还不够锐利到能开工单。视野允许多松就写多松、多满就写多满;它同时充当一个路标,供阅读这项工作走向何方的协作者参考。
迷雾还是工单? 判据在于你现在能否精确地陈述这个问题——而不是你现在能否回答它。
- 当问题已经锐利时开工单——即便它被阻塞、你还无法对它采取行动。
- 当你还无法把它表述得那么锐利时归入 Not yet specified。不要预先把迷雾切成工单大小的碎片:它比工单更粗糙,而且一旦前沿抵达它,一块可能升格为若干工单,或者一个都不成。
Not yet specified 不包括已经决定的(Decisions so far)、已经是活跃工单的,以及超出范围的(下一小节)。
超出范围
迷雾只会朝向目的地聚集。目的地固定了范围,所以在它之外的工作是超出范围的——它不是迷雾,也不属于 Not yet specified。它在地图上有自己的 Out of scope 小节:你有意识地排除出这项工作之外的工作。落到这里靠的是范围,而不是锐利度。
超出范围的工作绝不升格——前沿在目的地处停止——所以它只有在目的地被重画时才回来,而且那时是作为一项全新的工作,而不是一次续接。
把某件事判为超出范围是一个界定范围的动作,而不是路线上的一步。当一张已经存在的工单结果发现坐落在目的地之外——绘图时误纳进来,或被一次解决所暴露——就关闭它(一张关闭的工单毫不含糊地不在前沿上),并在 Out of scope 小节留一行:要点加上它为何超出范围,链接那张关闭的工单。它不进 Decisions so far,后者记录的是实际走过的路线——一条范围边界不是路线上的一步。
调用
两种模式。无论哪种方式,每个会话解决的工单绝不超过一张——research 工单除外。
绘制地图
用户带着一个粗略的想法调用。
- 为目的地命名。 运行一次
/grilling 和 /domain-modeling 会话,钉住这张地图正在寻路通向什么——那份规格说明、决策或改动。目的地固定了范围,所以它最先敲定。
- 绘制前沿。 再次拷问,这次是广度优先:在整个空间中扇形铺开,而不是在任何单一线索上深挖,浮现出未关闭的决策以及现在可采取的第一批步骤。如果这没浮现出任何迷雾——通往目的地的道路已经清晰,整段旅程小到一个会话就够——你就不需要地图。停下,问用户他们想如何推进。
- 创建地图(标签
wayfinder:map):填好 Destination 和 Notes,Decisions-so-far 为空,迷雾勾勒进 Not yet specified。
- 创建你现在能界定的工单作为地图的子 issue——然后在第二遍中接上阻塞边(issue 需要先有 id 才能互相引用)。接线把它们分拣进前沿和被阻塞者;你还无法界定的一切都留在迷雾里——Not yet specified 小节。
- 启动 research 子 agent。 对你刚创建的每张
research 工单,启动一个 /research 子 agent 并行解决它,把它的发现捕获到一个用完即弃的 research/<name> 分支上,并从工单留一个上下文指针。
- 停下——绘图是一个会话的工作;它不亲手解决任何东西。
处理地图
用户带着一张地图(URL 或编号)调用。工单是可选的——没有它,就由你、而不是用户,来挑下一个决策。
- 加载地图——那个低分辨率视图,而不是每一张工单正文。
- 选择工单。如果用户指定了一张,就用它。否则按顺序取第一张前沿工单。认领它:在任何工作之前把它指派给自己。
- 解决它——按需缩放:按需获取任何相关或已关闭工单的完整正文;调用
## Notes 块所指名的技能。如有疑问,用 /grilling 和 /domain-modeling。
- 记录解决结果:把答案作为一条解决评论发布,关闭该 issue,并把一个上下文指针追加到地图的 Decisions-so-far。
- 添加新浮现的工单(先创建后接线);把答案已使之可界定的任何迷雾升格,从 Not yet specified 中清除每一块已升格的部分,让它只作为它的新工单存在。如果答案揭示某张工单——这张或另一张——坐落在目的地之外,就把它判为超出范围,而不是在路线上解决它。如果这个决策使地图的其他部分失效,就更新或删除那些工单。
用户可能并行处理未阻塞的工单,所以要预料到其他会话在并发地编辑跟踪器。