name: reposix-quality-review
description: "Run subjective rubric checks (cold-reader hero clarity, install positioning, headline-numbers sanity) by dispatching one unbiased subagent per stale catalog row in parallel. Reads quality/catalogs/subjective-rubrics.json, persists JSON artifacts to quality/reports/verifications/subjective/.json. The next runner sweep re-grades the catalog rows. Pre-approved for v0.12.0 P61 per .planning/research/v0.12.0/open-questions-and-deferrals.md line 124."
argument-hint: "[--rubric ] [--all-stale] [--force]"
allowed-tools:
- Bash
- Read
- Task
Default invocation modes:
--rubric <id>-- dispatch one rubric (used byquality/runners/run.pyvia the catalog row'sverifier.scriptfield).--all-stale-- dispatch every rubric whose rowis_staleORlast_verified=null(parallel per OP-2).--force-- dispatch every rubric regardless of freshness (manual on-demand mode).- (no args) -- print usage + the 3 seed rubrics with their stale status.
Cross-references:
- Catalog:
quality/catalogs/subjective-rubrics.json - Dimension home:
quality/gates/subjective/README.md - Rubric prompts:
.claude/skills/reposix-quality-review/rubrics/<id>.md - Cold-reader rubric integrates
$HOME/.claude/skills/doc-clarity-review/SKILL.md(Wave D).
Reject unknown rubric IDs with a clear error naming the 3 valid IDs.
For --rubric mode: find the row by id; load .claude/skills/reposix-quality-review/rubrics/<slug>.md as the rubric prompt body; expand the row's sources field into a concrete file list.
For --all-stale: filter the catalog to rows where is_stale(row, now) returns True OR last_verified is null. Build a list of (rubric-id, prompt-path, sources) tuples.
For --force: include ALL rows regardless of freshness.
Construct the subagent prompt: "You have ZERO session context. You are an unbiased reviewer. Read these files:
- . Apply this rubric: <prompt body from rubrics/
.md>. Output JSON with shape {score: int 1-10, verdict: 'CLEAR'|'NEEDS-WORK'|'CONFUSING', rationale: str, evidence_files: [str]}."Path A (preferred) -- if the Task tool is available in the calling Claude session: dispatch via
Task({subagent_type: 'general-purpose', prompt: <prompt>}). For--all-stale+--forcemodes, dispatch all rubrics IN PARALLEL (one Task per rubric in a single tool-call block; the harness handles concurrency). This is the OP-2 case: rubrics are independent; subagents share no state.Path B (fallback) -- if Task is not available (the runner subprocess invocation typically lacks Task): emit a stub artifact (
score=0, verdict=NOT-IMPLEMENTED, dispatched_via=Path-B-runner-subprocess). The runner re-grade will mark the row FAIL; Wave G's full-skill dispatch (with Task tool) re-runs and produces the real artifact.Special case (cold-reader rubric) -- the cold-reader rubric's implementation is the existing
doc-clarity-reviewglobal skill. Instead of constructing a custom subagent prompt, invoke/doc-clarity-review --prompt <cold-reader-prompt> README.md docs/index.md. Parse the_feedback.mdoutput for the verdict + score (CLEAR=10, NEEDS-WORK=5, CONFUSING=2).
Capture each subagent's JSON output for the persist step.
{
"ts": "<RFC3339-UTC>",
"rubric_id": "subjective/<slug>",
"score": 7,
"verdict": "CLEAR",
"rationale": "<one paragraph>",
"evidence_files": ["README.md:1-50", "docs/index.md:1-50"],
"dispatched_via": "Path A subagent" | "Path B in-session" | "doc-clarity-review",
"asserts_passed": ["..."],
"asserts_failed": [],
"stale": false
}
The skill computes asserts_passed + asserts_failed from the rubric's expected.asserts field (catalog row).
The skill does NOT write the catalog row's status directly. The next quality runner sweep reads the artifact and updates status per compute_exit_code semantics. Single-writer invariant matches quality/runners/run.py:run_row.
For --all-stale + --force: print a summary table (rubric | score | verdict). Exit 0 iff every rubric exited 0; exit 1 otherwise.