Lesson 0016 · Engineering · 只能人启动(user-invoked)· 流程课

wayfinder:给太大太雾的任务画一张决策地图

你接手了一件真正大的事:把单体应用迁成事件驱动,或者从零做一个全新产品。 终点你隐约看得见,但从这里到终点的完全被雾罩着—— 打开一个 agent 会话想直接开写,却连第一张工单都列不出来, 因为每个想写的任务下面都挂着三个还没人回答的问题。 /wayfinder 就是为这一刻准备的:它把这件「一个 agent 会话装不下」的事, 画成工单系统上的一张共享地图——一个父 issue 挂着一排 决策票(Decision ticket,装的是问题,不是要做的活), 然后一次会话只解决一张票,直到雾散、路清。 它是 22 个已发布 skill 里最重的一条流程,也是只能由人启动的: AI 永远不会自己伸手拿它。学完这节课,你能说出两种调用模式各自的步骤、 四种票型谁来解、它会往工单系统写什么、雾散后交给谁, 以及行为不对时该改哪份文件的哪一段。

1. 它在整个系统里站在哪

0001 把 22 个 skill 分成配置层、编排层、纪律层。wayfinder 在编排层, 而且它是一条 on-ramp(入口匝道:一种产生工作、然后并入主流程的起点), 和 triage(别人提来的 bug 与需求)、diagnosing-bugs(有东西坏了) 并列三条入口之一。它的入口条件最苛刻:一个巨大而模糊的努力—— ask-matt 的原话是 greenfield project 或 huge feature build, 大到、雾到一个会话装不下,并称它是「这里最耗认知的一条流程」 (the most cognitively demanding flow here)。

它和主流程的关系是「更上游」。主流程是 grill-with-docsto-specto-ticketsimplement, 前提是想法已经能在一个会话里聊透。当想法大到连「聊透」这一步都装不下时, 先走 wayfinder:它不交付任何产品代码,只交付决策; 等地图上的雾散尽,再从 to-spec 并入主流程。 ask-matt 特意划了分界:grill-with-docs 磨利的是「一个会话装得下」的想法, wayfinder 服务的是「装不下」的那类。

调用方式一句话说死:只能人启动SKILL.md 的 frontmatter 里写着 disable-model-invocation: true,旁边的 agents/openai.yaml 里写着 policy.allow_implicit_invocation: false——两处一道把门关死: 你不输入 /wayfinder,它就不存在;AI 不会因为你任务大就自动加载它, 别的 skill 也不能用自然语言句子把它拉进来(0005 讲过的 prose 调用对它不适用)。 这是故意的:画地图要往工单系统里写一堆父 issue、子 issue、阻塞边, 这么重的副作用必须由人明确下令。

地图:0001 系统地图(wayfinder 行与「只能人启动」分组)· 路由规则:ask-matt/SKILL.md 的 On-ramps 一节 · 启动开关:wayfinder/SKILL.md frontmatter 与 wayfinder/agents/openai.yaml

2. 什么时候用它、什么时候换别的

docs 页给的判定句很具体:当一件工作 more than one agent session can hold (一个 agent 会话装不下),而且你能感觉到这件事的形状、却还没法把它写成 spec 或计划—— 用它。两个条件要同时成立:光是「大」不够(大而清楚直接去 to-spec), 光是「模糊」也不够(模糊但小,一场 grill-with-docs 就能聊透)。

情境 该用 wayfinder 更该去哪
全新产品或巨大功能,方向隐约有,从这里到终点的路看不见 (先画决策地图,一次解决一张票)
想法还没聊透,但一个会话装得下这场对话 不该(那是会话级的磨利,不需要地图) grill-with-docs(0003)
对话线程已经清楚,要落成一份可交接的 spec 不该(雾已散,直接写需求文档) to-spec(0009)
计划已经理解,要拆成可构建的实现票 不该(那是切片工作,不是找路) to-tickets(0010)
一堆别人报的 bug、提的原始需求堆在那没人分拣 不该(那是分拣入口,不是找路) triage(0014)
有东西坏了,而且第一眼找不出原因 不该(那是诊断入口) diagnosing-bugs(0015)
拿不准自己站在哪条流程的入口 不该 ask-matt(0019)
别拿它当常规流程用 ask-matt 的原话:它更慢、更密(slower and denser), 请把它留给「真正大而雾」的事,永远不要用在范围已经清楚的功能上。 一个范围清楚的功能走 wayfinder,等于为一下午的活建一张要维护几周的父 issue—— 地图本身会变成新的负担。

