yadflow 3.19.0-next.2 → 4.0.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +371 -0
  2. package/README.md +160 -22
  3. package/bin/commands.mjs +46 -0
  4. package/bin/yad.mjs +506 -117
  5. package/cli/artifact-status.mjs +30 -11
  6. package/cli/capture.mjs +417 -0
  7. package/cli/checkpoint.mjs +47 -27
  8. package/cli/claims.mjs +165 -0
  9. package/cli/codeowners-command.mjs +170 -0
  10. package/cli/codeowners.mjs +397 -0
  11. package/cli/commit.mjs +13 -9
  12. package/cli/dial.mjs +183 -0
  13. package/cli/docs.mjs +88 -32
  14. package/cli/doctor.mjs +1682 -90
  15. package/cli/epic-state.mjs +3460 -211
  16. package/cli/epic.mjs +506 -0
  17. package/cli/errors.mjs +3 -0
  18. package/cli/fold.mjs +247 -0
  19. package/cli/gate-local.mjs +296 -0
  20. package/cli/gate.mjs +977 -183
  21. package/cli/history.mjs +556 -0
  22. package/cli/hook.mjs +264 -53
  23. package/cli/hubcommit.mjs +9 -19
  24. package/cli/index-command.mjs +87 -0
  25. package/cli/ledger.mjs +54 -4
  26. package/cli/lib.mjs +161 -9
  27. package/cli/manifest.mjs +376 -38
  28. package/cli/migrate.mjs +683 -52
  29. package/cli/mode.mjs +170 -0
  30. package/cli/next.mjs +365 -86
  31. package/cli/openpr.mjs +193 -34
  32. package/cli/owners.mjs +266 -0
  33. package/cli/people.mjs +657 -0
  34. package/cli/plan.mjs +466 -125
  35. package/cli/platform.mjs +109 -128
  36. package/cli/product-index.mjs +287 -0
  37. package/cli/protection.mjs +706 -0
  38. package/cli/reconcile.mjs +40 -12
  39. package/cli/repo-publish.mjs +24 -26
  40. package/cli/repo.mjs +23 -14
  41. package/cli/report.mjs +24 -14
  42. package/cli/review.mjs +19 -22
  43. package/cli/riskmap-command.mjs +289 -0
  44. package/cli/riskmap.mjs +373 -0
  45. package/cli/setup.mjs +127 -279
  46. package/cli/ship.mjs +6 -5
  47. package/cli/skill.mjs +180 -0
  48. package/cli/skip.mjs +211 -30
  49. package/cli/thread.mjs +41 -16
  50. package/cli/tidy.mjs +18 -18
  51. package/cli/update-commit.mjs +21 -21
  52. package/cli/usage.mjs +115 -109
  53. package/package.json +3 -3
  54. package/skills/sdlc/config.yaml +149 -70
  55. package/skills/sdlc/module-help.csv +24 -24
  56. package/skills/yad-analysis/SKILL.md +121 -59
  57. package/skills/yad-architecture/SKILL.md +30 -18
  58. package/skills/yad-architecture/references/contract-format.md +8 -5
  59. package/skills/yad-backfill/SKILL.md +10 -4
  60. package/skills/yad-backfill/references/backfill.md +8 -1
  61. package/skills/yad-backfill/templates/checks/backfill-check.sh +10 -2
  62. package/skills/yad-change/SKILL.md +119 -42
  63. package/skills/yad-change/references/triage.md +42 -27
  64. package/skills/yad-checks/SKILL.md +68 -35
  65. package/skills/yad-checks/references/check-gates.md +310 -85
  66. package/skills/yad-checks/templates/checks/commit-message.sh +17 -3
  67. package/skills/yad-checks/templates/checks/contract-check.sh +130 -9
  68. package/skills/yad-checks/templates/checks/epic-open.sh +2 -2
  69. package/skills/yad-checks/templates/checks/ledger-guard.sh +55 -8
  70. package/skills/yad-checks/templates/checks/lineage-check.sh +23 -9
  71. package/skills/yad-checks/templates/checks/reconcile-debt-check.sh +1 -1
  72. package/skills/yad-checks/templates/checks/risk-map-check.sh +438 -0
  73. package/skills/yad-checks/templates/checks/verified-commits.sh +20 -46
  74. package/skills/yad-checks/templates/github/yad-checks.yml +13 -2
  75. package/skills/yad-checks/templates/github/yad-hub-checks.yml +5 -5
  76. package/skills/yad-checks/templates/github/yad-update-guard.yml +7 -5
  77. package/skills/yad-checks/templates/github/yad-verified-commits.yml +4 -4
  78. package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +10 -1
  79. package/skills/yad-checks/templates/gitlab/yad-hub-checks.gitlab-ci.yml +5 -5
  80. package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +3 -3
  81. package/skills/yad-checks/templates/hooks/ledger-guard-cursor.sh +91 -0
  82. package/skills/yad-checks/templates/hooks/ledger-guard.sh +37 -6
  83. package/skills/yad-checks/templates/hooks/yad-capture.sh +53 -0
  84. package/skills/yad-commit/SKILL.md +4 -4
  85. package/skills/yad-connect-design/SKILL.md +5 -5
  86. package/skills/yad-connect-design/references/design-context.md +1 -1
  87. package/skills/yad-connect-design/references/design-registry.md +2 -2
  88. package/skills/yad-connect-docs/SKILL.md +11 -11
  89. package/skills/yad-connect-docs/references/docs-registry.md +1 -1
  90. package/skills/yad-connect-learning/SKILL.md +5 -5
  91. package/skills/yad-connect-learning/references/learning-registry.md +2 -2
  92. package/skills/yad-connect-repos/SKILL.md +66 -45
  93. package/skills/yad-connect-repos/references/code-context.md +4 -4
  94. package/skills/yad-connect-repos/references/hub-config.md +47 -51
  95. package/skills/yad-connect-repos/references/repos-registry.md +8 -7
  96. package/skills/yad-connect-repos/references/risk-map.md +81 -0
  97. package/skills/yad-connect-testing/SKILL.md +5 -5
  98. package/skills/yad-connect-testing/references/testing-context.md +3 -4
  99. package/skills/yad-connect-testing/references/testing-registry.md +2 -2
  100. package/skills/yad-defects/SKILL.md +7 -7
  101. package/skills/yad-discovery/SKILL.md +131 -94
  102. package/skills/yad-discovery/references/discovery-schema.md +22 -6
  103. package/skills/yad-discovery/references/foundation-schema.md +374 -0
  104. package/skills/yad-docs/SKILL.md +13 -8
  105. package/skills/yad-docs/references/data-mapping.md +9 -7
  106. package/skills/yad-docs/templates/app/package-lock.json +3 -3
  107. package/skills/yad-docs-overview/SKILL.md +30 -15
  108. package/skills/yad-docs-overview/references/pipeline-model.md +33 -20
  109. package/skills/yad-docs-sync/SKILL.md +10 -5
  110. package/skills/yad-docs-sync/references/staleness.md +8 -7
  111. package/skills/yad-engineer-review/SKILL.md +81 -17
  112. package/skills/yad-engineer-review/references/ship-and-record.md +17 -8
  113. package/skills/yad-epic/SKILL.md +173 -92
  114. package/skills/yad-epic/references/state-schema.md +610 -94
  115. package/skills/yad-hub-bridge/SKILL.md +57 -38
  116. package/skills/yad-hub-bridge/references/bridge.md +94 -67
  117. package/skills/yad-hub-bridge/references/login-roster.md +163 -70
  118. package/skills/yad-hub-bridge/templates/checks/hub-route.sh +22 -19
  119. package/skills/yad-hub-bridge/templates/github/yad-gate-sync.yml +34 -14
  120. package/skills/yad-hub-bridge/templates/gitlab/gitlab-ci.include-root.yml +2 -2
  121. package/skills/yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml +21 -11
  122. package/skills/yad-implement/SKILL.md +27 -13
  123. package/skills/yad-implement/references/implement-conventions.md +2 -2
  124. package/skills/yad-learn/SKILL.md +9 -9
  125. package/skills/yad-learn/references/learning-state.md +2 -2
  126. package/skills/yad-open-pr/SKILL.md +61 -26
  127. package/skills/yad-pair-review/SKILL.md +7 -5
  128. package/skills/yad-pair-review/references/session-state.md +1 -1
  129. package/skills/yad-pr-template/SKILL.md +47 -26
  130. package/skills/yad-pr-template/references/risk-routing.md +97 -24
  131. package/skills/yad-pr-template/templates/checks/pr-template.sh +34 -11
  132. package/skills/yad-pr-template/templates/checks/pr-title.sh +32 -9
  133. package/skills/yad-pr-template/templates/checks/risk-route.sh +107 -14
  134. package/skills/yad-pr-template/templates/github/pull_request_template.md +7 -5
  135. package/skills/yad-pr-template/templates/gitlab/merge_request_templates/Default.md +7 -5
  136. package/skills/yad-pr-template/templates/hub/github/pull_request_template.md +14 -13
  137. package/skills/yad-pr-template/templates/hub/gitlab/merge_request_templates/Default.md +14 -12
  138. package/skills/yad-reconcile/SKILL.md +3 -3
  139. package/skills/yad-report/SKILL.md +5 -5
  140. package/skills/yad-review-companion/SKILL.md +6 -3
  141. package/skills/yad-review-gate/SKILL.md +203 -93
  142. package/skills/yad-review-gate/references/gating.md +232 -54
  143. package/skills/yad-run/SKILL.md +81 -51
  144. package/skills/yad-run/references/run-loop.md +61 -39
  145. package/skills/yad-ship/SKILL.md +15 -11
  146. package/skills/yad-spec/SKILL.md +21 -6
  147. package/skills/yad-spec/references/spec-handoff.md +17 -5
  148. package/skills/yad-status/SKILL.md +115 -50
  149. package/skills/yad-stories/SKILL.md +37 -21
  150. package/skills/yad-stories/references/story-schema.md +7 -6
  151. package/skills/yad-stub/SKILL.md +58 -47
  152. package/skills/yad-sync-repos/SKILL.md +2 -2
  153. package/skills/yad-test-cases/SKILL.md +32 -23
  154. package/skills/yad-test-cases/references/test-cases-schema.md +7 -4
  155. package/skills/yad-timeline/SKILL.md +8 -7
  156. package/skills/yad-ui/SKILL.md +41 -18
  157. package/cli/roster.mjs +0 -164
  158. package/skills/sdlc/install.sh +0 -68
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yad-implement
3
- description: 'Build Step B of the gated SDLC. With the dev lens, implement ONE atomic task from a story''s Spec Kit tasks.md as a small diff (≤3 files) on its own branch in the code repo. The diff stays inside the files the task declared — flag and STOP if it would grow beyond them. Commit per convention, ending with the task ID; add Contract-Change: yes only if the diff touches the locked contract surface (which routes back to the architecture gate). The step never advances itself; it produces a committed branch and hands off to the check gates, which the orchestrator (yad-run) may auto-run once `implement` is earned to machine_advance (Phase 4b Step D) — the merge still needs the gates and the engineer review. Use when the user says "implement task <id>" or after a story is spec''d.'
3
+ description: 'Build Step B of the gated SDLC. With the dev lens, implement ONE atomic task from a story''s Spec Kit tasks.md as a small diff (≤3 files) on its own branch in the code repo. The diff stays inside the files the task declared — flag and STOP if it would grow beyond them. Commit per convention, ending with the task ID; add Contract-Change: yes only if the diff touches the locked contract surface (which routes back to the architecture gate). The step never advances itself; it produces a committed branch and hands off to the check gates, which the orchestrator (yad-run) may auto-run once the team sets `implement` to `advance: auto` (`yad dial`) — the merge still needs the gates and the engineer review. Use when the user says "implement task <id>" or after a story is spec''d.'
4
4
  ---
