@seanyao/roll 3.615.1 → 3.617.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seanyao/roll",
3
- "version": "3.615.1",
3
+ "version": "3.617.1",
4
4
  "description": "Roll — Roll out features with AI agents",
5
5
  "packageManager": "pnpm@11.1.3",
6
6
  "scripts": {
@@ -44,8 +44,11 @@ Every hub must include `## Gotchas` or `## Known Failure Modes`.
44
44
  - Treat the section as append-mostly unless an entry is proven obsolete.
45
45
  - Never instruct agents to `source "$(command -v roll)"`: the TS-native `roll`
46
46
  is a bundled CLI, not a bash library, and sourcing it executes JS as shell
47
- (FIX-274). Skill steps call `roll <command>` directly — e.g. self-score notes
48
- go through `roll self-score <skill> <story> <score> <verdict> "<rationale>"`.
47
+ (FIX-274). Skill steps call `roll <command>` directly.
48
+ - Skills do NOT self-score (FIX-343). The working agent never scores its own
49
+ story; the Review Score is a runner-side peer-review outcome, produced by a
50
+ Reviewer in a FRESH, separate session (never a sub-agent of the builder's
51
+ session). Do not author any `self-score` step into a skill.
49
52
 
50
53
  ## Maintenance Workflow
51
54
 
@@ -34,7 +34,7 @@ Load when a user gives a US-XXX story or asks to ship a feature through Roll TCR
34
34
 
35
35
  - TCR for every micro-step.
36
36
  - No WIP commits or bypassed verification.
37
- - Self-review, attest, E2E evidence, and self-score remain required.
37
+ - Self-review, attest, and E2E evidence remain required. The Review Score is produced by the runner's fresh-session peer Reviewer — the agent does NOT self-score.
38
38
  - Docs/code/product alignment is a DoD gate: user-visible behavior, command, output-copy, site, or delivery-view changes update the touched README/docs/guide/site/help in the same delivery.
39
39
 
40
40
  ## Gotchas
@@ -314,14 +314,30 @@ $(msg build.micro_step {N} "{description of smallest testable change}")
314
314
  └── Write just enough to make test pass
315
315
 
316
316
  Step 3: TCR Decision
317
- └── Run test
317
+ └── roll test (per-commit gate — AFFECTED scope only)
318
318
  ├── ✅ GREEN → git commit -m "tcr: {micro-step description}"
319
319
  └── ❌ RED → git checkout -- . → Retry with new approach
320
320
 
321
321
  Step 4: Refactor (optional, while green)
322
- └── Run test → ✅ GREEN → Amend or new TCR cycle
322
+ └── roll test → ✅ GREEN → Amend or new TCR cycle
323
323
  ```
324
324
 
325
+ **The commit gate runs AFFECTED tests, not the full suite (FIX-325):**
326
+
327
+ - `roll test` (the per-commit gate) runs `vitest --changed` — only the
328
+ dependency closure of the working-tree change — and **excludes** the
329
+ env-divergent heavy suites (`*.integration.test.ts`, `*.e2e.test.ts`,
330
+ `npm-pack.test.ts`) that are red locally / in a cycle worktree but green in
331
+ CI. The FULL suite (`npm test`, no `--affected`) is the CI / pre-push gate
332
+ (Phase 5), never the per-commit gate.
333
+ - On green, `roll test` writes the proof record `.roll/last-test-pass`
334
+ (`{ts, tree, mode, scope}`). The `pre-commit` hook refuses the commit unless
335
+ that proof is **fresh (≤ 60s)** AND its `tree` matches the current
336
+ `git write-tree` — i.e. the exact code being committed was just tested. So:
337
+ stage → `roll test` → commit, in that order; editing after the test
338
+ invalidates the proof (commit blocked: "code changed since last test run").
339
+ Doc-only changes are exempt.
340
+
325
341
  **Micro-step guidelines:**
326
342
 
327
343
  | Change Type | Typical Micro-Steps |
@@ -411,7 +427,10 @@ E2E DEPOSIT
411
427
 
412
428
  ### Phase 5: Pre-Push CI Gate
413
429
 
414
- After all micro-steps, run full CI locally before pushing:
430
+ After all micro-steps, run the **FULL** suite locally before pushing — this is
431
+ where the heavy env-divergent suites (integration / e2e / npm-pack) excluded
432
+ from the per-commit affected gate (Phase 3) finally run. This is the same scope
433
+ CI runs (`npm test` with no `--affected`), so a green here predicts a green CI.
415
434
 
416
435
  ```bash
417
436
  npm run ci:local 2>/dev/null || (npm run lint && npm run build && npm test -- --run)
@@ -578,6 +597,15 @@ Follow the repo's deployment path (Vercel / Railway / etc.) and record the deplo
578
597
 
579
598
  Runs ONLY on a ✅ Gate PASS (a FAIL retry must not mint a misleading report). Non-blocking: any failure here → WARN, continue to Phase 12.
580
599
 
600
+ **Attest is EARNED during delivery — never backfilled (FIX-329).** Acceptance
601
+ evidence is produced inside the delivery: under `roll-loop` the HARD
602
+ `attest:gate` renders the report in-cycle; on the manual path you run
603
+ `roll attest` here, in Phase 10.6 of this delivery. There is no after-the-fact
604
+ reconstruction — `roll attest backfill` was a loophole and has been **removed**
605
+ (it now hard-errors). A Done card with no in-delivery evidence cannot acquire a
606
+ report; the only way past the release consistency gate is to **re-deliver** the
607
+ story (loop or manual Phase 10.6) and earn the report at delivery time.
608
+
581
609
  0. **Before/after pairing (owner ruling 2026-06-06)**: when the story CHANGES
582
610
  existing behavior, capture the prior state (`screenshots/before-*.png`)
583
611
  before building and the new state (`screenshots/after-*.png`) at acceptance —
@@ -604,6 +632,20 @@ Runs ONLY on a ✅ Gate PASS (a FAIL retry must not mint a misleading report). N
604
632
  (deterministic), never hand-craft an image; if the capture channel is
605
633
  unavailable (no GUI session / no permission), fall back to text evidence and
606
634
  mark the AC `partial` with a note — never fake a screenshot.
635
+
636
+ **Web capture — shoot the DELIVERABLE, not the dossier (FIX-321/314)**: a web
637
+ screenshot captures the card's **declared** deliverable, taken from the
638
+ story's frontmatter key `deliverable_url` (alias `screenshot_url`). It may be
639
+ a URL, a local file, or carry a `#fragment` to deep-link a specific tab/view
640
+ (e.g. `.roll/features/index.html#casting`). The loop captures it with
641
+ **headless Playwright** — no GUI browser window pops up, and a missing
642
+ Chromium self-heals via an auto-install on first use. The red line: **never**
643
+ screenshot roll's own attest report / dossier page and pass it off as the
644
+ deliverable — that is a hollow shot. If the card declares **no**
645
+ `deliverable_url`, the capture **honestly skips** (recorded as a real skip,
646
+ not a fabricated image) — that is the correct behavior, not a failure. Declare
647
+ `deliverable_url` in the spec frontmatter when the story ships a visible web
648
+ surface so the real view gets captured.
607
649
  2. **Write the intent map** `.roll/features/<epic>/{ID}/ac-map.json` — for EVERY AC (ids `{ID}:AC1..n`) pick `pass|readonly|partial|claimed|missing` and reference only evidence that exists (paths relative to the run dir; story-level dirs are reachable as `../evidence/...` / `../screenshots/...`):
608
650
 
609
651
  ```json
@@ -615,7 +657,7 @@ Runs ONLY on a ✅ Gate PASS (a FAIL retry must not mint a misleading report). N
615
657
  ```
616
658
 
617
659
  No evidence for an AC → say `claimed` yourself; the renderer enforces that downgrade anyway (red line) and lists it under Discrepancies.
618
- 3. **Run** `roll attest {ID}` (add `--deploy-url <url>` when one exists). The report lands at `.roll/features/<epic>/{ID}/latest/{ID}-report.html` (archive-per-card layout, US-META-001). The report is now layered (US-ATTEST-013): card context + conclusion/business badges + key screenshots up front, technical ANSI/command output folded into collapsed `<details>`, and a closing block (quality gate + evidence index + self-score).
660
+ 3. **Run** `roll attest {ID}` (add `--deploy-url <url>` when one exists). The report lands at `.roll/features/<epic>/{ID}/latest/{ID}-report.html` (archive-per-card layout, US-META-001). The report is now layered (US-ATTEST-013): card context + conclusion/business badges + key screenshots up front, technical ANSI/command output folded into collapsed `<details>`, and a closing block (quality gate + evidence index + Review Score).
619
661
  4. **Design QA checklist (US-ATTEST-013) — READABILITY ONLY**. After the report
620
662
  renders, open it and run the checklist below. This is a presentation review of
621
663
  the rendered HTML, NOT an evidence review.
@@ -641,6 +683,20 @@ Runs ONLY on a ✅ Gate PASS (a FAIL retry must not mint a misleading report). N
641
683
 
642
684
  ### Phase 12: Write Back Status (REQUIRED)
643
685
 
686
+ **Done ≡ merged (FIX-322/323).** A card is `✅ Done` only once its delivery is
687
+ **merged to `main`** — not when the branch is pushed and not while the PR is
688
+ merely open. `published_pending_merge` (pushed / PR open, awaiting merge) is
689
+ **not** delivered. Consequences you can rely on:
690
+
691
+ - The picker **skips** any card that already has a merged delivery, so a card
692
+ reset to 📋 Todo after merge is not re-picked and re-built.
693
+ - Preflight reconciles truth from the PR: a 🔨 In Progress card whose PR has
694
+ **MERGED** is flipped to ✅ Done automatically (an OPEN PR is left alone).
695
+
696
+ So on the manual path, flip the row to Done **after** the PR merges; under
697
+ `roll-loop` the runner waits for green CI, auto-merges, and the flip follows the
698
+ merge — do not pre-flip on a still-open PR.
699
+
644
700
  Both locations must be updated — neither can be skipped:
645
701
 
646
702
  **① Update .roll/backlog.md index row (Status column):**
@@ -738,9 +794,14 @@ Before creating any file or directory:
738
794
  worktree + branch and opens the PR; this rule is the manual-path
739
795
  equivalent and must hold either way.)
