Compare commits

..
4 Commits
Author SHA1 Message Date
mathias 62cfe46927 docs(superpowers): point the vendored cluster at the tools this harness has
CI / Check / Test (push) Successful in 1s
CI / Tag release (push) Successful in 0s
The vendored skills were written against a generic `Task()` and an operator
called "your human partner". Neither exists here. An agent following
dispatching-parallel-agents literally would call a tool that is not in its list.

`Task tool` becomes the `Agent` tool with `subagent_type` across all six prompt
templates and the Gemini mapping table, and the dispatch example gains the three
options that actually matter for parallel work: issuing every dispatch in ONE
message (several Agent uses in a single turn run concurrently; one per turn
serialises them), `isolation: "worktree"` so two agents cannot fight over the
same tree, and per-agent `model` override for cheap mechanical fan-out.

`Workflow` is named as the structured alternative — phases, per-finding verify,
fan-in — with its opt-in condition stated, because a skill that told an agent to
reach for it unprompted would be teaching a policy violation.

"your human partner" becomes "the operator" in five skills. Beyond phrasing, it
was factually wrong in executing-plans, which told the reader to *ask* whether
subagents are available; on this fleet Claude Code has them and Crush/Pi/OpenCode
do not, so it now says which skill to use where.

Closes #17
Bump-Type: patch
2026-08-29 11:43:46 +02:00
mathias de84800892 chore(release): plugin.json version 0.12.0
Skip-Release: true
2026-08-29 09:41:44 +00:00
mathias 51a2d396fd docs(spec): EARS-lite behavioural criteria and a context snapshot
CI / Check / Test (push) Successful in 1s
CI / Tag release (push) Successful in 1s
Both skills gain EARS-lite as an option alongside prose criteria: WHEN/WHILE/IF
plus the unconditional form, for behaviour that a measurable threshold cannot
express. feature-spec also gains a Context snapshot section — the executor of a
spec routinely cannot open the architecture document it points at, so the facts
it depends on get inlined with provenance.

Pressure-tested per #19, and the RED phase argued against half the issue. A
subagent with no skill wrote a strong spec and then explained that it had
deliberately NOT inlined architecture context, "because both are owned by the
existing architecture document and duplicating them here would create two
drifting sources of truth". That objection is correct, so the section is built
around answering it: snapshot what the implementer cannot look up, always cite
source and version, and state that the source wins on disagreement. Prose
criteria came out fine unaided; EARS phrasing did not appear at all, which is
where the real gap was.

The GREEN run then found seven defects in the first draft, all fixed here:

- The example was in the same domain as the test scenario, so it got copied
  rather than read — the spec inherited an extraction-confidence requirement
  its feature request never mentioned. The example is now deliberately
  off-domain, with that failure written up as the reason.