5
5
 
6
6
  # SDLC — Implement Task (Build Step B)
@@ -14,7 +14,7 @@ This step **never auto-advances**. When the task is implemented and committed, c
14
14
  **check gates** (Step C — `yad-checks`: spec-link, contract-check, build/test/lint) and then human/AI
15
15
  review (Steps D–E, not built yet). Implementation here produces a branch + commit and stops.
16
16
 
17
- The implementing lens is **`dev`** (`bmad-agent-dev`, Amelia). The dev writes only what the task
17
+ The implementing lens is **`dev`**. The dev writes only what the task
18
18
  declares; it does not redesign, does not widen the contract, and does not pick up sibling tasks.
19
19
 
20
20
  ## Conventions
@@ -30,7 +30,7 @@ declares; it does not redesign, does not widen the contract, and does not pick u
30
30
  `Co-Authored-By:` for any AI tool that helped author the diff (the human author owns the commit;
31
31
  trailer order `Task:` → `Contract-Change:` → `Co-Authored-By:`). The skill installs a `.gitmessage`
32
32
  template that scaffolds these (Step 2).
33
- - Speak in the configured `communication_language`; write code/comments in `document_output_language`.
33
+ - Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write code/comments in `document_output_language`.
34
34
 
35
35
  ## Inputs
36
36
 
@@ -55,7 +55,7 @@ rather than forking a second one (one task = one branch).
55
55
  **On the first implement in a repo, install the commit template** (idempotent): copy this skill's
56
56
  `templates/.gitmessage` to `<repo>/.gitmessage` and run `git -C <repo> config commit.template .gitmessage`
57
57
  so every commit is pre-scaffolded with the `Task:` trailer and the commented per-commit `Co-Authored-By:`
58
- choices (`config.yaml` `build.ai_coauthor.allowed`). Do the same at the hub root for hub commits. Skip if
58
+ choices (`config.yaml` `build.ai_coauthor.allowed`). Do the same at the Product root for Product commit. Skip if
59
59
  already configured.
60
60
 
61
61
  ### Step 3 — Read the spec inputs (do NOT re-derive the contract)
@@ -77,9 +77,14 @@ declared files are wrong is a spec bug, not an implementation decision.
77
77
 
78
78
  This stop is a **scope overrun** — a halt condition that pulls in a human regardless of any automation
79
79
  dial. When this step is driven by the orchestrator (`yad-run`, Phase 4), the stop must be legible to