740
796
 
741
- 1. **No local-only "done"**
797
+ 1. **No local-only "done" — Done ≡ merged (FIX-322/323)**
742
798
  Work is not complete until it reaches:
743
- commit → push → CI signal → deploy online verificationbacklog update
799
+ commit → push → CI signal → **PR merged to main**deploy → online
800
+ verification → backlog update.
801
+ A pushed branch or an open PR is `published_pending_merge`, NOT delivered;
802
+ the row flips to `✅ Done` only after the merge. Truth reconciles from the
803
+ PR: the picker skips already-merged cards and preflight flips a MERGED PR's
804
+ card to Done.
744
805
 
745
806
  2. **TCR for every micro-step**
746
807
  - Each behavior change: Test → Green=Commit / Red=Revert
@@ -792,33 +853,24 @@ Before creating any file or directory:
792
853
  - [ ] **.roll/backlog.md index status updated** (📋 → ✅, REQUIRED)
793
854
  - [ ] **`.roll/features/<feature>.md` US section updated** (Completed date + [x] ACs, REQUIRED)
794
855
  - [ ] **CHANGELOG.md staged and bundled** into completion commit via `$roll-.changelog` in Phase 12 (REQUIRED)
795
- - [ ] **Self-score note written (US-SKILL-010 / 012)** — see "Self-score" subsection below
796
856
  - [ ] Summary reported to user