- EARS-lite had no unconditional form, so a genuine invariant ("no instruction
  above threshold ever reaches a file") had to be bent into a WHILE that a
  system trivially satisfies by never entering the state. Added.
- "Maps 1:1 onto a test" was false for the WHILE form, which is universally
  quantified. Softened to say which forms map to one test and which do not.
- The provenance rule had no answer for the case it was written for: an author
  who also cannot read the source. Now: mark the block UNVERIFIED in those
  words and make confirmation the implementer's first task.
- "Snapshot only what this spec's decisions rest on" was narrower than the
  section's own purpose; a table name underpins no decision and still blocks
  the migration. Widened, with the omissions stated deliberately.
- "Say so in the section itself" did not say what, at what granularity. Now one
  opening line, not a per-fact annotation.
- The template had no slot for EARS lines, so their placement was a guess.
  Added as a subsection with a note that they are properties, not checkboxes.

Closes #12
Bump-Type: minor
2026-08-29 11:40:42 +02:00
mathias bb912e5594 chore(release): plugin.json version 0.11.0
Skip-Release: true
2026-08-29 09:34:36 +00:00
17 changed files with 198 additions and 34 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "skills",
"description": "Mathias's engineering skills library, plus the hooks and MCP servers that make it enforceable: TDD, clean code, debugging, specs, discovery, CI, and secret hygiene.",
"version": "0.10.2",
"version": "0.12.0",
"author": {
"name": "Mathias",
"url": "https://git.d-ma.be/mathias"
+93
View File
@@ -32,6 +32,90 @@ A feature spec is the implementation-level contract for one feature or component
2. **An "Out of scope" section is mandatory.** If you do not draw the boundary, the implementer (you, future-you, or another agent) will guess wrong.
3. **Every technical decision in "Technical approach" must have a rationale.** A decision is any choice where a reasonable alternative existed and was not taken. "Use Postgres" is not a decision; "use Postgres because the rest of the stack uses it and we need transactions across user + invoice" is.
## EARS-lite acceptance criteria
Measurable criteria answer "is it done?". They do not always answer "what should it do
when X happens?" — and behavioural requirements written as prose are where ambiguity
survives review. For any criterion that is conditional or event-driven, use EARS-lite
instead of prose:
```
WHEN <trigger> THE SYSTEM SHALL <observable response>
WHILE <state> THE SYSTEM SHALL <observable response>
IF <unwanted condition> THEN THE SYSTEM SHALL <observable response>
```
There is a fourth, unconditional form. Use it for invariants — the properties that must
hold with no trigger at all, which are usually the ones that matter most:
```
THE SYSTEM SHALL <observable response>
```
Worked, deliberately from a domain unlike whatever you are specifying:
```
THE SYSTEM SHALL reject a firmware image whose signature does not verify
WHEN a sensor reports a temperature above the shutdown limit
THE SYSTEM SHALL open the contactor within 200ms
WHILE the contactor is open
THE SYSTEM SHALL refuse every start command
IF a sensor reading is missing or stale by more than one interval
THEN THE SYSTEM SHALL treat it as above the limit
```
The example is off-domain on purpose. An on-domain example gets copied: a spec written
against an invoice-flavoured example inherited a requirement about extraction confidence
that its feature request never mentioned, and the author only noticed on review. Read
the shapes, not the content.
Each conditional line names a trigger and one observable response, which usually maps
onto a single test. The `WHILE` and unconditional forms are universally quantified —
"every start command", "a firmware image" — so they map onto a property or a set of
cases, not one assertion. That is still worth writing: it closes the requirements half
of the audit trail, which is otherwise issue-body prose.
**This is an option, not a replacement.** Threshold criteria ("p99 < 200ms under 100
RPS") stay as they are — EARS phrasing adds nothing to a number. Use it for conditional
behaviour, error handling, and state-dependent rules.
## Context snapshot
The executor of this spec will not see the conversation that produced it, and often
cannot see the architecture document either — a different agent, a fresh session, a
different machine. A spec that says "see the architecture doc" hands them a lookup they
may not be able to perform.
So inline the specific facts this spec depends on, not the whole document:
```markdown
## Context snapshot
Taken from <source> @ <commit-or-date>. Re-check before implementing if stale.
- The mailbox poller writes rows to `invoices` with `state = 'received'`.
- The payment-file writer reads `invoices` and emits one file per batch.
- Money is int64 minor units plus an ISO-4217 code; float is banned repo-wide.
```
Three rules keep this from becoming a second source of truth, which is the real
objection to inlining and a good one:
1. **Snapshot what the implementer cannot look up and cannot proceed without.** That is
wider than "facts this spec's decisions rest on" — a table name may underpin no
decision here and still be the thing that blocks writing the migration. It is still
narrower than the whole document: if a fact changes nothing and blocks nothing, leave
it out, and say what you left out so the omission reads as deliberate.
2. **Always cite source and version.** A snapshot without provenance cannot be
revalidated, and an unrevalidatable copy is exactly the drift everyone fears.
3. **If you could not read the source either, say so in those words.** Writing a spec
against a document you cannot open is common and is not a reason to skip the section
— it is a reason to mark the whole block `UNVERIFIED — reconstructed, not read`, and
to make confirming it the implementer's first task, before the first failing test.
An unmarked guess is the only genuinely dangerous version.
4. **The snapshot is evidence, not authority.** Open the section with one line to that
effect — "where this disagrees with the source, the source wins and this spec is
stale" — rather than annotating each fact.
## Spec Template
```markdown
@@ -42,12 +126,21 @@ A feature spec is the implementation-level contract for one feature or component
What problem does this feature solve? For whom? Why now?
(2-4 sentences. If you cannot answer "why now," ask before writing the rest.)
## Context snapshot
[Facts the implementer cannot look up, with source and version. See "Context snapshot" above.]
## Success Criteria
- [ ] Criterion 1 — measurable and verifiable
- [ ] Criterion 2 — measurable and verifiable
- [ ] Criterion 3 — measurable and verifiable
### Behavioural criteria (EARS-lite)
[Conditional and event-driven behaviour, one trigger and one observable response per
line. Not checkboxes — these are properties, and several need more than one test each.
Omit the subsection entirely if the feature has no conditional behaviour.]
## Constraints
Non-negotiable requirements the solution must satisfy.
+50
View File
@@ -200,6 +200,56 @@ Dev: [full command]
[Anything unresolved that needs input before implementation begins]
```
## EARS-lite acceptance criteria
Measurable criteria answer "is it done?". They do not always answer "what should it do
when X happens?" — and behavioural requirements written as prose are where ambiguity
survives review. For any criterion that is conditional or event-driven, use EARS-lite
instead of prose:
```
WHEN <trigger> THE SYSTEM SHALL <observable response>
WHILE <state> THE SYSTEM SHALL <observable response>
IF <unwanted condition> THEN THE SYSTEM SHALL <observable response>
```
There is a fourth, unconditional form. Use it for invariants — the properties that must
hold with no trigger at all, which are usually the ones that matter most:
```
THE SYSTEM SHALL <observable response>
```
Worked, deliberately from a domain unlike whatever you are specifying:
```
THE SYSTEM SHALL reject a firmware image whose signature does not verify
WHEN a sensor reports a temperature above the shutdown limit
THE SYSTEM SHALL open the contactor within 200ms
WHILE the contactor is open
THE SYSTEM SHALL refuse every start command
IF a sensor reading is missing or stale by more than one interval
THEN THE SYSTEM SHALL treat it as above the limit
```
The example is off-domain on purpose. An on-domain example gets copied: a spec written
against an invoice-flavoured example inherited a requirement about extraction confidence
that its feature request never mentioned, and the author only noticed on review. Read
the shapes, not the content.
Each conditional line names a trigger and one observable response, which usually maps
onto a single test. The `WHILE` and unconditional forms are universally quantified —
"every start command", "a firmware image" — so they map onto a property or a set of
cases, not one assertion. That is still worth writing: it closes the requirements half
of the audit trail, which is otherwise issue-body prose.
**This is an option, not a replacement.** Threshold criteria ("p99 < 200ms under 100
RPS") stay as they are — EARS phrasing adds nothing to a number. Use it for conditional
behaviour, error handling, and state-dependent rules.
For the executor-facing handoff, `feature-spec` also carries a **Context snapshot**
section — inline the architecture facts the implementer cannot look up.
## Reframing Vague Requirements
When you receive a vague requirement, translate it into specific success criteria before writing any spec content:
@@ -7,7 +7,7 @@ Use this template when dispatching a spec document reviewer subagent.
**Dispatch after:** Spec document is written to docs/superpowers/specs/
```
Task tool (general-purpose):
Agent tool (`subagent_type: "general-purpose"`):
description: "Review spec document"
prompt: |
You are a spec document reviewer. Verify this spec is complete and ready for planning.
@@ -68,13 +68,30 @@ Each agent gets:
### 3. Dispatch in Parallel
```typescript
// In Claude Code / AI environment
Task("Fix agent-tool-abort.test.ts failures")
Task("Fix batch-completion-behavior.test.ts failures")
Task("Fix tool-approval-race-conditions.test.ts failures")
// All three run concurrently
Issue every dispatch in **one** message — several `Agent` tool uses in a single
assistant turn run concurrently; one per turn runs them in series.
```
Agent(description: "fix abort tests", subagent_type: "general-purpose", prompt: ...)
Agent(description: "fix batch tests", subagent_type: "general-purpose", prompt: ...)
Agent(description: "fix approval tests", subagent_type: "general-purpose", prompt: ...)
```
Options that matter for this pattern:
- `run_in_background: true` (the default) returns immediately and notifies on
completion. Set it to `false` only when your very next action depends on the result.
- `isolation: "worktree"` gives an agent its own git worktree. Use it whenever two
agents might touch the same files — parallel writers to one tree is the failure this
skill's independence rule exists to avoid, and a worktree makes it structural rather
than a matter of discipline.
- `model` overrides the model per agent; cheap mechanical fan-out does not need the
same model as the reasoning that planned it.
For a fan-out with real structure — phases, a verify pass per finding, fan-in — the
`Workflow` tool expresses it directly with `agent()`, `parallel()` and `pipeline()`.
It spawns many agents and costs accordingly, so it runs **only on explicit opt-in from
the operator**; do not reach for it just because a task looks parallel.
### 4. Review and Integrate
+4 -2
View File
@@ -14,14 +14,16 @@ Load plan, review critically, execute all tasks, report when complete.
**Announce at start:** "I'm using the executing-plans skill to implement this plan."
**Note:** Tell your human partner that Superpowers works much better with access to subagents. The quality of its work will be significantly higher if run on a platform with subagent support (such as Claude Code or Codex). If subagents are available, use superpowers:subagent-driven-development instead of this skill.
**Note:** This skill is the fallback for harnesses with no subagents. Claude Code has
them — the `Agent` tool — so on this fleet prefer `superpowers-subagent-driven-development`
and use this skill only where `Agent` is genuinely unavailable (Crush, Pi, OpenCode).
## The Process
### Step 1: Load and Review Plan
1. Read plan file
2. Review critically - identify any questions or concerns about the plan
3. If concerns: Raise them with your human partner before starting
3. If concerns: Raise them with the operator before starting
4. If no concerns: Create TodoWrite and proceed
### Step 2: Execute Tasks
@@ -54,7 +54,7 @@ WHY: Items may be related. Partial understanding = wrong implementation.
**Example:**
```
your human partner: "Fix 1-6"
the operator: "Fix 1-6"
You understand 1,2,3,6. Unclear on 4,5.
❌ WRONG: Implement 1,2,3,6 now, ask about 4,5 later
@@ -63,7 +63,7 @@ You understand 1,2,3,6. Unclear on 4,5.
## Source-Specific Handling
### From your human partner
### From the operator
- **Trusted** - implement after understanding
- **Still ask** if scope unclear
- **No performative agreement**
@@ -84,11 +84,11 @@ IF suggestion seems wrong:
IF can't easily verify:
Say so: "I can't verify this without [X]. Should I [investigate/ask/proceed]?"
IF conflicts with your human partner's prior decisions:
Stop and discuss with your human partner first
IF conflicts with the operator's prior decisions:
Stop and discuss with the operator first
```
**your human partner's rule:** "External feedback - be skeptical, but check carefully"
**the operator's rule:** "External feedback - be skeptical, but check carefully"
## YAGNI Check for "Professional" Features
@@ -100,7 +100,7 @@ IF reviewer suggests "implementing properly":
IF used: Then implement properly
```
**your human partner's rule:** "You and reviewer both report to me. If we don't need this feature, don't add it."
**the operator's rule:** "You and reviewer both report to me. If we don't need this feature, don't add it."
## Implementation Order
@@ -123,13 +123,13 @@ Push back when:
- Violates YAGNI (unused feature)
- Technically incorrect for this stack
- Legacy/compatibility reasons exist
- Conflicts with your human partner's architectural decisions
- Conflicts with the operator's architectural decisions
**How to push back:**
- Use technical reasoning, not defensiveness
- Ask specific questions
- Reference working tests/code
- Involve your human partner if architectural
- Involve the operator if architectural
**Signal if uncomfortable pushing back out loud:** "Strange things are afoot at the Circle K"
@@ -200,7 +200,7 @@ Reviewer: "Implement proper metrics tracking with database, date filters, CSV ex
**Unclear Item (Good):**
```
your human partner: "Fix items 1-6"
the operator: "Fix items 1-6"
You understand 1,2,3,6. Unclear on 4,5.
✅ "Understand 1,2,3,6. Need clarification on 4 and 5 before implementing."
```
@@ -36,7 +36,9 @@ HEAD_SHA=$(git rev-parse HEAD)
**2. Dispatch code reviewer subagent:**
Use Task tool with `general-purpose` type, fill template at `code-reviewer.md`
Use the `Agent` tool with `subagent_type: "general-purpose"`, filling the template at
`code-reviewer.md`. A reviewer needs no write access and benefits from none — if the
harness offers a read-only agent type, prefer it.
**Placeholders:**
- `{DESCRIPTION}` - Brief summary of what you built
@@ -5,7 +5,7 @@ Use this template when dispatching a code reviewer subagent.
**Purpose:** Review completed work against requirements and code quality standards before it cascades into more work.
```
Task tool (general-purpose):
Agent tool (`subagent_type: "general-purpose"`):
description: "Review code changes"
prompt: |
You are a Senior Code Reviewer with expertise in software architecture,
@@ -14,7 +14,7 @@ Execute plan by dispatching fresh subagent per task, with two-stage review after
**Core principle:** Fresh subagent per task + two-stage review (spec then quality) = high quality, fast iteration
**Continuous execution:** Do not pause to check in with your human partner between tasks. Execute all tasks from the plan without stopping. The only reasons to stop are: BLOCKED status you cannot resolve, ambiguity that genuinely prevents progress, or all tasks complete. "Should I continue?" prompts and progress summaries waste their time — they asked you to execute the plan, so execute it.
**Continuous execution:** Do not pause to check in with the operator between tasks. Execute all tasks from the plan without stopping. The only reasons to stop are: BLOCKED status you cannot resolve, ambiguity that genuinely prevents progress, or all tasks complete. "Should I continue?" prompts and progress summaries waste their time — they asked you to execute the plan, so execute it.
## When to Use
@@ -7,7 +7,7 @@ Use this template when dispatching a code quality reviewer subagent.
**Only dispatch after spec compliance review passes.**
```
Task tool (general-purpose):
Agent tool (`subagent_type: "general-purpose"`):
Use template at requesting-code-review/code-reviewer.md
DESCRIPTION: [task summary, from implementer's report]
@@ -3,7 +3,7 @@
Use this template when dispatching an implementer subagent.
```
Task tool (general-purpose):
Agent tool (`subagent_type: "general-purpose"`):
description: "Implement Task N: [task name]"
prompt: |
You are implementing Task N: [task name]
@@ -5,7 +5,7 @@ Use this template when dispatching a spec compliance reviewer subagent.
**Purpose:** Verify implementer built what was requested (nothing more, nothing less)
```
Task tool (general-purpose):
Agent tool (`subagent_type: "general-purpose"`):
description: "Review spec compliance for Task N"
prompt: |
You are reviewing whether an implementation matches its specification.
@@ -24,11 +24,11 @@ When a skill says to dispatch a named agent type, use `@generalist` with the ful
| Skill instruction | Gemini CLI equivalent |
|-------------------|----------------------|
| `Task tool (superpowers:implementer)` | `@generalist` with the filled `implementer-prompt.md` template |
| `Task tool (superpowers:spec-reviewer)` | `@generalist` with the filled `spec-reviewer-prompt.md` template |
| `Task tool (superpowers:code-reviewer)` | `@code-reviewer` (bundled agent) or `@generalist` with the filled review prompt |
| `Task tool (superpowers:code-quality-reviewer)` | `@generalist` with the filled `code-quality-reviewer-prompt.md` template |
| `Task tool (general-purpose)` with inline prompt | `@generalist` with your inline prompt |
| `Agent tool (superpowers:implementer)` | `@generalist` with the filled `implementer-prompt.md` template |
| `Agent tool (superpowers:spec-reviewer)` | `@generalist` with the filled `spec-reviewer-prompt.md` template |
| `Agent tool (superpowers:code-reviewer)` | `@code-reviewer` (bundled agent) or `@generalist` with the filled review prompt |
| `Agent tool (superpowers:code-quality-reviewer)` | `@generalist` with the filled `code-quality-reviewer-prompt.md` template |
| `Agent tool (general-purpose)` with inline prompt | `@generalist` with your inline prompt |
### Prompt filling
@@ -111,7 +111,7 @@ Skip any step = lying, not verifying
## Why This Matters
From 24 failure memories:
- your human partner said "I don't believe you" - trust broken
- the operator said "I don't believe you" - trust broken
- Undefined functions shipped - would crash
- Missing requirements shipped - incomplete features
- Time wasted on false completion → redirect → rework
@@ -7,7 +7,7 @@ Use this template when dispatching a plan document reviewer subagent.
**Dispatch after:** The complete plan is written.
```
Task tool (general-purpose):
Agent tool (`subagent_type: "general-purpose"`):
description: "Review plan document"
prompt: |
You are a plan document reviewer. Verify this plan is complete and ready for implementation.
+2 -2
View File
@@ -246,7 +246,7 @@ Always use subagents (50-100x context savings). REQUIRED: Use [other-skill-name]
**Compress examples:**
```markdown
# ❌ BAD: Verbose example (42 words)
your human partner: "How did we handle authentication errors in React Router before?"
the operator: "How did we handle authentication errors in React Router before?"
You: I'll search past conversations for React Router authentication patterns.
[Dispatch subagent with search query: "React Router authentication error handling 401"]
@@ -318,7 +318,7 @@ digraph when_flowchart {
See @graphviz-conventions.dot for graphviz style rules.
**Visualizing for your human partner:** Use `render-graphs.js` in this directory to render a skill's flowcharts to SVG:
**Visualizing for the operator:** Use `render-graphs.js` in this directory to render a skill's flowcharts to SVG:
```bash
./render-graphs.js ../some-skill # Each diagram separately
./render-graphs.js ../some-skill --combine # All diagrams in one SVG