yadflow 1.4.0 → 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 +20 -2
- package/README.md +135 -131
- 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 +7 -4
- 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 +2 -2
- 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
|
@@ -8,10 +8,10 @@ repo uses. Each reads conventions established by earlier steps — it invents no
|
|
|
8
8
|
|
|
9
9
|
| Gate | Reads | Source step |
|
|
10
10
|
|------|-------|-------------|
|
|
11
|
-
| spec-link | the `Task: <story>-<task>` commit trailer; `specs/<story>/link.md` | `
|
|
12
|
-
| contract-check | changed files under `specs/<story>/contracts/`; the `Contract-Change: yes` trailer; `link.md`'s pinned `contract-lock`; the product repo's `contract-lock.json` | `
|
|
11
|
+
| spec-link | the `Task: <story>-<task>` commit trailer; `specs/<story>/link.md` | `yad-implement` (trailer), `yad-spec` (link.md) |
|
|
12
|
+
| contract-check | changed files under `specs/<story>/contracts/`; the `Contract-Change: yes` trailer; `link.md`'s pinned `contract-lock`; the product repo's `contract-lock.json` | `yad-architecture` (lock), `yad-spec` (slice + link), `yad-implement` (trailer) |
|
|
13
13
|
| build/test/lint | the repo's `npm run lint` / `npm run build` / `npm test` | the repo |
|
|
14
|
-
| verified-commits | each commit's platform signature-verification status; the author email vs `.sdlc/verified-authors` | hub roster `email` fields (`
|
|
14
|
+
| verified-commits | each commit's platform signature-verification status; the author email vs `.sdlc/verified-authors` | hub roster `email` fields (`yad check --fix` generates the allowlist) |
|
|
15
15
|
|
|
16
16
|
## 1. spec-link (`templates/checks/spec-link.sh`)
|
|
17
17
|
|
|
@@ -34,9 +34,9 @@ repo uses. Each reads conventions established by earlier steps — it invents no
|
|
|
34
34
|
- Best-effort fidelity: when the product repo is reachable (via `link.md`'s `product-repo` path),
|
|
35
35
|
require `link.md`'s pinned `contract-lock` hash to match the product repo's current
|
|
36
36
|
`contract-lock.json`. A claimed change that still pins the **old** lock **FAILS** — re-run
|
|
37
|
-
`
|
|
37
|
+
`yad-spec` so the slice matches the re-locked contract.
|
|
38
38
|
- This enforces the Phase 2 rule: the shared surface is owned upstream and is never widened from inside
|
|
39
|
-
a code repo. The hash recipe is in `../
|
|
39
|
+
a code repo. The hash recipe is in `../yad-architecture/references/contract-format.md`.
|
|
40
40
|
|
|
41
41
|
## 3. build/test/lint (`templates/checks/build-test-lint.sh`)
|
|
42
42
|
|
|
@@ -68,7 +68,7 @@ repo. For each commit in `<base>..HEAD`, two independent checks:
|
|
|
68
68
|
"Verified" badge: signed with a GPG/SSH key registered to the account owning the author email).
|
|
69
69
|
Read via `gh api repos/{owner}/{repo}/commits/<sha>` (GitHub) or the commits/signature API (GitLab).
|
|
70
70
|
- **Known author** — the commit's **author email** must appear in `.sdlc/verified-authors`, generated
|
|
71
|
-
by `
|
|
71
|
+
by `yad check --fix` from the hub roster's `email`/`emails` fields plus hub.json's
|
|
72
72
|
`verified_authors` list (edit hub.json, never the generated file). Only the author is checked:
|
|
73
73
|
platform-generated merge/squash commits set the platform as committer, and their integrity is
|
|
74
74
|
covered by the signature check.
|
|
@@ -80,7 +80,7 @@ closed** with guidance. GitLab CI needs a `GITLAB_TOKEN`/`SDLC_API_TOKEN` variab
|
|
|
80
80
|
`CI_JOB_TOKEN` cannot read the signature API.
|
|
81
81
|
|
|
82
82
|
Note the deliberate split with the gate-sync bot: this gate runs on **PRs/MRs only**, so the
|
|
83
|
-
`
|
|
83
|
+
`yad-gate-sync` ledger commits (pushed directly to the default branch, unsigned, bot-authored) are
|
|
84
84
|
not subject to it. Do **not** replace it with a platform-level "reject unsigned pushes" rule on the
|
|
85
85
|
default branch — that would break the event-driven gate sync (and GitLab push rules are Premium-only).
|
|
86
86
|
|
|
@@ -88,10 +88,10 @@ default branch — that would break the event-driven gate sync (and GitLab push
|
|
|
88
88
|
|
|
89
89
|
The gates run identically under either CI; the config just invokes the scripts with the PR/MR base.
|
|
90
90
|
|
|
91
|
-
- **GitHub Actions** — `templates/github/
|
|
91
|
+
- **GitHub Actions** — `templates/github/yad-checks.yml` → `.github/workflows/yad-checks.yml`. The
|
|
92
92
|
jobs run on `pull_request` with `fetch-depth: 0`, passing `origin/${{ github.base_ref }}` as base
|
|
93
93
|
(verified-commits also gets a read-only `GH_TOKEN` for the Verified-badge lookup).
|
|
94
|
-
- **GitLab CI** — `templates/gitlab/
|
|
94
|
+
- **GitLab CI** — `templates/gitlab/yad-checks.gitlab-ci.yml` → `.gitlab/ci/yad-checks.yml`, pulled in
|
|
95
95
|
by the root `.gitlab-ci.yml`'s `include:`. The jobs run on `merge_request_event` with `GIT_DEPTH: 0`,
|
|
96
96
|
passing `origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME`.
|
|
97
97
|
|
|
@@ -102,20 +102,20 @@ editing a foreign CI file. The principle is "own a separate file; touch the fore
|
|
|
102
102
|
one-line include".
|
|
103
103
|
|
|
104
104
|
**GitHub.** Every workflow file runs independently, so the gates simply live in their own
|
|
105
|
-
`
|
|
105
|
+
`yad-checks.yml`, identified by the first-line marker `# yad-managed: yad-checks`.
|
|
106
106
|
- No file at our path → copy the template verbatim.
|
|
107
107
|
- Our marked file already there → refresh it (no-op if identical).
|
|
108
|
-
- A **foreign** workflow occupies the name → install as `
|
|
108
|
+
- A **foreign** workflow occupies the name → install as `yad-checks.gen.yml` instead and make the
|
|
109
109
|
display `name:` unique. We never merge jobs into, or edit, a foreign workflow.
|
|
110
110
|
|
|
111
111
|
**GitLab.** Only one root `.gitlab-ci.yml` may exist, so the gates live in an **includable** fragment
|
|
112
|
-
`.gitlab/ci/
|
|
112
|
+
`.gitlab/ci/yad-checks.yml` (marker `# yad-managed-include: yad-checks`). Its jobs declare `needs: []`
|
|
113
113
|
and **no `stage:`**, so they run in the default stage and a foreign root's `stages:` list can neither
|
|
114
|
-
break nor reorder them; job names are `
|
|
114
|
+
break nor reorder them; job names are `yad-`prefixed to avoid collisions.
|
|
115
115
|
- No root `.gitlab-ci.yml` → write a minimal root (`gitlab-ci.include-root.yml`) that only `include:`s
|
|
116
116
|
the fragment.
|
|
117
117
|
- Root exists → read its top-level `include:`; add the key if absent, append
|
|
118
|
-
`- local: '.gitlab/ci/
|
|
118
|
+
`- local: '.gitlab/ci/yad-checks.yml'` if missing, no-op if already present. **Nothing else** in the
|
|
119
119
|
root is touched.
|
|
120
120
|
- Root YAML cannot be parsed safely → **STOP** and print the include snippet for the human to paste.
|
|
121
121
|
|
|
@@ -127,24 +127,24 @@ that already had its own pipeline keeps it and still gains the gates.
|
|
|
127
127
|
## Wiring the hub (`repo: hub`)
|
|
128
128
|
|
|
129
129
|
The product hub is itself a repo on a platform (recorded in `.sdlc/hub.json` by
|
|
130
|
-
`
|
|
130
|
+
`yad-connect-repos action: detect-hub`). `wire repo: hub` targets `{project-root}` and uses the same
|
|
131
131
|
merge-not-clobber logic, with a **hub-flavored gate set** appropriate to a "thinking" repo (it has no
|
|
132
132
|
`specs/` or `package.json` build):
|
|
133
133
|
- **owner-set** — every `epic.md` (and forward artifact) under `epics/EP-*/` carries an `owner`.
|
|
134
134
|
- **contract-locked** — where an epic has a `contract.md`, its surface hash matches
|
|
135
135
|
`.sdlc/contract-lock.json` (reuse the recipe in
|
|
136
|
-
`../
|
|
136
|
+
`../yad-architecture/references/contract-format.md`).
|
|
137
137
|
- **approvals-present** — an epic at `ready-for-build` has the approvals its gate rule requires recorded
|
|
138
|
-
in `.sdlc/approvals.json` (the same predicate `
|
|
138
|
+
in `.sdlc/approvals.json` (the same predicate `yad-review-gate` enforces).
|
|
139
139
|
|
|
140
140
|
These are advisory checks on the hub's own PRs (the front-half review PRs the bridge opens); they keep
|
|
141
141
|
the hub's artifacts internally consistent. The hub never runs the code-repo `spec-link`/`build-test-lint`
|
|
142
142
|
gates. Author the hub gate scripts under the hub's `checks/` following the same CI-agnostic-bash pattern.
|
|
143
143
|
|
|
144
|
-
The hub **does** run the verified-commits gate — `
|
|
145
|
-
plus a standalone workflow (`templates/github/
|
|
146
|
-
`.github/workflows/
|
|
147
|
-
`templates/gitlab/
|
|
144
|
+
The hub **does** run the verified-commits gate — `yad check --fix` installs `checks/verified-commits.sh`
|
|
145
|
+
plus a standalone workflow (`templates/github/yad-verified-commits.yml` →
|
|
146
|
+
`.github/workflows/yad-verified-commits.yml`, or the GitLab fragment
|
|
147
|
+
`templates/gitlab/yad-verified-commits.gitlab-ci.yml` → `.gitlab/ci/yad-verified-commits.yml` +
|
|
148
148
|
its one include line) whenever `.sdlc/hub.json` has a platform with the bridge enabled. So the
|
|
149
149
|
front-half review PRs are held to the same rule as code-repo PRs: signed, known authors only.
|
|
150
150
|
|
|
@@ -33,7 +33,7 @@ cc="$(git log "$RANGE" --format='%(trailers:key=Contract-Change,valueonly)' | se
|
|
|
33
33
|
if ! printf '%s\n' "$cc" | grep -qx 'yes'; then
|
|
34
34
|
echo "FAIL [contract-check]: contract surface changed without a 'Contract-Change: yes' trailer."
|
|
35
35
|
echo " -> Route back to the architecture gate: update + re-lock contract.md in the product repo,"
|
|
36
|
-
echo " re-run
|
|
36
|
+
echo " re-run yad-spec, then implement with Contract-Change: yes. The surface is never widened"
|
|
37
37
|
echo " from inside a code repo."
|
|
38
38
|
exit 1
|
|
39
39
|
fi
|
|
@@ -51,7 +51,7 @@ if [ -f "$link" ]; then
|
|
|
51
51
|
current="$(sed -nE 's/.*"hash":[[:space:]]*"sha256:([0-9a-f]+)".*/\1/p' "$lock" | head -1)"
|
|
52
52
|
if [ -n "$current" ] && [ "$current" != "$pinned" ]; then
|
|
53
53
|
echo "FAIL [contract-check]: Contract-Change claimed, but ${link} still pins ${pinned:0:12}…"
|
|
54
|
-
echo " while the product lock is ${current:0:12}… — re-run
|
|
54
|
+
echo " while the product lock is ${current:0:12}… — re-run yad-spec so the slice matches the re-locked contract."
|
|
55
55
|
exit 1
|
|
56
56
|
fi
|
|
57
57
|
echo "note [contract-check]: link.md hash matches the product lock (${current:0:12}…)."
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Every commit in the range under review must (1) carry a signature the PLATFORM marks as verified
|
|
4
4
|
# (the GitHub/GitLab "Verified" badge — proves the commit was signed by a key registered to the
|
|
5
5
|
# account that owns the author email) and (2) be AUTHORED by a known identity: the author email must
|
|
6
|
-
# appear in the .sdlc/verified-authors allowlist (generated by `
|
|
6
|
+
# appear in the .sdlc/verified-authors allowlist (generated by `yad check --fix` from the hub
|
|
7
7
|
# roster's `email` fields + hub.json `verified_authors`). Unsigned commits and commits from unknown
|
|
8
8
|
# authors do not reach merge — on the product hub and on every connected repo alike.
|
|
9
9
|
#
|
|
@@ -41,7 +41,7 @@ authors_on=0
|
|
|
41
41
|
if [ -f "$ALLOWLIST" ]; then
|
|
42
42
|
authors_on=1
|
|
43
43
|
else
|
|
44
|
-
echo "WARN [verified-commits]: ${ALLOWLIST} not found — author allowlist NOT enforced. Add 'email' to the hub roster (or hub.json 'verified_authors'), then run \`
|
|
44
|
+
echo "WARN [verified-commits]: ${ALLOWLIST} not found — author allowlist NOT enforced. Add 'email' to the hub roster (or hub.json 'verified_authors'), then run \`yad check --fix\`."
|
|
45
45
|
fi
|
|
46
46
|
|
|
47
47
|
# ---- platform for the signature check (override with SDLC_PLATFORM=github|gitlab|none) -----------
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yad-managed: yad-checks
|
|
2
2
|
# SDLC check gates (Phase 3 build plan §C). The three gates run on every PR and must pass before
|
|
3
3
|
# merge. They are CI-agnostic bash in checks/ — this workflow just invokes them with the PR base.
|
|
4
|
-
# This workflow file is OWNED by
|
|
4
|
+
# This workflow file is OWNED by yad-checks (the marker on line 1 identifies it). It runs
|
|
5
5
|
# independently of any other workflow in .github/workflows/, so wiring never edits a foreign workflow.
|
|
6
|
-
name:
|
|
6
|
+
name: yad-checks
|
|
7
7
|
on:
|
|
8
8
|
pull_request:
|
|
9
9
|
branches: ["**"]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yad-managed: yad-checks
|
|
2
2
|
# verified-commits gate for the PRODUCT HUB: every PR (including the front-half review/EP-* PRs)
|
|
3
3
|
# must contain only commits whose signature the platform marks Verified AND whose author email is a
|
|
4
|
-
# known identity (.sdlc/verified-authors — generated by `
|
|
5
|
-
# Standalone workflow so it never collides with the hub-flavored
|
|
6
|
-
name:
|
|
4
|
+
# known identity (.sdlc/verified-authors — generated by `yad check --fix` from the hub roster).
|
|
5
|
+
# Standalone workflow so it never collides with the hub-flavored yad-checks workflow.
|
|
6
|
+
name: yad-verified-commits
|
|
7
7
|
on:
|
|
8
8
|
pull_request:
|
|
9
9
|
branches: ["**"]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# SDLC check gates — minimal root pipeline.
|
|
2
|
-
# Written by `
|
|
2
|
+
# Written by `yad-checks wire` ONLY when the repo has no existing root `.gitlab-ci.yml`.
|
|
3
3
|
# The gates themselves live in the included fragment so the same single source is reused whether
|
|
4
4
|
# or not a root pipeline already exists. If a root later grows real jobs, they coexist with the
|
|
5
|
-
# included
|
|
5
|
+
# included yad-* jobs (which carry `needs: []` and no `stage:`).
|
|
6
6
|
include:
|
|
7
|
-
- local: '.gitlab/ci/
|
|
7
|
+
- local: '.gitlab/ci/yad-checks.yml'
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yad-managed-include: yad-checks
|
|
2
2
|
# SDLC check gates (Phase 3 build plan §C), as an INCLUDABLE fragment.
|
|
3
3
|
# This file is pulled into a repo's existing .gitlab-ci.yml via:
|
|
4
4
|
# include:
|
|
5
|
-
# - local: '.gitlab/ci/
|
|
5
|
+
# - local: '.gitlab/ci/yad-checks.yml'
|
|
6
6
|
# so wiring NEVER edits the foreign root pipeline beyond adding that one include line.
|
|
7
7
|
#
|
|
8
8
|
# Merge-safety: these jobs do NOT declare a `stage:` and use `needs: []`, so they run in the
|
|
9
9
|
# pipeline's default stage regardless of any `stages:` order the foreign root defines — a foreign
|
|
10
|
-
# `stages:` list can neither break them nor reorder them. Job names are
|
|
10
|
+
# `stages:` list can neither break them nor reorder them. Job names are yad-prefixed to avoid
|
|
11
11
|
# colliding with the host project's own job names.
|
|
12
12
|
default:
|
|
13
13
|
image: node:20
|
|
@@ -19,19 +19,19 @@ default:
|
|
|
19
19
|
variables:
|
|
20
20
|
GIT_DEPTH: "0" # full history so the gates can diff against the target branch
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
yad-spec-link:
|
|
23
23
|
extends: .sdlc_mr_only
|
|
24
24
|
needs: []
|
|
25
25
|
script:
|
|
26
26
|
- bash checks/spec-link.sh "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
yad-contract-check:
|
|
29
29
|
extends: .sdlc_mr_only
|
|
30
30
|
needs: []
|
|
31
31
|
script:
|
|
32
32
|
- bash checks/contract-check.sh "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
yad-build-test-lint:
|
|
35
35
|
extends: .sdlc_mr_only
|
|
36
36
|
needs: []
|
|
37
37
|
script:
|
|
@@ -40,7 +40,7 @@ sdlc-build-test-lint:
|
|
|
40
40
|
# No unverified commits from unverified users: platform-Verified signature + allowlisted author.
|
|
41
41
|
# Needs a CI/CD variable GITLAB_TOKEN (or SDLC_API_TOKEN) with read_api scope — CI_JOB_TOKEN cannot
|
|
42
42
|
# read the commit-signature API. Without it the job FAILS closed with guidance.
|
|
43
|
-
|
|
43
|
+
yad-verified-commits:
|
|
44
44
|
extends: .sdlc_mr_only
|
|
45
45
|
needs: []
|
|
46
46
|
script:
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# yad-managed-include: yad-checks
|
|
2
2
|
# verified-commits gate for the PRODUCT HUB, as an INCLUDABLE fragment. Pulled into the hub's root
|
|
3
3
|
# .gitlab-ci.yml via:
|
|
4
4
|
# include:
|
|
5
|
-
# - local: '.gitlab/ci/
|
|
5
|
+
# - local: '.gitlab/ci/yad-verified-commits.yml'
|
|
6
6
|
# Every MR (including the front-half review/EP-* MRs) must contain only commits whose signature the
|
|
7
7
|
# platform marks Verified AND whose author email is a known identity (.sdlc/verified-authors).
|
|
8
8
|
#
|
|
9
9
|
# Needs a CI/CD variable GITLAB_TOKEN (or SDLC_API_TOKEN) with read_api scope — CI_JOB_TOKEN cannot
|
|
10
10
|
# read the commit-signature API. The hub's SDLC_GATE_TOKEN (from the gate-sync wiring) also works:
|
|
11
11
|
# set GITLAB_TOKEN: $SDLC_GATE_TOKEN in the job if you prefer one token.
|
|
12
|
-
# Job name is
|
|
13
|
-
|
|
12
|
+
# Job name is yad-hub-prefixed so it can coexist with the code-repo fragment in one pipeline.
|
|
13
|
+
yad-hub-verified-commits:
|
|
14
14
|
needs: []
|
|
15
15
|
image: node:20
|
|
16
16
|
variables:
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: yad-connect-repos
|
|
3
3
|
description: 'Connects code repos to the product hub so the front/"brain" phases are code-aware. Registers N code repos (GitHub or GitLab, local-user auth, no stored tokens) into the project-wide .sdlc/repos.json, then caches an AI-readable picture of each — a compressed Repomix pack and a lightweight code-map (existing endpoints/events/data-models/modules), secret-scanned. Run at one-time setup or any time a new repo is added. Reusable, idempotent, refreshable; staleness is tracked by HEAD sha. Use when the user says "connect a repo", "connect the code repos", "refresh the code context", or "list connected repos".'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDLC — Connect Code Repos (make the brain code-aware)
|
|
7
7
|
|
|
8
|
-
**Goal:** Give the front/"brain" phases (`
|
|
8
|
+
**Goal:** Give the front/"brain" phases (`yad-epic` → `-architecture` → `-ui` → `-stories`)
|
|
9
9
|
full context about what **already exists** in the code, so the AI does not author a contract, UI, or
|
|
10
10
|
stories that contradict or duplicate what is built. This skill **connects** code repos to the product
|
|
11
11
|
hub and caches an AI-readable picture of each. It is the product → code half of the 2-way link (the
|
|
@@ -20,7 +20,7 @@ epic's approvals. It only writes the project-wide registry and the per-repo cont
|
|
|
20
20
|
- The **product repo is the front-phase toolchain hub** (`config.yaml` `code_context`): Repomix (and
|
|
21
21
|
Impeccable, later) are installed/run **here** and target the connected code repos **by path**. The
|
|
22
22
|
code repos themselves need no install for this. (The build-half CI gates are the exception — they
|
|
23
|
-
live inside each code repo; see `
|
|
23
|
+
live inside each code repo; see `yad-checks`.)
|
|
24
24
|
- **Repomix is a true CLI subprocess** (Phase 0 / RESEARCH-NOTES §3): `npx repomix@latest [flags]` —
|
|
25
25
|
NOT a slash-command. It secret-scans by default (Secretlint).
|
|
26
26
|
- Registry: `{project-root}/.sdlc/repos.json` (project-wide, shared across all epics — NOT per-epic).
|
|
@@ -114,7 +114,7 @@ the front phases will now load this repo's code-map. Nothing auto-advances; this
|
|
|
114
114
|
## Hub detection + reviewer roster (the front-half review bridge)
|
|
115
115
|
|
|
116
116
|
The hub is itself a git repo on a platform. These actions record that so the front-half review/comment/
|
|
117
|
-
approval cycle can run through a real PR/MR on the hub (`
|
|
117
|
+
approval cycle can run through a real PR/MR on the hub (`yad-review-gate` + `yad-hub-bridge`). They
|
|
118
118
|
write only `{project-root}/.sdlc/hub.json` (`config.yaml` `hub.config`) — never an epic's state/approvals.
|
|
119
119
|
|
|
120
120
|
- **`detect-hub`** — detect the hub's own platform and upsert `.sdlc/hub.json`. Run
|
|
@@ -137,7 +137,7 @@ re-run Repomix **live**, scoped to that area:
|
|
|
137
137
|
npx repomix@latest --compress --include "<area globs>" --style markdown -o -
|
|
138
138
|
```
|
|
139
139
|
Same CLI, invoked ad hoc — no registry write. A **stale repo** (HEAD ≠ `syncedHead`) is different: the
|
|
140
|
-
phase **flags it and stops**, pointing the human at `
|
|
140
|
+
phase **flags it and stops**, pointing the human at `yad repo refresh <repo>` (or `yad check --fix`) —
|
|
141
141
|
it does not silently re-pack. Refreshing the cache is a human decision. Documented in
|
|
142
142
|
`references/code-context.md`.
|
|
143
143
|
|
|
@@ -155,5 +155,5 @@ it does not silently re-pack. Refreshing the cache is a human decision. Document
|
|
|
155
155
|
- Hub config + reviewer roster (the review bridge): `references/hub-config.md`.
|
|
156
156
|
- Repomix command, secret-scan, degrade path, the code-map prompt, and live on-demand:
|
|
157
157
|
`references/code-context.md`.
|
|
158
|
-
- The repomix discipline this reuses (one-feature-at-a-time variant): `../
|
|
159
|
-
- Repos convention + per-repo review routing: `../
|
|
158
|
+
- The repomix discipline this reuses (one-feature-at-a-time variant): `../yad-backfill/references/backfill.md`.
|
|
159
|
+
- Repos convention + per-repo review routing: `../yad-stories/references/story-schema.md`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Code context — Repomix pack, the code-map prompt, and live on-demand
|
|
2
2
|
|
|
3
|
-
How `
|
|
4
|
-
phases can read. Three layers, same Repomix machinery as `
|
|
3
|
+
How `yad-connect-repos` turns a connected code repo into an AI-readable picture the front/"brain"
|
|
4
|
+
phases can read. Three layers, same Repomix machinery as `yad-backfill` (this is the repo-wide
|
|
5
5
|
variant; backfill is the one-feature-at-a-time variant).
|
|
6
6
|
|
|
7
7
|
## Layer 1 — the cached pack (full context)
|
|
@@ -78,15 +78,15 @@ npx repomix@latest --compress --include "<area globs>" --style markdown -o -
|
|
|
78
78
|
|
|
79
79
|
This is for a one-off look at a specific area. **Staleness is a human decision, not an automatic
|
|
80
80
|
side-effect:** when a repo is stale (HEAD ≠ `syncedHead`), the phase **flags it and stops** —
|
|
81
|
-
"`<repo>` is stale; run `
|
|
81
|
+
"`<repo>` is stale; run `yad repo refresh <repo>` to re-pack the cache + `syncedHead`" — rather than
|
|
82
82
|
silently re-packing the whole repo. A phase never refreshes the registry on its own; the human runs
|
|
83
|
-
`
|
|
83
|
+
`yad repo refresh` (or `yad check --fix`).
|
|
84
84
|
|
|
85
85
|
## Why this stays DRY with backfill
|
|
86
86
|
|
|
87
|
-
`
|
|
87
|
+
`yad-backfill` already documents the exact Repomix command, the Secretlint discipline, the
|
|
88
88
|
`repomix: unavailable` degrade, and the "describe what exists, do not invent" prompt
|
|
89
|
-
(`../
|
|
89
|
+
(`../yad-backfill/references/backfill.md`). This skill reuses all of it; the only differences are
|
|
90
90
|
**scope** (repo-wide index vs one feature) and **output** (a lightweight code-map for the brain vs a
|
|
91
91
|
human-approved feature spec). Backfill produces a *verified* spec that gates changes; connect produces a
|
|
92
92
|
*context* artifact that informs design — they are complementary.
|
|
@@ -9,7 +9,7 @@ login to an SDLC name + role. It is a single object for the hub itself — the s
|
|
|
9
9
|
|
|
10
10
|
`{project-root}/.sdlc/hub.json`
|
|
11
11
|
|
|
12
|
-
(`config.yaml` `hub.config`.) Created/updated by `
|
|
12
|
+
(`config.yaml` `hub.config`.) Created/updated by `yad-connect-repos action: detect-hub`.
|
|
13
13
|
|
|
14
14
|
## Schema
|
|
15
15
|
|
|
@@ -60,7 +60,7 @@ as the registry). `detect-hub` upserts `hub.json` in place — it is idempotent
|
|
|
60
60
|
## Bridge enable / degradation
|
|
61
61
|
|
|
62
62
|
- `bridge_enabled: true` **and** a non-null `platform` **and** `gh`/`glab` authenticated → the front-half
|
|
63
|
-
review opens a PR/MR on the hub and `
|
|
63
|
+
review opens a PR/MR on the hub and `yad-review-gate action: sync` pulls platform state into the ledger.
|
|
64
64
|
- `bridge_enabled: false`, `platform: null`, or no/unauthenticated CLI → the gate falls back to the
|
|
65
65
|
existing **file-only** flow with no error. The file ledger is the source of truth in both modes.
|
|
66
66
|
- The master switch `config.yaml` `hub.bridge: false` disables the bridge globally regardless of `hub.json`.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: yad-epic
|
|
3
3
|
description: 'Front state for the epic in the gated SDLC. Shape a feature idea with the analyst (or read analysis.md when the optional analysis step already ran), then write the epic with the pm, into epic.md. The entry point when analysis is skipped: assigns the EP-<slug> ID and seeds .sdlc/ state. Never auto-advances — hands off to the team review gate. Use when the user says "start a new feature/epic" or "author an epic".'
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -8,9 +8,9 @@ description: 'Front state for the epic in the gated SDLC. Shape a feature idea w
|
|
|
8
8
|
**Goal:** Produce a human-authored, AI-assisted `epic.md` for a new feature, and — when the epic is the
|
|
9
9
|
entry point — assign its stable `EP-<slug>` ID and initialise the per-epic state machine in `.sdlc/`.
|
|
10
10
|
This is a **front state**: human-authored with AI assist and **never auto-advances**. When the epic is
|
|
11
|
-
drafted, control passes to `
|
|
11
|
+
drafted, control passes to `yad-review-gate`.
|
|
12
12
|
|
|
13
|
-
**Two entry modes** (the optional `
|
|
13
|
+
**Two entry modes** (the optional `yad-analysis` step decides which):
|
|
14
14
|
- **Analysis ran** — `.sdlc/state.json` already exists with `currentStep == "epic"`. The epic **reads
|
|
15
15
|
`analysis.md`** as its shaped input and does not re-seed state.
|
|
16
16
|
- **Analysis skipped** (the default) — no `state.json` yet. The epic is the entry point: it shapes the
|
|
@@ -40,7 +40,7 @@ exists for the idea.
|
|
|
40
40
|
|
|
41
41
|
Either mode runs Step 3b (branch), Step 4 (write the epic), and Step 6 (stop at the gate).
|
|
42
42
|
|
|
43
|
-
If `state.json` exists but `currentStep != "epic"`, stop and point the user at `
|
|
43
|
+
If `state.json` exists but `currentStep != "epic"`, stop and point the user at `yad-status` / the gate.
|
|
44
44
|
|
|
45
45
|
### Step 2 — Shape the idea (assist: analyst) — or read the analysis
|
|
46
46
|
- **Analysis skipped:** ask the user for a one-line feature idea if not provided, then adopt the
|
|
@@ -59,14 +59,14 @@ and let it inform which `repos` the epic should touch.
|
|
|
59
59
|
- **Greenfield-safe:** if `repos.json` is absent or empty, note "no repos connected" and proceed — no
|
|
60
60
|
behaviour change for a project with no code yet.
|
|
61
61
|
- **Staleness:** if a repo's current HEAD (`git -C <path> rev-parse HEAD`) ≠ its registry `syncedHead`,
|
|
62
|
-
warn and suggest `
|
|
62
|
+
warn and suggest `yad repo refresh <repo>` (a human decision — flag and stop, never auto-refresh);
|
|
63
63
|
stamp `code-context: stale` in the frontmatter.
|
|
64
64
|
- **Traceability:** record which maps you loaded in the epic frontmatter `code-context:` field.
|
|
65
|
-
- For depth on a specific area not in the map, do a live on-demand read (see `
|
|
65
|
+
- For depth on a specific area not in the map, do a live on-demand read (see `yad-connect-repos`
|
|
66
66
|
`references/code-context.md`) — do not block on it.
|
|
67
67
|
|
|
68
68
|
### Step 3 — Generate the Epic ID (engine-assigned, never by hand) — analysis-skipped only
|
|
69
|
-
*(Skip when analysis ran — the ID was already assigned by `
|
|
69
|
+
*(Skip when analysis ran — the ID was already assigned by `yad-analysis`.)*
|
|
70
70
|
Derive `EP-<slug>` where `slug` is **2–4 lowercase words joined by hyphens**, drawn from the idea
|
|
71
71
|
(e.g. `EP-istifta-inquiries`). Lowercase except the fixed `EP` prefix. **The ID is assigned once and
|
|
72
72
|
never renamed** — renaming breaks every downstream link (build plan §6b).
|
|
@@ -105,7 +105,7 @@ Fill the body with the user; leave `owner` / `technical_product_owner` for the u
|
|
|
105
105
|
`repos` to the repos this epic will touch.
|
|
106
106
|
|
|
107
107
|
### Step 5 — Seed the state machine — analysis-skipped only
|
|
108
|
-
*(Skip when analysis ran — `
|
|
108
|
+
*(Skip when analysis ran — `yad-analysis` already seeded the 10-step chain. Go to Step 5b.)*
|
|
109
109
|
Create `{project-root}/epics/EP-<slug>/.sdlc/state.json` describing the full **8-step** front-state
|
|
110
110
|
sequence (no analysis), all steps defaulting to `automation: human_approve`, with the four authoring
|
|
111
111
|
steps **locked**. Use this exact shape (see `references/state-schema.md`):
|
|
@@ -134,21 +134,21 @@ Notes:
|
|
|
134
134
|
- Also create an empty approvals ledger `{project-root}/epics/EP-<slug>/.sdlc/approvals.json`
|
|
135
135
|
and an empty comments ledger `{project-root}/epics/EP-<slug>/.sdlc/comments.json`, each containing
|
|
136
136
|
`[]`, and the `reviews/` directory. (`comments.json` is the machine-readable counterpart to the
|
|
137
|
-
`reviews/*--comments.md` markdown — `
|
|
137
|
+
`reviews/*--comments.md` markdown — `yad-review-gate` appends to it on every `comment`.)
|
|
138
138
|
|
|
139
139
|
### Step 5b — Advance the authoring step — analysis-ran only
|
|
140
|
-
*(Only when analysis ran — `state.json` already exists from `
|
|
140
|
+
*(Only when analysis ran — `state.json` already exists from `yad-analysis`.)*
|
|
141
141
|
In `state.json`: set `epic.status: "done"`, set `epic-review.status: "in_review"`, and set
|
|
142
142
|
`currentStep: "epic-review"`. Write `state.json`. Do **not** re-seed and do **not** touch
|
|
143
143
|
`approvals.json` — only real reviewers approve, through the gate.
|
|
144
144
|
|
|
145
145
|
### Step 6 — Stop at the gate (do NOT advance)
|
|
146
146
|
Report: epic ID, the path to `epic.md`, and that the next action is **review** via
|
|
147
|
-
`
|
|
147
|
+
`yad-review-gate`. **Never mark the epic-review step approved here** — only real reviewers do that
|
|
148
148
|
through the gate. Front states do not auto-advance. When the hub has a platform, the gate opens a review
|
|
149
|
-
PR on the hub (via `
|
|
149
|
+
PR on the hub (via `yad-hub-bridge`) and `yad-review-gate action: sync` pulls platform approvals/
|
|
150
150
|
comments into the ledger; otherwise the review is recorded file-only.
|
|
151
151
|
|
|
152
152
|
## Reference
|
|
153
153
|
- State schema and field meanings: `references/state-schema.md`.
|
|
154
|
-
- Connecting code repos + the code-context the brain reads: `../
|
|
154
|
+
- Connecting code repos + the code-context the brain reads: `../yad-connect-repos/SKILL.md`.
|
|
@@ -22,15 +22,15 @@ Each `steps[]` entry:
|
|
|
22
22
|
### Two valid chain shapes (analysis is optional)
|
|
23
23
|
|
|
24
24
|
The `analysis` step (and its `analysis-review` gate) is **optional** — it exists only when the team
|
|
25
|
-
ran `
|
|
25
|
+
ran `yad-analysis` before the epic. The entry-point skill (whichever runs first) is the one
|
|
26
26
|
that assigns `EP-<slug>` and seeds `state.json` + the empty ledgers; the other skill detects an
|
|
27
27
|
existing `state.json` and does **not** re-seed.
|
|
28
28
|
|
|
29
|
-
- **With analysis** (10 steps — `
|
|
29
|
+
- **With analysis** (10 steps — `yad-analysis` seeded the chain):
|
|
30
30
|
`analysis → analysis-review → epic → epic-review → architecture → architecture-review → ui-design →
|
|
31
31
|
ui-design-review → stories → stories-review`. Seeded `currentStep` is `analysis-review`; `epic`
|
|
32
32
|
starts `blocked`.
|
|
33
|
-
- **Without analysis** (8 steps — `
|
|
33
|
+
- **Without analysis** (8 steps — `yad-epic` is the entry point, the default):
|
|
34
34
|
`epic → epic-review → … → stories-review`. Seeded `currentStep` is `epic-review`.
|
|
35
35
|
|
|
36
36
|
After `stories-review` passes, `currentStep` becomes the `ready-for-build` sentinel either way.
|
|
@@ -41,7 +41,7 @@ After `stories-review` passes, `currentStep` becomes the `ready-for-build` senti
|
|
|
41
41
|
Each front **authoring** step opens its own git branch at the start of the step, named
|
|
42
42
|
`<step>/EP-<slug>` where `<step>` ∈ `analysis | epic | architecture | ui-design | stories`
|
|
43
43
|
(`config.yaml` `defaults.front_authoring_branch`). This is **distinct** from the review branch
|
|
44
|
-
`review/EP-<slug>/<artifact-base>` that `
|
|
44
|
+
`review/EP-<slug>/<artifact-base>` that `yad-hub-bridge` opens later for the review PR/MR.
|
|
45
45
|
|
|
46
46
|
The shared procedure (run once the `EP-<slug>` is known):
|
|
47
47
|
1. **Git-safe / greenfield-safe:** if `{project-root}` is not a git work tree
|
|
@@ -66,12 +66,12 @@ Append-only ledger (an array). Each entry:
|
|
|
66
66
|
{ "artifact": "epic.md", "step": "epic-review", "approver": "<name>", "role": "owner|reviewer|domain-owner", "domain": "<repo-or-area, optional>", "status": "approved", "date": "<YYYY-MM-DD>", "source": "<bridge, optional>" }
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
`source: "bridge"` marks an approval synced from a hub review PR/MR by `
|
|
70
|
-
(via `
|
|
69
|
+
`source: "bridge"` marks an approval synced from a hub review PR/MR by `yad-review-gate action: sync`
|
|
70
|
+
(via `yad-hub-bridge`). Manual approvals omit `source` and are never altered by `sync`.
|
|
71
71
|
|
|
72
72
|
## `comments.json`
|
|
73
73
|
Append-only ledger (an array), the machine-readable counterpart to the `reviews/*--comments.md` markdown
|
|
74
|
-
("who reviewed/commented", as `approvals.json` is "who approved"). Written by `
|
|
74
|
+
("who reviewed/commented", as `approvals.json` is "who approved"). Written by `yad-review-gate`'s
|
|
75
75
|
`comment` action; feeds the `approved.md` participation roster, not the gate predicate. Each entry:
|
|
76
76
|
|
|
77
77
|
```json
|
|
@@ -102,7 +102,7 @@ and `<artifact-base>` is the artifact without extension (e.g. `epic`, `architect
|
|
|
102
102
|
# Phase 4 build-half state (the back half made dial-bearing)
|
|
103
103
|
|
|
104
104
|
Phase 3 recorded build progress only *after the fact* in `build-log.json`. Phase 4 needs the back
|
|
105
|
-
steps to carry their own `automation` dial so the orchestrator (`
|
|
105
|
+
steps to carry their own `automation` dial so the orchestrator (`yad-run`) can read it and decide
|
|
106
106
|
whether to advance on its own. Two new files under `.sdlc/` do this.
|
|
107
107
|
|
|
108
108
|
## `build-state/<story-id>.json`
|
|
@@ -134,7 +134,7 @@ Each `steps[]` entry:
|
|
|
134
134
|
| `id` | `spec`, `tasks`, `implement`, `checks`, `engineer-review` | Back-half step identity (the `back_steps` from `config.yaml` + the human merge gate). |
|
|
135
135
|
| `automation` | `human_approve` \| `machine_advance` | Dial 2. Defaults to `human_approve`; flipped to `machine_advance` only after the trust threshold is met (and never for `locked` steps). |
|
|
136
136
|
| `locked` | `true` \| `false` | `engineer-review` is `true` — it never auto-advances (build plan §E). |
|
|
137
|
-
| `status` | `blocked` \| `in_progress` \| `in_review` \| `done` | Lifecycle. `
|
|
137
|
+
| `status` | `blocked` \| `in_progress` \| `in_review` \| `done` | Lifecycle. `yad-run` advances `done` steps and `blocked`s on a halt. |
|
|
138
138
|
|
|
139
139
|
`currentStep` is the `id` the orchestrator is waiting on / about to run for that repo. The file is
|
|
140
140
|
created when a story enters the build half; all dials start `human_approve` (the `config.yaml`
|
|
@@ -170,9 +170,9 @@ base** that decides when a step is safe to automate (build plan Step A). One ent
|
|
|
170
170
|
|
|
171
171
|
| Step | Signals | Finalized at (the human gate) |
|
|
172
172
|
|------|---------|-------------------------------|
|
|
173
|
-
| `spec` | `human_edited_spec` | the human who accepts `specs/<story>/` (`
|
|
174
|
-
| `tasks` | `task_rescoped` | first consume by `
|
|
175
|
-
| `implement` | `human_edited_diff`, `scope_overrun`, `contract_touch` | engineer review at `
|
|
173
|
+
| `spec` | `human_edited_spec` | the human who accepts `specs/<story>/` (`yad-spec` Step 8) |
|
|
174
|
+
| `tasks` | `task_rescoped` | first consume by `yad-implement` (Step 8) |
|
|
175
|
+
| `implement` | `human_edited_diff`, `scope_overrun`, `contract_touch` | engineer review at `yad-ship` |
|
|
176
176
|
| `checks` | `checks` (`pass`\|`fail`) | the gate run itself (objective) |
|
|
177
177
|
|
|
178
178
|
**Deriving the provisional verdict** (build plan Step A; extended for `spec`/`tasks` in Phase 4b — the
|
|
@@ -184,4 +184,4 @@ same three-way shape, anchored to each step's human gate, never self-graded):
|
|
|
184
184
|
**Trust threshold** (from `config.yaml` `automation.trust_threshold`): a step is a candidate for
|
|
185
185
|
`machine_advance` only when its slice of `trust-log.json` (same `step`, this story's repo or the
|
|
186
186
|
project) has `>= min_runs` entries AND the fraction with `verdict == "approved-unchanged"` is
|
|
187
|
-
`>= min_approved_unchanged`. The dial-setter in `
|
|
187
|
+
`>= min_approved_unchanged`. The dial-setter in `yad-run` enforces this; `yad-status` surfaces it.
|