yadflow 3.18.1 → 4.0.0-next.1

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.
Files changed (156) hide show
  1. package/CHANGELOG.md +355 -0
  2. package/README.md +79 -26
  3. package/bin/commands.mjs +41 -0
  4. package/bin/yad.mjs +437 -124
  5. package/cli/artifact-status.mjs +34 -15
  6. package/cli/checkpoint.mjs +69 -49
  7. package/cli/codeowners-command.mjs +170 -0
  8. package/cli/codeowners.mjs +397 -0
  9. package/cli/commit.mjs +13 -9
  10. package/cli/companion.mjs +2 -2
  11. package/cli/dial.mjs +183 -0
  12. package/cli/docs.mjs +88 -32
  13. package/cli/doctor.mjs +1472 -97
  14. package/cli/epic-state.mjs +3478 -232
  15. package/cli/epic.mjs +506 -0
  16. package/cli/errors.mjs +4 -1
  17. package/cli/gate.mjs +1002 -209
  18. package/cli/history.mjs +556 -0
  19. package/cli/hook.mjs +266 -55
  20. package/cli/hubcommit.mjs +6 -17
  21. package/cli/index-command.mjs +87 -0
  22. package/cli/ledger.mjs +57 -7
  23. package/cli/lib.mjs +184 -18
  24. package/cli/manifest.mjs +367 -56
  25. package/cli/migrate.mjs +726 -53
  26. package/cli/mode.mjs +170 -0
  27. package/cli/next.mjs +349 -90
  28. package/cli/openpr.mjs +191 -39
  29. package/cli/people.mjs +654 -0
  30. package/cli/plan.mjs +417 -132
  31. package/cli/platform.mjs +110 -129
  32. package/cli/product-index.mjs +287 -0
  33. package/cli/protection.mjs +706 -0
  34. package/cli/reconcile.mjs +38 -12
  35. package/cli/repo-publish.mjs +24 -26
  36. package/cli/repo.mjs +23 -14
  37. package/cli/report.mjs +21 -15
  38. package/cli/review.mjs +24 -27
  39. package/cli/riskmap-command.mjs +289 -0
  40. package/cli/riskmap.mjs +373 -0
  41. package/cli/setup.mjs +139 -287
  42. package/cli/ship.mjs +7 -6
  43. package/cli/skill.mjs +180 -0
  44. package/cli/skip.mjs +211 -30
  45. package/cli/thread.mjs +42 -17
  46. package/cli/tidy.mjs +20 -20
  47. package/cli/update-commit.mjs +22 -22
  48. package/cli/usage.mjs +115 -109
  49. package/package.json +3 -3
  50. package/skills/sdlc/config.yaml +166 -87
  51. package/skills/sdlc/module-help.csv +35 -35
  52. package/skills/yad-analysis/SKILL.md +125 -65
  53. package/skills/yad-architecture/SKILL.md +34 -23
  54. package/skills/yad-architecture/references/contract-format.md +10 -8
  55. package/skills/yad-backfill/SKILL.md +14 -8
  56. package/skills/yad-backfill/references/backfill.md +1 -1
  57. package/skills/yad-change/SKILL.md +127 -52
  58. package/skills/yad-change/references/triage.md +42 -28
  59. package/skills/yad-checks/SKILL.md +89 -45
  60. package/skills/yad-checks/references/check-gates.md +315 -92
  61. package/skills/yad-checks/templates/checks/build-test-lint.sh +25 -7
  62. package/skills/yad-checks/templates/checks/commit-message.sh +17 -3
  63. package/skills/yad-checks/templates/checks/contract-check.sh +58 -2
  64. package/skills/yad-checks/templates/checks/epic-open.sh +3 -3
  65. package/skills/yad-checks/templates/checks/install-deps.sh +46 -0
  66. package/skills/yad-checks/templates/checks/ledger-guard.sh +94 -18
  67. package/skills/yad-checks/templates/checks/lineage-check.sh +23 -9
  68. package/skills/yad-checks/templates/checks/package-manager.sh +140 -0
  69. package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +4 -4
  70. package/skills/yad-checks/templates/checks/risk-map-check.sh +438 -0
  71. package/skills/yad-checks/templates/checks/verified-commits.sh +20 -46
  72. package/skills/yad-checks/templates/github/yad-checks.yml +37 -5
  73. package/skills/yad-checks/templates/github/yad-hub-checks.yml +5 -5
  74. package/skills/yad-checks/templates/github/yad-update-guard.yml +3 -4
  75. package/skills/yad-checks/templates/github/yad-verified-commits.yml +4 -4
  76. package/skills/yad-checks/templates/gitlab/.gitlab-ci.yml +7 -1
  77. package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +22 -4
  78. package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +5 -5
  79. package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +4 -4
  80. package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +91 -0
  81. package/skills/yad-checks/templates/hooks/ledger-guard.sh +38 -7
  82. package/skills/yad-commit/SKILL.md +6 -6
  83. package/skills/yad-connect-design/SKILL.md +6 -6
  84. package/skills/yad-connect-design/references/design-context.md +1 -1
  85. package/skills/yad-connect-design/references/design-registry.md +2 -2
  86. package/skills/yad-connect-docs/SKILL.md +12 -12
  87. package/skills/yad-connect-docs/references/docs-registry.md +1 -1
  88. package/skills/yad-connect-learning/SKILL.md +5 -5
  89. package/skills/yad-connect-learning/references/learning-registry.md +2 -2
  90. package/skills/yad-connect-repos/SKILL.md +92 -54
  91. package/skills/yad-connect-repos/references/code-context.md +6 -6
  92. package/skills/yad-connect-repos/references/hub-config.md +68 -58
  93. package/skills/yad-connect-repos/references/repos-registry.md +10 -9
  94. package/skills/yad-connect-repos/references/risk-map.md +81 -0
  95. package/skills/yad-connect-testing/SKILL.md +6 -6
  96. package/skills/yad-connect-testing/references/testing-context.md +3 -4
  97. package/skills/yad-connect-testing/references/testing-registry.md +2 -2
  98. package/skills/yad-defects/SKILL.md +8 -8
  99. package/skills/yad-discovery/SKILL.md +130 -94
  100. package/skills/yad-discovery/references/discovery-schema.md +23 -7
  101. package/skills/yad-discovery/references/foundation-schema.md +374 -0
  102. package/skills/yad-docs/SKILL.md +16 -11
  103. package/skills/yad-docs/references/data-mapping.md +9 -7
  104. package/skills/yad-docs/templates/app/package-lock.json +3 -3
  105. package/skills/yad-docs-overview/SKILL.md +32 -17
  106. package/skills/yad-docs-overview/references/pipeline-model.md +47 -28
  107. package/skills/yad-docs-sync/SKILL.md +10 -5
  108. package/skills/yad-docs-sync/references/staleness.md +8 -7
  109. package/skills/yad-engineer-review/SKILL.md +88 -24
  110. package/skills/yad-engineer-review/references/ship-and-record.md +25 -16
  111. package/skills/yad-epic/SKILL.md +178 -100
  112. package/skills/yad-epic/references/state-schema.md +626 -117
  113. package/skills/yad-hub-bridge/SKILL.md +66 -48
  114. package/skills/yad-hub-bridge/references/bridge.md +110 -83
  115. package/skills/yad-hub-bridge/references/login-roster.md +163 -70
  116. package/skills/yad-hub-bridge/templates/checks/hub-route.sh +22 -19
  117. package/skills/yad-hub-bridge/templates/github/yad-gate-sync.yml +34 -14
  118. package/skills/yad-hub-bridge/templates/gitlab/gitlab-ci.include-root.yml +2 -2
  119. package/skills/yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml +22 -12
  120. package/skills/yad-implement/SKILL.md +29 -15
  121. package/skills/yad-implement/references/implement-conventions.md +2 -2
  122. package/skills/yad-learn/SKILL.md +9 -9
  123. package/skills/yad-learn/references/learning-state.md +2 -2
  124. package/skills/yad-open-pr/SKILL.md +64 -29
  125. package/skills/yad-pair-review/SKILL.md +18 -16
  126. package/skills/yad-pair-review/references/session-state.md +4 -4
  127. package/skills/yad-pr-template/SKILL.md +48 -27
  128. package/skills/yad-pr-template/references/risk-routing.md +97 -24
  129. package/skills/yad-pr-template/templates/checks/pr-template.sh +37 -15
  130. package/skills/yad-pr-template/templates/checks/pr-title.sh +27 -13
  131. package/skills/yad-pr-template/templates/checks/risk-route.sh +107 -14
  132. package/skills/yad-pr-template/templates/github/pull_request_template.md +7 -5
  133. package/skills/yad-pr-template/templates/gitlab/merge_request_templates/Default.md +7 -5
  134. package/skills/yad-pr-template/templates/hub/github/pull_request_template.md +15 -14
  135. package/skills/yad-pr-template/templates/hub/gitlab/merge_request_templates/Default.md +15 -13
  136. package/skills/yad-reconcile/SKILL.md +3 -3
  137. package/skills/yad-report/SKILL.md +5 -5
  138. package/skills/yad-review-companion/SKILL.md +12 -9
  139. package/skills/yad-review-gate/SKILL.md +198 -79
  140. package/skills/yad-review-gate/references/gating.md +230 -54
  141. package/skills/yad-run/SKILL.md +86 -56
  142. package/skills/yad-run/references/run-loop.md +67 -45
  143. package/skills/yad-ship/SKILL.md +18 -14
  144. package/skills/yad-spec/SKILL.md +31 -17
  145. package/skills/yad-spec/references/spec-handoff.md +17 -5
  146. package/skills/yad-status/SKILL.md +114 -56
  147. package/skills/yad-stories/SKILL.md +42 -27
  148. package/skills/yad-stories/references/story-schema.md +10 -9
  149. package/skills/yad-stub/SKILL.md +59 -48
  150. package/skills/yad-sync-repos/SKILL.md +3 -3
  151. package/skills/yad-test-cases/SKILL.md +37 -30
  152. package/skills/yad-test-cases/references/test-cases-schema.md +8 -5
  153. package/skills/yad-timeline/SKILL.md +8 -7
  154. package/skills/yad-ui/SKILL.md +46 -25
  155. package/cli/roster.mjs +0 -164
  156. package/skills/sdlc/install.sh +0 -68
