yadflow 2.2.0 → 2.3.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.
@@ -18,7 +18,7 @@ touched `domain`, `|domainOwners[domain]| >= 1`.
18
18
  - Stories review: the touched domains are the **union of every story's `repos`** under `stories/`.
19
19
 
20
20
  So one gate, two option-shapes:
21
- - Epic / UI reviews: base rule (no risk tags, no per-repo routing).
21
+ - Epic / UI / test-cases reviews: base rule (no risk tags, no per-repo routing).
22
22
  - Architecture+contract review: escalated (`risk_tags: ["contract"]`) — owner + 1 reviewer + a
23
23
  `domain-owner` for **each** repo in `epic.repos`. (A small team may have one engineer own several
24
24
  repos — one person can supply several `domain-owner` records with different `domain` values.)
@@ -57,7 +57,7 @@ if step in cfg.locked_steps: eff = "human_approve"
57
57
  ```
58
58
 
59
59
  So a kill switch, a `locked` flag, or membership in `locked_steps` forces a stop no matter what the
60
- per-step dial says. `engineer-review` and the four front states are covered by `locked` / `locked_steps`.
60
+ per-step dial says. `engineer-review` and the five front states are covered by `locked` / `locked_steps`.
61
61
 
62
62
  ## Deriving signals & the provisional verdict
63
63
 
@@ -115,7 +115,7 @@ Reverting (`to: human_approve`) is never gated — automation must be reversible
115
115
  ## What stays human, always
116
116
 
117
117
  - `engineer-review` — the merge gate. `yad-run` always stops here and hands to `yad-ship`.
118
- - The four front states (`epic`, `architecture`, `ui-design`, `stories`) — not in `back_steps`, in
119
- `locked_steps`; the dial-setter refuses them.
118
+ - The five front states (`epic`, `architecture`, `ui-design`, `stories`, `test-cases`) — not in
119
+ `back_steps`, in `locked_steps`; the dial-setter refuses them.
120
120
  - Any contract-surface change — halts the loop and routes back to the architecture gate, regardless of
121
121
  the dial.
@@ -43,7 +43,9 @@ is the same graceful-degradation pattern `yad-ui` uses for Impeccable.
43
43
 
44
44
  ### Step 1 — Resolve the story and check readiness
45
45
  Read `{project-root}/epics/<epic>/.sdlc/state.json`. Proceed only when
46
- `currentStep == "ready-for-build"` (the whole front half is `done`). Read the story file
46
+ `currentStep == "ready-for-build"` (the gating front half — through the **stories** gate — is `done`).
47
+ The **`test-cases` track may still be `in_progress`**: it is parallel and non-blocking, so the build
48
+ half runs alongside it — its status does not affect readiness here. Read the story file
47
49
  `epics/<epic>/stories/<story>.md`; confirm `repo` is in its `repos`. If the epic is not ready, STOP
48
50
  and point the user at `yad-status`. **Do not mutate front-half state** — `ready-for-build` semantics
49
51
  stay intact.
@@ -30,12 +30,15 @@ Print, in this order:
30
30
 
31
31
  1. **Epic:** `epicId`, `status` from `epic.md` frontmatter, `currentStep`, and `repos` (the touched
32
32
  domains).
33
- 2. **Steps table** — for every front step in `steps[]` order (8, or 10 when the optional analysis step
33
+ 2. **Steps table** — for every front step in `steps[]` order (10, or 12 when the optional analysis step
34
34
  was run): `id`, `type`, `status`, `assistance`, `automation`, `locked`, and `risk_tags`. Mark the
35
- `currentStep` with `→`. The full front-state chain is `[analysis → analysis-review →] epic →
36
- epic-review → architecture → architecture-review → ui-design → ui-design-review → stories →
37
- stories-review` (then `ready-for-build`); the bracketed `analysis` prefix is present only when
38
- `yad-analysis` seeded it. Always render exactly the steps present in `steps[]`.
35
+ `currentStep` with `→`. The gating chain is `[analysis → analysis-review →] epic → epic-review →
36
+ architecture → architecture-review → ui-design → ui-design-review → stories → stories-review` →
37
+ **`ready-for-build`** (the bracketed `analysis` prefix is present only when `yad-analysis` seeded it).
38
+ `test-cases → test-cases-review` is a **parallel, non-blocking track**: it opens when `stories-review`
39
+ passes and runs alongside the build half, so when `currentStep` is `ready-for-build` the `test-cases`
40
+ step may still be `in_progress`/`in_review` — show its status, and note "parallel" so it is clear it
41
+ does not gate the build. Always render exactly the steps present in `steps[]`.
39
42
  3. **Active gate** — for the `currentStep` (if it is a `review+approve` step), compute and show:
40
43
  - the reviewer rule in force — **base** (`owner + 1 reviewer`), **escalated** (list the required
41
44
  domains), or **per-repo** for `stories-review` (list each repo needing sign-off),
@@ -97,7 +97,9 @@ In `state.json`: set `stories.status: "done"`, set `stories-review.status: "in_r
97
97
  ### Step 7 — Stop at the gate (do NOT advance)
