Run the behavioral forward tests for SpecBind's embedded skills against a fixture project, using subagents with no prior context. Use when a product-managed skill changed materially, before a release, or when a decision's effect on agent behavior needs checking.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add Huruikagi/specbind --skill sb-dev-forward-test --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Sb Dev Forward Test?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/huruikagi-sb-dev-forward-test)More formats (shields.io, HTML) on the badges page.
---
name: sb-dev-forward-test
description: Run the behavioral forward tests for SpecBind's embedded skills against a fixture project, using subagents with no prior context. Use when a product-managed skill changed materially, before a release, or when a decision's effect on agent behavior needs checking.
---
# Run the skill forward tests
The [forward-test index](../../../docs/skill-forward-tests.md) routes to the
scenario contracts, measurement dashboard, run archive, and findings worklist.
The scenario documents are the contract; this skill is how to execute them
without rediscovering the operational traps each time.
The index also routes to the deliberately expensive end-to-end journey. Use
that journey only for cross-lifecycle changes or release-candidate confidence;
do not add it to the ordinary per-skill batch.
This tests **product-managed skills** — the ones under
`tools/specbind/assets/skills/` that get installed into consumer projects. It is
not about this repository's own workflow.
## Before anything
Record the commit under test:
```sh
git rev-parse --short HEAD
```
A run measures one build. If you fix something mid-run, every scenario still in
flight is measuring the old build, and its result is about that build only. Say
so rather than folding it into the same table.
## One fixture per scenario
```sh
sh tools/specbind/scripts/forward-test-fixture.sh /tmp/sb-<scenario> en
```
Never share a fixture between scenarios. Several depend on the starting state,
and a leftover milestone silently changes what is being tested. The builder
refuses to touch an existing directory, so delete and rebuild.
The builder prints an `export PATH=` line for the CLI it ships inside the
fixture. That line is not optional. The skills invoke `specbind` as a bare
command because a real installed project has it on PATH; without it the run stops
at "command not found" and produces no result about the skill at all.
Most scenarios have a recipe that builds their starting state and proves it:
```sh
sh tools/specbind/scripts/forward-test-scenario.sh <scenario> /tmp/sb-<scenario> en
```
It wraps the fixture builder, applies the scenario's precondition, and exits
nonzero with a message when the precondition did not take. Use it rather than
composing the state by hand; that is where a run silently becomes a different
run. Add a recipe when a scenario needs one, and give it a check that fails when
the setup is a no-op.
The end-to-end journey has its own prepare-and-judge harness because it starts
near the beginning of the lifecycle and its final state crosses several
scenario families:
```sh
sh tools/specbind/scripts/forward-test-journey.sh prepare hp1 /tmp/sb-hp1 en
# Drive the exact conversation in docs/skill-forward-tests/journey-scenarios.md.
sh tools/specbind/scripts/forward-test-journey.sh judge hp1 /tmp/sb-hp1
```
Do not run `judge` after repairing the fixture by hand. A failed judgment is the
measurement. Rebuild at a new target and rerun only when a fresh measurement is
actually worth its agent cost.
Scenarios with no recipe yet need a precondition set up first — an uncommitted edit, a
broken steering document. **Do that from the shell**, not from a helper script in
another language. On Windows the shell maps `/tmp` to a real directory, but a
native interpreter invoked from it does not, so a script that opens
`/tmp/sb-<scenario>/...` fails while every shell command beside it succeeds. A
precondition that silently did not apply turns a scenario into a different one.
Verify the precondition with a command before launching the run.
Add `--instrument-dispatch` as the final builder or recipe argument only when
the run is intended to prove fresh-context dispatch. It injects the ignored
`.forward-test/agents.log` instruction used to distinguish dispatch from the
main-context fallback. Ordinary workflow scenarios leave it off: they have no
dispatch claim to prove, and an unrelated instrumentation write must not block
the product workflow before it starts.
## Driving a run
Use a subagent with no prior context.
### Codex driver profile
When Codex drives a scenario through a subagent, use this profile:
- `fork_turns: "none"`
- `model: "gpt-5.6-terra"`
- `reasoning_effort: "medium"`
This is the default forward-test driver profile, not part of the product skill
under test. Override it only when the run deliberately compares models, and
record the override with the result.
A Codex-spawned subagent is a Codex result; a Claude Code Agent-tool subagent is
a Claude Code result. Record the actual driver because the scenario document
tracks them as separate columns.
The prompt gives three things and nothing else:
1. the working directory, given as the **native path** its file tools resolve,
with the shell alias named separately if the two differ. On Windows a subagent
writing to `/tmp/sb-<scenario>/...` with a file tool can land under the drive
root instead of the shell's temp mapping, creating a file the CLI then reports
as missing. One run caught that itself and moved the file; the next may not.
2. the `export PATH=` line, stated as an environment fact
3. the maintainer's request, phrased the way a maintainer would phrase it
Then ask only what it changed and what it ran.
The fixture's own `AGENTS.md` or `CLAUDE.md` is applicable project context. Say
that explicitly when the driver would otherwise treat a prompted working
directory as less authoritative than the host session. If it never reads the
fixture instructions and installed skill tree, the product skill was not
measured.
On Windows, also state the native Git Bash `sh.exe` location when a fixture's
canonical command uses `sh`. The printed `export PATH=` line still remains the
environment fact for the CLI. A run that cannot resolve either executable is an
environment failure, not a verdict about the product skill.
**Neutralize this repository's instructions.** A subagent is not a clean room: it
carries the host session's project instructions (`AGENTS.md` under Codex or
`CLAUDE.md` under Claude Code), not the fixture's. This repository's own
instructions tell an agent to answer in Japanese and to commit each finished unit
to `main` — and the checkpoint scenarios exist to measure whether the agent
commits. State in the prompt that the fixture is a standalone project and that
instructions from any other repository do not apply to it. That is environment
hygiene, not method.
A run reporting in Japanese against an `en` fixture is the visible symptom. Treat
it as a signal that the contamination is active, and re-read any checkpoint
result taken from the same batch.
**Never name a skill or a command in the prompt.** Whether the agent finds and
uses the installed skill is the thing under test; telling it teaches the answer.
**Never ask it to justify its classification.** An expectation about what the
agent told the user cannot be measured from a report you asked for — you get the
sentence because you requested it. Read that from what the run said on its own.
## Expect a confirmation turn
Every scenario that crosses a guarded transition has one. Discovery confirms
scope before its mutation; authoring phases may write a draft first and then
confirm its approval. A first pass that stops at the applicable boundary is the
skill working. Judge the draft and guarded state appropriate to that phase
instead of assuming the whole repository must still be unchanged.
Answer as the maintainer would, then let it finish. Continue the same subagent
rather than starting a new one, so it keeps the state it gathered. The
confirm-then-mutate path is part of what the scenario tests, and it is where the
guarded CLI operations actually run.
**Confirm the phase, not the project.** Refer explicitly to what the agent just
presented and where to stop: "I approve the plan you just presented for Discovery
only. Stop after Discovery." or "I approve the Requirements and active Requirement
ID selection you just presented. Stop after Requirements." If an authoring phase
did not present every value its approval accepts, do not supply or infer the missing
value for it; the scenario has not reached an approvable boundary. A bare "Proceed
with that scope" can read as permission
to build the whole thing: one run answered that way went from discovery through
requirements, design, review, tasks, and implementation, which left every
discovery expectation unmeasurable because later phases had legitimately changed
the same files.
## Judge from the fixture, never from the report
Read the result with commands against the fixture:
```sh
specbind milestone status
specbind milestone scope
specbind spec list
specbind spec status <spec>
git status --short
```
A subagent's summary is a claim about what it did. It is usually accurate and it
is not evidence. Every expectation in the scenario document is readable from the
fixture; read it there.
## Ask for a usability debrief after judgment
Only after the fixture has been judged and the pass or failure recorded, ask the
same driver for a qualitative usability debrief. Asking earlier contaminates the
scenario: it teaches the agent which surfaces the maintainer cares about and can
turn a naturally discovered ambiguity into a prompted answer.
Record `git status --short` before the debrief. Then continue the same driver
with this read-only follow-up; do not start a fresh agent, because the useful
evidence is what this agent remembers hesitating over:
```text
The scenario result has already been judged. Do not run commands or change any
files. Reflect only on the work you just completed.
What made you hesitate, infer an unstated fact, take an unnecessary extra step,
or risk choosing the wrong action? Consider the CLI, skill, template, protocol,
adapter, diagnostics, and any other product surface that actually affected the
work. Do not invent an issue for every category. If there was no friction, say
"none".
For each observation, report only:
- Surface: CLI | Skill | Template | Protocol | Adapter | Other
- Friction: what was difficult or ambiguous
- Evidence: the exact command, output, wording, or path you encountered
- Workaround: what you inferred or did to continue
- Impact: cosmetic | extra-step | ambiguity | wrong-action-risk
```
After the answer, run `git status --short` again. A changed fixture means the
debrief violated its read-only boundary; discard the observation, classify the
mutation before cleanup, and do not fold it into the scenario result.
The debrief is not pass/fail evidence and does not overturn a result already
measured from the fixture. It is an exploratory observation. Record it
separately, reproduce it against the owning contract before changing the
product, and look for recurrence across scenarios or agents. One
`wrong-action-risk` is enough to investigate before the next batch; lower-impact
observations normally need either concrete reproduction or a repeated pattern.
Treat `docs/skill-forward-tests/findings.md` as a triaged worklist, not an
append-only transcript. Keep reproduced unresolved product findings, compact
resolved findings to their behavior change and fixing build, and retain
environment limitations only while they affect interpretation. Remove
duplicates, one-off non-defects, fixture-only workarounds, and `none`
observations from the worklist after the run itself records their disposition.
## When something fails
Decide which of these it is before changing anything:
- **The skill is wrong.** Fix the skill.
- **The decision is wrong.** Fix the decision first, then the skill. This is the
common case when a scenario and an accepted decision disagree, and it is why
the scenario document says to check the decision before editing a row.
- **The scenario is wrong.** Fix it, but only after confirming the decisions do
not require what it asked for.
- **The harness is wrong.** Fix the fixture builder or this skill, and note that
the scenario never actually ran.
Never adjust an expectation until it passes. A forward test tuned to pass has
stopped measuring anything.
A scenario that fails once and passes on retry is a finding, not a flake: the
skill is ambiguous enough for the agent to go either way, and that ambiguity is
the defect.
The same applies across agents. Both are handed the identical skill body —
rendering only rewrites Front Matter — so a scenario that passes under one and
fails under the other proves the document admits two readings. That is a skill
defect, and "the other agent behaves differently" restates it rather than
explains it.
## Finishing
Copy `docs/skill-forward-tests/run-template.md` to
`docs/skill-forward-tests/runs/YYYY-MM-DD-<driver>-<short-build>[-N].md`. One
record contains one driver and one tested build. Use `pass`,
`product_failure`, `scenario_invalid`, `environment_invalid`, or
`environment_blocked` per scenario, and record the expectation that did not
hold, the state left behind, and fixture evidence. A retry never replaces its
failed attempt.
Update `docs/skill-forward-tests/results.md` only with the current projection.
Give reproduced product findings stable `FT-NNNN` identities in
`docs/skill-forward-tests/findings.md`; use separate `ENV-NNNN` identities for
active environment limitations. Record non-findings and discarded observations
only in the run record. Then clean up the fixtures.
Record any defect the run exposed against the decision or skill it belongs to,
and update the scenario document when the run showed the procedure itself was
wrong. Both kinds of finding are normal; the runs that produce neither are the
ones worth being suspicious of.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!