@@ -1,29 +1,31 @@
1
1
  ---
2
2
  name: yad-epic
3
- description: 'Front state for the epic in the gated SDLC. Shape a feature idea with the analyst (or read analysis.md when the optional analysis step already ran), then write the epic with the pm, into epic.md. The entry point when analysis is skipped: assigns the EP-<slug> ID and seeds .sdlc/ state. Never auto-advances — hands off to the team review gate. Use when the user says "start a new feature/epic" or "author an epic".'
3
+ description: 'Shape step for the epic in the gated SDLC. Shape a feature idea with the analyst (or read analysis.md when the optional analysis step already ran), then write the epic with the pm, into epic.md. The entry point when analysis is skipped: assigns the EP-<slug> ID and seeds .sdlc/ state. Never auto-advances — hands off to the team review gate. Use when the user says "start a new feature/epic" or "author an epic".'
4
4
  ---
5
5
 
6
- # SDLC — Author Epic (front state)
6
+ # SDLC — Author Epic (Shape step)
7
7
 
8
8
  **Goal:** Produce a human-authored, AI-assisted `epic.md` for a new feature, and — when the epic is the
9
9
  entry point — assign its stable `EP-<slug>` ID and initialise the per-epic state machine in `.sdlc/`.
10
- This is a **front state**: human-authored with AI assist and **never auto-advances**. When the epic is
10
+ This is a **Shape step**: human-authored with AI assist and **never auto-advances**. When the epic is
11
11
  drafted, control passes to `yad-review-gate`.