80
- it: mark the `implement` step `status: blocked` in `build-state/<story>.json` and surface
81
- `scope_overrun: true` so the run records a `rejected` trust entry and halts (it never advances past a
82
- boundary breach). The same applies to the Step 5 contract-surface stop (`contract_touch: true`).
80
+ it: mark the `implement` step `status: blocked` in `build-state/<story>.json` — **with a `record`**,
81
+ `{ "reason": "scope overrun: <which file>", "by": "<login or null>", "date": "<YYYY-MM-DD>" }` — and
82
+ surface `scope_overrun: true` so the run records a `rejected` trust entry and halts (it never advances
83
+ past a boundary breach). The same applies to the Step 5 contract-surface stop (`contract_touch: true`).
84
+
85
+ The record is what makes the halt legible. Since shape 7 (E38) a `blocked` step carrying nothing
86
+ reads as `todo` — "not started" — because that is what the word meant in every file written before
87
+ shape 7. The record is the only thing that separates a lane that stopped from a lane nobody began.
83
88
 
84
89
  ### Step 5 — Contract-surface check (local pre-flight for Step C)
85
90
  Determine whether the diff touches the **locked contract surface** (the API/event/data-model shapes in
@@ -89,9 +94,18 @@ A contract change means the diff alters the agreed cross-repo shape itself.
89
94
 
90
95
  - If the diff does **not** change the surface: proceed; no `Contract-Change` trailer.
91
96
  - If the task **requires** changing the surface: **flag and STOP**. The contract is owned upstream;
92
- route back to the **architecture gate** to amend and re-lock `contract.md` first. Only then return
97
+ route back to the **architecture gate** to amend and re-lock `contract.md` first — on a route that
98
+ has one; the short lanes do not, see the bullet below. Only then return
93
99
  here, and record `Contract-Change: yes` in the commit body (the Step C contract-check will require a
94
100
  matching, already-updated contract).
101
+ - **Short-lane epics have no contract and no architecture gate.** Read
102
+ `epics/<epic>/.sdlc/state.json`'s `profile` (or, on an epic seeded before file shape 6, what its
103
+ `steps[]` contains): on `chore` and `spike` there is no `contract.md`, so
104
+ there is no surface block to compare against and **no gate to route back to**. Never write
105
+ `Contract-Change: yes` on a short-lane task: there is no lock for the check to verify it against, so
106
+ the claim cannot be true of anything. Where the Product repo is reachable the gate now FAILS it
107
+ outright; where it is not, the check defers and nothing catches it. If the task needs the shared cross-repo surface to change, **STOP and escalate
108
+ to a human**: the work belongs to a new epic on `classic`.
95
109
 
96
110
  ### Step 6 — Commit on the task branch
97
111
  Stage only the declared files. Commit with the convention: a conventional subject, a short body, and a
@@ -109,13 +123,13 @@ then the PR and review (Steps D–E). Do **not** open a PR, merge, or hand-edit
109
123
  - **Run standalone:** stop here; a human triggers the gates.
110
124
  - **Run by the orchestrator** (`yad-run`): this skill still just produces the committed branch and
111
125
  signals success (or a scope/contract halt). The orchestrator records the `implement` step's status
112
- and trust entry and, when `implement` is earned to `machine_advance` (Step D, Phase 4b), **auto-runs
126
+ and trust entry and, when `implement` is set to `advance: auto` (`yad dial`), **auto-runs
113
127
  the check gates** instead of waiting for a manual nudge. The diff still cannot merge without the
114
128
  gates passing and the engineer review — Step D removes only the "now run the gates" hand-off.
115
129
 
116
130
  ### Step 8 — Record the `tasks` trust signal on first consume (Phase 4b)
117
131
  Resolving a task from `tasks.md` (Step 1) is the moment the generated task list "survives contact" —
118
- the evidence that could later earn the `tasks` step a `machine_advance`. When driven by `yad-run`,
132
+ part of the run record `yad dial` shows beside the `tasks` dial. When driven by `yad-run`,
119
133
  finalize a `tasks` trust entry, anchored to what the human/dev actually did with the list:
120
134
  - the task is implemented with its declared `Files:`/scope **as generated** → `approved-unchanged`;
121
135
  - the task is **re-scoped** first (its `Files:`/boundary edited) → `approved-with-edits`
@@ -124,8 +138,8 @@ finalize a `tasks` trust entry, anchored to what the human/dev actually did with
124
138
  Write the entry to its own shard `epics/<epic>/.sdlc/trust-log/<story>-<repo>-tasks-<uid>.json` (a fresh
125
139
  `uid` per run, so concurrent writers never conflict; readers union the folded `trust-log.json` + the
126
140
  loose shards, skipping any shard whose full `(story, repo, step, uid)` already appears folded — a
127
- half-applied `yad tidy up` — so entries are never double-counted). Schema: `../yad-epic/references/state-schema.md`. `tasks` stays `human_approve` until its slice clears
128
- the threshold — this only *gathers* evidence. (The `implement` step's own verdict is finalized later,
141
+ half-applied `yad tidy up` — so entries are never double-counted). Schema: `../yad-epic/references/state-schema.md`. The record is advice: the `tasks` dial
142
+ is whatever the team sets with `yad dial`. (The `implement` step's own verdict is finalized later,
129
143
  at the engineer review in `yad-engineer-review`: merged as authored → `approved-unchanged`; edited first →
130
144
  `approved-with-edits`; scope/contract/checks halt → `rejected`.)
131
145
 
@@ -136,7 +150,7 @@ at the engineer review in `yad-engineer-review`: merged as authored → `approve
136
150
  - **Never widen the contract here.** Surface changes go back to the architecture gate (Step 5).
137
151
  - **The step never advances itself.** A scope overrun or contract touch always halts. The
138
152
  `implement → checks` hand-off advances only when the orchestrator's `implement` dial is
139
- `machine_advance` (earned, Step D) — and never past the engineer review, which is always human.
153
+ `advance: auto` (`yad dial`) — and never past the engineer review, which is always human.
140
154
  Standalone, the step stops at a committed branch.
141
155
 
142
156
  ## Reference
@@ -89,8 +89,8 @@ The **locked contract surface** is the cross-repo agreement in `epics/<epic>/con
89
89
  change; no trailer.
90
90
  - **Changing the contract** (exceptional) — altering the agreed shape itself (new field crossing repos,
91
91
  changed status enum, new shared endpoint). This is **not** an implementation decision. Stop, go back
92
- to the **architecture gate**, amend and re-lock `contract.md` (which re-escalates that review per the
93
- contract `risk_tags`), and only then implement — recording `Contract-Change: yes` so the §C
92
+ to the **architecture gate**, amend and re-lock `contract.md` (which sends that review round again; its contract `risk_tags`
93
+ raise the full approver count, which is advisory — E72 reports it capped at the active people less one), and only then implement — recording `Contract-Change: yes` so the §C
94
94
  contract-check finds the matching, already-updated contract.
95
95
 
