yadflow 3.19.0-next.2 → 4.0.0-next.3
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/CHANGELOG.md +371 -0
- package/README.md +160 -22
- package/bin/commands.mjs +46 -0
- package/bin/yad.mjs +506 -117
- package/cli/artifact-status.mjs +30 -11
- package/cli/capture.mjs +417 -0
- package/cli/checkpoint.mjs +47 -27
- package/cli/claims.mjs +165 -0
- package/cli/codeowners-command.mjs +170 -0
- package/cli/codeowners.mjs +397 -0
- package/cli/commit.mjs +13 -9
- package/cli/dial.mjs +183 -0
- package/cli/docs.mjs +88 -32
- package/cli/doctor.mjs +1682 -90
- package/cli/epic-state.mjs +3460 -211
- package/cli/epic.mjs +506 -0
- package/cli/errors.mjs +3 -0
- package/cli/fold.mjs +247 -0
- package/cli/gate-local.mjs +296 -0
- package/cli/gate.mjs +977 -183
- package/cli/history.mjs +556 -0
- package/cli/hook.mjs +264 -53
- package/cli/hubcommit.mjs +9 -19
- package/cli/index-command.mjs +87 -0
- package/cli/ledger.mjs +54 -4
- package/cli/lib.mjs +161 -9
- package/cli/manifest.mjs +376 -38
- package/cli/migrate.mjs +683 -52
- package/cli/mode.mjs +170 -0
- package/cli/next.mjs +365 -86
- package/cli/openpr.mjs +193 -34
- package/cli/owners.mjs +266 -0
- package/cli/people.mjs +657 -0
- package/cli/plan.mjs +466 -125
- package/cli/platform.mjs +109 -128
- package/cli/product-index.mjs +287 -0
- package/cli/protection.mjs +706 -0
- package/cli/reconcile.mjs +40 -12
- package/cli/repo-publish.mjs +24 -26
- package/cli/repo.mjs +23 -14
- package/cli/report.mjs +24 -14
- package/cli/review.mjs +19 -22
- package/cli/riskmap-command.mjs +289 -0
- package/cli/riskmap.mjs +373 -0
- package/cli/setup.mjs +127 -279
- package/cli/ship.mjs +6 -5
- package/cli/skill.mjs +180 -0
- package/cli/skip.mjs +211 -30
- package/cli/thread.mjs +41 -16
- package/cli/tidy.mjs +18 -18
- package/cli/update-commit.mjs +21 -21
- package/cli/usage.mjs +115 -109
- package/package.json +3 -3
- package/skills/sdlc/config.yaml +149 -70
- package/skills/sdlc/module-help.csv +24 -24
- package/skills/yad-analysis/SKILL.md +121 -59
- package/skills/yad-architecture/SKILL.md +30 -18
- package/skills/yad-architecture/references/contract-format.md +8 -5
- package/skills/yad-backfill/SKILL.md +10 -4
- package/skills/yad-backfill/references/backfill.md +8 -1
- package/skills/yad-backfill/templates/checks/backfill-check.sh +10 -2
- package/skills/yad-change/SKILL.md +119 -42
- package/skills/yad-change/references/triage.md +42 -27
- package/skills/yad-checks/SKILL.md +68 -35
- package/skills/yad-checks/references/check-gates.md +310 -85
- package/skills/yad-checks/templates/checks/commit-message.sh +17 -3
- package/skills/yad-checks/templates/checks/contract-check.sh +130 -9
- package/skills/yad-checks/templates/checks/epic-open.sh +2 -2
- package/skills/yad-checks/templates/checks/ledger-guard.sh +55 -8
- package/skills/yad-checks/templates/checks/lineage-check.sh +23 -9
- package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +1 -1
- package/skills/yad-checks/templates/checks/risk-map-check.sh +438 -0
- package/skills/yad-checks/templates/checks/verified-commits.sh +20 -46
- package/skills/yad-checks/templates/github/yad-checks.yml +13 -2
- package/skills/yad-checks/templates/github/yad-hub-checks.yml +5 -5
- package/skills/yad-checks/templates/github/yad-update-guard.yml +7 -5
- package/skills/yad-checks/templates/github/yad-verified-commits.yml +4 -4
- package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +10 -1
- package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +5 -5
- package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +3 -3
- package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +91 -0
- package/skills/yad-checks/templates/hooks/ledger-guard.sh +37 -6
- package/skills/yad-checks/templates/hooks/yad-capture.sh +53 -0
- package/skills/yad-commit/SKILL.md +4 -4
- package/skills/yad-connect-design/SKILL.md +5 -5
- package/skills/yad-connect-design/references/design-context.md +1 -1
- package/skills/yad-connect-design/references/design-registry.md +2 -2
- package/skills/yad-connect-docs/SKILL.md +11 -11
- package/skills/yad-connect-docs/references/docs-registry.md +1 -1
- package/skills/yad-connect-learning/SKILL.md +5 -5
- package/skills/yad-connect-learning/references/learning-registry.md +2 -2
- package/skills/yad-connect-repos/SKILL.md +66 -45
- package/skills/yad-connect-repos/references/code-context.md +4 -4
- package/skills/yad-connect-repos/references/hub-config.md +47 -51
- package/skills/yad-connect-repos/references/repos-registry.md +8 -7
- package/skills/yad-connect-repos/references/risk-map.md +81 -0
- package/skills/yad-connect-testing/SKILL.md +5 -5
- package/skills/yad-connect-testing/references/testing-context.md +3 -4
- package/skills/yad-connect-testing/references/testing-registry.md +2 -2
- package/skills/yad-defects/SKILL.md +7 -7
- package/skills/yad-discovery/SKILL.md +131 -94
- package/skills/yad-discovery/references/discovery-schema.md +22 -6
- package/skills/yad-discovery/references/foundation-schema.md +374 -0
- package/skills/yad-docs/SKILL.md +13 -8
- package/skills/yad-docs/references/data-mapping.md +9 -7
- package/skills/yad-docs/templates/app/package-lock.json +3 -3
- package/skills/yad-docs-overview/SKILL.md +30 -15
- package/skills/yad-docs-overview/references/pipeline-model.md +33 -20
- package/skills/yad-docs-sync/SKILL.md +10 -5
- package/skills/yad-docs-sync/references/staleness.md +8 -7
- package/skills/yad-engineer-review/SKILL.md +81 -17
- package/skills/yad-engineer-review/references/ship-and-record.md +17 -8
- package/skills/yad-epic/SKILL.md +173 -92
- package/skills/yad-epic/references/state-schema.md +610 -94
- package/skills/yad-hub-bridge/SKILL.md +57 -38
- package/skills/yad-hub-bridge/references/bridge.md +94 -67
- package/skills/yad-hub-bridge/references/login-roster.md +163 -70
- package/skills/yad-hub-bridge/templates/checks/hub-route.sh +22 -19
- package/skills/yad-hub-bridge/templates/github/yad-gate-sync.yml +34 -14
- package/skills/yad-hub-bridge/templates/gitlab/gitlab-ci.include-root.yml +2 -2
- package/skills/yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml +21 -11
- package/skills/yad-implement/SKILL.md +27 -13
- package/skills/yad-implement/references/implement-conventions.md +2 -2
- package/skills/yad-learn/SKILL.md +9 -9
- package/skills/yad-learn/references/learning-state.md +2 -2
- package/skills/yad-open-pr/SKILL.md +61 -26
- package/skills/yad-pair-review/SKILL.md +7 -5
- package/skills/yad-pair-review/references/session-state.md +1 -1
- package/skills/yad-pr-template/SKILL.md +47 -26
- package/skills/yad-pr-template/references/risk-routing.md +97 -24
- package/skills/yad-pr-template/templates/checks/pr-template.sh +34 -11
- package/skills/yad-pr-template/templates/checks/pr-title.sh +32 -9
- package/skills/yad-pr-template/templates/checks/risk-route.sh +107 -14
- package/skills/yad-pr-template/templates/github/pull_request_template.md +7 -5
- package/skills/yad-pr-template/templates/gitlab/merge_request_templates/Default.md +7 -5
- package/skills/yad-pr-template/templates/hub/github/pull_request_template.md +14 -13
- package/skills/yad-pr-template/templates/hub/gitlab/merge_request_templates/Default.md +14 -12
- package/skills/yad-reconcile/SKILL.md +3 -3
- package/skills/yad-report/SKILL.md +5 -5
- package/skills/yad-review-companion/SKILL.md +6 -3
- package/skills/yad-review-gate/SKILL.md +203 -93
- package/skills/yad-review-gate/references/gating.md +232 -54
- package/skills/yad-run/SKILL.md +81 -51
- package/skills/yad-run/references/run-loop.md +61 -39
- package/skills/yad-ship/SKILL.md +15 -11
- package/skills/yad-spec/SKILL.md +21 -6
- package/skills/yad-spec/references/spec-handoff.md +17 -5
- package/skills/yad-status/SKILL.md +115 -50
- package/skills/yad-stories/SKILL.md +37 -21
- package/skills/yad-stories/references/story-schema.md +7 -6
- package/skills/yad-stub/SKILL.md +58 -47
- package/skills/yad-sync-repos/SKILL.md +2 -2
- package/skills/yad-test-cases/SKILL.md +32 -23
- package/skills/yad-test-cases/references/test-cases-schema.md +7 -4
- package/skills/yad-timeline/SKILL.md +8 -7
- package/skills/yad-ui/SKILL.md +41 -18
- package/cli/roster.mjs +0 -164
- package/skills/sdlc/install.sh +0 -68
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-stories
|
|
3
|
-
description: 'Shape step 7 of the gated SDLC. With the pm, break the approved epic into user stories, each tagged with the repos that must implement it. Assigns zero-padded EP-<slug>-S0N IDs and writes one file per story under stories/. Reads epic + architecture + contract + UI as input. Never auto-advances — hands off to the team review gate (
|
|
3
|
+
description: 'Shape step 7 of the gated SDLC. With the pm, break the approved epic into user stories, each tagged with the repos that must implement it. Assigns zero-padded EP-<slug>-S0N IDs and writes one file per story under stories/. Reads epic + architecture + contract + UI as input. Never auto-advances — hands off to the team review gate (an ordinary approval-count gate). Use when the user says "author the stories" or after the UI gate passes.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Author Stories (Shape step 7)
|
|
@@ -8,8 +8,8 @@ description: 'Shape step 7 of the gated SDLC. With the pm, break the approved ep
|
|
|
8
8
|
**Goal:** Break an approved epic into human-authored, AI-assisted user stories, each with a stable
|
|
9
9
|
`EP-<slug>-S0N` ID and a `repos` tag listing which repos must implement it. This is a **Shape step**:
|
|
10
10
|
human-authored with AI assist, **never auto-advances**. When the stories are drafted, control passes
|
|
11
|
-
to `yad-review-gate`,
|
|
12
|
-
|
|
11
|
+
to `yad-review-gate`, an ordinary count gate: at least 1 distinct approver, who should not be the author. The stories'
|
|
12
|
+
`repos` tags still say which repos a story touches, and the review PR is labelled with those repos.
|
|
13
13
|
|
|
14
14
|
There is **no `sm` agent** (Phase 0 Deviation 1): the `pm` lens breaks down the epic; the `pm` or
|
|
15
15
|
`architect` lens prepares each story's detail. IDs are engine-assigned and never renamed.
|
|
@@ -19,7 +19,7 @@ There is **no `sm` agent** (Phase 0 Deviation 1): the `pm` lens breaks down the
|
|
|
19
19
|
- `{project-root}` resolves from the project working directory.
|
|
20
20
|
- Stories live under `{project-root}/epics/EP-<slug>/stories/` (build plan §6).
|
|
21
21
|
- Story files are named `EP-<slug>-S0N.md` (zero-padded, e.g. `EP-checkout-S01.md`).
|
|
22
|
-
- Speak in the
|
|
22
|
+
- Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write documents in `document_output_language`.
|
|
23
23
|
|
|
24
24
|
## On Activation
|
|
25
25
|
|
|
@@ -37,7 +37,8 @@ This passes when `stories` is the next runnable step per the state sequence —
|
|
|
37
37
|
Open the stories authoring branch `stories/EP-<slug>` per the shared procedure
|
|
38
38
|
(`../yad-epic/references/state-schema.md` → "Authoring branches"): git-safe (skip with a note
|
|
39
39
|
if `{project-root}` is not a git work tree), check out the branch if it exists, else create it from the
|
|
40
|
-
|
|
40
|
+
Product's default branch. Author the story files under `stories/` on it, and end the step with `yad fold EP-<slug> stories` — the
|
|
41
|
+
one commit the step keeps (E44). This is **distinct**
|
|
41
42
|
from the verified ledger's `review/…` branch.
|
|
42
43
|
|
|
43
44
|
### Step 2 — Read inputs
|
|
@@ -48,7 +49,18 @@ must collectively satisfy the epic's acceptance signals and stay within the cont
|
|
|
48
49
|
- **UI-optional-safe:** `ui-design.md` may be absent — the `ui-design` step is optional and can be
|
|
49
50
|
marked N/A for an epic with no user-facing surface (state.json shows it `skipped`). When there is no
|
|
50
51
|
UI design, proceed without UI screens; the epic's acceptance signals + contract remain the source of
|
|
51
|
-
truth for the stories.
|
|
52
|
+
truth for the stories. If state.json shows it `deferred` instead, the UI **will** come later: write the
|
|
53
|
+
stories so they do not assume there are no screens, and note in each story that touches the UI that
|
|
54
|
+
its screens are still to be designed.
|
|
55
|
+
- **Short-lane-safe:** `architecture.md` and `contract.md` may BOTH be absent, and on the `chore` and
|
|
56
|
+
`spike` routes they always are — those lanes carry no architecture step, so there is no locked
|
|
57
|
+
contract for this epic. Read `state.json`'s `profile` key first — an epic seeded before file shape 6
|
|
58
|
+
has no such key, so fall back to what its `steps[]` actually contains, which is the real answer
|
|
59
|
+
either way. On a short lane, write the stories
|
|
60
|
+
from `epic.md` alone and say so in each story's "Contract & design touchpoints" section. Because
|
|
61
|
+
there is no lock, a story on a short lane **must not change the shared cross-repo surface**: if the
|
|
62
|
+
work turns out to need that, stop and say so — the epic belongs on `classic`, which has the
|
|
63
|
+
architecture gate that locks the surface.
|
|
52
64
|
|
|
53
65
|
### Step 2b — Load existing-code context (make the brain code-aware)
|
|
54
66
|
Read the registry `{project-root}/.sdlc/repos.json` (`config.yaml` `code_context`). For **each repo in
|
|
@@ -63,7 +75,7 @@ Phase 3 build (Spec Kit per repo) accurate anchors instead of invented ones.
|
|
|
63
75
|
- **Traceability:** record the loaded maps in each story's `code-context:` frontmatter field.
|
|
64
76
|
|
|
65
77
|
### Step 3 — Break down the epic (assist: pm)
|
|
66
|
-
Adopt the **pm** lens
|
|
78
|
+
Adopt the **pm** lens. Decompose the epic into the smallest set of
|
|
67
79
|
independently reviewable, independently buildable stories. For each story decide which repos it touches
|
|
68
80
|
(must be a subset of the epic's `repos`). Prefer stories scoped to a clear slice of user value.
|
|
69
81
|
|
|
@@ -105,31 +117,35 @@ As a <role>, I want <capability>, so that <outcome>.
|
|
|
105
117
|
**verified mode** is `platform` set AND `ledger: "verified"` — or, on a project that has not run `yad migrate` yet, `bridge_enabled` (or legacy `bridge`) `true`. `ledger` wins whenever it is present.
|
|
106
118
|
|
|
107
119
|
**verified mode — do NOT write `state.json`.** The ledger is CI-owned: the `ledger-guard` check rejects
|
|
108
|
-
any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,hub-prs}.json` or
|
|
120
|
+
any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,product-prs,hub-prs}.json` or
|
|
109
121
|
`epics/*/reviews/*.md`, `yad gate open` deliberately skips this write for the same reason, and
|
|
110
122
|
`yad gate ci --merged` performs the whole transition when the review PR merges. Making the edit here
|
|
111
123
|
fails the gate if it rides the review PR, and desynchronises the ledger CI is about to rewrite if it
|
|
112
124
|
is pushed around the gate. Commit **the story files under `stories/` only** — nothing else
|
|
113
|
-
under `.sdlc/` — then hand off to `yad-review-gate`.
|
|
125
|
+
under `.sdlc/` (`yad fold EP-<slug> stories` takes exactly these) — then hand off to `yad-review-gate`.
|
|
114
126
|
|
|
115
|
-
**Otherwise — local, or a platform with no gate-sync CI —
|
|
116
|
-
`stories
|
|
117
|
-
|
|
127
|
+
**Otherwise — local, or a platform with no gate-sync CI — the engine makes this edit, not you.**
|
|
128
|
+
`yad gate open <epic> stories/` marks `stories-review` `in_review`, closes `stories` as `done`, and moves `currentStep` to the gate
|
|
129
|
+
— the same transition, from the one function that owns it (`markInReview`, `cli/epic-state.mjs`).
|
|
130
|
+
`yad-review-gate action: open` runs that command; hand off to it rather than editing the ledger here.
|
|
118
131
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
132
|
+
**With no platform configured** it writes the ledger and simply opens no PR, so this works offline.
|
|
133
|
+
**With a platform** the `review/EP-<slug>/stories` branch must already be **on origin** — the command
|
|
134
|
+
refuses and writes nothing otherwise. Cut it from the authoring branch and push it before handing off
|
|
135
|
+
(or run `yad open-pr` from that branch: it pushes the branch, then delegates).
|
|
136
|
+
|
|
137
|
+
Do **not** hand-edit `state.json`, and do **not** touch `approvals.json` — only real reviewers approve,
|
|
138
|
+
through the gate.
|
|
124
139
|
|
|
125
140
|
### Step 7 — Stop at the gate (do NOT advance)
|
|
126
141
|
Report: the story IDs created, the repos each touches, and that the next action is **review** via
|
|
127
|
-
`yad-review-gate`.
|
|
128
|
-
|
|
142
|
+
`yad-review-gate`. This review is an ordinary count gate: it passes with at least 1 distinct approver (who
|
|
143
|
+
should not be the author) and, with a platform, resolved threads and a merged review PR. It is not routed per repo, and it requests no
|
|
144
|
+
reviewers — the team asks them on the review PR itself. When this gate
|
|
129
145
|
passes the epic becomes **`ready-for-build`** — Build can start **and** the parallel
|
|
130
146
|
**`test-cases`** track opens for the tester (`yad-test-cases`); the two run at the same time. **Never record
|
|
131
|
-
approval here.** Shape steps do not auto-advance. When the
|
|
132
|
-
PR on the
|
|
147
|
+
approval here.** Shape steps do not auto-advance. When the Product has a platform, the gate opens a review
|
|
148
|
+
PR on the Product (via `yad-hub-bridge`, with a `domain:<repo>` label per touched repo) and
|
|
133
149
|
`yad-review-gate action: sync` pulls platform approvals/comments into the ledger; otherwise the review
|
|
134
150
|
is recorded local.
|
|
135
151
|
|
|
@@ -11,7 +11,7 @@ Each story authored at Shape step 7 is one Markdown file under `epics/EP-<slug>/
|
|
|
11
11
|
| `epic` | `EP-<slug>` | Parent epic ID — the unbroken link back to the epic. |
|
|
12
12
|
| `owner` | name | Inherited from `epic.md` `owner` (the single source — not retyped per story). Carries the responsible owner through to Build. |
|
|
13
13
|
| `status` | `draft` \| `in_review` \| `approved` | Story lifecycle within the stories gate. |
|
|
14
|
-
| `repos` | subset of the epic's `repos` | Which repos must implement this story. **
|
|
14
|
+
| `repos` | subset of the epic's `repos` | Which repos must implement this story. **Labels the stories review PR with the touched repos now and (Phase 3) decides where specs are scaffolded.** |
|
|
15
15
|
| `code-context` | `{ repos: [<name@sha>], loaded: <date> }` | Optional. Which connected-repo code-maps anchored "Notes for build" (Shape step 7 Step 2b). The `@sha` (a repo's `syncedHead`) is recommended so freshness is recorded but may be omitted; the SKILL templates show the empty placeholder `{ repos: [], loaded: <date or none> }`. `none` / `[]` when no repos are connected. |
|
|
16
16
|
|
|
17
17
|
## Body
|
|
@@ -38,9 +38,10 @@ As a <role>, I want <capability>, so that <outcome>.
|
|
|
38
38
|
- **Stay within the contract surface.** "Notes for build" should reference the contract elements a
|
|
39
39
|
story touches; a story may not invent cross-repo surface that `contract.md` does not define.
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## Review (the stories gate)
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
The stories gate is an ordinary count gate. It passes with at least 1 distinct approver (who should not
|
|
44
|
+
be the author) and, with a platform, resolved threads and a merged review PR. It is **not** routed per repo: no repo needs its own
|
|
45
|
+
sign-off, and no role is checked. The union of every story's `repos` still names the touched repos, and
|
|
46
|
+
the review PR carries a `domain:<repo>` label for each. The review PR requests no reviewers; the team
|
|
47
|
+
asks them on the PR itself.
|
package/skills/yad-stub/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-stub
|
|
3
|
-
description: 'Phase 6 brownfield helper — mint a STUB genesis epic for an already-built feature that has no epic in the
|
|
3
|
+
description: 'Phase 6 brownfield helper — mint a STUB genesis epic for an already-built feature that has no epic in the Product, so a defect/change can thread off it TODAY. In a brownfield repo not every feature has an epic; yad-change requires a real parent and dead-ends without one. This skill creates the smallest real thread anchor — a tiny epic.md (type feature under both names, thread:self, verified:false, stub:backfill-pending) + a seeded state.json + empty ledgers — never inventing behaviour. Defects thread off it immediately (gates pass, the bug list is derived by the thread rollup), and yad-backfill + its promote step later fill/flip it into a real feature epic. Never auto-advances. Use when the user says "there is no epic for this feature", "file a bug on a legacy feature", "anchor a brownfield feature", or when yad-change / yad-reconcile point here because a parent epic is missing.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Stub Genesis Epic (Phase 6, the brownfield thread anchor)
|
|
@@ -13,19 +13,19 @@ stub is a **thread anchor, not a spec**: it invents no behaviour. It stays `veri
|
|
|
13
13
|
|
|
14
14
|
This is the missing connective tissue in a brownfield adoption: `yad-backfill` produces a *draft spec in
|
|
15
15
|
the code repo*, and `yad-reconcile` *detects* shipped code with no owning epic — but neither mints the
|
|
16
|
-
|
|
16
|
+
Product epic a defect must thread from. `yad-stub` does exactly that, and only that.
|
|
17
17
|
|
|
18
18
|
## Conventions
|
|
19
19
|
|
|
20
|
-
- `{project-root}` resolves from the
|
|
20
|
+
- `{project-root}` resolves from the Product. Epic artifacts live under
|
|
21
21
|
`{project-root}/epics/EP-<slug>/` (build plan §6), exactly like a normal genesis epic.
|
|
22
22
|
- **A stub is NOT a reserved-empty id.** An epic in yad *is* a directory + `epic.md`; the tooling skips
|
|
23
23
|
any epic dir lacking `epic.md` (`threadEpics`) and `lineage-check` rejects a parent that is not a real
|
|
24
24
|
`epic.md`. So the stub is a real (if minimal) genesis — that is what makes it a valid parent.
|
|
25
|
-
- The stub is a **genesis** (`
|
|
25
|
+
- The stub is a **genesis** (type `feature` under both names, `thread == id`, no `parent`) — the root of a new thread.
|
|
26
26
|
Lineage frontmatter, the sentinel state, and the `stub`/`verified` fields are defined in
|
|
27
27
|
`../yad-epic/references/state-schema.md` (Phase 6 section).
|
|
28
|
-
- Speak in the
|
|
28
|
+
- Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write documents in `document_output_language`.
|
|
29
29
|
|
|
30
30
|
## Inputs
|
|
31
31
|
|
|
@@ -44,26 +44,43 @@ not a stub case either. Confirm the brownfield-no-epic situation with the human
|
|
|
44
44
|
|
|
45
45
|
### Step 2 — Derive the stub epic id (engine-assigned, never by hand)
|
|
46
46
|
Derive `EP-<slug>` where `slug` is **2–4 lowercase words** from the feature name (e.g.
|
|
47
|
-
`EP-legacy-billing`). `EP-discovery`
|
|
47
|
+
`EP-legacy-billing`). `EP-foundation` and `EP-discovery` are **reserved** (the Product level) — never use either. Check `epics/` for collisions;
|
|
48
48
|
append a distinguishing word if the slug exists. **The id is assigned once and never renamed** (a rename
|
|
49
49
|
breaks every downstream link) — so pick from the best-known feature name and accept it as permanent.
|
|
50
50
|
|
|
51
51
|
### Step 3 — Open the authoring branch
|
|
52
52
|
Open `epic/EP-<slug>` per the shared "Authoring branches" procedure
|
|
53
53
|
(`../yad-epic/references/state-schema.md`): git-safe (skip with a note if `{project-root}` is not a git
|
|
54
|
-
work tree), check out if it exists, else create from the
|
|
54
|
+
work tree), check out if it exists, else create from the Product's default branch.
|
|
55
55
|
|
|
56
56
|
### Step 4 — Write the stub `epic.md` (thread anchor — never invent behaviour)
|
|
57
57
|
Write `{project-root}/epics/EP-<slug>/epic.md` using EXACTLY this shape:
|
|
58
58
|
|
|
59
|
+
**Every key below is read by a machine, so write them BARE — no trailing `#` comment.** The
|
|
60
|
+
frontmatter readers keep the whole rest of the line, so a comment becomes part of the value: a
|
|
61
|
+
commented `stub:` stops `yad thread` and `yad-status` seeing the stub at all, and a commented `kind:`
|
|
62
|
+
makes `lineage-check` refuse every commit that links a story to this epic. What they mean:
|
|
63
|
+
|
|
64
|
+
| Key | Why it is here |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `title` | the feature's one-line name, as the code shows it (such as `Order checkout`) — the name a list of work items shows for this stub. No invented behaviour. One line; no `#` comment; no YAML block (`>` or `\|`); quotes are optional. A title that begins with `[` and ends with `]` goes in double quotes (write an inner `"` as `\"`), or it is read as a list. The full rules are the `title` row of the `epic.md` frontmatter table in `../yad-epic/references/state-schema.md`. Leave it empty if you cannot name it from the code: the stub is then shown by its id |
|
|
67
|
+
| `kind` + `type` | the work-item type, the same value under both names — `feature`, because a stub is a genesis / thread root and a valid parent for `lineage-check` |
|
|
68
|
+
| `thread` | `thread == id` for a genesis |
|
|
69
|
+
| `theme` | the optional grouping tag — one word or short phrase, in any language, shared by every epic in the group. Usually **empty here**: a stub is minted from code that already exists, not shaped in conversation, so there is normally nobody to say which group it is in. Fill it only if the user names one, and then copy an existing spelling exactly — `yad doctor` reports one theme spelled two ways, because two spellings group as two. One tag, never a list, and no `#` (the readers keep the whole rest of the line; the `#` the commands print is decoration on the screen) |
|
|
70
|
+
| `verified` | `false` — not a real, human-authored epic yet, a stub awaiting backfill |
|
|
71
|
+
| `stub` | `backfill-pending` — the honest marker; cleared on promote |
|
|
72
|
+
|
|
59
73
|
```markdown
|
|
60
74
|
---
|
|
61
75
|
id: EP-<slug>
|
|
76
|
+
title: <the feature's one-line name>
|
|
62
77
|
status: draft
|
|
63
|
-
kind: feature
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
kind: feature
|
|
79
|
+
type: feature
|
|
80
|
+
thread: EP-<slug>
|
|
81
|
+
theme:
|
|
82
|
+
verified: false
|
|
83
|
+
stub: backfill-pending
|
|
67
84
|
origin: brownfield
|
|
68
85
|
owner:
|
|
69
86
|
repos: [<the code repos this feature lives in>]
|
|
@@ -84,46 +101,40 @@ created: <YYYY-MM-DD>
|
|
|
84
101
|
|
|
85
102
|
Leave `owner` for the human to set. Set `repos` to the code repo(s) the feature lives in.
|
|
86
103
|
|
|
87
|
-
### Step 5 — Seed the stub
|
|
88
|
-
Create `{project-root}/epics/EP-<slug>/.sdlc/state.json`. It carries the top-level marker
|
|
89
|
-
`kind: "stub"` and the sentinel `currentStep: "backfill-pending"`, and the **same 10-step Shape chain**
|
|
90
|
-
as a normal epic (`yad-epic` Step 5) but with **every step `status: "blocked"`** — so the state is valid
|
|
91
|
-
(`validateState` needs a non-empty `steps` + a string `currentStep`) and `promote` can later "wake" it
|
|
92
|
-
into normal authoring with zero re-seeding.
|
|
93
|
-
|
|
94
|
-
```json
|
|
95
|
-
{
|
|
96
|
-
"schemaVersion": 1,
|
|
97
|
-
"epicId": "EP-<slug>",
|
|
98
|
-
"createdAt": "<YYYY-MM-DD>",
|
|
99
|
-
"kind": "stub",
|
|
100
|
-
"currentStep": "backfill-pending",
|
|
101
|
-
"steps": [
|
|
102
|
-
{ "id": "epic", "type": "author", "artifact": "epic.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
103
|
-
{ "id": "epic-review", "type": "review+approve", "artifact": "epic.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
104
|
-
{ "id": "architecture", "type": "author", "artifact": "architecture.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
105
|
-
{ "id": "architecture-review","type": "review+approve", "artifact": "architecture.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": ["contract"] },
|
|
106
|
-
{ "id": "ui-design", "type": "author", "artifact": "ui-design.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
107
|
-
{ "id": "ui-design-review", "type": "review+approve", "artifact": "ui-design.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
108
|
-
{ "id": "stories", "type": "author", "artifact": "stories/", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
109
|
-
{ "id": "stories-review", "type": "review+approve", "artifact": "stories/", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
110
|
-
{ "id": "test-cases", "type": "author", "artifact": "test-cases.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
|
|
111
|
-
{ "id": "test-cases-review", "type": "review+approve", "artifact": "test-cases.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] }
|
|
112
|
-
]
|
|
113
|
-
}
|
|
114
|
-
```
|
|
104
|
+
### Step 5 — Seed the stub ledger (a `backfill-pending` sentinel)
|
|
115
105
|
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
**Run the engine. Do not hand-write the chain.**
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
yad epic new EP-<slug> --stub
|
|
110
|
+
```
|
|
118
111
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
`
|
|
122
|
-
|
|
112
|
+
That writes `{project-root}/epics/EP-<slug>/.sdlc/state.json` with the **same 10-step `classic` chain**
|
|
113
|
+
a normal epic walks, but with **every step `todo`** (nobody is running it yet), the top-level marker
|
|
114
|
+
`kind: "stub"`, and
|
|
115
|
+
`currentStep: "backfill-pending"`. It also writes the empty `approvals.json` and `comments.json` and
|
|
116
|
+
the `reviews/` directory. It writes no `epic.md`, no branch and no commit, and it refuses an epic that
|
|
117
|
+
already has a `state.json`.
|
|
118
|
+
|
|
119
|
+
**Do NOT** write a `contract-lock.json` — a stub has no locked surface yet.
|
|
120
|
+
|
|
121
|
+
Notes:
|
|
122
|
+
- **`kind` and `type` are different things and a stub carries both.** `kind: "stub"` is the lifecycle
|
|
123
|
+
marker the engine keys off; `type: "feature"` is the work-item type, copied from `epic.md`. A stub is
|
|
124
|
+
always a `feature` and always `classic` — `--type` and `--profile` are refused here, because
|
|
125
|
+
`yad-backfill promote` wakes the chain at its `epic` step and upkeep leaves nothing to backfill.
|
|
126
|
+
- The blocked chain is what makes the state valid (`validateState` needs a non-empty `steps` and a
|
|
127
|
+
string `currentStep`) and what lets `promote` **wake** it into normal authoring with zero re-seeding.
|
|
128
|
+
- Nothing in the chain is runnable until then: `preconditionsMet` refuses every step of an anchor, and
|
|
129
|
+
`yad next` routes the epic to `yad-backfill` rather than to authoring.
|
|
130
|
+
- Commit the seed on this step's authoring branch; it reaches the Product's default branch through the
|
|
131
|
+
epic's **first** review PR/MR (or, for a stub, the PR that carries the stub itself). In verified mode
|
|
132
|
+
`ledger-guard` exempts a new epic's ledger — creation, not mutation (#162) — while every later change
|
|
133
|
+
to it stays CI's. See `../yad-epic/references/state-schema.md`, "Authoring branches".
|
|
123
134
|
|
|
124
135
|
### Step 6 — Stop; hand off (NO auto-advance)
|
|
125
136
|
Report the new `EP-<slug>`, that it is a **stub (backfill pending)**, and the two next moves:
|
|
126
|
-
- **File bugs now:** `yad-change` (`--parent EP-<slug>`, `
|
|
137
|
+
- **File bugs now:** `yad-change` (`--parent EP-<slug>`, type `defect|change`) — the defect threads off
|
|
127
138
|
the stub, its gates pass, and `yad thread EP-<slug>` lists it. A defect off a stub inherits only what
|
|
128
139
|
exists (the stub `epic.md`), re-authors its own stories/test-cases, and locks no contract (there is no
|
|
129
140
|
surface yet — see `../yad-change/SKILL.md`).
|
|
@@ -143,7 +154,7 @@ Shape steps do not auto-advance. Suggest `yad next EP-<slug>` (prints the backfi
|
|
|
143
154
|
- **You never implement directly against a stub.** It owns no `stories/`, so there is nothing to
|
|
144
155
|
implement against directly — real work threads off it as a change/defect epic (which has its own
|
|
145
156
|
stories). (This is a convention of the empty stub, not a hard gate: `lineage-check` passes a
|
|
146
|
-
`
|
|
157
|
+
`feature`-type genesis and `epic-open` treats a story-less epic as un-sealed, so neither blocks a
|
|
147
158
|
story mistakenly linked to the stub — keep the stub story-less.)
|
|
148
159
|
- **Never auto-advances.** This skill seeds the anchor and stops; humans thread changes and run backfill.
|
|
149
160
|
|
|
@@ -15,7 +15,7 @@ tree (branch + fast-forward). It writes **nothing** back to the registry.
|
|
|
15
15
|
|
|
16
16
|
## Conventions
|
|
17
17
|
|
|
18
|
-
- `{project-root}` resolves from the project working directory (the **
|
|
18
|
+
- `{project-root}` resolves from the project working directory (the **Product**).
|
|
19
19
|
- Registry: `{project-root}/.sdlc/repos.json` (project-wide; the same file `yad-connect-repos` writes).
|
|
20
20
|
Each repo entry supplies `path` (local path, relative to `{project-root}` or absolute) and
|
|
21
21
|
`default_branch` (the branch to land on).
|
|
@@ -64,7 +64,7 @@ Per repo: `switched to <branch>, pulled (ff)` / `already current` / `SKIPPED (..
|
|
|
64
64
|
so any repo whose `HEAD` now differs from its registry `syncedHead` has a **stale code-context pack** —
|
|
65
65
|
the command ends by pointing the human at `yad repo refresh` to repack (that is a separate human
|
|
66
66
|
decision; this skill never repacks or writes the registry). After the repack + AI code-map
|
|
67
|
-
regeneration, `yad repo refresh --push` publishes the refreshed code-maps + registry to the
|
|
67
|
+
regeneration, `yad repo refresh --push` publishes the refreshed code-maps + registry to the Product's
|
|
68
68
|
default branch as a `chore(hub): sync code-context … [skip ci]` audit commit.
|
|
69
69
|
|
|
70
70
|
## Hard rules
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-test-cases
|
|
3
|
-
description: 'Shape step 9 of the gated SDLC — a PARALLEL, non-blocking track. Opens when the stories gate passes (the epic is already ready-for-build, so Build can start at the same time) and runs alongside implementation. With the test architect
|
|
3
|
+
description: 'Shape step 9 of the gated SDLC — a PARALLEL, non-blocking track. Opens when the stories gate passes (the epic is already ready-for-build, so Build can start at the same time) and runs alongside implementation. With the test architect, 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
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Author Test Cases (Shape step 9 — parallel, non-blocking)
|
|
@@ -9,7 +9,7 @@ description: 'Shape step 9 of the gated SDLC — a PARALLEL, non-blocking track.
|
|
|
9
9
|
test cases that cover the stories' acceptance criteria — **and**, when a testing tool is connected, the
|
|
10
10
|
**actual automation tests** inside the connected code repo(s), linked back from the artifact. This is a
|
|
11
11
|
**Shape step**: human-authored with AI assist, **never auto-advances**. When the test cases are
|
|
12
|
-
drafted, control passes to `yad-review-gate` (base rule:
|
|
12
|
+
drafted, control passes to `yad-review-gate` (base rule: 1 distinct approver, who should not be the author).
|
|
13
13
|
|
|
14
14
|
**This step does NOT block Build.** It opens when the **stories** gate passes — at which point
|
|
15
15
|
the epic is already `ready-for-build`, so implementation (`yad-spec` → `yad-implement` → …) can start
|
|
@@ -17,8 +17,7 @@ the epic is already `ready-for-build`, so implementation (`yad-spec` → `yad-im
|
|
|
17
17
|
(it opens to `in_progress` when `stories-review` passes) and its review **never moves `currentStep`
|
|
18
18
|
away from `ready-for-build`**, so the two run in parallel.
|
|
19
19
|
|
|
20
|
-
Test work is shaped by the **test architect** lens
|
|
21
|
-
`bmad-testarch-test-design` for the cases and `bmad-testarch-automate` for the automation. The
|
|
20
|
+
Test work is shaped by the **test architect** lens, which designs the cases and writes the automation. The
|
|
22
21
|
automation is materialized in the **testing tool connected via `yad-connect-testing`**
|
|
23
22
|
(`.sdlc/testing.json`), reached through its MCP. When a tool is connected the lens **generates** tests
|
|
24
23
|
into it (or **links** an existing suite and reads it back); when none is connected, the step degrades to
|
|
@@ -31,7 +30,7 @@ the Markdown artifact only — the testing tool is additive, exactly like the de
|
|
|
31
30
|
- The connected testing tool is recorded in `{project-root}/.sdlc/testing.json` (`config.yaml`
|
|
32
31
|
`testing`), written by `yad-connect-testing`. The per-epic case→test map is `test-links.json`
|
|
33
32
|
(Step 4b).
|
|
34
|
-
- Speak in the
|
|
33
|
+
- Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write documents in `document_output_language`.
|
|
35
34
|
|
|
36
35
|
## On Activation
|
|
37
36
|
|
|
@@ -44,14 +43,15 @@ it passes. The check is track-aware: it keys off the `test-cases` step's predece
|
|
|
44
43
|
`currentStep` (this is a parallel track — `currentStep` stays at `ready-for-build`).
|
|
45
44
|
|
|
46
45
|
This passes once the `test-cases` step is runnable — its predecessor `stories-review` is `done` (so the
|
|
47
|
-
step has opened to `in_progress`) and `test-cases` is not already `done`. While it is still `
|
|
48
|
-
the stories review has not passed.
|
|
46
|
+
step has opened to `in_progress`) and `test-cases` is not already `done`. While it is still `todo` (or
|
|
47
|
+
`blocked`, in a file written before shape 7), the stories review has not passed.
|
|
49
48
|
|
|
50
49
|
### Step 1b — Open the authoring branch
|
|
51
50
|
Open the test-cases authoring branch `test-cases/EP-<slug>` per the shared procedure
|
|
52
51
|
(`../yad-epic/references/state-schema.md` → "Authoring branches"): git-safe (skip with a note if
|
|
53
52
|
`{project-root}` is not a git work tree), check out the branch if it exists, else create it from the
|
|
54
|
-
|
|
53
|
+
Product's default branch. Author `test-cases.md` on it, and end the step with `yad fold EP-<slug> test-cases` — the one commit the
|
|
54
|
+
step keeps (E44). This is **distinct** from the verified ledger's
|
|
55
55
|
`review/…` branch.
|
|
56
56
|
|
|
57
57
|
### Step 2 — Read inputs
|
|
@@ -62,7 +62,9 @@ for the cases — the test cases must collectively verify every story's criteria
|
|
|
62
62
|
|
|
63
63
|
- **UI-optional-safe:** `ui-design.md` may be absent — the `ui-design` step is optional and can be
|
|
64
64
|
marked N/A for a UI-less epic (state.json shows it `skipped`). When there is no UI design, there are
|
|
65
|
-
simply no screens to exercise; the stories' acceptance criteria remain the source of truth.
|
|
65
|
+
simply no screens to exercise; the stories' acceptance criteria remain the source of truth. If it
|
|
66
|
+
shows `deferred`, the screens are still to be designed: cover the stories' criteria now, and leave the
|
|
67
|
+
screen-level cases for when the UI design lands.
|
|
66
68
|
|
|
67
69
|
### Step 2b — Load existing-code context (make the brain code-aware)
|
|
68
70
|
Read the registry `{project-root}/.sdlc/repos.json` (`config.yaml` `code_context`). For **each repo in
|
|
@@ -77,11 +79,11 @@ inventing parallel ones.
|
|
|
77
79
|
- **Traceability:** record the loaded maps in the `test-cases.md` `code-context:` frontmatter field.
|
|
78
80
|
|
|
79
81
|
### Step 3 — Author the test cases (assist: test architect)
|
|
80
|
-
Adopt the **test architect** lens
|
|
82
|
+
Adopt the **test architect** lens. For each
|
|
81
83
|
story / user flow shape risk-based test cases:
|
|
82
84
|
|
|
83
85
|
- **Risk assessment** — categorize and score what can fail (probability × impact); depth scales with
|
|
84
|
-
impact (
|
|
86
|
+
impact (risk-based testing).
|
|
85
87
|
- **Coverage plan** — assign each case a priority **P0 (critical) / P1 (high) / P2 (medium) / P3 (low)**
|
|
86
88
|
and a level, preferring the lowest useful level (unit > integration > E2E).
|
|
87
89
|
- **Entry/exit criteria** and any **NFR** thresholds (security, performance, reliability) in scope.
|
|
@@ -95,8 +97,8 @@ Read `{project-root}/.sdlc/testing.json` (`config.yaml` `testing.registry`). Dec
|
|
|
95
97
|
(mirrors the `design: none` degrade). Skip to Step 4.
|
|
96
98
|
- **A tool is connected and its MCP is available:** adopt the `test architect` lens and, using the
|
|
97
99
|
provider recorded in `testing.json` (Playwright via a Playwright MCP, Cypress/pytest/Maestro via
|
|
98
|
-
theirs — Maestro authors mobile flows where Playwright has no reach)
|
|
99
|
-
|
|
100
|
+
theirs — Maestro authors mobile flows where Playwright has no reach) write the
|
|
101
|
+
automation:
|
|
100
102
|
- **Generate** — when the provider is write-capable, author one automation test per high-priority
|
|
101
103
|
(P0/P1) case into the connected code repo(s) for the repos in `epic.repos`, reusing the code-maps
|
|
102
104
|
(Step 2b) and existing fixtures so tests target built endpoints/components, then run them via the MCP
|
|
@@ -166,27 +168,34 @@ degraded (`testing: none`), do **not** write `test-links.json`.
|
|
|
166
168
|
**verified mode** is `platform` set AND `ledger: "verified"` — or, on a project that has not run `yad migrate` yet, `bridge_enabled` (or legacy `bridge`) `true`. `ledger` wins whenever it is present.
|
|
167
169
|
|
|
168
170
|
**verified mode — do NOT write `state.json`.** The ledger is CI-owned: the `ledger-guard` check rejects
|
|
169
|
-
any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,hub-prs}.json` or
|
|
171
|
+
any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,product-prs,hub-prs}.json` or
|
|
170
172
|
`epics/*/reviews/*.md`, `yad gate open` deliberately skips this write for the same reason, and
|
|
171
173
|
`yad gate ci --merged` performs the whole transition when the review PR merges. Making the edit here
|
|
172
174
|
fails the gate if it rides the review PR, and desynchronises the ledger CI is about to rewrite if it
|
|
173
175
|
is pushed around the gate. Commit the artifact set — **`test-cases.md` and, when a testing
|
|
174
|
-
tool was used, `.sdlc/test-links.json`** (artifact-side, not ledger; generated tests live in their
|
|
176
|
+
tool was used, `.sdlc/test-links.json`** (artifact-side, not ledger; `yad fold EP-<slug> test-cases` takes exactly these; generated tests live in their
|
|
175
177
|
own code repo, not here) — then hand off to `yad-review-gate`.
|
|
176
178
|
|
|
177
|
-
**Otherwise — local, or a platform with no gate-sync CI —
|
|
178
|
-
`test-cases.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
**Otherwise — local, or a platform with no gate-sync CI — the engine makes this edit, not you.**
|
|
180
|
+
`yad gate open <epic> test-cases.md` marks `test-cases-review` `in_review`, closes `test-cases` as `done`, and **leaves `currentStep` at `ready-for-build`** — this is the parallel track, and moving it would pull the epic back from Build
|
|
181
|
+
— the same transition, from the one function that owns it (`markInReview`, `cli/epic-state.mjs`).
|
|
182
|
+
`yad-review-gate action: open` runs that command; hand off to it rather than editing the ledger here.
|
|
183
|
+
|
|
184
|
+
**With no platform configured** it writes the ledger and simply opens no PR, so this works offline.
|
|
185
|
+
**With a platform** the `review/EP-<slug>/test-cases` branch must already be **on origin** — the command
|
|
186
|
+
refuses and writes nothing otherwise. Cut it from the authoring branch and push it before handing off
|
|
187
|
+
(or run `yad open-pr` from that branch: it pushes the branch, then delegates).
|
|
188
|
+
|
|
189
|
+
Do **not** hand-edit `state.json`, and do **not** touch `approvals.json` — only real reviewers approve,
|
|
190
|
+
through the gate.
|
|
182
191
|
|
|
183
192
|
### Step 6 — Stop at the gate (do NOT advance)
|
|
184
193
|
Report: the path to `test-cases.md`, the connected testing tool and what it produced (e.g. "Playwright —
|
|
185
194
|
6 tests generated", the suite path + `test-links.json` path, or "no testing tool — artifacts-only"), that
|
|
186
195
|
Build may already be underway in parallel, and that the next action is **review** via
|
|
187
|
-
`yad-review-gate` (base rule:
|
|
188
|
-
auto-advance. When the
|
|
189
|
-
PR on the
|
|
196
|
+
`yad-review-gate` (base rule: 1 distinct approver, who should not be the author). **Never record approval here.** Shape steps do not
|
|
197
|
+
auto-advance. When the Product has a platform, the gate opens a review
|
|
198
|
+
PR on the Product (via `yad-hub-bridge`) and `yad-review-gate action: sync` pulls platform approvals/comments
|
|
190
199
|
into the ledger; otherwise the review is recorded local.
|
|
191
200
|
|
|
192
201
|
## Reference
|
|
@@ -56,15 +56,18 @@ Written by `yad-test-cases` Step 4b. Absent when the step ran artifacts-only (`t
|
|
|
56
56
|
- **Cover every story.** The "Coverage & traceability" section must map each story's acceptance criteria
|
|
57
57
|
to at least one case — an unmapped criterion is a gap the reviewer should catch.
|
|
58
58
|
- **Priorities are risk-based.** P0 = critical (run on every commit) … P3 = low (on-demand); depth
|
|
59
|
-
scales with impact
|
|
59
|
+
scales with impact.
|
|
60
60
|
- **Prefer the lowest useful level.** unit > integration > E2E when a case can be verified lower.
|
|
61
61
|
- **`repos` is a subset of `epic.repos`.** Automation cannot target a repo the epic does not declare.
|
|
62
62
|
- **Single-file, not a folder.** `test-cases.md` resolves through the gate's default content-hash path
|
|
63
|
-
(the file
|
|
63
|
+
(the file without its frontmatter `status:` line), so the review gate, revoke-on-change, and review-PR machinery work unchanged.
|
|
64
64
|
- **Automation is additive.** When no testing tool is connected, the step still produces a complete
|
|
65
65
|
`test-cases.md`; `testing: none` and no `test-links.json`.
|
|
66
66
|
|
|
67
67
|
## Review routing (the test-cases gate)
|
|
68
68
|
|
|
69
|
-
The test-cases gate uses the **base rule
|
|
70
|
-
|
|
69
|
+
The test-cases gate uses the **base rule**: at least 1 distinct approver, who should not be the author.
|
|
70
|
+
The step carries no risk tags, so its full count is also 1. The natural reviewer is the test architect /
|
|
71
|
+
QA owner, but the gate names no role — any approver counts. yadflow does not itself check that the
|
|
72
|
+
approver is not the author (see `yad-review-gate`). The review PR requests no reviewers; the team asks
|
|
73
|
+
them on the PR itself.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-timeline
|
|
3
|
-
description: 'Phase 6 output enrichment (never a gate) — render a feature THREAD as an evolution view AND resolve its current truth. Walks the thread (genesis -> changes -> defects, linked by parent: frontmatter), renders the evolution as the vendored React/Vite/Tailwind shell HTML + a TIMELINE.md summary (each node:
|
|
3
|
+
description: 'Phase 6 output enrichment (never a gate) — render a feature THREAD as an evolution view AND resolve its current truth. Walks the thread (genesis -> changes -> defects, linked by parent: frontmatter), renders the evolution as the vendored React/Vite/Tailwind shell HTML + a TIMELINE.md summary (each node: type, what it re-authored vs inherited, ship events, contract re-lock history, open debt), and emits thread-resolved.md — the composed CURRENT-TRUTH map (the latest epic that owns each artifact + the resolved contract-lock hash). That resolved map is the source-of-truth AI/humans read to plan the next change, instead of a stale genesis epic. Degrades to markdown-only when no docs target is connected. Use when the user says "show the feature timeline", "how did this feature evolve", "resolve the current truth", or "render the thread".'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Feature Timeline + Current-Truth Resolver (Phase 6, output enrichment)
|
|
@@ -14,9 +14,9 @@ It is an **output enrichment**, exactly like `yad-docs` — **never a gate**: it
|
|
|
14
14
|
|
|
15
15
|
## Conventions
|
|
16
16
|
|
|
17
|
-
- `{project-root}` resolves from the
|
|
17
|
+
- `{project-root}` resolves from the Product.
|
|
18
18
|
- Reuses the **`yad-docs` shell** verbatim (`../yad-docs/templates/app/`) — generated `src/data/*.ts`,
|
|
19
|
-
themed
|
|
19
|
+
themed; build-only / markdown-only (`yad docs deploy` does not build `timeline-site/` yet)
|
|
20
20
|
(`.sdlc/docs.json`). The resolver part drives the **`yad thread` CLI** (`cli/thread.mjs`).
|
|
21
21
|
- The thread is **derived** from `parent:` frontmatter (no registry). The thread report lives under the
|
|
22
22
|
**genesis** epic (`thread == genesis id`).
|
|
@@ -32,7 +32,8 @@ It is an **output enrichment**, exactly like `yad-docs` — **never a gate**: it
|
|
|
32
32
|
|
|
33
33
|
### Step 1 — Resolve the thread
|
|
34
34
|
Run `yad thread <thread> --json` (`resolveThread` + `threadEpics` + `resolveCurrentArtifacts`). This
|
|
35
|
-
gives the genesis-first chain, each epic's lineage (`
|
|
35
|
+
gives the genesis-first chain, each epic's lineage (`type`, and `kind` holding the same value under
|
|
36
|
+
the older name, plus `parent` and `inherits`), the resolved
|
|
36
37
|
current-truth map, and any open reconcile debt. **STOP** and report if the lineage is broken (point at
|
|
37
38
|
`yad doctor` / `yad-reconcile`).
|
|
38
39
|
|
|
@@ -54,9 +55,9 @@ deterministically; theme from the design system). The thread maps onto the shell
|
|
|
54
55
|
= what it re-authored, its side-effects = the ships it produced + any contract re-lock.
|
|
55
56
|
- **System components** = the artifacts (epic/architecture/contract/ui/stories/test-cases), each labelled
|
|
56
57
|
with the epic that currently **owns** it (from the resolved map).
|
|
57
|
-
- Label and colour nodes by `
|
|
58
|
+
- Label and colour nodes by `type` — render each node's type noun (**Change request** / **Defect** /
|
|
58
59
|
**Hotfix** / **Epic** for feature) alongside its id, not the generic word "epic"; mark sealed epics and
|
|
59
|
-
open debt. (A bug is a defect — `
|
|
60
|
+
open debt. (A bug is a defect — type `defect`. Presentation only; every node is still an epic.)
|
|
60
61
|
|
|
61
62
|
### Step 4 — Emit `thread-resolved.md` (the current-truth map — derived, non-authoritative)
|
|
62
63
|
Write `epics/<thread>/thread-resolved.md`: for each artifact base, the **owning epic** (the latest in the
|
|
@@ -66,7 +67,7 @@ is the file the next `yad-change` / `yad-epic` reads as "the feature's current t
|
|
|
66
67
|
|
|
67
68
|
### Step 5 — Emit `TIMELINE.md` + (optional) deploy
|
|
68
69
|
Write a short `epics/<thread>/TIMELINE.md` (the chain, what each node changed, ships, open debt) for a
|
|
69
|
-
plain-text read — head each node with its
|
|
70
|
+
plain-text read — head each node with its type noun (Change request / Defect / Hotfix / Chore / Epic) + id. On `action: deploy`, note that `yad docs deploy` does not build this folder yet (it builds only the epic `docs-site/` and the overview) — build it with `npm ci` (or `npm install` when it has no lockfile) and `npm run build` inside the folder, and report it as build-only; a failed npm build is reported as a failure, never as a deploy.
|
|
70
71
|
|
|
71
72
|
## Hard rules
|
|
72
73
|
|