12
12
 
13
- **Two entry modes** (the optional `yad-analysis` step decides which):
14
- - **Analysis ran** — `.sdlc/state.json` already exists with `currentStep == "epic"`. The epic **reads
15
- `analysis.md`** as its shaped input and does not re-seed state.
16
- - **Analysis skipped** (the default) — no `state.json` yet. The epic is the entry point: it shapes the
17
- idea inline with the analyst, assigns `EP-<slug>`, and seeds the **10-step** chain.
13
+ **Two entry modes**, decided by one question: does `.sdlc/state.json` already exist?
14
+ - **Chain already seeded** — `state.json` exists with `currentStep == "epic"`. Two things put it there:
15
+ the optional `yad-analysis` step (which also wrote `analysis.md`, and the epic **reads** it as its
16
+ shaped input), or `yad epic new <slug>`, which seeds the same chain and writes no artifact. Either
17
+ way this skill does **not** re-seed state.
18
+ - **Nothing seeded** (the default) — no `state.json`. The epic is the entry point: it shapes the idea
19
+ inline with the analyst, assigns `EP-<slug>`, and seeds the **10-step** chain.
18
20
 
19
21
  This skill enforces the build plan's core rules: all state lives in files; IDs are generated by the
20
- engine (never typed by hand); front steps are locked to `human_approve`.
22
+ engine (never typed by hand); Shape steps are locked to `advance: human`.
21
23
 
22
24
  ## Conventions
23
25
 
24
26
  - `{project-root}` resolves from the project working directory.
25
27
  - Epic artifacts live under `{project-root}/epics/EP-<slug>/` (build plan §6).
26
- - Speak in the configured `communication_language`; write documents in `document_output_language`.
28
+ - Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write documents in `document_output_language`.
27
29
 
28
30
  ## On Activation
29
31
 
@@ -31,23 +33,27 @@ engine (never typed by hand); front steps are locked to `human_approve`.
31
33
  Read `{project-root}/epics/EP-<slug>/.sdlc/state.json` if an epic is named, otherwise check whether one
32
34
  exists for the idea.
33
35
 
34
- - **Analysis ran** — `state.json` exists with `currentStep == "epic"` and the `epic` step
35
- `status == "in_progress"` (the analysis review already passed). Skip **Step 3** (the ID is already
36
- assigned) and **Step 5** (state is already seeded); take the *analysis-ran* branch of Step 2 (read
37
- `analysis.md`) and run Step 5b to advance the authoring step.
38
- - **Analysis skipped** (the default) — no `state.json`. The epic is the entry point: run Steps 2–5
39
- (inline analyst shaping + ID assignment + seed) and **skip Step 5b**.
36
+ - **Chain already seeded** — `state.json` exists with `currentStep == "epic"`. Skip **Step 3** (the ID
37
+ is already assigned) and **Step 5** (the chain is already there — re-seeding is refused anyway). For
38
+ Step 2, read `analysis.md` when it is there (the analysis ran); when it is not, the chain came from
39
+ `yad epic new` and no analysis exists, so shape the idea inline with the analyst exactly as the
40
+ greenfield branch does.
41
+ - **Nothing seeded** (the default) — no `state.json`. The epic is the entry point: run Steps 2–5
42
+ (inline analyst shaping + ID assignment + seed).
43
+
44
+ **Step 5b runs on both paths.** It is what closes the authoring step and opens its gate, and nothing
45
+ else does it.
40
46
 