96
96
  This keeps the contract singular and owned upstream: a code repo can never widen the shared surface
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yad-learn
3
- description: 'The cross-cutting learning layer: at ANY SDLC stage, a team member can ask to learn a concept and be tutored in the context of what the team is building. Routes the request to the connected learning tool (.sdlc/learning.json, DeepTutor-first) grounded in the project knowledge base, or degrades to harness-native tutoring (the harness model reading the artifacts) when no tool is connected. Renders a tutorial artifact and appends to a per-member learning ledger that is kept LOCAL-ONLY — gitignored, never committed or pushed to the product hub or any code repo — so it stays a private, personal skills log (yad-status rolls up the local records). Purely opt-in — it NEVER blocks a gate and never touches epic state, approvals, or the contract lock. Use when the user says "teach me <concept>", "learn about <concept>", or "yad-learn".'
3
+ description: 'The cross-cutting learning layer: at ANY SDLC stage, a team member can ask to learn a concept and be tutored in the context of what the team is building. Routes the request to the connected learning tool (.sdlc/learning.json, DeepTutor-first) grounded in the project knowledge base, or degrades to harness-native tutoring (the harness model reading the artifacts) when no tool is connected. Renders a tutorial artifact and appends to a per-member learning ledger that is kept LOCAL-ONLY — gitignored, never committed or pushed to the Product or any code repo — so it stays a private, personal skills log (yad-status rolls up the local records). Purely opt-in — it NEVER blocks a gate and never touches epic state, approvals, or the contract lock. Use when the user says "teach me <concept>", "learn about <concept>", or "yad-learn".'
4
4
  ---
5
5
 
6
6
  # SDLC — Learn (the cross-cutting tutor)
@@ -13,8 +13,8 @@ therefore their **control over what is being built** — explicit, without ever
13
13
  to the team.
14
14
 
15
15
  **Learning output is LOCAL-ONLY.** The records ledger and the rendered tutorials are personal artifacts:
16
- they are **gitignored and must never be committed or pushed** — not to the product hub and not to any
17
- code repo. The skill ensures the product hub's `.gitignore` lists these paths before it writes them. The
16
+ they are **gitignored and must never be committed or pushed** — not to the Product and not to any
17
+ code repo. The skill ensures the Product's `.gitignore` lists these paths before it writes them. The
18
18
  only committed, shared learning file is the connection registry `.sdlc/learning.json` (no secrets, no
19
19
  personal data) — written by `yad-connect-learning`, not here.
20
20
 
@@ -24,7 +24,7 @@ approvals ledger, or the contract lock. It writes only the local learning ledger
24
24
 
25
25
  ## Conventions
26
26
 
27
- - `{project-root}` resolves from the project working directory (the **product hub**).
27
+ - `{project-root}` resolves from the project working directory (the **Product**).
28
28
  - The tutor is reached via the project's learning connection (`.sdlc/learning.json`, written by
29
29
  `yad-connect-learning`). **DeepTutor-first** (a CLI subprocess); when no tool is connected (or the
30
30
  `deeptutor` binary is absent) it degrades to **harness-native** tutoring — the harness model reads the
@@ -35,7 +35,7 @@ approvals ledger, or the contract lock. It writes only the local learning ledger
35
35
  - When no epic is scoped, records go to `.sdlc/learning-records.json` and tutorials to `.sdlc/learning/`
36
36
  (cross-project learning).
37
37
  - **Local-only, never committed.** All of the above paths are personal output. Before writing any of
38
- them, ensure the **product hub's** `.gitignore` ignores learning output (idempotent — append only if
38
+ them, ensure the **Product's** `.gitignore` ignores learning output (idempotent — append only if
39
39
  the lines are absent):
40
40
  ```
41
41
  # yadflow learning layer — personal, local-only (never commit or push)
@@ -44,10 +44,10 @@ approvals ledger, or the contract lock. It writes only the local learning ledger
44
44
  epics/*/.sdlc/learning-records.json
45
45
  epics/*/learning/
46
46
  ```
47
- Never write learning output into a connected **code repo** — it lives only in the product hub, and only
47
+ Never write learning output into a connected **code repo** — it lives only in the Product, and only
48
48
  on the local machine. `.sdlc/learning.json` (the connection registry) is the sole committed learning
49
49
  file and is NOT ignored.
50
- - Speak in the configured `communication_language`; write tutorials in `document_output_language`.
50
+ - Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write tutorials in `document_output_language`.
51
51
 
52
52
  ## Inputs
53
53
 
@@ -84,7 +84,7 @@ Keep the tutorial focused (usually < 600 words): explain the concept, then tie i
84
84
  example from this project** (an artifact line, a contract field, a story).
85
85
 
86
86
  ### Step 2 — Render the tutorial artifact (local-only)
87
- First ensure the product hub's `.gitignore` lists the learning-output paths (see Conventions — append the
87
+ First ensure the Product's `.gitignore` lists the learning-output paths (see Conventions — append the
88
88
  block only if absent, so the artifacts can never be committed or pushed). Then write the tutorial to
89
89
  `epics/EP-<slug>/learning/<member>--<concept-slug>.md` (or `.sdlc/learning/` when no epic is scoped).
90
90
  Front-matter the file with `member`, `concept`, `stage`, `tool`, and `requestedAt`.
@@ -130,7 +130,7 @@ there is no approval and no gate. The learner runs `action: complete` (below) wh
130
130
  - **Read-only except the learning ledger.** It writes only `learning-records.json` + tutorial artifacts;
131
131
  it never touches `state.json`, `approvals.json`, `comments.json`, or the contract lock.
132
132
  - **Local-only output.** The records ledger and tutorials are gitignored personal artifacts — never
133
- commit or push them, and never write them into a code repo. Ensure the hub `.gitignore` covers them
133
+ commit or push them, and never write them into a code repo. Ensure the Product `.gitignore` covers them
134
134
  before writing (see Conventions).
135
135
  - **Always works.** No DeepTutor / no connection → tutor harness-native. Never fail because a tool is
136
136
  absent.
@@ -12,7 +12,7 @@ evidence base for the **local skills-log roll-up** in `yad-status`.
12
12
  (`config.yaml` `learning.records` and `learning.artifacts`.)
13
13
 
14
14
  **Local-only.** Every path above is personal output and is **gitignored — never committed or pushed**, to
15
- the product hub or any code repo. `yad-learn` ensures the hub `.gitignore` lists them before writing. The
15
+ the Product or any code repo. `yad-learn` ensures the Product `.gitignore` lists them before writing. The
16
16
  only committed learning file is the connection registry `.sdlc/learning.json`.
17
17
 
18
18
  ## Record schema
@@ -42,7 +42,7 @@ only committed learning file is the connection registry `.sdlc/learning.json`.
42
42
  - **No secrets.** Records hold concept text + references only — never keys or raw tool output beyond the
43
43
  rendered tutorial.
44
44
  - **Never commit the ledger or tutorials.** They are personal, local-only artifacts: gitignored, never
45
- committed or pushed (to the hub or a code repo). Only `.sdlc/learning.json` is committed.
45
+ committed or pushed (to the Product or a code repo). Only `.sdlc/learning.json` is committed.
46
46
 
47
47
  ## Mode → DeepTutor capability
48
48
 
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  name: yad-open-pr
3
- description: 'Build helper of the gated SDLC. Open a code-repo task PR/MR from the committed platform template — detect GitHub/GitLab, push the current task branch, and create the PR/MR with the template body prefilled (Summary / Story-task / Impact & Risk) and the title defaulting to the commit subject. Auto-assigns from the hub roster: assignee = the committer, reviewers = the repo''s reviewers + domain-owners. High risk / contract surface routes to domain owners (risk-route.sh). Drives the `yad open-pr` CLI; never merges. Use when the user says "open the PR", "open the MR", or "raise the merge request".'
3
+ description: 'Build helper of the gated SDLC. Open a code-repo task PR/MR from the committed platform template — detect GitHub/GitLab, push the current task branch, and create the PR/MR with the template body prefilled (Summary / Story-task / Impact & Risk) and the title defaulting to the commit subject. Assigns the PR/MR to the logged-in gh/glab login and requests no reviewers (ask them on the PR itself); prints a reviewer suggestion from recent history and CODEOWNERS, a hint and never a request. High risk / contract surface raises the approver count (risk-route.sh prints it). Drives the `yad open-pr` CLI; never merges. Use when the user says "open the PR", "open the MR", or "raise the merge request".'
4
4
  ---
5
5
 
6
6
  # SDLC — Open Task PR/MR (Build helper)
7
7
 
8
8
  **Goal:** Open the PR/MR for the current task branch from the repo's committed PR/MR template
9
- (installed by `yad-pr-template`, Step D), with the body prefilled and the right reviewers requested.
9
+ (installed by `yad-pr-template`, Step D), with the body prefilled and the assignee set.
10
10
  This is the standalone open-PR step; it **never merges** — the engineer review (`yad-engineer-review`,
11
11
  Step E) owns the merge. Distinct from `yad gate open`, which opens a Shape artifact-review PR on
12
- the product hub.
12
+ the Product.
13
13
 
14
14
  ## Conventions
15
15
 
@@ -19,19 +19,20 @@ the product hub.
19
19
  - **Title** — defaults to the last commit subject (one atomic task = one branch = one PR/MR), so it
20
20
  follows the same Conventional-Commits style and passes the `pr-title` gate. Override with `--title`.
21
21
  - **Body** — the committed template (`.github/pull_request_template.md` /
22
- `.gitlab/merge_request_templates/Default.md`) with `Task:`, `Risk level:`, `Contract surface
23
- touched:`, and `Domains` prefilled; the rest is left for the author. This satisfies the `pr-template`
22
+ `.gitlab/merge_request_templates/Default.md`) with the Summary (from the commit), the story/task id and
23
+ its `specs/` path, `Risk level:`, `Contract surface touched:`, and `Domains` (the repo name when
24
+ `--repo` is passed) prefilled; the rest is left for the author. This satisfies the `pr-template`
24
25
  gate.
25
- - **Stage-aware on the product hub** — `open-pr` mirrors the `--head` split the hub gates apply:
26
+ - **Stage-aware on the Product** — `open-pr` mirrors the `--head` split the Product gates apply:
26
27
  - a **`review/EP-*/<artifact>`** branch is a Shape artifact-review PR → it **delegates to
27
- `yad gate open`** (artifact-review title `review: <artifact> (EP-<slug>)`, the hub artifact-review
28
+ `yad gate open`** (artifact-review title `review: <artifact> (EP-<slug>)`, the Product artifact-review
28
29
  body, and the gate ledger bookkeeping all in one place). Any `--title`/`-m` is ignored here.
29
- - any **other hub branch** is a tooling/CI change → it uses the bundled **code-task** template
30
- (`## Summary` / `Risk level:` / `## Checklist`) instead of the hub's artifact-review
31
- `pull_request_template.md`, so the hub `pr-template` gate passes.
30
+ - any **other Product branch** is a tooling/CI change → it uses the bundled **code-task** template
31
+ (`## Summary` / `Risk level:` / `## Checklist`) instead of the Product's artifact-review
32
+ `pull_request_template.md`, so the Product `pr-template` gate passes.
32
33
  In a code repo nothing changes — it reads the repo's own committed code-task template.
33
34
  - **Base branch** — **resolved, never assumed.** In order: `--base` → the repo's `default_branch` in
34
- `.sdlc/repos.json` → (for a PR against the hub itself) `hub.json`'s `default_branch` → what the
35
+ `.sdlc/repos.json` → (for a PR against the Product itself) `hub.json`'s `default_branch` → what the
35
36
  platform reports (`gh repo view --json defaultBranchRef` / `glab api projects/:id`) → local
36
37
  `origin/HEAD` → `main`. The same **configuration-outranks-the-remote** order `yad repo sync` and the
37
38
  contract-check gate already use (they stop at `origin/HEAD`; only this chain also asks the platform).
@@ -41,18 +42,28 @@ the product hub.
41
42
  auto-review eligibility from the base at PR-**open** time, and retargeting afterwards does not undo
42
43
  the skip. Hardcoding `main` here is the same bug the check gates already refuse to make (see
43
44
  `../yad-checks/references/check-gates.md`).
44
- - **Auto-assign** — from the hub roster scoped to this repo: assignee = the committer (resolved from
45
- the local git identity), reviewers = the repo's `reviewer`/`domain-owner` logins minus the committer.
46
- Degrades cleanly when there is no roster.
47
- - **Routing** — `low`/`medium` → base rule (owner + 1 reviewer); `high` (or a touched
48
- contract/auth/payments surface) → plus one domain-owner per touched domain. `bash
49
- checks/risk-route.sh <body>` prints the required reviewers.
45
+ - **Assignee** — the person opening it: `@me` on GitHub (`gh` resolves it on the repo's own host), and
46
+ on GitLab the login `glab` reports (no assignee is passed when that lookup fails). **No reviewers are
47
+ requested** (E62): yadflow keeps no list of people. The CLI prints `no
48
+ reviewers were requested — ask them on the PR itself`. For a `high` directory the CLI names the people
49
+ who have worked there lately (E67, Step 3). For every code-repo change it also prints a reviewer **suggestion**
50
+ (E68, Step 3a): who has committed in the touched folders lately, and what CODEOWNERS lists — a hint
51
+ only, never a request.
52
+ - **Routing** — the merge needs 1 approval from someone other than the author (the base). `high` risk
53
+ adds 1, a touched contract surface adds 2, and a change touching a `high` directory on the base
54
+ branch's risk map adds 1 (E66) — the larger, never the sum. That risk step is advisory: branch
55
+ protection holds the merge, never this count. The CLI prints the count once the PR is open — capped by
56
+ the active people (E72) when run from the Product — for example `this PR asks for 3 approvers = base 1
57
+ + contract risk 2, capped to 1 for 2 active people — base enforced, risk step advisory; …` — and prints the count of people on its
58
+ own line (`active people: not counted — no cap applies; …` when it cannot count them).
59
+ `bash checks/risk-route.sh <body>` prints the same count from the PR body, without the cap: a code
60
+ repo's CI has no Product to count people from.
50
61
 
51
62
  ## Inputs
52
63
 
53
64
  - `repo` — target a registered repo by name (optional; else the current dir).
54
65
  - `risk` — `low|medium|high` (default `low`); prefilled into the body.
55
- - `contractChange` — flag; marks the contract surface touched and triggers escalation.
66
+ - `contractChange` — flag; marks the contract surface touched and raises the approver count.
56
67
  - `base` — override the PR/MR base (optional; defaults to the repo's own default branch —
57
68
  see **Base branch** above). Only pass it deliberately: a non-default base loses the AI first pass.
58
69
  - `platform` / `title` — optional overrides.
@@ -69,8 +80,8 @@ Run from the repo root:
69
80
  yad open-pr [--repo <name>] [--risk <level>] [--contract-change] [--title "<subject>"]
70
81
  ```
71
82
  The CLI pushes the branch (sets upstream, the user's own auth), fills the template, and creates the
72
- PR/MR with the auto-assigned assignee + reviewers. It prints the base it resolved and where that came
73
- from.
83
+ PR/MR with the assignee set and no reviewers requested. It prints the base it resolved and where that
84
+ came from.
74
85
 
75
86
  The non-default-base warning is **advisory — it does not block, and the PR/MR is already open by the
76
87
  time you read it.** If the base was intended (a stacked PR, a release branch), carry on. If it was
@@ -78,9 +89,33 @@ not, do **not** just retarget the open PR — that leaves the AI first pass skip
78
89
  cause (the repo's `default_branch`, or drop the wrong `--base`), and re-run `yad open-pr` so the PR
79
90
  is *created* against the right base.
80
91
 
81
- ### Step 3 — Route the review (if escalated)
82
- On `high` risk or a contract touch, run `bash checks/risk-route.sh <pr-body>` to print the required
83
- domain-owner reviewers — the same escalation `yad-engineer-review` enforces.
92
+ ### Step 3 — Route the review (if the count is raised)
93
+ Once the PR is open, the CLI prints how many approvers it asks for — the same count the engineer review
94
+ (`yad-engineer-review`) uses. It joins the body's level (`--risk`, `--contract-change`) with the code
95
+ repo's risk map on `origin/<base>`: a change touching a `high` directory adds 1 even when the body says
96
+ `low`, and the CLI warns that the two disagree. It also names who has **committed in those directories
97
+ in the last 30 days** (E67) — the people who can meet that ask — or says plainly that nobody has, or
98
+ that the history could not be read. It only prints; the body keeps the author's level. If
99
+ the level in the body is wrong, fix the body on the PR. When the map cannot be read (no `origin/<base>`
100
+ fetched, a newer map), it says so and counts the body alone. `bash checks/risk-route.sh "<pr body>"`
101
+ also lists the touched domains as a hint for whom to ask; request those reviewers on the PR/MR yourself.
102
+
103
+ ### Step 3a — Relay the reviewer suggestion (E68)
104
+ The CLI then prints two hints about whom to ask, on separate lines: the people who have **committed in
105
+ the folders this change touches in the last 30 days** (base branch; the change's own authors and robots
106
+ left out; ranked by commits, five shown), and what **CODEOWNERS on the base branch** lists for the changed
107
+ files. Relay both as they are. It is a **suggestion only**:
108
+
109
+ - Never request those people as reviewers on the PR/MR yourself, and never call them owners or required
110
+ approvers. A name is a hint about who **may** know the code. The author decides whom to ask.
111
+ - CODEOWNERS is a hint: these files go stale. A `CODEOWNERS line N not read — …` line is a line yadflow
112
+ could not match safely (the first three get a reason, the rest a count, and the list then says it
113
+ `may be wrong`); mention it, do not guess what it meant.
114
+ If the author asks whether CODEOWNERS is out of date, run `yad codeowners check <repo>` (E69) and relay
115
+ it. Never edit CODEOWNERS for them: a name written there becomes an owner the platform can enforce.
116
+ - The same person can appear in both lists under two names (a git name, a platform login). Do not join
117
+ them unless the output says `also in the 30-day history` (only a `noreply` login of the same platform counts, and only on github.com or gitlab.com).
118
+ - `not read` (a shallow clone, a missing base) is never "nobody". Say it as the CLI says it.
84
119
 
85
120
  ### Step 3b — Post the review trailer (optional, recommended)
86
121
  Make the reviewer's job easy: generate the 60-sec briefing and post it to the new PR/MR so it greets
@@ -93,8 +128,8 @@ The full fun-review flow (cards + grounded chat + engagement) is driven by the
93
128
  design — companion comments carry `<!-- yad:noblock -->`.
94
129
 
95
130
  ### Step 4 — Stop (no merge)
96
- Report the PR/MR URL and the requested reviewers. The PR now runs the check gates (Step C); the human
97
- engineer review and merge happen in `yad-engineer-review` (Step E).
131
+ Report the PR/MR URL and that no reviewers were requested. The PR now runs the check gates (Step C);
132
+ the human engineer review and merge happen in `yad-engineer-review` (Step E).
98
133
 
99
134
  ## Hard rules
100
135
 
@@ -102,7 +137,7 @@ engineer review and merge happen in `yad-engineer-review` (Step E).
102
137
  - **The base is the repo's default branch** unless you deliberately chose otherwise with `--base`.
103
138
  Never hardcode `main`, and never ignore the non-default-base warning silently.
104
139
  - **Title follows the commit subject** — Conventional-Commits style, so the `pr-title` gate passes.
105
- - **High risk routes to domain owners** — the same escalation as the gate; never a separate rule.
140
+ - **High risk raises the approver count** — the same count as the gate; never a separate rule.
106
141
  - **Opening a PR never merges.** The human owns the merge in Step E.
107
142
 
108
143
  ## Reference
@@ -26,14 +26,14 @@ platform.**
26
26
 
27
27
  ## Conventions
28
28
 
29
- - `{project-root}` resolves from the project working directory — the **product hub**.
29
+ - `{project-root}` resolves from the project working directory — the **Product**.
30
30
  - Build (code PR/MR): grounded by `yad review walkthrough --repo <r> --pr <n>`.
31
31
  - Shape (artifact-review PR/MR): grounded by `yad gate walkthrough <epic> [artifact]`.
32
32
  - The transferable review method + scorecard live in `references/review-rubric.md`.
33
33
  - The session-record comment shape, the dual sign-off, and the learning record this writes live in
34
34
  `references/session-state.md` (it reuses [`yad-learn`](../yad-learn/SKILL.md)'s ledger + gitignore
35
35
  discipline **verbatim** — the learning output is **local-only, never committed or pushed**).
36
- - Speak in the configured `communication_language`; write any rendered tutorial in
36
+ - Speak in the `communication_language` set in `{project-root}/.sdlc/config.yaml`; write any rendered tutorial in
37
37
  `document_output_language`.
38
38
 
39
39
  ## Inputs
@@ -49,7 +49,9 @@ platform.**
49
49
  Run the walkthrough grounding for the half you're on:
50
50
  - Build: `yad review walkthrough --repo <r> --pr <n>` → prints the grounding bundle **plus an ordered
51
51
  `stops[]`** (the code diff parsed into hunk-anchored, risk-tagged review stops, highest-risk first).
52
- - Shape: `yad gate walkthrough <epic> [artifact]` → the same, over the artifact's review diff.
52
+ - Shape: `yad gate walkthrough <epic> [artifact]` → the same, over the artifact's review diff. Its
53
+ `step.gateRule` carries the step's full approver count (`needed` distinct people, and the `risk`
54
+ tier that set it), and `step.cap` — an object `{ active, limit, to, capped }`: `to` is the count capped by the active people (E72), `capped` is true when the cap lowered it, and the whole field is `null` when the people were not counted — useful context for how hard a step is being reviewed, never a pass/fail input.
53
55
 
54
56
  **Read the real material yourself** — run the bundle's `diffCmd`, and read the named `codeMap` / `pack` /
55
57
  `contract` / `artifactPath` / `specs/<story>/` files. Never invent content. If a stop's material isn't
@@ -105,7 +107,7 @@ addresses them) — nothing advances on a half-finished session.
105
107
  `engineer-review` (back) / `<artifact>-review` (front), `mode` = `deep` (or `quiz` when you scored
106
108
  comprehension), `comprehension` = the scorecard roll-up, `tutorial` = a rendered
107
109
  `learning/<member>--review-<pr>.md` capturing the method as applied to this PR + the engineer's gaps.
108
- **First ensure the hub `.gitignore` covers the learning paths** (reuse yad-learn's guard), then write —
110
+ **First ensure the Product `.gitignore` covers the learning paths** (reuse yad-learn's guard), then write —
109
111
  these are personal, gitignored, **never committed or pushed**. The growth rolls up under `yad status`
110
112
  "My skills".
111
113
 
@@ -127,7 +129,7 @@ addresses them) — nothing advances on a half-finished session.
127
129
 
128
130
  ## local mode (no platform)
129
131
 
130
- With no hub platform there is no PR to post to: write the session record to
132
+ With no Product platform there is no PR to post to: write the session record to
131
133
  `reviews/<base>--<date>--pair-session.md` alongside the existing `reviews/*.md`, and the human records
132
134
  approval the manual way via [`yad-review-gate`](../yad-review-gate/SKILL.md). The learning record is
133
135
  written exactly the same (it is local-only regardless of platform). The session logic is unchanged; only
@@ -30,7 +30,7 @@ This is the "review **is** the lesson" half. It reuses [`yad-learn`](../../yad-l
30
30
  schema and gitignore discipline **verbatim** — see `yad-learn/references/learning-state.md`. Do not
31
31
  invent a new store.
32
32
 
33
- **Before writing anything**, ensure the **product hub's** `.gitignore` covers the learning paths
33
+ **Before writing anything**, ensure the **Product's** `.gitignore` covers the learning paths
34
34
  (idempotent — append only if absent), the same block yad-learn uses:
35
35
 
36
36
  ```
@@ -1,15 +1,17 @@
1
1
  ---
2
2
  name: yad-pr-template
3
- description: 'Build Step D of the gated SDLC. Detect a code repo''s platform and commit the matching PR/MR template — .github/pull_request_template.md (GitHub) or .gitlab/merge_request_templates/Default.md (GitLab). The template carries an Impact & Risk block; a high risk level (or a touched contract/auth/payments surface) routes the review to domain owners, reusing yad-review-gate''s escalation. Includes risk-route.sh to print the required reviewers from a PR body. Never auto-advances. Use when the user says "add the PR template" or "set up the MR template" for a repo.'
3
+ description: 'Build Step D of the gated SDLC. Detect a code repo''s platform and commit the matching PR/MR template — .github/pull_request_template.md (GitHub) or .gitlab/merge_request_templates/Default.md (GitLab). The template carries an Impact & Risk block; a high risk level (or a touched contract surface) raises the approver count, the same count yad-review-gate prints. Includes risk-route.sh to print that count from a PR body. Never auto-advances. Use when the user says "add the PR template" or "set up the MR template" for a repo.'
4
4
  ---
5
5
 
6
6
  # SDLC — PR/MR Template (Build Step D)
7
7
 
8
8
  **Goal:** Commit the platform-correct PR/MR template into a code repo so every PR/MR carries an
9
9
  **Impact & Risk** block and a checklist tied to the check gates. A **high** risk level (or a touched
10
- contract/auth/payments surface) **routes the review to domain owners** — the same escalation
11
- `yad-review-gate` applies on the Shape gates (owner + 1 reviewer, plus one domain-owner per
12
- touched domain). This step **never auto-advances**; it sets up the template and the routing helper.
10
+ contract surface) **raises the approver count** — the same count `yad-review-gate` prints on
11
+ the Shape gates: base 1 (someone other than the author, enforced) plus a risk step (`high` +1, contract
12
+ +2, advisory — branch protection holds the merge; `yad open-pr` shows the count capped by the active
13
+ people). This step **never auto-advances**; it sets up the template and the
14
+ routing helper.
13
15
 
14
16
  ## Conventions
15
17
 
@@ -21,11 +23,12 @@ touched domain). This step **never auto-advances**; it sets up the template and
21
23
  - `templates/gitlab/merge_request_templates/Default.md` → installs to
22
24
  `<repo>/.gitlab/merge_request_templates/Default.md`
23
25
  - `templates/checks/risk-route.sh` → installs to `<repo>/checks/risk-route.sh` (advisory routing helper)
24
- - **Hub variants** (`repo: hub`) — Shape artifact-review PR/MR bodies:
26
+ - **Product variants** (`repo: hub`) — Shape artifact-review PR/MR bodies:
25
27
  `templates/hub/github/pull_request_template.md` → `{project-root}/.github/pull_request_template.md`;
26
28
  `templates/hub/gitlab/merge_request_templates/Default.md` →
27
- `{project-root}/.gitlab/merge_request_templates/Default.md`. The hub body carries no `Task:` trailer
28
- (hub PRs change artifacts, not code); its routing helper is `yad-hub-bridge`'s `hub-route.sh`.
29
+ `{project-root}/.gitlab/merge_request_templates/Default.md`. The Product body carries no `Task:` trailer
30
+ (Product PRs change artifacts, not code); its routing helper is `yad-hub-bridge`'s
31
+ `templates/checks/hub-route.sh`, run from the skill (nothing installs it into the Product's `checks/`).
29
32
  - **GitLab reads a truncated description.** The `pr-template` gate is fed
30
33
  `$CI_MERGE_REQUEST_DESCRIPTION`, which GitLab cuts at **2700 characters** — a required section below
31
34
  that cutoff is invisible to the gate even though the MR shows it, and the failure reads "does not use
@@ -33,14 +36,15 @@ touched domain). This step **never auto-advances**; it sets up the template and
33
36
  `## Impact & Risk` / `## Checklist` (hub: `## Artifact under review` / `## Impact & Risk (front-half)`
34
37
  / `## Checklist`) early, so a truncated body still passes. Long narrative goes **after** them.
35
38
  Sections may be reordered freely; deleting one fails the gate. GitHub is unaffected.
36
- - **Installed templates are yad-managed.** `yad update` rewrites them on upgrade. An edit yad can
39
+ - **Installed code-repo templates are yad-managed.** `yad update` rewrites them on upgrade (the Product
40
+ variants under `templates/hub/` are copied by hand in Step 2 and are not managed). An edit yad can
37
41
  prove — the file's sha differs from the one it recorded when it wrote the template — is reported as
38
42
  `modified` and left alone; a copy it has no record of is replaced after a `.yad-orig` backup (see
39
43
  `docs/CLI.md` → *Managed files*). Either way, put knowledge that must survive an upgrade in an ADR
40
44
  under `docs/`, not in the template.
41
45
  - The Impact & Risk block reuses the conventions of earlier steps: the `Task: <story>-<task>` trailer
42
46
  (`yad-implement`), the contract surface (`yad-architecture` / contract-check), and the
43
- domain-owner escalation (`yad-review-gate`).
47
+ approver count (`yad-review-gate`).
44
48
  - **PR/MR title.** One atomic task = one branch = one PR/MR, so the title **defaults to that task's
45
49
  commit subject** and follows the same Conventional Commits style — `<type>: <lowercase imperative
46
50
  description, no trailing period>`, proper nouns/acronyms keep their case (`config.yaml`
@@ -50,8 +54,8 @@ touched domain). This step **never auto-advances**; it sets up the template and
50
54
 
51
55
  ## Inputs
52
56
 
53
- - `repo` — the code repo to add the template to (one of an epic's repos), or `hub` for the product hub.
54
- - `action` — `wire` (commit the matching template + helper) | `route` (print required reviewers from a
57
+ - `repo` — the code repo to add the template to (one of an epic's repos), or `hub` for the Product.
58
+ - `action` — `wire` (commit the matching template + helper) | `route` (print the approver count from a
55
59
  PR body). Default `wire`.
56
60
  - `body` — for `route`: a file holding the PR/MR description to evaluate.
57
61
 
@@ -68,24 +72,41 @@ Copy from this skill's `templates/`:
68
72
  - GitLab → `templates/gitlab/merge_request_templates/Default.md` to
69
73
  `<repo>/.gitlab/merge_request_templates/Default.md`.
70
74
  - **`repo: hub`** → use the `templates/hub/<platform>/…` variants, installed into `{project-root}`'s own
71
- `.github/`/`.gitlab/`. The hub's routing helper (`hub-route.sh`) is installed by `yad-hub-bridge`.
75
+ `.github/`/`.gitlab/`. The Product's routing helper (`hub-route.sh`) stays in `yad-hub-bridge`'s
76
+ `templates/checks/`; neither this skill nor `yad setup` / `yad check --fix` installs it.
72
77
  Drop **only the matching** template (drop both only if the repo genuinely uses both). For code repos also
73
- install `templates/checks/risk-route.sh` to `<repo>/checks/` (`chmod +x`). If the target already has a
78
+ install `templates/checks/risk-route.sh` to `<repo>/checks/` (`chmod +x`), beside
79
+ `../yad-checks/templates/checks/risk-map-check.sh` — risk-route reads the risk map through it, and
80
+ without it every count says "not counted". `yad update` installs both. If the target already has a
74
81
  non-SDLC PR/MR template, do not clobber it — back it up / ask. Commit the template on the repo's default
75
82
  branch (shared infrastructure, not a task diff).
76
83
 
77
- ### Step 3 — `route` (show who must review)
78
- Run `bash checks/risk-route.sh <body>` to parse the PR description's Impact & Risk block and print the
79
- required reviewers:
80
- - **low | medium** risk → base rule: owner + 1 reviewer.
81
- - **high** risk (or a contract/auth/payments surface touched) → base rule **plus** one domain-owner
82
- approval per touched domain — identical to `yad-review-gate`'s escalation. The actual approvals are
83
- recorded by the engineer review (Step E), via `yad-review-gate`.
84
+ ### Step 3 — `route` (show how many approvers)
85
+ Run `bash checks/risk-route.sh <body> [<base>]` **inside the code repo, on the PR's branch** to parse the
86
+ PR description's Impact & Risk block, read the base branch's risk map, and print the approver count:
87
+ - **low | medium** risk → `ROUTE: 1 approver = base 1 (no risk step).`
88
+ - **high** risk → `ROUTE: 2 approvers = base 1 + high risk 1 (risk: high)`.
89
+ - a **contract surface** touched → `ROUTE: 3 approvers = base 1 + contract risk 2 (contract surface
90
+ touched)`. With `high` too, the larger step (contract) wins, never the sum.
91
+ - a change touching a directory the **base branch's** `.sdlc/risk-map` marks `high` → +1 as well (E66),
92
+ even when the body says `low`: the larger step wins, and the script says the two disagree. A `guessed`
93
+ level counts. When the map cannot be read, it says so and counts the body alone.
94
+ - that same `high` directory asks for an approval from someone who **committed there in the last 30
95
+ days** (E67). The script names them from the base branch's history, without this change's own authors,
96
+ as one list across every `high` directory touched; "nobody" and "not read" are said apart.
84
97
 
85
- When the PR/MR is actually opened with `yad open-pr`, these reviewers are **requested automatically**
86
- from the repo-scoped roster (everyone with `reviewer`/`domain-owner` for the repo, minus the committer),
87
- and the **committer is set as the assignee**. `risk-route.sh` remains the advisory printout of who the
88
- gate will require.
98
+ When the count is raised, the script adds that branch protection holds the merge, not this count (at
99
+ least 1 approval from someone other than the author), that the risk step is advisory and not capped
100
+ there (`yad open-pr` shows the count capped by the active people), and lists the touched
101
+ domains as a hint for whom to ask. The actual approvals are recorded by the engineer review (Step E),
102
+ via `yad-review-gate`.
103
+
104
+ When the PR/MR is actually opened with `yad open-pr`, **no reviewers are requested** — it prints `no
105
+ reviewers were requested — ask them on the PR itself`. The **assignee** is the person opening it: `@me`
106
+ on GitHub (resolved by `gh`), and on GitLab the login `glab` reports (no assignee is passed when that
107
+ lookup fails). yadflow keeps no list of people. After opening, it prints a reviewer suggestion (E68):
108
+ who has committed in the touched folders in the last 30 days, and what CODEOWNERS lists — a hint only,
109
+ never a request.
89
110
 
90
111
  ### Step 4 — Stop (no auto-advance)
91
112
  Report what was committed (or the routing result). The template and routing are advisory inputs to the
@@ -94,10 +115,10 @@ human review (Step E); they do not approve or merge. Do not touch the epic's `.s
94
115
  ## Hard rules (build plan §D, Cross-cutting)
95
116
 
96
117
  - **Drop only the matching template** for the detected platform.
97
- - **High risk routes to domain owners** — the same escalation as the gate; never a separate rule.
118
+ - **High risk raises the approver count** — the same count as the gate; never a separate rule.
98
119
  - **Nothing auto-advances.** The template sets up review; the human owns the merge.
99
120
 
100
121
  ## Reference
101
122
  - The Impact & Risk block, the risk levels, and the routing rule: `references/risk-routing.md`.
102
- - The escalation this reuses: `../yad-review-gate/SKILL.md` and its `references/gating.md`.
123
+ - The approver count this reuses: `../yad-review-gate/SKILL.md` and its `references/gating.md`.
103
124
  - The check gates the checklist references: `../yad-checks/references/check-gates.md`.