2.1 前置条件:工单系统得先接好线

地图和票都住在仓库的 Issue tracker(工单系统)上——这个词按 CONTEXT.md 的定义,指托管这个仓库 issue 的工具: GitHub Issues、GitLab Issues,或者本地 .scratch/ 目录下的一套 markdown 约定。 所以 wayfinder 假定 setup-matt-pocock-skills(0002)已经跑过: setup 会在 docs/agents/issue-tracker.md 里种下一节 「Wayfinding operations」,写清这个仓库的地图、子票、阻塞、前线查询具体怎么表达。 如果这份配置不存在,wayfinder 的 SKILL.md 让自己先去跑 setup; 如果连 tracker 都没提供,就退回本地 markdown 工单系统的默认约定(第 9 节细讲)。

判定与前置:docs/engineering/wayfinder.md 的 When to reach for it 与 Prerequisites 两节 (aihero.dev/skills-wayfinder)· 配置来源:setup-matt-pocock-skills/SKILL.md

3. 核心词汇:先把六个词说明白

wayfinder 自带一套独立词汇,CONTEXT.md 已经把其中最关键的 Decision ticket 收进了全仓库统一的领域语言。下面这张表按 SKILL.md 与 CONTEXT.md 的原文把每个词说成人话;后面的每一节都只用这套词。

术语 平实定义 容易误读成什么
Destination(目的地) 这张地图要找的路的终点:可能是一份要交接迭代的 spec、一个开规划前必须拍板的决策、或者一次就地完成的变更(比如数据结构迁移)。画地图的第一个动作就是给它命名,因为它定死了范围,之后每张票都拿它来量 愿景陈述或长篇目标文档——它只要一两行,但每个会话开工前都要先朝它对齐
Map(地图) 工单系统上挂着 wayfinder:map 标签的单个 issue,是这次努力唯一的权威工件(canonical artifact)。它是索引,不是仓库:每个决策只住在一个地方——它的票里;地图只写一行摘要加链接,绝不复述细节 把所有结论都抄进去的总文档——那样结论就有了两个家,改一处忘另一处
Decision ticket(决策票)
CONTEXT.md 收录
地图的子 issue,身体里只装一个问题;它的解决产物是一个决策,而不是一块要执行的构建切片——这正是它区别于实现票(to-tickets 切出来的那种)的地方。wayfinder 引入这个词,之后就简称「票」。每张票挂一个 wayfinder:<type> 标签,体量按「一个 100K token 的 agent 会话能解决」来切 伪装成决策的实现任务——如果票的答案是一坨代码而不是一个判断,多半是它越界了(见第 6 节)或该走主流程
Frontier(前线) 所有开放、没被阻塞、没人认领的子票——「已知的边缘」,也就是现在就能上手的工作面。阻塞关系用工单系统的原生依赖表达,所以前线在工单系统自己的界面里就能看见,人不用打开地图 一张写死在地图正文里的待办清单——开放票根本不列在地图正文里,靠查询发现
Fog of war(战争迷雾) 知道会来、但现在还没法精确写成问题的那些决策和调查,记在地图的 Not yet specified 一节。解决一张票会清掉它前方的雾,把现在能写清楚的部分「毕业」(graduate)成新票 「还没回答的票」——雾和票的区别不在于能不能回答,而在于能不能精确陈述问题(第 6 节的判定)
Resolution comment(解决评论) 解决一张票时发在它上面的那条评论,里面写着答案。随后关票、在地图的 Decisions so far 追加一行上下文指针。答案不写进票的正文;解决过程中产出的资产(原型、研究发现)以链接形式挂上来,不粘贴全文 把答案回填进票的正文——正文永远只是那个问题
两个贯穿全程的副词 HITL(human in the loop,人在环路里:这张票必须和真人一起解决)和 AFK(away from keyboard,离开键盘:agent 独自就能驱动)。 每张票必是其一;第 5 节的四种票型就是按这个轴排的。

