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.
@@ -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`