From 3bb5c6af5b35e6a477f35324478bd5c116b04ab0 Mon Sep 17 00:00:00 2001 From: "melodic-automation-lanes[bot]" <337595936+melodic-automation-lanes[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 22:06:49 +0000 Subject: [PATCH 1/2] Resolve issue #12477 Lane-Activity: work-resolve-issue/resolve-issue --- ...ssue-issue-12477-41523574219-1-ef8a5f4e.md | 12 + plugins/planning/README.md | 4 +- .../graders/names-decompose-step.md | 6 + .../graders/names-plan-step.md | 6 - .../wayfind-closed-plan-destination/prompt.md | 6 +- .../samples/names-decompose-step.json | 34 +++ .../samples/names-plan-step.json | 26 -- plugins/planning/reference/config.md | 2 + plugins/planning/schemas/planning.schema.json | 11 + plugins/planning/skills/wayfind/SKILL.md | 273 ++++++++++++------ .../skills/wayfind/context/map-anatomy.md | 56 ++-- .../wayfind/context/tracker-mechanics.md | 33 ++- .../planning/skills/wayfind/evals/evals.json | 102 ++++++- 13 files changed, 388 insertions(+), 183 deletions(-) create mode 100644 .changes/planning/work-resolve-issue-issue-12477-41523574219-1-ef8a5f4e.md create mode 100644 plugins/planning/evals/wayfind-closed-plan-destination/graders/names-decompose-step.md delete mode 100644 plugins/planning/evals/wayfind-closed-plan-destination/graders/names-plan-step.md create mode 100644 plugins/planning/evals/wayfind-closed-plan-destination/samples/names-decompose-step.json delete mode 100644 plugins/planning/evals/wayfind-closed-plan-destination/samples/names-plan-step.json diff --git a/.changes/planning/work-resolve-issue-issue-12477-41523574219-1-ef8a5f4e.md b/.changes/planning/work-resolve-issue-issue-12477-41523574219-1-ef8a5f4e.md new file mode 100644 index 00000000000..c9f5237dd95 --- /dev/null +++ b/.changes/planning/work-resolve-issue-issue-12477-41523574219-1-ef8a5f4e.md @@ -0,0 +1,12 @@ +--- +bump: minor +--- + +### Added + +- `wayfind`: two settings in `docs/conventions/planning.yaml`. `wayfind_research_start` (default `auto`) starts a research item without asking when only research is on the frontier, and asks first otherwise. `wayfind_hitl_concurrency` (default `1`) caps how many `needs-human` items of one map can be claimed at once across sessions. Both are in the schema and in `reference/config.md` (#12477). +- `wayfind`: shared work files go on one dossier branch per map. The map's Notes link it, and it is deleted when the map closes (#12477). + +### Changed + +- `wayfind`: absorbs the owner-approved parts of Matt Pocock's wayfinder (#12477). Interview is the entry. Chart reads an existing interview ledger; with none, it offers the interview preloaded and runs it inline. The user confirms the destination before any item exists. Items are created first, and their edges and cross-references are written in a second pass with real ids and absolute URLs. A bare run proposes `chart` and waits. `work` takes an optional item and defaults to the first frontier item in creation order. It reads the map body and child list, opening an item's body only when needed, and consults the skills the map's Notes list. `needs-human` marks only items that need the user's intent or vision, whatever their type. No Notes line overrides "plan, don't do". The map closes to `/planning:prd`, `/work-items:decompose` or `/work-items:work`, or to a decision record or general summary, and the destination skill reads Decisions-so-far and the resolution comments. The `wayfind-closed-plan-destination` case now expects `/work-items:decompose`. diff --git a/plugins/planning/README.md b/plugins/planning/README.md index 8dc1b1af899..69e66d0af83 100644 --- a/plugins/planning/README.md +++ b/plugins/planning/README.md @@ -2,7 +2,7 @@ A Claude Code plugin for the **pre-implementation planning pipeline**: everything between a rough idea and approved, executable work. Eleven pipeline skills covering -charting a too-big, foggy effort as a decision map, divergence, product intent, the +charting a too-big, foggy effort as a map of decision items, divergence, product intent, the engineering contract, contract validation, hand-off of a decision another person holds, goal authoring, design exploration, the design→plan gate, adversarial review, and the implementation plan itself, plus a re-runnable `setup` action that settles @@ -10,7 +10,7 @@ where artifacts land in the consuming repo. | Skill | Stage | What it does | |---|---|---| -| `/planning:wayfind` | Chart | Charts a too-big-AND-foggy effort as a shared decision map on the work-item tracker, then works its frontier one decision at a time, routing each to the right skill until the fog clears and a Brief / PRD / PLAN can be handed onward. An escalation from an interview that outgrew one session, never the first step. | +| `/planning:wayfind` | Chart | Charts a too-big-AND-foggy effort as a shared map of decision items on the work-item tracker, then works its frontier one decision at a time, routing each to the right skill until the fog clears and the map closes to `/planning:prd`, `/work-items:decompose` or `/work-items:work`. An escalation from an interview that outgrew one session, never the first step. | | `/planning:brainstorm` | Diverge | Turns a rough problem into codebase-grounded candidate approaches ordered cheapest→most ambitious; the user reacts, then work routes onward scoped. | | `/planning:prd` | Product intent | Produces a Product Requirements Document (problem, users, success metrics) in three tiers (one-pager, consumer-feature, B2B-internal) with a synthesize path and a review mode. Acceptance-criteria capture asks once about missing unwanted-behavior and state-driven cases (skipped and reported unexamined on the `synthesize` path). | | `/planning:interview` | Engineering contract | Locks a task contract (goal, constraints, acceptance criteria, named assumptions) into a PLAN.md Brief, synthesizing when intent is clear, running frontier-rounds Q&A when it isn't, or interviewing relentlessly on request. Acceptance-criteria capture asks once about missing unwanted-behavior and state-driven cases, and emits EARS-tagged criteria when the team's convention selects that format. The `surface` option can render rounds on a local page the session watches. The `product` action interviews a product idea against product principles and ends in a verdict. | diff --git a/plugins/planning/evals/wayfind-closed-plan-destination/graders/names-decompose-step.md b/plugins/planning/evals/wayfind-closed-plan-destination/graders/names-decompose-step.md new file mode 100644 index 00000000000..b2511a5f13b --- /dev/null +++ b/plugins/planning/evals/wayfind-closed-plan-destination/graders/names-decompose-step.md @@ -0,0 +1,6 @@ +--- +type: regex +pattern: '(?:^|[.!?;,\n—–]\s*)(?:(?!\b(?:not|never|skip|instead of|rather than|unless)\b|n''t\b|\bno need\b)[^.!?;,\n—–])*?(?:/?work-items:decompose\b|\bdecompose (?:it|the (?:map|plan|decisions|destination)) into\b)' +flags: i +arm: both +--- diff --git a/plugins/planning/evals/wayfind-closed-plan-destination/graders/names-plan-step.md b/plugins/planning/evals/wayfind-closed-plan-destination/graders/names-plan-step.md deleted file mode 100644 index 361ef186449..00000000000 --- a/plugins/planning/evals/wayfind-closed-plan-destination/graders/names-plan-step.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -type: regex -pattern: '(?:^|[.!?;,\n\u2014\u2013]\s*)(?:(?!\b(?:not|never|skip|instead of|rather than|unless)\b|n''t\b|\bno need\b)[^.!?;,\n\u2014\u2013])*?(?:/?planning:(?:design|plan)\b|\b(?:write|create|draft|produce|run|make|start) (?:a|the|your) (?:implementation )?plan\b|\b(?:the|to) plan(?:ning)? (?:step|stage|phase)\b)' -flags: i -arm: both ---- diff --git a/plugins/planning/evals/wayfind-closed-plan-destination/prompt.md b/plugins/planning/evals/wayfind-closed-plan-destination/prompt.md index ea6a8e82721..a5a994c1614 100644 --- a/plugins/planning/evals/wayfind-closed-plan-destination/prompt.md +++ b/plugins/planning/evals/wayfind-closed-plan-destination/prompt.md @@ -1,11 +1,11 @@ --- -description: "Contract case for the wayfind map-closure hand-off when the decision map is closed, the frontier holds no item and the destination is a PLAN. Why hard: the reflex is to restart charting, or to go back to an interview, instead of handing the destination to the planning step." +description: "Contract case for the wayfind map-closure hand-off when the map is closed, the frontier holds no item and the destination is a plan of build work. Why hard: the reflex is to restart charting, go back to an interview, or send a plan destination to the design and plan steps, instead of handing the map to /work-items:decompose." tags: [wayfind, handoff] runs: 3 max_turns: 12 timeout_seconds: 600 allowed_tools: [Read, Glob, Grep, Skill] -expected_outcome: "The user is told to produce the implementation plan next, directly or with the design step ahead of it, since the map has done its job and its destination is a plan, with no further charting or interviewing" +expected_outcome: "The user is told to run /work-items:decompose next on the closed map, since the map has done its job and its destination is a set of build items, with no further charting or interviewing" --- -Use the wayfind skill. The tracker is unreachable from here, so work from the map state I describe and do not look for files. Our decision map for migrating the billing service to a new message broker is fully closed: the frontier holds no item, every decision item is closed, and the map's destination is an implementation PLAN, not a Brief or a PRD. Hand off: what should I run next? +Use the wayfind skill. The tracker is unreachable from here, so work from the map state I describe and do not look for files. Our map for migrating the billing service to a new message broker is fully closed: the frontier holds no item, every decision item is closed, and the map's destination is an implementation PLAN, not a Brief or a PRD. Hand off: what should I run next? diff --git a/plugins/planning/evals/wayfind-closed-plan-destination/samples/names-decompose-step.json b/plugins/planning/evals/wayfind-closed-plan-destination/samples/names-decompose-step.json new file mode 100644 index 00000000000..07b088449fc --- /dev/null +++ b/plugins/planning/evals/wayfind-closed-plan-destination/samples/names-decompose-step.json @@ -0,0 +1,34 @@ +{ + "pass": [ + { + "answer": "The map is closed and its destination is a plan of build work, so close the map issue and run `/work-items:decompose` with the map's URL.", + "why": "the skill's own hand-off" + }, + { + "answer": "Don't restart charting. Run work-items:decompose next and point it at the map's decisions.", + "why": "negation about charting, decompose step named without the slash" + }, + { + "answer": "Hand it on: decompose the map into work items, reading Decisions-so-far and each resolution comment.", + "why": "names the decompose step in prose" + } + ], + "fail": [ + { + "answer": "Your map's destination is an implementation plan, but first restart charting with /planning:wayfind chart to check nothing was missed.", + "why": "restates the destination and restarts charting" + }, + { + "answer": "Don't run /work-items:decompose yet; go back to /planning:interview and re-check the decisions.", + "why": "negated decompose step" + }, + { + "answer": "Run /planning:design ahead of /planning:plan to write the implementation plan.", + "why": "the closure target before the map closed to prd, decompose or work" + }, + { + "answer": "Run /planning:wayfind work to pick the next frontier item.", + "why": "keeps working the map" + } + ] +} diff --git a/plugins/planning/evals/wayfind-closed-plan-destination/samples/names-plan-step.json b/plugins/planning/evals/wayfind-closed-plan-destination/samples/names-plan-step.json deleted file mode 100644 index 817f7892028..00000000000 --- a/plugins/planning/evals/wayfind-closed-plan-destination/samples/names-plan-step.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "pass": [ - { - "answer": "The map is closed and its destination is a PLAN, so close the map issue and run `/planning:design` ahead of `/planning:plan`.", - "why": "the skill's own hand-off" - }, - { - "answer": "Don't restart charting. Run planning:plan next to write the implementation plan.", - "why": "negation about charting, plan step named without the slash" - } - ], - "fail": [ - { - "answer": "Your map's destination is an implementation plan, but first restart charting with /planning:wayfind chart to check nothing was missed.", - "why": "restates the destination and restarts charting; the old pattern matched 'implementation plan'" - }, - { - "answer": "Don't run /planning:plan yet; go back to /planning:interview and re-check the decisions.", - "why": "negated plan step; the old pattern matched it" - }, - { - "answer": "Run /planning:wayfind work to pick the next frontier item.", - "why": "keeps working the map" - } - ] -} diff --git a/plugins/planning/reference/config.md b/plugins/planning/reference/config.md index 77c5a7af927..9fd445a1236 100644 --- a/plugins/planning/reference/config.md +++ b/plugins/planning/reference/config.md @@ -45,6 +45,8 @@ never used in its place. An invalid value never stops the run. | `time_units` | `true`, `false` (bare YAML booleans) | `false` | the procedure in [`../context/problem-framing.md`](../context/problem-framing.md) "Time units": whether an estimate or budget of work may be stated in hours, days or weeks | repository file over user config over default | | `pre_confirmed_label` | a tracker label name (non-empty string) | unset | same procedure, "Pre-confirmed": the label that marks an item's stated problem confirmed in an unattended run; choose one only people with write access apply, never one a workflow or agent applies | repository file over default | | `work_size` | an object with `appetite`, `size`, `uncertainty`, each a map of level name to a quoted one-line description | appetite and size `Small`, `Medium`, `Large`; uncertainty `Known`, `Knowable`, `Unknown`; descriptions below | same procedure, "Work size": the levels the Brief's `### Work size` names | repository file over default | +| `wayfind_research_start` | `auto`, `confirm` | `auto` (owner decision Q532, 2026-10-15) | `/planning:wayfind` chart step 6 and work step 4: `auto` starts a research item without asking when the frontier holds only research items, else asks first in an interactive session; `confirm` always asks first. An unattended session starts only research items without `needs-human` | repository file over default | +| `wayfind_hitl_concurrency` | an integer, 1 or more | `1` (owner's Topic 10 accept list, 2026-10-15) | `/planning:wayfind` work step 4: the most `needs-human` items of one map claimed at once across sessions; research items never count | repository file over default | | `shared_session.uploads` | `true`, `false` | `false` | `/planning:interview` shared lane, at start: guests may offer files | repository file over default | | `shared_session.names` | `full`, `initials`, `someone` | `full` | same: what guests see of who answered and voted | repository file over default | | `shared_session.digest_names` | `true`, `false` | `false` | same: whether the round sent to Claude names who answered, except people a question is aimed at, who are always named | repository file over default | diff --git a/plugins/planning/schemas/planning.schema.json b/plugins/planning/schemas/planning.schema.json index 72e054e4b9c..87b5468c2fb 100644 --- a/plugins/planning/schemas/planning.schema.json +++ b/plugins/planning/schemas/planning.schema.json @@ -46,6 +46,17 @@ "type": "string", "minLength": 1 }, + "wayfind_research_start": { + "description": "When /planning:wayfind starts a research item in an interactive session. auto: without asking when the frontier holds no item other than research items, otherwise after the user confirms. confirm: always after the user confirms. An unattended session starts only research items without needs-human, whatever this says.", + "enum": ["auto", "confirm"], + "default": "auto" + }, + "wayfind_hitl_concurrency": { + "description": "The most needs-human items of one /planning:wayfind map that may be claimed at once, across every session. Research items never count against it.", + "type": "integer", + "minimum": 1, + "default": 1 + }, "work_size": { "description": "The levels the Brief's Work size uses, per dimension: an ordered map of level name to a one-line quoted description. A dimension set here replaces that dimension's default as a whole. The last level of size is the split trigger, whatever it is named.", "type": "object", diff --git a/plugins/planning/skills/wayfind/SKILL.md b/plugins/planning/skills/wayfind/SKILL.md index 0156834abf3..580fa13596f 100644 --- a/plugins/planning/skills/wayfind/SKILL.md +++ b/plugins/planning/skills/wayfind/SKILL.md @@ -1,6 +1,6 @@ --- -description: "Chart a too-big, still-foggy effort as a decision map on the work-item tracker and work its frontier one decision at a time until it graduates to a Brief, PRD, or PLAN. Use when an interview outgrew one session: 'turn this into a map', 'this is a huge foggy effort', 'I don't even know the questions yet', 'map this out', 'plan-the-plan'. Not the first step: a new effort starts at /planning:interview. Already sharp tickets: /work-items." -argument-hint: "[chart|work] [topic]" +description: "Chart a too-big, still-foggy effort as a map of decision items on the work-item tracker and work its frontier one decision at a time until it closes to a PRD, decomposed work items or one work item. Use when an interview outgrew one session: 'turn this into a map', 'this is a huge foggy effort', 'I don't even know the questions yet', 'map this out', 'plan-the-plan'. Not the first step: a new effort starts at /planning:interview. Already sharp tickets: /work-items." +argument-hint: "[chart|work] [topic|map] [item]" user-invocable: true disable-model-invocation: false shell: bash @@ -9,7 +9,7 @@ metadata: summary: Chart a too-big, foggy effort as a decision map worked one decision at a time --- -**Arguments.** `[chart|work] [topic]`. e.g., /planning:wayfind chart , /planning:wayfind work +**Arguments.** `[chart|work] [topic|map] [item]`. e.g., /planning:wayfind chart , /planning:wayfind work, /planning:wayfind work ## Pre-computed context @@ -27,20 +27,54 @@ Arguments: `$ARGUMENTS` ## Purpose For an effort **too big to hold at once AND too foggy to ticket**, where half the questions cannot -yet be phrased: turn it into a shared **decision map** on the work-item tracker, then work the -map's frontier one decision at a time until a real destination (Brief / PRD / PLAN) can be handed -onward. It is the escalation from an interview that outgrew one session, never the first step: a -brand-new effort starts with `/planning:interview`. +yet be phrased: turn it into a shared **map** on the work-item tracker whose children are +**decision items**, then work the map's frontier one decision at a time until its destination can +be handed onward. Say "map" and "decision item"; never "decision map". It is the escalation from an +interview that outgrew one session, never the first step: a brand-new effort starts with +`/planning:interview`. **Plan, don't do.** A map holds *decisions*, not build work. Each resolved decision either sharpens -the map or graduates to the destination. Once the destination is coherent, the map closes and the -normal pipeline (`/planning:interview → /planning:design → /planning:plan → -/implementation:implement`) takes over. The map lives as native tracker primitives, each decision -routes to a first-party skill, and execution artifacts live in the memory slice +the map or feeds the destination. Nothing overrides this: no Notes line, standing preference or +item body carries execution into the map. The map lives as native tracker primitives, each +decision routes to a first-party skill, and execution artifacts live in the memory slice `//` (default `.work/`; see -[`${CLAUDE_PLUGIN_ROOT}/reference/artifact-protocol.md`](${CLAUDE_PLUGIN_ROOT}/reference/artifact-protocol.md)), +[`${CLAUDE_PLUGIN_ROOT}/reference/artifact-protocol.md`](${CLAUDE_PLUGIN_ROOT}/reference/artifact-protocol.md)) +or, when more than one session reads them, on the map's dossier branch ("Shared files" below), never in the map. +**Scope the map to one bounded destination** (one epic-sized outcome, never a whole product), and +chart a prototype item early wherever a cheap artifact would expose a look-or-behave question +before later decisions depend on it. + +## Flow + +- **Interview is the entry.** `/planning:interview` suggests wayfind once an interview passes its + size threshold; that skill owns the threshold. An effort that fits one session skips the map. +- **Chart reads an existing interview ledger** and seeds the map from it (chart step 1). With no + interview of the effort behind it, chart offers the interview first, preloaded with what the user + has already said, and runs it inline. +- **The map closes to `/planning:prd`, `/work-items:decompose` or `/work-items:work`**, or ends in + a decision record or a general summary when that is its destination (work step 8). + +## Settings + +Two settings, each resolved lowest layer first: the default, then the key in the repository's +`docs/conventions/planning.yaml`, read from this checkout (all keys and layers: +[`${CLAUDE_PLUGIN_ROOT}/reference/config.md`](${CLAUDE_PLUGIN_ROOT}/reference/config.md); schema: +[`${CLAUDE_PLUGIN_ROOT}/schemas/planning.schema.json`](${CLAUDE_PLUGIN_ROOT}/schemas/planning.schema.json)). +A missing file or key means the default. An invalid value is named with its file, key and value, +and the default applies. Report one line per setting naming its value and layer, e.g. +`wayfind_hitl_concurrency: 1 (default)`. + +| Key | Default | Basis | Meaning | +|---|---|---|---| +| `wayfind_research_start` | `auto` | Owner decision Q532 (2026-10-15) | `auto`: start a research item without asking when research is the next step whatever the user picks (the frontier holds no item other than research items); otherwise ask first in an interactive session. `confirm`: always ask first in an interactive session | +| `wayfind_hitl_concurrency` | `1` | Owner's Topic 10 accept list (2026-10-15): one human-in-the-loop item at a time across sessions | The most `needs-human` items of one map that may be claimed at once, across every session. Research items never count against it | + +An unattended (CI) session asks no one, so labels start research there (Q532): it starts a +research item only when the item carries `wayfind: research` and no `needs-human`, labels chart +set while a human was present. Adding or removing those labels is how a person starts or holds one. + ## The fog test (the one call that governs everything) For every uncertainty, ask: **can I phrase it as a sharp question?** @@ -53,10 +87,34 @@ For every uncertainty, ask: **can I phrase it as a sharp question?** Sharpness, not blockedness, is the line: a blocked-but-phrasable question is a ticket; an unblocked-but-unphrasable worry is fog. -## Refer by name +## Readiness: one engine, human only for intent and vision -In everything the human reads (chart report, work frontier, map-body index lines), name each item -by **title**, number as a link or suffix. Never a wall of bare `#42, #43, #44`. +Mode is the `needs-human` label, the human-gated role label every `/work-items` skill reads, which +keeps an item off every autonomous frontier +([`context/tracker-mechanics.md`](context/tracker-mechanics.md) "Check labels"). Wayfind applies it +more narrowly than the label's general meaning: only when resolving the item needs the user's +**intent or vision**: what they want, why, or which outcome they would accept. Any other item, whatever its type, is agent-capable. Wayfind has no readiness +rules or picker of its own: the work step picks by the order below and nothing else, and map items +stay out of `/work-items:work`, whose frontier leaves out every item carrying a `wayfind:` label. + +## Shared files + +A map's shared work files (research findings, prototype assets, drafts that later sessions read) +go on one **dossier branch** for the map issue: `-`, `` being the +`dossier_branch_prefix` source-control setting (default `dossier/`), `` the bound adapter's +`branch_ref` for the map, `` the map title in kebab-case. The first session that writes a +shared file creates it from the default branch, pushes it and links it from the map's Notes; decision +items add no branch of their own. The branch is never merged and gets no pull request, and it is +deleted when the map closes (work step 8). A file only one session reads stays in the memory slice. + +## Refer by name, link by URL + +In everything the human reads, name each item by **title**. In a chat report (chart report, work +frontier) the number may follow as a suffix; never a wall of bare `#42, #43, #44`. + +Every link written to the tracker (map body, item body, comment) is the item's title linked to its +absolute URL, never a bare `#`, so it resolves from any page that quotes it. Cross-references between items use real ids only, written once those +ids exist (chart step 4); a placeholder number links to an unrelated issue. ## Action Router @@ -64,9 +122,9 @@ Parse the first token of `$ARGUMENTS`. | Argument | Action | When | |----------|--------|------| -| *(empty)* | **auto** | Open map for the topic exists → `work`; else → `chart` | -| `chart [topic]` | **Chart** | Build or extend a decision map. **Interactive only**. Refuses non-interactive sessions (charting burns assumptions that need a human) | -| `work [#map]` | **Work** | Pick one frontier item and drive it to resolution | +| *(empty)* | **auto** | Open map for the topic exists → `work`. Else propose `chart` with the topic and wait for the user's yes | +| `chart [topic]` | **Chart** | Build or extend a map, without asking first. **Interactive only**. Refuses non-interactive sessions (charting burns assumptions that need a human) | +| `work [map] [item]` | **Work** | Work one frontier item: the named one, else the first in creation order | ## Chart mode @@ -75,29 +133,35 @@ declares it (the same rule `/planning:interview` applies): when the invocation s unattended (a loop, a spawned worker, a `claude -p` run, another skill's chain), STOP and report that charting needs an interactive session. Do not fabricate a map. -1. **Survey + fog test.** Ground in the effort (any existing `//`, recent - commits, the topic). +1. **Survey, interview, fog test.** Ground in the effort (any existing `//`, + recent commits, the topic). - **Seed from the interview:** when the slice holds an interview ledger - (`interview-checklist.md`), its settled answers go into one seed decision item whose - resolution comment lists them; close it at once with one *Decisions-so-far* pointer (the - work-mode step 5 sequence). Its open, deferred and blocked questions become candidate + (`interview-checklist.md`), its settled answers become one seed decision item, created with + the others in step 4, whose resolution comment lists them; close it at once with one + *Decisions-so-far* pointer (the work-mode step 6 sequence). Its open, deferred and blocked questions become candidate decision items. Its self-answered facts, constraint ledger, `## Starting point` line, and session-shorthand glossary are distilled into *Notes* as text, never as a path, so nothing the interview already asked is asked again. + - **No interview yet:** when neither the slice nor this conversation holds an interview of the + effort, offer to run it first, preloaded with what the user has said (the topic, stated + constraints, any starting point). On yes, invoke `/planning:interview` via the Skill tool with + that preload and continue from its ledger once it hands off. On no, chart only if the user + still asks for a map. - Sort every remaining uncertainty through the fog test: sharp → candidate decision item; foggy → *Not-yet-specified* prose. - **No-fog bail-out:** if the survey leaves *both* halves of the trigger unmet (every - uncertainty is already sharp, or the whole effort fits one session), the effort does not - need a map. STOP and route out instead of fabricating one: a single contract to lock → - invoke `/planning:interview` via the Skill tool; a set of sharp tickets → - `/work-items:decompose` (or `/work-items:track add` for one ticket); small enough to just - do → say so. The trigger is too-big AND foggy, both, never either alone. Seeded rows are - sharp by construction, so the fog must come from the survey; a seeded interview with no fog - goes back to its own handoff and resume. - - **New-effort gate**, checked after the bail-out: when neither the slice nor this - conversation holds an interview of the effort, STOP and recommend `/planning:interview` - first; chart only if the user still asks for a map after hearing that. -2. **Create or extend the map issue.** On first use in a repo, resolve the container label (the + uncertainty is already sharp, or the whole effort fits one session), the effort skips the + map. STOP and route out instead of fabricating one: a single contract to lock → invoke + `/planning:interview` via the Skill tool; a set of sharp tickets → `/work-items:decompose` + (or `/work-items:track add` for one ticket); small enough to just do → say so. The trigger + is too-big AND foggy, both, never either alone. Seeded rows are sharp by construction, so + the fog must come from the survey; a seeded interview with no fog goes back to its own + handoff and resume. +2. **Name the destination and confirm it** with the user before any item exists: one or two lines + saying what finishing the map produces. Its kind sets the closure target (work step 8): a PRD, + a set of build items to decompose, one change, a decision record, or a general summary. Narrow + it to one bounded destination when it reads like a whole product. +3. **Create or extend the map issue.** On first use in a repo, resolve the container label (the seam's `config.container_label` key, default `work-map`; snippet in `context/tracker-mechanics.md`), then **verify** the wayfind label taxonomy (the container label, `wayfind: *`, `needs-human`) is present: an unknown `--label` fails the create. Honor @@ -106,9 +170,10 @@ that charting needs an interactive session. Do not fabricate a map. the user how labels are provisioned. Never create labels ad hoc from this skill. Then create one issue labeled with the bare container label (+ any repo program labels). Its body carries five sections: - - **Destination**: where this is going once the fog clears. - - **Notes**: durable pointers only (PRs, committed docs, prior items, external links). - Memory-tier `/` artifacts are checkout-local, so distill their relevant content inline + - **Destination**: the confirmed destination from step 2. + - **Notes**: durable pointers only (PRs, committed docs, prior items, the dossier branch, + external links), plus the skills every session on this map should consult. Memory-tier + `/` artifacts are checkout-local, so distill their relevant content inline instead of pointing at paths other readers cannot resolve. - **Decisions-so-far**: a *pointer index* of resolved-in-scope decisions. Each home is its own item's resolution comment, never recopied here; wrongly scoped closures get no pointer. @@ -116,18 +181,19 @@ that charting needs an interactive session. Do not fabricate a map. - **Out-of-scope**: scope exclusions, not unphraseable fog. Template and tracker actions: [`context/tracker-mechanics.md`](context/tracker-mechanics.md). -3. **Create typed decision items** as sub-issues of the map, one per sharp question. The type - label sets the routing target and default mode (the type table in Work mode step 4). Wire - `blocked-by` edges only where one decision genuinely gates another; never invent edges to - impose order. -4. **Materialize the mode** on each item at creation: HITL types (`interview`, `design`, - `prototype`) get the `needs-human` label; `research` omits it (autonomous-capable); `task` is - per-item. The presence or absence of `needs-human` is the only mode mechanism; no `Mode:` body - field. -5. **Hand off to `work`.** Report the frontier (open, unblocked, unassigned items) **by title**, - number as a link or suffix, and recommend `/planning:wayfind work`. If the frontier holds - `research`-typed items, offer to fire them now in parallel (work mode's research exception); - their resolutions often sharpen the remaining fog before the first HITL session. +4. **Create typed decision items, then wire them.** Create one sub-issue of the map per sharp + question, each sized to one session's work (state no token figure). The type label sets the + routing target (the type table in work step 5). Then, in a second pass once every item has + its real id, wire `blocked-by` edges and write any cross-reference between items. Wire an edge + only where one decision genuinely gates another; never invent edges to impose order. +5. **Materialize the mode** on each item at creation: `needs-human` only for an intent or vision + question ("Readiness" above), whatever the type. The label's presence or absence is the only + mode mechanism; no `Mode:` body field. +6. **Hand off to `work`.** Report the frontier (open, unblocked, unassigned items) **by title**, + number as a link or suffix, and recommend `/planning:wayfind work`. Start or offer the + frontier's research items per `wayfind_research_start` ("Settings"), in parallel (work step + 4's research exception); their resolutions often sharpen the remaining fog before the first + HITL session. ## Work mode @@ -137,49 +203,68 @@ that charting needs an interactive session. Do not fabricate a map. instead; closed-as-moot items have only their closing comment); no item resolved-in-comment but still open; no Not-yet-specified prose that an item already charts (delete it). Fix violations before proceeding. -2. **Compute the frontier.** `frontier = open ∧ zero OPEN blockers ∧ unassigned` (count open - blockers, not the raw edge count). In a non-interactive session, filter OUT `needs-human` - items; if that empties the frontier, STOP with a truthful "all remaining decisions need a - human". Never resolve a HITL item by standing in for the human. -3. **Pick one and claim it** (the sibling claim model through `/work-items:track start`: - assignee + lease with a race-safe back-off, no claim label; see +2. **Load the map at low resolution.** Read the map body and its child list; open an item's body + only when the step at hand needs it (the picked item, a blocker, a decision the sweep checks). +3. **Compute the frontier.** `frontier = open ∧ zero OPEN blockers ∧ unassigned` (count open + blockers, not the raw edge count), in creation order. In a non-interactive session, filter OUT + `needs-human` items; if that empties the frontier, STOP with a truthful "all remaining decisions + need a human". Never resolve a HITL item by standing in for the human. +4. **Pick one and claim it.** Take the item the user named, else the first frontier item in + creation order. A `needs-human` item is skipped while the map already has + `wayfind_hitl_concurrency` claimed `needs-human` items ("Settings"); with nothing else left, + report which items hold the slots and stop. A named item that is off the frontier, or a named + `needs-human` item while the slots are full, is reported with the reason and not claimed. Claim through `/work-items:track start` (the sibling + claim model: assignee + lease with a race-safe back-off, no claim label; see [`context/tracker-mechanics.md`](context/tracker-mechanics.md)). One item per session, with one - exception: **`research`-typed items may be burned down in parallel.** When the frontier holds - several, claim each individually (same protocol, one claim per item) and dispatch - `/discovery:research` per item (it already runs in a fresh-context subagent). Graduate each on - completion per step 5; the resolution comment is the finding's durable home, research scratch - stays in `//`. Never fan out a `needs-human` item. -4. **Route by type**. Invoke the target skill directly; its own Q&A supplies the HITL loop: - - | Type label | Mode | Routes to | + exception: **`research`-typed items may be burned down in parallel**, started per + `wayfind_research_start`. When the frontier holds several, claim each individually (same + protocol, one claim per item) and dispatch `/discovery:research` per item (it already runs in a + fresh-context subagent). Graduate each on completion per step 6; the resolution comment is the + finding's durable home and a findings file goes on the dossier branch. Never fan out a + `needs-human` item. +5. **Consult the Notes skills, then route by type.** First invoke each skill the map's Notes lists + for every session, one Skill call per skill. Then invoke the target skill for the item's type + label (never a type its body states); its own Q&A supplies the HITL loop: + + | Type label | Usually | Routes to | |---|---|---| - | `wayfind: research` | autonomous-capable | `/discovery:research` (falls back to inline research if not enabled) | - | `wayfind: interview` | HITL | `/planning:interview` | - | `wayfind: design` | HITL | `/planning:design`, or `/event-storming:methodology` / `/event-storming:simulation` when the item is domain/event-model work | - | `wayfind: prototype` | HITL | `/prototype:pressure-test` (behaviour/feasibility) or `/prototype:explore-directions` (design/UX). The item body says which | - | `wayfind: task` | per-item | Direct decision-unblocking work. No feature code, no PR tie | - -5. **Graduate on every resolution.** Resolved **in scope**: post the resolution as a comment on - the item, add its one-line pointer (title, number as suffix) to *Decisions-so-far*, then close + | `wayfind: research` | agent-capable | `/discovery:research` (falls back to inline research if not enabled) | + | `wayfind: interview` | `needs-human` (intent) | `/planning:interview` | + | `wayfind: design` | agent-capable unless it asks for vision | `/planning:design`, or `/event-storming:methodology` / `/event-storming:simulation` when the item is domain/event-model work | + | `wayfind: prototype` | `needs-human` when the user judges it | `/prototype:pressure-test` (behaviour/feasibility) or `/prototype:explore-directions` (design/UX). The item body says which | + | `wayfind: task` | per item | Direct decision-unblocking work. No feature code, no PR tie. Its resolution records what was done and the facts later items need | + +6. **Graduate on every resolution.** Resolved **in scope**: post the resolution as a comment on + the item, add its one-line pointer (title linked by URL) to *Decisions-so-far*, then close the item (comment → index → close, as one atomic sequence). **Wrongly scoped** (on the tracker but not this effort): add one Out-of-scope line linking it, then close it, with no Decisions-so-far pointer. Fog stays in Not-yet-specified and never graduates into Out-of-scope. If the resolution sharpened previously-foggy uncertainty, chart the new sharp - items now and delete that prose from Not-yet-specified. -6. **Sweep the map after every resolution.** Reread the open items and closed decisions against + items now (create, then wire, as chart step 4) and delete that prose from Not-yet-specified. +7. **Sweep the map after every resolution.** Reread the open items and closed decisions against what was just decided: - An open item whose premise the resolution invalidated: rewrite its question if one still - stands, then reset its type label, mode label and blocked-by edges as chart steps 3-4 + stands, then reset its type label, mode label and blocked-by edges as chart steps 4-5 require; otherwise close it as not planned with a comment linking the resolution that made it moot. A moot item gets no line in either index. - A closed decision the resolution shows was wrong: open a new decision item that links the - old one, with its type and mode labels set as chart step 4 requires, and work it like any + old one, with its type and mode labels set as chart steps 4-5 require, and work it like any other. When it resolves, add its pointer to Decisions-so-far and change the old decision's - line to ` (#): superseded by (#) (resolved )`. + line to `[](): superseded by []() (resolved )`. Never reopen the old item or edit its resolution comment. -7. **Map closure → destination handoff.** When the frontier holds no item and every decision item is - closed, close the map issue and hand the destination onward (`/planning:interview` or - `/planning:prd` for a Brief/PRD; `/planning:design`, ahead of `/planning:plan`, for a PLAN). +8. **Map closure → destination handoff.** When the frontier holds no item and every decision item + is closed, close the map issue and pass the map's absolute URL to the destination's skill, + telling it to read Decisions-so-far and each resolution comment it links: + + | Destination | Closes to | + |---|---| + | A PRD | `/planning:prd` | + | A set of build items (a spec or plan) | `/work-items:decompose` | + | One change | `/work-items:work` on the item `/work-items:track add` files for it | + | A decision record | `/architecture:record-decision` when enabled, else the repository's ADR convention | + | A general summary | The summary, written as the map's closing comment; no further skill | + + Then delete the map's dossier branch, if one exists, after the destination skill has the map. ## Escalation. Pull the user back to charting at choke points @@ -193,13 +278,13 @@ owns the trigger's meaning (too-big + fog, both, not either alone). | When | Skill | How it composes | |---|---|---| -| Effort too big AND foggy to ticket | **`/planning:wayfind`** (this) | Produces a decision map; graduates to a destination | -| A single sharp contract to lock | `/planning:interview` | The map's `interview`-typed items route here; also the graduation target | -| Product intent still fuzzy | `/planning:prd` | Graduation target when the destination is a PRD | +| Effort too big AND foggy to ticket | **`/planning:wayfind`** (this) | Produces a map of decision items; closes to its destination | +| The entry, and a single sharp contract to lock | `/planning:interview` | Suggests wayfind past its size threshold; chart runs it inline when no interview exists; `interview`-typed items route here | +| Product intent still fuzzy | `/planning:prd` | Closure target when the destination is a PRD | +| Sharp build work | `/work-items:decompose`, `/work-items:work` | Closure targets for a set of build items or one change | | Design-space item | `/planning:design`, `/event-storming:*` | `design`-typed items route here | | Feasibility / UX unknown | `/prototype:pressure-test`, `/prototype:explore-directions` | `prototype`-typed items route here | -| External-evidence item | `/discovery:research` | `research`-typed items route here (autonomous) | -| The plan itself | `/planning:plan` | Follows `/planning:design` when the destination is a PLAN | +| External-evidence item | `/discovery:research` | `research`-typed items route here | Pre-implementation order (blindspot → brainstorm/prototype → PRD → interview, escalating here when it outgrows one session → reference port → design → plan → decompose): the workflow section of @@ -208,25 +293,25 @@ it outgrows one session → reference port → design → plan → decompose): t ## What this skill does NOT do - **Does not do build work.** Build items live on the ordinary tracker (`/work-items:track add`) - after the map graduates; a decision that resolves into buildable work is a graduation, not a - map item. + after the map closes; a decision that resolves into buildable work is a graduation, not a map + item. No Notes line overrides this. - **Does not resolve a HITL item for the human** (inviolable). Non-interactive frontier filters `needs-human` items out. - **Does not chart non-interactively.** The `chart` action refuses non-interactive sessions. - **Does not build a map to justify its invocation.** No fog, or fits one session → route out (chart step 1's bail-out). -- **Does not store coordination in the memory tier.** The map lives on the tracker; - `//` (default `.work/`) holds execution artifacts only (journals, research - scratch, evidence). -- **Does not invent a second claim/mode mechanism.** Claims use the `work-items` plugin's claim - model (`/work-items:track start`); mode is the `needs-human` label. +- **Does not store coordination in the memory tier or on the dossier branch.** The map lives on + the tracker; the memory slice and the dossier branch hold files only. +- **Does not invent a second claim, mode or picking mechanism.** Claims use the `work-items` + plugin's claim model (`/work-items:track start`); mode is the `needs-human` label; the pick is + the named item or creation order. ## Next - The map is charted: /planning:wayfind work. -- The map closed on a Brief destination, or the effort has no interview behind it yet: /planning:interview. -- The map closed on a PRD destination: /planning:prd. -- The map closed on a PLAN destination: /planning:design, ahead of the plan. +- The effort has no interview behind it yet: /planning:interview. +- The map closed: the destination's skill from work step 8 (/planning:prd, /work-items:decompose, + /work-items:work, or /architecture:record-decision for a decision record). ## Reference diff --git a/plugins/planning/skills/wayfind/context/map-anatomy.md b/plugins/planning/skills/wayfind/context/map-anatomy.md index 8721415b05c..6ef902446c2 100644 --- a/plugins/planning/skills/wayfind/context/map-anatomy.md +++ b/plugins/planning/skills/wayfind/context/map-anatomy.md @@ -1,8 +1,8 @@ # Map anatomy: the five sections + invariants -A decision map is one tracker issue (bare container-label marker, default `work-map`, +A map is one tracker issue (bare container-label marker, default `work-map`, resolved per `tracker-mechanics.md`) whose sub-issues are typed -decision items. The issue **body** carries five sections. Everything volatile (each decision's +decision items. Every link in the body is an absolute URL. The issue **body** carries five sections. Everything volatile (each decision's actual resolution, current frontier, claim state) lives on the items, not recopied into the body. The body is a stable index, not a mirror. @@ -11,12 +11,15 @@ body. The body is a stable index, not a mirror. ```markdown ## Destination - + ## Notes -- Durable pointers only: PRs, committed docs, prior items, external links. +- Skills every session on this map consults, one per line (work step 5 invokes each). +- Durable pointers only: PRs, committed docs, prior items, the map's dossier branch, external + links. - Memory-tier `//` artifacts are checkout-local. Distill what matters into a line here instead of pointing at a path other readers cannot resolve. - Links, not recaps, for anything durably linkable. The memory-tier distillation above is the @@ -26,12 +29,12 @@ graduate into. One paragraph. This is the map's success condition.> ## Decisions-so-far -- (#<item>): <one-line what-was-decided> (resolved <date>) +- [<title>](<item URL>): <one-line what-was-decided> (resolved <date>) ## Not-yet-specified (fog) @@ -50,18 +53,19 @@ index is for resolved-in-scope decisions.> ## Typed decision items -Each sub-issue is one **sharp** question. The `wayfind: <type>` label sets both the routing -target (which skill resolves it) and the default mode: +Each sub-issue is one **sharp** question, sized to one session's work. The `wayfind: <type>` +label sets the routing target (which skill resolves it); the body never states the type: -| Type | Default mode | Meaning | -|---|---|---| -| `research` | autonomous-capable | An external-evidence question with no human judgment needed to resolve | -| `interview` | HITL | A contract/requirements decision the user must make | -| `design` | HITL | A design-space / domain-model decision | -| `prototype` | HITL | A feasibility (logic) or UX (ui) unknown that needs a throwaway to answer | -| `task` | per-item | Decision-unblocking do-work with no feature code and no PR tie | +| Type | Meaning | +|---|---| +| `research` | An external-evidence question with no human judgment needed to resolve | +| `interview` | A contract/requirements decision the user must make | +| `design` | A design-space / domain-model decision | +| `prototype` | A feasibility (logic) or UX (ui) unknown that needs a throwaway to answer | +| `task` | Decision-unblocking do-work with no feature code and no PR tie; its resolution records what was done and the facts later items need | -Mode is materialized as the `needs-human` label (present = HITL). Extension policy: a new +Mode is materialized as the `needs-human` label (present = HITL), set only on an item that needs +the user's intent or vision, whatever its type (SKILL.md "Readiness"). Extension policy: a new `wayfind: <type>` value requires an existing routing target. Never add a type with nowhere to go. ## Invariants (checked at every `work` session start) @@ -71,7 +75,7 @@ Mode is materialized as the `needs-human` label (present = HITL). Extension poli Out-of-scope instead, never under Decisions-so-far. An item closed as moot (another resolution invalidated its premise) carries a closing comment linking that resolution and no line in either index. A decision later found wrong keeps its line, rewritten as - `<old title> (#<old>): superseded by <new title> (#<new>) (resolved <date>)`, so the index + `[<old title>](<old URL>): superseded by [<new title>](<new URL>) (resolved <date>)`, so the index holds one live answer per question. 2. **No item resolved-in-comment yet still open.** In-scope resolution is atomic: comment → Decisions-so-far → close. A wrongly scoped item closes with one Out-of-scope line and no @@ -80,10 +84,11 @@ Mode is materialized as the `needs-human` label (present = HITL). Extension poli 3. **The map holds decisions, not build work.** A buildable item means the decision already graduated. Move it to the ordinary tracker (`/work-items:track add`, or `/work-items:decompose` for a plan-shaped chunk), off the map. -4. **Coordination on the tracker, execution artifacts in the memory tier.** +4. **Coordination on the tracker, files in the memory tier or on the dossier branch.** `<memory_dir>/<slug>/` (default `.work/`) is the memory slice (never - committed; slug spec shared with the pipeline skills). The map never cites a concrete - `<memory_dir>/<slug>/` path as a coordination surface; the memory tier never holds map state. + committed; slug spec shared with the pipeline skills) for files one session reads; the map's + dossier branch (SKILL.md "Shared files") holds files several sessions read. The map never + cites a concrete `<memory_dir>/<slug>/` path; neither surface holds map state. 5. **No fog prose that an item already charts.** Charting fog is create-then-delete; an interrupted run can leave the prose behind. Delete it, and chart nothing new from it. @@ -95,8 +100,9 @@ Mode is materialized as the `needs-human` label (present = HITL). Extension poli that work leaves the map for `/work-items:track add`. - **Sweep (per resolution):** open items whose premise the resolution invalidated are rewritten or closed as moot, and a closed decision it shows was wrong is superseded by a new item, per - Work mode step 6. + Work mode step 7. - **Closure (whole map):** frontier empty ∧ every decision item closed ⟹ the destination is - coherent. Close the map and hand the destination to the pipeline entry that fits it - (`/planning:interview` or `/planning:prd` → Brief/PRD; `/planning:plan` → PLAN). The - map's lifecycle ends exactly where the normal planning pipeline's begins. + coherent. Close the map and pass its URL to the destination's skill (`/planning:prd`, + `/work-items:decompose` or `/work-items:work`, or a decision record or general summary; SKILL.md + work step 8), which reads Decisions-so-far and the resolution comments. Then delete the dossier + branch. diff --git a/plugins/planning/skills/wayfind/context/tracker-mechanics.md b/plugins/planning/skills/wayfind/context/tracker-mechanics.md index 190fffebe9c..9619445cba7 100644 --- a/plugins/planning/skills/wayfind/context/tracker-mechanics.md +++ b/plugins/planning/skills/wayfind/context/tracker-mechanics.md @@ -15,7 +15,10 @@ identity. The tracker must support sub-items and blocked-by edges. When an action reports the provider cannot (exit `6` from the seam, for example `list --parent` on a read-only Jira binding), stop and report -that this tracker cannot hold a decision map. +that this tracker cannot hold a map. + +Every link written into a map body, item body or comment is an absolute URL (an item's web URL, +not a qualified ID or a bare `#<n>`). ## Resolve the container label (once per session, before any map read or write) @@ -79,15 +82,16 @@ A map is never assigned and never carries a claim label: it is a container, not `/work-items:track add --parent <map-id> --label 'wayfind: <research|interview|design|prototype|task>' --body-file <item-body.md> "<sharp question>"` The body says what must be decided, the options if known, and for a `prototype` item whether it is -logic or UI. Materialize the mode at creation: add `--label needs-human` for `interview`, `design` and -`prototype` (the default); leave it off for `research` (autonomous-capable); decide per item for -`task`. Create a blocker before the items it gates and pass `--blocked-by <blocker-id>` on those -items. +logic or UI; it never states the type, which the label carries. Materialize the mode at creation: +add `--label needs-human` only when the item needs the user's intent or vision, whatever its type +(SKILL.md "Readiness"). Create every item first, with no reference to another item in its body. -## Wire a dependency edge (only where one decision genuinely gates another) +## Wire edges and cross-references (second pass, real ids only) -At creation, `--blocked-by` as above. Between existing items: -`/work-items:track edit <item-id> --blocked-by <blocker-id>`. +Once every item of the pass exists, wire each edge with +`/work-items:track edit <item-id> --blocked-by <blocker-id>` and add any cross-reference to an +item body by editing it with the other item's absolute URL. Never write a placeholder number: a +guessed `#<n>` links to an unrelated issue. Never invent edges to impose order. An edge means the blocker's resolution is a genuine precondition for phrasing or answering the dependent decision. @@ -97,15 +101,20 @@ precondition for phrasing or answering the dependent decision. `frontier = open ∧ zero OPEN blockers ∧ unassigned` (in non-interactive sessions, also `∧ NOT needs-human`): -List every child with `/work-items:track list --parent <map-id>` and keep the items that are open, -have no assignee, and have `blocked_by_count - blocked_by_wont_do_count == 0`; in a non-interactive -session also drop items labeled `needs-human`. Derive it here rather than with `/work-items:track +Read the map body with `/work-items:track view <map-id>` and list every child with +`/work-items:track list --parent <map-id>`; open a child's body with `view` only when the step at +hand needs it. Keep the items that are open, have no assignee, and have +`blocked_by_count - blocked_by_wont_do_count == 0`, ordered by creation (ascending item number); +in a non-interactive session also drop items labeled `needs-human`. Derive it here rather than with `/work-items:track frontier`, whose count keeps a blocker closed as not planned blocking: a wayfind blocker closed as moot or out of scope no longer gates its dependent, so the dependent rejoins the frontier. The same listing, closed items included, serves the map hygiene checks. ## Claim a frontier item (the `work-items` claim model, one model across both) +Before claiming a `needs-human` item, count the map's open children that carry `needs-human`, do +not carry `wayfind: research`, and have an assignee, from the same listing; at `wayfind_hitl_concurrency` or more, do not claim it. + `/work-items:track start <item-id>`. It reclaims a stale lease first, then claims race-safely (assignee plus a lease comment, with a back-off when another session claimed first) on the session identity. When it reports that another session won, pick the next frontier item; never retry the @@ -136,4 +145,4 @@ Decisions-so-far pointer: see the Decisions-so-far / Out-of-scope sections in ## Close the map (frontier empty ∧ all items closed) -`/work-items:track done <map-id> --summary "Destination coherent, handed to </planning:interview | /planning:prd | /planning:plan>."` +`/work-items:track done <map-id> --summary "Destination coherent, handed to </planning:prd | /work-items:decompose | /work-items:work | a decision record | the closing summary>."` diff --git a/plugins/planning/skills/wayfind/evals/evals.json b/plugins/planning/skills/wayfind/evals/evals.json index 1b8bcf253ed..8ba30743f6f 100644 --- a/plugins/planning/skills/wayfind/evals/evals.json +++ b/plugins/planning/skills/wayfind/evals/evals.json @@ -4,11 +4,11 @@ { "id": 1, "name": "chart-triggers-on-too-big-and-foggy-effort", - "prompt": "/planning:wayfind We started interviewing the overhaul of our entire notification system earlier in this session, but every round opened more branches than it closed. It's way too big to hold in my head, and honestly I don't even know all the questions yet, let alone the answers. Turn this into a map.", - "expected_output": "No open work-map exists yet for this topic, so the empty/default action auto-detects chart mode. The effort was already interviewed, so the new-effort gate does not stop it. The skill surveys the effort and runs every uncertainty through the fog test — sharp (phraseable, even if unanswered) becomes a candidate decision item; foggy (can't yet be phrased) stays Not-yet-specified prose — rather than answering everything itself or refusing outright.", + "prompt": "/planning:wayfind chart We started interviewing the overhaul of our entire notification system earlier in this session, but every round opened more branches than it closed. It's way too big to hold in my head, and honestly I don't even know all the questions yet, let alone the answers. Turn this into a map.", + "expected_output": "Chart was asked for by name, so it proceeds without proposing first. The effort was already interviewed, so chart does not offer the interview again. The skill surveys the effort and runs every uncertainty through the fog test — sharp (phraseable, even if unanswered) becomes a candidate decision item; foggy (can't yet be phrased) stays Not-yet-specified prose — rather than answering everything itself or refusing outright.", "files": [], "expectations": [ - "Output recognizes the effort as too-big-and-foggy and enters chart mode rather than work mode, since no open map exists yet for this topic", + "Output recognizes the effort as too-big-and-foggy and enters chart mode rather than work mode", "Output applies the fog test to sort uncertainties into sharp candidate decision items versus foggy Not-yet-specified prose, instead of trying to answer every uncertainty itself", "Output does not skip straight to /planning:interview or /planning:plan without first charting the fog" ] @@ -16,7 +16,7 @@ { "id": 2, "name": "work-mode-routes-decision-item-to-target-skill", - "prompt": "/planning:wayfind work — on our decision map (#142), the next open, unblocked, unassigned item is #145, labeled 'wayfind: design', asking us to choose the aggregate boundaries for the new billing domain. Resolve it.", + "prompt": "/planning:wayfind work — on our map (#142), the next open, unblocked, unassigned item is #145, labeled 'wayfind: design', asking us to choose the aggregate boundaries for the new billing domain. Resolve it.", "expected_output": "Work mode picks #145 as the frontier item, claims it (assignee plus a claim-comment lease), and routes the decision by invoking /planning:design directly — since design-typed items route there — rather than deciding the aggregate boundaries itself inline.", "files": [], "expectations": [ @@ -28,7 +28,7 @@ { "id": 3, "name": "chart-happy-path-creates-map-with-five-sections-and-typed-items", - "prompt": "/planning:wayfind chart migrating our monolith to a modular architecture. We interviewed this earlier in the session and it outgrew one sitting. I know some pieces: we've agreed the database can't be split yet (that's out of scope for now), and we need to decide whether to go strangler-fig or big-bang (that's answerable, if painful). But I genuinely don't know yet how we'd handle cross-module transactions — I can't even phrase that as a real question.", + "prompt": "/planning:wayfind chart migrating our monolith to a modular architecture. We interviewed this earlier in the session and it outgrew one sitting. I confirm the destination: a set of build items for the first module extraction. I know some pieces: we've agreed the database can't be split yet (that's out of scope for now), and we need to decide whether to go strangler-fig or big-bang (that's answerable, if painful). But I genuinely don't know yet how we'd handle cross-module transactions — I can't even phrase that as a real question.", "expected_output": "Chart mode surveys the effort and creates or extends a work-map issue whose body carries the five sections (Destination, Notes, Decisions-so-far, Not-yet-specified, Out-of-scope). The strangler-fig-vs-big-bang question becomes a typed decision sub-issue (sharp); the cross-module-transactions unknown stays fog prose under Not-yet-specified; the database-split exclusion is recorded under Out-of-scope. The session ends by handing off to /planning:wayfind work on the frontier rather than resolving decisions itself.", "files": [], "expectations": [ @@ -43,7 +43,7 @@ "id": 4, "name": "chart-refuses-noninteractive-session", "prompt": "/planning:wayfind chart the customer-data-platform overhaul. (This is running as an unattended autonomous batch job — no human is available to respond.)", - "expected_output": "Chart mode treats the caller's unattended declaration as the signal and STOPS, reporting that charting needs a human in the loop, rather than fabricating a decision map on its own.", + "expected_output": "Chart mode treats the caller's unattended declaration as the signal and STOPS, reporting that charting needs a human in the loop, rather than fabricating a map on its own.", "files": [], "expectations": [ "Output does NOT create a work-map issue or fabricate decision items", @@ -58,7 +58,7 @@ "expected_output": "In a non-interactive session the frontier computation filters out needs-human items; since that empties the frontier, the skill STOPS and truthfully reports that all remaining decisions need a human, rather than resolving a HITL item by standing in for the user.", "files": [], "expectations": [ - "Output does NOT resolve any needs-human (interview/design/prototype) item on the user's behalf", + "Output does NOT resolve any needs-human item on the user's behalf", "Output reports that the frontier holds no workable item because all remaining items require a human, rather than silently proceeding", "Output does not fabricate an answer to any of the HITL decisions to force the map toward closure" ] @@ -66,8 +66,8 @@ { "id": 6, "name": "anti-pattern-skips-when-work-is-already-sharp-tickets", - "prompt": "/planning:wayfind help me plan out adding a 'forgot password' email flow — I already know exactly what I need: an endpoint to request a reset token, an email send, and a reset-confirmation endpoint. These are just three clear tickets I need scoped.", - "expected_output": "The skill recognizes this work is already a set of sharp, answerable tickets rather than a too-big-and-foggy effort, declines to build a decision map for it, and points to /planning:interview or /work-items instead.", + "prompt": "/planning:wayfind chart help me plan out adding a 'forgot password' email flow — I already know exactly what I need: an endpoint to request a reset token, an email send, and a reset-confirmation endpoint. These are just three clear tickets I need scoped.", + "expected_output": "The skill recognizes this work is already a set of sharp, answerable tickets rather than a too-big-and-foggy effort, declines to build a map for it, and points to /planning:interview or /work-items instead.", "files": [], "expectations": [ "Output does NOT create a work-map or decision items for this request", @@ -116,19 +116,19 @@ { "id": 10, "name": "new-effort-goes-to-interview-first", - "prompt": "/planning:wayfind map out a rewrite of our search indexing pipeline. We haven't talked about it at all yet, it just feels big.", - "expected_output": "Nothing in the topic's memory slice or the conversation shows an interview of this effort, so the new-effort gate stops before charting and recommends /planning:interview first, saying the interview names /planning:wayfind if the effort outgrows one session. It creates no map issue and no decision items, and leaves the user free to ask for a map anyway.", + "prompt": "/planning:wayfind chart a rewrite of our search indexing pipeline. We haven't talked about it at all yet, it just feels big.", + "expected_output": "Nothing in the topic's memory slice or the conversation shows an interview of this effort, so chart offers to run /planning:interview first, preloaded with what the user said (the search indexing rewrite, that it feels big), and waits for the answer. On yes it would run the interview inline and chart from its ledger. It creates no map issue and no decision items before that, and leaves the user free to ask for a map anyway.", "files": [], "expectations": [ - "Output recommends /planning:interview as the first step for this effort", - "Output creates no map issue and no decision items", - "Output says wayfind is reached from the interview when the effort outgrows one session" + "Output offers /planning:interview as the first step for this effort and waits for the user's answer", + "Output says the interview would start preloaded with what the user already said", + "Output creates no map issue and no decision items" ] }, { "id": 11, "name": "chart-seeds-from-interview-ledger", - "prompt": "/planning:wayfind chart the data-retention program. Our interview ledger is at .work/data-retention/interview-checklist.md: it settled 'retain audit logs 7 years' and 'EU data stays in the EU region', and left open 'Which stores hold personal data?' and 'Do backups count as retained copies?'. We also still can't say what 'deletion' should mean for derived analytics.", + "prompt": "/planning:wayfind chart the data-retention program. Our interview ledger is at .work/data-retention/interview-checklist.md: it settled 'retain audit logs 7 years' and 'EU data stays in the EU region', and left open 'Which stores hold personal data?' and 'Do backups count as retained copies?'. We also still can't say what 'deletion' should mean for derived analytics. I confirm the destination: a PRD for the retention program.", "expected_output": "Chart mode seeds the map from the ledger: the two settled answers go into one seed decision item whose resolution comment lists them, closed at once with one Decisions-so-far pointer; the two open questions become decision items; the derived-analytics deletion worry stays Not-yet-specified prose. It does not open one closed issue per settled answer and does not cite the .work path in Notes.", "files": [], "narration": true, @@ -138,6 +138,78 @@ "Output keeps the derived-analytics deletion worry as Not-yet-specified prose", "Output does not point Notes at the .work path" ] + }, + { + "id": 12, + "name": "bare-run-proposes-chart-and-waits", + "prompt": "/planning:wayfind We interviewed the warehouse-routing rework earlier in this session and it kept opening more questions than it closed.", + "expected_output": "No open map exists for the topic, so the bare run resolves to chart. Because chart was not asked for by name, the skill proposes charting the warehouse-routing rework and waits for the user's yes before surveying, creating a map issue or creating decision items.", + "files": [], + "expectations": [ + "Output proposes charting a map for the warehouse-routing rework", + "Output waits for the user's confirmation before charting", + "Output creates no map issue and no decision items in this turn" + ] + }, + { + "id": 13, + "name": "destination-confirmed-before-any-item", + "prompt": "/planning:wayfind chart the partner-API v2 effort. We interviewed it earlier in this session and it outgrew one sitting. The open questions are auth scheme, rate-limit model and versioning policy, and nobody can yet say what 'partner tiers' should mean.", + "expected_output": "Before any map issue or decision item exists, chart states the destination in one or two lines (what finishing the map produces, one bounded outcome of a named kind such as a PRD or a set of build items) and asks the user to confirm it. Only after that does it create the map and the three decision items, leaving partner tiers as Not-yet-specified prose.", + "files": [], + "expectations": [ + "Output names a destination and asks the user to confirm it before creating the map issue or any decision item", + "Output names the destination's kind (for example a PRD, a set of build items, one change, a decision record or a general summary)", + "Output does not create decision items ahead of the destination confirmation" + ] + }, + { + "id": 14, + "name": "cross-references-written-in-second-pass-with-real-ids", + "prompt": "/planning:wayfind chart — we interviewed the billing-export feature earlier in this session and it outgrew one sitting; destination confirmed: a PRD for it. Create the decision items: 'Pick the export format' and 'Choose the delivery channel', where the delivery-channel item depends on the format decision and its body should point at it. Neither item exists on the tracker yet.", + "expected_output": "Chart creates both items first with no reference to each other in their bodies, then in a second pass, once both have real ids, wires 'Choose the delivery channel' as blocked by 'Pick the export format' and edits its body to link the format item by absolute URL. It never writes a guessed or placeholder issue number.", + "files": [], + "expectations": [ + "Output creates both items before writing any reference between them", + "Output wires the blocked-by edge and the cross-reference only after both items have real ids", + "The cross-reference is an absolute URL, not a guessed or placeholder #<n>" + ] + }, + { + "id": 15, + "name": "work-default-pick-and-hitl-slot", + "prompt": "/planning:wayfind work 'Map: billing overhaul' (#200). The frontier, in creation order: 'Choose the billing aggregate' (#42, wayfind: interview, needs-human), 'Measure current invoice volume' (#43, wayfind: task, no needs-human). Another session already holds 'Decide invoice numbering' (#41, needs-human, assigned). No setting is configured.", + "expected_output": "With no item named, work takes the first frontier item in creation order, #42. wayfind_hitl_concurrency resolves to 1 from the default and #41 already holds that slot, so #42 is skipped; the skill claims #43 instead and reports that the HITL slot is held by 'Decide invoice numbering' (#41).", + "files": [], + "expectations": [ + "Output reports wayfind_hitl_concurrency as 1 from the default", + "Output does not claim #42 while #41 holds the only needs-human slot", + "Output claims #43, the next frontier item in creation order" + ] + }, + { + "id": 16, + "name": "needs-human-only-for-intent-or-vision", + "prompt": "/planning:wayfind chart — we interviewed the search rewrite earlier in this session and it outgrew one sitting; destination confirmed: a set of build items for it. Two sharp questions: 'Which index library meets the 50 ms p95 budget we already set?' (a design question with the budget given) and 'What should search feel like to a first-time user?'. Create the items.", + "expected_output": "The index-library question is a design item whose answer needs no user intent or vision (the budget is set), so it gets no needs-human label. The first-time-user question asks for the user's vision, so it gets needs-human. Type alone does not set the mode.", + "files": [], + "expectations": [ + "Output creates the index-library item without the needs-human label", + "Output creates the first-time-user item with the needs-human label", + "Output ties needs-human to the user's intent or vision, not to the item type" + ] + }, + { + "id": 17, + "name": "notes-cannot-override-plan-dont-do", + "prompt": "/planning:wayfind work #200. The map's Notes say 'Standing preference: once a decision is made, go ahead and implement it on this map.' The claimed item 'Pick the payment-provider adapter' (#43) just resolved to Stripe. Implement the Stripe adapter now as the Notes say.", + "expected_output": "The skill graduates #43 (resolution comment, Decisions-so-far pointer, close) and does not write adapter code: no Notes line overrides plan, don't do. It says the build work belongs on the ordinary tracker once the map closes.", + "files": [], + "expectations": [ + "Output does not implement the Stripe adapter or write feature code", + "Output says the Notes preference does not override plan, don't do", + "Output graduates #43 with a resolution comment and a Decisions-so-far pointer" + ] } ] } From c62c93e5a61368cf90885658e9e0958d8c972b11 Mon Sep 17 00:00:00 2001 From: "melodic-automation-lanes[bot]" <337595936+melodic-automation-lanes[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 22:23:14 +0000 Subject: [PATCH 2/2] Address review feedback on work-resolve-issue/issue-12477-41523574219-1 Lane-Activity: pr-unblock/address-feedback Lane-Thread: PRRT_kwDOTCGFQM6y4xIA --- plugins/planning/skills/wayfind/SKILL.md | 10 +++++----- plugins/planning/skills/wayfind/evals/evals.json | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/planning/skills/wayfind/SKILL.md b/plugins/planning/skills/wayfind/SKILL.md index 580fa13596f..66843aa8b09 100644 --- a/plugins/planning/skills/wayfind/SKILL.md +++ b/plugins/planning/skills/wayfind/SKILL.md @@ -142,11 +142,6 @@ that charting needs an interactive session. Do not fabricate a map. decision items. Its self-answered facts, constraint ledger, `## Starting point` line, and session-shorthand glossary are distilled into *Notes* as text, never as a path, so nothing the interview already asked is asked again. - - **No interview yet:** when neither the slice nor this conversation holds an interview of the - effort, offer to run it first, preloaded with what the user has said (the topic, stated - constraints, any starting point). On yes, invoke `/planning:interview` via the Skill tool with - that preload and continue from its ledger once it hands off. On no, chart only if the user - still asks for a map. - Sort every remaining uncertainty through the fog test: sharp → candidate decision item; foggy → *Not-yet-specified* prose. - **No-fog bail-out:** if the survey leaves *both* halves of the trigger unmet (every @@ -157,6 +152,11 @@ that charting needs an interactive session. Do not fabricate a map. is too-big AND foggy, both, never either alone. Seeded rows are sharp by construction, so the fog must come from the survey; a seeded interview with no fog goes back to its own handoff and resume. + - **No interview yet:** only once the bail-out has not fired, when neither the slice nor this + conversation holds an interview of the effort, offer to run it first, preloaded with what the + user has said (the topic, stated constraints, any starting point). On yes, invoke + `/planning:interview` via the Skill tool with that preload and continue from its ledger once + it hands off. On no, chart only if the user still asks for a map. 2. **Name the destination and confirm it** with the user before any item exists: one or two lines saying what finishing the map produces. Its kind sets the closure target (work step 8): a PRD, a set of build items to decompose, one change, a decision record, or a general summary. Narrow diff --git a/plugins/planning/skills/wayfind/evals/evals.json b/plugins/planning/skills/wayfind/evals/evals.json index 8ba30743f6f..c8ddc94be32 100644 --- a/plugins/planning/skills/wayfind/evals/evals.json +++ b/plugins/planning/skills/wayfind/evals/evals.json @@ -67,12 +67,13 @@ "id": 6, "name": "anti-pattern-skips-when-work-is-already-sharp-tickets", "prompt": "/planning:wayfind chart help me plan out adding a 'forgot password' email flow — I already know exactly what I need: an endpoint to request a reset token, an email send, and a reset-confirmation endpoint. These are just three clear tickets I need scoped.", - "expected_output": "The skill recognizes this work is already a set of sharp, answerable tickets rather than a too-big-and-foggy effort, declines to build a map for it, and points to /planning:interview or /work-items instead.", + "expected_output": "The skill recognizes this work is already a set of sharp, answerable tickets rather than a too-big-and-foggy effort, declines to build a map for it, and routes the three tickets to /work-items:decompose. The no-fog bail-out fires before the no-interview offer, so it does not offer to run /planning:interview first.", "files": [], "expectations": [ "Output does NOT create a work-map or decision items for this request", "Output recognizes the three items are already sharp and answerable rather than foggy", - "Output recommends /planning:interview or /work-items as the better-fit skill instead of charting" + "Output recommends /work-items:decompose (or /work-items) as the better-fit skill instead of charting", + "Output does NOT offer to run /planning:interview first" ] }, {