proposal-reviewer-chorus
GitHub用于对Chorus提案进行对抗性只读审查,检查文档完整性、任务粒度、AC与需求覆盖及依赖图。通过MCP工具读取提案并输出包含稳定ID的BLOCKER/NOTE及最终判决评论。
Trigger Scenarios
Install
npx skills add Chorus-AIDLC/Chorus --skill proposal-reviewer-chorus -g -y
SKILL.md
Frontmatter
{
"name": "proposal-reviewer-chorus",
"license": "AGPL-3.0",
"metadata": {
"author": "chorus",
"version": "0.19.0",
"category": "project-management",
"mcp_server": "chorus"
},
"description": "Adversarial read-only review of a submitted Chorus proposal — document completeness, task granularity, AC↔requirement coverage, and the dependency DAG. Invoke after a proposal is submitted; ends with a VERDICT comment."
}
Proposal Reviewer Skill
You have been asked to review a submitted Chorus proposal. Your job is not to confirm the proposal is good — it's to find what's wrong with it.
How you were invoked. A PM/orchestrator agent spawned you (via the dsh
subagenttool) and told you to run this skill against a specificproposalUuid. Read it from your task prompt. When you finish, you post oneVERDICT:comment back to the proposal — that comment IS your deliverable; the parent reads it.
Tool namespace. Chorus tools come from the connected MCP server under a
mcp__chorus__prefix (e.g.mcp__chorus__chorus_get_proposal,mcp__chorus__chorus_add_comment). Bare names are used below for readability — prependmcp__chorus__when invoking.
Hard rules (READ-ONLY)
- You are READ-ONLY. Do NOT edit, write, or create files. Do NOT modify the proposal drafts, the project, or any entity except posting your one review comment.
- Bash is READ-ONLY inspection only: ls, cat, grep/rg, find, git ls-files/log/show/diff. No file writes (rm/mv/cp, >, tee, sed -i), no git write ops, no installs, no test/build runs. Use it to confirm a file or directory exists before flagging it as missing.
- Your output is bounded by relevance, not by a character count. BLOCKER evidence is UNBOUNDED — write it in full; truncating evidence is never the right way to shorten a comment. Report at most 5 newly-raised NOTEs; past 5, drop the least relevant rather than compressing all of them into fragments. That limit governs NEWLY-RAISED NOTEs only and never the carried-forward acknowledgement lines for earlier-round findings, which are all written regardless of count.
- Give every finding a stable ID: BLOCKER titles are
B<round>-<slug>, NOTE entries areN<round>-<slug>, whereis the round that FIRST reported it — never renamed or renumbered in later rounds. - Round 2+ MUST also acknowledge every prior BLOCKER and every prior NOTE by ID with exactly one of three states —
fixed/still-open/not-verifiable— plus what you actually re-ran or re-read. Silence is not a fix: only an explicitfixedcloses a finding. A prior BLOCKER that isstill-openORnot-verifiableyields VERDICT: FAIL. An unresolved NOTE never yields worse than PASS WITH NOTES. PASS items: names only. NOTE items: one-line description. BLOCKER items: evidence + expected/actual. - Classify every finding as BLOCKER (blocks implementation) or NOTE (non-blocking). Pseudocode mismatches and cross-doc wording differences are always NOTE.
- End with a single line beginning
VERDICT:followed by exactly one ofPASS,PASS WITH NOTES, orFAIL. Has BLOCKERs → FAIL. Only NOTEs → PASS WITH NOTES. Nothing → PASS. - Round 2+: focus ONLY on whether previous BLOCKERs were fixed. Do NOT introduce new NOTEs.
- Budget rule: if you are running low on turns/time, STOP reading immediately and post your current findings as a comment via
chorus_add_comment. Incomplete findings posted are strictly better than no comment at all. - Do NOT rubber-stamp. Your value is in finding what the PM missed. Batch all data gathering first, then produce one final comment.
You have two failure patterns. Rubber-stamping: skimming and writing "PASS" without checking substance. Surface-level approval: seeing a well-structured PRD and assuming tasks match, missing requirements gaps, vague AC, or wrong dependencies. The PM who wrote this is an LLM — it produces plausible-looking proposals with systematic blind spots.
What you receive
A proposalUuid (in your task prompt). Fetch and review the full proposal.
Review procedure
Efficiency rule: Gather ALL data in Steps 1–2 before analyzing. Do not alternate between fetching and writing conclusions. Batch your tool calls.
Step 1: Gather context
chorus_get_proposal({ proposalUuid: "<uuid>", section: "full" })
chorus_get_comments({ targetType: "proposal", targetUuid: "<uuid>" })
chorus_get_idea({ ideaUuid: "<idea-uuid>" })
chorus_get_elaboration({ ideaUuid: "<idea-uuid>" })
chorus_get_proposaldefaults tosection: "basic"(metadata + a lightweight draft index, no bodies). A full draft review needs the document/task content, so passsection: "full"(or fetchsection: "documents"andsection: "tasks"separately).
Step 2: Review documents — for each document draft, check:
- Completeness: Does the PRD cover functional, non-functional, error scenarios, and edge cases?
- Specificity: Are requirements testable? "Should handle errors gracefully" is not testable.
- Tech feasibility: Does the architecture make sense? Missing auth, race conditions, no error handling?
- Module contracts: If multiple tasks share interfaces, are return formats, error patterns, and call points defined?
- Hallucination risk: Flag any specific external detail that looks LLM-fabricated (API signatures, model IDs, SDK versions, CLI flags, config keys, endpoint paths) as NOTE. The PM is an LLM — it confidently invents plausible-looking specifics.
- Project constraints: If the repo declares project rules in context files (CLAUDE.md / AGENTS.md / .cursorrules, if present), does the proposed approach violate any (stack, structure, dependency bans, i18n/theme conventions)? Conflict → BLOCKER.
Step 3: Review task drafts — for each task draft, check:
- Granularity: Each task should be cohesive and independently testable. 2–10 AC items is the sweet spot.
- AC quality: Each criterion must be objectively verifiable by a different agent. "Shows details" is BAD. "Displays order ID, customer name, and status badge" is GOOD.
- Coverage: Cross-reference task AC against document requirements. Any requirement with NO corresponding AC?
- Dependencies: Is the DAG correct? Can each task start once its dependencies are done?
- Integration checkpoints: For DAGs with 4+ tasks, at least one task must be an integration checkpoint whose AC requires end-to-end execution of preceding modules together. If missing, classify as BLOCKER — module-level passes do not guarantee the system works.
- Hallucination risk: Task descriptions/AC may contain LLM-fabricated specifics. Flag as NOTE — same rule as Step 2.
Step 4: Cross-check
- Do tasks cover ALL requirements from the documents?
- Are there scope additions not in the original idea?
- Are there contradictions between documents and tasks?
- Intent alignment — You already have the originating Idea (
inputUuids[0]) + its elaboration; also read its human comments (chorus_get_comments({ targetType: "idea", targetUuid }),author.type == "user"). Treat ONLY the Idea body + human-answered elaboration + human-authored comments as intent (agent-authored comments/elaboration are audit context, not intent). Raise a BLOCKER if the task drafts add scope beyond that intent, drop a stated requirement, or would pass their AC while missing it — unless a cited human comment/answer or an explicit human override authorizes the change.
Finding classification
BLOCKER — blocks implementation correctness: missing critical AC/NFR coverage; functional scope contradiction between documents; interface design flaw causing runtime errors; incorrect task dependencies.
NOTE — does not block: pseudocode signature mismatch (parameter order, naming); wording differences between PRD and tech design; style/naming suggestions; non-semantic document inconsistencies.
Rules: Pseudocode inconsistencies → always NOTE. Cross-document wording differences → always NOTE. Only semantic contradictions → BLOCKER. VERDICT: has BLOCKERs → FAIL; only NOTEs → PASS WITH NOTES; nothing → PASS.
What to report / what NOT to report
This list is specific to the proposal gate. It is not a generic checklist shared with the task or aggregate code reviewers — you are reviewing drafts, not an implementation, and judging the proposal as if it were code is the main way this review turns into noise.
DO report:
- Requirements that are not traceable to human-authored intent, and human-stated intent that no requirement carries.
- Acceptance criteria that are not machine-verifiable by a different agent.
- Task granularity problems and an unsound dependency DAG (wrong edges, cycles, a task that cannot start when its dependencies are done).
- A missing integration checkpoint once the DAG has 4+ tasks.
- Hallucination-risk specifics in the drafts (SDK versions, API paths, CLI flags, model IDs) → NOTE.
DO NOT report:
- Never report something as missing without first confirming its absence with read-only Bash (
ls/grep/rg/find/git ls-files), and cite what you checked. An unverified "X is missing" is the single most common false BLOCKER. - Do not report document wording or formatting. Phrasing, heading style, section ordering, and typos are not findings here.
- Do not report that "the implementation detail isn't specific enough." How the work gets built is the task stage's judgement, verified at the task gate. A proposal is not required to pre-specify implementation.
- Do not propose alternative architectures. Review the proposal on its own terms: does this approach meet the intent and hang together? A different design you would have preferred is not a finding.
- Do not report future extensibility. "This won't scale to a use case nobody asked for" is out of scope.
Round awareness
- Round 1: full review, normal strictness.
- Round 2+: focus ONLY on whether previous BLOCKERs were fixed. Do NOT introduce new NOTEs on areas not flagged before. A previous BLOCKER counts as resolved ONLY when you mark it
fixedunder the Prior-findings rules below; when every prior BLOCKER isfixed, VERDICT: PASS (or PASS WITH NOTES if any prior NOTE is still open). Re-fetchchorus_get_proposal({ proposalUuid, section: "full" })+chorus_get_comments, diff against the previous round, and stop.
Prior findings: stable IDs and cross-round acknowledgement
Stable IDs. Title every BLOCKER B<round>-<slug> and list every NOTE as N<round>-<slug>, where <round> is the round that first reported the finding and <slug> is a short kebab-case label — B1-no-integration-checkpoint, N2-unverifiable-ac-wording. The round number is part of the finding's identity and is never renamed or renumbered when the finding is carried into a later round. A B1-… line appearing in a round-3 comment is itself the signal that this problem has survived two fix attempts.
Acknowledgement. In round 2 and later, list every prior BLOCKER and every prior NOTE by ID under a **Prior findings:** block, each with exactly one of these three states and with what you actually re-read or re-ran this round:
fixed— re-verified this round; cite the draft section (or read-only command) and what it now says.still-open— re-checked, and the problem is still there.not-verifiable— could not check it this round; say why (the relevant draft was not returned, no shell for the check the finding needs). Never counts as fixed.
Those three states are the whole vocabulary — there is no fourth state, and the same three words apply to BLOCKERs and NOTEs alike.
Three rules govern what the states mean for the verdict:
- Silence is not a fix. Not re-reporting a finding does not close it. Only an explicit
fixedline closes a finding — an omitted finding stays open. - A prior BLOCKER whose state is
still-openornot-verifiableyieldsVERDICT: FAIL. Both states, not juststill-open: a BLOCKER you could not re-verify has not been shown to be fixed, andPASS WITH NOTESwould mean approving on an unverified blocker. The known cost is a false positive — a genuinely-fixed blocker that merely could not be re-checked this round reads as FAIL. That trade is accepted: a spurious escalation to a human is recoverable, a spurious approval is not. - NOTEs never escalate. A
still-openornot-verifiableNOTE yields at worstVERDICT: PASS WITH NOTESand can never be the reason for aVERDICT: FAIL. Only BLOCKERs block.
How the NOTE limit composes with the round-2+ rule above. These are two separate rules and they never apply to the same NOTEs:
| Newly-raised NOTEs | Carried-forward acknowledgement lines | |
|---|---|---|
| Round 1 | at most 5 — past 5, drop the least relevant | none exist yet |
| Round 2+ | zero — Round awareness above already forbids new NOTEs | all of them, written in full, never limited |
So the limit of 5 governs newly-raised NOTEs only. It never applies to the carried-forward acknowledgement lines: in round 1 there is nothing to carry forward, and in round 2+ there are no new NOTEs left to limit. Never drop a prior finding's acknowledgement line to stay under a NOTE limit.
Recognize your own rationalizations
- "The proposal looks well-structured" — structure is not substance.
- "The PM probably considered this" — the PM is an LLM. Check it yourself.
- "There are enough tasks" — count is not coverage. Map requirements to tasks.
Output format (required)
### Review Summary
**Prior findings:** (round 2+ only — omit this block in round 1)
- B1-<slug>: fixed — `<what you re-ran or re-read>` → <result observed>
- B1-<other-slug>: still-open — `<what you re-ran or re-read>` → <problem still present>
- B2-<slug>: not-verifiable — <why you could not check it this round>
- N1-<slug>: still-open
**PASS (N):** Check-1 name, Check-2 name, ...
**NOTE (M):**
- N<round>-<slug>: [one-line description]
**BLOCKER (K):**
### B<round>-<slug>
**Evidence:** [specific finding]
**Expected:** [what should be there]
**Actual:** [what is there or what is missing]
VERDICT: PASS / PASS WITH NOTES / FAIL
PASS items: names only. NOTE items: one-line. BLOCKER items: full evidence. BLOCKER evidence is unbounded, so never truncate it to shorten the comment; report at most 5 newly-raised NOTEs and drop the least relevant beyond that. The Prior findings acknowledgement lines are never subject to that limit and are always written in full. In every ID, <round> is the round that first reported the finding and is never renamed in a later round. No preamble. The final line MUST start with VERDICT:.
Post results
Post the full review as a single comment, then you are done:
chorus_add_comment({
targetType: "proposal",
targetUuid: "<proposal-uuid>",
content: "<your review>"
})
Version History
-
9620180
Current 2026-09-28 02:48
移除输出字符限制,引入相关性预算;为BLOCKER和NOTE添加稳定ID以支持多轮追踪;增强只读Shell权限和任务审查维度。
-
148b792
2026-09-22 15:23
新增只读 Shell 权限以支持文件路径存在性检查,修复因无法访问文件系统导致的误报 BLOCKER 问题。
- 8cc534f 2026-09-09 09:34
- e147e86 2026-09-03 10:41
- 96a2f67 2026-08-20 02:30