41
47
  Either mode runs Step 3b (branch), Step 4 (write the epic), and Step 6 (stop at the gate).
42
48
 
43
- **Precondition gate (rail):** if `state.json` already exists (analysis-ran or re-entry), run
49
+ **Precondition gate (rail):** if `state.json` already exists (seeded, or a re-entry), run
44
50
  `yad next EP-<slug> --check epic` — if it exits non-zero, **STOP** and surface the blocker, pointing the
45
51
  user at `yad next EP-<slug>`. When no `state.json` exists yet, this is the greenfield entry point — the
46
52
  check is not applicable, so proceed and seed state.
47
53
 
48
54
  ### Step 2 — Shape the idea (assist: analyst) — or read the analysis
49
55
  - **Analysis skipped:** ask the user for a one-line feature idea if not provided, then adopt the
50
- **analyst** lens (`bmad-agent-analyst`, Mary) to pressure-test it: who is the user, what problem, what
56
+ **analyst** lens to pressure-test it: who is the user, what problem, what
51
57
  signals success, what is out of scope. Keep it brief — this is shaping, not a PRD.
52
58
  - **Analysis ran:** read `{project-root}/epics/EP-<slug>/analysis.md` (the analyst's discovery brief)
53
59
  and carry its Recommendation / Scope framing forward — do not re-shape from scratch.
@@ -68,40 +74,86 @@ and let it inform which `repos` the epic should touch.
68
74
  - For depth on a specific area not in the map, do a live on-demand read (see `yad-connect-repos`
69
75
  `references/code-context.md`) — do not block on it.
70
76
 
71
- ### Step 2c — Read the project roadmap (project context, only once discovery is APPROVED)
72
- Consume the project front-zero (`yad-discovery`) **only after its review gate has passed** — never a
73
- draft or in-review roadmap (that would bypass `discovery-review`). Gate on the **state**, not file
74
- existence: read `{project-root}/epics/EP-discovery/.sdlc/state.json` and proceed **only when
75
- `currentStep == "discovery-done"`**. When it is, read its `roadmap.md` and sibling `requirements.md`
76
- for the project framing: which phase (MVP / later) this feature belongs to, the functional/non-functional
77
- requirements it carries, and how it fits the wider plan — so the epic's **Goal / Scope / Acceptance
78
- signals** stay consistent with the approved roadmap. **Optional & non-blocking:** if there is no
79
- discovery, or it has not yet reached `discovery-done` (absent / still draft / in-review), proceed
80
- unchanged — do not consume an unapproved roadmap. After seeding the epic, the matching roadmap row's
81
- `status:` can be bumped `planned → epic-started` by hand (a human edit; discovery never auto-seeds epics).
77
+ ### Step 2c — Read the Foundation (product context, only once it is APPROVED)
78
+ Consume the Product level (written by `yad-discovery`) **only after its review gate has passed** — never
79
+ a draft or in-review one (that would bypass its gate). Gate on the **state**, not file existence:
80
+ - **The Foundation:** read `{project-root}/foundation/.sdlc/state.json` and proceed **only when
81
+ `currentStep == "foundation-done"`**. Then read `foundation/purpose.md`, `scope.md`, `mvp.md` and
82
+ `roadmap.md` (and `stack.md` / `repos.md` for the technical frame).
83
+ - **The old spelling**, only when there is no Foundation: read
84
+ `{project-root}/epics/EP-discovery/.sdlc/state.json` and proceed **only when
85
+ `currentStep == "discovery-done"`**. Then read its `roadmap.md` and sibling `requirements.md`.
86
+
87
+ Use it for: which phase (MVP / later) this feature belongs to, what the product explicitly is **not**,
88
+ the requirements it carries, and how it fits the wider plan — so the epic's **Goal / Scope / Acceptance
89
+ signals** stay consistent with the approved product. **Optional & non-blocking:** if there is no product
90
+ level, or it has not passed its gate yet (absent / still draft / in-review), proceed unchanged — do not
91
+ consume an unapproved one. (`yad next` reports feature work that goes ahead of an unapproved Foundation;
92
+ it never blocks it.) Prefer the roadmap row's **proposed epic id** when you assign the id (Step 3), so
93
+ the feature and its epic stay linked. **Do not edit the roadmap row's `Status` after seeding** (the
94
+ Foundation never auto-seeds epics, and nothing needs the row changed): the roadmap table is part of what
95
+ the Foundation's reviewers approved, so the edit makes `yad doctor` report their approvals as stale.
96
+ `yad foundation status` reads how far each feature has got from the epic ledgers instead.
82
97
 
