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
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
`yad-docs-overview` reuses the per-epic shell, but the *content* is the **workflow itself** rather than
|
|
4
4
|
one epic's flows. This file pins how the setup→ship pipeline maps onto the shell's primitives. The
|
|
5
5
|
ordering source of truth is `skills/sdlc/module-help.csv` (`phase`, `preceded-by`, `followed-by`,
|
|
6
|
-
`outputs`); the
|
|
6
|
+
`outputs`); the dial defaults come from `skills/sdlc/config.yaml`; the node classes come from
|
|
7
7
|
`docs/diagrams/sdlc-overview.mmd`.
|
|
8
8
|
|
|
9
9
|
## Primitive mapping
|
|
10
10
|
|
|
11
11
|
| Shell primitive | Overview meaning |
|
|
12
12
|
|-----------------|------------------|
|
|
13
|
-
| `FlowPath` (`paths.ts`) | a **phase**: Setup, Front-zero (discovery),
|
|
13
|
+
| `FlowPath` (`paths.ts`) | a **phase**: Setup, Front-zero (discovery), Shape, Build, Automation, Change management (feature threads). |
|
|
14
14
|
| `FlowStep` (within a path) | a **skill or gate** in order; `messages` = its `outputs`; `sideEffects` = the `.sdlc/` files it writes; `status`/`bookingStatus` annotate gated vs. enrichment vs. earned. |
|
|
15
|
-
| `SystemComponent` (`components.ts`) | a **durable state object** (the
|
|
15
|
+
| `SystemComponent` (`components.ts`) | a **durable state object** (the Product, each `.sdlc/*.json`, code repos, the design/testing/learning tools, the platform). |
|
|
16
16
|
| `RoleConfig` (`roles.ts`) | a **lens** → its relevant sections + paths. |
|
|
17
|
-
| doc sections (`docSections.ts`/`referenceData.ts`) | the phase narratives + the dial
|
|
17
|
+
| doc sections (`docSections.ts`/`referenceData.ts`) | the phase narratives + the dial reference tables (from `config.yaml` + the build-plan docs). |
|
|
18
18
|
|
|
19
19
|
## Flow paths = phases, with their skills in order
|
|
20
20
|
|
|
@@ -26,40 +26,59 @@ and never gates.
|
|
|
26
26
|
|
|
27
27
|
| Step (skill) | Outputs / sideEffects |
|
|
28
28
|
|--------------|------------------------|
|
|
29
|
-
| `yad-connect-repos` | `repos.json`, `code-context/<repo>/pack.md` + `code-map.md` (+ `detect-hub
|
|
29
|
+
| `yad-connect-repos` | `repos.json`, `code-context/<repo>/pack.md` + `code-map.md` (+ `detect-hub` → `hub.json`) |
|
|
30
30
|
| `yad-connect-design` | `design.json` |
|
|
31
31
|
| `yad-connect-testing` | `testing.json` |
|
|
32
32
|
| `yad-connect-learning` | `learning.json` |
|
|
33
33
|
| `yad-connect-docs` | `docs.json` |
|
|
34
34
|
|
|
35
35
|
### Path: Front-zero (`phase: 0-front`)
|
|
36
|
-
The OPTIONAL once-per-
|
|
37
|
-
Greenfield AND brownfield; a 2-step author→review chain whose
|
|
38
|
-
and terminates at `
|
|
36
|
+
The OPTIONAL once-per-product **Foundation** (E75) — the Product level, in its own folder `foundation/`
|
|
37
|
+
under the fixed id `EP-foundation`. Greenfield AND brownfield; a 2-step author→review chain whose
|
|
38
|
+
review binds to the required sections and terminates at `foundation-done` (no Build). Its approval is
|
|
39
|
+
reported, not enforced, before feature work begins.
|
|
39
40
|
|
|
40
41
|
| Step (skill) | Gate | Outputs / sideEffects |
|
|
41
42
|
|--------------|------|------------------------|
|
|
42
|
-
| `yad-discovery` *(optional)* | → `
|
|
43
|
+
| `yad foundation new` then `yad-discovery` *(optional)* | → `foundation-review` (base rule) | `purpose.md`, `scope.md`, `mvp.md`, `roadmap.md`, `stack.md`, `repos.md` (+ optional `market.md`, `risks.md`); seeds `foundation/.sdlc/state.json` |
|
|
43
44
|
|
|
44
45
|
`roadmap.md` is the menu of features each `yad-epic` reads (Step 2c) — reference-only, never
|
|
45
|
-
auto-seeds epics.
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
auto-seeds epics. A product created before E75 may still hold the old spelling, `epics/EP-discovery/`
|
|
47
|
+
(six files, ending at `discovery-done`); `yad migrate --apply` converts it on a local ledger.
|
|
48
|
+
|
|
49
|
+
<!-- `1-front` and `3-build` are DATA — the `phase` column in skills/sdlc/module-help.csv, which
|
|
50
|
+
the overview build reads. The Shape/Build/Run rename deliberately left them alone: change-safety
|
|
51
|
+
rule 3 says a release may add but never rename, so a stored value moves in a major with a
|
|
52
|
+
migration, not in a wording sweep. The display names below are the new vocabulary; the ids are
|
|
53
|
+
the old one, on purpose. -->
|
|
54
|
+
|
|
55
|
+
<!-- Each skill's `phase` in module-help.csv agrees with where this model places it. `4-automate` holds
|
|
56
|
+
yad-run and the docs skills; `6-change` holds yad-change, yad-stub, yad-timeline, yad-defects and
|
|
57
|
+
yad-reconcile; yad-status (a read-only view) and yad-learn (a tutor for any stage) are `anytime`, the
|
|
58
|
+
value for a skill available at every stage — they are listed under
|
|
59
|
+
Automation below only because the site needs one place to draw them. yad-report has no phase: it is
|
|
60
|
+
a CLI helper, not a pipeline step.
|
|
61
|
+
Moving three of these from `1-front` needed no migration, and that does not contradict the note
|
|
62
|
+
above: module-help.csv is catalogue content the tool ships, read from the package's skills/sdlc/ folder
|
|
63
|
+
and never installed into a project. It is not state a user's project stores. The note above is about
|
|
64
|
+
the `1-front` / `3-build` ids as they are read back. -->
|
|
65
|
+
|
|
66
|
+
### Path: Shape (`phase: 1-front`)
|
|
48
67
|
The gated authoring chain + the reusable review gate (10 steps, or 12 with the optional analysis).
|
|
49
68
|
|
|
50
69
|
| Step (skill) | Gate | Outputs / sideEffects |
|
|
51
70
|
|--------------|------|------------------------|
|
|
52
71
|
| `yad-analysis` *(optional)* | → `analysis-review` | `analysis.md`, seeds `state.json` |
|
|
53
72
|
| `yad-epic` | → `epic-review` | `epic.md`, seeds `state.json` |
|
|
54
|
-
| `yad-architecture` | → `architecture-review` (
|
|
73
|
+
| `yad-architecture` | → `architecture-review` (contract tag raises the count) | `architecture.md`, `contract.md`, `contract-lock.json` |
|
|
55
74
|
| `yad-ui` | → `ui-design-review` | `ui-design.md`, `DESIGN.md`, `design-links.json` |
|
|
56
|
-
| `yad-stories` | → `stories-review` (
|
|
75
|
+
| `yad-stories` | → `stories-review` (labelled with every touched repo) | `stories/EP-<slug>-S0N.md` |
|
|
57
76
|
| `yad-test-cases` | → `test-cases-review` (parallel, non-blocking) | `test-cases.md`, `test-links.json` |
|
|
58
77
|
| `yad-review-gate` | the shared gate | `reviews/*.md`, `approvals.json`, `comments.json` |
|
|
59
78
|
| `yad-review-companion` | the fun/visible review layer (trailer/cards/chat + engagement) | `approvals.json` `engagement`, platform trailer/cards |
|
|
60
79
|
| `yad-hub-bridge` | the platform PR/MR bridge | `hub-prs.json` |
|
|
61
80
|
|
|
62
|
-
### Path: Build
|
|
81
|
+
### Path: Build (`phase: 3-build`)
|
|
63
82
|
Per-story, per-repo: `spec → tasks → implement → checks → engineer-review`, plus the commit/PR helpers.
|
|
64
83
|
|
|
65
84
|
| Step (skill) | Outputs / sideEffects |
|
|
@@ -70,15 +89,15 @@ Per-story, per-repo: `spec → tasks → implement → checks → engineer-revie
|
|
|
70
89
|
| `yad-pr-template` | PR/MR template + routing helpers |
|
|
71
90
|
| `yad-commit` / `yad-open-pr` / `yad-ship` | one commit / one PR/MR |
|
|
72
91
|
| `yad-engineer-review` | engineer review + ship recorded as a `build-log/` shard |
|
|
73
|
-
| `yad-backfill` | DRAFT specs for legacy features |
|
|
92
|
+
| `yad-backfill` | DRAFT specs for legacy features — its own step in the Build path (Step G, brownfield) |
|
|
74
93
|
|
|
75
|
-
### Path: Automation (the second dial + observation
|
|
94
|
+
### Path: Automation (`phase: 4-automate`) — the second dial + observation
|
|
76
95
|
The orchestrator + the trust evidence + the read-only views. Maps the **earns** / **locked** / **sentinel**
|
|
77
96
|
node classes from the diagram.
|
|
78
97
|
|
|
79
98
|
| Step (skill) | Outputs / sideEffects |
|
|
80
99
|
|--------------|------------------------|
|
|
81
|
-
| `yad-run` | drives the
|
|
100
|
+
| `yad-run` | drives the Build loop; `build-state/<story>.json`, `trust-log.json`; dials and kill switch through `yad dial` / `yad kill` (`.sdlc/automation.json`) |
|
|
82
101
|
| `yad-learn` | tutoring; `learning-records.json` (LOCAL-ONLY, gitignored) |
|
|
83
102
|
| `yad-status` | read-only view (no writes) |
|
|
84
103
|
| `yad-docs` / `yad-docs-overview` / `yad-docs-sync` | the docs sites + their `docs-build.json` manifests |
|
|
@@ -86,24 +105,24 @@ node classes from the diagram.
|
|
|
86
105
|
### Path: Change management — feature threads (`phase: 6-change`)
|
|
87
106
|
The post-lock evolution layer. Once an epic is **sealed** (all stories shipped), behaviour can no longer
|
|
88
107
|
be mutated in place — a change request becomes a **new epic threaded to its parent** (genesis → change →
|
|
89
|
-
defect), inheriting unchanged
|
|
108
|
+
defect), inheriting unchanged Shape artifacts **by reference** and re-authoring only what changes, so
|
|
90
109
|
locked artifacts are never mutated and never go stale, only superseded. Three CI gates enforce the thread
|
|
91
|
-
(`lineage-check`, `epic-open`, `reconcile-debt`). This path never gates the
|
|
110
|
+
(`lineage-check`, `epic-open`, `reconcile-debt`). This path never gates the Shape chain; `yad-change` is
|
|
92
111
|
the intake, then it hands off to the normal authoring skills + the review gate.
|
|
93
112
|
|
|
94
113
|
| Step (skill) | Outputs / sideEffects |
|
|
95
114
|
|--------------|------------------------|
|
|
96
|
-
| `yad-change` | intake + triage depth (defect-fix / behavioral-no-surface / contract-surface / new-capability);
|
|
115
|
+
| `yad-change` | intake + triage depth (defect-fix / behavioral-no-surface / contract-surface / new-capability); writes a threaded change-epic's lineage frontmatter and `change.json`, seeds its ledger with `yad epic new --parent` (inherited-step `state.json`, pointer-lock `contract-lock.json` — E42), and opens `reconcile-debt.json` for hotfixes |
|
|
97
116
|
| `yad-timeline` | `TIMELINE.md` (the thread evolution view) + `thread-resolved.md` (the resolved current truth) |
|
|
98
117
|
| `yad-defects` | `DEFECTS.md` (quality-gap report by `escape_stage` + root cause) |
|
|
99
118
|
| `yad-reconcile` | advisory drift / orphan / debt sweep (read-only; mirrors `yad-docs-sync`) |
|
|
100
119
|
|
|
101
120
|
CLI: `yad thread [<epic>]` prints a thread + its resolved current truth + open debt; `yad reconcile`
|
|
102
|
-
runs the sweep. The three thread gates ride in the
|
|
121
|
+
runs the sweep. The three thread gates ride in the Build `yad-checks` set above.
|
|
103
122
|
|
|
104
123
|
## System components = the durable state objects
|
|
105
124
|
|
|
106
|
-
`components.ts` renders these on the canvas (deterministic positions): the **
|
|
125
|
+
`components.ts` renders these on the canvas (deterministic positions): the **Product**; each
|
|
107
126
|
`.sdlc/*.json` (`state.json`, `approvals.json`, `comments.json`, `hub.json`, `repos.json`, `design.json`,
|
|
108
127
|
`testing.json`, `learning.json`, `docs.json`, `contract-lock.json`, `build-state/*`, `trust-log.json`,
|
|
109
128
|
and the change-thread ledgers `change.json`, `reconcile-debt.json`, `build-log.json`);
|
|
@@ -121,13 +140,13 @@ The eight yadflow lenses, each to its relevant phase sections + paths:
|
|
|
121
140
|
|
|
122
141
|
| Lens | Relevant phases / sections |
|
|
123
142
|
|------|----------------------------|
|
|
124
|
-
| analyst | Setup intent,
|
|
125
|
-
| pm |
|
|
126
|
-
| architect | architecture + the locked contract;
|
|
143
|
+
| analyst | Setup intent, the Foundation (the Product level), analysis step, Shape discovery |
|
|
144
|
+
| pm | the Foundation (purpose/scope/MVP/roadmap), epic, stories; the Shape gates |
|
|
145
|
+
| architect | architecture + the locked contract; the contract risk step |
|
|
127
146
|
| ux | UI design, design tool connection, the design system |
|
|
128
|
-
| dev |
|
|
147
|
+
| dev | Build: spec → implement, the per-repo loop |
|
|
129
148
|
| tester | test-cases (parallel track), the testing tool, checks |
|
|
130
|
-
| reviewer | the review gate, comments, the
|
|
149
|
+
| reviewer | the review gate, comments, the Product bridge |
|
|
131
150
|
| engineer | engineer review + ship, the merge gate, automation dial/trust |
|
|
132
151
|
|
|
133
152
|
## Determinism + theme
|
|
@@ -16,14 +16,14 @@ silent (the same discipline as `yad repo refresh`).
|
|
|
16
16
|
|
|
17
17
|
## Conventions
|
|
18
18
|
|
|
19
|
-
- `{project-root}` resolves from the project working directory (the **
|
|
19
|
+
- `{project-root}` resolves from the project working directory (the **Product**).
|
|
20
20
|
- Per-epic baseline: `epics/EP-<slug>/.sdlc/docs-build.json` (written by `yad-docs`). Overview baseline:
|
|
21
21
|
`docs/sdlc-site/.docs-build.json` (written by `yad-docs-overview`).
|
|
22
22
|
- The hashing + build + deploy is the **`yad docs sync` CLI**'s job; the regeneration of a stale site is
|
|
23
23
|
delegated back to `yad-docs` / `yad-docs-overview` (the AI generation step). This skill orchestrates
|
|
24
24
|
the reconcile.
|
|
25
25
|
- The docs target is `.sdlc/docs.json` (`yad-connect-docs`).
|
|
26
|
-
- Speak in the
|
|
26
|
+
- Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write documents in `document_output_language`.
|
|
27
27
|
|
|
28
28
|
## Inputs
|
|
29
29
|
|
|
@@ -50,17 +50,22 @@ Read each `docs-build.json` and compare. A site is **stale** when **any** of:
|
|
|
50
50
|
- any `repoHeads[<repo>]` differs from the repo's current HEAD (the code the components cite advanced —
|
|
51
51
|
the same head-sha staleness as `repos.json`), or
|
|
52
52
|
- for the overview, `config.yaml` / `module-help.csv` / the `.mmd` / `skillCount` moved, or
|
|
53
|
-
-
|
|
53
|
+
- for a per-epic site, its `shellVersion` differs from the `version` in `skills/yad-docs/templates/app/package.json`
|
|
54
|
+
(the shell was upgraded). The overview has no shell version: it is updated in place, not re-copied. An
|
|
55
|
+
older manifest records only `templateVersion` (the yad CLI version, which changed on every release). That
|
|
56
|
+
value is never compared; such a manifest counts as built on shell `0.0.0`, the only version before this.
|
|
54
57
|
|
|
55
58
|
A missing `docs-build.json` (a site never generated) counts as **stale → needs generate**.
|
|
56
59
|
|
|
57
60
|
### Step 3 — Act on `action`
|
|
58
61
|
- **`check`** (default, **read-only**) — print which sites are stale and **WHY**, in `yad check` drift
|
|
59
62
|
style: *which artifact moved* (name it), *which repo HEAD advanced* (`<repo>: <old>→<new>`), *config /
|
|
60
|
-
manifest / diagram / skill-count changed*, or *shell upgraded* (`
|
|
63
|
+
manifest / diagram / skill-count changed*, or *shell upgraded* (`shellVersion`, per-epic only). Writes nothing.
|
|
61
64
|
- **`refresh`** — for each stale site, re-run the generator (`yad-docs` for an epic site, `yad-docs-overview`
|
|
62
65
|
for the overview) to regenerate `src/data/*.ts` + theme + manifest, then redeploy via `yad docs deploy`
|
|
63
|
-
(degrading to build-only when no platform CLI). Report every site refreshed
|
|
66
|
+
(degrading to build-only when no platform CLI). Report every site refreshed, and every site whose
|
|
67
|
+
rebuild failed: `yad docs sync --refresh` exits 1 when a stale site's npm install or build fails, and
|
|
68
|
+
its `--json` `sites` rows say which (`built: false` with an `error`). **Never silent** — refresh
|
|
64
69
|
is a deliberate human/CI act, surfaced exactly like `yad repo refresh`.
|
|
65
70
|
- **`wire`** — commit the CI workflow (Step 4) that automates the check + rebuild.
|
|
66
71
|
|
|
@@ -16,7 +16,7 @@ the current inputs, or its shell template is out of date. This mirrors the `repo
|
|
|
16
16
|
"artifactHash": "<sha256 of epic.md + architecture.md + contract.md CONTRACT-SURFACE + ui-design.md + each story>",
|
|
17
17
|
"repoHeads": { "<repo>": "<HEAD sha>" },
|
|
18
18
|
"deployUrl": "<url or null>",
|
|
19
|
-
"
|
|
19
|
+
"shellVersion": "<the `version` in templates/app/package.json>"
|
|
20
20
|
}
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -28,8 +28,7 @@ the current inputs, or its shell template is out of date. This mirrors the `repo
|
|
|
28
28
|
"theme": "yadflow-brand",
|
|
29
29
|
"artifactHash": "<sha256 of config.yaml + module-help.csv + docs/diagrams/sdlc-overview.mmd>",
|
|
30
30
|
"skillCount": <number of yad-* skills>,
|
|
31
|
-
"deployUrl": "<url or null>"
|
|
32
|
-
"templateVersion": "<shell template version>"
|
|
31
|
+
"deployUrl": "<url or null>"
|
|
33
32
|
}
|
|
34
33
|
```
|
|
35
34
|
|
|
@@ -55,10 +54,12 @@ A site is **stale** when ANY holds:
|
|
|
55
54
|
repo is *flagged*, never auto-refreshed: the `code-context` itself is refreshed by a human via
|
|
56
55
|
`yad repo refresh`, and the docs are regenerated only on an explicit `refresh`/CI decision;
|
|
57
56
|
3. (overview) `config.yaml` / `module-help.csv` / the `.mmd` moved — the pipeline changed (this is what
|
|
58
|
-
enforces "the overview regenerates whenever the workflow definition or skill set changes");
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
enforces "the overview regenerates whenever the workflow definition or skill set changes");
|
|
58
|
+
4. (per-epic) manifest `shellVersion` ≠ the `version` in `templates/app/package.json` — the shell was
|
|
59
|
+
upgraded, so the site should re-copy it. The overview has no shell version (it is updated in place).
|
|
60
|
+
A manifest's older `templateVersion` field held the yad CLI version, which moved on every release, so
|
|
61
|
+
it is never compared: a manifest with only that field counts as built on shell `0.0.0`, the one version
|
|
62
|
+
the shell had before `shellVersion` existed. It reads fresh today, and a real shell upgrade still shows;
|
|
62
63
|
5. the `docs-build.json` is **missing** — the site was never generated (treat as stale → generate).
|
|
63
64
|
|
|
64
65
|
`check` reports which of these tripped and why; `refresh` regenerates + redeploys; neither blocks any
|
|
@@ -1,38 +1,41 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yad-engineer-review
|
|
3
|
-
description: 'Build
|
|
3
|
+
description: 'Build Step E of the gated SDLC — AI review, engineer review, then merge. Wire an advisory AI first-pass (CodeRabbit) on the PR/MR; record the human engineer review with the same advance-human discipline as the Shape gates (1 distinct approver, who should not be the author; high risk / contract raise the full count, advisory, not enforced — the Step D routing); and on merge, record the ship in the epic build-log and update the story state so the epic → story → task → PR chain is traceable. Never auto-advances — the human owns the merge. Use when the user says "record the engineer review", "merge this task", or "wire the AI review". (To commit + open the PR/MR, use yad-ship.)'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# SDLC — Engineer Review & Merge (
|
|
6
|
+
# SDLC — Engineer Review & Merge (Build Step E)
|
|
7
7
|
|
|
8
8
|
**Goal:** Take a task PR/MR that has passed the **check gates** (Step C) through two sets of eyes and
|
|
9
9
|
out to production: an **AI first-pass** (advisory) and a **human engineer review** (the authority),
|
|
10
|
-
then **ship** — merge, record the ship, and update the story state. This is the last
|
|
11
|
-
(build plan §E). It is a **human gate**, the same `
|
|
10
|
+
then **ship** — merge, record the ship, and update the story state. This is the last Build step
|
|
11
|
+
(build plan §E). It is a **human gate**, the same `advance: human` discipline as the Shape steps:
|
|
12
12
|
**nothing auto-advances**; the engineer owns the merge.
|
|
13
13
|
|
|
14
14
|
## Conventions
|
|
15
15
|
|
|
16
16
|
- `{project-root}` resolves from the project working directory — the **product** repo (the source of
|
|
17
17
|
truth: it holds the story and the build ledger).
|
|
18
|
-
- Code repos are separate git repos under `{project-root}/demo-repos/<repo
|
|
18
|
+
- Code repos are separate git repos under `{project-root}/demo-repos/<repo>/` (or the registry `path` in
|
|
19
|
+
`.sdlc/repos.json`).
|
|
19
20
|
- The build ledger uses **shard-then-fold** storage: each ship is its own shard file
|
|
20
21
|
`{project-root}/epics/<epic>/.sdlc/build-log/<story>-<task>-<repo>.json`, so concurrent shippers never
|
|
21
22
|
conflict; readers UNION the folded `build-log.json` with every loose shard, and `yad tidy up` folds
|
|
22
23
|
finished shards back into `build-log.json`. It — like the trust log and build-state — is committed by
|
|
23
24
|
`yad checkpoint` (see Step 3), not by hand.
|
|
24
|
-
- The engineer-review rule reuses `yad-review-gate
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
- The engineer-review rule reuses `yad-review-gate`'s count: `needed = base 1 + risk step` distinct
|
|
26
|
+
approvers. The risk step comes from the PR's Impact & Risk block — `high` risk +1, a touched contract
|
|
27
|
+
surface +2 — and from the code repo's risk map on the **base branch**: a change touching a `high`
|
|
28
|
+
directory +1 (E66). The largest step wins, never the sum. The count is reported, not enforced: branch protection holds the merge (at least 1
|
|
29
|
+
distinct approver, who should not be the author), and the risk step is advisory. `yad open-pr` shows
|
|
30
|
+
the count capped by the active people (E72); the check scripts cannot cap it. This is what `yad-pr-template`'s `risk-route.sh`
|
|
31
|
+
prints. The real merge protection is the platform's branch protection.
|
|
28
32
|
- AI review wiring: `templates/.coderabbit.yaml` → `<repo>/.coderabbit.yaml`.
|
|
29
33
|
|
|
30
34
|
## Inputs
|
|
31
35
|
|
|
32
36
|
- `epic` / `story` / `task` / `repo` — the PR under review (the task branch `feat/<story>-<task>-…`).
|
|
33
37
|
- `action` — `ai-review` | `approve` | `ship` (default `ai-review`).
|
|
34
|
-
- For `approve`: the reviewer
|
|
35
|
-
domain owner the `domain`.
|
|
38
|
+
- For `approve`: the reviewer's platform login. No role and no domain.
|
|
36
39
|
|
|
37
40
|
## On Activation
|
|
38
41
|
|
|
@@ -58,29 +61,84 @@ never gates. When a pair session backs the approve, you may set `companion.pair:
|
|
|
58
61
|
|
|
59
62
|
### Step 2 — `approve` (the engineer review — the human gate)
|
|
60
63
|
A human engineer reads the diff **against the spec** (`specs/<story>/`) and the acceptance criteria,
|
|
61
|
-
and records an approval. Determine the
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
and records an approval. Determine the count with `bash checks/risk-route.sh <pr-body-file> origin/<base>`,
|
|
65
|
+
run **in the code repo with the PR's branch checked out** — it reads the body's Impact & Risk block and
|
|
66
|
+
the base branch's `.sdlc/risk-map`, and the larger step wins. On the base branch the change is empty and
|
|
67
|
+
the map adds nothing, so check out the PR branch first. If the repo has no `checks/risk-route.sh`, it is
|
|
68
|
+
not wired yet: run `yad update` for it (that installs `checks/risk-route.sh` and
|
|
69
|
+
`checks/risk-map-check.sh` together). Until then, count from the body alone and say that the map was not
|
|
70
|
+
counted. It prints e.g.
|
|
71
|
+
`ROUTE: 3 approvers = base 1 + contract risk 2 (contract surface touched)`, says branch protection holds the
|
|
72
|
+
merge, not this count (the risk step is advisory and not capped there), and lists the touched domains as a hint for whom to ask. With no risk it
|
|
73
|
+
prints `ROUTE: 1 approver = base 1 (no risk step).` When the map raises a body that says `low`, it
|
|
74
|
+
names the `high` directories and says the two disagree — tell the engineer, and ask the author to fix the
|
|
75
|
+
body if the body is wrong. Record each approval; re-evaluate whether the base
|
|
76
|
+
is met, and report any shortfall against the full count without blocking on it.
|
|
77
|
+
|
|
78
|
+
**Proven history (E67).** When the change touches a `high` directory, `risk-route.sh` also prints the
|
|
79
|
+
people who have **committed there in the last 30 days**, read from the base branch and with this
|
|
80
|
+
change's own authors left out:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
This change touches src/payments/, so it asks for an approval from someone who has
|
|
84
|
+
committed there in the last 30 days (its own authors left out):
|
|
85
|
+
- Alice (@alice)
|
|
86
|
+
- @carol
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
A person whose git name holds an `@` is printed as their bare login (`- @carol`), or, when there is no
|
|
90
|
+
login, as `a name that is an e-mail address` or `a name written like a login` — both have NO login. No
|
|
91
|
+
address is ever printed, and a printed `@word` is always a real login, never a git name. A bare `@login`
|
|
92
|
+
counts exactly like a `(@login)` below.
|
|
93
|
+
|
|
94
|
+
Report it as an ask, never as a block, and use exactly these three answers:
|
|
95
|
+
|
|
96
|
+
Work down these rows in order and stop at the first that fits — a mixed list, where one person has a
|
|
97
|
+
login and another does not, fits more than one:
|
|
98
|
+
|
|
99
|
+
| In order | What you see | What to report |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| 1 | A recorded approver's login is one of the printed logins — a `(@login)` after a name, or a bare `@login` — ignoring upper and lower case | **met** |
|
|
102
|
+
| 2 | The printer says `not read` (a shallow clone, or git could not read the history) | **could not confirm** |
|
|
103
|
+
| 3 | No approver matches, and at least one named person has no login (neither `(@login)` nor a bare `@login`) | **could not confirm** — name everyone printed, and say the names could not be compared |
|
|
104
|
+
| 4 | No approver matches, and every named person has a login (`(@login)` or a bare `@login`) | **short** — name who could meet it |
|
|
105
|
+
|
|
106
|
+
Rows 2 and 3 matter: an approval records a platform login, while git history records a name, and a login
|
|
107
|
+
only comes from a `noreply` address. Different spellings of a name prove nothing either way, so say the
|
|
108
|
+
ask could not be confirmed rather than inventing a shortfall. Logins are compared without case, because
|
|
109
|
+
a platform login is case-insensitive and the printer shows it as the address wrote it.
|
|
110
|
+
|
|
111
|
+
With nobody printed at all — `nobody else has committed there in the last 30 days` — there is nobody to
|
|
112
|
+
ask for, and the count stands on its own. That line, and `not read`, are printed higher up in the
|
|
113
|
+
`Risk map (…)` section, not inside the `ROUTE` paragraph above.
|
|
114
|
+
|
|
115
|
+
**One list, not one per directory.** When a change touches two `high` directories, the people are printed
|
|
116
|
+
as one list: someone who has worked in ANY of them meets the ask. Nothing says which person worked where.
|
|
117
|
+
|
|
64
118
|
Record `engagement: verified` when the engineer reviewed through the companion (else `none` for a bare
|
|
65
119
|
approve); `yad review reconcile --epic <id> --repo <r> --pr <n>` stamps it onto the ship record from the
|
|
66
120
|
platform (mutating the ship's shard where it lives, or its folded entry if already tidied). Soft by default (both count; a bare approve draws `yad review nudge`); only gates when
|
|
67
121
|
`hub.review.requireEngagement: true`. The signal is gameable by design and sits **beside** the CI gates,
|
|
68
122
|
never above them.
|
|
69
|
-
Recording an approval does **not** ship — shipping is a separate, explicit step.
|
|
123
|
+
Recording an approval does **not** ship — shipping is a separate, explicit step. Shape discipline:
|
|
70
124
|
the gate talks only through files; refuse to treat AI review as a human approval.
|
|
71
125
|
|
|
72
126
|
### Step 3 — `ship` (merge + record + update state)
|
|
73
127
|
Ship **iff ALL hold**: the check gates pass (Step C), the AI review has run (advisory), and the
|
|
74
128
|
engineer-review rule is satisfied (Step 2). Then:
|
|
75
129
|
- **Merge** the task branch into the repo's default branch (the human performs/authorises the merge).
|
|
130
|
+
- **Check the lane is not skipped (E39)** — read `build-state/<story>.json`. If this repo's lane is
|
|
131
|
+
`status: skipped`, it was set aside as needing no change: stop, and run
|
|
132
|
+
`yad unskip <epic> <story> --repo <repo>` before recording a ship, so the two records never say opposite
|
|
133
|
+
things (`yad doctor` fails that as `lane:…:contradiction`; `yad checkpoint --retro-ship` refuses it).
|
|
76
134
|
- **Record the ship** — write the ship to its own shard
|
|
77
135
|
`epics/<epic>/.sdlc/build-log/<story>-<task>-<repo>.json` (readers union the folded `build-log.json` +
|
|
78
136
|
the loose shards, deduping by (story, task, repo) so a shard wins over a stale folded ship):
|
|
79
137
|
```json
|
|
80
138
|
{ "story": "<story>", "task": "<task>", "repo": "<repo>", "branch": "feat/<story>-<task>-…",
|
|
81
139
|
"pr": "<url|#>", "mergeCommit": "<sha>", "gates": ["spec-link","contract-check","build-test-lint"],
|
|
82
|
-
"ai_review": "coderabbit (advisory)", "engineer_review": [{"approver":"<
|
|
83
|
-
"companion": {"trailer":true,"cards":true,"chat":false}, "risk": "<low|medium|high>", "shippedAt": "<YYYY-MM-DD>" }
|
|
140
|
+
"ai_review": "coderabbit (advisory)", "engineer_review": [{"approver":"<platform login>","engagement":"<verified|none>"}],
|
|
141
|
+
"companion": {"trailer":true,"cards":true,"chat":false}, "risk": "<low|medium|high — the BODY's level>", "shippedAt": "<YYYY-MM-DD>" }
|
|
84
142
|
```
|
|
85
143
|
- **Update the story state** — when **every** task in `specs/<story>/tasks.md` has a ship record, set
|
|
86
144
|
the story frontmatter `status: shipped`; otherwise `status: in-build`. The chain
|
|
@@ -91,30 +149,36 @@ engineer-review rule is satisfied (Step 2). Then:
|
|
|
91
149
|
`epics/<epic>/.sdlc/trust-log/<story>-<repo>-implement-<uid>.json` (or, if the run was already folded
|
|
92
150
|
by `yad tidy up`, into its entry in the folded `trust-log.json`). The human has the last word on the trust signal: a diff merged
|
|
93
151
|
as authored is `approved-unchanged`; one the engineer edited before merge is `approved-with-edits`;
|
|
94
|
-
a rejected one is `rejected`. This is the
|
|
152
|
+
a rejected one is `rejected`. This is the run record `yad dial` shows the team beside a step's dial
|
|
95
153
|
(it never weakens the merge gate — the engineer still owns the merge).
|
|
96
154
|
- **Commit the machine-written ledgers.** Run `yad checkpoint --push` from `{project-root}` to commit
|
|
97
|
-
the
|
|
155
|
+
the Build ledgers just written (the `build-log/` shard, and the `trust-log/` shard /
|
|
98
156
|
`build-state/<story>.json` if the story ran through `yad-run`) as one `chore(hub): …` audit-trail
|
|
99
157
|
commit — default branch only, staging the shard dirs (`yad tidy up` folds finished shards later),
|
|
100
|
-
never a
|
|
158
|
+
never a Shape gate file. It is the Build analogue of the Shape `yad gate` sync. The
|
|
101
159
|
same commit also **carries the story `status:` flip** you just wrote (`approved → in-build/shipped`,
|
|
102
160
|
#112) — because that story now has a build-log ship, checkpoint stages `stories/<story>.md` alongside
|
|
103
161
|
the ledgers, so the artifact never drifts from build-log and you never fall back to a raw git-to-main
|
|
104
162
|
push. (The code-repo `tasks.md` is committed in its own repo as usual.)
|
|
105
163
|
|
|
106
164
|
### Step 4 — Stop
|
|
107
|
-
Report what shipped and the story's state. Do not advance anything else; the
|
|
108
|
-
stays as it was (`ready-for-build`).
|
|
165
|
+
Report what shipped and the story's state. Do not advance anything else; the Shape `state.json`
|
|
166
|
+
stays as it was (`ready-for-build`). Build is recorded in `build-log.json` + the story status.
|
|
109
167
|
|
|
110
168
|
## Hard rules (build plan §E, Cross-cutting)
|
|
111
169
|
|
|
112
170
|
- **AI review is advisory, never the authority.** Only a human engineer approval counts toward the gate.
|
|
113
|
-
- **High risk
|
|
171
|
+
- **High risk raises the count** — the same count as `yad-review-gate` / `risk-route.sh`, and a `high`
|
|
172
|
+
directory on the base branch's risk map raises it too; that directory also asks for an approver who has
|
|
173
|
+
worked there in the last 30 days (E67), reported in the same three states as everything else here:
|
|
174
|
+
met, short, or could not confirm. The count is advisory — branch protection holds the
|
|
175
|
+
merge; `yad open-pr` shows the count capped by the active people. There are no domain owners to route to.
|
|
176
|
+
- **The ship record's `risk` is the body's level**, as the author wrote it — not the level the map raised
|
|
177
|
+
it to. The count is worked out live each time and never stored (the user's decision, 2026-09-18).
|
|
114
178
|
- **Ship only after gates + engineer review.** No gate skipped; the human owns the merge.
|
|
115
179
|
- **Nothing auto-advances.** Step E records human decisions in files; it never machine-advances.
|
|
116
180
|
|
|
117
181
|
## Reference
|
|
118
182
|
- The build ledger + story-state rules: `references/ship-and-record.md`.
|
|
119
|
-
- The
|
|
183
|
+
- The count reused: `../yad-review-gate/SKILL.md`; the routing helper: `../yad-pr-template/`.
|
|
120
184
|
- The gates that must pass first: `../yad-checks/references/check-gates.md`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ship — the build ledger and the story state
|
|
2
2
|
|
|
3
|
-
Step E (`yad-engineer-review`) closes
|
|
3
|
+
Step E (`yad-engineer-review`) closes Build: AI review (advisory) → engineer review (the human gate) →
|
|
4
4
|
ship. Shipping records the merge and updates the story state so the whole chain is traceable.
|
|
5
5
|
|
|
6
6
|
## Two sets of eyes
|
|
@@ -10,10 +10,17 @@ ship. Shipping records the merge and updates the story state so the whole chain
|
|
|
10
10
|
gate. Where CodeRabbit can't run (no remote), an equivalent AI first-pass is run by hand and its
|
|
11
11
|
notes captured.
|
|
12
12
|
2. **Engineer review (the authority).** A human reads the diff against the spec and the acceptance
|
|
13
|
-
criteria and records an approval. The rule is `yad-review-gate`'s:
|
|
14
|
-
- **base:**
|
|
15
|
-
- **
|
|
16
|
-
|
|
13
|
+
criteria and records an approval. The rule is `yad-review-gate`'s count, in distinct approvers:
|
|
14
|
+
- **base (enforced):** 1 distinct approver, who should not be the author. This holds the merge.
|
|
15
|
+
- **full count (advisory):** base 1 + a risk step from the PR's Impact & Risk block — `high` risk
|
|
16
|
+
+1, a touched contract surface +2 — or from the base branch's risk map, where a change touching a
|
|
17
|
+
`high` directory adds +1 (E66). The largest step, never the sum. Exactly what `risk-route.sh` prints,
|
|
18
|
+
run in the code repo on the PR's branch.
|
|
19
|
+
The risk step holds nothing on a code PR: branch protection holds the merge. `yad open-pr` shows
|
|
20
|
+
the count capped by the active people (E72), for information only. The touched domains it lists are a hint
|
|
21
|
+
for whom to ask.
|
|
22
|
+
|
|
23
|
+
The actual merge protection is the platform's branch protection.
|
|
17
24
|
|
|
18
25
|
## The build ledger — shard-then-fold (`epics/<epic>/.sdlc/build-log/` → `build-log.json`)
|
|
19
26
|
|
|
@@ -48,8 +55,8 @@ without the `{ epic, ships }` wrapper):
|
|
|
48
55
|
"gates": ["spec-link", "contract-check", "build-test-lint"],
|
|
49
56
|
"ai_review": "coderabbit (advisory)",
|
|
50
57
|
"engineer_review": [
|
|
51
|
-
{ "approver": "amelia", "
|
|
52
|
-
{ "approver": "carol", "
|
|
58
|
+
{ "approver": "amelia-dev", "engagement": "verified" },
|
|
59
|
+
{ "approver": "carol-k", "engagement": "none" }
|
|
53
60
|
],
|
|
54
61
|
"companion": { "trailer": true, "cards": true, "chat": false },
|
|
55
62
|
"risk": "low",
|
|
@@ -59,16 +66,16 @@ without the `{ epic, ships }` wrapper):
|
|
|
59
66
|
}
|
|
60
67
|
```
|
|
61
68
|
|
|
62
|
-
This is the
|
|
69
|
+
This is the Build analogue of Shape's `approvals.json` — files only, no hidden state, so a
|
|
63
70
|
future service can drive ship by writing the same records. Like the trust log and build-state, it is a
|
|
64
|
-
machine-written ledger committed by **`yad checkpoint`** (the
|
|
71
|
+
machine-written ledger committed by **`yad checkpoint`** (the Build analogue of `yad gate` sync),
|
|
65
72
|
not by hand: after recording the ship, `yad checkpoint --push` lands the new `build-log/` shard as a
|
|
66
|
-
`chore(hub): …` audit-trail commit on the default branch (allowlist-scoped to the
|
|
67
|
-
never a
|
|
73
|
+
`chore(hub): …` audit-trail commit on the default branch (allowlist-scoped to the Build ledgers,
|
|
74
|
+
never a Shape gate file); `yad tidy up` folds finished shards into `build-log.json` later.
|
|
68
75
|
|
|
69
76
|
### Retroactive ship — a pre-tracking story (#142)
|
|
70
77
|
|
|
71
|
-
A story that was merged and shipped **before** the
|
|
78
|
+
A story that was merged and shipped **before** the Build ledger existed has no build-log ship, so
|
|
72
79
|
`yad checkpoint` can't carry its `status: shipped` flip (the flip is only carried when a ship backs it,
|
|
73
80
|
#112) — leaving a raw `git push origin main` as the only way to land it, against the never-raw-git
|
|
74
81
|
convention. To reconcile it through yad, record a **retroactive** ship, then checkpoint carries the flip
|
|
@@ -83,7 +90,7 @@ It writes ONE minimal ship shard marked `retroactive: true` (`task` defaults to
|
|
|
83
90
|
the normal checkpoint so the story's already-made `status:` flip rides along in the **same** commit. It
|
|
84
91
|
refuses when the story already has a ship **in that repo** (then it isn't pre-tracking there — use the
|
|
85
92
|
normal flow). It does **not** author the story frontmatter — and to keep evidence and the flip atomic (the no-drift
|
|
86
|
-
invariant), it **refuses** unless you have already set a
|
|
93
|
+
invariant), it **refuses** unless you have already set a Build `status:` (`in-build` or `shipped`) in
|
|
87
94
|
`stories/<story>.md`, so a ship shard is never committed while the artifact still says `approved`.
|
|
88
95
|
|
|
89
96
|
**Where the record lands — it is a shard, not an append to `build-log.json`.** Like every other ship, a
|
|
@@ -121,7 +128,8 @@ writing the same ledger at once would otherwise both read "no ship yet" and both
|
|
|
121
128
|
empty directory (`build-log.json.lock`), so git never sees it; one held by a process that died is
|
|
122
129
|
reclaimed after 30s, and a live one reports `YAD-STATE-006` rather than writing over the other's work.
|
|
123
130
|
|
|
124
|
-
**Engagement (the Review Companion).** Each `engineer_review` entry
|
|
131
|
+
**Engagement (the Review Companion).** Each `engineer_review` entry names the approver by platform login
|
|
132
|
+
(no role or domain) and carries `engagement: verified | none`
|
|
125
133
|
— `verified` when the engineer reviewed through the [companion](../../yad-review-companion/SKILL.md)
|
|
126
134
|
(`yad review trailer/context/nudge`, a real trailer/cards/chat session over the diff), `none` for a bare
|
|
127
135
|
approve. The optional `companion` block records which faces ran. It is **soft by default** (both count;
|
|
@@ -129,7 +137,7 @@ a bare approve draws a friendly `yad review nudge`); it only gates ship when
|
|
|
129
137
|
`hub.review.requireEngagement: true`. `yad review reconcile --epic <id> --repo <r> --pr <n>` reads the
|
|
130
138
|
code PR's approvals (with the engagement signal) and stamps them onto the matching ship record — writing
|
|
131
139
|
back into the ship's shard where it lives (or its folded entry if the story was already tidied) — the
|
|
132
|
-
|
|
140
|
+
Build **bridge**, the analogue of `yad gate sync`. The signal is gameable by design ("visible, not
|
|
133
141
|
impossible"): it makes engineer-review quality visible, it does not prove a human read the diff. It sits
|
|
134
142
|
**beside** the CI gates (build/test/lint/contract/verified-commits) — never above them; CI still
|
|
135
143
|
decides machine safety, the merge is still the human act.
|
|
@@ -156,6 +164,7 @@ trailer → story → epic). Resolve that ship by the union rule, not from `buil
|
|
|
156
164
|
|
|
157
165
|
1. The three **check gates** pass (Step C) — re-run them on the PR branch if unsure.
|
|
158
166
|
2. The **AI review** has run (advisory; findings surfaced to the engineer).
|
|
159
|
-
3. The **engineer review**
|
|
167
|
+
3. The **engineer review** base is met (1 distinct approver); any shortfall against the full count from
|
|
168
|
+
the Impact & Risk block is reported, not blocking.
|
|
160
169
|
|
|
161
170
|
Only then does the human merge and `yad-engineer-review` record it. Nothing auto-advances.
|