98
98
  Report: the story IDs created, the repos each touches, and that the next action is **review** via
99
99
  `yad-review-gate`. Note that this review routes **per-repo reviewers**: owner + 1 reviewer **plus**, for
100
- each repo appearing in any story's `repos`, a `domain-owner` approval for that repo. **Never record
100
+ each repo appearing in any story's `repos`, a `domain-owner` approval for that repo. When this gate
101
+ passes the epic becomes **`ready-for-build`** — the build half can start **and** the parallel
102
+ **`test-cases`** track opens for the tester (`yad-test-cases`); the two run at the same time. **Never record
101
103
  approval here.** Front states do not auto-advance. When the hub has a platform, the gate opens a review
102
104
  PR on the hub (via `yad-hub-bridge`, with a `domain:<repo>` label per touched repo) and
103
105
  `yad-review-gate action: sync` pulls platform approvals/comments into the ledger; otherwise the review
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: yad-test-cases
3
+ description: 'Front state 9 of the gated SDLC — a PARALLEL, non-blocking track. Opens when the stories gate passes (the epic is already ready-for-build, so the build half can start at the same time) and runs alongside implementation. With the test architect (Murat), author test-cases.md for the approved stories, and — when a testing tool is connected — generate/link the actual automation tests in it; otherwise produce the test-case artifact only. Reads epic + architecture + contract + UI + stories as input. Never auto-advances — hands off to the team review gate. Use when the user says "author the test cases" or after the stories gate passes.'
4
+ ---
5
+
6
+ # SDLC — Author Test Cases (front state 9 — parallel, non-blocking)
7
+
8
+ **Goal:** Produce a human-authored, AI-assisted `test-cases.md` for an approved epic — the risk-based
9
+ test cases that cover the stories' acceptance criteria — **and**, when a testing tool is connected, the
10
+ **actual automation tests** inside the connected code repo(s), linked back from the artifact. This is a
11
+ **front state**: human-authored with AI assist, **never auto-advances**. When the test cases are
12
+ drafted, control passes to `yad-review-gate` (base rule: owner + 1 reviewer).
13
+
14
+ **This step does NOT block the build half.** It opens when the **stories** gate passes — at which point
15
+ the epic is already `ready-for-build`, so implementation (`yad-spec` → `yad-implement` → …) can start
16
+ **at the same time** the tester works here. The test-cases track is driven by its own step `status`
17
+ (it opens to `in_progress` when `stories-review` passes) and its review **never moves `currentStep`
18
+ away from `ready-for-build`**, so the two run in parallel.
19
+
20
+ Test work is shaped by the **test architect** lens — **Murat** (`bmad-tea`), driving
21
+ `bmad-testarch-test-design` for the cases and `bmad-testarch-automate` for the automation. The
22
+ automation is materialized in the **testing tool connected via `yad-connect-testing`**
23
+ (`.sdlc/testing.json`), reached through its MCP. When a tool is connected the lens **generates** tests
24
+ into it (or **links** an existing suite and reads it back); when none is connected, the step degrades to
25
+ the Markdown artifact only — the testing tool is additive, exactly like the design tool.
26
+
27
+ ## Conventions
28
+
29
+ - `{project-root}` resolves from the project working directory.
30
+ - Artifacts live under `{project-root}/epics/EP-<slug>/` (build plan §6).
31
+ - The connected testing tool is recorded in `{project-root}/.sdlc/testing.json` (`config.yaml`
32
+ `testing`), written by `yad-connect-testing`. The per-epic case→test map is `test-links.json`
33
+ (Step 4b).
34
+ - Speak in the configured `communication_language`; write documents in `document_output_language`.
35
+
36
+ ## On Activation
37
+
38
+ ### Step 1 — Resolve the epic and check the track
39
+ Resolve the `EP-<slug>` (ask if not provided). Read `.sdlc/state.json`. Only proceed when the
40
+ **`test-cases` step's `status == "in_progress"`** — it opens when `stories-review` passes (the epic is
41
+ already `ready-for-build` by then; `currentStep` stays there because this is a parallel track, so do
42
+ **not** gate on `currentStep`). If `test-cases` is still `blocked`, the stories review has not passed —
43
+ stop and point the user at `yad-status` / the gate.
44
+
45
+ ### Step 1b — Open the authoring branch
46
+ Open the test-cases authoring branch `test-cases/EP-<slug>` per the shared procedure
47
+ (`../yad-epic/references/state-schema.md` → "Authoring branches"): git-safe (skip with a note if
48
+ `{project-root}` is not a git work tree), check out the branch if it exists, else create it from the
49
+ hub's default branch. Author and commit `test-cases.md` on it. This is **distinct** from the bridge's
50
+ `review/…` branch.
51
+
52
+ ### Step 2 — Read inputs
53
+ Read `epic.md` (user-level acceptance signals, scope), `architecture.md` (flows, components by repo),
54
+ `contract.md` (the shared surface under test), `ui-design.md` (screens/states the tests exercise), and
55
+ **all** approved `stories/EP-<slug>-S0N.md`. Each story's **acceptance criteria are the source of truth**
56
+ for the cases — the test cases must collectively verify every story's criteria.
57
+
58
+ ### Step 2b — Load existing-code context (make the brain code-aware)
59
+ Read the registry `{project-root}/.sdlc/repos.json` (`config.yaml` `code_context`). For **each repo in
60
+ `epic.repos`**, load the code-map `{project-root}/.sdlc/code-context/<repo>/code-map.md` so the
61
+ automation **targets real existing endpoints/components and reuses existing fixtures** rather than
62
+ inventing parallel ones.
63
+
64
+ - **Greenfield-safe:** if `repos.json` is absent/empty, note "no repos connected" and proceed.
65
+ - **Staleness:** if a repo's current HEAD ≠ its registry `syncedHead`, warn and suggest
66
+ `yad repo refresh <repo>` (a human decision — flag and stop, never auto-refresh); stamp
67
+ `code-context: stale` in the frontmatter.
68
+ - **Traceability:** record the loaded maps in the `test-cases.md` `code-context:` frontmatter field.
69
+
70
+ ### Step 3 — Author the test cases (assist: test architect)
71
+ Adopt the **test architect** lens (`bmad-tea`, Murat), driving `bmad-testarch-test-design`. For each
72
+ story / user flow shape risk-based test cases:
73
+
74
+ - **Risk assessment** — categorize and score what can fail (probability × impact); depth scales with
75
+ impact (Murat's "risk-based testing" principle).
76
+ - **Coverage plan** — assign each case a priority **P0 (critical) / P1 (high) / P2 (medium) / P3 (low)**
77
+ and a level, preferring the lowest useful level (unit > integration > E2E).
78
+ - **Entry/exit criteria** and any **NFR** thresholds (security, performance, reliability) in scope.
79
+ - Each case: a stable label, the story it covers, preconditions, steps, and expected result.
80
+
81
+ ### Step 3b — Materialize the automation in the connected tool (generate or link)
82
+ Read `{project-root}/.sdlc/testing.json` (`config.yaml` `testing.registry`). Decide the path:
83
+
84
+ - **No tool / `tool: "none"` / `source: "unavailable"`** (or the file is absent): **degrade** — author
85
+ the Markdown artifact only and record `testing: none` in the frontmatter with a one-line note
86
+ (mirrors the `design: none` degrade). Skip to Step 4.
87
+ - **A tool is connected and its MCP is available:** adopt the `test architect` lens and, using the
88
+ provider recorded in `testing.json` (Playwright via a Playwright MCP, Cypress/pytest via theirs) drive
89
+ `bmad-testarch-automate`:
90
+ - **Generate** — when the provider is write-capable, author one automation test per high-priority
91
+ (P0/P1) case into the connected code repo(s) for the repos in `epic.repos`, reusing the code-maps
92
+ (Step 2b) and existing fixtures so tests target built endpoints/components, then run them via the MCP
93
+ to confirm they execute.
94
+ - **Link** — when the user points at an existing suite (or the provider is read-only), reference it and
95
+ **read the tests back** so `test-cases.md` reflects the real suite.
96
+
97
+ Capture each test's `name`, `repo`, `level`, `path`, and `url`. Record which direction was used
98
+ (`generated | linked`). Honest-capability rule: a read-only MCP supports **link** only — never claim a
99
+ test was generated that the provider cannot produce. See
100
+ `../yad-connect-testing/references/testing-context.md`.
101
+
102
+ ### Step 4 — Write the test-cases artifact
103
+ Write `{project-root}/epics/EP-<slug>/test-cases.md` using EXACTLY this template:
104
+
105
+ ```markdown
106
+ ---
107
+ id: EP-<slug>
108
+ epic: EP-<slug>
109
+ artifact: test-cases
110
+ status: draft
111
+ owner: <inherit from epic.md owner> # the epic owner carries through; not retyped
112
+ repos: [<inherit from epic>]
113
+ code-context: { repos: [], loaded: <YYYY-MM-DD or none> } # code-maps that informed the tests (Step 2b)
114
+ testing: <none | { tool: <playwright|cypress|pytest|…>, direction: <generated|linked>, suite: <url/path>, tests: <N> }> # the connected testing tool (Step 3b)
115
+ ---
116
+
117
+ ## Test strategy & risk
118
+ <!-- risk assessment (category, probability, impact, score), entry/exit criteria, NFR thresholds in scope -->
119
+
120
+ ## Test cases
121
+ <!-- one row/subsection per case: id, story covered, priority (P0–P3), level, preconditions, steps, expected -->
122
+
123
+ ## Coverage & traceability
124
+ <!-- story -> case map; confirm every story's acceptance criteria are covered -->
125
+
126
+ ## Automation (<tool>)
127
+ <!-- omit this section when testing: none. one row per automation test, linking to it in the repo.
128
+ mirrors test-links.json (Step 4b). -->
129
+ <!-- - <Case id> -> <repo>:<test path> (<level>) — <url> -->
130
+ ```
131
+
132
+ ### Step 4b — Write the test-links map (when a tool was used)
133
+ When Step 3b generated or linked automation, write the machine-readable case→test map to
134
+ `{project-root}/epics/EP-<slug>/.sdlc/test-links.json` (sibling of `contract-lock.json` /
135
+ `design-links.json`):
136
+
137
+ ```json
138
+ {
139
+ "tool": "playwright",
140
+ "suite": "tests/playwright.config.ts",
141
+ "generatedAt": "<YYYY-MM-DD>",
142
+ "direction": "generated | linked",
143
+ "tests": [
144
+ { "case": "TC-01", "story": "EP-<slug>-S01", "repo": "backend", "level": "e2e",
145
+ "path": "tests/inquiry.spec.ts", "url": "<repo url to the test>" }
146
+ ],
147
+ "source": "playwright-mcp"
148
+ }
149
+ ```
150
+
151
+ Keep the `## Automation (<tool>)` section of `test-cases.md` in step with this file. When Step 3b
152
+ degraded (`testing: none`), do **not** write `test-links.json`.
153
+
154
+ ### Step 5 — Advance the authoring step (NOT the gate)
155
+ In `state.json`: set `test-cases.status: "done"` and set `test-cases-review.status: "in_review"`. **Leave
156
+ `currentStep` at `ready-for-build`** — this is the parallel track; moving `currentStep` would pull it
157
+ back from the build half. Write `state.json`. Do **not** touch `approvals.json`.
158
+
159
+ ### Step 6 — Stop at the gate (do NOT advance)
160
+ Report: the path to `test-cases.md`, the connected testing tool and what it produced (e.g. "Playwright —
161
+ 6 tests generated", the suite path + `test-links.json` path, or "no testing tool — artifacts-only"), that
162
+ the build half may already be underway in parallel, and that the next action is **review** via
163
+ `yad-review-gate` (base rule: owner + 1 reviewer). **Never record approval here.** Front states do not
164
+ auto-advance. When the hub has a platform, the gate opens a review
165
+ PR on the hub (via `yad-hub-bridge`) and `yad-review-gate action: sync` pulls platform approvals/comments
166
+ into the ledger; otherwise the review is recorded file-only.
167
+
168
+ ## Reference
169
+ - Test-cases frontmatter, body template, and the `test-links.json` schema: `references/test-cases-schema.md`.
170
+ - State schema and field meanings: `../yad-epic/references/state-schema.md`.
171
+ - Connecting a testing tool (Playwright, pluggable) + generate-vs-link recipes and the degrade path:
172
+ `../yad-connect-testing/SKILL.md` (+ `references/testing-context.md`).
173
+ - Connecting code repos + the code-context the brain reads: `../yad-connect-repos/SKILL.md`.
@@ -0,0 +1,70 @@
1
+ # Test-cases schema
2
+
3
+ The test cases authored at front state 9 are one Markdown file under `epics/EP-<slug>/`, named
4
+ `test-cases.md` (one per epic — mirrors `ui-design.md`, not a per-story folder). The optional automation
5
+ linkage is a sibling `test-links.json`.
6
+
7
+ ## Frontmatter
8
+
9
+ | Field | Values | Meaning |
10
+ |-------|--------|---------|
11
+ | `id` | `EP-<slug>` | The epic ID — the artifact is epic-level. |
12
+ | `epic` | `EP-<slug>` | Parent epic ID — the unbroken link back to the epic. |
13
+ | `artifact` | `test-cases` | Marks the artifact kind (mirrors `ui-design`). |
14
+ | `status` | `draft` \| `in_review` \| `approved` | Lifecycle within the test-cases gate. |
15
+ | `owner` | name | Inherited from `epic.md` `owner` (the single source — not retyped). |
16
+ | `repos` | subset of the epic's `repos` | Which repos the automation targets. |
17
+ | `code-context` | `{ repos: [<name@sha>], loaded: <date> }` | Optional. Which connected-repo code-maps anchored the tests (Step 2b). The `@sha` (a repo's `syncedHead`) is recommended so freshness is recorded but may be omitted; the SKILL template shows the empty placeholder `{ repos: [], loaded: <date or none> }`. `none` / `[]` when no repos are connected. |
18
+ | `testing` | `none` \| `{ tool, direction, suite, tests }` | The connected testing tool and what it produced (Step 3b). `none` when the step ran artifacts-only. |
19
+
20
+ ## Body
21
+
22
+ ```markdown
23
+ ## Test strategy & risk
24
+ <!-- risk assessment (category, probability, impact, score), entry/exit criteria, NFR thresholds -->
25
+
26
+ ## Test cases
27
+ <!-- one row/subsection per case: id, story covered, priority (P0–P3), level, preconditions, steps, expected -->
28
+
29
+ ## Coverage & traceability
30
+ <!-- story -> case map; every story's acceptance criteria must be covered -->
31
+
32
+ ## Automation (<tool>)
33
+ <!-- omit when testing: none. one row per automation test, linking to it in the repo. mirrors test-links.json -->
34
+ ```
35
+
36
+ ## `test-links.json` (sibling, when a tool was used)
37
+
38
+ Written by `yad-test-cases` Step 4b. Absent when the step ran artifacts-only (`testing: none`).
39
+
40
+ ```json
41
+ {
42
+ "tool": "playwright",
43
+ "suite": "tests/playwright.config.ts",
44
+ "generatedAt": "<YYYY-MM-DD>",
45
+ "direction": "generated | linked",
46
+ "tests": [
47
+ { "case": "TC-01", "story": "EP-<slug>-S01", "repo": "backend", "level": "e2e",
48
+ "path": "tests/inquiry.spec.ts", "url": "<repo url to the test>" }
49
+ ],
50
+ "source": "playwright-mcp"
51
+ }
52
+ ```
53
+
54
+ ## Rules
55
+
56
+ - **Cover every story.** The "Coverage & traceability" section must map each story's acceptance criteria
57
+ to at least one case — an unmapped criterion is a gap the reviewer should catch.
58
+ - **Priorities are risk-based.** P0 = critical (run on every commit) … P3 = low (on-demand); depth
59
+ scales with impact (Murat's principle).
60
+ - **Prefer the lowest useful level.** unit > integration > E2E when a case can be verified lower.
61
+ - **`repos` is a subset of `epic.repos`.** Automation cannot target a repo the epic does not declare.
62
+ - **Single-file, not a folder.** `test-cases.md` resolves through the gate's default content-hash path
63
+ (the file's bytes), so the review gate, revoke-on-change, and review-PR machinery work unchanged.
64
+ - **Automation is additive.** When no testing tool is connected, the step still produces a complete
65
+ `test-cases.md`; `testing: none` and no `test-links.json`.
66
+
67
+ ## Review routing (the test-cases gate)
68
+
69
+ The test-cases gate uses the **base rule** (owner + 1 reviewer) — it is not escalated. The natural
70
+ reviewer is the test architect / QA owner, but the gate predicate requires only owner + 1.