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.
- package/CHANGELOG.md +355 -0
- package/README.md +79 -26
- package/bin/commands.mjs +41 -0
- package/bin/yad.mjs +437 -124
- package/cli/artifact-status.mjs +34 -15
- package/cli/checkpoint.mjs +69 -49
- package/cli/codeowners-command.mjs +170 -0
- package/cli/codeowners.mjs +397 -0
- package/cli/commit.mjs +13 -9
- package/cli/companion.mjs +2 -2
- package/cli/dial.mjs +183 -0
- package/cli/docs.mjs +88 -32
- package/cli/doctor.mjs +1472 -97
- package/cli/epic-state.mjs +3478 -232
- package/cli/epic.mjs +506 -0
- package/cli/errors.mjs +4 -1
- package/cli/gate.mjs +1002 -209
- package/cli/history.mjs +556 -0
- package/cli/hook.mjs +266 -55
- package/cli/hubcommit.mjs +6 -17
- package/cli/index-command.mjs +87 -0
- package/cli/ledger.mjs +57 -7
- package/cli/lib.mjs +184 -18
- package/cli/manifest.mjs +367 -56
- package/cli/migrate.mjs +726 -53
- package/cli/mode.mjs +170 -0
- package/cli/next.mjs +349 -90
- package/cli/openpr.mjs +191 -39
- package/cli/people.mjs +654 -0
- package/cli/plan.mjs +417 -132
- package/cli/platform.mjs +110 -129
- package/cli/product-index.mjs +287 -0
- package/cli/protection.mjs +706 -0
- package/cli/reconcile.mjs +38 -12
- package/cli/repo-publish.mjs +24 -26
- package/cli/repo.mjs +23 -14
- package/cli/report.mjs +21 -15
- package/cli/review.mjs +24 -27
- package/cli/riskmap-command.mjs +289 -0
- package/cli/riskmap.mjs +373 -0
- package/cli/setup.mjs +139 -287
- package/cli/ship.mjs +7 -6
- package/cli/skill.mjs +180 -0
- package/cli/skip.mjs +211 -30
- package/cli/thread.mjs +42 -17
- package/cli/tidy.mjs +20 -20
- package/cli/update-commit.mjs +22 -22
- package/cli/usage.mjs +115 -109
- package/package.json +3 -3
- package/skills/sdlc/config.yaml +166 -87
- package/skills/sdlc/module-help.csv +35 -35
- package/skills/yad-analysis/SKILL.md +125 -65
- package/skills/yad-architecture/SKILL.md +34 -23
- package/skills/yad-architecture/references/contract-format.md +10 -8
- package/skills/yad-backfill/SKILL.md +14 -8
- package/skills/yad-backfill/references/backfill.md +1 -1
- package/skills/yad-change/SKILL.md +127 -52
- package/skills/yad-change/references/triage.md +42 -28
- package/skills/yad-checks/SKILL.md +89 -45
- package/skills/yad-checks/references/check-gates.md +315 -92
- package/skills/yad-checks/templates/checks/build-test-lint.sh +25 -7
- package/skills/yad-checks/templates/checks/commit-message.sh +17 -3
- package/skills/yad-checks/templates/checks/contract-check.sh +58 -2
- package/skills/yad-checks/templates/checks/epic-open.sh +3 -3
- package/skills/yad-checks/templates/checks/install-deps.sh +46 -0
- package/skills/yad-checks/templates/checks/ledger-guard.sh +94 -18
- package/skills/yad-checks/templates/checks/lineage-check.sh +23 -9
- package/skills/yad-checks/templates/checks/package-manager.sh +140 -0
- package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +4 -4
- 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 +37 -5
- package/skills/yad-checks/templates/github/yad-hub-checks.yml +5 -5
- package/skills/yad-checks/templates/github/yad-update-guard.yml +3 -4
- package/skills/yad-checks/templates/github/yad-verified-commits.yml +4 -4
- package/skills/yad-checks/templates/gitlab/.gitlab-ci.yml +7 -1
- package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +22 -4
- 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 +4 -4
- package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +91 -0
- package/skills/yad-checks/templates/hooks/ledger-guard.sh +38 -7
- package/skills/yad-commit/SKILL.md +6 -6
- package/skills/yad-connect-design/SKILL.md +6 -6
- 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 +12 -12
- 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 +92 -54
- package/skills/yad-connect-repos/references/code-context.md +6 -6
- package/skills/yad-connect-repos/references/hub-config.md +68 -58
- package/skills/yad-connect-repos/references/repos-registry.md +10 -9
- package/skills/yad-connect-repos/references/risk-map.md +81 -0
- package/skills/yad-connect-testing/SKILL.md +6 -6
- 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 +8 -8
- package/skills/yad-discovery/SKILL.md +130 -94
- package/skills/yad-discovery/references/discovery-schema.md +23 -7
- package/skills/yad-discovery/references/foundation-schema.md +374 -0
- package/skills/yad-docs/SKILL.md +16 -11
- 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 +32 -17
- package/skills/yad-docs-overview/references/pipeline-model.md +47 -28
- 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 +88 -24
- package/skills/yad-engineer-review/references/ship-and-record.md +25 -16
- package/skills/yad-epic/SKILL.md +178 -100
- package/skills/yad-epic/references/state-schema.md +626 -117
- package/skills/yad-hub-bridge/SKILL.md +66 -48
- package/skills/yad-hub-bridge/references/bridge.md +110 -83
- 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 +22 -12
- package/skills/yad-implement/SKILL.md +29 -15
- 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 +64 -29
- package/skills/yad-pair-review/SKILL.md +18 -16
- package/skills/yad-pair-review/references/session-state.md +4 -4
- package/skills/yad-pr-template/SKILL.md +48 -27
- package/skills/yad-pr-template/references/risk-routing.md +97 -24
- package/skills/yad-pr-template/templates/checks/pr-template.sh +37 -15
- package/skills/yad-pr-template/templates/checks/pr-title.sh +27 -13
- 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 +15 -14
- package/skills/yad-pr-template/templates/hub/gitlab/merge_request_templates/Default.md +15 -13
- package/skills/yad-reconcile/SKILL.md +3 -3
- package/skills/yad-report/SKILL.md +5 -5
- package/skills/yad-review-companion/SKILL.md +12 -9
- package/skills/yad-review-gate/SKILL.md +198 -79
- package/skills/yad-review-gate/references/gating.md +230 -54
- package/skills/yad-run/SKILL.md +86 -56
- package/skills/yad-run/references/run-loop.md +67 -45
- package/skills/yad-ship/SKILL.md +18 -14
- package/skills/yad-spec/SKILL.md +31 -17
- package/skills/yad-spec/references/spec-handoff.md +17 -5
- package/skills/yad-status/SKILL.md +114 -56
- package/skills/yad-stories/SKILL.md +42 -27
- package/skills/yad-stories/references/story-schema.md +10 -9
- package/skills/yad-stub/SKILL.md +59 -48
- package/skills/yad-sync-repos/SKILL.md +3 -3
- package/skills/yad-test-cases/SKILL.md +37 -30
- package/skills/yad-test-cases/references/test-cases-schema.md +8 -5
- package/skills/yad-timeline/SKILL.md +8 -7
- package/skills/yad-ui/SKILL.md +46 -25
- package/cli/roster.mjs +0 -164
- package/skills/sdlc/install.sh +0 -68
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-status
|
|
3
|
-
description: 'Read-only view of an SDLC epic: prints the current step, each step''s dials (
|
|
3
|
+
description: 'Read-only view of an SDLC epic: prints the current step, each step''s dials (driver/advance, under either spelling) and status, and which approvals are still required at the active gate. For stories in Build it also prints each Build step''s automation dial, status, and run record (runs / % approved-unchanged, as advice), plus the kill switch and the Shape author dials from .sdlc/automation.json — so the team can see WHY a step is automated and reverse it. Also prints the cross-cutting personal skills-log roll-up from the LOCAL-ONLY learning ledger (gitignored, never committed/pushed — the local learner''s own learning, by stage). Across multiple epics, prints a fleet roll-up (scale of read). Use when the user says "yad status", "where is epic EP-...", "what is blocking the gate", "show the trust record", "team skills", or "fleet status".'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Status (read-only)
|
|
@@ -10,7 +10,8 @@ reads `.sdlc/` and `reviews/` and reports.
|
|
|
10
10
|
|
|
11
11
|
## Conventions
|
|
12
12
|
- `{project-root}` resolves from the project working directory.
|
|
13
|
-
- Operate on one epic: `{project-root}/epics/EP-<slug>/`.
|
|
13
|
+
- Operate on one epic: `{project-root}/epics/EP-<slug>/`. The Product level is the exception:
|
|
14
|
+
`EP-foundation` lives at `{project-root}/foundation/` (its `.sdlc/` and `reviews/` are there).
|
|
14
15
|
|
|
15
16
|
## On Activation
|
|
16
17
|
|
|
@@ -20,14 +21,16 @@ report all if the user asked for an overview).
|
|
|
20
21
|
|
|
21
22
|
### Step 2 — Read state
|
|
22
23
|
Read `.sdlc/state.json`, `.sdlc/approvals.json`, `epic.md` frontmatter (for `repos`), and — if present
|
|
23
|
-
— `.sdlc/contract-lock.json`. For
|
|
24
|
+
— `.sdlc/contract-lock.json`. For Build (Phase 4), also read — if present — every
|
|
24
25
|
`.sdlc/build-state/<story-id>.json`, and the trust ledger read as the **union** of the folded
|
|
25
26
|
`.sdlc/trust-log.json` `runs` PLUS every loose `.sdlc/trust-log/` shard (concatenate — every shard is a
|
|
26
27
|
distinct run; never dedup by story/repo/step — but DO skip a shard whose full identity
|
|
27
28
|
`(story,repo,step,uid)` already appears in the folded `runs`, i.e. a half-applied `yad tidy up`). All are committed by `yad checkpoint` (so a fresh clone
|
|
28
29
|
or another machine sees current evidence; `yad tidy up` folds finished shards into `trust-log.json`).
|
|
29
30
|
Also read the `automation` block of
|
|
30
|
-
|
|
31
|
+
`.sdlc/config.yaml` (`back_steps`), and `.sdlc/automation.json` if present — the kill switch and the
|
|
32
|
+
Shape author steps set to auto (absent = the switch off, every Shape step human). The effective dial of any
|
|
33
|
+
step is `yad dial … --json`, which applies the kill switch and gates for you. For the
|
|
31
34
|
cross-cutting learning layer, also read — if present — the **local-only** `.sdlc/learning-records.json`
|
|
32
35
|
(the per-epic learning ledger, gitignored) and the project-wide `{project-root}/.sdlc/learning-records.json`.
|
|
33
36
|
Do not modify any of them.
|
|
@@ -35,72 +38,127 @@ Do not modify any of them.
|
|
|
35
38
|
### Step 3 — Report
|
|
36
39
|
Print, in this order:
|
|
37
40
|
|
|
38
|
-
1. **Header:** render the
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
1. **Header:** render the type noun from the `epic.md` frontmatter work-item type. Two names carry it,
|
|
42
|
+
`kind:` and `type:`; read `kind:` first, then `type:`. **Change request** (`change`),
|
|
43
|
+
**Defect** (`defect`), **Hotfix** (`hotfix`), **Chore** (`chore`), or **Epic** (`feature`, and the default when neither is
|
|
44
|
+
present) — followed by `epicId`, then `status` from `epic.md` frontmatter, `currentStep`, and `repos`
|
|
41
45
|
(the touched domains). Example: `Defect EP-checkout-queue-filter — draft @ stories`. A bug is a defect
|
|
42
|
-
(`
|
|
43
|
-
2. **Steps table** — for every
|
|
44
|
-
|
|
45
|
-
`currentStep` with `→`. The
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
(type `defect`) — there is no separate noun. This is presentation only; the artifact is still an epic.
|
|
47
|
+
2. **Steps table** — for every Shape step in `steps[]` order, however many there are: `id`, `type`,
|
|
48
|
+
`status`, the two dials (`driver`/`assistance` and `advance`/`automation` — read whichever the step carries, the OLD name wins), `locked`, and `risk_tags`. Mark the
|
|
49
|
+
`currentStep` with `→`. **The chain length is a fact about the epic's ROUTE, never a constant** —
|
|
50
|
+
read `profile` from `state.json`: `classic` is 10 steps, `analysis-first` 12, and the short lanes
|
|
51
|
+
`chore` 4 and `spike` 6 (E40). On `classic` the gating chain is `[analysis → analysis-review →]
|
|
52
|
+
epic → epic-review → architecture → architecture-review → ui-design → ui-design-review → stories →
|
|
53
|
+
stories-review` → **`ready-for-build`** (the bracketed `analysis` prefix is not on `classic`: it is
|
|
54
|
+
what makes `analysis-first`, the route `yad-analysis` seeds). A short lane runs `epic → epic-review → stories → stories-review` →
|
|
55
|
+
**`ready-for-build`**, with `analysis` in front on `spike`, and has no architecture, UI-design or
|
|
56
|
+
test-case rows at all — render what `steps[]` holds and never a step it lacks.
|
|
48
57
|
`test-cases → test-cases-review` is a **parallel, non-blocking track**: it opens when `stories-review`
|
|
49
|
-
passes and runs alongside
|
|
58
|
+
passes and runs alongside Build, so when `currentStep` is `ready-for-build` the `test-cases`
|
|
50
59
|
step may still be `in_progress`/`in_review` — show its status, and note "parallel" so it is clear it
|
|
51
60
|
does not gate the build. Always render exactly the steps present in `steps[]`.
|
|
52
|
-
- **Skipped (N/A) steps:** the optional `ui-design
|
|
53
|
-
|
|
54
|
-
in `steps[]`, each
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
- **Skipped (N/A) steps:** a step the epic's route marks optional — `ui-design`, on the routes that
|
|
62
|
+
ship — may be marked N/A with `yad skip`. **Both** the author step **and** its `-review` gate stay
|
|
63
|
+
in `steps[]`, each with `status: "skipped"` and a `record` (`{ reason, by, date }`). A file from
|
|
64
|
+
before shape 7 spells the same thing `status: "done"` with `skipped: true` and a `skipReason`
|
|
65
|
+
beside it; read either. Render **each** as `<id> — SKIPPED (N/A: <reason>)` (with who and when if
|
|
66
|
+
present) instead of the plain status, so the deliberate skip and its reason are visible and the
|
|
67
|
+
gate does not appear to vanish. The chain then reads `… architecture-review → ui-design (N/A) → ui-design-review (N/A) →
|
|
58
68
|
stories → …`; the review gate never needs approvals.
|
|
69
|
+
- **Deferred steps:** `yad defer` sets an optional step aside to come back to later. Both the author
|
|
70
|
+
step and its `-review` gate carry `status: "deferred"` and a `record`. Render each as
|
|
71
|
+
`<id> — DEFERRED (later: <reason>)`, with who and when if present. A deferred step is still owed:
|
|
72
|
+
never render it as done or as N/A.
|
|
73
|
+
- **Debt:** a step carrying `"debt": true` (written by `yad defer … --debt`) is owed back and must be
|
|
74
|
+
reminded until paid. Add `· DEBT` to its line, and list every debt in a short **Owed** block under
|
|
75
|
+
the chain with the command that pays it: `yad undefer <epic> <id>` while it is still `deferred` (on a verified Product,
|
|
76
|
+
say that verb is refused once the ledger is on the default branch), or
|
|
77
|
+
"being paid back — clears when `<id>-review` passes" once it is back in progress. The flag is
|
|
78
|
+
removed only when that review passes. `yad doctor` reports the same list as `step:debt`.
|
|
79
|
+
- **Closed steps:** a `done` step may carry `closed` (E18) — `{ by, date, via, pr?, … }`. Add
|
|
80
|
+
`(closed <date>, via <via>, PR #<pr>)` to its line when it is there, and nothing when it is not: a
|
|
81
|
+
step closed before this release has none, and that is not a fault.
|
|
82
|
+
- **Re-opened steps:** an unfinished step with a later step `done` (not its own `-review` gate) was
|
|
83
|
+
put back after the chain built past it — a late `yad undefer`. Render it as
|
|
84
|
+
`<id> — RE-OPENED (beside finished work)`: it does not block the finished steps after it, and
|
|
85
|
+
`currentStep` stays where it is. `yad next <epic>` prints it as a `re-opened lane`.
|
|
86
|
+
- **Blocked steps:** a step with `status: "blocked"` **and** a `record` is waiting on someone outside
|
|
87
|
+
the workflow. Render it as `<id> — BLOCKED (<reason>)`, with who recorded it and when, and say it is
|
|
88
|
+
cleared with `yad unblock <epic> <id>` once the wait is over — on a verified Product that verb refuses
|
|
89
|
+
once the ledger is on the default branch, so say so. A `blocked` with no record is the older
|
|
90
|
+
word for `todo`: render it as not started.
|
|
59
91
|
3. **Active gate** — for the `currentStep` (if it is a `review+approve` step), compute and show:
|
|
60
|
-
- the
|
|
61
|
-
|
|
62
|
-
- approvals **recorded so far** (from `approvals.json
|
|
63
|
-
- approvals **still required** to pass the gate (
|
|
92
|
+
- the count in force — **distinct approvers** recorded, against the **base** (1, enforced) and the
|
|
93
|
+
**full count** from the step's risk tags (advisory),
|
|
94
|
+
- approvals **recorded so far** (from `approvals.json`, one line per approver), and
|
|
95
|
+
- approvals **still required** to pass the gate (`1 approval(s)`, or none).
|
|
64
96
|
Do not advance — just state whether the gate would pass right now.
|
|
65
97
|
|
|
66
98
|
Apply the same predicate `yad-review-gate` uses (restated here so this skill is
|
|
67
99
|
self-contained). From the `approved` records in `approvals.json` for the current step:
|
|
68
|
-
- `
|
|
69
|
-
`
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
100
|
+
- `approvers` = the distinct, non-empty `approver` values of the approvals that are not stale (below).
|
|
101
|
+
A record that names nobody counts as nobody. When `requireEngagement` is on in the Product config,
|
|
102
|
+
only approvals with `engagement: verified` count. There are no roles; a `role` or `domain` an older
|
|
103
|
+
record carries is legacy data, and it counts for nothing.
|
|
104
|
+
- **Pass (team mode):** `|approvers| >= 1` — the base — plus, with a platform, resolved review threads and a merged
|
|
105
|
+
review PR/MR. Solo mode waives approvals entirely.
|
|
106
|
+
- **The full count, reported on every step that is not inherited, skipped or deferred:** `needed = base 1 + risk step` — plus `2` when the
|
|
107
|
+
step's `risk_tags` carry `contract`, or `1` when they carry `auth`/`payments` (the highest tag,
|
|
108
|
+
never the sum). The engine **caps** that ask at `active − 1` (floor 1) and prints it (E72) — for
|
|
109
|
+
example a contract gate asks 3, and with 2 active people the capped ask is 1. The risk step is
|
|
110
|
+
ADVISORY, capped or not — it never decides whether the gate would pass, because the count
|
|
111
|
+
of people can read high (a git name and a platform login are two people until proven one). When the
|
|
112
|
+
people could not be counted, no cap is shown. `yad gate status` prints the sum and the shortfall
|
|
113
|
+
(`; count: 3 approvers = base 1 + contract risk 2 — capped to 1: 2 active people, less one seat
|
|
114
|
+
for the author — base enforced, risk step advisory — 1 short`, or without the `capped to …` part
|
|
115
|
+
when the cap lowered nothing) — read it from there rather than recomputing it, and say "short N"
|
|
116
|
+
rather than "blocked" when it is short. A closed team gate whose ask was lowered says
|
|
117
|
+
`count capped from 3 to 1 (2 active people)`. In solo mode it prints no shortfall.
|
|
118
|
+
- **A gate that may not pass (E73):** under a team gate that has not passed, `yad gate status` can
|
|
119
|
+
print a warning line. Relay it as stated, as a warning and never as "blocked": it holds nothing.
|
|
120
|
+
A line starting `! may not be met:` means there is no approval in the counting window and the one
|
|
121
|
+
required approval may have nobody but the author to give it; another person's approval settles it.
|
|
122
|
+
A line starting `! if the risk step were enforced:` is a what-if: the extra approvals that risk
|
|
123
|
+
tags add could not all be given by the people counted. The gate can still pass today, and the line
|
|
124
|
+
says so.
|
|
125
|
+
- **How many people there are to ask (E71), printed once per epic and not per step:** `active people:
|
|
126
|
+
4 in the last 90 days — caps each gate's count at 3 approvers (one seat is left for the author);
|
|
127
|
+
reported, only the base is enforced`, with the window's basis on the line under it. It is
|
|
128
|
+
the count the cap (E72) uses, so never report a step as blocked by it. A source that could not be
|
|
129
|
+
read prints `active people: NOT COUNTED — <which source> — no cap can be shown, and only the base
|
|
130
|
+
holds each gate`: report that wording as it stands and NEVER as a number or as "no people" — an
|
|
131
|
+
unreadable input is not a small team.
|
|
132
|
+
- **Solo mode may be wrong (E74):** in solo mode, under the `active people:` line, `yad gate status`
|
|
133
|
+
can print `! solo mode is on, but … so more than one person may work on this Product`. Relay it as
|
|
134
|
+
a suggestion to run `yad mode team`, never as a fault and never as switched: nothing changes until
|
|
135
|
+
a person runs it. It never suggests solo mode.
|
|
136
|
+
- Touched domains (`epic.repos` for a step with a risk tag; the union of every story's `repos` for
|
|
137
|
+
`stories-review`) only label the review. They add no approvals.
|
|
138
|
+
- An approval is **stale** (it no longer counts) when the `artifactHash` it recorded no longer
|
|
139
|
+
matches the artifact's current fingerprint — the content changed after that person approved. For
|
|
140
|
+
`architecture-review` the fingerprint is the contract surface in `contract.md`. An approval with no
|
|
141
|
+
`artifactHash` is never stale. `yad gate status` prints the stale count. For `architecture-review`,
|
|
142
|
+
also flag when the contract-surface hash no longer matches `.sdlc/contract-lock.json`.
|
|
77
143
|
4. **Contract lock** — if `.sdlc/contract-lock.json` exists, show the locked hash and `lockedAt`
|
|
78
144
|
(and, when at/after `architecture-review`, whether the current surface still matches it).
|
|
79
145
|
5. **Stories** — if `stories/` has files, list each story `id` and its `repos` tags.
|
|
80
146
|
6. **Files** — list the review records present under `reviews/` for the current artifact.
|
|
81
|
-
7. **Build
|
|
82
|
-
each such story and each of its repos print the
|
|
147
|
+
7. **Build (per story, per repo)** — if any `.sdlc/build-state/<story-id>.json` exists, then for
|
|
148
|
+
each such story and each of its repos print the Build chain
|
|
83
149
|
`spec → tasks → implement → checks → engineer-review`, marking each step's `status`, its
|
|
84
|
-
`
|
|
85
|
-
which
|
|
150
|
+
`advance` dial (or `automation`, whichever the step carries), and `locked`. Mark that repo's `currentStep` with `→`. A repo whose lane is `status: skipped` (a whole lane set aside with `yad skip <epic> <story> --repo <repo>`, E39) prints `skipped (N/A)` and its `record.reason` instead of the chain. This shows, at a glance,
|
|
151
|
+
which Build steps are automated and where a run is waiting. (For the single *next* build sub-step to
|
|
86
152
|
take per story/repo — rather than this full status view — point the user at `yad next <epic>`, which
|
|
87
153
|
reads the same `build-state` files.)
|
|
88
|
-
8. **Automation &
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
Never recommend flipping a locked step or a front state — those can never be `machine_advance`.
|
|
97
|
-
|
|
98
|
-
**Nudge-cost signal (Phase 5 instrumentation).** For each back step that is **earned but its dial
|
|
99
|
-
is still `human_approve`** (and it is not locked / not a front state), flag it:
|
|
100
|
-
`⚠ earned but manual — could be machine_advance`. This is the *nudge cost* the Phase 5 trigger
|
|
101
|
-
watches: automation that is proven safe but still hand-started. It is a read-only observation, not a
|
|
102
|
-
recommendation to flip — earning the evidence and flipping the dial stay deliberate human acts
|
|
103
|
-
(`yad-run action: set-dial`). See `docs/phase-5-build-plan.md` §"What to instrument now".
|
|
154
|
+
8. **Automation & run record** — print the **kill switch** from `.sdlc/automation.json` (when on, who
|
|
155
|
+
turned it on, when and why, and that every step is held at `advance: human`), and the Shape author
|
|
156
|
+
steps the project set to `auto` — noting that a Shape `auto` is recorded only: nothing drives a Shape
|
|
157
|
+
step on its own yet. Then, for each Build step that has entries in the trust ledger — the **union** of
|
|
158
|
+
the folded `.sdlc/trust-log.json` `runs` plus every loose `.sdlc/trust-log/` shard — print its **run
|
|
159
|
+
record**: number of runs and the fraction with `verdict == "approved-unchanged"`. It is **advice**:
|
|
160
|
+
there is no threshold and nothing is "earned" (E34). Do not recommend flipping a dial; the team sets
|
|
161
|
+
dials with `yad dial`. A review gate is never auto.
|
|
104
162
|
|
|
105
163
|
9. **My skills (the learning layer — local-only).** If `.sdlc/learning-records.json` exists for the epic
|
|
106
164
|
(or the project-wide ledger does), print the **personal skills-log** roll-up from it — read-only. These
|
|
@@ -117,10 +175,10 @@ Print, in this order:
|
|
|
117
175
|
|
|
118
176
|
10. **Fleet roll-up (overview only).** When the user asked for an overview, or more than one epic exists
|
|
119
177
|
under `{project-root}/epics/`, print a one-line-per-epic roll-up across the fleet: each epic's
|
|
120
|
-
`currentStep` (
|
|
121
|
-
at a human gate
|
|
178
|
+
`currentStep` (Shape gate) and, for stories in Build, a count of Build steps **waiting
|
|
179
|
+
at a human gate**, plus a **local skills-log** count (records
|
|
122
180
|
in the local-only `learning-records.json`: learned / in-progress). Close with fleet totals (epics at
|
|
123
|
-
each
|
|
181
|
+
each Shape gate; total concepts learned locally across the fleet).
|
|
124
182
|
This is the
|
|
125
183
|
*scale-of-read* signal the Phase 5 trigger watches — when this roll-up stops fitting in one glance,
|
|
126
184
|
that is the measured bottleneck. Still strictly read-only; it only scans the per-epic files.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-stories
|
|
3
|
-
description: '
|
|
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
|
-
# SDLC — Author Stories (
|
|
6
|
+
# SDLC — Author Stories (Shape step 7)
|
|
7
7
|
|
|
8
8
|
**Goal:** Break an approved epic into human-authored, AI-assisted user stories, each with a stable
|
|
9
|
-
`EP-<slug>-S0N` ID and a `repos` tag listing which repos must implement it. This is a **
|
|
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,8 +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
|
-
|
|
41
|
-
from the
|
|
40
|
+
Product's default branch. Author and commit the story files under `stories/` on it. This is **distinct**
|
|
41
|
+
from the verified ledger's `review/…` branch.
|
|
42
42
|
|
|
43
43
|
### Step 2 — Read inputs
|
|
44
44
|
Read `epic.md` (scope, acceptance signals, `repos`), `architecture.md` (components by repo, flows),
|
|
@@ -48,7 +48,18 @@ must collectively satisfy the epic's acceptance signals and stay within the cont
|
|
|
48
48
|
- **UI-optional-safe:** `ui-design.md` may be absent — the `ui-design` step is optional and can be
|
|
49
49
|
marked N/A for an epic with no user-facing surface (state.json shows it `skipped`). When there is no
|
|
50
50
|
UI design, proceed without UI screens; the epic's acceptance signals + contract remain the source of
|
|
51
|
-
truth for the stories.
|
|
51
|
+
truth for the stories. If state.json shows it `deferred` instead, the UI **will** come later: write the
|
|
52
|
+
stories so they do not assume there are no screens, and note in each story that touches the UI that
|
|
53
|
+
its screens are still to be designed.
|
|
54
|
+
- **Short-lane-safe:** `architecture.md` and `contract.md` may BOTH be absent, and on the `chore` and
|
|
55
|
+
`spike` routes they always are — those lanes carry no architecture step, so there is no locked
|
|
56
|
+
contract for this epic. Read `state.json`'s `profile` key first — an epic seeded before file shape 6
|
|
57
|
+
has no such key, so fall back to what its `steps[]` actually contains, which is the real answer
|
|
58
|
+
either way. On a short lane, write the stories
|
|
59
|
+
from `epic.md` alone and say so in each story's "Contract & design touchpoints" section. Because
|
|
60
|
+
there is no lock, a story on a short lane **must not change the shared cross-repo surface**: if the
|
|
61
|
+
work turns out to need that, stop and say so — the epic belongs on `classic`, which has the
|
|
62
|
+
architecture gate that locks the surface.
|
|
52
63
|
|
|
53
64
|
### Step 2b — Load existing-code context (make the brain code-aware)
|
|
54
65
|
Read the registry `{project-root}/.sdlc/repos.json` (`config.yaml` `code_context`). For **each repo in
|
|
@@ -63,7 +74,7 @@ Phase 3 build (Spec Kit per repo) accurate anchors instead of invented ones.
|
|
|
63
74
|
- **Traceability:** record the loaded maps in each story's `code-context:` frontmatter field.
|
|
64
75
|
|
|
65
76
|
### Step 3 — Break down the epic (assist: pm)
|
|
66
|
-
Adopt the **pm** lens
|
|
77
|
+
Adopt the **pm** lens. Decompose the epic into the smallest set of
|
|
67
78
|
independently reviewable, independently buildable stories. For each story decide which repos it touches
|
|
68
79
|
(must be a subset of the epic's `repos`). Prefer stories scoped to a clear slice of user value.
|
|
69
80
|
|
|
@@ -102,36 +113,40 @@ As a <role>, I want <capability>, so that <outcome>.
|
|
|
102
113
|
|
|
103
114
|
### Step 6 — Advance the authoring step (NOT the gate)
|
|
104
115
|
**Check the mode first — the two modes have opposite instructions here.** Read `.sdlc/hub.json`:
|
|
105
|
-
**
|
|
116
|
+
**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
117
|
|
|
107
|
-
**
|
|
108
|
-
any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,hub-prs}.json` or
|
|
118
|
+
**verified mode — do NOT write `state.json`.** The ledger is CI-owned: the `ledger-guard` check rejects
|
|
119
|
+
any non-bot commit touching `epics/*/.sdlc/{state,approvals,comments,product-prs,hub-prs}.json` or
|
|
109
120
|
`epics/*/reviews/*.md`, `yad gate open` deliberately skips this write for the same reason, and
|
|
110
121
|
`yad gate ci --merged` performs the whole transition when the review PR merges. Making the edit here
|
|
111
122
|
fails the gate if it rides the review PR, and desynchronises the ledger CI is about to rewrite if it
|
|
112
123
|
is pushed around the gate. Commit **the story files under `stories/` only** — nothing else
|
|
113
124
|
under `.sdlc/` — then hand off to `yad-review-gate`.
|
|
114
125
|
|
|
115
|
-
**Otherwise —
|
|
116
|
-
`stories
|
|
117
|
-
|
|
126
|
+
**Otherwise — local, or a platform with no gate-sync CI — the engine makes this edit, not you.**
|
|
127
|
+
`yad gate open <epic> stories/` marks `stories-review` `in_review`, closes `stories` as `done`, and moves `currentStep` to the gate
|
|
128
|
+
— the same transition, from the one function that owns it (`markInReview`, `cli/epic-state.mjs`).
|
|
129
|
+
`yad-review-gate action: open` runs that command; hand off to it rather than editing the ledger here.
|
|
118
130
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
**With no platform configured** it writes the ledger and simply opens no PR, so this works offline.
|
|
132
|
+
**With a platform** the `review/EP-<slug>/stories` branch must already be **on origin** — the command
|
|
133
|
+
refuses and writes nothing otherwise. Cut it from the authoring branch and push it before handing off
|
|
134
|
+
(or run `yad open-pr` from that branch: it pushes the branch, then delegates).
|
|
135
|
+
|
|
136
|
+
Do **not** hand-edit `state.json`, and do **not** touch `approvals.json` — only real reviewers approve,
|
|
137
|
+
through the gate.
|
|
124
138
|
|
|
125
139
|
### Step 7 — Stop at the gate (do NOT advance)
|
|
126
140
|
Report: the story IDs created, the repos each touches, and that the next action is **review** via
|
|
127
|
-
`yad-review-gate`.
|
|
128
|
-
|
|
129
|
-
|
|
141
|
+
`yad-review-gate`. This review is an ordinary count gate: it passes with at least 1 distinct approver (who
|
|
142
|
+
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
|
|
143
|
+
reviewers — the team asks them on the review PR itself. When this gate
|
|
144
|
+
passes the epic becomes **`ready-for-build`** — Build can start **and** the parallel
|
|
130
145
|
**`test-cases`** track opens for the tester (`yad-test-cases`); the two run at the same time. **Never record
|
|
131
|
-
approval here.**
|
|
132
|
-
PR on the
|
|
146
|
+
approval here.** Shape steps do not auto-advance. When the Product has a platform, the gate opens a review
|
|
147
|
+
PR on the Product (via `yad-hub-bridge`, with a `domain:<repo>` label per touched repo) and
|
|
133
148
|
`yad-review-gate action: sync` pulls platform approvals/comments into the ledger; otherwise the review
|
|
134
|
-
is recorded
|
|
149
|
+
is recorded local.
|
|
135
150
|
|
|
136
151
|
## Reference
|
|
137
152
|
- Story frontmatter and body template: `references/story-schema.md`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Story schema
|
|
2
2
|
|
|
3
|
-
Each story authored at
|
|
3
|
+
Each story authored at Shape step 7 is one Markdown file under `epics/EP-<slug>/stories/`, named
|
|
4
4
|
`EP-<slug>-S0N.md` (zero-padded, never renamed).
|
|
5
5
|
|
|
6
6
|
## Frontmatter
|
|
@@ -9,10 +9,10 @@ Each story authored at front state 7 is one Markdown file under `epics/EP-<slug>
|
|
|
9
9
|
|-------|--------|---------|
|
|
10
10
|
| `id` | `EP-<slug>-S0N` | Stable story ID. Engine-assigned, zero-padded, never renamed. |
|
|
11
11
|
| `epic` | `EP-<slug>` | Parent epic ID — the unbroken link back to the epic. |
|
|
12
|
-
| `owner` | name | Inherited from `epic.md` `owner` (the single source — not retyped per story). Carries the responsible owner through to
|
|
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. **
|
|
15
|
-
| `code-context` | `{ repos: [<name@sha>], loaded: <date> }` | Optional. Which connected-repo code-maps anchored "Notes for build" (
|
|
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
|
+
| `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
|
|
18
18
|
|
|
@@ -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,53 +101,47 @@ 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 front 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`).
|
|
130
141
|
- **Make it real later:** `yad-backfill` for the code repo, then `yad-backfill promote EP-<slug>` to flip
|
|
131
142
|
the stub to `verified: true`.
|
|
132
143
|
|
|
133
|
-
|
|
144
|
+
Shape steps do not auto-advance. Suggest `yad next EP-<slug>` (prints the backfill-pending guidance) and
|
|
134
145
|
`yad thread EP-<slug>` to see the anchor and everything threaded off it.
|
|
135
146
|
|
|
136
147
|
## Hard rules
|
|
@@ -143,7 +154,7 @@ Front states do not auto-advance. Suggest `yad next EP-<slug>` (prints the backf
|
|
|
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
|
|