83
98
  ### Step 3 — Generate the Epic ID (engine-assigned, never by hand) — analysis-skipped only
84
- *(Skip when analysis ran — the ID was already assigned by `yad-analysis`.)*
99
+ *(Skip when `state.json` already exists — the ID was assigned by whatever seeded the chain.)*
85
100
  Derive `EP-<slug>` where `slug` is **2–4 lowercase words joined by hyphens**, drawn from the idea
86
- (e.g. `EP-checkout`). Lowercase except the fixed `EP` prefix. `EP-discovery` is **reserved**
87
- for the project front-zero — never use it for a feature. **The ID is assigned once and
101
+ (e.g. `EP-checkout`). Lowercase except the fixed `EP` prefix. `EP-foundation` and `EP-discovery` are
102
+ **reserved** for the Product level — never use either for a feature. **The ID is assigned once and
88
103
  never renamed** — renaming breaks every downstream link (build plan §6b).
89
104
  Check `{project-root}/epics/` for collisions; if the slug exists, append a distinguishing word.
90
105
 
91
106
  ### Step 3b — Open the authoring branch
92
107
  Open the epic authoring branch `epic/EP-<slug>` per the shared procedure
93
108
  (`references/state-schema.md` → "Authoring branches"): git-safe (skip with a note if `{project-root}`
94
- is not a git work tree), check out the branch if it exists, else create it from the hub's default
95
- branch. Author and commit `epic.md` on it. This is **distinct** from the bridge's `review/…` branch.
109
+ is not a git work tree), check out the branch if it exists, else create it from the Product's default
110
+ branch. Author and commit `epic.md` on it. This is **distinct** from the verified ledger's `review/…` branch.
96
111
 
97
112
  ### Step 4 — Write the epic (assist: pm)
98
- Adopt the **pm** lens (`bmad-agent-pm`, John) and write `{project-root}/epics/EP-<slug>/epic.md`
99
- using EXACTLY this template (build plan §6b):
113
+ Adopt the **pm** lens and write `{project-root}/epics/EP-<slug>/epic.md`
114
+ using EXACTLY this template (build plan §6b).
115
+
116
+ **Five of these keys are read by machines, so write them BARE — no trailing `#` comment.** The
117
+ frontmatter readers (`readFrontmatter` in the CLI, `fm_val` in the check gates) keep the whole rest of
118
+ the line, so a comment becomes part of the value and the gates stop recognising it:
119
+
120
+ - `title` is the epic's **one-line name** — the name a list of work items shows for it (E111; it is carried in `.sdlc/index.json`). Plain words,
121
+ such as `Checkout from the mobile app`, on ONE line. Quotes are optional: a title quoted the YAML way
122
+ (`"…"` or `'…'`) is read without them. If the title begins with `[` and ends with `]` (such as
123
+ `[Mobile] Checkout [v2]`), wrap it in double quotes, writing an inner `"` as `\"` — otherwise it is
124
+ read as a list, which is not a title. The full rules are the `title` row of the frontmatter table in
125
+ `references/state-schema.md`. Never end it with a `#` comment (the comment becomes part of the title), and never use a YAML
126
+ block (`>` or `|`): only one line is read. Set it NOW, for the same reason as the theme below: the epic review gate is bound to a hash of
127
+ the file, so a title added or reworded after that gate is approved drops the approval as stale. An
128
+ epic with no title is shown by its id.
129
+ - `kind` and `type` are the **work-item type**, and both carry the same value. `kind:` is the name
130
+ every reader still uses; `type:` is the name from shape 5 on. Write both. Use `feature` for new
131
+ value, or `chore` for upkeep with no user-visible change — those are the two types allowed to stand
132
+ alone with no `parent:`. Everything else (`change`, `defect`, `hotfix`) is authored by `yad-change`.
133
+ - `thread` is the thread id. A genesis epic is the root of its own thread, so `thread == id` and there
134
+ is no `parent:`.
135
+ - `theme` is an optional **grouping tag**: one word or short phrase shared by every epic that belongs
136
+ together, such as `checkout-revamp`. It is what this method has instead of a rung above the Epic —
137
+ the ladder stays Product → Epic → Story → Task, and grouping is a label. Nothing has to be
138
+ registered first and no list of allowed themes exists. Ask the user whether this epic belongs to a
139
+ group; if one already exists, **copy its spelling exactly** (`yad doctor` reports a theme spelled
140
+ two ways, because two spellings group as two themes). Leave the key empty when there is no group.
141
+ Write ONE tag, never a list — `theme: [a, b]` is read as no theme at all — and never write a `#`:
142
+ `yad next` and `yad thread` PRINT the tag as `#checkout-revamp`, but the `#` is decoration on the
143
+ screen, and anything from a `#` onward is kept as part of the value, so the epic then groups only
144
+ with epics carrying that exact text. Any language is fine. Set it NOW, while the epic
145
+ is being written: the epic review gate is bound to a hash of the file (all of it except the `status:` line), so adding a theme after
146
+ that gate is approved drops the approval as stale and the step has to be approved again.
100
147
 
