feat(skills): skill workshop, test-first and debugging preloaded into the step helper
The workshop (ordre 7a, contracts S1 and S2): a form check (lib/skills/skill-lint.mjs) that follows Claude Code's own skill fields, and a model-free routing test (lib/skills/routing.mjs) over every skill, the 7 commands and the 21 spawnable agents, reading the eval cases themselves (evals/skill-*, 3 fire / 2 quiet / 1 effect, tagged with the event they came from). Thresholds pinned, never lowered. The two skills were written against failures measured first in helpers without them: red only as an import crash, the whole suite run from a hand-made file list instead of the repo's own command, and an unreproduced fix shipped under authority pressure. step-implementer preloads both through its skills: line; no tool list change. Credits: addyosmani/agent-skills @9d0c60d, obra/superpowers @8ca22db, mattpocock/skills @c55ee46 (MIT), Anthropic skill-creator (Apache-2.0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4ee711a6ac
commit
cc832fd430
41 changed files with 1996 additions and 0 deletions
93
skills/test-first/SKILL.md
Normal file
93
skills/test-first/SKILL.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
name: test-first
|
||||
description: "Red-before-green discipline for a code change: find the repository's own test command, write one failing test at an agreed seam, see each new assertion fail for the reason the change exists (a crash is not red), write the smallest code that passes, then run the whole suite with that same command. Use when code is about to change and a test can pin the change: a plan step with a Test first field, a new behaviour, a bug fix, a pasted or ready-made implementation, or a test that passed at once."
|
||||
---
|
||||
|
||||
# Test first
|
||||
|
||||
## Overview
|
||||
|
||||
A test proves something only if it was seen to fail, for the right reason, before the code that
|
||||
makes it pass existed. Everything here serves that one rule. Time pressure, a senior voice saying
|
||||
"just ship it", or finished code pasted into the chat do not change it: they are when it matters.
|
||||
|
||||
## When to use
|
||||
|
||||
- A plan step carries `Test first:`; a bug is about to be fixed; a behaviour is about to be added.
|
||||
- Someone hands over ready code ("paste this in"): the test still comes first, and runs against the
|
||||
current code before the new code goes in.
|
||||
- A new test passed the first time it ran.
|
||||
- Not for: a change no test can observe (a comment, a config value read nowhere, a doc). Say so and
|
||||
stop; do not invent a test that checks the source text.
|
||||
|
||||
## Process
|
||||
|
||||
1. **Find the repository's own test command before anything else.** Read `package.json` scripts,
|
||||
`Makefile`, `pyproject.toml`, `CONTRIBUTING`, CI files. Note two commands: the focused one (one
|
||||
file) and the whole-suite one (`npm test`, `make test`, `pytest`, ...). Use exactly these. Do not
|
||||
hand-assemble a list of test files for "the whole suite": a list misses the next test file, and a
|
||||
form the repo does not use (`node --test tests/` on a Node that wants files) fails for reasons
|
||||
unrelated to the code.
|
||||
2. **Agree the seam.** The test sits at the public boundary where the behaviour is observed: the
|
||||
function, command or endpoint the plan names. Never a private helper, never the source text.
|
||||
3. **Write one test for one behaviour.** Before writing it, name the code change that would make it
|
||||
fail. Take the expected value from an independent source: a literal, a worked example, the spec.
|
||||
An expected value computed the way the code computes it (`expect(total(xs)).toBe(xs.reduce(...))`,
|
||||
`bookedMinutes(s) / 60 * rate` to test a cost built on `bookedMinutes`) passes by construction.
|
||||
4. **See it fail, for the reason the change exists.** Run the focused command. Read the failure:
|
||||
- an assertion on the behaviour fails (`2 !== 120`): red. Go on.
|
||||
- it passes: it proves nothing. Change the test until it fails for the step's reason; if it cannot,
|
||||
the behaviour already exists: report that and stop, do not build.
|
||||
- it crashes (missing export, syntax error, import of a file that does not exist yet): that is not
|
||||
red for the assertions behind it. Add the bare signature (an export that returns nothing useful,
|
||||
an empty route) so the file loads, run again, and see each new assertion fail on its own.
|
||||
5. **Write the smallest code that makes it pass.** Nothing the test does not ask for. Pasted or
|
||||
ready-made code goes in only now, after step 4, and only as far as the test needs it; run the test
|
||||
against it rather than trusting "I tested it by hand".
|
||||
6. **Run the whole suite with the repository's own command** (step 1), fresh, and read the exit code.
|
||||
A green focused file is not a green suite. Any failure it shows, also one this change did not
|
||||
cause, goes into the report by name.
|
||||
7. **A test changed after green is a new test.** Edited an assertion, added a case, tightened a
|
||||
tolerance after the code passed? Prove that assertion red again (revert the code change, or plant
|
||||
the fault it should catch), then green. Otherwise say plainly that it was never seen failing.
|
||||
|
||||
## Red flags
|
||||
|
||||
| Thought | What it means |
|
||||
|---|---|
|
||||
| "It's a one-liner, the test can come tomorrow" | The one-liner is the change most often left untested. The test is one line too. |
|
||||
| "Here's working code, paste it in" | Then the test runs against the current code first, and against the pasted code second. Reports of "tested by hand" are not runs. |
|
||||
| "The test failed with `does not provide an export`" | The file crashed; no assertion ran. Add the signature, then see the assertion fail. |
|
||||
| "Passed first time, good" | It proves nothing about this change. Make it fail for the step's reason. |
|
||||
| "I'll run the two test files, that's the suite" | Use the repository's whole-suite command; a hand-made list goes stale. |
|
||||
| "Adjusted the expected value to match the output" | The output is what is under test. Find the value independently. |
|
||||
| "Added one more case after it went green" | That case was never red. Prove it or say so. |
|
||||
|
||||
## Enforced by
|
||||
|
||||
- `lib/verification/red-proof.mjs` (inside `/trekexecute`): the step's test must fail at the step's
|
||||
start point and pass at its result. It counts any failing exit, so a crash also passes it; seeing
|
||||
each assertion fail is prose only.
|
||||
- `lib/util/test-lock.mjs` with `hooks/scripts/pre-write-executor.mjs` (inside `/trekexecute`): once
|
||||
the step's tests are locked, they cannot be edited to fit the code.
|
||||
- `lib/verification/test-integrity.mjs` (the floor guard, inside `/trekexecute`): a diff that deletes
|
||||
asserts or tests, skips a test, mutes a check or loosens a threshold is a finding.
|
||||
- `lib/verification/done-line.mjs` (inside `/trekexecute`): only the script writes a step's DONE
|
||||
line, and only when the step's test command exits 0.
|
||||
- prose only: finding and using the repository's own whole-suite command, the independent expected
|
||||
value, and proving a test changed after green. Outside `/trekexecute` none of the checks above run.
|
||||
|
||||
## Credits
|
||||
|
||||
Ideas adapted, text rewritten; no code or prose copied.
|
||||
|
||||
- obra/superpowers @8ca22db, `skills/test-driven-development/` (`SKILL.md`, `writing-good-tests.md`):
|
||||
watched red, red that errors is not red, the whole suite decides green, name the change that would
|
||||
make the test fail. MIT, Copyright (c) 2025 Jesse Vincent.
|
||||
- addyosmani/agent-skills @9d0c60d, `skills/test-driven-development/SKILL.md`: discover the
|
||||
repository's own test commands first; a test that passes immediately proves nothing. MIT,
|
||||
Copyright (c) 2025 Addy Osmani.
|
||||
- mattpocock/skills @c55ee46, `skills/engineering/tdd/` (`SKILL.md`, `tests.md`): tests at agreed
|
||||
seams, the tautological test, one test then one implementation. MIT, Copyright (c) 2026 Matt Pocock.
|
||||
- The step-by-step targets come from Voyage's own baseline runs without this skill (the crash-as-red
|
||||
and hand-listed-suite failures); see `docs/skills-authoring.md`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue