yadflow 1.0.1 → 2.0.0
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 +25 -0
- package/README.md +137 -134
- package/bin/{sdlc.mjs → yad.mjs} +18 -17
- package/cli/commit.mjs +3 -3
- package/cli/epic-state.mjs +2 -2
- package/cli/gate.mjs +8 -8
- package/cli/lib.mjs +1 -1
- package/cli/manifest.mjs +77 -36
- package/cli/openpr.mjs +3 -3
- package/cli/plan.mjs +88 -1
- package/cli/platform.mjs +2 -2
- package/cli/reconcile.mjs +18 -10
- package/cli/repo.mjs +5 -5
- package/cli/setup.mjs +7 -7
- package/docs/index.html +1227 -0
- package/package.json +10 -7
- package/skills/sdlc/config.yaml +24 -24
- package/skills/sdlc/install.sh +2 -2
- package/skills/sdlc/module-help.csv +16 -16
- package/skills/{sdlc-author-analysis → yad-analysis}/SKILL.md +12 -12
- package/skills/{sdlc-author-architecture → yad-architecture}/SKILL.md +12 -12
- package/skills/{sdlc-author-architecture → yad-architecture}/references/contract-format.md +1 -1
- package/skills/{sdlc-backfill → yad-backfill}/SKILL.md +4 -4
- package/skills/{sdlc-backfill → yad-backfill}/references/backfill.md +2 -2
- package/skills/{sdlc-backfill → yad-backfill}/templates/checks/backfill-check.sh +1 -1
- package/skills/{sdlc-checks → yad-checks}/SKILL.md +20 -20
- package/skills/{sdlc-checks → yad-checks}/references/check-gates.md +21 -21
- package/skills/{sdlc-checks → yad-checks}/templates/checks/contract-check.sh +2 -2
- package/skills/{sdlc-checks → yad-checks}/templates/checks/verified-commits.sh +2 -2
- package/skills/{sdlc-checks/templates/github/sdlc-checks.yml → yad-checks/templates/github/yad-checks.yml} +3 -3
- package/skills/{sdlc-checks/templates/github/sdlc-verified-commits.yml → yad-checks/templates/github/yad-verified-commits.yml} +4 -4
- package/skills/{sdlc-checks → yad-checks}/templates/gitlab/gitlab-ci.include-root.yml +3 -3
- package/skills/{sdlc-checks/templates/gitlab/sdlc-checks.gitlab-ci.yml → yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml} +7 -7
- package/skills/{sdlc-checks/templates/gitlab/sdlc-verified-commits.gitlab-ci.yml → yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml} +4 -4
- package/skills/{sdlc-connect-repos → yad-connect-repos}/SKILL.md +7 -7
- package/skills/{sdlc-connect-repos → yad-connect-repos}/references/code-context.md +6 -6
- package/skills/{sdlc-connect-repos → yad-connect-repos}/references/hub-config.md +3 -3
- package/skills/{sdlc-author-epic → yad-epic}/SKILL.md +13 -13
- package/skills/{sdlc-author-epic → yad-epic}/references/state-schema.md +13 -13
- package/skills/{sdlc-hub-bridge → yad-hub-bridge}/SKILL.md +24 -24
- package/skills/{sdlc-hub-bridge → yad-hub-bridge}/references/bridge.md +11 -11
- package/skills/{sdlc-hub-bridge → yad-hub-bridge}/references/login-roster.md +2 -2
- package/skills/{sdlc-hub-bridge → yad-hub-bridge}/templates/checks/hub-route.sh +3 -3
- package/skills/{sdlc-hub-bridge/templates/github/sdlc-gate-sync.yml → yad-hub-bridge/templates/github/yad-gate-sync.yml} +10 -10
- package/skills/{sdlc-hub-bridge → yad-hub-bridge}/templates/gitlab/gitlab-ci.include-root.yml +3 -3
- package/skills/{sdlc-hub-bridge/templates/gitlab/sdlc-gate-sync.gitlab-ci.yml → yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml} +11 -11
- package/skills/{sdlc-implement → yad-implement}/SKILL.md +14 -14
- package/skills/{sdlc-implement → yad-implement}/references/implement-conventions.md +4 -4
- package/skills/{sdlc-pr-template → yad-pr-template}/SKILL.md +11 -11
- package/skills/{sdlc-pr-template → yad-pr-template}/references/risk-routing.md +5 -5
- package/skills/{sdlc-pr-template → yad-pr-template}/templates/checks/risk-route.sh +2 -2
- package/skills/{sdlc-pr-template → yad-pr-template}/templates/github/pull_request_template.md +1 -1
- package/skills/{sdlc-pr-template → yad-pr-template}/templates/gitlab/merge_request_templates/Default.md +1 -1
- package/skills/{sdlc-pr-template → yad-pr-template}/templates/hub/github/pull_request_template.md +4 -4
- package/skills/{sdlc-pr-template → yad-pr-template}/templates/hub/gitlab/merge_request_templates/Default.md +4 -4
- package/skills/{sdlc-review-comments → yad-review-comments}/SKILL.md +6 -6
- package/skills/{sdlc-review-comments → yad-review-comments}/references/comment-conventions.md +6 -6
- package/skills/{sdlc-review-comments → yad-review-comments}/templates/github/REVIEW_COMMENTS.md +2 -2
- package/skills/{sdlc-review-comments → yad-review-comments}/templates/gitlab/REVIEW_COMMENTS.md +2 -2
- package/skills/{sdlc-review-gate → yad-review-gate}/SKILL.md +13 -13
- package/skills/{sdlc-review-gate → yad-review-gate}/references/gating.md +3 -3
- package/skills/{sdlc-run → yad-run}/SKILL.md +12 -12
- package/skills/{sdlc-run → yad-run}/references/run-loop.md +10 -10
- package/skills/{sdlc-ship → yad-ship}/SKILL.md +8 -8
- package/skills/{sdlc-ship → yad-ship}/references/ship-and-record.md +3 -3
- package/skills/{sdlc-ship → yad-ship}/templates/.coderabbit.yaml +1 -1
- package/skills/{sdlc-spec → yad-spec}/SKILL.md +11 -11
- package/skills/{sdlc-spec → yad-spec}/references/spec-handoff.md +2 -2
- package/skills/{sdlc-status → yad-status}/SKILL.md +6 -6
- package/skills/{sdlc-author-stories → yad-stories}/SKILL.md +10 -10
- package/skills/{sdlc-author-stories → yad-stories}/references/story-schema.md +1 -1
- package/skills/{sdlc-author-ui → yad-ui}/SKILL.md +9 -9
- /package/skills/{sdlc-checks → yad-checks}/templates/checks/build-test-lint.sh +0 -0
- /package/skills/{sdlc-checks → yad-checks}/templates/checks/spec-link.sh +0 -0
- /package/skills/{sdlc-checks → yad-checks}/templates/gitlab/.gitlab-ci.yml +0 -0
- /package/skills/{sdlc-connect-repos → yad-connect-repos}/references/repos-registry.md +0 -0
- /package/skills/{sdlc-implement → yad-implement}/templates/.gitmessage +0 -0
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: 'The templated PR/MR bridge for the front-half review gate. When the product hub has a platform (.sdlc/hub.json), it opens a review PR/MR on the hub for an authored artifact (the optional analysis / epic / architecture+contract / ui-design / stories), sets the required reviewers/labels from the routing rule, and provides the read-only gh/glab recipes that
|
|
2
|
+
name: yad-hub-bridge
|
|
3
|
+
description: 'The templated PR/MR bridge for the front-half review gate. When the product hub has a platform (.sdlc/hub.json), it opens a review PR/MR on the hub for an authored artifact (the optional analysis / epic / architecture+contract / ui-design / stories), sets the required reviewers/labels from the routing rule, and provides the read-only gh/glab recipes that yad-review-gate uses to pull platform comments + approvals back into the file ledger. Can also wire event-driven sync on the hub: a CI workflow that runs `yad gate ci` whenever a reviewer approves / requests changes / a human merges, committing the ledger to the default branch. Local-user auth only — no stored tokens. The file ledger stays the source of truth; degrades to the file-only gate when there is no platform / no CLI. Use when the user says "open the review PR", "route the review", "wire the gate sync", or it is invoked by yad-review-gate open/sync.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Hub Review Bridge (the templated PR/MR bridge)
|
|
7
7
|
|
|
8
8
|
**Goal:** Run the front-half review/comment/approval cycle through a **real PR/MR on the product hub**,
|
|
9
9
|
without changing the gate's predicate or making the file ledger optional. The bridge is an **alternate
|
|
10
|
-
input path** into `
|
|
10
|
+
input path** into `yad-review-gate`: it opens a review PR for an artifact, reviewers approve/comment on
|
|
11
11
|
the platform with **their own** `gh`/`glab` auth, and the gate's `sync` action (which calls this skill's
|
|
12
12
|
read recipes) maps that platform state into `approvals.json` / `comments.json` / `reviews/*.md`, then
|
|
13
13
|
runs the **unchanged** predicate. The file ledger remains the source of truth.
|
|
14
14
|
|
|
15
|
-
This skill owns the **branch/PR mechanics + the gh/glab recipes** (mirroring how `
|
|
16
|
-
keeps platform mechanics out of the gate). `
|
|
15
|
+
This skill owns the **branch/PR mechanics + the gh/glab recipes** (mirroring how `yad-pr-template`
|
|
16
|
+
keeps platform mechanics out of the gate). `yad-review-gate` *calls* it; it never advances a step.
|
|
17
17
|
|
|
18
18
|
## Conventions
|
|
19
19
|
|
|
20
20
|
- `{project-root}` is the **product hub**. Hub platform + reviewer roster live in `.sdlc/hub.json`
|
|
21
|
-
(`config.yaml` `hub.config`; schema in `../
|
|
21
|
+
(`config.yaml` `hub.config`; schema in `../yad-connect-repos/references/hub-config.md`).
|
|
22
22
|
- Per-step review-PR record: `epics/EP-<slug>/.sdlc/hub-prs.json` (`config.yaml` `hub.pr_ledger`) — a
|
|
23
23
|
sibling ledger to `approvals.json`, so `state.json`'s locked step shape is untouched.
|
|
24
|
-
- The review-PR body is the hub template from `
|
|
24
|
+
- The review-PR body is the hub template from `yad-pr-template` (`templates/hub/<platform>/…`).
|
|
25
25
|
- Branch per artifact: `review/EP-<slug>/<artifact-base>` (`config.yaml` `hub.artifact_branch`).
|
|
26
26
|
- **Local-user auth only; store no tokens.** Use the user's own `gh`/`glab`. If neither is installed/
|
|
27
27
|
authenticated, STOP this path and tell the gate to fall back to file-only — never embed a credential.
|
|
@@ -31,7 +31,7 @@ keeps platform mechanics out of the gate). `sdlc-review-gate` *calls* it; it nev
|
|
|
31
31
|
- `epic` — the `EP-<slug>` under review.
|
|
32
32
|
- `artifact` — the artifact file (`analysis.md` | `epic.md` | `architecture.md` | `ui-design.md` | `stories/`).
|
|
33
33
|
- `action` — `open` | `route` | `wire` (default `route`). (`sync`'s ledger writes live in
|
|
34
|
-
`
|
|
34
|
+
`yad-review-gate`; this skill provides the read recipes `sync` calls — see `references/bridge.md`.)
|
|
35
35
|
|
|
36
36
|
## Preconditions (the bridge runs only when all hold)
|
|
37
37
|
|
|
@@ -44,7 +44,7 @@ gate proceeds **file-only** (no error) and stop.
|
|
|
44
44
|
### Step 1 — Resolve platform + routing
|
|
45
45
|
Read `.sdlc/hub.json` for the platform and roster, `epics/<epic>/epic.md` for `repos` + `owner`, and the
|
|
46
46
|
matching `review+approve` step's `risk_tags` from `.sdlc/state.json`. Compute the **required reviewers**
|
|
47
|
-
with `route` (below) — the same rule `
|
|
47
|
+
with `route` (below) — the same rule `yad-review-gate` enforces: base (owner + 1 reviewer); escalated
|
|
48
48
|
(`risk_tags` ∩ {contract,auth,payments}, or the stories step) adds a domain-owner per touched repo. Map
|
|
49
49
|
each required domain-owner to a platform `login` via the roster (a roster `name` equal to a repo's
|
|
50
50
|
`domain_owner` in `repos.json` is that repo's domain-owner).
|
|
@@ -53,7 +53,7 @@ each required domain-owner to a platform `login` via the roster (a roster `name`
|
|
|
53
53
|
1. From the hub default branch, create `review/EP-<slug>/<artifact-base>` and ensure the artifact file
|
|
54
54
|
(and, for architecture, `contract.md` + `.sdlc/contract-lock.json`) is committed on it. Push as the
|
|
55
55
|
local user.
|
|
56
|
-
2. Open the PR/MR with `gh`/`glab` using the hub body template (`
|
|
56
|
+
2. Open the PR/MR with `gh`/`glab` using the hub body template (`yad-pr-template` `templates/hub/…`),
|
|
57
57
|
filled with the epic, artifact, gate step, owner, `epic.repos`, and the step's risk tags.
|
|
58
58
|
3. **Request the required reviewers** (their logins) and add a `domain:<repo>` label per touched repo so
|
|
59
59
|
per-repo routing is legible on the PR.
|
|
@@ -63,7 +63,7 @@ each required domain-owner to a platform `login` via the roster (a roster `name`
|
|
|
63
63
|
"number": <n>, "url": "<pr/mr url>", "branch": "review/EP-<slug>/<artifact-base>", "lastSyncedAt": null }
|
|
64
64
|
```
|
|
65
65
|
5. Report the PR/MR URL and the required reviewers. **Do not** record approvals or advance — reviewers
|
|
66
|
-
act on the platform; `
|
|
66
|
+
act on the platform; `yad-review-gate action: sync` pulls it back.
|
|
67
67
|
|
|
68
68
|
### Step 3 — `route` (print required reviewers)
|
|
69
69
|
Compute and print the required reviewers as above. Use `templates/checks/hub-route.sh <body>` to parse a
|
|
@@ -72,18 +72,18 @@ PR/MR body's Impact & Risk block when given one; otherwise derive from `epic.rep
|
|
|
72
72
|
|
|
73
73
|
### Step 4 — `wire` (event-driven sync on the hub)
|
|
74
74
|
Install the hub CI that turns platform actions — a review **approval**, a **change request**, a review
|
|
75
|
-
dismissal, or the human **merge** — into an automatic `
|
|
76
|
-
commits it to the hub's default branch. No more waiting on a manual `
|
|
75
|
+
dismissal, or the human **merge** — into an automatic `yad gate ci` run that syncs the ledger and
|
|
76
|
+
commits it to the hub's default branch. No more waiting on a manual `yad gate sync`; the manual command
|
|
77
77
|
remains valid and is the fallback whenever CI cannot push.
|
|
78
78
|
|
|
79
|
-
1. Run `
|
|
79
|
+
1. Run `yad check --fix` (the wiring is manifest-driven, like `yad-checks`): with a platform +
|
|
80
80
|
enabled bridge in `.sdlc/hub.json` it installs
|
|
81
|
-
- GitHub → `.github/workflows/
|
|
82
|
-
- GitLab → `.gitlab/ci/
|
|
81
|
+
- GitHub → `.github/workflows/yad-gate-sync.yml` (from `templates/github/yad-gate-sync.yml`)
|
|
82
|
+
- GitLab → `.gitlab/ci/yad-gate-sync.yml` (from `templates/gitlab/yad-gate-sync.gitlab-ci.yml`)
|
|
83
83
|
- plus the hub-side **verified-commits** gate (`checks/verified-commits.sh` + its workflow/fragment,
|
|
84
|
-
owned by `
|
|
84
|
+
owned by `yad-checks`) so review PRs accept only signed commits from roster-known authors
|
|
85
85
|
2. **GitLab only — two one-time steps** (see the fragment's header for the exact recipes):
|
|
86
|
-
- add `include: - local: '.gitlab/ci/
|
|
86
|
+
- add `include: - local: '.gitlab/ci/yad-gate-sync.yml'` to the root `.gitlab-ci.yml`, or write
|
|
87
87
|
`templates/gitlab/gitlab-ci.include-root.yml` as the root when none exists;
|
|
88
88
|
- create the 15-minute pipeline **schedule** (variable `SDLC_GATE_SYNC=true`) and the masked
|
|
89
89
|
`SDLC_GATE_TOKEN` project-access-token variable (`read_api` + `write_repository`). GitLab fires no
|
|
@@ -91,17 +91,17 @@ remains valid and is the fallback whenever CI cannot push.
|
|
|
91
91
|
latency); MR events and the merge are near-immediate.
|
|
92
92
|
3. Commit the workflow to the hub. GitHub needs nothing else — the ephemeral `github.token` reads the
|
|
93
93
|
PR and pushes the ledger. If the default branch is protected, see the workflow header for the
|
|
94
|
-
bypass / PAT options; until then the run fails visibly and manual `
|
|
94
|
+
bypass / PAT options; until then the run fails visibly and manual `yad gate sync` still works.
|
|
95
95
|
|
|
96
96
|
## Hard rules
|
|
97
97
|
|
|
98
98
|
- **Local-user auth only; store no tokens.** Reviewers use their own `gh`/`glab`.
|
|
99
99
|
- **The bridge is an input path, never the authority.** It opens PRs and reads state; the **file ledger
|
|
100
|
-
is the source of truth** and the gate predicate (in `
|
|
100
|
+
is the source of truth** and the gate predicate (in `yad-review-gate`) is unchanged.
|
|
101
101
|
- **The bridge never approves on a reviewer's behalf.** Reviewers approve/merge with their own auth. The
|
|
102
102
|
step advances when a human **merges** the approved, fully-resolved review PR (the merge is that human
|
|
103
|
-
act) — `
|
|
104
|
-
comments or a changed artifact hold it `in_review`. The mechanical sync is the `
|
|
103
|
+
act) — `yad gate sync` records the approvals + resolution + merged state and advances; unresolved
|
|
104
|
+
comments or a changed artifact hold it `in_review`. The mechanical sync is the `yad gate` CLI.
|
|
105
105
|
- **CI never approves and never merges.** The wired workflow only runs `gate ci` — the same sync +
|
|
106
106
|
unchanged predicate — and commits the **ledger files only** to the default branch; the artifact lands
|
|
107
107
|
on the default branch exclusively via the human merge. Front gates stay permanently human.
|
|
@@ -115,5 +115,5 @@ remains valid and is the fallback whenever CI cannot push.
|
|
|
115
115
|
- PR-body→ledger mapping, the read-only gh/glab recipes, idempotent re-sync, contract re-lock handling:
|
|
116
116
|
`references/bridge.md`.
|
|
117
117
|
- Roster schema, login→role resolution, unverified-login fallback, per-repo routing: `references/login-roster.md`.
|
|
118
|
-
- The gate this feeds (open hook + sync action + unchanged predicate): `../
|
|
119
|
-
- The hub PR/MR body template + the code-repo routing analogue: `../
|
|
118
|
+
- The gate this feeds (open hook + sync action + unchanged predicate): `../yad-review-gate/SKILL.md`, `../yad-review-gate/references/gating.md`.
|
|
119
|
+
- The hub PR/MR body template + the code-repo routing analogue: `../yad-pr-template/`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# The bridge — PR/MR ↔ ledger mapping, read recipes, idempotency
|
|
2
2
|
|
|
3
3
|
The bridge maps platform review state onto the **same file records** the manual gate writes, so the gate
|
|
4
|
-
predicate (`../
|
|
4
|
+
predicate (`../yad-review-gate/references/gating.md`) runs unchanged. The bridge only changes the
|
|
5
5
|
*input path*; it never changes what passing the gate means.
|
|
6
6
|
|
|
7
7
|
## State mapping (platform → ledger)
|
|
@@ -72,7 +72,7 @@ comments, replies, the reviewer **resolves** their thread, then `sync` runs agai
|
|
|
72
72
|
|
|
73
73
|
- **Merge → advance.** When the reviewer rule is satisfied, every thread is resolved, **and the review
|
|
74
74
|
PR/MR is merged**, `sync` marks the step `done` and unblocks the next step. The merge is the human
|
|
75
|
-
approval act — there is no separate machine advance. (`
|
|
75
|
+
approval act — there is no separate machine advance. (`yad gate sync` performs this deterministically.)
|
|
76
76
|
- **Revoke on artifact change.** Each bridge approval is stamped with the content hash it was given
|
|
77
77
|
against (the file bytes; the locked contract surface for architecture). On re-sync, an approval whose
|
|
78
78
|
stamped hash ≠ the current hash is **dropped** — the reviewer must re-approve the changed artifact. A
|
|
@@ -82,10 +82,10 @@ comments, replies, the reviewer **resolves** their thread, then `sync` runs agai
|
|
|
82
82
|
## Event-driven sync (hub CI)
|
|
83
83
|
|
|
84
84
|
The `wire` action (SKILL.md Step 4) installs a CI workflow on the hub so the platform events drive
|
|
85
|
-
`
|
|
85
|
+
`yad gate ci` instead of waiting on a manual `yad gate sync`. The CLI entry is self-sufficient: it
|
|
86
86
|
derives the epic + artifact from the `review/EP-<slug>/<artifact-base>` head branch and takes the PR/MR
|
|
87
87
|
number from the event payload — it even upserts the `hub-prs.json` entry when the author never committed
|
|
88
|
-
it, so the first CI commit converges the views. `
|
|
88
|
+
it, so the first CI commit converges the views. `yad gate ci` with no `--branch` sweeps every open
|
|
89
89
|
review PR (the scheduled path).
|
|
90
90
|
|
|
91
91
|
| Platform event | CI action |
|
|
@@ -115,22 +115,22 @@ across epics touch disjoint files).
|
|
|
115
115
|
push.
|
|
116
116
|
- Protected default branch (GitHub): prefer a ruleset bypass for Actions; else a fine-grained PAT as
|
|
117
117
|
`SDLC_GATE_TOKEN` passed to `actions/checkout`; else leave it — the run fails **visibly** and manual
|
|
118
|
-
`
|
|
118
|
+
`yad gate sync` remains the fallback. Never wire branch protection that couples the merge itself to
|
|
119
119
|
the gate.
|
|
120
120
|
|
|
121
|
-
**Manual sync stays first-class.** `
|
|
121
|
+
**Manual sync stays first-class.** `yad gate sync <epic> [artifact]` is unchanged and always valid —
|
|
122
122
|
the CI is the same sync on a trigger, and the file ledger is still the source of truth.
|
|
123
123
|
|
|
124
124
|
### Manual end-to-end verification (GitHub)
|
|
125
125
|
|
|
126
|
-
1. On a scratch hub: `
|
|
127
|
-
installs `.github/workflows/
|
|
128
|
-
2. Author an epic → `
|
|
126
|
+
1. On a scratch hub: `yad setup` (platform github, roster with a second account) → `yad check --fix`
|
|
127
|
+
installs `.github/workflows/yad-gate-sync.yml`; commit + push it.
|
|
128
|
+
2. Author an epic → `yad gate open EP-x epic.md` → the review PR opens.
|
|
129
129
|
3. Second account **approves** → the Actions run commits `approvals.json` to the default branch.
|
|
130
|
-
4. Second account **requests changes** → the run records the blocking comment; `
|
|
130
|
+
4. Second account **requests changes** → the run records the blocking comment; `yad gate status EP-x`
|
|
131
131
|
(after `git pull`) shows the gate held.
|
|
132
132
|
5. Resolve the thread, approve again, a human **merges** → the closed-event run advances `state.json`
|
|
133
133
|
(`epic-review: done`, `currentStep: architecture`).
|
|
134
|
-
6. `git pull` locally — `
|
|
134
|
+
6. `git pull` locally — `yad gate status EP-x` matches the platform history.
|
|
135
135
|
|
|
136
136
|
GitLab variant: same flow on an MR; a bare approval appears after the next schedule tick.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The roster lives in `.sdlc/hub.json` (`roster: [...]`) and is the only thing that turns a platform
|
|
4
4
|
**login** into an SDLC **name + role** for the ledger. Schema and the no-tokens rule are documented once
|
|
5
|
-
in `../../
|
|
5
|
+
in `../../yad-connect-repos/references/hub-config.md`; this file covers how the bridge *uses* it.
|
|
6
6
|
|
|
7
7
|
## Entry
|
|
8
8
|
|
|
@@ -38,5 +38,5 @@ review PR the bridge makes this legible and enforceable:
|
|
|
38
38
|
`repos.json[R].domain_owner == roster[L].name`. So a domain owner's approval is scoped to exactly the
|
|
39
39
|
repos they own, and a repo with no approving owner shows up as still-required in the gate report.
|
|
40
40
|
|
|
41
|
-
This is the same touched-domains computation the gate uses (`../
|
|
41
|
+
This is the same touched-domains computation the gate uses (`../yad-review-gate/references/gating.md`):
|
|
42
42
|
architecture+contract → `epic.repos`; stories → union of story `repos`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Hub review routing — the front-half analogue of
|
|
2
|
+
# Hub review routing — the front-half analogue of yad-pr-template's risk-route.sh. Reads a hub review
|
|
3
3
|
# PR/MR description's "Impact & Risk (front-half)" block and prints the required reviewers, reusing
|
|
4
|
-
#
|
|
4
|
+
# yad-review-gate's rule: base = owner + 1 reviewer; if a risk tag (contract|auth|payments) is set OR
|
|
5
5
|
# the artifact is the stories set, ALSO a domain-owner per touched repo. Advisory: it ROUTES the human
|
|
6
6
|
# review; it does not approve or merge.
|
|
7
7
|
set -euo pipefail
|
|
@@ -35,7 +35,7 @@ case "$artifact" in *stories*) escalate=yes; why="${why:+$why, }stories per-repo
|
|
|
35
35
|
|
|
36
36
|
if [ "$escalate" = "yes" ]; then
|
|
37
37
|
echo "ROUTE: ESCALATED (${why}) -> owner + 1 reviewer PLUS one domain-owner approval per touched repo"
|
|
38
|
-
echo " (same escalation as
|
|
38
|
+
echo " (same escalation as yad-review-gate; map each repo to its domain_owner in repos.json)."
|
|
39
39
|
case "$repos" in
|
|
40
40
|
""|*"<"*|*"…"*|*"|"*)
|
|
41
41
|
echo " (Repos line not filled in — list each touched repo to route the domain owners.)" ;;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yad-managed: yad-hub-bridge
|
|
2
2
|
# Event-driven gate sync for the PRODUCT HUB. When a reviewer approves, requests changes, or a
|
|
3
|
-
# human merges a review/EP-* PR, this workflow runs `
|
|
3
|
+
# human merges a review/EP-* PR, this workflow runs `yad gate ci`, which maps the platform state
|
|
4
4
|
# into the file ledger (epics/<epic>/.sdlc/*.json + reviews/*.md) and commits ONLY those ledger
|
|
5
5
|
# files to the default branch. It never approves and never merges — the merge click remains the
|
|
6
|
-
# human approval act; the gate predicate is the same one `
|
|
6
|
+
# human approval act; the gate predicate is the same one `yad gate sync` runs locally.
|
|
7
7
|
#
|
|
8
8
|
# Loop prevention: neither `pull_request_review` nor `pull_request` fires on a push to the default
|
|
9
9
|
# branch, and the ledger commit carries [skip ci] to guard every other workflow.
|
|
10
10
|
#
|
|
11
11
|
# Protected default branch? The github.token push will fail (visibly — the run goes red and manual
|
|
12
|
-
# `
|
|
12
|
+
# `yad gate sync` still works). Options, in order of preference:
|
|
13
13
|
# a) add a ruleset bypass so GitHub Actions may push to the default branch, or
|
|
14
14
|
# b) store a fine-grained PAT as the SDLC_GATE_TOKEN secret and pass it to actions/checkout via
|
|
15
15
|
# `with: { token: ${{ secrets.SDLC_GATE_TOKEN }} }` — the one exception to the bridge's
|
|
16
|
-
# no-stored-tokens rule; see skills/
|
|
17
|
-
name:
|
|
16
|
+
# no-stored-tokens rule; see skills/yad-hub-bridge/references/bridge.md.
|
|
17
|
+
name: yad-gate-sync
|
|
18
18
|
on:
|
|
19
19
|
pull_request_review:
|
|
20
20
|
types: [submitted, dismissed]
|
|
@@ -28,7 +28,7 @@ permissions:
|
|
|
28
28
|
# Serialize runs repo-wide so ledger pushes never race; sync reads the FULL platform state each
|
|
29
29
|
# time, so a queued superseded run loses nothing.
|
|
30
30
|
concurrency:
|
|
31
|
-
group:
|
|
31
|
+
group: yad-gate-sync
|
|
32
32
|
cancel-in-progress: false
|
|
33
33
|
|
|
34
34
|
jobs:
|
|
@@ -56,8 +56,8 @@ jobs:
|
|
|
56
56
|
node-version: "20"
|
|
57
57
|
- name: Sync the gate ledger
|
|
58
58
|
run: |
|
|
59
|
-
git config user.name "
|
|
60
|
-
git config user.email "
|
|
61
|
-
npx -y -p yadflow@
|
|
59
|
+
git config user.name "yad-gate-sync[bot]"
|
|
60
|
+
git config user.email "yad-gate-sync[bot]@users.noreply.github.com"
|
|
61
|
+
npx -y -p yadflow@2 yad gate ci \
|
|
62
62
|
--branch "${{ github.event.pull_request.head.ref }}" \
|
|
63
63
|
--pr "${{ github.event.pull_request.number }}"
|
package/skills/{sdlc-hub-bridge → yad-hub-bridge}/templates/gitlab/gitlab-ci.include-root.yml
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# SDLC gate sync — minimal root pipeline for the PRODUCT HUB.
|
|
2
|
-
# Written by the
|
|
2
|
+
# Written by the yad-hub-bridge `wire` action ONLY when the hub has no existing root
|
|
3
3
|
# `.gitlab-ci.yml`. The job itself lives in the included fragment so the same single source is
|
|
4
4
|
# reused whether or not a root pipeline already exists. If a root later grows real jobs, they
|
|
5
|
-
# coexist with the included
|
|
5
|
+
# coexist with the included yad-* job (which carries `needs: []` and no `stage:`).
|
|
6
6
|
include:
|
|
7
|
-
- local: '.gitlab/ci/
|
|
7
|
+
- local: '.gitlab/ci/yad-gate-sync.yml'
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yad-managed-include: yad-hub-bridge
|
|
2
2
|
# Event-driven gate sync for the PRODUCT HUB, as an INCLUDABLE fragment. Pulled into the hub's
|
|
3
3
|
# root .gitlab-ci.yml via:
|
|
4
4
|
# include:
|
|
5
|
-
# - local: '.gitlab/ci/
|
|
5
|
+
# - local: '.gitlab/ci/yad-gate-sync.yml'
|
|
6
6
|
# so wiring never edits the foreign root pipeline beyond that one include line. The job carries
|
|
7
|
-
# `needs: []` and no `stage:` (same merge-safety as the
|
|
7
|
+
# `needs: []` and no `stage:` (same merge-safety as the yad-checks fragment).
|
|
8
8
|
#
|
|
9
|
-
# What it does: run `
|
|
9
|
+
# What it does: run `yad gate ci`, which maps MR approvals / change-request discussions / the
|
|
10
10
|
# merge into the file ledger (epics/<epic>/.sdlc/*.json + reviews/*.md) and commits ONLY those
|
|
11
11
|
# ledger files to the default branch. It never approves and never merges — the merge click remains
|
|
12
12
|
# the human approval act.
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
# be committed as code): cron `*/15 * * * *` with variable SDLC_GATE_SYNC=true — so an approval
|
|
18
18
|
# can take up to ~15 minutes to reach the ledger. UI: CI/CD > Schedules, or:
|
|
19
19
|
# glab api projects/:id/pipeline_schedules -X POST \
|
|
20
|
-
# -f description='
|
|
20
|
+
# -f description='yad gate sync' -f ref=main -f cron='*/15 * * * *'
|
|
21
21
|
# glab api "projects/:id/pipeline_schedules/<id>/variables" -X POST \
|
|
22
22
|
# -f key=SDLC_GATE_SYNC -f value=true
|
|
23
23
|
#
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
# read the approvals API nor push to a protected branch. Create a PROJECT ACCESS TOKEN with
|
|
26
26
|
# `read_api` + `write_repository` (role Developer+, allowed to push to the default branch) and
|
|
27
27
|
# store it as a masked CI/CD variable SDLC_GATE_TOKEN. Without it the job fails visibly and
|
|
28
|
-
# manual `
|
|
28
|
+
# manual `yad gate sync` remains the fallback.
|
|
29
29
|
variables:
|
|
30
30
|
GIT_DEPTH: "0" # full history: gate ci fetches the review branch and pushes the ledger
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
yad-gate-sync:
|
|
33
33
|
needs: []
|
|
34
34
|
image: node:20
|
|
35
35
|
rules:
|
|
@@ -47,7 +47,7 @@ sdlc-gate-sync:
|
|
|
47
47
|
# The ledger lives on the default branch; gate ci overlays the artifact from the review branch itself.
|
|
48
48
|
- git fetch origin "$CI_DEFAULT_BRANCH"
|
|
49
49
|
- git checkout -B "$CI_DEFAULT_BRANCH" "origin/$CI_DEFAULT_BRANCH"
|
|
50
|
-
- git config user.name "
|
|
50
|
+
- git config user.name "yad-gate-sync" && git config user.email "yad-gate-sync@noreply.${CI_SERVER_HOST}"
|
|
51
51
|
- git remote set-url origin "https://oauth2:${SDLC_GATE_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
|
|
52
52
|
- export GITLAB_TOKEN="$SDLC_GATE_TOKEN" GITLAB_HOST="$CI_SERVER_URL"
|
|
53
53
|
- |
|
|
@@ -56,9 +56,9 @@ sdlc-gate-sync:
|
|
|
56
56
|
# catch-all (squash/FF merges whose message omits the branch land there).
|
|
57
57
|
REVIEW_BRANCH="$(printf '%s' "$CI_COMMIT_MESSAGE" | grep -oE 'review/EP-[A-Za-z0-9._/-]+' | head -n1 || true)"
|
|
58
58
|
if [ -n "$CI_MERGE_REQUEST_IID" ]; then
|
|
59
|
-
npx -y -p yadflow@
|
|
59
|
+
npx -y -p yadflow@2 yad gate ci --branch "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" --pr "$CI_MERGE_REQUEST_IID"
|
|
60
60
|
elif [ -n "$REVIEW_BRANCH" ]; then
|
|
61
|
-
npx -y -p yadflow@
|
|
61
|
+
npx -y -p yadflow@2 yad gate ci --branch "$REVIEW_BRANCH"
|
|
62
62
|
else
|
|
63
|
-
npx -y -p yadflow@
|
|
63
|
+
npx -y -p yadflow@2 yad gate ci
|
|
64
64
|
fi
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: 'Build-half 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 (
|
|
2
|
+
name: yad-implement
|
|
3
|
+
description: 'Build-half 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.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Implement Task (build-half Step B)
|
|
7
7
|
|
|
8
|
-
**Goal:** Turn ONE atomic task from a story's `tasks.md` (produced by Step A `
|
|
8
|
+
**Goal:** Turn ONE atomic task from a story's `tasks.md` (produced by Step A `yad-spec`) into a small,
|
|
9
9
|
reviewable diff on its own branch in the code repo. **One atomic task = one branch = one PR/MR**
|
|
10
10
|
(build plan §B). This is the **light per-task loop**: it runs once per task; the heavy spec ceremony
|
|
11
11
|
already ran once for the story.
|
|
12
12
|
|
|
13
13
|
This step **never auto-advances**. When the task is implemented and committed, control passes to the
|
|
14
|
-
**check gates** (Step C — `
|
|
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
17
|
The implementing lens is **`dev`** (`bmad-agent-dev`, Amelia). The dev writes only what the task
|
|
@@ -45,7 +45,7 @@ declares; it does not redesign, does not widen the contract, and does not pick u
|
|
|
45
45
|
Read `demo-repos/<repo>/specs/<story>/tasks.md`. Find the block for `<task>` (`## <task> — …`). Read
|
|
46
46
|
its one-line goal and its **Files:** list (the declared file boundary) and the acceptance criterion it
|
|
47
47
|
satisfies. If the task ID is not in `tasks.md`, STOP. Confirm the spec exists (Step A ran); if not,
|
|
48
|
-
STOP and point at `
|
|
48
|
+
STOP and point at `yad-spec`.
|
|
49
49
|
|
|
50
50
|
### Step 2 — Resolve the code repo and branch
|
|
51
51
|
Confirm `demo-repos/<repo>/` is its own git repo (`.git` present). From its default branch, create the
|
|
@@ -72,11 +72,11 @@ demonstrably met (record the result in the Step 7 report).
|
|
|
72
72
|
|
|
73
73
|
**File-boundary rule (hard):** if the implementation genuinely needs a file **not** in the declared
|
|
74
74
|
list, **flag and STOP** — do not silently widen the diff. Report the extra file(s) needed so the
|
|
75
|
-
task's spec can be corrected (re-run `
|
|
75
|
+
task's spec can be corrected (re-run `yad-spec` / re-scope the task) before implementing. A task whose
|
|
76
76
|
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
|
-
dial. When this step is driven by the orchestrator (`
|
|
79
|
+
dial. When this step is driven by the orchestrator (`yad-run`, Phase 4), the stop must be legible to
|
|
80
80
|
it: mark the `implement` step `status: blocked` in `build-state/<story>.json` and surface
|
|
81
81
|
`scope_overrun: true` so the run records a `rejected` trust entry and halts (it never advances past a
|
|
82
82
|
boundary breach). The same applies to the Step 5 contract-surface stop (`contract_touch: true`).
|
|
@@ -102,12 +102,12 @@ trailers in one contiguous block. Do not commit sibling tasks' work.
|
|
|
102
102
|
|
|
103
103
|
### Step 7 — Report; the advance decision belongs to the dial (Phase 4)
|
|
104
104
|
Report: the branch name, the files changed, how the change satisfies the task's acceptance criterion,
|
|
105
|
-
the result of any test/smoke run, and the next action — the **check gates** (Step C — `
|
|
105
|
+
the result of any test/smoke run, and the next action — the **check gates** (Step C — `yad-checks`)
|
|
106
106
|
then the PR and review (Steps D–E). Do **not** open a PR, merge, or hand-edit the epic's front-half
|
|
107
107
|
`state.json`. Step B ends at a committed task branch.
|
|
108
108
|
|
|
109
109
|
- **Run standalone:** stop here; a human triggers the gates.
|
|
110
|
-
- **Run by the orchestrator** (`
|
|
110
|
+
- **Run by the orchestrator** (`yad-run`): this skill still just produces the committed branch and
|
|
111
111
|
signals success (or a scope/contract halt). The orchestrator records the `implement` step's status
|
|
112
112
|
and trust entry and, when `implement` is earned to `machine_advance` (Step D, Phase 4b), **auto-runs
|
|
113
113
|
the check gates** instead of waiting for a manual nudge. The diff still cannot merge without the
|
|
@@ -115,16 +115,16 @@ then the PR and review (Steps D–E). Do **not** open a PR, merge, or hand-edit
|
|
|
115
115
|
|
|
116
116
|
### Step 8 — Record the `tasks` trust signal on first consume (Phase 4b)
|
|
117
117
|
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 `
|
|
118
|
+
the evidence that could later earn the `tasks` step a `machine_advance`. When driven by `yad-run`,
|
|
119
119
|
finalize a `tasks` trust entry, anchored to what the human/dev actually did with the list:
|
|
120
120
|
- the task is implemented with its declared `Files:`/scope **as generated** → `approved-unchanged`;
|
|
121
121
|
- the task is **re-scoped** first (its `Files:`/boundary edited) → `approved-with-edits`
|
|
122
122
|
(signal `task_rescoped: true`);
|
|
123
123
|
- the task list is discarded / regenerated → `rejected`.
|
|
124
124
|
Append the entry to `epics/<epic>/.sdlc/trust-log.json` (schema:
|
|
125
|
-
`../
|
|
125
|
+
`../yad-epic/references/state-schema.md`). `tasks` stays `human_approve` until its slice clears
|
|
126
126
|
the threshold — this only *gathers* evidence. (The `implement` step's own verdict is finalized later,
|
|
127
|
-
at the engineer review in `
|
|
127
|
+
at the engineer review in `yad-ship`: merged as authored → `approved-unchanged`; edited first →
|
|
128
128
|
`approved-with-edits`; scope/contract/checks halt → `rejected`.)
|
|
129
129
|
|
|
130
130
|
## Hard rules (build plan §B, Cross-cutting)
|
|
@@ -139,5 +139,5 @@ at the engineer review in `sdlc-ship`: merged as authored → `approved-unchange
|
|
|
139
139
|
|
|
140
140
|
## Reference
|
|
141
141
|
- Branch/commit conventions, the file-boundary rule, the Contract-Change rule: `references/implement-conventions.md`.
|
|
142
|
-
- The task list this step consumes: Step A's `references/spec-handoff.md` (`../
|
|
143
|
-
- Contract surface + hash recipe: `../
|
|
142
|
+
- The task list this step consumes: Step A's `references/spec-handoff.md` (`../yad-spec/...`).
|
|
143
|
+
- Contract surface + hash recipe: `../yad-architecture/references/contract-format.md`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Implement conventions — branch, commit, file boundary, contract change
|
|
2
2
|
|
|
3
|
-
Step B (`
|
|
3
|
+
Step B (`yad-implement`) turns ONE atomic task into ONE branch and ONE commit in the code repo. These
|
|
4
4
|
conventions are what the later steps (check gates §C, PR template §D, review §E) rely on to trace a
|
|
5
5
|
diff back to its task, story, and contract.
|
|
6
6
|
|
|
@@ -59,10 +59,10 @@ Co-Authored-By: CodeRabbit <noreply@coderabbit.ai>
|
|
|
59
59
|
|
|
60
60
|
- Choose the entry whose `id` matches the tool that actually helped author the diff; add more than one
|
|
61
61
|
line if several did. CodeRabbit is a co-author only when it **contributed code**, not when it merely
|
|
62
|
-
reviewed (that is `ai_review` in `
|
|
62
|
+
reviewed (that is `ai_review` in `yad-ship`).
|
|
63
63
|
- For a fully human-authored commit, pick `id: none` — i.e. **omit** the trailer. `ai_coauthor.required`
|
|
64
64
|
is `false`, so a missing trailer is valid and no gate fails on it.
|
|
65
|
-
- `
|
|
65
|
+
- `yad-implement` installs the `.gitmessage` template (`templates/.gitmessage`) and sets
|
|
66
66
|
`git config commit.template .gitmessage` in the repo, so these lines are pre-scaffolded (commented) for
|
|
67
67
|
the owner to uncomment.
|
|
68
68
|
|
|
@@ -74,7 +74,7 @@ Each task in `tasks.md` declares a `Files:` list (≤3 where possible). The impl
|
|
|
74
74
|
1. **Stop.** Do not widen the diff silently.
|
|
75
75
|
2. Report the extra file(s) needed.
|
|
76
76
|
3. Treat it as a **spec bug**: the task's declared files were wrong. Correct the task (re-run
|
|
77
|
-
`
|
|
77
|
+
`yad-spec` / re-scope) so the boundary is right, then implement.
|
|
78
78
|
|
|
79
79
|
A diff that quietly spreads beyond the declared files is the single easiest way to smuggle unreviewed
|
|
80
80
|
scope past the gates — hence the hard stop.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: 'Build-half 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
|
|
2
|
+
name: yad-pr-template
|
|
3
|
+
description: 'Build-half 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.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — PR/MR Template (build-half Step D)
|
|
@@ -8,7 +8,7 @@ description: 'Build-half Step D of the gated SDLC. Detect a code repo''s platfor
|
|
|
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
10
|
contract/auth/payments surface) **routes the review to domain owners** — the same escalation
|
|
11
|
-
`
|
|
11
|
+
`yad-review-gate` applies on the front-half gates (owner + 1 reviewer, plus one domain-owner per
|
|
12
12
|
touched domain). This step **never auto-advances**; it sets up the template and the routing helper.
|
|
13
13
|
|
|
14
14
|
## Conventions
|
|
@@ -25,10 +25,10 @@ touched domain). This step **never auto-advances**; it sets up the template and
|
|
|
25
25
|
`templates/hub/github/pull_request_template.md` → `{project-root}/.github/pull_request_template.md`;
|
|
26
26
|
`templates/hub/gitlab/merge_request_templates/Default.md` →
|
|
27
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 `
|
|
28
|
+
(hub PRs change artifacts, not code); its routing helper is `yad-hub-bridge`'s `hub-route.sh`.
|
|
29
29
|
- The Impact & Risk block reuses the conventions of earlier steps: the `Task: <story>-<task>` trailer
|
|
30
|
-
(`
|
|
31
|
-
domain-owner escalation (`
|
|
30
|
+
(`yad-implement`), the contract surface (`yad-architecture` / contract-check), and the
|
|
31
|
+
domain-owner escalation (`yad-review-gate`).
|
|
32
32
|
- **PR/MR title.** One atomic task = one branch = one PR/MR, so the title **defaults to that task's
|
|
33
33
|
commit subject** and follows the same Conventional Commits style — `<type>: <lowercase imperative
|
|
34
34
|
description, no trailing period>`, proper nouns/acronyms keep their case (`config.yaml`
|
|
@@ -56,7 +56,7 @@ Copy from this skill's `templates/`:
|
|
|
56
56
|
- GitLab → `templates/gitlab/merge_request_templates/Default.md` to
|
|
57
57
|
`<repo>/.gitlab/merge_request_templates/Default.md`.
|
|
58
58
|
- **`repo: hub`** → use the `templates/hub/<platform>/…` variants, installed into `{project-root}`'s own
|
|
59
|
-
`.github/`/`.gitlab/`. The hub's routing helper (`hub-route.sh`) is installed by `
|
|
59
|
+
`.github/`/`.gitlab/`. The hub's routing helper (`hub-route.sh`) is installed by `yad-hub-bridge`.
|
|
60
60
|
Drop **only the matching** template (drop both only if the repo genuinely uses both). For code repos also
|
|
61
61
|
install `templates/checks/risk-route.sh` to `<repo>/checks/` (`chmod +x`). If the target already has a
|
|
62
62
|
non-SDLC PR/MR template, do not clobber it — back it up / ask. Commit the template on the repo's default
|
|
@@ -67,8 +67,8 @@ Run `bash checks/risk-route.sh <body>` to parse the PR description's Impact & Ri
|
|
|
67
67
|
required reviewers:
|
|
68
68
|
- **low | medium** risk → base rule: owner + 1 reviewer.
|
|
69
69
|
- **high** risk (or a contract/auth/payments surface touched) → base rule **plus** one domain-owner
|
|
70
|
-
approval per touched domain — identical to `
|
|
71
|
-
recorded by the engineer review (Step E), via `
|
|
70
|
+
approval per touched domain — identical to `yad-review-gate`'s escalation. The actual approvals are
|
|
71
|
+
recorded by the engineer review (Step E), via `yad-review-gate`.
|
|
72
72
|
|
|
73
73
|
### Step 4 — Stop (no auto-advance)
|
|
74
74
|
Report what was committed (or the routing result). The template and routing are advisory inputs to the
|
|
@@ -82,5 +82,5 @@ human review (Step E); they do not approve or merge. Do not touch the epic's `.s
|
|
|
82
82
|
|
|
83
83
|
## Reference
|
|
84
84
|
- The Impact & Risk block, the risk levels, and the routing rule: `references/risk-routing.md`.
|
|
85
|
-
- The escalation this reuses: `../
|
|
86
|
-
- The check gates the checklist references: `../
|
|
85
|
+
- The escalation this reuses: `../yad-review-gate/SKILL.md` and its `references/gating.md`.
|
|
86
|
+
- The check gates the checklist references: `../yad-checks/references/check-gates.md`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The PR/MR template (Phase 3 build plan §D) carries an **Impact & Risk** block so every change states
|
|
4
4
|
its blast radius before review, and so high-risk changes pull in the right reviewers automatically —
|
|
5
|
-
reusing the escalation `
|
|
5
|
+
reusing the escalation `yad-review-gate` already applies on the front-half gates.
|
|
6
6
|
|
|
7
7
|
## The Impact & Risk block
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ reusing the escalation `sdlc-review-gate` already applies on the front-half gate
|
|
|
18
18
|
when the change escalates.
|
|
19
19
|
- **Contract surface touched** — `yes` means the diff changes the shared contract surface. That path is
|
|
20
20
|
governed by `contract-check` (needs `Contract-Change: yes` + a re-locked contract) AND it escalates
|
|
21
|
-
the review (contract is a `
|
|
21
|
+
the review (contract is a `yad-review-gate` risk tag).
|
|
22
22
|
- **Risk level** — `low | medium | high`. The author's assessment of blast radius.
|
|
23
23
|
- **Rollback plan** — how to revert safely.
|
|
24
24
|
|
|
@@ -29,10 +29,10 @@ reusing the escalation `sdlc-review-gate` already applies on the front-half gate
|
|
|
29
29
|
| `low` / `medium`, no sensitive surface | **base rule:** owner + 1 reviewer |
|
|
30
30
|
| `high`, OR a touched contract/auth/payments surface | base rule **plus one domain-owner approval per touched domain** |
|
|
31
31
|
|
|
32
|
-
This is exactly `
|
|
32
|
+
This is exactly `yad-review-gate`'s rule (`references/gating.md`): the base rule is owner + 1
|
|
33
33
|
reviewer; escalation adds a domain-owner per touched domain. The PR template applies the same logic at
|
|
34
34
|
the code-review boundary so a risky PR cannot be approved by just any two people. The **approvals are
|
|
35
|
-
recorded by the engineer review (Step E) through `
|
|
35
|
+
recorded by the engineer review (Step E) through `yad-review-gate`** — the template and `risk-route.sh`
|
|
36
36
|
only *route* (advisory); they never approve or merge.
|
|
37
37
|
|
|
38
38
|
## risk-route.sh
|
|
@@ -45,7 +45,7 @@ Risk level: high
|
|
|
45
45
|
Contract surface touched: no
|
|
46
46
|
Domains touched: backend, mobile
|
|
47
47
|
ROUTE: ESCALATED (risk: high) -> owner + 1 reviewer PLUS one domain-owner approval per touched domain
|
|
48
|
-
(same escalation as
|
|
48
|
+
(same escalation as yad-review-gate). Required domain owners:
|
|
49
49
|
- domain-owner: backend
|
|
50
50
|
- domain-owner: mobile
|
|
51
51
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Risk routing (Phase 3 build plan §D). Reads a PR/MR description's Impact & Risk block and prints the
|
|
3
|
-
# required reviewers, reusing
|
|
3
|
+
# required reviewers, reusing yad-review-gate's escalation: a `high` risk level — or a touched
|
|
4
4
|
# contract/auth/payments surface — requires a domain-owner approval per touched domain, on top of the
|
|
5
5
|
# base rule (owner + 1 reviewer). Advisory: it ROUTES the human review; it does not approve or merge.
|
|
6
6
|
set -euo pipefail
|
|
@@ -29,7 +29,7 @@ if [ "$risk" = "high" ] || [ "$contract" = "yes" ]; then
|
|
|
29
29
|
[ "$risk" = "high" ] && why="risk: high"
|
|
30
30
|
[ "$contract" = "yes" ] && why="${why:+$why, }contract surface touched"
|
|
31
31
|
echo "ROUTE: ESCALATED (${why}) -> owner + 1 reviewer PLUS one domain-owner approval per touched domain"
|
|
32
|
-
echo " (same escalation as
|
|
32
|
+
echo " (same escalation as yad-review-gate). Required domain owners:"
|
|
33
33
|
case "$domains" in
|
|
34
34
|
""|*"<"*|*"…"*|*"|"*)
|
|
35
35
|
echo " (Domains line not filled in — list each touched domain to route the owners.)" ;;
|
package/skills/{sdlc-pr-template → yad-pr-template}/templates/github/pull_request_template.md
RENAMED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
> **Routing:** `low`/`medium` → base rule (owner + 1 reviewer). `high` (or a touched
|
|
19
19
|
> contract/auth/payments surface) → **plus one domain-owner approval per touched domain**, the same
|
|
20
|
-
> escalation `
|
|
20
|
+
> escalation `yad-review-gate` applies. Run `bash checks/risk-route.sh <this-description>` to list them.
|
|
21
21
|
|
|
22
22
|
## Testing
|
|
23
23
|
<!-- How the acceptance criteria were exercised. Tests must exercise behavior, not just pass. -->
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
> **Routing:** `low`/`medium` → base rule (owner + 1 reviewer). `high` (or a touched
|
|
19
19
|
> contract/auth/payments surface) → **plus one domain-owner approval per touched domain**, the same
|
|
20
|
-
> escalation `
|
|
20
|
+
> escalation `yad-review-gate` applies. Run `bash checks/risk-route.sh <this-description>` to list them.
|
|
21
21
|
|
|
22
22
|
## Testing
|
|
23
23
|
<!-- How the acceptance criteria were exercised. Tests must exercise behavior, not just pass. -->
|