Graduate wayfinder to engineering; unify changesets for v1.1

Graduate `wayfinder` out of in-progress into the engineering bucket
(plugin.json, top-level + Engineering READMEs under User-invoked, docs
page, ask-matt on-ramp, disable-model-invocation).

Consolidate the 22 pending changesets into 10 coherent v1.1 entries:
one `wayfinder` (rename from decision-mapping + full reframe +
graduation), one `grilling`, one `code-review`, one `tdd`; fold the
superseded to-issues changeset into unify-to-tickets and drop its stray
`</content>` tag. Highest bump is minor → 1.0.1 becomes 1.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Pocock
2026-07-08 14:18:36 +01:00
co-authored by Claude Opus 4.8
parent d29732e49f
commit 639df6e738
29 changed files with 94 additions and 124 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"mattpocock-skills": minor
---
Rename the in-progress **`review`** skill to **`code-review`** and promote it from `in-progress/` to the `engineering/` bucket. It now ships in the plugin, is listed in the top-level and Engineering READMEs (Model-invoked), and has a human-facing docs page at `docs/engineering/code-review.md`. The `/implement` skill and docs now point at `/code-review`.
+7
View File
@@ -0,0 +1,7 @@
---
"mattpocock-skills": minor
---
Promote and harden **`code-review`**. The in-progress **`review`** skill is renamed to **`code-review`** and moved from `in-progress/` into `engineering/`: it now ships in the plugin, is listed in the top-level and Engineering READMEs (Model-invoked), and has a docs page at `docs/engineering/code-review.md`. The `/implement` skill and docs point at `/code-review`.
It also gains an always-on **Fowler smell baseline** on its Standards axis — a curated ~12 high-signal "Bad Smells in Code" (Mysterious Name, Duplicated Code, Feature Envy, Data Clumps, Primitive Obsession, Repeated Switches, Shotgun Surgery, Divergent Change, Speculative Generality, Message Chains, Middle Man, Refused Bequest) inlined into `SKILL.md` as a fixed baseline alongside whatever the repo documents, not a new third axis. Two binding rules keep it safe: a documented repo standard overrides the baseline, and every smell is reported as a judgement call, never a hard violation.
-5
View File
@@ -1,5 +0,0 @@
---
"mattpocock-skills": minor
---
Add a fourth **Task** ticket type to the **`decision-mapping`** skill. Some blockers are neither a decision, a prototype, nor research — just literal manual work that has to happen before the discussion can move forward (moving data, signing up for a third-party service, provisioning access). The agent automates it where it can, otherwise hands the human a precise checklist, and records any resulting facts later tickets depend on.
@@ -1,5 +0,0 @@
---
"mattpocock-skills": minor
---
Add a confirmation gate to **`grilling`**: the agent won't enact the plan until you confirm the shared understanding has been reached, turning the skill's existing "shared understanding" completion criterion into an explicit stop-gate. The `description` also recruits the pretrained **`grill`** leading word ("Grill the user relentlessly") to sharpen invocation, and the docs page is re-synced with the new gate behaviour.
+9
View File
@@ -0,0 +1,9 @@
---
"mattpocock-skills": minor
---
Sharpen **`grilling`** on two fronts.
**A confirmation gate.** The agent won't enact the plan until you confirm the shared understanding has been reached — turning the skill's existing "shared understanding" completion criterion into an explicit stop-gate. The `description` also recruits the pretrained **`grill`** leading word ("Grill the user relentlessly") to sharpen invocation, and the docs page is re-synced.
**Facts vs. decisions.** Grilling now splits *facts* (look them up — explore the codebase) from *decisions* (put each one to the human and wait for their answer). The old blanket line — "if a question can be answered by exploring the codebase, explore the codebase instead" — was written for the live-human case, but once another skill runs grilling inside a resolve-the-ticket frame it read as license to answer *decisions* autonomously too. Separating the two keeps a grilling agent from racing ahead and answering its own questions.
-5
View File
@@ -1,5 +0,0 @@
---
"mattpocock-skills": patch
---
Give the in-progress **`code-review`** skill an always-on Fowler smell baseline on its Standards axis. A curated ~12 high-signal "Bad Smells in Code" (Mysterious Name, Duplicated Code, Feature Envy, Data Clumps, Primitive Obsession, Repeated Switches, Shotgun Surgery, Divergent Change, Speculative Generality, Message Chains, Middle Man, Refused Bequest) are inlined into `SKILL.md` as a fixed baseline alongside whatever the repo documents — not a new third axis. Two binding rules keep it safe: a documented repo standard overrides the baseline, and every smell is reported as a judgement call, never a hard violation.
-7
View File
@@ -1,7 +0,0 @@
---
"mattpocock-skills": patch
---
Reshape the `tdd` skill into reference-only. The red → green → refactor loop is anchored by leading words the model already holds, so the step-by-step Workflow was largely restating the loop and duplicating the horizontal-slicing anti-pattern. Dropped the Workflow and per-cycle checklist; folded their one durable idea — vertical slices / tracer bullets — into the Anti-patterns section and a short Rules-of-the-loop list. Introduced **seam** as the leading word for where tests go, collapsing the old Philosophy "public interfaces" prose and the Planning "confirm interface / behaviors" handshake into one rule: test only at pre-agreed seams, confirmed with the user before any test is written.
Also dropped the refactor stage — TDD is now red → green, not red → green → refactor. Refactoring belongs to the review stage, not the implementation loop, so the refactor rule and `refactoring.md` were removed (its home is the `review` skill).
-5
View File
@@ -1,5 +0,0 @@
---
"mattpocock-skills": patch
---
Add the **tautological test** anti-pattern to the `tdd` skill. Tests whose assertion is recomputed the way the code computes it pass by construction and give zero confidence — distinct from the implementation-coupling anti-pattern already covered. Added as a peer at the same three sites: a Philosophy principle (expected values must come from an independent source of truth), a per-cycle checklist gate, and a BAD/GOOD example pair in `tests.md`.
+9
View File
@@ -0,0 +1,9 @@
---
"mattpocock-skills": patch
---
Reshape **`tdd`** into a reference-only skill and add a missing anti-pattern.
**Reference-only.** The red → green → refactor loop is anchored by leading words the model already holds, so the step-by-step Workflow was largely restating the loop. Dropped the Workflow and per-cycle checklist; folded their one durable idea — vertical slices / tracer bullets — into the Anti-patterns section and a short Rules-of-the-loop list. Introduced **seam** as the leading word for where tests go: test only at pre-agreed seams, confirmed with the user before any test is written. Also dropped the refactor stage — TDD is now red → green; refactoring belongs to the review stage, so the refactor rule and `refactoring.md` moved out (its home is `code-review`).
**Tautological tests.** Added the tautological-test anti-pattern: a test whose assertion is recomputed the way the code computes it passes by construction and gives zero confidence — distinct from the implementation-coupling anti-pattern already covered. Added as a peer at the same sites: a Philosophy principle (expected values must come from an independent source of truth), a checklist gate, and a BAD/GOOD example pair in `tests.md`.
@@ -1,5 +0,0 @@
---
"mattpocock-skills": minor
---
Sharpen how the **`to-issues`** skill records structure. The "What to build" template now adds a context pointer to where the **`/prototype`** skill's code lives, rather than inlining a snippet from it. And publishing now prefers the tracker's **native sub-issues** for parent → slice and **native blocking edges** for `Blocked by` where the tracker supports them (mechanics already live in the issue-tracker doc), keeping the `## Parent` / `## Blocked by` body sections as the fallback.
+2 -1
View File
@@ -6,5 +6,6 @@ Unify the planning skills. **`to-prd` is renamed to `to-spec`** — "spec" is no
`to-tickets` breaks a plan, spec, or conversation into a set of **tickets** — tracer-bullet vertical slices, each declaring its **blocking edges**. That one artifact reads two ways depending on the tracker `/setup-matt-pocock-skills` configured: a **local file** (`tickets.md`) writes the edges as text and you work it top-to-bottom by hand; a **real tracker** writes them as native blocking links, so any ticket whose blockers are done is on the frontier and several agents can run at once. The edges live in the ticket either way — the medium only decides whether anything acts on them in parallel.
Publishing prefers the tracker's **native sub-issues** for parent → slice and **native blocking edges** for `Blocked by` where the tracker supports them, keeping the `## Parent` / `## Blocked by` body sections as the fallback. The "What to build" template points at where a `/prototype`'s code lives rather than inlining a snippet from it.
`ask-matt`'s main flow now routes `idea → /to-spec → /to-tickets → /implement`, and there are human-facing docs pages at `docs/engineering/to-spec.md` and `docs/engineering/to-tickets.md`.
</content>
-7
View File
@@ -1,7 +0,0 @@
---
"mattpocock-skills": minor
---
Change **`wayfinder`**'s claim mechanism from a label to an assignee.
A session now **claims** a ticket by assigning it to the dev driving the map, rather than setting a `wayfinder:claimed` label. The assignee _is_ the claim — an open, unassigned ticket is unclaimed — which reads more naturally in GitHub's own UI and frees the label vocabulary to `wayfinder:<type>` alone. The *claim* leading word and its "first, before any work" rationale are unchanged; only the physical expression moved.
@@ -1,9 +0,0 @@
---
"mattpocock-skills": minor
---
Make **`wayfinder`** collaborative by moving the map off a local Markdown file and onto the repo's issue tracker.
The map is now a single `wayfinder:map` issue whose tickets are its child issues — one shared URL the whole team can watch and comment on. Blocking, claiming (`wayfinder:claimed`), and the frontier query all use native tracker semantics, so a session loads the map at low resolution (Notes + one context pointer per closed ticket + Fog prose) and zooms into individual tickets on demand, instead of loading the whole map every time.
Wayfinder stays tracker-agnostic: the per-tracker mechanics live behind a pointer in `docs/agents/issue-tracker.md`, so `setup-matt-pocock-skills` now seeds a "Wayfinding operations" section for GitHub, GitLab, and local-markdown. Absent that doc, Wayfinder defaults to local-markdown.
-11
View File
@@ -1,11 +0,0 @@
---
"mattpocock-skills": minor
---
Give **`wayfinder`** a first-class notion of **out of scope**, separate from fog.
Fog and out-of-scope were conflated under one `## Fog` map section, gated by different things: fog by *knowledge* (can't specify it yet — in scope, unripe, graduates as the frontier advances), out-of-scope by *scope* (beyond the destination — never graduates). Cramming both under "Fog" made out-of-scope work read as takeable frontier (an unblocked, unclaimed item is indistinguishable from a live ticket).
Now the map body has two plainly-named sections — **`## Not yet specified`** and **`## Out of scope`** — and the skill's prose splits to match: the **Fog of war** section teaches only the not-yet-specified bucket and keeps the two-way *fog-or-ticket* sharpness test, while a new **Out of scope** section owns the scope axis (beyond the destination, closed not graduating, returns only as a fresh effort if the destination is redrawn). Charting and working-the-map now rule a beyond-destination ticket out of scope — close it, one line in *Out of scope* — rather than leaving it on the frontier or logging it in *Decisions so far*.
The **fog of war** leading word is retained: it names the concept and drives the graduate-the-fog behavior in the prose; only the human-facing map headings go to plain language.
@@ -1,7 +0,0 @@
---
"mattpocock-skills": minor
---
Sharpen **`wayfinder`**'s top-level purpose around **destination** as the leading word: wayfinding finds the *way* to a destination, it doesn't charge at building it.
The opening now states that the destination varies per effort — a spec to hand off and iterate, a decision to lock before planning, or a change made in place like a data-structure migration — and that naming it is the first act of charting, because it shapes every ticket. The map body gains a `## Destination` field that every session orients to before choosing a ticket, and triage's first step now pins the destination before any ticket exists. The stray `goal` mentions in the description and Fog section are unified onto `destination`.
-12
View File
@@ -1,12 +0,0 @@
---
"mattpocock-skills": patch
---
Stop **`wayfinder`** grilling *itself* instead of the human, and classify ticket types by **HITL** / **AFK**.
Students reported `/wayfinder` picking a **grilling** ticket and answering its own questions rather than turning to the human. Root cause: **`grilling`** carried a line written for the live-human case — "If a question can be answered by exploring the codebase, explore the codebase instead" — which, once `wayfinder` runs grilling inside a resolve-the-ticket frame, reads as license to answer questions autonomously and race the ticket to "resolved".
Two changes:
- **`grilling`** now splits *facts* (look them up) from *decisions* (put each one to the human and wait for their answer).
- **`wayfinder`** labels every ticket type **HITL** (human in the loop — Prototype, Grilling) or **AFK** (agent alone — Research; Task is either). A HITL ticket only resolves through the live exchange, so the "wait for the human" behaviour falls out of the label instead of being spelled out per type — a grilling agent that answers its own questions has, by definition, broken HITL.
-7
View File
@@ -1,7 +0,0 @@
---
"mattpocock-skills": minor
---
Make **`wayfinder`**'s no-duplication contract explicit: the map is an **index**, not a store.
Adopting "index" as the leading word for the map's role fixes two duplication risks. The map now states up front that a decision lives in exactly one place — its ticket — so it only ever gists and links, never restates the answer (previously this rule was implied inside an HTML comment in the map-body template). And graduating fog into a ticket now clears the graduated patch from the Fog, so a suspected question can't linger in both places at once.
@@ -1,7 +0,0 @@
---
"mattpocock-skills": patch
---
Sharpen Wayfinder's blocking rule to prefer the tracker's native dependency relationship, and update the GitHub and GitLab issue-tracker templates to match.
Native blocking is essential rather than cosmetic: it renders the frontier visually in the tracker's own UI, so the human sees what's takeable at a glance without opening the map. `wayfinder`'s SKILL.md now states that preference and rationale; the GitHub template spells out the native issue-dependencies recipe (`gh api .../dependencies/blocked_by`, frontier query on `issue_dependencies_summary.blocked_by`), and the GitLab template names the native `/blocked_by` blocking link (Premium/Ultimate) with the body-convention fallback. Both keep the body fallback for trackers that lack native blocking.
@@ -1,9 +0,0 @@
---
"mattpocock-skills": patch
---
Restore **`wayfinder`**'s early exit when the frontier grilling turns up no fog.
The skill used to have a **Skipping The Decision Map** section: if the opening grilling surfaced no fog of war, there was no map to build, so it offered to skip straight to implementing. That clause was demoted to a parenthetical inside the Handoff section, then deleted as collateral when Handoff was removed — never an intentional cut.
It's back, co-located in **Chart the map** step 2 (Map the frontier), where the fog/no-fog outcome is actually determined: if breadth-first grilling surfaces no fog — the journey is small enough for one session — you don't need a map, so stop and ask the user how they'd like to proceed. The ask, rather than an auto-skip, is preserved from the original.
-7
View File
@@ -1,7 +0,0 @@
---
"mattpocock-skills": minor
---
Reframe **`wayfinder`**'s description around the work it's for: planning a huge chunk of work, more than one agent session can hold.
The description does the skill's invocation work, so it now leads with the trigger that actually reaches for Wayfinder — a big effort you need to break down — instead of the softer "chart a route through a foggy problem". The skill body and fog-of-war mechanic are unchanged.
+17
View File
@@ -0,0 +1,17 @@
---
"mattpocock-skills": minor
---
Graduate and reframe **`wayfinder`** — the skill for planning a huge chunk of work, more than one agent session can hold. It moves out of `in-progress/` into `engineering/` (plugin entry, top-level + Engineering READMEs under **User-invoked**, a docs page at `docs/engineering/wayfinder.md`, and a route in `ask-matt`), landing as a mature skill. The rename and reframe that got it there:
- **`decision-mapping` is renamed to `wayfinder`**, invoked as `/wayfinder`. "Decision map" was jargony and inaccurate — only one ticket type is actually a decision. The reframe charts a route through a foggy problem instead, giving one coherent leading-word frame — **fog of war**, **frontier**, **the map** — rather than an invented term layered on top.
- **Destination as the leading word.** Wayfinding finds the *way* to a destination; it doesn't charge at building it. Naming the destination is the first act of charting — it fixes the scope and shapes every ticket — so the map gains a `## Destination` field every session orients to, and triage pins it before any ticket exists.
- **Plan, don't do.** The map produces **decisions, not deliverables**; it's done when nothing is left to decide before someone builds the thing. An effort can override this in its Notes.
- **The map is an index, not a store.** A decision lives in exactly one place — its ticket — so the map only gists and links, never restates; graduating fog into a ticket clears the graduated patch so nothing lingers in two places.
- **Collaborative by default.** The map moves off a local Markdown file onto the repo's issue tracker: a single `wayfinder:map` issue whose tickets are its child issues — one shared URL the team can watch. Sessions load the map at low resolution and zoom into tickets on demand. Wayfinder stays tracker-agnostic (GitHub, GitLab, local-markdown) behind a pointer in `docs/agents/issue-tracker.md`, and `setup-matt-pocock-skills` seeds the "Wayfinding operations" section.
- **Claim by assignment, not a label.** A session claims a ticket by assigning it to the driving dev — the assignee *is* the claim — freeing the label vocabulary to `wayfinder:<type>` alone.
- **Native blocking.** Blocking prefers the tracker's native dependency relationship, which renders the frontier visually in the tracker's own UI so the human sees what's takeable without opening the map. GitHub and GitLab templates spell out the native recipe, with a body-convention fallback.
- **Fog vs. out of scope, split.** Two plainly-named map sections — `## Not yet specified` (in-scope fog that graduates as the frontier advances) and `## Out of scope` (work ruled beyond the destination, closed, never graduating) — so beyond-destination work no longer reads as takeable frontier.
- **A fourth `task` ticket type.** For literal manual work that blocks a decision (provisioning access, moving data, signing up for a service) — the one type that *does* rather than decides, earning its place by unblocking a decision.
- **HITL / AFK ticket classification.** Every ticket type is **HITL** (human in the loop — grilling, prototype) or **AFK** (agent alone — research; task is either). A HITL ticket only resolves through the live exchange, so "wait for the human" falls out of the label — a grilling agent that answers its own questions has, by definition, broken HITL. (This fixes students' reports of `/wayfinder` grilling *itself* instead of the human.)
- **No-fog early exit restored.** If the opening breadth-first grilling surfaces no fog, the journey is small enough for one session — so it stops and asks how you'd like to proceed rather than building a map nobody needs.
-9
View File
@@ -1,9 +0,0 @@
---
"mattpocock-skills": minor
---
Rename the **`decision-mapping`** skill to **`wayfinder`**, invoked as `/wayfinder`.
"Decision map" was jargony and inaccurate — only one of the skill's four ticket types (Grilling) is actually a decision. The reframe charts a route through a foggy problem, resolving investigation tickets one at a time until the way to the goal is clear. This makes one coherent leading-word frame (fog of war / frontier / the map) instead of mixing an invented term on top of it.
Also a pruning pass: unified `node``ticket`, bound "the frontier" to the unblocked tickets, dropped the duplicated "one question at a time" (owned by `/grilling`), and trimmed intro no-ops.