权威原文:wayfinder/SKILL.md 开篇、The Map、Ticket Types、Fog of war 各节 · 领域词:CONTEXT.md 的 Decision ticket 条

4. 地图的身体:五个固定小节

地图正文是「整张地图的低分辨率视图」,每个会话开工时加载一次。它固定五个小节, 开放票列在里面——它们是开放的子 issue,靠查询找到:

## Destination
<这张地图要找的终点长什么样——spec、决策或变更。一两行;每个会话选票前先朝它对齐>

## Notes
<领域;每个会话都应该查阅的 skill;这次努力的长期偏好>

## Decisions so far
<!-- 索引——每张已关闭的票一行:足够判断相关性的一行摘要,细节点链接进票里看 -->
- [<已关闭票的标题>](链接) — <答案的一行摘要>

## Not yet specified
<!-- 战争迷雾:在范围内、但还没法开票的朦胧问题;随前线推进毕业 -->

## Out of scope
<!-- 被明确判在这次努力之外的活;已关闭,永不毕业 -->

三个小节各有一条容易违反的纪律,先在这里立住,第 6、8 节会反复用到:

权威原文:wayfinder/SKILL.md 的 The map body、Refer by name 两节

5. 四种票型:谁来解决这张票

每张票挂一个 wayfinder:<type> 标签,取值只有四个: researchprototypegrillingtask。 分型先看 HITL 还是 AFK,再看关键问题是什么。铁律先立: HITL 票只能通过和真人的实时交流来解决——agent 绝不替人站位子; SKILL.md 的原话是「一个自问自答的 grilling agent 已经破坏了这条规矩」。

票型 HITL 还是 AFK 由什么解决 什么时候选它 解决时留下什么
Research AFK 一个 /research 子代理(sub-agent:主会话派出去独立干活的 agent,0007 讲) 需要当前工作目录之外的知识:文档、第三方 API、本地知识库,决策在等一个事实 发现捕获在一次性的 research/<name> 分支上,票里留上下文指针;它可以并行烧掉,不挡前线
Prototype HITL /prototype skill(0008),或大纲、粗稿、stub 这类便宜粗糙的具体物 关键问题是「它该长什么样」「它该怎么表现」——纸上谈不拢,要个能上手反应的东西来抬高讨论的保真度 原型作为资产链接在票上,不粘贴
Grilling HITL /grilling/domain-modeling,一次一个问题(0003、0004) 默认票型——不确定选哪个时就是它 解决评论里的答案;过程中可能按 domain-modeling 的纪律更新 CONTEXT.md / ADR
Task HITL 或 AFK 手动劳动:agent 能做的就独自做(AFK),否则交给人一份精确清单(HITL) 没什么可决定、可原型、可研究的,但讨论被一件体力活挡着:注册一个服务好评判它的 API、开权限、搬数据好看见它的形状 做完了就算解决;答案记录做了什么,以及后续的票要依赖的事实(凭据位置、新 URL、行数)

5.1 Task 是唯一的例外,和它的资格证

wayfinder 的总原则是 Plan, don't do:每张票解决一个决策, 地图在「没什么还要决定的」那一刻就算完工——产出决策,不产出交付物。 「干脆把活干了吧」的冲动,通常就是信号:你已经摸到地图边缘,该交接了。 Task 型票是这套纪律里唯一「做」而不是「决定」的票型, 它挣到存在资格的理由只有一个:它解锁一个决策,而不是交付目的地。 如果一件「活」本身就是目的地的一部分,它不该出现在地图上——那是主流程的实现票。

整条 Plan, don't do 纪律本身也可以被推翻,但只有一个入口: 这次努力的 Notes 一节里写明「把执行也带进地图」。没有这句话,就老老实实产出决策。

权威原文:wayfinder/SKILL.md 的 Ticket Types、Plan, don't do 两节

6. 战争迷雾与范围之外

地图是故意不完整的:看不见的东西不要画。前线的票之外就是雾—— 那些你说得出「肯定要面对」、却还钉不下来的决策,因为它们挂在还没回答的问题上。 雾写在地图的 Not yet specified 一节:可以写得潦草也可以写得完整, 它同时是给协作者看的路标——这次努力在往哪走。

6.1 雾还是票?看能不能「说」,不看能不能「答」

判定标准(原文一句话) 测试是「你现在能不能把这个问题精确地说出来」—— 不是「你现在能不能回答它」。

毕业(graduation)是雾离开的唯一正路:解决一张票 → 清掉它前方的雾 → 把现在能写清的部分开成新票 → 把已毕业的那块从 Not yet specified 划掉, 让它从此只以新票的形式存在。如此一次一张,直到通往目的地的路清楚、再没有票剩下。

6.2 范围之外:永不毕业的另一种「模糊」

雾只朝目的地聚集;目的地定死了范围,所以越过目的地的活不是雾, 不许进 Not yet specified。它有自己专属的一节:Out of scope—— 你有意识地判在这次努力之外的工作。落到这里是「范围」问题,不是「清晰度」问题。 范围之外的活永不毕业:前线到目的地为止;它要回来,只有一种可能—— 目的地被重画,而那是作为一次新的努力重新开始,不是恢复旧地图。

已经开出来的票被发现越界(画图时误判,或被某个答案暴露):关掉它—— 关闭的票毫无歧义地不在前线上——然后在 Out of scope 一节留一行:摘要、 为什么越界、链到那张关闭的票。它不进 Decisions so far, 因为那里记录的是真正走过的路;划一条范围边界不是路上的一步。

同名不同物:别和 triage 的 .out-of-scope/ 搞混 wayfinder 的 Out of scope 是地图正文里的一节,判的是「这件活在不在这张地图的范围里」。 triage(0014)也管着一个叫 .out-of-scope/目录, 那里归档的是分拣时被拒绝的增强建议(0001 的写入清单记过)。 一个是地图内部的章节,一个是仓库里的归档目录,机制、主人、用途全不同。

权威原文:wayfinder/SKILL.md 的 Fog of war、Out of scope 两节 · 对照:0001 系统地图 的写入清单

7. 模式一:画地图(Chart the map)

触发方式:你带着一个松散的想法输入 /wayfinder。 SKILL.md 的 Invocation 一节把两种模式写得像操作手册,画图模式一共六步:

做什么 关键细节
1. 命名目的地 跑一场 /grilling + /domain-modeling,把这张地图要找的东西钉死:是 spec、决策还是变更 目的地定死范围,所以必须最先解决;它后面量着每一张票
2. 画出前线 再 grill 一轮,这次广度优先:铺满整个问题空间,不在任何一条线上深挖,把开放的决策和现在就能迈的第一步都翻出来 如果这轮没翻出雾——路已经清楚、整趟旅程一个会话装得下——你不需要地图。停下来问用户想怎么走
3. 建地图 建挂 wayfinder:map 标签的 issue:Destination 和 Notes 填好,Decisions so far 留空,雾写进 Not yet specified 一个努力只有一张地图;它是唯一的权威工件
4. 建现在能写清的票 开成地图的子 issue——然后第二遍再接阻塞边 必须先建后接:issue 得先有 id 才能互相引用。接线把票分成前线和被阻塞两组;写不清的留在雾里
5. 发射研究子代理 对刚建好的每张 research 票,各起一个 /research 子代理并行解决 发现捕获在一次性的 research/<name> 分支上,票里留上下文指针
6. 停 画图本身就是一个会话的全部工作 这个模式什么票都不亲手解决——研究票也是点火,不是陪读
为什么研究票能在画图当天就「解决」? 因为研究是 AFK:会话不用停下来等人,也不用停下来读。 docs 页的说法是——研究仍然是一张真票(下游决策挂在它身上的共享阻塞物), 但会话只需派一个子代理去把它并行烧掉,让前线保持快。 这也是全程「一个会话最多解决一张票」铁律的唯一例外(见第 8 节)。

