| name | review-readiness-scan |
| description | 掃描 openspec/changes/ 各 change 的 manual-review 區塊,判斷哪些已 ready for 人工檢查、哪些被 Pre-Review Data Readiness pattern 命中(alert)尚未 ready,並把結果登記到 HANDOFF.md。Use when 使用者說「掃 review readiness」「review:ui 哪些 ready」「scan manual review alerts」「批次人工檢查前先看哪些 ready」「找出 review:ui 的 alert」。不適用於單一 change 內逐項 review(那走 `pnpm review` GUI,從 clade home 跑)。 |
| license | MIT |
| metadata | {"author":"clade","version":"1.0"} |
review-readiness-scan
主動掃描 consumer 端所有 active change 的 ## 人工檢查 區塊,把「已 ready / 尚未 ready」分組寫入 HANDOFF.md,讓使用者能在合適時機批次跑 pnpm review(從 clade home),而不是每條 change 個別開 GUI 才知道沒準備好。
前置:consumer 必須已從 clade 散播到 scripts/review-gui.mts(各 consumer 預設都有;若沒有,跑 pnpm hub:check 確認)。
Step 1 — 跑 headless scan
cd ~/offline/clade
node vendor/scripts/review-gui.mts --scan
預設從 clade home 掃,輸出會聚合 consumers.local 內所有 consumer + worktree。若是 CI / debug 要只掃單一 consumer,才改用 node vendor/scripts/review-gui.mts --repo <consumer-path> --scan。
reviewPort 會用跟 GUI server 相同的 fallback 規則計算:若 5174 已被占用,scan 會輸出下一個可用 port(例如 5175),後續 handoff MUST 使用 entry 內的 reviewUrl,不要硬寫 5174。
輸出 JSON(schema: review-readiness-scan/v2)到 stdout,結構:
{
"schema": "review-readiness-scan/v2",
"generatedAt": "<ISO8601>",
"repoRoot": "<abs>",
"reviewHost": "127.0.0.1",
"reviewPort": 5174,
"counts": {
"ready": N,
"notReady": M,
"buckets": { "ready": N, "readyForEvidence": N, "applyInProgress": N }
},
"ready": [ { "name": "<change>", "consumerId": "perno",
"changeKey": "perno:<change>", "reviewUrl": "http://127.0.0.1:5174/review/perno:<change>",
"bucket": "ready", "pending": N, "issued": N, "total": N } ],
"notReady": [ { "name": "<change>", "consumerId": "perno",
"changeKey": "perno:<change>", "reviewUrl": "http://127.0.0.1:5174/review/perno:<change>",
"bucket": "readyForEvidence", "pending": N, "issued": N, "total": N,
"readinessHits": N, "malformed": N,
"hitsByCode": { "UI_ITEM_NO_URL": 2, "REVIEW_UI_BACKEND_ROUNDTRIP": 1 },
"evidenceMissing": [ { "itemId": "#3", "description": "...",
"kinds": ["e2e", "api", "ui"] } ] } ],
"buckets": {
"ready": [ ],
"readyForEvidence": [ ],
"applyInProgress": [ ],
"applyBlocked": [ ],
"healthCheckNeeded": [ ],
"awaitArchiveWalkthrough": [ ],
"awaitingUserDecision": [ ],
"feedbackGiven": [ ]
}
}
Hono 沒裝 → script 會在 dynamic import 時報 missing dep。讓 user 跑 pnpm add -D hono,不要自動安裝。
Step 2 — Patch HANDOFF.md 固定 section
HANDOFF.md 用 marker 包夾,每次重跑覆蓋同一段(不累積垃圾,不留時戳 entries):
<!-- BEGIN: review-readiness-scan -->
## Manual Review Readiness(auto-scan)
> 最後掃描:<generatedAt> | ready: N not-ready: M | review: http://127.0.0.1:<port>
### ✅ 可以開始檢查(N changes)
可批次跑 `pnpm review`(從 clade home)處理;每行直接列 `reviewUrl`,不要重新手組 URL:
- `<changeKey>` — pending N/total — `<reviewUrl>`
- ...
### ⚠ 尚未準備好,需先補強(M changes)
下列 change 落這群的原因有兩種,依實際 entry 欄位分開列:
**(A) Pre-Review Data Readiness alert** — `readinessHits > 0`,**先補資料再 review**(patterns 詳見 `vendor/snippets/manual-review-enforcement/patterns.json`):
- `<changeKey>` — pending N · ⚠ N hits: UI_ITEM_NO_URL ×2, REVIEW_UI_BACKEND_ROUNDTRIP ×1 — `<reviewUrl>`
- ...
**(B) Verify-channel evidence missing** — `evidenceMissing.length > 0`,**跑 `/spectra-apply` Step 8a 補 evidence**:
- `<changeKey>` — pending N · ⚠ N item 缺 evidence (e2e ×2, api ×1, ui ×1) — `<reviewUrl>`
- ...
**(C) Apply 尚未完成 / feedback / archive walkthrough** — 依 `bucket` 分組列在同一 section 下,不要把這些 change 放進「可以開始檢查」:
- `applyInProgress` → 繼續 `/spectra-apply <change>`,不要補 Step 8a evidence
- `applyBlocked` → impl 卡外部 blocker(`@apply-blocked` marker),ball in user,**不要**硬推;解 blocker 後移除 marker 回 applyInProgress
- `feedbackGiven` → user 已在 GUI 留 issue 或 verify pending,交回 Claude 針對 issue 處理
- `awaitingUserDecision` → Claude 已標 `(awaiting-user-decision:)`,等 user 商業拍板,ball in user,**不要**硬推
- `awaitArchiveWalkthrough` → 跑 `/spectra-archive <change>` 觸發 Step 2.5 discuss walkthrough
- `crossWtDirty` / `malformed` → 先修 worktree routing 或 tasks.md 格式
<!-- END: review-readiness-scan -->
寫入規則
- HANDOFF.md 不存在:建立 HANDOFF.md 並把 section 放在檔尾
- HANDOFF.md 存在、有舊 marker:用 BEGIN/END 之間整段覆寫,保留 marker 外的所有內容
- HANDOFF.md 存在、無 marker:append 到檔尾(前面空一行)
- ready 與 notReady 都為 0:仍寫入 section,但內容改成
> 目前無含人工檢查區塊的 active change。,讓 user 看到 skill 跑過、不是漏跑
不該做
- ❌ 不要刪 HANDOFF.md 其他段落(即使看起來過時)
- ❌ 不要在 ready 段落 append 額外備註、推測 user 接下來該做什麼 — section 是純資料,主線判讀
- ❌ 不要因為 hitsByCode 命中某個 code 就自動修 tasks.md(修法走
/spectra-ingest,由 user 拍板)
Step 3 — 主線報告
寫完 HANDOFF.md 後,給 user 一段精簡 summary:
Scanned at <generatedAt>:
✅ Ready (N): consumer:change-a, consumer:change-b
⚠ Need fix (M): consumer:change-c (3 hits), consumer:change-d (1 evidence missing)
HANDOFF.md updated(section: Manual Review Readiness)。
Ready deep-links 已寫入 HANDOFF.md;需要 fix 的先看 bucket / hitsByCode 處理後再 rescan。
不要主動跑 /spectra-ingest、不要主動修 tasks.md、不要推薦 schedule。User 拍板下一步。
何時 NOT 觸發
- 使用者只想跑單一 change 的人工檢查 → 直接
cd ~/offline/clade && pnpm review,不需要 scan
- 使用者問「現在有哪些 active change」這類純列表 → 用
spectra list,scan 是 readiness 評估不是 change 列表
- consumer 沒有
openspec/changes/ 目錄(非 spectra 專案)→ scan 會輸出空,回 user 「此專案沒有 openspec/changes/,跳過」
邊界與已知限制
- Scan 只看
openspec/changes/<name>/tasks.md 的 ## 人工檢查 section,不讀 parked changes(spectra parked 那群會被排除)— 因為 parked 通常是暫存不在動的,readiness 評估無意義
- hitsByCode 用的 pattern 規格存在
vendor/snippets/manual-review-enforcement/patterns.json,與 review-gui banner、post-propose-manual-review-check.sh 共用同一份 source-of-truth
- 截圖資料夾數(screenshotTopicCount)不影響 readiness 判斷 — 截圖缺失屬於 GUI 內 banner(red verify-channel evidence-missing),不在 Pre-Review Data Readiness 範疇