关于 wayfinder
wayfinder 是一项规划技能,可在仓库的 issue tracker 中把开放式想法整理为共享决策地图。它用关联工单跟踪待决问题,并逐项推进规划,默认不执行实现工作。
主要功能
- 01在 issue tracker 中维护共享地图
- 02以子 issue 关联决策工单
- 03按依赖关系追踪可处理前沿
- 04支持研究、原型、讨论和任务工单
- 05记录决策与新浮现的问题
适用场景
- 01梳理项目启动前需要作出的决策
- 02通过关联问题明确规格
- 03协调多个 Agent 会话间的规划工作
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ leandrocfe/ skills --skill wayfinder安装后在 Claude Code 中输入/wayfinder确认已加载。
附带文件agents/openai.yaml
详细介绍
一个零散的想法来了——它太大,无法在一次 Agent 会话中完成,而且笼罩在迷雾中:从这里到目的地的路径尚不可见。Wayfinding 旨在找到这条路径,而不是直接冲向目的地。此技能会在仓库的 issue 跟踪器中将路径绘制成一张共享地图,然后逐一处理其中的决策工单——这些问题的解决方式是做出决策,而不是拆成待执行的构建任务——直到路线清晰为止。
每次工作的目的地都不一样,为它命名是绘制地图的第一步——它会塑造每张工单。目的地可以是一份需要交付并迭代的规范、一项必须在规划开始前敲定的决策,也可以是在原地完成的变更,例如数据结构迁移。这张地图不依赖特定领域——工程工作、课程内容,任何适合这种形式的事情都可以。
规划,而非执行
Wayfinder 默认用于规划:每张工单解决一项决策,地图在路径清晰时结束——也就是在有人动手做之前,不再有待决定的事项。想要直接执行工作的冲动,通常意味着你已到达地图的边缘,是时候交接了。某项工作可以在其 Notes 中覆盖此规则——将执行纳入地图本身——但若无此说明,请产出决策,而非交付物。
按名称引用
每张地图和每张工单都是一个 issue,因此都有一个名称——也就是标题。在所有供人阅读的内容中——叙述、地图的 Decisions-so-far——都要用名称来指代它,绝不要只用 id、编号或 slug。一串 #42, #43, #44 难以阅读;名称则能让人一眼看懂。id 和 URL 不会消失——名称会包含它们的链接——但它们只会作为名称的一部分出现,绝不会取代名称。
地图
地图是此仓库的 issue 跟踪器中的单个 issue,带有 wayfinder:map 标签——这是规范产物。它的工单是地图的子 issue。
地图是索引,不是存储库。它列出已做出的决策,并指向保存其详细内容的工单;一项决策只存在于一个地方——它对应的工单——因此地图绝不重复决策内容,只做摘要并提供链接。
地图、其子工单、阻塞关系以及 frontier 查询在物理上如何存放,取决于具体的跟踪器。 跟踪器应该已经提供给你——如果没有,请运行 /setup-leandrocfe-skills。请查看跟踪器文档的 “Wayfinding operations” 部分,了解_此_仓库如何表达这些内容。如果未提供跟踪器,则默认使用 local-markdown 跟踪器。
地图正文
整张地图以低分辨率呈现,每个会话加载一次。不会列出未关闭的工单——它们是通过查询找到的未关闭子 issue。
## Destination
<como é chegar ao fim deste mapa — a spec, decisão ou mudança que esta empreitada está buscando. Uma ou duas linhas; toda sessão se orienta por isso antes de escolher um ticket.>
## Notes
<domínio; skills que toda sessão deve consultar; preferências permanentes desta empreitada>
## Decisions so far
- [<título do ticket fechado>](link) — <resumo de uma linha da resposta>
## Not yet specified
## Out of scope
工单
每张工单都是地图的一个子 issue;跟踪器中的 issue id 就是它的身份。它的正文是一个问题,大小适合一次 100K token 的 Agent 会话:
## Question
<a decisão ou investigação que este ticket resolve>
每张工单都带有一个 wayfinder:<type> 标签,类型为 research、prototype、grilling、task 之一(参见工单类型)。
会话会通过将工单分配给负责推进地图的开发者来认领工单,并且必须首先认领,然后再开始任何工作,以便并行会话跳过该工单。这个 assignee _就是_认领者:未关闭且没有 assignee 的工单表示尚未有人认领。
阻塞关系使用跟踪器的原生依赖关系——这至关重要,因为它会在跟踪器 UI 中_直观地_显示 frontier,这样人就能看到哪些工单可处理,而不必打开地图。只有不支持原生阻塞关系的跟踪器才会退回到正文中的约定格式。当阻塞某张工单的所有工单都已关闭时,这张工单就处于未阻塞状态;frontier 是未关闭、未阻塞且未被认领的子工单——也就是已知范围的边界。
答案不属于正文——它会记录在解决结果中(参见处理地图)。解决工单时创建的资产会从 issue 链接,不会粘贴到 issue 内。
工单类型
每个工单要么是 HITL — human in the loop,由一个代表自己发言的人类共同处理 — 要么是 AFK,由 Agent 独自处理。HITL 工单只能通过这场实时交流解决;Agent 绝不能代替人类一方发言(一个自己回答自己问题的 grilling Agent 就违反了这一点)。
- Research(AFK):阅读文档、第三方 API 或知识库等本地资源,以找出某项决策所依赖的事实。由 subagent
/research解决。当需要当前工作目录之外的知识时使用。 - Prototype(HITL):制作一个具体、低成本且粗糙的产物供人讨论,从而提高讨论的保真度 — 例如大纲、草图、存根,或通过 skill /prototype 编写的 UI/逻辑代码。将 prototype 链接为 asset。当“它应该是什么样子”或“它应该如何表现”是核心问题时使用。
- Grilling(HITL):对话。这是默认情况。始终调用 skills /grilling 和 /domain-modeling。
- Task(HITL 或 AFK):在做出决策之前必须完成的人工工作 — 没有什么需要决策、原型设计或研究,但讨论会一直卡住,直到工作完成。注册服务以便评估其 API、开通访问权限、迁移数据以便查看其格式。这是唯一一种执行而非做决策的类型 — 它之所以有存在价值,是因为能解锁一项决策,而不是因为交付最终成果。条件允许时由 Agent 独自处理(AFK);否则,向人类提供一份精确的清单(HITL)。工作完成后即为解决;答案会记录已完成的工作,以及后续工单所依赖的任何相关事实(凭证存放位置、新 URL、行数)。
战争迷雾
地图会_刻意_保持不完整:不要描绘你还看不到的内容。除了进行中的工单之外,还有战争迷雾 — 你察觉即将到来的决策和调查,却还无法确定其具体内容,因为它们依赖尚未解答的问题。解决一个工单会驱散它前方的迷雾,让如今可以明确界定的内容逐步形成新工单 — 一次一个,直到通往目的地的路径清晰,且不再有任何工单。
地图中的 尚未具体说明 部分用于记录这片迷雾:可疑的问题、之后需要重新审视的领域。这是通往目的地、尚未探索的前沿 — 这里的所有内容都在范围内,只是还不够清晰,无法形成工单。可以根据当前认知,写得宽泛或详尽;这也能为协作者指明项目的发展方向。
是迷雾还是工单? 判断标准是你现在能否准确表述问题 — 而不是 现在能否回答它。
- 当问题已经清晰时,创建工单 — 即使它被阻塞、暂时无法处理。
- 当你还无法清晰地表述问题时,归入 尚未具体说明。不要提前把迷雾切分成工单大小的块:它比工单更粗略;等前沿推进到那里时,一片区域可能逐步形成多个工单,也可能一个都没有。
尚未具体说明 不包括已经做出的决定(迄今的决策)、已经存在的工单,以及超出范围的内容(见下一节)。
范围之外
迷雾只会沿着通往目标的方向逐渐累积。目标确定了范围,因此超出目标的工作属于范围之外——它不是迷雾,也不属于 Not yet specified。它在地图上有自己的 Out of scope 部分:你有意排除在_本次_工作之外的内容。决定它归属何处的是范围,而不是清晰度。
范围之外的工作永远不会晋级——frontier 止于目标——因此只有在重新设定目标时,它才会再次出现;届时它会成为一项新的工作,而不是继续之前的工作。
声明某项工作超出范围,是范围界定行为,而不是路线中的一步。当现有 ticket 被发现超出目标时——可能是在绘制路线时范围界定不当,也可能是在解决问题时才暴露出来——关闭它(已关闭的 ticket 明确位于 frontier 之外),并在 Out of scope 部分添加一行:写明摘要和超出范围的原因,并链接到已关闭的 ticket。它不属于 Decisions so far,因为该部分记录的是实际走过的路线——范围边界不是路线中的一步。
调用方式
有两种模式。无论哪种模式,每个会话最多只能解决一个 ticket——research ticket 除外。
绘制地图
用户通过提出一个大致的想法来调用。
- 确定目标。 运行一轮
/grilling和/domain-modeling会话,明确这张地图要实现什么——规范、决策或变更。目标确定了范围,因此要先解决目标。 - 绘制 frontier。 再次进行探索,这次要广泛展开:遍历整个空间,而不是深入单一路径,找出尚未做出的决策和可以立即着手的第一步。如果没有发现任何迷雾——通往目标的路径已经清楚,整个过程也足够短,可以在一个会话内完成——就不需要地图。停下来询问用户想如何继续。
- 创建地图(标签为
wayfinder:map):填写 Destination 和 Notes,Decision-so-far 留空,并在 Not yet specified 中勾勒迷雾。 - 创建当前能够明确说明的 ticket,将其作为地图的子 issue;然后在第二轮中连接 blocking edge(issue 需要先有 id,才能相互引用)。连接 edge 后,它们会被划分为 frontier 上的 issue 和被阻塞的 issue;目前仍无法明确说明的内容留在迷雾中,即 Not yet specified 部分。
- 启动 research 子代理。 对于刚创建的每个
researchticket,启动一个/research子代理并行解决,在临时 branchresearch/<name>中记录发现,并从 ticket 添加 context pointer。 - 停下——绘制地图是一整个会话的工作;不要手动解决任何问题。
处理地图
用户会携带一张地图(URL 或编号)发起请求。工单是可选的——如果没有工单,选择下一项决策的人是你,而不是用户。
- 加载地图——低分辨率视图,而不是每个工单的正文。
- 选择工单。如果用户指定了工单,就使用它。否则,按顺序选择 frontier 中的第一个工单。认领它:在开展任何工作之前,将其指派给自己。
- 解决它——按需缩放:按需获取任何相关或已关闭工单的完整正文;调用
## Notes区块中列出的技能。如有疑问,使用/grilling和/domain-modeling。 - 记录解决方案:将答案作为解决评论发布,关闭 issue,并向地图的 Decisions-so-far 添加一个上下文指针。
- 添加新显现的工单(先创建,再关联);将答案已使其可明确描述的任何模糊事项升级为工单,并从每个已升级事项中清除 Not yet specified,使其仅作为新的工单存在。如果答案表明某个工单——无论是当前工单还是其他工单——超出目标范围,就将其声明为范围外,而不是在路线中解决。如果决策使地图的其他部分失效,请更新或删除这些工单。
用户可能会并行处理已解除阻塞的工单,因此请做好其他会话同时编辑跟踪系统的准备。