101
148
  ```markdown
102
149
  ---
103
150
  id: EP-<slug>
151
+ title: <one line: what this epic delivers>
104
152
  status: draft
153
+ kind: feature
154
+ type: feature
155
+ thread: EP-<slug>
156
+ theme:
105
157
  owner:
106
158
  technical_product_owner:
107
159
  repos: [backend, mobile, dashboard]
@@ -118,90 +170,116 @@ code-context: { repos: [], loaded: <YYYY-MM-DD or none> } # which code-maps in
118
170
  ```
119
171
 
120
172
  Fill the body with the user; leave `owner` / `technical_product_owner` for the user to set. Set
121
- `repos` to the repos this epic will touch.
122
-
123
- ### Step 5 — Seed the state machine — analysis-skipped only
124
- *(Skip when analysis ran — `yad-analysis` already seeded the 12-step chain. Go to Step 5b.)*
125
- Create `{project-root}/epics/EP-<slug>/.sdlc/state.json` describing the full **10-step** front-state
126
- sequence (no analysis), all steps defaulting to `automation: human_approve`, with the five authoring
127
- steps **locked**. Use this exact shape (see `references/state-schema.md`):
128
-
129
- ```json
130
- {
131
- "schemaVersion": 1,
132
- "epicId": "EP-<slug>",
133
- "createdAt": "<YYYY-MM-DD>",
134
- "currentStep": "epic-review",
135
- "steps": [
136
- { "id": "epic", "type": "author", "artifact": "epic.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "done", "risk_tags": [] },
137
- { "id": "epic-review", "type": "review+approve", "artifact": "epic.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "in_review", "risk_tags": [] },
138
- { "id": "architecture", "type": "author", "artifact": "architecture.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
139
- { "id": "architecture-review","type": "review+approve", "artifact": "architecture.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": ["contract"] },
140
- { "id": "ui-design", "type": "author", "artifact": "ui-design.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
141
- { "id": "ui-design-review", "type": "review+approve", "artifact": "ui-design.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
142
- { "id": "stories", "type": "author", "artifact": "stories/", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
143
- { "id": "stories-review", "type": "review+approve", "artifact": "stories/", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
144
- { "id": "test-cases", "type": "author", "artifact": "test-cases.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] },
145
- { "id": "test-cases-review", "type": "review+approve", "artifact": "test-cases.md", "assistance": "review", "automation": "human_approve", "locked": true, "status": "blocked", "risk_tags": [] }
146
- ]
147
- }
173
+ `repos` to the repos this epic will touch, and `theme` only if the user names a group.
174
+
175
+ ### Step 5 — Seed the state machine — only when nothing is seeded
176
+ *(Skip when `state.json` already exists — `yad-analysis` seeded the 12-step chain, or `yad epic new`
177
+ seeded the 10-step one. Go to Step 5b.)*
178
+
179
+ **Run the engine. Do not hand-write the chain.**
180
+
181
+ ```bash
182
+ yad epic new EP-<slug> # after Step 4: the type comes from epic.md
183
+ yad epic new EP-<slug> --type chore # only when there is no epic.md yet
184
+ yad epic new EP-<slug> --profile chore # the short upkeep lane — see below
148
185
  ```
149
186
 
187
+ That writes `{project-root}/epics/EP-<slug>/.sdlc/state.json`, the empty `approvals.json` and
188
+ `comments.json`, and the `reviews/` directory. Without `--profile` the chain is the full **10-step**
189
+ `classic` route (no analysis). Every step is `advance: human` and locked; `epic` is open and the rest
190
+ are blocked. The chain comes from the step catalogue and the lifecycle profile in the engine
191
+ (`references/state-schema.md`), so there is one definition of it and no copy here to drift from it.
192
+
193
+ **Ask which lane this work belongs on before you run it.** `classic` is the default and the right
194
+ answer for a feature. For upkeep somebody has already decided on — a dependency bump, a CI move —
195
+ `--profile chore` seeds a **4-step** lane instead: `epic → epic-review → stories → stories-review`,
196
+ with no architecture, UI-design or test-case steps. `--profile spike` is the same lane with the
197
+ analyst's brief in front, for a timeboxed question (start that one from `yad-analysis`, which owns the
198
+ first step). Both are described in `references/state-schema.md`.
199
+
200
+ A short lane has **no architecture gate, so no `contract.md` and no lock**, and no step on it is
201
+ optional — `yad skip` is refused. **Choose the route before you seed, because the choice is final:**
202
+ `yad epic new` refuses an epic that already has a `state.json` and there is no re-seed flag. If the
203
+ work turns out to move the shared cross-repo surface, the short-lane epic records the finding and the
204
+ surface change belongs to a NEW epic on `classic` — say that rather than trying to widen this one. The
205
+ work-item type is a separate choice: `--type chore --profile classic` is right for large upkeep that
206
+ does touch the contract.
207
+
208
+ It writes no `epic.md`, no branch and no commit, and it refuses an epic that already has a
209
+ `state.json`. Run it **after** Step 4 when `epic.md` exists, and it reads the type from that header —
210
+ then `--type` is unnecessary and a contradicting one is refused.
211
+
150
212
  Notes:
151
- - `architecture-review` carries `risk_tags: ["contract"]` so the gate escalates it by default
152
- (build plan §4): the contract review needs domain owners, not just owner + 1.
153
- - `test-cases` / `test-cases-review` are a **parallel, non-blocking track**: they seed `blocked` and open
154
- when `stories-review` passes — at which point the epic is already `ready-for-build`, so the build half
213
+ - **Then advance the authoring step.** The seed leaves `epic` open, which is truthful: the command runs
214
+ before the artifact exists. Closing it is Step 5b's job, and on the local path `yad gate open` does it
215
+ — so after writing `epic.md`, take Step 5b.
216
+ - `architecture-review` carries `risk_tags: ["contract"]` by default (build plan §4): the tag raises
217
+ the step's full approver count to 3 (base 1 + contract risk 2). Only the base holds the
218
+ gate; the risk step is advisory, reported as a shortfall against the count capped at the
219
+ active people less one (E72). The catalogue sets it;
220
+ there is nothing to type.
221
+ - `test-cases` / `test-cases-review` are a **parallel, non-blocking track**: they seed `todo` and open
222
+ when `stories-review` passes — at which point the epic is already `ready-for-build`, so Build
155
223
  runs alongside the tester. They never gate `ready-for-build` (see `references/state-schema.md`).
156
- - Commit the seed on this step's authoring branch. It reaches the hub's default branch through the
224
+ - Commit the seed on this step's authoring branch. It reaches the Product's default branch through the
157
225
  epic's **first** review PR/MR — cut `review/EP-<slug>/epic` from the authoring branch so it carries
158
- the seed. In bridge mode `ledger-guard` exempts a new epic's ledger (creation, not mutation, #162);
226
+ the seed. In verified mode `ledger-guard` exempts a new epic's ledger (creation, not mutation, #162);
159
227
  every later change to it is CI's. See `references/state-schema.md`, "Authoring branches".
160
- - Also create an empty approvals ledger `{project-root}/epics/EP-<slug>/.sdlc/approvals.json`
161
- and an empty comments ledger `{project-root}/epics/EP-<slug>/.sdlc/comments.json`, each containing
162
- `[]`, and the `reviews/` directory. (`comments.json` is the machine-readable counterpart to the
163
- `reviews/*--comments.md` markdown — `yad-review-gate` appends to it on every `comment`.)
164
- - **No UI?** Seed the chain **as-is** (always include the two `ui-design` steps). If this epic has no
228
+ - **No UI?** Seed the chain **as-is** (the two `ui-design` steps are always in it). If this epic has no
165
229
  user-facing surface (a backend/API service, data pipeline, infra), the `ui-design` step is optional
166
230
  and can be marked N/A now with `yad skip EP-<slug> ui-design --reason "<why>"` — it stays visible,
167
231
  short-circuits its gate, and advances straight to `stories` when architecture is approved. It is
168
- reversible with `--undo` until the stories review opens. Don't hand-edit the seed to drop the steps;
232
+ reversible with `yad unskip EP-<slug> ui-design` until the stories review opens. **On a verified Product, now is the only time:** once this epic's first review PR merges, CI owns `state.json` and `yad skip` refuses. Don't hand-edit the chain to drop the steps;
169
233
  the skip is the single, auditable mechanism (see `references/state-schema.md` → "ui-design is optional").
170
234
 
171
- ### Step 5b — Advance the authoring step — analysis-ran only
172
- *(Only when analysis ran — `state.json` already exists from `yad-analysis`.)*
235
+ ### Step 5b — Open the epic's review gate
236
+ *(**Always run this**, on both entry modes. The chain is seeded by now either way — by `yad-analysis`,
237
+ by `yad epic new` in Step 5, or by `yad epic new` before this skill was invoked — and `epic.md` is
238
+ written. This is the step that closes the authoring step and opens its gate.)*
173
239
  **Check the mode first — the two modes have opposite instructions here.** Read `.sdlc/hub.json`:
174
- **bridge mode** is `platform` set AND `bridge_enabled` (or legacy `bridge`) `true`.
240
+ **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.
175
241
 
176
- **Bridge mode — do NOT write `state.json`.** The ledger is CI-owned: the `ledger-guard` check rejects
177
- any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,hub-prs}.json` or
242
+ **verified mode — do NOT write `state.json`.** The ledger is CI-owned: the `ledger-guard` check rejects
243
+ any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,product-prs,hub-prs}.json` or
178
244
  `epics/*/reviews/*.md`, `yad gate open` deliberately skips this write for the same reason, and
179
245
  `yad gate ci --merged` performs the whole transition when the review PR merges. Making the edit here
180
246
  fails the gate if it rides the review PR, and desynchronises the ledger CI is about to rewrite if it
181
- is pushed around the gate. Commit **`epic.md` only** — nothing else under `.sdlc/` — then hand off
182
- to `yad-review-gate`.
183
-
184
- > **This is not the Step 5 seed exemption.** `ledger-guard` exempts a *brand-new* epic's ledger
185
- > (creation, not mutation, #162). On this path `state.json` already exists from `yad-analysis` and
186
- > reached the base ref through the analysis review — so the guard is absolute here.
187
-
188
- **Otherwise — file-only, or a platform with no gate-sync CI — write it.** In `state.json`: set
189
- `epic.status: "done"`, set `epic-review.status: "in_review"`, and set `currentStep: "epic-review"`.
190
- Write `state.json`. Do **not** re-seed and do **not** touch `approvals.json` — only real reviewers
191
- approve, through the gate.
192
-
193
- > **File-only branch only.** Since 3.11 the CLI closes the authoring step itself whenever its review
194
- > gate opens or advances (`yad gate open` / `sync`), so this edit is a no-op when the gate has already
195
- > run. It keeps `state.json` truthful before the gate opens, but it is no longer load-bearing: an epic
196
- > whose author step is left `in_progress` used to strand forever (`YAD-STATE-005`). In bridge mode
197
- > `gate open` writes nothing and local `gate sync` is advisory — `gate ci` closes the step at merge.
247
+ is pushed around the gate.
248
+
249
+ **Do not EDIT the ledger — but do COMMIT it when it is untracked.** Those are two different acts and
250
+ the guard treats them differently. Commit `epic.md`, and also `.sdlc/state.json`, `.sdlc/approvals.json`
251
+ and `.sdlc/comments.json` when `git status` shows them **untracked** — that is the case after
252
+ `yad epic new`, whose seed has never been reviewed and so rides this epic's first review PR exactly as
253
+ a Step 5 seed does. Leave their contents exactly as they are. When `git status` shows them tracked and
254
+ unmodified (the `yad-analysis` path), commit `epic.md` alone. Then hand off to `yad-review-gate`.
255
+
256
+ > **The Step 5 seed exemption may or may not still apply — read the base ref, not the calendar.**
257
+ > `ledger-guard` exempts an epic whose ledger is absent from the BASE ref: that is creation, not
258
+ > mutation (#162). After `yad-analysis` the ledger reached the base ref through the analysis review,
259
+ > so the exemption is spent and the guard is absolute. After `yad epic new` the ledger has never been
260
+ > reviewed, so it is still off the base ref and the seed rides this epic's first review PR exactly as
261
+ > in Step 5. Either way the instruction above is the safe one: in verified mode, do not write
262
+ > `state.json` here. Advancing a step is a mutation on any path, and CI performs it at merge.
263
+
264
+ **Otherwise — local, or a platform with no gate-sync CI — the engine makes this edit, not you.**
265
+ `yad gate open <epic> epic.md` marks `epic-review` `in_review`, closes `epic` as `done`, and moves
266
+ `currentStep` to the gate — the same transition, from the one function that owns it (`markInReview`, `cli/epic-state.mjs`).
267
+ `yad-review-gate action: open` runs that command; hand off to it rather than editing the ledger here.
268
+
269
+ **With no platform configured** it writes the ledger and simply opens no PR, so this works offline.
270
+ **With a platform** the `review/EP-<slug>/epic` branch must already be **on origin** — the command refuses
271
+ and writes nothing otherwise. Cut it from the authoring branch and push it before handing off
272
+ (`yad open-pr` does both, then delegates).
273
+
274
+ Do **not** hand-edit `state.json`, do **not** re-seed, and do **not** touch `approvals.json` — only real
275
+ reviewers approve, through the gate.
198
276
 
199
277
  ### Step 6 — Stop at the gate (do NOT advance)
200
278
  Report: epic ID, the path to `epic.md`, and that the next action is **review** via
201
279
  `yad-review-gate`. **Never mark the epic-review step approved here** — only real reviewers do that
202
- through the gate. Front states do not auto-advance. When the hub has a platform, the gate opens a review
203
- PR on the hub (via `yad-hub-bridge`) and `yad-review-gate action: sync` pulls platform approvals/
204
- comments into the ledger; otherwise the review is recorded file-only.
280
+ through the gate. Shape steps do not auto-advance. When the Product has a platform, the gate opens a review
281
+ PR on the Product (via `yad-hub-bridge`) and `yad-review-gate action: sync` pulls platform approvals/
282
+ comments into the ledger; otherwise the review is recorded local.
205
283
 
206
284
  ## Reference
207
285
  - State schema and field meanings: `references/state-schema.md`.