797
857
 
798
- ### Self-score (US-SKILL-012)
799
-
800
- Before reporting completion to the user, ensure one score note lands.
801
- **Pair-first (US-PAIR-009/010): when `.roll/pairing.yaml` enables the `score`
802
- stage, the paired heterogeneous agent produces the score — self-score is the
803
- fallback, not the default.** Run from the main project root (the directory
804
- holding `.roll/`); the note lands under `.roll/features/<epic>/<US-id>/notes/<date>-roll-build-<US-id>-<epoch>.md` (the card folder is the note home, US-META-008; epic resolution and the `.roll/notes/` fallback are built in)
805
- with YAML frontmatter so trend analysis (US-SKILL-014) can aggregate later:
806
-
807
- ```bash
808
- # 1. pair-first: ask the paired heterogeneous agent to score the cycle
809
- roll pair score US-XXX-NNN --summary "<one-paragraph delivery summary>"
810
- # 2. ONLY when the command prints a fallback hint (pairing off / no candidate /
811
- # timeout), write the self-score with the printed reason:
812
- roll self-score roll-build US-XXX-NNN <score 1..10> <good|ok|regression> "<rationale>" --fallback-reason "<reason>"
813
- ```
858
+ ### Review Score (FIX-343)
814
859
 
815
- Both commands are idempotent retrying after a transient failure is safe.
860
+ The story's Review Score is **not** produced by this skill. The building agent
861
+ **does NOT self-score**. The quality score is produced SOLELY by the runner's
862
+ peer score stage — a Reviewer running in a FRESH, separate session (never a
863
+ sub-agent of the builder's session). The agent's job is to deliver clean
864
+ evidence (report + ac-map + attest); the runner then casts a fresh-session
865
+ Reviewer that mints the Review Score (1..10 + verdict + rationale), recorded
866
+ with `scoredBy` and the fresh-session id so independence is verifiable.
816
867
 
817
- > FIX-274: the TS-native `roll` is a bundled CLI and MUST NOT be sourced as a
818
- > bash library the old `source`-based `_skill_write_self_score`
819
- > path is dead. Retrying after a transient failure is safe (idempotent).
868
+ Independence is about session/context, not vendor: a fresh same-vendor session
869
+ is the minimum acceptable; a different agent+model+session (non-sub-agent) is
870
+ encouraged (absolute heterogeneity). A score sharing the builder's session
871
+ (including any sub-agent of it) is rejected as a self-score.
820
872
 
821
- Score guidance (integer 1..10):
873
+ Score guidance the Reviewer applies (integer 1..10):
822
874
  - **9..10** — story shipped cleanly: AC fully met, TCR rhythm tight, no
823
875
  re-tries from `verdict: too_big`, peer review concerns addressed inline.
824
876
  - **6..8** — shipped with caveats: re-tries on red, edge case left to a
@@ -30,7 +30,6 @@ Load when the user wants to discuss approaches, design a solution, model domains
30
30
  3. Detailed design before decomposition — for any non-trivial work, produce a concrete, implementable design artifact and get owner sign-off: (a) data/contract schema, (b) AT LEAST ONE complete worked sample of the intended output/behavior, (c) key interface signatures, (d) mapping/normalization rules, (e) edge cases & failure modes. Depth scales with risk/novelty; trivial work may be light.
31
31
  4. Split into INVEST stories — each a slice of the agreed detailed design.
32
32
  5. Write specs through roll story new and update backlog.
33
- 6. Self-score the design quality.
34
33
 
35
34
  ## Hard Gates
36
35
 
@@ -38,6 +37,7 @@ Load when the user wants to discuss approaches, design a solution, model domains
38
37
  - Backlog rows and spec files must stay consistent.
39
38
  - Peer review gates apply only when explicitly available/requested.
40
39
  - No story decomposition until a detailed design exists and the owner has signed off (proportional to risk). Decomposition slices an agreed design — it is NOT a substitute for designing. If you cannot show at least one complete worked sample of the intended output/behavior, the design is NOT done.
40
+ - **Visual-evidence contract (FIX-311 — design-phase gate)**: every story spec is born honest. By default each story MUST carry one AC that captures its user-visible surface (web/CLI/TUI), and a web/visual card MUST declare the real product surface in its spec frontmatter — `deliverable_url:` (alias `screenshot_url:`) pointing at the actual deliverable page (e.g. `.roll/features/index.html#casting`), NEVER the card's own dossier/report page. A card with genuinely no visual surface writes `screenshot_exempt: <reason>` (a naked `true`/`yes` is NOT a valid exemption — it must carry a reason). This is enforced, not advisory: `validateStoryVisualEvidence(specText)` in `packages/cli/src/lib/design-visual-evidence.ts` returns `ok:false` for a non-exempt spec with no visual-evidence AC, or one that declares a visual surface but no `deliverable_url`. Keyword matching may only RECOGNISE an exemption / an existing visual-evidence AC — it may NEVER be used to decide a card needs a screenshot (it always does, by default). This is the same contract the runtime enforce gate (FIX-309) and archive gate (FIX-334) hold; the three must agree.
41
41
 
42
42
  ## Gotchas
43
43
 
@@ -2,6 +2,32 @@
2
2
 
3
3
  > **These are not best practices — they are baseline requirements.** Violations are bugs.
4
4
 
5
+ ## 0. Visual Evidence Contract (FIX-311) 📸
6
+
7
+ **Definition:** A spec must be born honest — its design already names HOW the
8
+ delivery will prove its user-visible surface. A missing screenshot is a DESIGN
9
+ defect, not a delivery omission.
10
+
11
+ **Must verify (default = REQUIRED; exemption is the only opt-out):**
12
+ - [ ] Every story carries one AC that captures its user-visible surface (web/CLI/TUI screenshot / 截图).
13
+ - [ ] A web/visual card declares the real product surface in frontmatter — `deliverable_url:` (alias `screenshot_url:`) pointing at the actual deliverable page (e.g. `.roll/features/index.html#casting`), NEVER the card's own dossier/report page.
14
+ - [ ] A card with genuinely no visual surface records `screenshot_exempt: <reason>` (a naked `true`/`yes` is invalid — the reason is mandatory).
15
+
16
+ **Enforced, not advisory:** `validateStoryVisualEvidence(specText)` in
17
+ `packages/cli/src/lib/design-visual-evidence.ts` returns `ok:false` for a
18
+ non-exempt spec missing a visual-evidence AC, or one that declares a visual
19
+ surface but no `deliverable_url`. Keyword matching may only RECOGNISE an
20
+ exemption / an existing visual-evidence AC — never decide a card needs a
21
+ screenshot (it always does, by default). Same contract the runtime enforce gate
22
+ (FIX-309) and archive gate (FIX-334) hold; the three must agree.
23
+
24
+ **Counter-example (FIX-284):** ① a card declared a deliverable url yet wired no
25
+ capture AC → honest-skip / empty shell forever; ② a clear UI redesign lacking
26
+ the literal keyword slipped the iron rule (keyword-as-enabler leak). Both are
27
+ caught here at the spec source.
28
+
29
+ ---
30
+
5
31
  ## 1. Idempotency 🔁
6
32
 
7
33
  **Definition:** Performing the same operation N times produces the same result as performing it once.
@@ -719,6 +719,25 @@ Note: `{DOMAIN}` maps to the Bounded Context name identified in DDD analysis.
719
719
  - [ ] {measurable criteria 1}
720
720
  - [ ] {measurable criteria 2}
721
721
  - [ ] {measurable criteria 3}
722
+ - [ ] {visual-evidence AC — REQUIRED by default: a captured screenshot of this story's user-visible surface (web/CLI/TUI). For a web/visual card this is "screenshot of <the deliverable page> is captured", paired with the `deliverable_url:` frontmatter below. Omit this AC ONLY when the card is `screenshot_exempt:` (see frontmatter).}
723
+
724
+ **Spec frontmatter (visual-evidence contract — FIX-311):**
725
+ - A web/visual card MUST declare the real product surface it delivers:
726
+ ```yaml
727
+ ---
728
+ deliverable_url: .roll/features/index.html#casting # alias: screenshot_url. The actual deliverable page, NEVER the card's own dossier/report page.
729
+ ---
730
+ ```
731
+ - **Pin down the deliverable surface — locate it, don't guess** (`deliverable_url` MUST be the EXACT page + anchor the story lands on):
732
+ - *Existing surface* → cite the real tab/anchor and VERIFY it exists (grep the generated page for the `#anchor`); never a parent or plausible-but-wrong page.
733
+ - *New feature* → DECIDE and NAME where it lands (which page / tab / route it is added to); that landing point IS the `deliverable_url` (it may not exist until this story builds it — that is expected; FIX-309 will require a real capture of it at attest, so a wrong/empty target fails loud).
734
+ - Never the card's dossier; never a generic page when the story changes a specific sub-surface.
735
+ - A card with genuinely NO user-visible surface (pure data-migration, infra, …) instead records:
736
+ ```yaml
737
+ ---
738
+ screenshot_exempt: pure data-migration — no user-visible surface # a naked `true`/`yes` is NOT valid; the reason is mandatory.
739
+ ---
740
+ ```
722
741
 
723
742
  **Files:**
724
743
  - `{file1}`
@@ -807,48 +826,16 @@ Each story must be:
807
826
 
808
827
  ---
809
828
 
810
- ## Self-score (US-SKILL-010 / 013)
829
+ ## Review Score (FIX-343)
811
830
 
812
- After Step 5 (Write to BACKLOG) completes — i.e. once the new US rows are
813
- landed and the user has either confirmed or chosen `No` (story still
814
- queued) write a single self-score note covering the design session:
831
+ The design session is **not** self-scored. The designing agent **does NOT
832
+ self-score**. A design Review Score when one is produced comes SOLELY from
833
+ a Reviewer running in a FRESH, separate session (never a sub-agent of the
834
+ designer's session), the same independence rule as build/fix.
815
835
 
816
- ```bash
817
- # 1. pair-first (US-PAIR-009/010): when .roll/pairing.yaml enables the `score`
818
- # stage, the paired heterogeneous agent scores the design session
819
- roll pair score US-XXX-NNN --skill roll-design --summary "<one-paragraph design-session summary>"
820
- # 2. ONLY when the command prints a fallback hint (pairing off / no candidate /
821
- # timeout), write the self-score with the printed reason:
822
- roll self-score roll-design US-XXX-NNN <score 1..10> <good|ok|regression> "<rationale>" --fallback-reason "<reason>"
823
- ```
824
-
825
- > FIX-274: the TS-native `roll` is a bundled CLI and MUST NOT be sourced as a
826
- > bash library — the old `source`-based `_skill_write_self_score`
827
- > path is dead. Retrying after a transient failure is safe (idempotent).
828
-
829
- Use the **first** US-id of the batch as the story handle (or the
830
- representative story when splitting). Run from the main project root; when the
831
- story already has a card folder the note lands there, otherwise it falls back
832
- to `.roll/notes/<date>-roll-design-<id>-<epoch>.md` so US-SKILL-014 can
833
- read trend data.
834
-
835
- Score guidance for design quality (integer 1..10):
836
- - **9..10** — clean split: every US is INVEST-compliant, profile
837
- (est_min / risk_zone / chain_depth) filled, doc-refresh closer wired
838
- when user-visible behaviour changed, peer-review unnecessary or
839
- reached AGREE quickly.
840
- - **6..8** — split shipped but with caveats: one US borderline on
841
- INVEST (e.g. shared file conflict), or Discuss had ESCALATE before
842
- settling, or profile was partial.
843
- - **1..5** — split shipped but rough: missing doc-refresh closer,
844
- profile fields skipped, USer story too coarse for AI cycle; flag a
845
- follow-up `roll-design` pass.
846
-
847
- Verdict values:
848
- - `good` — design + split are clean.
849
- - `ok` — design is acceptable with one or two trade-offs noted.
850
- - `regression` — the split visibly broke something earlier (rare; e.g.
851
- invalidated a previously-stable depends-on chain).
836
+ The design-side peer Review Score path is tracked by **FIX-344** (the runner's
837
+ score stage does not yet cover `roll-design`). Until FIX-344 lands, this skill
838
+ emits no quality score; the agent just delivers the split + specs and stops.
852
839
 
853
840
  ---
854
841
 
@@ -34,7 +34,7 @@ Load when the user provides a FIX-XXX or BUG-XXX item, or asks for a focused hot
34
34
 
35
35
  - Every fix gets a regression signal or documented exception.
36
36
  - Blocking review findings are fixed in another TCR cycle.
37
- - Self-score note is required before exit.
37
+ - The Review Score is produced by the runner's fresh-session peer Reviewer — the agent does NOT self-score.
38
38
  - Docs/code/product alignment is a DoD gate: user-visible behavior, command, output-copy, site, or delivery-view changes update the touched README/docs/guide/site/help in the same delivery.
39
39
 
40
40
  ## Gotchas
@@ -397,7 +397,7 @@ Runs ONLY on a ✅ Gate PASS (a FAIL retry must not mint a misleading report). N
397
397
  ```
398
398
 
399
399
  No evidence for an AC → say `claimed` yourself; the renderer enforces that downgrade anyway (red line) and lists it under Discrepancies.
400
- 3. **Run** `roll attest {ID}` (add `--deploy-url <url>` when one exists). The report lands at `.roll/features/<epic>/{ID}/latest/{ID}-report.html` (archive-per-card layout, US-META-001). The report is now layered (US-ATTEST-013): card context + conclusion/business badges + key screenshots up front, technical ANSI/command output folded into collapsed `<details>`, and a closing block (quality gate + evidence index + self-score). A FIX usually carries a before/after pair (`screenshots/before-*.png` + `after-*.png`) — the坏态/好态 contrast is the clearest proof a bug is gone.
400
+ 3. **Run** `roll attest {ID}` (add `--deploy-url <url>` when one exists). The report lands at `.roll/features/<epic>/{ID}/latest/{ID}-report.html` (archive-per-card layout, US-META-001). The report is now layered (US-ATTEST-013): card context + conclusion/business badges + key screenshots up front, technical ANSI/command output folded into collapsed `<details>`, and a closing block (quality gate + evidence index + Review Score). A FIX usually carries a before/after pair (`screenshots/before-*.png` + `after-*.png`) — the坏态/好态 contrast is the clearest proof a bug is gone.
401
401
  4. **Design QA checklist (US-ATTEST-013) — READABILITY ONLY**. After the report
402
402
  renders, open it and run the checklist below. This is a presentation review of
403
403
  the rendered HTML, NOT an evidence review.
@@ -507,34 +507,22 @@ A minor change is only "done" when all are true:
507
507
  - [ ] Deployment completed
508
508
  - [ ] Online verification performed
509
509
  - [ ] **Verification Gate passed** (fresh evidence for tests, build, fix confirmation, no regression)
510
- - [ ] **Self-score note written (US-SKILL-010 / 011)** — before exit, the agent
511
- writes a structured score note via `roll self-score` so trend
512
- analysis (US-SKILL-014) and skill-self-scoring docs (US-SKILL-015) have
513
- data to read.
514
-
515
- ### Self-score (US-SKILL-011)
516
-
517
- Before exiting the cycle, ensure one score note lands. **Pair-first
518
- (US-PAIR-009/010): when `.roll/pairing.yaml` enables the `score` stage, the
519
- paired heterogeneous agent produces the score — self-score is the fallback,
520
- not the default.** Run from the main project root (the directory holding
521
- `.roll/`); the note lands under `.roll/features/<epic>/<FIX-id>/notes/<date>-roll-fix-<FIX-id>-<epoch>.md` (the card folder is the note home, US-META-008; epic resolution and the `.roll/notes/` fallback are built in):
522
-
523
- ```bash
524
- # 1. pair-first: ask the paired heterogeneous agent to score the cycle
525
- roll pair score FIX-XXX-NNN --summary "<one-paragraph delivery summary>"
526
- # 2. ONLY when the command prints a fallback hint (pairing off / no candidate /
527
- # timeout), write the self-score with the printed reason:
528
- roll self-score roll-fix FIX-XXX-NNN <score 1..10> <good|ok|regression> "<rationale>" --fallback-reason "<reason>"
529
- ```
530
-
531
- Both commands are idempotent — retrying after a transient failure is safe.
532
-
533
- > FIX-274: the TS-native `roll` is a bundled CLI and MUST NOT be sourced as a
534
- > bash library — the old `source`-based `_skill_write_self_score`
535
- > path is dead. Retrying after a transient failure is safe (idempotent).
536
-
537
- Score guidance (integer 1..10):
510
+ ### Review Score (FIX-343)
511
+
512
+ The Review Score is **not** produced by this skill. The fixing agent **does NOT
513
+ self-score**. The quality score is produced SOLELY by the runner's peer score
514
+ stage — a Reviewer running in a FRESH, separate session (never a sub-agent of
515
+ the builder's session). The agent's job is to deliver clean evidence (report +
516
+ ac-map + attest); the runner then casts a fresh-session Reviewer that mints the
517
+ Review Score (1..10 + verdict + rationale), recorded with `scoredBy` and the
518
+ fresh-session id so independence is verifiable.
519
+
520
+ Independence is about session/context, not vendor: a fresh same-vendor session
521
+ is the minimum acceptable; a different agent+model+session (non-sub-agent) is
522
+ encouraged (absolute heterogeneity). A score sharing the builder's session
523
+ (including any sub-agent of it) is rejected as a self-score.
524
+
525
+ Score guidance the Reviewer applies (integer 1..10):
538
526
  - **9..10** — clean root-cause fix; regression test added; TCR cycle smooth.
539
527
  - **6..8** — fix shipped but with caveats (e.g. workaround, partial coverage,
540
528
  or repeated TCR red iterations); rationale explains the trade-off.