NW-SPIKE: Probe → Walking Skeleton
Wave: SPIKE (between DISCUSS and DESIGN) | Agent: Attila (nw-software-crafter) | Command: /nw-spike
Overview
Execute a two-phase wave that turns a risky assumption into visible, iterable value as fast as possible:
- PROBE — quick throwaway validation of one core assumption (30-60 min, code in
/tmp/) - PROMOTION GATE (interactive) — ask the user whether to promote the probe
- WALKING SKELETON — refactor the probe into an end-to-end thin slice committed to the repository (1-3 h, code in
src/+ 1 acceptance test)
The PROBE answers "does the mechanism work?". The WALKING SKELETON answers "can a user see it working end-to-end?". You never throw away working validated code — you promote it and iterate.
When to use
The spike is needed when the feature introduces:
- A new mechanism never tried in this codebase
- A performance requirement that cannot be validated by reasoning alone
- An external integration with unknown behaviour
If none of the above apply, skip SPIKE and go to DESIGN.
Prior Wave Consultation
- DISCUSS artifacts: Read
docs/feature/{feature-id}/discuss/(required) user-stories.md— scope and acceptance criteriawave-decisions.md— constraints and assumptions to test- DIVERGE artifacts: Read
docs/feature/{feature-id}/diverge/recommendation.md(if present)
Interactive decision points (Phase 1 entry)
Decision 1: Probe scope
Question: What is the ONE assumption you need to validate? Examples:
- "Can we parse pytest output reliably in <5 seconds?"
- "Can the CEL library evaluate 100 expressions in <1 second?"
- "Can we write to
.git/hooks/from a subprocess without corruption?"
Decision 2: Performance budget
Question: What is the timing constraint? (Enter "none" if mechanism validation only) Examples:
- "<5 seconds end-to-end"
- "<100ms per operation"
- "Handle 10K items without OOM"
Decision 3: End-to-end path preview
Question: If this probe works, what would the thinnest end-to-end slice look like? Capture the rough path: user-facing entry → business logic → persistence/services → user-visible output. This is not a commitment — it's context for the promotion gate later.
Phase 1 — PROBE
Throwaway validation of the assumption.
Agent invocation
@nw-software-crafter
Execute PROBE for "{feature-description}".
Probe question: {Decision 1 answer} Performance budget: {Decision 2 answer} Target e2e path (for later): {Decision 3 answer}
Rules:
- Code goes in
/tmp/spike_{feature_id}/. Never insrc/. - Max 1 hour. No tests, no types, no error handling, no abstractions.
- One file preferred. Two files maximum.
- Use
time.perf_counter()for timing. - Print results to stdout.
After probe completes:
- Write findings to
docs/feature/{feature-id}/spike/findings.md— binary verdict (WORKS / DOESN'T WORK), timing, edge cases, design implications. - Do not delete the probe code yet — wait for the promotion gate.
- Report verdict and ask the orchestrator to run the promotion gate.
Phase 2 — PROMOTION GATE (interactive)
Run this gate only after the probe completes and findings.md is written.
Present the user with three choices:
| Choice | When to pick | Outcome | |---|---|---| | PROMOTE | Probe verdict is WORKS and the mechanism is worth building on | Proceed to Phase 3 — walking skeleton | | DISCARD | Probe verdict is WORKS but not worth pursuing (findings are enough) | Delete /tmp/spike_{feature_id}/. Commit findings.md. Hand off to DESIGN. | | PIVOT | Probe verdict is DOESN'T WORK or revealed a better approach | Delete probe code. Annotate findings.md with the pivot. Either loop back to DISCUSS or run a second probe. |
Default: if the probe verdict is WORKS and no reason to stop, recommend PROMOTE but let the user override.
Record the promotion decision in docs/feature/{feature-id}/spike/wave-decisions.md as an explicit wave decision with rationale.
Phase 3 — WALKING SKELETON (only if PROMOTE)
Refactor the probe into the thinnest end-to-end slice that is committed, tested, and demo-able.
Definition of Done (walking skeleton)
- End-to-end path: the slice enters from a real user-facing entry point (CLI command, HTTP endpoint, UI action, hook) and exits at a real user-visible output (stdout, HTTP response, rendered screen, persisted file). Every layer in between is exercised — no layer is mocked unless that layer is an external paid service classified as costly in DISTILL's Walking Skeleton Strategy (then use the fake/contract test pattern).
- One acceptance test: a
@walking_skeleton @driving_porttagged scenario intests/{test-type-path}/{feature-id}/acceptance/walking-skeleton.feature. The scenario MUST be green before hand-off. - Production location: code lives under
src/{production-path}/, not in/tmp/. Minimal module skeleton is fine — no premature abstractions, no features beyond the walking skeleton. - Committed: the walking skeleton commit message is
feat({feature-id}): walking skeleton — {one-line description}. - Demo-able: running the single acceptance test (or the real entry-point command) produces visible output that matches the user story from DISCUSS.
- Back-propagation: if building the skeleton reveals a contradiction with DISCUSS or DESIGN, write the contradiction to
docs/feature/{feature-id}/spike/upstream-issues.mdand stop — do not hand off to DISTILL until resolved.
Agent invocation (Phase 3)
@nw-software-crafter
Promote probe for "{feature-description}" into a walking skeleton.
Source probe: /tmp/spike_{feature_id}/ Target driving adapter: {from Decision 3, refined with user} Target acceptance test path: tests/{test-type-path}/{feature-id}/acceptance/walking-skeleton.feature
Rules:
- Max 3 hours. Stop and escalate if over budget.
- One acceptance test only. No unit tests unless they are strictly required to make the acceptance test pass.
- No premature abstractions. The skeleton should be obviously incomplete — only the single path from the user story works. Error paths, edge cases, and other scenarios are DISTILL's job.
- Use the real driving adapter, the real domain code, the real driven adapter. In-memory doubles only for costly external services.
- Delete
/tmp/spike_{feature_id}/after promotion.
Walking skeleton commit checklist
- [ ] 1 acceptance test @walking_skeleton green
- [ ] Real user-facing entry point exercised (not a service function call)
- [ ] Real driven adapters for local resources (filesystem, git, subprocess, SQLite)
- [ ] Code in
src/, not/tmp/ - [ ] Committed with conventional commit message
- [ ] Probe directory deleted
- [ ] Findings.md includes the "promoted on {date}" note
Progress tracking
The invoked agent MUST create a task list from its workflow phases at the start of execution using TaskCreate. Each phase becomes a task with the gate condition as completion criterion. Phase 1, Phase 2, and Phase 3 are separate task groups — Phase 3 tasks are only created if the promotion gate says PROMOTE.
Success criteria
Phase 1 (always)
- [ ] Exactly one assumption tested (not two, not zero)
- [ ] Probe code lives in
/tmp/, never insrc/ - [ ] Completed within 1 hour (or escalated with "BIGGER THAN EXPECTED")
- [ ]
findings.mdwritten with binary verdict, timing, and edge cases
Phase 2 (always)
- [ ] Promotion gate decision captured in
wave-decisions.md - [ ] One of: PROMOTE / DISCARD / PIVOT selected by user
Phase 3 (only if PROMOTE)
- [ ] Walking skeleton acceptance test green
- [ ] E2E path exercised through all non-costly layers
- [ ] Skeleton code in
src/, committed - [ ] Probe directory deleted
- [ ] No upstream contradictions left unresolved
Next wave
Handoff to: nw-solution-architect (DESIGN) — DESIGN reads findings.md and the walking