A vague idea arrives—too big for one agent session to hold, and shrouded in fog: from the current position to thedestinationthe route is not yet visible. Wayfinding is about finding that route, not rushing to the destination. This skill charts it as ashared mapon the issue tracker, then works through itsdecision tickets—questions whose answer is a decision, not a slice of a deliverable being built—until the route is clear.
Each project's goal is different, and naming the goal is the first act of charting—it shapes every ticket. It might be a specification to deliver and iterate on, a decision to lock in before planning begins, or an in-place change (such as a data structure migration). A map is domain-agnostic—engineering work, course content, whatever form it takes, it applies.
Planning, not doing
Wayfinder is by default aplanningtool: each ticket resolves a decision, and the map is complete when the route is clear—when there is nothing left to decide, it can be handed off to someone else to do the work. The urge to just start doing is usually a sign that you have reached the edge of the map and it is time to hand off. A project can override this setting in itsnotes—including execution tasks in the map—but by default, what is produced is decisions, not deliverables.
Refer by name
Every map and ticket is an issue, so it has aname—its title. In everything a human reads—narrative, the map's "decisions already made" section—refer to it by name, never by raw ID, number, or hyphenated identifier. A wall of #42, #43, #44 is hard to read; a name is clear at a glance. IDs and URLs do not disappear—but the name wraps the link—they just live inside the nameinside, not as a substitute for it.
Map
A map is an issue on this repository's issue tracker, tagged with wayfinder:map —this is the authoritative artifact. Its tickets are the map's sub-issues.
A map is anindex, not a repository. It lists the decisions that have been made and points to the tickets containing their details; a decision exists in only one place—its ticket—so the map never restates it, only summarizes it and links.
Where the map, its sub-tickets, blocking relationships, and frontier queries physically live depends on the specific tracker. The issue tracker should already be provided to you—if not, tell the user to run /setup-matt-pocock-skills. See the tracker documentation's "Wayfinding operations" section for how this repository expresses them. If no tracker is provided, default to the local Markdown tracker.
Map body
The entire map is loaded at low resolution, once per session. Open tickets are notlisted here—they are open sub-issues, found by query.
## 目的地
<到达此地图终点时的样子——该目标最终产出的规格、决策或变更。一两行;每个会话在选择 ticket 前都会以此为导向。>
## 笔记
<领域;每个会话应查阅的技能;此工作的固定偏好>
## 已有决策
<!-- 索引——每个已关闭 ticket 一行:足以判断相关性,然后点击链接获取 ticket 中的详细内容 -->
- [<已关闭 ticket 标题>](link) — <一行答案摘要>
## 尚未明确
<!-- 见"战争迷雾":范围内的迷雾,尚不能创建 ticket;随着前沿推进而毕业-->
## 范围外
<!-- 见"范围外":目的地之外排除的工作;已关闭,永不毕业-->
Ticket
Every ticket is the map'ssub-issue; a tracker's issue ID is its identity. Its body is the question, with a size limit of one 100K-token agent session:
## 问题
<该 ticket 解决的决策或调查>
Each ticket carries a wayfinder:<type> label—one ofresearch、prototype、grilling、task (see Ticket Types). The map and its tickets carry only the wayfinder: label and must not carry triage labels such as ready-for-agent : they record decisions, not implementation work.
A session claimsa ticket byassigningit to the developer driving the map, and does thisfirst, before starting any work, so that concurrent sessions skip it. The assigneeisthe claim: an open, unassigned ticket is unclaimed.
Blocking relationships use the tracker'snativedependencies—this is critical because it lets the frontierbe rendered visuallyin the tracker's own UI, letting people see what is claimable without opening the map. Fall back to a body convention only when a tracker lacks native blocking. A ticket isallof the tickets blocking it are closed; a ticket isunblocked;Frontiermeans open, unblocked, unassigned child tickets—the boundary of the known territory.
The answer is not part of the body—it is recorded upon resolution (seeAdvancing the Map). Assets created while resolving a ticket are linked to the issue rather than pasted in.
Ticket Types
Each ticket is either HITL(human-in-the-loop—advanced throughcollaborationwith a person who can speak autonomously) or AFK(driven independently by an agent). HITL tickets can only be resolved through real-time communication; an agent cannot substitute for the human side (a grilling agent that answers its own questions breaks this).
- Research (AFK): Read documentation, third-party APIs, or local resources such as knowledge bases to reveal facts that a decision depends on. Resolved by a subagent that invokes the Skill tool with "research". Use when knowledge outside the current working directory is needed.
- Prototype (HITL): Increase the fidelity of the discussion by producing a cheap, rough, concrete artifact—an outline, an early draft, stub code, or UI/logic code implemented by invoking the Skill tool with "prototype". Link the prototype as an asset. Use when "what it should look like" or "how it should behave" is the key question.
- Grilling (HITL): Conversation. The default. Always invoke the Skill tool twice, passing "grilling" and "domain-modeling" respectively.
- Task (HITL or AFK): Purely manual work that must be completed before making adecision—no decision, prototype, or research needed, but discussion is blocked until it is done. Register a service so its API can be judged, configure access permissions, migrate data so its shape can be observed. This is the only one thatdoes thingsrather thanmakes decisionstype of thing—it earns its place by unblocking decisions, not by delivering the destination. The Agent drives independently when possible (AFK); otherwise it hands the user a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any derived facts that follow-up tickets depend on (credential locations, new URLs, line counts).
Fog of War
The map isdeliberatelyincomplete: do not draw what you cannot yet see. Outside the active ticket is theFog of War—the faint outline of decisions and investigations you can sense coming but cannot yet pin down, because they depend on questions still open. Resolving a ticket clears the fog ahead of it, graduating what is now specifiable into new tickets—one at a time, until the road to the destination is clear and no tickets remain.
The map'sfuzzypart is where that faint outline is written down: suspected questions, areas to revisit later, risks put on hold. It is the unexplored frontier on the way to the destination—everything here is in scope, just not yet clear enough to create a ticket. Write it as roughly or as fully as visibility allows; it also serves as a signpost for collaborators, pointing the direction of the work.
Fog or ticket? The test is whether you can now state the question precisely—notwhether you can now answer it.
- Ticket whenthe question is already clear—even if it is blocked and you cannot yet act on it.
- Fuzzy whenyou cannot yet say it that clearly. Do not pre-cut the fog into ticket-sized pieces: it is coarser than tickets, and one area in the fog may graduate into several tickets, or none, depending on when the frontier reaches it.
Fuzzyexcludes what is already decided (that is "Decisions Made"), what is already a ticket, and what is out of scope (see the next section).
Out of Scope
Fog only gathers in the direction of the destination. The destination bounds the scope, so work beyond the destination isout of scope—it is not fog, it does not belong inFuzzy. It has its ownOut of Scopesection on the map: artifacts you have consciously excluded fromthiswork. It is scope, not clarity, that determines whether it goes here.
Out-of-scope artifacts never graduate—the frontier stops at the destination—so they can return only if the destination is redrawn, and even then as entirely new items, not as resurrections of the old.
Excluding something from scope is an act of scoping, not a step on the route. When an existing ticket is found to be beyond the destination—perhaps mis-scoped during mapping, or exposed by the outcome of a resolution—close it(a closed ticket is explicitly not on the frontier), and leave a line in theOut of Scopesection: a summary plus why it is out of scope, linking to the closed ticket. It does not go intoDecisions Made, which records the route actually traveled—a scope boundary is not a step on the route.
How to invoke
Two modes. In either case,each session resolves at most one ticket—except research tickets.
Drawing the map
The user invokes it with a vague idea.
- Name the destination. Invoke the Skill tool twice, passing "grilling" and "domain-modeling" respectively, to determine the target this map is looking for—a spec, a decision, or a change. The destination delimits the scope, so determine it first.
- Draw the frontier. Do another round of grilling, this timebreadth-first: spread across the whole space rather than going deep into any one branch, surfacing the open decisions and the first steps that can be taken now.If this round of grilling surfaces no fog—the route to the destination is already clear, and the whole journey is small enough to fit in a single session—then you do not need a map at all. Stop and ask the user what they want to do.
- Create the map(label
wayfinder:map): fill in the destination and notes, leave the existing decisions empty, and sketch the fog intonot yet specified. - Create the tickets you can specify now as child issues of the map—then inthe second roundset the blocking relationships (issues need IDs before they can reference each other). Also in this round write the cross-references with real IDs: the placeholder
#<n>will automatically link to an unrelated issue. The connections classify them as frontier and blocked; everything you cannot yet specify stays in the fog—that is, thenot yet specifiedsection. - Launch research subagents. For each
researchticket you just created, launch a subagent that invokes the Skill tool with "research" to resolve it in parallel, capture its findings on a disposableresearch/<name>branch, and attach a context pointer in the ticket. Push that branch, but do not create a PR: it will never be merged. - Stop—drawing the map is one session's work; it does not manually resolve any ticket.
Advancing the map
The user invokes it with the map (URL or number). The ticket isoptional—when none is specified, you pick the next decision, not the user.
- Loadthe map—a low-resolution view, excluding each ticket's body.
- Choose a ticket. If the user specified one, use it. Otherwise take the first frontier ticket in order.Claim it: assign it to yourself before starting any work.
- Resolve it according to its
wayfinder:<type>type as indicated by the label (see Ticket types). Read the label, not just the body: the body will not state the ticket type.Zoom as needed: fetch the full body of any related or closed ticket when needed; for the## Notesskills specified in the block, invoke the Skill tool. When in doubt, invoke the Skill tool twice, passing "grilling" and "domain-modeling" respectively. - Record the resolution: post the answer asa resolution comment,Close the issue, and append one to the map's "existing decisions"Context pointer。
- Add newly surfaced tickets (create then wire); promote fogged content made decidable by this answer, removing each promoted fragment fromnot yet specifiedso that it exists only in the new ticket. If the answer reveals that a ticket (current or other) is outside the destination, mark itout of scoperather than resolving it as a step on the route. If the decision invalidates other parts of the map, update or delete those tickets.
The user may run unblocked tickets in parallel, so expect that other sessions may be editing the tracker at the same time.