yadflow 3.0.0 → 3.1.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 +9 -9
- package/bin/yad.mjs +30 -5
- package/cli/companion.mjs +61 -0
- package/cli/doctor.mjs +11 -0
- package/cli/epic-state.mjs +13 -3
- package/cli/gate.mjs +87 -5
- package/cli/manifest.mjs +1 -0
- package/cli/openpr.mjs +5 -1
- package/cli/plan.mjs +10 -4
- package/cli/platform.mjs +149 -23
- package/cli/reconcile.mjs +3 -3
- package/cli/review.mjs +145 -0
- package/package.json +1 -1
- package/skills/sdlc/config.yaml +8 -0
- package/skills/sdlc/module-help.csv +1 -0
- package/skills/yad-connect-repos/references/hub-config.md +10 -0
- package/skills/yad-docs-overview/references/pipeline-model.md +1 -0
- package/skills/yad-engineer-review/SKILL.md +13 -2
- package/skills/yad-engineer-review/references/ship-and-record.md +15 -2
- package/skills/yad-hub-bridge/references/bridge.md +34 -0
- package/skills/yad-open-pr/SKILL.md +10 -0
- package/skills/yad-pr-template/templates/checks/pr-template.sh +9 -0
- package/skills/yad-review-companion/SKILL.md +89 -0
- package/skills/yad-review-gate/SKILL.md +5 -1
- package/skills/yad-review-gate/references/gating.md +18 -0
|
@@ -45,6 +45,15 @@ if [ -z "$BODY" ] || [ ! -f "$BODY" ]; then
|
|
|
45
45
|
exit 1
|
|
46
46
|
fi
|
|
47
47
|
|
|
48
|
+
# The Review Companion injects a `<!-- yad:trailer --> … <!-- /yad:trailer -->` briefing block (and
|
|
49
|
+
# `<!-- yad:noblock -->` notes) into the description. Strip those before the template check so the
|
|
50
|
+
# AI-generated prose can never hide a required section heading or be mistaken for the `Risk level:`
|
|
51
|
+
# value (the trailer is prepended, so an unstripped "risk level" mention would win `head -1`).
|
|
52
|
+
STRIPPED="$(mktemp)"
|
|
53
|
+
trap 'rm -f "$STRIPPED"' EXIT
|
|
54
|
+
sed '/<!-- yad:trailer -->/,/<!-- \/yad:trailer -->/d; /<!-- yad:noblock -->/d' "$BODY" > "$STRIPPED"
|
|
55
|
+
BODY="$STRIPPED"
|
|
56
|
+
|
|
48
57
|
rc=0
|
|
49
58
|
require_heading() {
|
|
50
59
|
if ! grep -qiE "^[[:space:]]*$1[[:space:]]*$" "$BODY"; then
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yad-review-companion
|
|
3
|
+
description: 'The fun, easy, transparent review companion for the SDLC review gates. Generates a 60-second AI "trailer" of what changed and where the risk is, deals a swipe-through deck of small review "cards", and runs a grounded chat where a reviewer asks anything and their questions become the review record — then records an engagement signal on the approval (verified vs none) and posts a friendly public nudge on a bare rubber-stamp. Works on the front-half artifact-review PR/MR (yad gate) and the back-half code PR/MR (yad review). Use when the user says "review this", "run the companion", "give me the trailer/cards", or wants reviewing to be less of a chore.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SDLC — Review Companion (fun & easy, transparent review)
|
|
7
|
+
|
|
8
|
+
**Goal:** make the honest review the *easiest, most enjoyable* path, and make laziness **visible**, not
|
|
9
|
+
blocked. This companion does **not** try to prove a human read something — no quiz, no un-fakeable
|
|
10
|
+
proof (a quiz is answerable by AI, swipes can be spammed). Instead it removes the friction that makes
|
|
11
|
+
reviewers skip, and it makes review *quality* visible to the whole team.
|
|
12
|
+
|
|
13
|
+
> **Philosophy — "visible, not impossible."** Every engagement signal here is gameable by design. It
|
|
14
|
+
> raises the cost of a bare rubber-stamp and shines a light on it; it never claims certainty. State that
|
|
15
|
+
> openly — do not oversell it.
|
|
16
|
+
|
|
17
|
+
This companion is the AI layer on top of [`yad-review-gate`](../yad-review-gate/SKILL.md) (front half)
|
|
18
|
+
and [`yad-engineer-review`](../yad-engineer-review/SKILL.md) (back half). The **gate** still owns the
|
|
19
|
+
predicate and advancement; the companion only enriches the *input* and records the *engagement* field.
|
|
20
|
+
The CLI never calls an LLM — **you** (this skill) generate the text and post it via the platform.
|
|
21
|
+
|
|
22
|
+
## The four faces
|
|
23
|
+
|
|
24
|
+
1. **🎬 Trailer (A)** — a 60-second briefing: what this change does, where the risk is (from the step's
|
|
25
|
+
`risk_tags`), and an honest read-time estimate. Posted to the **PR/MR description** as a delimited
|
|
26
|
+
`<!-- yad:trailer --> … <!-- /yad:trailer -->` block so everyone sees it in the UI. Regenerated when
|
|
27
|
+
the artifact changes (it must never lie about the current content).
|
|
28
|
+
2. **🃏 Cards (B)** — split the change into small **atomic claims**, one per card, each anchored to real
|
|
29
|
+
line numbers / hunks and tagged with risk. Posted as PR/MR comment threads the reviewer skims 👍/🤔.
|
|
30
|
+
3. **💬 Chat (C)** — a grounded Q&A: the reviewer asks anything; you answer **only from real material**
|
|
31
|
+
(the artifact + diff + contract + the repo `code-map.md`/`pack.md` + sister docs). The reviewer's
|
|
32
|
+
questions and flagged concerns become the review record. If you **cannot** answer from the material,
|
|
33
|
+
say so — that gap is itself a finding (post it as a genuine, blocking comment).
|
|
34
|
+
4. **🏆 Social (E)** — a verified-engagement mark on a real companion review, a friendly public
|
|
35
|
+
@-mention nudge on a bare approve, and light read-only gamification surfaced by `yad status`.
|
|
36
|
+
|
|
37
|
+
## Markers (the contract with the gate — all live in PLATFORM data, never a ledger file)
|
|
38
|
+
|
|
39
|
+
- `<!-- yad:trailer -->` / `<!-- /yad:trailer -->` — the trailer block in the PR/MR description.
|
|
40
|
+
- `<!-- yad:noblock -->` — on **every** companion-posted comment (card deck, chat log) and the nudge.
|
|
41
|
+
The gate **excludes** these threads from the blocking check, so they stay unresolved as a permanent
|
|
42
|
+
PR/MR history trail and never hold the gate. A reviewer's *genuine* concern is posted **without** this
|
|
43
|
+
marker, so it blocks normally.
|
|
44
|
+
- `<!-- yad:engagement verified -->` — embedded in the body of a companion-driven **Approve** review.
|
|
45
|
+
A bare UI click has no marker → `engagement: none`. (Definitions live in `cli/companion.mjs`.)
|
|
46
|
+
|
|
47
|
+
## On activation
|
|
48
|
+
|
|
49
|
+
Inputs: `epic` + `artifact` (front half) **or** `repo` + `pr` (back half); and the `action`
|
|
50
|
+
(`trailer` | `cards` | `chat` | `approve` | `nudge`, default the full flow).
|
|
51
|
+
|
|
52
|
+
1. **Get the grounding bundle.** Front half: `yad gate review <epic> [artifact]` prints JSON with the
|
|
53
|
+
artifact path, risk tags, PR number, contract path, touched domains, repo code-map paths, and
|
|
54
|
+
`requireEngagement`. Back half: `yad review chat --repo <r>` (see `yad-engineer-review`) provides the
|
|
55
|
+
diff + code-map grounding. Read the named files yourself — never invent content.
|
|
56
|
+
2. **Trailer.** Generate ≤6 lines (what / risk / read-time), grounded only in the bundle. Post it:
|
|
57
|
+
`yad gate trailer <epic> <artifact> --body "<text>" [--pr <n>]` (idempotent; re-run after edits).
|
|
58
|
+
3. **Cards.** Produce atomic claims, each citing real lines. Post the deck as a single comment carrying
|
|
59
|
+
`<!-- yad:noblock -->`. A reviewer's 🤔 with a real concern → re-post as a **normal, unflagged**
|
|
60
|
+
comment so it blocks.
|
|
61
|
+
4. **Chat.** Answer from the material with cited lines. Append the Q&A log as a `<!-- yad:noblock -->`
|
|
62
|
+
comment so it persists in history without blocking. Turn genuine concerns into unflagged comments.
|
|
63
|
+
5. **Approve.** When the reviewer is satisfied, submit an Approve whose body carries
|
|
64
|
+
`<!-- yad:engagement verified -->` (so the gate records `engagement: verified`). GitHub:
|
|
65
|
+
`gh pr review <n> --approve --body "<note>\n\n<!-- yad:engagement verified -->"`. GitLab: approve,
|
|
66
|
+
then post the marker as a note (`glab mr approve <n>` + `glab mr note <n> -m "…<!-- yad:engagement verified -->"`).
|
|
67
|
+
6. **Nudge.** A bare approve (engagement `none`) still counts under the soft default; `yad gate sync`
|
|
68
|
+
posts the friendly @-mention automatically. You may also post it directly with the
|
|
69
|
+
`<!-- yad:noblock -->` marker.
|
|
70
|
+
|
|
71
|
+
## Hard rules
|
|
72
|
+
|
|
73
|
+
- **Never write a ledger file.** Post comments / the trailer / the approval to the PLATFORM (the
|
|
74
|
+
reviewer's own `gh`/`glab`). CI writes `approvals.json`/`comments.json`; the `ledger-guard` check
|
|
75
|
+
rejects a human ledger edit on a review PR. The markers ride in platform data only.
|
|
76
|
+
- **Trailer/cards/chat are grounded ONLY in real material.** If the material does not answer a
|
|
77
|
+
question, say so and record the gap — do not fabricate.
|
|
78
|
+
- **Companion comments never block; genuine concerns always do.** Flag the former with `yad:noblock`;
|
|
79
|
+
leave the latter unflagged.
|
|
80
|
+
- **The engagement signal is gameable and you say so.** It makes review quality visible; it is not
|
|
81
|
+
proof. The strict-mode switch is `hub.review.requireEngagement` (off by default).
|
|
82
|
+
- **The companion never approves on a human's behalf and never merges.** It assists; the human acts.
|
|
83
|
+
|
|
84
|
+
## File-only mode (no platform)
|
|
85
|
+
|
|
86
|
+
With no hub platform, there is no PR to post to: write the trailer to
|
|
87
|
+
`reviews/<artifact-base>--<date>--trailer.md` and the card/chat notes alongside the existing
|
|
88
|
+
`reviews/*.md`, and the reviewer records approval the manual way (`yad-review-gate` `approve`). The same
|
|
89
|
+
generation logic applies; only the surface changes.
|
|
@@ -92,8 +92,12 @@ Repeat comment→address rounds until reviewers are satisfied. **Commenting neve
|
|
|
92
92
|
|
|
93
93
|
**`approve`** — Record an approval. Append to `.sdlc/approvals.json`:
|
|
94
94
|
```json
|
|
95
|
-
{ "artifact": "<artifact>", "step": "<step id>", "approver": "<name>", "role": "<owner|reviewer|domain-owner>", "domain": "<optional>", "status": "approved", "date": "<YYYY-MM-DD>" }
|
|
95
|
+
{ "artifact": "<artifact>", "step": "<step id>", "approver": "<name>", "role": "<owner|reviewer|domain-owner>", "domain": "<optional>", "status": "approved", "date": "<YYYY-MM-DD>", "engagement": "<verified|none>" }
|
|
96
96
|
```
|
|
97
|
+
`engagement` records whether the approval came through the [Review Companion](../yad-review-companion/SKILL.md)
|
|
98
|
+
(a real trailer/cards/chat session = `verified`) or as a bare click (`none`). It is soft by default
|
|
99
|
+
(both count; a bare approve draws a friendly nudge) and only gates when `hub.review.requireEngagement`
|
|
100
|
+
is on — see `references/gating.md`. The signal is gameable by design ("visible, not impossible").
|
|
97
101
|
Also write/refresh `reviews/<artifact-base>--<YYYY-MM-DD>--approved.md` as a **named roster** with three
|
|
98
102
|
sections, so every participant is attributable in one place:
|
|
99
103
|
|
|
@@ -12,6 +12,15 @@ Let `A` = the set of `approved` records in `.sdlc/approvals.json` for this step.
|
|
|
12
12
|
**Escalated pass** (step `risk_tags` ∩ `{contract, auth, payments}` ≠ ∅): base pass AND, for every
|
|
13
13
|
touched `domain`, `|domainOwners[domain]| >= 1`.
|
|
14
14
|
|
|
15
|
+
**Engagement (the Review Companion).** Each approval carries `engagement: verified | none` —
|
|
16
|
+
`verified` when it was recorded through the companion (a real trailer/cards/chat session), `none` for a
|
|
17
|
+
bare UI click. By **default (soft)** both count: a bare approve still passes the gate but is recorded
|
|
18
|
+
`none` and draws a friendly public @-mention nudge, so review *quality* is visible without blocking
|
|
19
|
+
anyone. When `hub.review.requireEngagement: true`, only `verified` approvals are counted toward the
|
|
20
|
+
sets above (a determined faker can still run an empty session — the signal is **gameable by design**;
|
|
21
|
+
it raises the cost of a rubber-stamp and makes laziness visible, it does not prove a human read the
|
|
22
|
+
artifact). Philosophy: *visible, not impossible.*
|
|
23
|
+
|
|
15
24
|
**Touched domains** are resolved from files, not hardcoded:
|
|
16
25
|
- Architecture+contract review: the touched domains are the epic's `repos` (every repo shares the
|
|
17
26
|
contract surface).
|
|
@@ -55,6 +64,15 @@ counterpart to the `reviews/*--comments.md` markdown). It does **not** feed the
|
|
|
55
64
|
alone decide the gate — but it makes the `approved.md` roster's "Reviewed / commented by" section
|
|
56
65
|
attributable, and it is the same shape a future service or the platform bridge can write.
|
|
57
66
|
|
|
67
|
+
## Non-blocking companion comments (`<!-- yad:noblock -->`)
|
|
68
|
+
The Review Companion posts scaffolding comments (the card deck, the chat log) and the social nudge.
|
|
69
|
+
These are fun/interactive aids, **not** review objections, so they must never hold the PR/MR — yet they
|
|
70
|
+
are deliberately **left unresolved** so they remain in the PR/MR history forever (anyone can scroll back
|
|
71
|
+
to see the trailer, cards, chat, and nudges). Every such comment carries a `<!-- yad:noblock -->`
|
|
72
|
+
marker, and the gate **excludes marked threads** from the unresolved-thread blocking check (so it does
|
|
73
|
+
not "resolve to pass" — it ignores them). A reviewer's *genuine* concern is posted **without** the
|
|
74
|
+
marker and blocks normally, exactly as a `CHANGES_REQUESTED` or any unresolved human thread does.
|
|
75
|
+
|
|
58
76
|
## Platform-backed input (the bridge)
|
|
59
77
|
When the hub has a platform (`.sdlc/hub.json`) and the bridge is enabled, reviewers can approve/comment
|
|
60
78
|
on a real PR/MR instead of (or as well as) the skill recording it directly. `action: sync`
|