Speclet Council Skill
Run a council review over a draft, spec, or ticket input, then emit audit artifacts.
What I Do
- Validate the target input exists (
draft.md,spec.json, or a ticket file) - Invoke two reviewers (GPT, GLM) in parallel with per-reviewer timeouts and retries
- Collect critiques and generate a Review Status Header (succeeded vs. failed models)
- Synthesize feedback using Thematic Clustering and collapsible HTML tags
- Write
.speclet/council-session.mdand.speclet/council-summary.md - Write optional
.speclet/draft.review.md(full Council Review) - Support
--dry-runmode with mocked reviewer outputs
When to Use Me
Use this after a target exists and before conversion/implementation:
Use the speclet-council skill
Supported Targets
- Draft:
.speclet/draft.md(default) - Spec:
.speclet/spec.jsonor an explicit spec path - Ticket:
.speclet/tickets/<TICKET-ID>/draft.mdorticket-draft.md
Example Invocations
Use the speclet-council skill
Use the speclet-council skill for .speclet/spec.json
Use the speclet-council skill for .speclet/tickets/TICKET-1/draft.md
If the user says "use speclet-council to review this spec.json" or "review this ticket", treat the referenced file as the target input.
Setup (Required)
Reviewers must be configured in your oh-my-opencode.json:
plan-reviewer-gpt(implementability)plan-reviewer-glm(clean design and completeness)
Only these two reviewers are used by this skill.
Each agent should be configured to use a distinct model in your OpenCode config (for true multi-model reviews). If they all point to the same model, the council will run but not be multi-model.
Permissions (recommended):
read: allowwebfetch: allow (optional)edit: denybash: denycall_omo_agent: denybackground_task: allow (only for the orchestrator)
Do not edit oh-my-opencode.json from this repo; document this setup for the user.
Inputs
- Target input (default:
.speclet/draft.md) - Reviewer prompts in
skills/speclet-council/prompts/
Outputs
.speclet/council-session.md(full audit log).speclet/council-summary.md(executive summary).speclet/draft.review.md(optional full review)
Note: Always read existing artifact files before writing to avoid OpenCode validation errors. Artifacts are written regardless of target type.
Your Task
Step 1: Validate Target Exists
Default target is .speclet/draft.md unless a path is provided by the user.
Supported targets:
.speclet/draft.md.speclet/spec.json.speclet/tickets/<TICKET-ID>/draft.mdorticket-draft.md
If missing, fail with:
❌ Missing target file
Provide a valid draft/spec/ticket path before using speclet-council.
Step 2: Load Reviewer Prompts
Use these prompt templates:
skills/speclet-council/prompts/reviewer-gpt.mdskills/speclet-council/prompts/reviewer-glm.md
Each prompt defines a strict output contract. Do not embed the target content in the orchestration prompt; instruct reviewers to read the target path directly. Orchestration prompts must be in English.
If the target is spec.json, reviewers should focus on story sizing, acceptance criteria verifiability, file lists, and non-goals.
If the target is a ticket draft, reviewers should focus on scope isolation, missing requirements, and ticket metadata alignment.
Step 3: Parallel Review Invocation
Launch all reviewers in parallel using background_task.
Pseudo-flow:
typescript1for (const reviewer of ["gpt", "glm"]) { 2 background_task( 3 agent=`plan-reviewer-${reviewer}`, 4 description=`Council Review: ${reviewer}`, 5 prompt=`[ENGLISH INSTRUCTIONS ONLY]\n\nPlease read the target file and respond in the target's language.` 6 ); 7}
Defaults:
- Per-reviewer timeout: 500s
- Max retries: 3
- Backoff: 1s → 2s → 4s
Step 4: Classify Errors and Retry
Retry only for transient errors. If using background_task, monitor the task status via background_output.
Transient errors:
- Timeouts
- Rate limit / 429
- Temporary network failures
Do not retry for:
- Invalid model name
- Permission denied
- Missing agent configuration
If a reviewer fails after max retries, record the failure and continue.
Step 5: Collect Results
Retrieve each task with background_output(task_id="...", block=true) and map it back to its reviewer.
Note: Ensure you wait for all tasks to complete or timeout before proceeding to synthesis.
Review Status Header: Generate a summary table or list showing the status of each reviewer.
- ✅ [Model Name] (Success)
- ⚠️ [Model Name] (Failed/Timeout)
If zero reviewers succeed, fail with:
❌ All reviewers failed
Check API keys, network, or agent configuration. Try again or reduce the reviewer set.
If any reviewer fails due to missing agent configuration, include a reminder to install or configure agents as described in the Setup section.
Step 6: Synthesize Council Review
Use a specialized synthesis prompt to consolidate all issues using Thematic Clustering:
- Thematic Grouping: Identify shared problems across reviewers and group them under a single descriptive heading.
- Nuance Preservation: Do NOT delete unique details. If Reviewer A found a race condition and Reviewer B found a general concurrency limit in the same area, list them both as distinct perspectives under the same theme.
- UX Formatting: Use HTML
<details>and<summary>tags. The summary MUST contain the severity (🔴 HIGH, 🟡 MEDIUM, 🟢 LOW) and the theme title. - Reviewer Attribution: Clearly state which models identified each issue.
- Language Parity: Detect the language of the target and ensure the synthesis matches it exactly.
- HTML Integrity: Ensure all
<details>blocks are correctly opened and closed.
Before writing any artifacts, read the existing files (if any) to avoid OpenCode read-before-write violations.
Write the full Council Review into .speclet/draft.review.md (not into the target file).
markdown1# Council Review 2 3### Status 4- ✅ plan-reviewer-gpt 5- ✅ plan-reviewer-glm 6 7<details> 8<summary>🔴 HIGH: [Theme Title]</summary> 9 10- **Reviewers:** GPT, GLM 11- **Problem:** [Consolidated description of the theme] 12- **Specific Notes:** 13 - **Opus:** [Unique architectural nuance] 14 - **GPT:** [Unique implementation detail] 15- **Consolidated Suggestion:** [Actionable fix merging both suggestions] 16</details>
Step 7: Write Council Artifacts
Write .speclet/council-session.md with a deterministic audit log (include the target path in the header):
markdown1# Council Session 2 3- Target: path/to/target 4- Started: YYYY-MM-DD HH:MM 5- Finished: YYYY-MM-DD HH:MM 6 7## Review Tasks 8- plan-reviewer-gpt 9 - task_id: <id> 10 - status: success|failed 11 - attempts: N 12 - error: [if failed] 13- plan-reviewer-glm 14 - task_id: <id> 15 - status: success|failed 16 - attempts: N 17 - error: [if failed] 18 19## Critiques 20### plan-reviewer-gpt 21[raw critique output] 22 23### plan-reviewer-glm 24[raw critique output]
Write .speclet/council-summary.md as an executive summary (read the file first if it already exists):
markdown1# Council Summary 2 3- Total issues: N 4- By severity: High H / Medium M / Low L 5- By reviewer: gpt X / glm Y 6 7## Decisions 8- Accepted: [list] 9- Rejected: [list] 10- Deferred: [list] 11 12## Draft Changes 13- Council Review saved to .speclet/draft.review.md
Step 8: Git Commit Rule
Do not create commits unless the user explicitly asks.
Step 9: Dry-Run Mode
When invoked with --dry-run:
- Do not call external models
- Use mocked reviewer outputs embedded in the skill
- Still write council-session.md, council-summary.md, and draft.review.md
Use this to validate the workflow without API costs.
Notes
- This skill never modifies the target file; use /speclet-consolidate to merge accepted feedback when reviewing drafts.
- English-First Protocol: Internal orchestration prompts and background task instructions are in English for reliability, but final user-facing output matches the target's language.
- Webfetch policies can only be enforced via reviewer prompts or disabled in agent config.