注意第 2 步的「无雾出口」:0001 的系统地图专门把它收进了分支表里—— 画图时发现其实没雾,是 wayfinder 的合法结局之一,不是失败。 它替你省下的正是「为一个下午的活维护一张几周的父 issue」。

权威原文:wayfinder/SKILL.md 的 Invocation / Chart the map · 无雾分支:0001 系统地图 · 研究票动机:docs/engineering/wayfinder.md

8. 模式二:走地图(Work through the map)

触发方式:你带着一张地图(URL 或编号)输入 /wayfinder。 票可带可不带——不带,就是「你替我挑下一个决策」,不是用户挑。一共五步:

  1. 载地图——低分辨率视图(第 4 节那五个小节),不是每张票的正文。
  2. 选票——用户点了名就用点名的;否则按顺序拿前线第一张。 然后认领(claim):开工之前,先把票指派给驱动这张地图的开发者。 这个 assignee 就是认领本身:一张开放、没指派人的票就是没人认领的。
  3. 解决——按需变焦(zoom):相关的或已关闭的票,正文要用到了才去拉全文; 调用地图 Notes 一节点名的 skill;拿不准,就用 /grilling/domain-modeling
  4. 记录解决:把答案作为解决评论发出去 → 关闭 issue → 在地图的 Decisions so far 追加一行上下文指针(名字包链接加一行摘要,第 4 节的纪律)。
  5. 维护地图:把新浮出水面的票开出来(还是先建后接); 把答案已经能写清的雾毕业成票,并把已毕业的部分从 Not yet specified 划掉; 如果答案暴露某张票——这张或别的——越过了目的地,按第 6 节「范围之外」处理(关掉加留行), 而不是在路上顺手解决它;如果这个决定推翻了地图的其它部分,更新或删掉那些票。
铁律:一个会话最多解决一张票 SKILL.md 在 Invocation 开头用加粗写下:两种模式都一样, 永远不要在一个会话里解决超过一张票——研究票是唯一例外。 这不是省 token,是保质量:每张决策票按「一个 100K token 会话」切, 一张票装满一次专注;连着解决两张,第二张就是在变迟钝的上下文里拍的板。

8.1 并发是常态,所以 claim 必须是第一笔写入

SKILL.md 最后一句提醒你:用户可能并行跑多张未阻塞的票, 所以要预期别的会话正在同时改这个工单系统。 这就是认领顺序的理由——先指派、再开工,后来的会话看到 assignee 就会跳过这张票。 反过来的顺序(做完再指派)等于邀请两个会话解同一张票。

8.2 和 handoff 的对照:跨会话的记忆住在哪

0006 讲的 /handoff 是把一段对话压缩成 markdown 文件、搬进新会话; wayfinder 不需要它,因为这次努力的记忆不住在对话里—— 它就住在工单系统上:地图是低分辨率索引,票是细节,Decisions so far 是已走过的路。 每个新会话从地图重新定向,上下文窗口始终干净。 两套机制解决的是同一个问题(一个会话装不下),但 handoff 搬的是「会话状态」, wayfinder 搬的是「决策状态」——后者天然支持多人、多会话并行。

权威原文:wayfinder/SKILL.md 的 Invocation / Work through the map 及末句 · 对照机制:0006 handoff

9. 落到三种工单系统上

SKILL.md 把话说得很清楚:地图、子票、阻塞、前线查询物理上住在哪,是 tracker 特定的。 本 skill 只管语义(什么是地图、什么叫认领),物理操作去查仓库里 docs/agents/issue-tracker.md 的「Wayfinding operations」一节—— 那是 setup(0002)从模板种下来的。三份模板都在 skills/engineering/setup-matt-pocock-skills/ 目录里,下表是压缩对照:

操作 GitHub GitLab 本地 markdown(默认兜底)
建地图 gh issue create --label wayfinder:map,正文装 Notes / Decisions-so-far / Fog glab issue create --label wayfinder:map;有原生 epic 的付费档位可用 epic 当地图,带标签的 issue 到处可用 建文件 .scratch/<effort>/map.md 装同样五节
开子票 链接为地图的 GitHub sub-issue(走 gh api 的 sub-issues 端点);没启用 sub-issues 就在地图正文维护任务清单、并在子票正文顶部写 Part of #<map>;挂 wayfinder:<type> 标签 子票描述顶部写 Part of #<map>,挂 wayfinder:<type> 标签 .scratch/<effort>/issues/NN-<slug>.md(从 01 编号),问题进正文,Type: 行记票型
接阻塞边 GitHub 原生 issue 依赖:POST 到 issues/<child>/dependencies/blocked_by,注意要用阻塞方的数据库 id(.id),不是 #number 或 node_id;不可用则退化为正文顶部的 Blocked by: #<n> GitLab 原生 blocking 链接:以 note 形式发 /blocked_by #<n> 快捷动作;这是 Premium/Ultimate 功能,免费档退化为描述顶部的 Blocked by: 票文件顶部写 Blocked by: NN, NN 行;列出的文件全部 resolved 即为解除阻塞
查前线 列出地图的开放子票,丢掉有开放阻塞(issue_dependencies_summary.blocked_by > 0)或已有 assignee 的,地图顺序第一张胜出 glab issue list -F json 圈定地图子票,同样丢掉有开放阻塞或有 assignee 的,地图顺序第一张胜出 .scratch/<effort>/issues/ 目录,找开放、无阻塞、未认领的文件,编号最小者胜出
认领 gh issue edit <n> --add-assignee @me——会话的第一笔写入 glab issue update <n> --assignee @me——会话的第一笔写入 Status: claimed 写进票文件并保存——先于一切工作
解决 gh issue comment 发答案 → gh issue close → 地图 Decisions so far 追加指针 glab issue note 发答案(GitLab 的 close 不接受附言,顺序不能反)→ glab issue close → 追加指针 答案追加到票文件的 ## Answer 一节 → Status: resolved → 追加指针到 map.md

三份模板在一个设计上完全一致:阻塞优先用工单系统的原生依赖关系, 正文里的 Blocked by 行只是没有原生能力时的退化方案。 理由写在 SKILL.md 里:原生关系会把前线画在工单系统自己的界面里, 人不打开地图就能看见哪张票能拿——这正是 Frontier 这个定义成立的物理基础。

模板原文: issue-tracker-github.md · issue-tracker-gitlab.md · issue-tracker-local.md (各自的 Wayfinding operations 一节)· 语义与物理的分工:wayfinder/SKILL.md 的 The Map 一节

10. 它依赖谁、谁依赖它

                 ┌────────────────────────┐
                 │ setup-matt-pocock-     │  种下 docs/agents/issue-tracker.md
                 │ skills                 │  含 Wayfinding operations 一节
                 └───────────┬────────────┘
                             │ 前置(没跑就先跑;否则退回本地 markdown)
                             ▼
   grill ───────────►  ┌─────────────┐         ┌──► research(research 票,AFK 子代理)
   with-docs ───────►  │  wayfinder  │ 解决票时调 ├──► prototype(prototype 票,HITL)
   (0019 ask-matt    │ user-invoked│         ├──► grilling + domain-modeling
    路由过来的入口)    └──────┬──────┘         │    (grilling 票 / 拿不准时的默认)
                             │                └──► domain-modeling 顺手写 CONTEXT/ADR
              雾散、路清      ▼
                 ┌────────────────────────┐
                 │ to-spec(0009)        │  把地图链着的决策「折叠」成可建计划
                 │ → to-tickets → implement
                 └────────────────────────┘
