| name | map |
| description | Discover work structure by approaching goals and finding blockers — emergent planning through action, not top-down decomposition |
/yx:map — Yak Mapping
Overview
Yak mapping is emergent planning through action. You discover work structure by approaching goals and finding what blocks you, not by decomposing from the top down.
Core principle: "It is in the doing of the work that we discover the work that we must do." — Woody Zuill
When invoked with arguments (e.g., /yx:map build a REST API), use those as the initial goal.
Announcement
Always start yak mapping by saying:
"I'm using /yx:map to discover the work structure by approaching the goal. I'll add yaks one at a time and show the map after each addition."
This sets expectations that we're doing emergent discovery, not top-down planning.
When to Use
Use when:
- User asks to "plan" or "map out" work using yaks
- User says "adapt for yaks" or "plan with yaks" or "break down into yaks"
- Starting to structure a new feature or goal
- Need to discover work structure for complex work
- User provides a goal and you need to find blockers
Don't use when:
- Just executing already-mapped work (use
/yx:work)
- Single straightforward task (just do it)
- User wants detailed specs (use
/yx:prepare for fleshing out individual yaks)
THE IRON LAW
After EVERY yx add, immediately run yx ls to show what changed.
No exceptions:
- Not "I'll show it at the end"
- Not "just adding a quick one"
- Not "the structure is obvious"
yx add then yx ls is non-negotiable. This keeps the human in sync with your thinking.
The Approach Pattern
Phase 1: Scope the Goal (BEFORE creating child yaks)
After creating the top-level goal yak, have a conversation to agree scope before going deeper. Don't start adding children yet.
- Add the goal yak and show the map
- Summarise your understanding of the goal back to the human
- Present candidate areas you've identified (if any), but as a conversation — NOT as yaks yet
- Ask the human to pick what's in scope for now
- Only after agreement, start the discovery loop on the agreed scope
This prevents runaway mapping where you create yaks for everything you can think of. The human decides what matters now.
Example:
I've created the goal yak. Before I start mapping blockers, let me check scope with you.
From the research, I can see several areas where this could apply:
- Area A (quick win)
- Area B (medium effort, high impact)
- Area C (ambitious stretch goal)
Which of these do you want to map out now? We can always add the others later.
Phase 2: Discovery Loop (ONE yak at a time)
1. Add ONE yak
2. Show map with `yx ls` (THE IRON LAW)
3. Add brief context to that yak (a sentence or two)
4. Pick ONE child to explore next
5. Repeat
Step-by-Step Process
1. Start with the Agreed Scope
Only create child yaks for areas the human has agreed to explore.
2. Approach It (Don't Decompose)
Ask yourself: "If we tried to implement this RIGHT NOW, what would we try first?"
Don't ask: "What are all the components?"
3. Discover ONE Blocker
When approaching reveals "we need X first", add X as a child:
yx add write events to git ref --under sync
yx ls
The nesting means: "sync is BLOCKED BY write events"
4. Add Brief Context
During mapping, context is lightweight — just enough to remember what this is:
yx context write events to git ref <<'EOF'
Commands are logged as events in git refs/notes/yaks for replay.
Need to implement `yx log` command to verify.
EOF
Detailed specs, acceptance criteria, and comprehensive context come later in /yx:prepare.
5. Approach This Blocker
Now explore this one level deeper:
yx add implement log command --under "write events to git ref"
yx ls
6. Continue ONE Level at a Time
Keep approaching and discovering until you hit a leaf node (can implement without discovering new blockers).
When to Stop Exploring a Branch
Stop when:
- You've reached a leaf (no new blockers discovered)
- You've identified enough structure to start work
- Going deeper requires actually doing the work (not just thinking)
- You hit a question only the human can answer (use
@needs-human)
Then explore other branches or let someone start implementing leaves.
@needs-human Convention
When mapping surfaces a question only the human can answer:
- Tag the yak:
yx tag "yak name" @needs-human
- Add the question to the yak's context
- Move on to another branch
When encountering a @needs-human tag:
Surface it: "This yak has an open question: [question]. Want to answer now or should I continue mapping elsewhere?"
Why Nesting Works
Yaks enforces: parent cannot be marked done if it has incomplete children.
The nesting is an artifact of discovery, not a planning decision. You literally CAN'T complete the parent until you clear the blocker.
Growth is bidirectional:
- Downward: Approach a goal, discover blockers → add them as children
- Upward: Working on a goal, realize it's part of something bigger → create parent with
yx move
Multiple blockers all become children:
yx add deploy to production
yx add deployment script --under "deploy to production"
yx add configure secrets --under "deploy to production"
yx add update documentation --under "deploy to production"
You must complete all three before the parent goal is achievable.
Work deepest-first (leaves before parents):
deploy to production
├─ ○ deployment script <- Start here
├─ ○ configure secrets <- Or here
╰─ ○ update documentation <- Or here
The structure naturally guides you to unblocked work (leaf nodes).
Reorganizing Flat Yaks into a Dependency Hierarchy
Sometimes you have a flat set of sibling yaks and realize they have phased dependencies. To restructure them:
The rule: later phases are parents, earlier phases are children. Phase 1 items nest under the Phase 2 item they block, not the other way around.
Example: You're planning a tea party. You start with flat yaks:
tea party
├─ ○ buy teapot
├─ ○ buy tea leaves
├─ ○ brew tea
├─ ○ invite friends
╰─ ○ serve tea
Then you realize: you can't serve tea until it's brewed and friends are invited. You can't brew until you have a teapot and leaves. Restructure so prerequisites nest under what they block:
yx move "brew tea" --under "serve tea"
yx move "invite friends" --under "serve tea"
yx move "buy teapot" --under "brew tea"
yx move "buy tea leaves" --under "brew tea"
Result:
tea party
╰─ ○ serve tea
├─ ○ brew tea
│ ├─ ○ buy teapot
│ ╰─ ○ buy tea leaves
╰─ ○ invite friends
Now the tree enforces the order: work leaves first (buy teapot, buy tea leaves, invite friends), then brew, then serve.
Yak Granularity
Leaf yaks should be small enough to just do (20-40 minutes):
- Could implement in one TDD cycle
- Single focused change
- Can describe "done" in 3-5 bullets
Right-sized yaks:
- Approaching reveals 2-4 blockers → probably good size
- Approaching reveals 0 blockers and feels ready to implement → perfect leaf
- Approaching reveals 0 blockers and feels tiny → too granular
- Approaching reveals 6+ blockers → too large, needs intermediate level
If a yak feels too big:
- Don't try to spec it out in detail during mapping
- Add a brief context note
- Continue approaching to discover blockers
- The tree will naturally decompose it through discovery
After Mapping is Complete
Once you've discovered blockers and identified leaf nodes, present the map:
Mapping complete! The yak tree:
[show yx ls output]
Ready-to-implement leaf yaks:
- yak name (context: what it does)
- another yak (context: what it does)
Next steps:
1. Use /yx:prepare on any yak that needs detailed specs or acceptance criteria
2. Use /yx:work to pick up a leaf yak and implement it
3. Continue mapping other areas if needed
Which would you like to do?
Common Mistakes
Top-Down Decomposition
yx add event logging --under sync
yx add git storage --under sync
yx add replay algorithm --under sync
Discovery Through Approach:
yx add sync
yx add write events to git ref --under sync
yx add implement log --under "write events to git ref"
Inverted Nesting
yx add setup local dev lint --under "add ci workflow"
yx add add ci workflow
yx add setup local dev lint --under "add ci workflow"
Skipping the Scope Conversation
yx add feature A --under goal
yx add feature B --under goal
yx add feature C --under goal
yx add feature D --under goal
yx add goal
yx add feature B --under goal
Writing Full Specs During Mapping
yx context new feature <<'EOF'
Goal: Implement feature X
Definition of Done:
- Criterion 1
- Criterion 2
- Criterion 3
Edge cases:
- Case A
- Case B
Implementation notes:
...15 more lines...
EOF
yx context new feature <<'EOF'
Add feature X to support use case Y.
EOF
Other Red Flags
- Adding multiple yaks without
yx ls between them (Iron Law!)
- Showing markdown structure instead of actual
yx commands
- Over-planning context before discovering blockers
- Nesting by "feels like subtask" instead of "blocks the parent"
- Exploring 3+ levels deep before adding context to parents
- Creating child yaks without agreeing scope first (scope creep!)
If you catch yourself doing these, stop and restart with approach-first.
Quick Reference
| Action | Command |
|---|
| Add goal | yx add goal name |
| Add blocker | yx add blocker --under "goal name" |
| Show map | yx ls |
| Add context | yx context yak name (uses stdin) |
| Read context | yx context --show yak name |
| Move yak under parent | yx move yak name --under "parent name" |
| Move to root | yx move yak name --to-root |
| Tag yak | yx tag yak name @needs-human |
| List tags | yx ls --tag @needs-human |
See Also
mapping-flow.dot — Visual diagram of the mapping process
/yx:prepare — Flesh out a yak with detailed specs and acceptance criteria
/yx:work — Pick up ready yaks, implement in worktrees, merge
../docs/yak-workflow.dot — High-level workflow showing when to use each skill