spectoflow 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +133 -0
- package/bin/spectoflow.js +170 -0
- package/lib/adapters.js +120 -0
- package/lib/detect.js +34 -0
- package/lib/manifest.js +36 -0
- package/lib/ownership.js +34 -0
- package/lib/update.js +78 -0
- package/package.json +30 -0
- package/templates/AGENTS.md +66 -0
- package/templates/agents/architect.md +54 -0
- package/templates/agents/business-analyst.md +53 -0
- package/templates/agents/code-reviewer.md +58 -0
- package/templates/agents/developer.md +73 -0
- package/templates/agents/devops.md +59 -0
- package/templates/agents/product-manager.md +53 -0
- package/templates/agents/qa-engineer.md +63 -0
- package/templates/agents/security-engineer.md +59 -0
- package/templates/agents/tech-lead.md +52 -0
- package/templates/agents/ux-designer.md +50 -0
- package/templates/capabilities.md +15 -0
- package/templates/config.json +10 -0
- package/templates/dashboard/orchestrator.js +117 -0
- package/templates/dashboard/public/app.js +747 -0
- package/templates/dashboard/public/charts.js +192 -0
- package/templates/dashboard/public/icons.js +28 -0
- package/templates/dashboard/public/index.html +226 -0
- package/templates/dashboard/public/stats.js +32 -0
- package/templates/dashboard/public/styles.css +426 -0
- package/templates/dashboard/runner.js +77 -0
- package/templates/dashboard/server.js +115 -0
- package/templates/lib/store.js +289 -0
- package/templates/policy.md +11 -0
- package/templates/skills/analyze-requirements/SKILL.md +67 -0
- package/templates/skills/brainstorm/SKILL.md +58 -0
- package/templates/skills/code-review/SKILL.md +67 -0
- package/templates/skills/implement/SKILL.md +80 -0
- package/templates/skills/security-review/SKILL.md +70 -0
- package/templates/skills/write-adr/SKILL.md +61 -0
- package/templates/skills/write-e2e-tests/SKILL.md +99 -0
- package/templates/skills/write-plan/SKILL.md +66 -0
- package/templates/skills/write-spec/SKILL.md +66 -0
- package/templates/skills/write-tests/SKILL.md +80 -0
- package/templates/workflow.md +15 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-adr
|
|
3
|
+
description: Record an architecturally significant decision as a short, durable ADR.
|
|
4
|
+
capability: architecture
|
|
5
|
+
inputs: The design under discussion (components/boundaries, framed by C4 views) and the options weighed.
|
|
6
|
+
outputs: An ADR file recording context, decision, and consequences.
|
|
7
|
+
standard: "ADR (Nygard/MADR) + C4"
|
|
8
|
+
---
|
|
9
|
+
# Write ADR
|
|
10
|
+
|
|
11
|
+
Capture one architecturally significant decision — the forces behind it, what was chosen, and what it
|
|
12
|
+
costs — so the reasoning survives past the conversation that produced it.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
Whenever a decision has lasting consequence: it constrains a boundary, an interface, a technology
|
|
16
|
+
choice, or a trade-off that would be expensive to reverse. Not for routine implementation choices a
|
|
17
|
+
developer can freely change later.
|
|
18
|
+
|
|
19
|
+
## Method
|
|
20
|
+
Frame the decision against the relevant C4 view first — is this a System Context decision (an external
|
|
21
|
+
dependency or actor), a Container decision (a new service, store, or protocol between them), or a
|
|
22
|
+
Component decision (internal structure of one container)? Naming the level keeps the ADR scoped to one
|
|
23
|
+
decision instead of drifting into a general design doc. Then record it using Nygard's four-part
|
|
24
|
+
structure (default) or MADR's fuller field set when the trade-off between options needs to be visible:
|
|
25
|
+
|
|
26
|
+
1. **Title.** A short noun phrase naming the decision, numbered — `NNNN-title.md`.
|
|
27
|
+
2. **Status.** `proposed`, `accepted`, `deprecated`, or `superseded by NNNN`.
|
|
28
|
+
3. **Context.** The forces and constraints in play, stated as fact, not argument for the decision.
|
|
29
|
+
(MADR: also list **Decision drivers** explicitly if more than one competing force is at play.)
|
|
30
|
+
4. **Decision.** What was decided, in full sentences, active voice: "We will …".
|
|
31
|
+
(MADR: list the **Considered options**, and for each, brief pros/cons, before naming the outcome —
|
|
32
|
+
this is what makes a later "why not X" answerable without re-litigating.)
|
|
33
|
+
5. **Consequences.** What becomes easier or harder as a result — positive, negative, and neutral. Name
|
|
34
|
+
what was rejected and why, not just what was chosen.
|
|
35
|
+
|
|
36
|
+
## Output contract
|
|
37
|
+
Write one file per decision to the project's ADR location — `docs/adr/NNNN-title.md` if the project has
|
|
38
|
+
no other convention, else the location the project already uses (check for an existing `docs/adr/` or
|
|
39
|
+
`specs/adr/` directory before creating a new one). Use granular writes (one section at a time). Report
|
|
40
|
+
via the `::spectoflow` sentinel:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
::spectoflow role=architecture kind=progress msg=ADR drafted: docs/adr/NNNN-title.md
|
|
44
|
+
::spectoflow role=architecture kind=report msg=ADR accepted: NNNN-title (<N> options considered)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A decision that supersedes an earlier ADR updates that ADR's Status line (`superseded by NNNN`) and is
|
|
48
|
+
reported as its own event, never a silent edit.
|
|
49
|
+
|
|
50
|
+
## Quality bar
|
|
51
|
+
- [ ] Framed at the right C4 level — the ADR states which boundary/container/component it constrains.
|
|
52
|
+
- [ ] Context is stated as fact (forces/constraints), not as an argument for the chosen option.
|
|
53
|
+
- [ ] Considered options are named with their trade-offs, not only the winner.
|
|
54
|
+
- [ ] Consequences cover positive, negative, and neutral — not just the upside.
|
|
55
|
+
- [ ] Status is current; a reversed or replaced decision points to its successor, it isn't deleted.
|
|
56
|
+
|
|
57
|
+
## References
|
|
58
|
+
- Michael Nygard, "Documenting Architecture Decisions" (2011), the original ADR format —
|
|
59
|
+
https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
|
|
60
|
+
- MADR (Markdown Any Decision Records) template — https://adr.github.io/madr/
|
|
61
|
+
- Simon Brown, "The C4 model for visualising software architecture" — https://c4model.com/
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-e2e-tests
|
|
3
|
+
description: Author durable, CI-runnable end-to-end tests with Playwright — locators over selectors, web-first assertions, no hard waits.
|
|
4
|
+
capability: testing
|
|
5
|
+
inputs: The user-visible flow(s) under test (spec acceptance criteria or a plan task), the running app under test, and its existing `tests/e2e/` suite and Playwright config if any.
|
|
6
|
+
outputs: Committed Playwright spec files under `tests/e2e/*.spec.ts`, runnable in CI.
|
|
7
|
+
standard: Playwright
|
|
8
|
+
---
|
|
9
|
+
# Write end-to-end tests
|
|
10
|
+
|
|
11
|
+
Author a durable, CI-runnable Playwright suite that exercises real user-visible flows — the committed
|
|
12
|
+
artifact the project can re-run forever, distinct from one-off live/exploratory checks.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
When the workflow reaches an Integration or End-to-end tests step for a flow that spans multiple pages,
|
|
16
|
+
services, or a full user journey, and the result needs to live in the repo and run again in CI on every
|
|
17
|
+
change — not just be eyeballed once.
|
|
18
|
+
|
|
19
|
+
## Method
|
|
20
|
+
Practices below are current Playwright guidance (see References for exact source pages).
|
|
21
|
+
1. **Test user-visible behavior, not implementation.** Assert on what an end user actually sees and does
|
|
22
|
+
— text, roles, visible state — never internal state or private methods. This keeps tests resilient
|
|
23
|
+
to refactors.
|
|
24
|
+
2. **Locate elements the way a user would find them.** Prefer `page.getByRole()`, `getByText()`,
|
|
25
|
+
`getByLabel()`, `getByTestId()` over CSS/XPath selectors — user-facing locators survive DOM churn that
|
|
26
|
+
breaks structural selectors. Reserve `getByTestId()` for elements with no meaningful role/text.
|
|
27
|
+
3. **Use web-first assertions, never manual polling.** Write `await expect(locator).toBeVisible()`,
|
|
28
|
+
`.toHaveText(...)`, etc. — these auto-retry until the condition holds or the timeout expires. Never
|
|
29
|
+
use `page.waitForTimeout()` in a committed test: it is a fixed sleep, is explicitly documented as
|
|
30
|
+
debug-only, and is the single biggest source of flakiness. If a wait is genuinely needed, wait for a
|
|
31
|
+
specific state/locator/response, never a clock duration.
|
|
32
|
+
4. **Lean on built-in test isolation.** Each `test()` gets a fresh `page` / `BrowserContext` for free —
|
|
33
|
+
do not share mutable state between tests. For data that must be unique per run, use worker-scoped
|
|
34
|
+
fixtures (e.g. keyed by `test.info().workerIndex`) rather than global setup that couples tests
|
|
35
|
+
together.
|
|
36
|
+
5. **Extend fixtures instead of repeating setup.** When multiple specs need the same login, seeded data,
|
|
37
|
+
or page object, define it once via `test.extend()` and consume it as a fixture parameter — do not
|
|
38
|
+
copy-paste setup code across spec files.
|
|
39
|
+
6. **Configure `projects` for the matrix you actually need** (browsers, smoke vs. full suite, retries per
|
|
40
|
+
project) in the project's `playwright.config.ts` — this skill authors specs against that config, and
|
|
41
|
+
proposes config changes only when a task requires a new project/browser target.
|
|
42
|
+
7. **Turn on `trace: 'on-first-retry'`** (with `retries` set for CI) so a flaky/failing run leaves a
|
|
43
|
+
debuggable trace without paying the cost of tracing every green run.
|
|
44
|
+
8. **Keep specs scoped to one flow each**, named for the behavior under test, and placed under
|
|
45
|
+
`tests/e2e/*.spec.ts` in the user's project.
|
|
46
|
+
|
|
47
|
+
**Live/exploratory verification is not this skill's output.** When an agent needs to *see* a change work
|
|
48
|
+
right now (e.g. eyeballing a UI during development), it uses its native browser tooling (for Claude Code,
|
|
49
|
+
the Chrome extension / `claude-in-chrome`) to drive the real browser interactively. If that tooling is
|
|
50
|
+
unavailable, the fallback is Playwright in headed mode or `playwright codegen` for a quick, throwaway
|
|
51
|
+
look — never a substitute for the committed suite. Either way, the durable, CI-runnable artifact this
|
|
52
|
+
skill produces is always the Playwright spec file, not the live session.
|
|
53
|
+
|
|
54
|
+
**Playwright is a dependency of the user's project, never of spectoflow.** This skill authors tests
|
|
55
|
+
against whatever Playwright version the target project has (or proposes adding `@playwright/test` as a
|
|
56
|
+
project devDependency when none exists) — spectoflow itself stays at zero runtime dependencies per
|
|
57
|
+
`CLAUDE.md`.
|
|
58
|
+
|
|
59
|
+
## Output contract
|
|
60
|
+
- One or more `tests/e2e/*.spec.ts` files committed to the user's project, each runnable via the
|
|
61
|
+
project's Playwright config (`npx playwright test`) in CI with no manual step.
|
|
62
|
+
- No `waitForTimeout` / fixed sleeps; assertions are web-first (`expect(locator)...`); locators are
|
|
63
|
+
role/text/label/testid based, not brittle CSS/XPath.
|
|
64
|
+
- Progress and completion reported to the orchestrator and group chat with:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
::spectoflow role=testing kind=progress msg=<flow name> — spec drafted
|
|
68
|
+
::spectoflow role=testing kind=result msg=<spec file> <pass|fail> (<n> tests)
|
|
69
|
+
::spectoflow role=testing kind=done msg=<flow name> e2e suite committed at tests/e2e/<file>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Quality bar
|
|
73
|
+
- [ ] Each spec asserts user-visible behavior (text/role/state), not internal implementation.
|
|
74
|
+
- [ ] Locators use `getByRole`/`getByText`/`getByLabel`/`getByTestId`, not CSS/XPath selectors.
|
|
75
|
+
- [ ] All assertions are web-first (`await expect(...)`); zero `waitForTimeout` calls in committed specs.
|
|
76
|
+
- [ ] Tests are isolated — no shared mutable state between tests; per-worker data via fixtures where
|
|
77
|
+
parallel runs need unique data.
|
|
78
|
+
- [ ] Repeated setup (login, seed data, page objects) lives in a shared fixture, not copy-pasted.
|
|
79
|
+
- [ ] Suite is committed under `tests/e2e/` and runs headless in CI via the project's Playwright config.
|
|
80
|
+
- [ ] `trace: 'on-first-retry'` (or equivalent) is set so a CI failure is debuggable without tracing
|
|
81
|
+
every run.
|
|
82
|
+
- [ ] No spectoflow file declares Playwright as a dependency — only the user project's `package.json`.
|
|
83
|
+
|
|
84
|
+
## References
|
|
85
|
+
- Playwright — Best Practices — https://playwright.dev/docs/best-practices (test user-visible behavior;
|
|
86
|
+
prefer user-facing locators over XPath/CSS; use web-first assertions).
|
|
87
|
+
- Playwright — Locators — https://playwright.dev/docs/locators (`getByRole`, `getByText`, `getByLabel`,
|
|
88
|
+
`getByTestId`).
|
|
89
|
+
- Playwright — Auto-waiting / web-first assertions — https://playwright.dev/docs/actionability and
|
|
90
|
+
https://playwright.dev/docs/api/class-frame (`waitForTimeout` documented as debug-only; never use in
|
|
91
|
+
production tests).
|
|
92
|
+
- Playwright — Test fixtures — https://playwright.dev/docs/test-fixtures (`test.extend()`, worker-scoped
|
|
93
|
+
fixtures for per-worker isolation).
|
|
94
|
+
- Playwright — Test isolation — https://playwright.dev/docs/writing-tests (each test gets its own
|
|
95
|
+
`page`/`BrowserContext`).
|
|
96
|
+
- Playwright — Projects — https://playwright.dev/docs/test-projects (per-project browser/retry/file
|
|
97
|
+
matching configuration).
|
|
98
|
+
- Playwright — Trace viewer — https://playwright.dev/docs/trace-viewer (`trace: 'on-first-retry'` for
|
|
99
|
+
CI).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-plan
|
|
3
|
+
description: Break an approved, designed spec into small, dependency-ordered, checkbox tasks.
|
|
4
|
+
capability: planning
|
|
5
|
+
inputs: A signed-off spec (specs/<feature>.md) and its architecture/ADRs, if any.
|
|
6
|
+
outputs: plans/<feature>.md — dependency-ordered checkbox tasks.
|
|
7
|
+
standard: INVEST
|
|
8
|
+
---
|
|
9
|
+
# Write plan
|
|
10
|
+
|
|
11
|
+
Decompose an approved spec into tasks small and independent enough to execute one at a time, ordered so
|
|
12
|
+
nothing starts before what it depends on exists.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
Once a spec is signed off (and, when the change is architecturally significant, once the architect has
|
|
16
|
+
defined boundaries/ADRs), or whenever the workflow reaches the Plan step.
|
|
17
|
+
|
|
18
|
+
## Method
|
|
19
|
+
1. **Slice to INVEST size.** Break the spec's requirements into tasks that are each Independent,
|
|
20
|
+
Negotiable, Valuable, Estimable, Small, and Testable (Bill Wake). A task that can't be estimated or
|
|
21
|
+
tested on its own is still too big — split it again before it goes in the plan.
|
|
22
|
+
2. **Order by dependency.** Group into phases (`##` headings) and sequence tasks so every dependency
|
|
23
|
+
appears before what needs it — data/schema before the services that read it, services before the UI
|
|
24
|
+
that calls them, cross-cutting infra before the features built on it. State a cross-task dependency
|
|
25
|
+
explicitly in the task line or a short note, never leave it implicit.
|
|
26
|
+
3. **Write each task as a checkbox line** using the repo's task convention exactly:
|
|
27
|
+
`- [ ] T-012 Title @owner ~level %status`
|
|
28
|
+
- `T-012` — a stable, sequential task ID (never reused, never renumbered after creation).
|
|
29
|
+
- `Title` — outcome-phrased, short enough to scan.
|
|
30
|
+
- `@owner` — who/what role picks it up (`@dev`, `@qa`, agent name, or a person).
|
|
31
|
+
- `~level` — size signal, one of `~quick` / `~standard` / `~major` — keep it Small by this skill's
|
|
32
|
+
standard; a task that only fits `~major` is a candidate to split further.
|
|
33
|
+
- `%status` — current status, one of `%in_progress` / `%to_validate` / `%to_analyze` / `%blocked`.
|
|
34
|
+
A task not yet started carries **no** `%status` tag at all (todo = absent, not `%todo`). A finished
|
|
35
|
+
task is marked by checking the box (`- [x]`), never by a `%done` tag.
|
|
36
|
+
4. **Check INVEST before closing the plan.** Re-scan the list: any task not independent, not small, or
|
|
37
|
+
not testable gets split or re-scoped before the plan is handed off.
|
|
38
|
+
|
|
39
|
+
## Output contract
|
|
40
|
+
Write `plans/<feature>.md` with phase headings (`##`) grouping dependency-ordered checkbox tasks in the
|
|
41
|
+
exact line format above. Use granular writes (one task/line at a time, not one giant dump — the
|
|
42
|
+
dashboard tracks each line). Report via the `::spectoflow` sentinel:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
::spectoflow role=planning kind=progress msg=plan drafted: plans/<feature>.md (<N> tasks)
|
|
46
|
+
::spectoflow role=planning kind=report msg=plan ready: <feature> (<N> tasks, <M> phases)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A plan revised after a task reveals a missing dependency is reported again, not silently edited.
|
|
50
|
+
|
|
51
|
+
## Quality bar
|
|
52
|
+
- [ ] Every task line matches `- [ ] T-xxx Title @owner ~level %status` exactly, with `~level` from
|
|
53
|
+
`{quick, standard, major}` and `%status` from `{in_progress, to_validate, to_analyze, blocked}` —
|
|
54
|
+
never invented tags.
|
|
55
|
+
- [ ] A not-yet-started task carries no `%status` tag (todo = absent); a finished task is `- [x] …` with
|
|
56
|
+
no `%status` tag, never `%done`.
|
|
57
|
+
- [ ] Every task is Independent, Small, and Testable enough to be picked up and closed on its own
|
|
58
|
+
(INVEST); nothing in the plan is a disguised multi-task epic.
|
|
59
|
+
- [ ] Tasks are grouped into phases and ordered so no task precedes a dependency it needs.
|
|
60
|
+
- [ ] Task IDs are stable and sequential; none are reused or skipped without reason.
|
|
61
|
+
- [ ] The plan traces back to the spec's requirements — no task exists that isn't grounded in one.
|
|
62
|
+
|
|
63
|
+
## References
|
|
64
|
+
- Bill Wake, "INVEST in Good Stories, and SMART Tasks" (2003) —
|
|
65
|
+
https://xp123.com/invest-in-good-stories-and-smart-tasks/
|
|
66
|
+
- Agile Alliance, "What does INVEST Stand For?" — https://agilealliance.org/glossary/invest/
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-spec
|
|
3
|
+
description: Produce a clear, reviewable specification in markdown, signed off before design/code starts.
|
|
4
|
+
capability: analysis
|
|
5
|
+
inputs: Acceptance criteria and edge cases from analyze-requirements, plus any known constraints.
|
|
6
|
+
outputs: specs/<feature>.md — a reviewable, signed-off spec.
|
|
7
|
+
standard: spec-kit / OpenSpec conventions
|
|
8
|
+
---
|
|
9
|
+
# Write spec
|
|
10
|
+
|
|
11
|
+
Shape acceptance criteria into a single reviewable spec document, then drive it to explicit sign-off.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
Once `analyze-requirements` has produced acceptance criteria and edge cases for a feature or change, or
|
|
15
|
+
whenever the workflow reaches the Spec step.
|
|
16
|
+
|
|
17
|
+
## Method
|
|
18
|
+
Structure the document like GitHub `spec-kit`'s spec template and OpenSpec's requirement/scenario
|
|
19
|
+
format — behavior contract, not implementation plan:
|
|
20
|
+
|
|
21
|
+
1. **Purpose.** 1-2 sentences: what this capability provides and to whom. No design detail.
|
|
22
|
+
2. **Requirements.** Numbered (`REQ-001`, `REQ-002`, …), each phrased with RFC 2119 strength —
|
|
23
|
+
**MUST** (mandatory), **SHOULD** (recommended, exceptions allowed), **MAY** (optional). One
|
|
24
|
+
requirement = one testable statement, not a paragraph of intent.
|
|
25
|
+
3. **Scenarios.** Under each requirement, one or more concrete scenarios in Given/When/Then, sourced
|
|
26
|
+
directly from `analyze-requirements`' criteria and edge cases (happy path + boundaries + error
|
|
27
|
+
paths). Mark any unresolved detail inline as `[NEEDS CLARIFICATION: …]` rather than guessing.
|
|
28
|
+
4. **Out-of-scope.** What this spec deliberately does not cover — prevents silent scope creep during
|
|
29
|
+
implementation.
|
|
30
|
+
5. **Open questions.** Anything still unresolved, each tagged as a `need` per `policy.md` if it blocks
|
|
31
|
+
a decision this role can't make alone.
|
|
32
|
+
6. **Review loop.** Show the draft to the requester/stakeholders. Revise on feedback. The spec is only
|
|
33
|
+
"done" once it has explicit sign-off recorded — never inferred from silence.
|
|
34
|
+
|
|
35
|
+
## Output contract
|
|
36
|
+
Write `specs/<feature>.md` with exactly these sections, in order: Purpose, Requirements, Scenarios,
|
|
37
|
+
Out-of-scope, Open questions. Use granular writes (one line/section at a time, not one giant dump).
|
|
38
|
+
Report via the `::spectoflow` sentinel:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
::spectoflow role=analysis kind=progress msg=spec draft written: specs/<feature>.md
|
|
42
|
+
::spectoflow role=analysis kind=review msg=spec sent for sign-off: <feature>
|
|
43
|
+
::spectoflow role=analysis kind=report msg=spec signed off: <feature> (<N> requirements, <M> scenarios)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
A spec revised after feedback is reported again, not silently overwritten.
|
|
47
|
+
|
|
48
|
+
## Quality bar
|
|
49
|
+
- [ ] All five sections present, in order: Purpose, Requirements, Scenarios, Out-of-scope, Open
|
|
50
|
+
questions.
|
|
51
|
+
- [ ] Every requirement uses MUST/SHOULD/MAY and is independently testable.
|
|
52
|
+
- [ ] Every requirement has at least one Given/When/Then scenario grounded in real acceptance criteria
|
|
53
|
+
(not invented after the fact).
|
|
54
|
+
- [ ] No implementation detail (class names, frameworks, data schemas) leaks into Requirements or
|
|
55
|
+
Scenarios.
|
|
56
|
+
- [ ] Explicit sign-off is recorded before the spec is treated as done; unresolved items are tagged
|
|
57
|
+
`[NEEDS CLARIFICATION: …]` or raised as a `need`, never silently dropped.
|
|
58
|
+
|
|
59
|
+
## References
|
|
60
|
+
- GitHub, `spec-kit` spec template (User Scenarios & Testing, Requirements FR-NNN, Success Criteria) —
|
|
61
|
+
https://github.com/github/spec-kit/blob/main/templates/spec-template.md
|
|
62
|
+
- GitHub, `spec-kit` — Spec-Driven Development methodology —
|
|
63
|
+
https://github.com/github/spec-kit/blob/main/spec-driven.md
|
|
64
|
+
- Fission-AI, OpenSpec concepts (Purpose / Requirements / Scenarios, RFC 2119 strength keywords) —
|
|
65
|
+
https://github.com/Fission-AI/OpenSpec/blob/main/docs/concepts.md
|
|
66
|
+
- Cucumber, "Gherkin Syntax" — https://cucumber.netlify.app/docs/gherkin/
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-tests
|
|
3
|
+
description: Write unit/integration tests test-first, one behaviour per test, red-green-refactor.
|
|
4
|
+
capability: testing
|
|
5
|
+
inputs: Acceptance criteria or a spec section, and the code under test (or the stub it will be written against).
|
|
6
|
+
outputs: Test files (red then green) plus a pass/fail report for the covered behaviours.
|
|
7
|
+
standard: TDD (Beck) + xUnit Test Patterns
|
|
8
|
+
---
|
|
9
|
+
# Write tests
|
|
10
|
+
|
|
11
|
+
Test-first authoring of unit and integration tests, one behaviour at a time. End-to-end tests are a
|
|
12
|
+
separate scope — use the `write-e2e-tests` skill for those; do not duplicate that work here.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
Whenever a piece of behaviour (a function, method, module, or the interaction of a few collaborators
|
|
16
|
+
without crossing a real network/DB/UI boundary) needs to be implemented or changed, or when the
|
|
17
|
+
workflow reaches a testing step for unit/integration coverage.
|
|
18
|
+
|
|
19
|
+
## Method
|
|
20
|
+
Apply Kent Beck's red-green-refactor loop per behaviour, structuring each test per Meszaros's
|
|
21
|
+
xUnit Test Patterns:
|
|
22
|
+
|
|
23
|
+
1. **Pick one behaviour.** Take the next acceptance criterion or edge case not yet covered. If it
|
|
24
|
+
needs more than one sentence to describe, it is more than one test — split it.
|
|
25
|
+
2. **Red.** Write a test that fails for the right reason (the behaviour doesn't exist yet, not a typo
|
|
26
|
+
or setup bug). Give it a descriptive name stating the behaviour and condition, e.g.
|
|
27
|
+
`returns_empty_list_when_input_is_empty` or `throws_when_amount_is_negative` — not `test1` or
|
|
28
|
+
`testFoo`.
|
|
29
|
+
3. **Structure with Arrange-Act-Assert** (Bill Wake / Beck): set up inputs and collaborators (Arrange),
|
|
30
|
+
invoke exactly the one thing under test (Act), check the outcome (Assert). No conditionals, loops,
|
|
31
|
+
or try/catch-as-control-flow inside a test — a test with logic in it is itself untested code
|
|
32
|
+
(Meszaros, *Obscure Test*). Prefer one focused assertion or a tight cluster checking one outcome;
|
|
33
|
+
avoid *Assertion Roulette* (many unrelated asserts with no way to tell which one failed) and
|
|
34
|
+
*Eager Test* (one test exercising several behaviours at once).
|
|
35
|
+
4. **Green.** Write the minimum production code to pass the test — resist adding behaviour the test
|
|
36
|
+
doesn't require yet.
|
|
37
|
+
5. **Refactor.** With the test green, remove duplication and improve naming in both test and production
|
|
38
|
+
code, in small steps, re-running the test after each. Never refactor and add behaviour in the same
|
|
39
|
+
step.
|
|
40
|
+
6. **Repeat** for the next behaviour, including edge cases (empty/null/zero, boundary values, invalid
|
|
41
|
+
input, error/exception paths) — not just the happy path — until every acceptance criterion is
|
|
42
|
+
covered. Keep each test independent: no shared mutable fixture state and no ordering dependency
|
|
43
|
+
between tests (Meszaros, *Interacting Tests* / *Test Run Wars*).
|
|
44
|
+
7. Choose the lowest level that gives honest confidence: unit-test pure logic in isolation; use a thin
|
|
45
|
+
integration test only for the seam where two real collaborators must be checked together (e.g. a
|
|
46
|
+
repository against a real schema). If the behaviour requires a live UI, network, or full-stack
|
|
47
|
+
boundary, hand off to `write-e2e-tests` instead of stretching a unit test to cover it.
|
|
48
|
+
|
|
49
|
+
## Output contract
|
|
50
|
+
Test files committed alongside the code, one file per unit under test following the project's test
|
|
51
|
+
naming convention, red commit(s) allowed only transiently before the corresponding green commit. Report
|
|
52
|
+
progress with granular, one-line-at-a-time writes and the `::spectoflow` sentinel:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
::spectoflow role=testing kind=progress msg=<behaviour> red
|
|
56
|
+
::spectoflow role=testing kind=progress msg=<behaviour> green
|
|
57
|
+
::spectoflow role=testing kind=report msg=<N passed>/<N total>, 0 failed, 0 skipped
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A suite left red or with a skipped test is reported as such, never silently marked done.
|
|
61
|
+
|
|
62
|
+
## Quality bar
|
|
63
|
+
- [ ] Every acceptance criterion has at least one test; meaningful edge cases (empty/null, boundary,
|
|
64
|
+
error paths) are covered, not just the happy path.
|
|
65
|
+
- [ ] Each test covers exactly one behaviour and is named for that behaviour and its condition.
|
|
66
|
+
- [ ] Each test follows Arrange-Act-Assert with no branching/looping logic inside the test body.
|
|
67
|
+
- [ ] No Assertion Roulette (unrelated asserts bundled) and no Eager Test (one test, many behaviours).
|
|
68
|
+
- [ ] Tests are independent — no shared mutable state, no required run order, no real secrets or live
|
|
69
|
+
external endpoints.
|
|
70
|
+
- [ ] The full suite is green before reporting done; nothing is skipped or commented out to get there.
|
|
71
|
+
|
|
72
|
+
## References
|
|
73
|
+
- Kent Beck, *Test-Driven Development: By Example* (Addison-Wesley, 2002) — red/green/refactor.
|
|
74
|
+
- Kent Beck, "Canon TDD" — https://tidyfirst.substack.com/p/canon-tdd
|
|
75
|
+
- Martin Fowler, "Test Driven Development" — https://www.martinfowler.com/bliki/TestDrivenDevelopment.html
|
|
76
|
+
- Gerard Meszaros, *xUnit Test Patterns: Refactoring Test Code* (Addison-Wesley, 2007) —
|
|
77
|
+
http://xunitpatterns.com/ ; "Assertion Roulette" http://xunitpatterns.com/Assertion%20Roulette.html ;
|
|
78
|
+
"Obscure Test" http://xunitpatterns.com/Obscure%20Test.html ; test smell catalog
|
|
79
|
+
http://xunitpatterns.com/TestSmells.html
|
|
80
|
+
- Bill Wake, "3A – Arrange, Act, Assert" (2001) — https://xp123.com/3a-arrange-act-assert/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Active workflow
|
|
2
|
+
|
|
3
|
+
The enabled steps below define how work flows for this project. Check = enabled; uncheck or remove a
|
|
4
|
+
line to change the pipeline (you can also edit this from the dashboard). This file is the single
|
|
5
|
+
source of truth for the workflow.
|
|
6
|
+
|
|
7
|
+
- [x] Brainstorm {cap:intake skill:brainstorm}
|
|
8
|
+
- [x] Analysis {cap:analysis skill:analyze-requirements}
|
|
9
|
+
- [x] Spec {cap:analysis skill:write-spec}
|
|
10
|
+
- [x] Plan {cap:planning skill:write-plan}
|
|
11
|
+
- [x] Develop {cap:implementation skill:implement}
|
|
12
|
+
- [x] Unit tests {cap:testing skill:write-tests}
|
|
13
|
+
- [ ] Integration tests (optional) {cap:testing skill:write-e2e-tests}
|
|
14
|
+
- [ ] End-to-end tests (optional) {cap:testing skill:write-e2e-tests}
|
|
15
|
+
- [x] Review {cap:quality skill:code-review}
|