Skill 关系 细节
setup-matt-pocock-skills 被 wayfinder 依赖(前置) 提供工单系统接线和「Wayfinding operations」一节;SKILL.md 说 tracker 应该已经被提供给你,没有就先跑 setup,再没有就退回本地 markdown 约定
grilling / domain-modeling 被 wayfinder 调用 画图第 1、2 步靠它们钉目的地、广度优先翻前线;grilling 票和「拿不准」时的默认解决方式也是它们。注意:grilling 解决票的过程里,domain-modeling 可能顺手更新 CONTEXT.md / ADR——那是 domain-modeling 写的,不是 wayfinder 自己写仓库文件
research 被 wayfinder 调用 research 票的解决器:派子代理并行烧掉,发现落在一次性 research/<name> 分支上。0007 深讲这个 skill 本身
prototype 被 wayfinder 调用 prototype 票的解决器:做个便宜粗糙的东西给人反应,原型链接上票。0008 深讲
ask-matt 路由到 wayfinder 在它的地图上,wayfinder 是「巨大而模糊的努力」这条 on-ramp,并负责警告「别给范围清楚的功能用」。0019 深讲
to-spec wayfinder 的默认下游 雾散后接棒:把地图上链着的决策折叠(collapse)成一份可建计划,再走 to-tickets、implement。0009 深讲

和 0005 那套词汇地板的关系是「平行不交叉」:wayfinder 不引用 codebase-design 的模块词汇, 它自己的六个词(第 3 节)就是全部术语需求;如果某张决策票恰好是「这个模块该怎么切」, 解决它靠的是 grilling + domain-modeling,必要时翻 codebase-design—— 但那是解决票内容的事,不是 wayfinder 机制的一部分。

依赖声明:wayfinder/SKILL.md 的 The Map、Ticket Types、Invocation 各节 · 下游交接:ask-matt/SKILL.md 的 On-ramps 一节

11. 副作用、下一步、行为不对改哪里

11.1 它会写什么、不会写什么

