mirror of
https://github.com/mattpocock/skills.git
synced 2026-07-29 02:52:42 +07:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80e9dcc685 | ||
|
|
e81f97660a |
@@ -1,81 +0,0 @@
|
|||||||
# Writing docs pages
|
|
||||||
|
|
||||||
Every promoted skill (`engineering/`, `productivity/`, `misc/`) has a human-facing **docs page** at `docs/<bucket>/<skill-name>.md` — the docs tree mirrors the bucket folders under `skills/`. It is published at `https://aihero.dev/skills-<skill-name>`; the URL is always `skills-<skill-name>` regardless of bucket, so the docs path is repo organisation only. The page is not the skill and not a copy of `SKILL.md`.
|
|
||||||
|
|
||||||
Most of these skills are **user-invoked**: the agent will never fire them for you, so *you* are the index that has to remember they exist and when to reach for them. That memory is **cognitive load**. The job of a docs page is to relieve it — to orient one reader around one skill so they can hold it in their head, know when to reach for it, and see where it sits in the system. The pages are collectively a distributed router; each is a node.
|
|
||||||
|
|
||||||
Act whenever a promoted skill is added, renamed, or has its behaviour changed: create or re-sync its docs page. A rename moves the file too (`docs/<bucket>/<old>.md` → `docs/<bucket>/<new>.md`), because the published URL tracks the name; a skill that moves buckets moves its docs file to the matching folder. Skills in `personal/`, `in-progress/`, and `deprecated/` get no page, mirroring the README rule.
|
|
||||||
|
|
||||||
Because these pages are published on `aihero.dev`, **every link is absolute** — never a repo-relative path. A link to another skill points at `https://aihero.dev/skills-<name>`; a link into the repo points at its full `https://github.com/mattpocock/skills/...` URL. A relative link that works in the repo breaks once published.
|
|
||||||
|
|
||||||
There is no H1 — the published page takes its title from the slug.
|
|
||||||
|
|
||||||
## Page structure
|
|
||||||
|
|
||||||
Fill the template below. The **fixed frame** (Quickstart block, source link, `## What it does`, `## When to reach for it`, `## Where it fits`) appears on every page. The **adaptable middle** — `## Prerequisites` and the free-form substance sections — carries only what this particular skill earns; delete the rest.
|
|
||||||
|
|
||||||
<page-template>
|
|
||||||
|
|
||||||
Quickstart:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx skills add mattpocock/skills --skill=<name>
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx skills update <name>
|
|
||||||
```
|
|
||||||
|
|
||||||
[Source](https://github.com/mattpocock/skills/tree/main/skills/<bucket>/<name>)
|
|
||||||
|
|
||||||
## What it does
|
|
||||||
|
|
||||||
One or two plain-language paragraphs. Lead with the skill's one-sentence job, then state the **load-bearing constraint** — the single fact that makes this skill behave differently from the obvious default (for `to-prd`: it does not interview the user again, it synthesises what is already known). This line is the most valuable on the page; never omit it.
|
|
||||||
|
|
||||||
## When to reach for it
|
|
||||||
|
|
||||||
How and when you reach for the skill — two beats, both effectively always present:
|
|
||||||
|
|
||||||
- **Invocation mode.** State whether you type it or the agent fires it. A user-invoked skill: "You invoke this by typing `/<name>` — the agent won't reach for it on its own." A model-invoked skill: "Type `/<name>`, or the agent reaches for it automatically when a task fits."
|
|
||||||
- **Trigger boundary.** The index entry: "reach for this when …". Where the skill is confusable with a sibling, add the other half — "for <X> instead, use [<sibling>](https://aihero.dev/skills-<sibling>)."
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Optional — include only when the skill needs something in place to be functional; omit the heading entirely otherwise. Covers: a **workspace it writes into** (a stateful skill like `grill-with-docs` writes `CONTEXT.md` and ADRs; `teach` builds a whole directory — say what it writes and where), **prior setup** (`triage`/`to-prd`/`to-issues` need `setup-matt-pocock-skills` to have configured an issue tracker), or **repo-specific tooling**. A stateless skill that runs anywhere has no prerequisites — drop the section.
|
|
||||||
|
|
||||||
## <free-form middle>
|
|
||||||
|
|
||||||
One to three short sections, in the skill's *own vocabulary*, that make it click — choose whatever headings fit the skill: the loop it runs, the artifact it produces, the fork it makes, the one anti-pattern it kills. There is no prescribed heading; the skills are too heterogeneous for one.
|
|
||||||
|
|
||||||
The single non-negotiable: **surface the skill's leading word / load-bearing idea** — `tight` feedback loop, `deep module`, throwaway-code-answers-a-question, red-green. It pays off twice: the reader learns what the skill *is*, and learns the word they'll later think with to *reach for* it.
|
|
||||||
|
|
||||||
## It's working if
|
|
||||||
|
|
||||||
Optional. A short, checkable list of the observable signals that tell the reader the skill is actually doing its job — what they should see when it fires, and by absence when it hasn't. Include it when a skill has crisp tells (e.g. `to-prd` writes without re-interviewing you; a leading word reappearing in the trace); omit the heading when the signals are vague. A few bullets, no more.
|
|
||||||
|
|
||||||
## Where it fits
|
|
||||||
|
|
||||||
Always present. Situate the skill in the system in a sentence or two:
|
|
||||||
|
|
||||||
- **Role.** Name it: a **chain step** (`grill-with-docs → to-prd → to-issues → tdd`), a **run-once setup** (`setup-matt-pocock-skills`), **periodic maintenance** (`improve-codebase-architecture`, "every few days"), or a **reach-for-it-anytime standalone** (`diagnosing-bugs`, `prototype`, `handoff`). A standalone's map is one honest sentence — far better than omitting the section.
|
|
||||||
- **Neighbours.** The one or two siblings that matter, each with a because-clause, linked absolutely.
|
|
||||||
- **The map.** Point to [ask-matt](https://aihero.dev/skills-ask-matt), the router over the whole set, so this page stays a node and never has to redraw the graph.
|
|
||||||
|
|
||||||
</page-template>
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- Explain the **why**, not the process. The page orients and situates the skill; it never reproduces the `SKILL.md` steps or template dumps — a human choosing a tool does not need the runbook.
|
|
||||||
- Use the skill's **leading words** (_seam_, _deep module_, _tracer bullet_) so the page and the skill speak one language.
|
|
||||||
- Keep the page itself low-load. It is documentation *about* low-cognitive-load skills; furniture (spare headings, restated links) is the thing it is arguing against.
|
|
||||||
|
|
||||||
## Done when
|
|
||||||
|
|
||||||
- The page exists at `docs/<bucket>/<name>.md`, and no stale page survives a rename or bucket move.
|
|
||||||
- The Quickstart block and source link name the correct bucket and skill; the update line names the skill.
|
|
||||||
- `## What it does` states the load-bearing constraint.
|
|
||||||
- `## When to reach for it` states invocation mode and the trigger boundary.
|
|
||||||
- `## Where it fits` names the role and links to `ask-matt`.
|
|
||||||
- A prerequisite (workspace, prior setup, tooling) is stated where one exists, and the section is absent where none does.
|
|
||||||
- The middle surfaces the leading word.
|
|
||||||
- Every link is absolute, and every one resolves.
|
|
||||||
@@ -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": patch
|
|
||||||
---
|
|
||||||
|
|
||||||
Give the in-progress **`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.
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"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).
|
||||||
@@ -13,8 +13,4 @@ Each skill entry in the top-level `README.md` must link the skill name to its `S
|
|||||||
|
|
||||||
Each bucket folder has a `README.md` that lists every skill in the bucket with a one-line description, with the skill name linked to its `SKILL.md`. Bucket `README.md`s and the top-level `README.md` group entries into **User-invoked** and **Model-invoked**.
|
Each bucket folder has a `README.md` that lists every skill in the bucket with a one-line description, with the skill name linked to its `SKILL.md`. Bucket `README.md`s and the top-level `README.md` group entries into **User-invoked** and **Model-invoked**.
|
||||||
|
|
||||||
Every promoted skill also has a human-facing docs page at `docs/<bucket>/<skill-name>.md` (the docs tree mirrors the bucket folders under `skills/`). The published URL is `https://aihero.dev/skills-<skill-name>` regardless of bucket — the docs path is repo organisation only. When you add, rename, or change the behaviour of a skill in `engineering/`, `productivity/`, or `misc/`, create or re-sync its docs page following [.agents/writing-docs.md](./.agents/writing-docs.md).
|
Every `SKILL.md` is either user-invoked (`disable-model-invocation: true`, reachable only by the human) or model-invoked (model- or user-reachable). For the full definitions, description conventions, and why a user-invoked skill can invoke model-invoked skills but never another user-invoked one, see [docs/invocation.md](./docs/invocation.md).
|
||||||
|
|
||||||
Every `SKILL.md` is either user-invoked (`disable-model-invocation: true`, reachable only by the human) or model-invoked (model- or user-reachable). See [.agents/invocation.md](./.agents/invocation.md).
|
|
||||||
|
|
||||||
To (re)link every skill into the local harness skill directories (`~/.claude/skills`, `~/.agents/skills`), run `scripts/link-skills.sh`. Each entry is a symlink into this repo, so a `git pull` keeps installed skills current; re-run the script after adding, removing, or renaming a skill.
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
Quickstart:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx skills add mattpocock/skills --skill=to-prd
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx skills update to-prd
|
|
||||||
```
|
|
||||||
|
|
||||||
[Source](https://github.com/mattpocock/skills/tree/main/skills/engineering/to-prd)
|
|
||||||
|
|
||||||
## What it does
|
|
||||||
|
|
||||||
`to-prd` turns the current conversation and your codebase understanding into a product requirements document, then publishes it to your issue tracker.
|
|
||||||
|
|
||||||
The load-bearing constraint: it does **not** interview you again. By the time you reach for it, the alignment work is done — `to-prd` synthesises what is already known rather than asking a fresh round of questions.
|
|
||||||
|
|
||||||
## When to reach for it
|
|
||||||
|
|
||||||
You invoke this by typing `/to-prd` — the agent won't reach for it on its own.
|
|
||||||
|
|
||||||
Reach for it once a change has been talked through and the domain language is settled, and you want that shared understanding written down as a spec before any code is written. If you *haven't* aligned yet, grill first — for that, use [grill-with-docs](https://aihero.dev/skills-grill-with-docs). To split the finished PRD into tickets, use [to-issues](https://aihero.dev/skills-to-issues).
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
`to-prd` publishes into your issue tracker, so [setup-matt-pocock-skills](https://aihero.dev/skills-setup-matt-pocock-skills) must have configured the tracker and triage labels for this repo first. It applies the `ready-for-agent` label itself — no separate triage pass needed.
|
|
||||||
|
|
||||||
## What the PRD includes
|
|
||||||
|
|
||||||
- **Problem statement** — what is broken or missing, and why it's worth solving, in the project's own vocabulary.
|
|
||||||
- **Solution** — the shape of the fix at a high level, before any implementation detail.
|
|
||||||
- **User stories** — an extensive, numbered list of the concrete behaviours the change must support, each one independently checkable.
|
|
||||||
- **Implementation decisions** — the choices already settled during the conversation, so they aren't relitigated later.
|
|
||||||
- **Testing decisions** — the seams the feature will be tested at, and what "done" looks like.
|
|
||||||
- **Out-of-scope items** — what this change deliberately does *not* cover, to keep the ticket bounded.
|
|
||||||
- **Further notes** — anything else worth carrying forward that doesn't fit the sections above.
|
|
||||||
|
|
||||||
## Deep modules
|
|
||||||
|
|
||||||
Before writing the PRD, `to-prd` sketches the **seams** at which the feature will be tested and looks for **deep module** opportunities — a lot of functionality hidden behind a small, stable interface. It prefers existing seams to new ones and the highest seam possible, ideally just one across the whole change.
|
|
||||||
|
|
||||||
That matters for agentic development: a good interface gives tests something durable to target, so the code underneath can change without the tests moving.
|
|
||||||
|
|
||||||
## It's working if
|
|
||||||
|
|
||||||
- It starts writing the PRD instead of asking you a fresh round of questions.
|
|
||||||
- It checks the seams with you before writing, and proposes as few as possible.
|
|
||||||
- The PRD comes back in your project's domain vocabulary, not generic boilerplate.
|
|
||||||
|
|
||||||
## Where it fits
|
|
||||||
|
|
||||||
`to-prd` is a step in the main build chain:
|
|
||||||
|
|
||||||
```txt
|
|
||||||
grill-with-docs → to-prd → to-issues → tdd
|
|
||||||
```
|
|
||||||
|
|
||||||
Reach for it after the plan and domain language are resolved, and before you break the work into implementation tickets. Its key neighbours are [grill-with-docs](https://aihero.dev/skills-grill-with-docs), which sharpens the context so the PRD is precise, and [to-issues](https://aihero.dev/skills-to-issues), which turns the PRD into independently-grabbable issues for [tdd](https://aihero.dev/skills-tdd) to implement. When you're unsure which skill or flow fits, [ask-matt](https://aihero.dev/skills-ask-matt) routes you.
|
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# NOTE: This is a dev-only script, intended for use by maintainers of this repo.
|
|
||||||
# It is not a supported installer. Modifications to it — or requests for
|
|
||||||
# modifications — will not be approved.
|
|
||||||
#
|
|
||||||
# Links all skills in the repository into the local skill directories used by
|
# Links all skills in the repository into the local skill directories used by
|
||||||
# each agent harness:
|
# each agent harness:
|
||||||
# - ~/.claude/skills — Claude Code
|
# - ~/.claude/skills — Claude Code
|
||||||
|
|||||||
@@ -5,107 +5,32 @@ description: Test-driven development. Use when the user wants to build features
|
|||||||
|
|
||||||
# Test-Driven Development
|
# Test-Driven Development
|
||||||
|
|
||||||
## Philosophy
|
TDD is the red → green loop. This skill is the reference that makes that loop produce tests worth keeping: what a good test is, where tests go, the anti-patterns, and the rules of the loop. Every section applies on every cycle — consult them before and during the loop, not after.
|
||||||
|
|
||||||
**Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.
|
When exploring the codebase, read `CONTEXT.md` (if it exists) so test names and interface vocabulary match the project's domain language, and respect ADRs in the area you're touching.
|
||||||
|
|
||||||
**Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.
|
## What a good test is
|
||||||
|
|
||||||
**Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior.
|
Tests verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't. A good test reads like a specification — "user can checkout with valid cart" tells you exactly what capability exists — and survives refactors because it doesn't care about internal structure.
|
||||||
|
|
||||||
**Tautological tests** restate the implementation inside the assertion, so they pass by construction and give zero confidence. When the expected value is computed the way the code computes it — `expect(add(a, b)).toBe(a + b)`, snapshotting a figure you derived by hand the same way the code does, asserting a constant equals itself — the test can never disagree with the code: break the code wrong and the assertion breaks wrong with it. The expected value must come from an independent source of truth — a known-good literal, a worked example, the spec.
|
|
||||||
|
|
||||||
See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.
|
See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.
|
||||||
|
|
||||||
## Anti-Pattern: Horizontal Slices
|
## Seams — where tests go
|
||||||
|
|
||||||
**DO NOT write all tests first, then all implementation.** This is "horizontal slicing" - treating RED as "write all tests" and GREEN as "write all code."
|
A **seam** is the public boundary you test at: the interface where you observe behavior without reaching inside. Tests live at seams, never against internals.
|
||||||
|
|
||||||
This produces **crap tests**:
|
**Test only at pre-agreed seams.** Before writing any test, write down the seams under test and confirm them with the user. No test is written at an unconfirmed seam. You can't test everything — agreeing the seams up front is how testing effort lands on the critical paths and complex logic instead of every edge case.
|
||||||
|
|
||||||
- Tests written in bulk test _imagined_ behavior, not _actual_ behavior
|
Ask: "What's the public interface, and which seams should we test?"
|
||||||
- You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior
|
|
||||||
- Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine
|
|
||||||
- You outrun your headlights, committing to test structure before understanding the implementation
|
|
||||||
|
|
||||||
**Correct approach**: Vertical slices via tracer bullets. One test → one implementation → repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it.
|
## Anti-patterns
|
||||||
|
|
||||||
```
|
- **Implementation-coupled** — mocks internal collaborators, tests private methods, or verifies through a side channel (querying the database instead of using the interface). The tell: the test breaks when you refactor but behavior hasn't changed.
|
||||||
WRONG (horizontal):
|
- **Tautological** — the assertion recomputes the expected value the way the code does (`expect(add(a, b)).toBe(a + b)`, a snapshot derived by hand the same way, a constant asserted equal to itself), so it passes by construction and can never disagree with the code. Expected values must come from an independent source of truth — a known-good literal, a worked example, the spec.
|
||||||
RED: test1, test2, test3, test4, test5
|
- **Horizontal slicing** — writing all tests first, then all implementation. Bulk tests verify _imagined_ behavior: you test the _shape_ of things rather than user-facing behavior, the tests go insensitive to real changes, and you commit to test structure before understanding the implementation. Work in **vertical slices** instead — one test → one implementation → repeat, each test a **tracer bullet** that responds to what the last cycle taught you.
|
||||||
GREEN: impl1, impl2, impl3, impl4, impl5
|
|
||||||
|
|
||||||
RIGHT (vertical):
|
## Rules of the loop
|
||||||
RED→GREEN: test1→impl1
|
|
||||||
RED→GREEN: test2→impl2
|
|
||||||
RED→GREEN: test3→impl3
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Workflow
|
- **Red before green.** Write the failing test first, then only enough code to pass it. Don't anticipate future tests or add speculative features.
|
||||||
|
- **One slice at a time.** One seam, one test, one minimal implementation per cycle.
|
||||||
### 1. Planning
|
- **Refactoring is not part of the loop.** It belongs to the review stage (see the `review` skill), not the red → green implementation cycle.
|
||||||
|
|
||||||
When exploring the codebase, read `CONTEXT.md` (if it exists) so that test names and interface vocabulary match the project's domain language, and respect ADRs in the area you're touching.
|
|
||||||
|
|
||||||
Before writing any code:
|
|
||||||
|
|
||||||
- [ ] Confirm with user what interface changes are needed
|
|
||||||
- [ ] Confirm with user which behaviors to test (prioritize)
|
|
||||||
- [ ] Identify opportunities for deep modules (small interface, deep implementation) — run the `/codebase-design` skill for the vocabulary and the testability checks
|
|
||||||
- [ ] List the behaviors to test (not implementation steps)
|
|
||||||
- [ ] Get user approval on the plan
|
|
||||||
|
|
||||||
Ask: "What should the public interface look like? Which behaviors are most important to test?"
|
|
||||||
|
|
||||||
**You can't test everything.** Confirm with the user exactly which behaviors matter most. Focus testing effort on critical paths and complex logic, not every possible edge case.
|
|
||||||
|
|
||||||
### 2. Tracer Bullet
|
|
||||||
|
|
||||||
Write ONE test that confirms ONE thing about the system:
|
|
||||||
|
|
||||||
```
|
|
||||||
RED: Write test for first behavior → test fails
|
|
||||||
GREEN: Write minimal code to pass → test passes
|
|
||||||
```
|
|
||||||
|
|
||||||
This is your tracer bullet - proves the path works end-to-end.
|
|
||||||
|
|
||||||
### 3. Incremental Loop
|
|
||||||
|
|
||||||
For each remaining behavior:
|
|
||||||
|
|
||||||
```
|
|
||||||
RED: Write next test → fails
|
|
||||||
GREEN: Minimal code to pass → passes
|
|
||||||
```
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
|
|
||||||
- One test at a time
|
|
||||||
- Only enough code to pass current test
|
|
||||||
- Don't anticipate future tests
|
|
||||||
- Keep tests focused on observable behavior
|
|
||||||
|
|
||||||
### 4. Refactor
|
|
||||||
|
|
||||||
After all tests pass, look for [refactor candidates](refactoring.md):
|
|
||||||
|
|
||||||
- [ ] Extract duplication
|
|
||||||
- [ ] Deepen modules (move complexity behind simple interfaces)
|
|
||||||
- [ ] Apply SOLID principles where natural
|
|
||||||
- [ ] Consider what new code reveals about existing code
|
|
||||||
- [ ] Run tests after each refactor step
|
|
||||||
|
|
||||||
**Never refactor while RED.** Get to GREEN first.
|
|
||||||
|
|
||||||
## Checklist Per Cycle
|
|
||||||
|
|
||||||
```
|
|
||||||
[ ] Test describes behavior, not implementation
|
|
||||||
[ ] Test uses public interface only
|
|
||||||
[ ] Test would survive internal refactor
|
|
||||||
[ ] Expected values are independent literals, not recomputed from the code
|
|
||||||
[ ] Code is minimal for this test
|
|
||||||
[ ] No speculative features added
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
# Refactor Candidates
|
|
||||||
|
|
||||||
After TDD cycle, look for:
|
|
||||||
|
|
||||||
- **Duplication** → Extract function/class
|
|
||||||
- **Long methods** → Break into private helpers (keep tests on public interface)
|
|
||||||
- **Shallow modules** → Combine or deepen
|
|
||||||
- **Feature envy** → Move logic to where data lives
|
|
||||||
- **Primitive obsession** → Introduce value objects
|
|
||||||
- **Existing code** the new code reveals as problematic
|
|
||||||
@@ -4,7 +4,7 @@ description: Turn a loose idea into a sequenced map of investigation tickets, th
|
|||||||
disable-model-invocation: true
|
disable-model-invocation: true
|
||||||
---
|
---
|
||||||
|
|
||||||
This skill is invoked when a loose idea requires more than one agent session to turn into a plan. It creates a stateful decision map in a markdown file, and drives the user through a sequence of tickets to resolve the open questions - which may require either prototyping, research or grilling. The map is domain-agnostic: it plans engineering work, course content, or anything else that fits the same shape.
|
This skill is invoked when a loose idea requires more than one agent session to turn into a plan. It creates a stateful decision map in a markdown file, and drives the user through a sequence of tickets to resolve the open questions - which may require either prototyping, research or grilling.
|
||||||
|
|
||||||
## The Decision Map
|
## The Decision Map
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ terse enough to stay token-efficient, and unique within the map.
|
|||||||
|
|
||||||
Blocked by: <slug>, <slug>
|
Blocked by: <slug>, <slug>
|
||||||
Status: open | in-progress | resolved
|
Status: open | in-progress | resolved
|
||||||
Type: Research | Prototype | Grilling | Task
|
Type: Research | Prototype | Grilling
|
||||||
|
|
||||||
### Question
|
### Question
|
||||||
|
|
||||||
@@ -44,12 +44,11 @@ Each ticket must be sized to one 100K token agent session.
|
|||||||
|
|
||||||
## Ticket Types
|
## Ticket Types
|
||||||
|
|
||||||
There are four types of tickets:
|
There are three types of tickets:
|
||||||
|
|
||||||
- **Research**: Reading documentation, third-party API's, or local resources like knowledge bases. Creates a markdown summary as an asset. Use this when knowledge outside the current working directory is required.
|
- **Research**: Reading documentation, third-party API's, or local resources like knowledge bases. Creates a markdown summary as an asset. Use this when knowledge outside the current working directory is required.
|
||||||
- **Prototype**: Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to — an outline, a rough take, a stub, or UI/logic code via the /prototype skill. Creates the prototype as an asset. Use this when "how should it look" or "how should it behave" is the key question.
|
- **Prototype**: Writing UI or logic code to test a hypothesis, or to explore a design space. Uses the /prototype skill. Creates a prototype as an asset. Use this when "how should it look" or "how should it behave" is the key question.
|
||||||
- **Grilling**: Conversation with the agent. Uses the /grilling and /domain-modeling skills. Asks one question at a time. The default case.
|
- **Grilling**: Conversation with the agent. Uses the /grilling and /domain-modeling skills. Asks one question at a time. The default case.
|
||||||
- **Task**: Literal manual work that must be done before the discussion can move forward — nothing to decide, prototype, or research. Moving data from one place to another, signing up for a third-party service, provisioning access. The agent automates it where it can; otherwise it hands the human a precise checklist to do by hand. Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on.
|
|
||||||
|
|
||||||
## Fog of war
|
## Fog of war
|
||||||
|
|
||||||
@@ -73,7 +72,7 @@ User invokes with a path to an existing map. A ticket slug is **optional** — w
|
|||||||
|
|
||||||
1. Load the **whole map** as context.
|
1. Load the **whole map** as context.
|
||||||
2. Choose the ticket. If the user named one, use it. Otherwise pick the first `open` ticket in document order that is [unblocked](#structure). [Claim it](#structure): set `Status: in-progress` and save before any work.
|
2. Choose the ticket. If the user named one, use it. Otherwise pick the first `open` ticket in document order that is [unblocked](#structure). [Claim it](#structure): set `Status: in-progress` and save before any work.
|
||||||
3. Resolve it, invoking skills as needed — including any the `## Notes` block names. If in doubt, use `/grilling` and `/domain-modeling`.
|
3. Resolve it, invoking skills as needed. If in doubt, use `/grilling` and `/domain-modeling`.
|
||||||
4. Record the answer in the ticket's body and set `Status: resolved`.
|
4. Record the answer in the ticket's body and set `Status: resolved`.
|
||||||
5. Add newly-discovered tickets with correct `Blocked by` edges. If the decisions made invalidate other parts of the map, update or delete those nodes.
|
5. Add newly-discovered tickets with correct `Blocked by` edges. If the decisions made invalidate other parts of the map, update or delete those nodes.
|
||||||
6. Handoff.
|
6. Handoff.
|
||||||
@@ -102,7 +101,3 @@ End every session by clearing the context and opening one or more fresh sessions
|
|||||||
> ```
|
> ```
|
||||||
|
|
||||||
**No open tickets remain.** The fog is pushed back far enough that the path to the finish line is clear — the map is done. (The initial grilling may also surface no fog at all, in which case there was never a map to build.) Recommend implementing directly, or using `/to-prd` to schedule a multi-session implementation.
|
**No open tickets remain.** The fog is pushed back far enough that the path to the finish line is clear — the map is done. (The initial grilling may also surface no fog at all, in which case there was never a map to build.) Recommend implementing directly, or using `/to-prd` to schedule a multi-session implementation.
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
An optional block declaring the **domain**, any skills every session should `consult`, and freeform standing preferences the planning surfaces.
|
|
||||||
|
|||||||
@@ -35,26 +35,6 @@ Look for the originating spec, in this order:
|
|||||||
|
|
||||||
Anything in the repo that documents how code should be written, such as `CODING_STANDARDS.md` or `CONTRIBUTING.md`.
|
Anything in the repo that documents how code should be written, such as `CODING_STANDARDS.md` or `CONTRIBUTING.md`.
|
||||||
|
|
||||||
On top of whatever the repo documents, the Standards axis always carries the **smell baseline** below — a fixed set of Fowler code smells (_Refactoring_, ch.3) that applies even when a repo documents nothing. Two rules bind it:
|
|
||||||
|
|
||||||
- **The repo overrides.** A documented repo standard always wins; where it endorses something the baseline would flag, suppress the smell.
|
|
||||||
- **Always a judgement call.** Each smell is a labelled heuristic ("possible Feature Envy"), never a hard violation — and, like any standard here, skip anything tooling already enforces.
|
|
||||||
|
|
||||||
Each smell reads *what it is* → *how to fix*; match it against the diff:
|
|
||||||
|
|
||||||
- **Mysterious Name** — a function, variable, or type whose name doesn't reveal what it does or holds. → rename it; if no honest name comes, the design's murky.
|
|
||||||
- **Duplicated Code** — the same logic shape appears in more than one hunk or file in the change. → extract the shared shape, call it from both.
|
|
||||||
- **Feature Envy** — a method that reaches into another object's data more than its own. → move the method onto the data it envies.
|
|
||||||
- **Data Clumps** — the same few fields or params keep travelling together (a type wanting to be born). → bundle them into one type, pass that.
|
|
||||||
- **Primitive Obsession** — a primitive or string standing in for a domain concept that deserves its own type. → give the concept its own small type.
|
|
||||||
- **Repeated Switches** — the same `switch`/`if`-cascade on the same type recurs across the change. → replace with polymorphism, or one map both sites share.
|
|
||||||
- **Shotgun Surgery** — one logical change forces scattered edits across many files in the diff. → gather what changes together into one module.
|
|
||||||
- **Divergent Change** — one file or module is edited for several unrelated reasons. → split so each module changes for one reason.
|
|
||||||
- **Speculative Generality** — abstraction, parameters, or hooks added for needs the spec doesn't have. → delete it; inline back until a real need shows.
|
|
||||||
- **Message Chains** — long `a.b().c().d()` navigation the caller shouldn't depend on. → hide the walk behind one method on the first object.
|
|
||||||
- **Middle Man** — a class or function that mostly just delegates onward. → cut it, call the real target direct.
|
|
||||||
- **Refused Bequest** — a subclass or implementer that ignores or overrides most of what it inherits. → drop the inheritance, use composition.
|
|
||||||
|
|
||||||
### 4. Spawn both sub-agents in parallel
|
### 4. Spawn both sub-agents in parallel
|
||||||
|
|
||||||
Send a single message with two `Agent` tool calls. Use the `general-purpose` subagent for both.
|
Send a single message with two `Agent` tool calls. Use the `general-purpose` subagent for both.
|
||||||
@@ -62,8 +42,8 @@ Send a single message with two `Agent` tool calls. Use the `general-purpose` sub
|
|||||||
**Standards sub-agent prompt** — include:
|
**Standards sub-agent prompt** — include:
|
||||||
|
|
||||||
- The full diff command and commit list.
|
- The full diff command and commit list.
|
||||||
- The list of standards-source files you found in step 3, **plus the smell baseline from step 3** pasted in full — the sub-agent has no other access to it.
|
- The list of standards-source files you found in step 3.
|
||||||
- The brief: "Report — per file/hunk where relevant — (a) every place the diff violates a documented standard: cite the standard (file + the rule); and (b) any baseline smell you spot: name it and quote the hunk. Distinguish hard violations from judgement calls — documented-standard breaches can be hard, but baseline smells are always judgement calls, and a documented repo standard overrides the baseline. Skip anything tooling enforces. Under 400 words."
|
- The brief: "Report — per file/hunk where relevant — every place the diff violates a documented standard. Cite the standard (file + the rule). Distinguish hard violations from judgement calls. Skip anything tooling enforces. Under 400 words."
|
||||||
|
|
||||||
**Spec sub-agent prompt** — include:
|
**Spec sub-agent prompt** — include:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user