动作 写到哪里 说明
画地图 工单系统:1 个 wayfinder:map issue + N 个子 issue + 阻塞边 本地 tracker 则是 .scratch/<effort>/map.mdissues/NN-*.md 一排文件
发射研究子代理 一次性的 research/<name> 分支 + 票上的上下文指针 分支是耗材;发现以链接挂在票上,不粘贴进票正文
认领一张票 票的 assignee(或本地文件的 Status: claimed 行) 会话的第一笔写入,先于一切工作
解决一张票 解决评论 + 关票 + 地图 Decisions so far 追加一行 + Not yet specified 划掉已毕业的雾 + 新票与接线;必要时更新/删被推翻的票 本地 tracker 对应 ## Answer 一节、Status: resolved、map.md 的指针行
grilling 票解决过程中的命名与决策 可能更新 CONTEXT.md / docs/adr/* 由被调用的 domain-modeling 按它自己的纪律写(0004),不是 wayfinder 的机制
业务代码、产品交付物 默认什么都不写 Plan, don't do:地图产出决策。唯一的推翻入口是这次努力的 Notes 一节

11.2 雾散之后,默认交给谁

  1. 默认:进 /to-spec(0009)。ask-matt 的措辞是「折叠」—— to-spec 把地图上链着的决策压成一份可建的计划,然后照常走 /to-tickets(0010)、/implement(0011)。
  2. 例外:直接 /implement——只有当这件努力在做题过程中 真的变小到一个会话装得下时。ask-matt 明确警告:把地图直接环进 implement 会跳过那次折叠,把链着的细节全扔掉——决策票里的答案、 研究分支上的发现、原型链接,都会在这一跳里丢失。
  3. 如果画图第 2 步就发现没雾:地图根本没建,按用户选择直接进主流程—— 这是第 7 节讲过的合法出口。

11.3 行为不对时,去改哪个文件的哪一段

症状 先查 不要误改
一个会话连着解决好几张票,或者画图当天顺手把 grilling 票也聊了 wayfinder/SKILL.md 的 Invocation 开头铁律 + Chart the map 第 6 步 票型的定义段(那是分型,不是限量)
agent 在 grilling 票上自问自答、替人拍了板 SKILL.md 的 Ticket Types 开头 HITL/AFK 段落 grilling skill 本身(0003)——它没坏,是坏在 wayfinder 没守住人在环路里
还没说清的问题被预切成了一排小票 SKILL.md 的 Fog of war 一节「Fog or ticket?」判定 Out of scope 一节(那是范围问题,不是清晰度问题)
越界的票还留在前线上,或者越界票被写进了 Decisions so far SKILL.md 的 Out of scope 一节:关掉 + 留行 + 不进已决清单 triage 的 .out-of-scope/ 目录机制(0014)——同名不同物
汇报里出现一面 #42, #43 编号墙 SKILL.md 的 Refer by name 一节 地图模板的其它小节
某个仓库里认领、阻塞、前线查询的操作不对(比如用了 #number 去接 GitHub 依赖边) 该仓库的 docs/agents/issue-tracker.md 的 Wayfinding operations 一节;模板源在 setup-matt-pocock-skills/ 的三份 issue-tracker-*.md wayfinder/SKILL.md——它故意只写语义,物理操作都在 tracker 文档里
答案被回填进了票正文,或原型全文粘进了票 SKILL.md 的 The Map / Tickets 一段:「答案不是正文的一部分;资产用链接」 解决评论的格式
希望 AI 在任务变大时自动启用 wayfinder 这是设计决定:SKILL.mddisable-model-invocation: trueagents/openai.yamlallow_implicit_invocation: false;真要改,两处一起翻 description 字段塞触发词——对它无效,它不吃 model 触发

12. 检索练习

先别往回翻表,凭记忆答。选项的长度刻意对齐,不会从版式泄题。术语以本课、SKILL.md 与 CONTEXT.md 的精确定义为准。

自测(立即反馈)

1. wayfinder 的启动方式是哪一种?
2. 一张 Decision ticket 的解决产物是什么?
3. 「雾还是票」的判定标准是什么?
4. 「走地图」模式里,一个会话最多解决几张票?
5. agent 在一张 grilling 票上自问自答拍了板,违反了哪条?
6. 雾散、路清之后,作者默认推荐的下一步是?
7. 认领(claim)一张票的正确时机与方式是?
8. 阻塞关系首选怎么表达、为什么这么选?
额外提取练习(无选项) 合上本页,默写六个术语:destination、map、decision ticket、frontier、fog of war、resolution comment, 每个配一句「容易误读成什么」。再默写四种票型和它们各自的 HITL/AFK 归属, 以及画图六步、走票五步的顺序。写完对照第 3、5、7、8 节。 最后拿你手里一件真事做判定:它是「大而清楚」(直接去 to-spec)、 「模糊但小」(grill-with-docs),还是「又大又雾」(够格画地图)?

13. 下一课与一手材料

本课主一手材料(请打开原文读,不要只背本页摘要):

速查页(本课同步): reference/wayfinder.html

导航: 上一课 0015 diagnosing-bugs (另一条 on-ramp:有东西坏了时的入口,修完发现没好接缝会把架构问题交出去)。 总览仍回 0001 系统地图; 本课反复用到的相邻课: 0002 setup(接线从哪来)、 0003 grilling0004 domain-modeling(钉目的地和默认解决器)、 0006 handoff(搬会话状态,对照第 8.2 节)、 0007 research0008 prototype(两种票型的解决器)、 0009 to-spec(雾散后的默认下一站)、 0019 ask-matt(路由表本身)。

建议下一课(0017,正在并行编写): 0017 improve-codebase-architecture—— 三条 on-ramp 讲完后,换一条完全不同的线:codebase health(代码库体检)。 交接点值得先记住:0017 的扫描每次产生的是「一个加深想法」,正常走 grill-with-docs 进主流程; 如果那个想法大到、雾到一个会话装不下——比如「整个仓库的依赖方向要重画」—— 它就升级成你刚学的这张地图的原料。

老师就在会话里。 对本课任何一个边界有疑问——比如一张票同时像 grilling 又像 task 该怎么分、 Notes 推翻 Plan-don't-do 之后地图怎么收场、没有原生阻塞的工单系统上前线还能不能成立—— 直接在对话里问。回答会回到 wayfinder/SKILL.md、三份 tracker 模板、ask-matt/SKILL.md 的原文,不会临场编造。 做完检索练习后,回复「练习结果 / 哪里卡住 / 开 0017 或先补 0015」,我们安排下一课。