- name
- skill-slide-critic
- description
- Interactive critique loop for slide presentations. Delegates to slide-critic-agent, presents findings to user, collects accept/reject/modify decisions, produces filtered critique report.
- allowed-tools
- Agent, Bash, Edit, Read, Write, AskUserQuestion
- context
- fork
- agent
- slide-critic-agent
# Slide Critic Skill
Interactive critique feedback loop for academic presentations. Delegates to slide-critic-agent for
initial material review, parses the structured critique report, presents findings to the user grouped
by severity tier, collects accept/reject/modify decisions, loops until all issues are addressed, and
produces a final filtered critique report consumable by `/plan`.
**IMPORTANT**: This skill implements the skill-internal postflight pattern. After the subagent returns
and the interactive loop completes, this skill handles all postflight operations (status update,
artifact linking, git commit) before returning.
## Context References
Reference (do not load eagerly):
- Path: `.claude/context/formats/return-metadata-file.md` - Metadata file schema
- Path: `.claude/context/patterns/postflight-control.md` - Marker file protocol
- Path: `.claude/context/patterns/file-metadata-exchange.md` - File I/O helpers
- Path: `.claude/context/patterns/jq-escaping-workarounds.md` - jq escaping patterns (Issue #1132)
Note: This skill runs delegation then interactive Q&A. Context is loaded by the delegated agent.
## Trigger Conditions
This skill activates when:
- `/critique` command with task number input
- `/research` on a task with `task_type: "present:slides"` and `workflow_type: "slides_critique"`
- Present extension is available
- Task has existing slide materials to review (research reports, plans, or assembled slides)
---
## Input Parameters
### Required Parameters
- `task_number` - Task number (must exist in state.json with task_type containing "slides")
- `session_id` - Session ID from orchestrator
### Optional Parameters
- `focus_categories` - Subset of 6 rubric categories to prioritize (e.g., ["Narrative Flow", "Timing Balance"])
- `audience_context` - Audience description for calibrating review
- `materials_to_review` - Override default material discovery (array of file paths)
---
## Execution Flow
### Stage 1: Input Validation
Validate required inputs:
- `task_number` - Must be provided and exist in state.json
- Verify task_type contains "slides" (supports "present:slides", "slides")
```bash
# Lookup task
task_data=$(jq -r --argjson num "$task_number" \
'.active_projects[] | select(.project_number == $num)' \
specs/state.json)
# Validate exists
if [ -z "$task_data" ]; then
return error "Task $task_number not found"
fi
# Extract fields
task_type=$(echo "$task_data" | jq -r '.task_type // ""')
status=$(echo "$task_data" | jq -r '.status')
project_name=$(echo "$task_data" | jq -r '.project_name')
description=$(echo "$task_data" | jq -r '.description // ""')
forcing_data=$(echo "$task_data" | jq -r '.forcing_data // {}')
# Validate task_type (supports "present:slides" or legacy "slides")
if [ "$task_type" != "present:slides" ] && [ "$task_type" != "slides" ]; then
return error "Task $task_number is not a slides task (task_type=$task_type)"
fi
# Extract talk_type from forcing_data
talk_type=$(echo "$forcing_data" | jq -r '.talk_type // "CONFERENCE"')
```
---
### Stage 2: Preflight Status Update and Postflight Marker
Source `skill-base.sh` once, then follow `@.claude/context/patterns/skill-preflight-flow.md` in
full for Stage 2 (preflight status update) and Stage 3 (marker creation):
```bash
source .claude/scripts/skill-base.sh
padded_num=$(printf "%03d" "$task_number")
task_dir="specs/${padded_num}_${project_name}"
mkdir -p "$task_dir"
skill_name="skill-slide-critic"
operation="research"
```
`operation="research"` (not `"slides_critique"`) is required here: `update-task-status.sh`'s
`target_status` vocabulary has no `slides_critique` value, so this skill maps onto the plain
`research` operation (this skill is invoked from `/research` on `workflow_type: "slides_critique"`
tasks). The marker's `operation` field now reads `"research"` rather than `"slides_critique"`.
---
### Stage 3: Prepare Delegation Context
Discover materials to review (if not provided via `materials_to_review`):
```bash
# Auto-discover materials in task directory
report_files=$(ls -1 "${task_dir}/reports/"*.md 2>/dev/null)
plan_files=$(ls -1 "${task_dir}/plans/"*.md 2>/dev/null)
# Check for assembled slides
talk_dir="talks/${task_number}_${project_name}"
slide_files=$(ls -1 "${talk_dir}/slides.md" 2>/dev/null)
```
Build the materials array from discovered files, or use the `materials_to_review` parameter if provided.
**Delegation context**:
```json
{
"session_id": "{session_id}",
"delegation_depth": 1,
"delegation_path": ["orchestrator", "critique", "skill-slide-critic", "slide-critic-agent"],
"timeout": 3600,
"task_context": {
"task_number": N,
"task_name": "{project_name}",
"description": "{description}",
"task_type": "present:slides"
},
"workflow_type": "slides_critique",
"forcing_data": {
"talk_type": "{talk_type}",
"materials_to_review": ["{discovered or provided paths}"],
"focus_categories": "{focus_categories or omitted}",
"audience_context": "{audience_context or omitted}"
},
"metadata_file_path": "specs/{NNN}_{SLUG}/.return-meta.json"
}
```
---
### Stage 4: Invoke Subagent
**CRITICAL**: Use the **Agent** tool to spawn the slide-critic-agent. Do NOT use `Skill(...)`.
```
Tool: Agent (NOT Skill, NOT Plan)
Parameters:
- subagent_type: "slide-critic-agent"
- prompt: [Include full delegation context from Stage 3]
- description: "Critique presentation materials for task {N}"
```
The slide-critic-agent will:
1. Load the critique rubric and priority matrix
2. Read all review materials
3. Evaluate against 6 rubric categories (or focus_categories)
4. Write a critique report to `specs/{NNN}_{SLUG}/reports/{MM}_slide-critique.md`
5. Write metadata to `specs/{NNN}_{SLUG}/.return-meta.json`
**DO NOT** use `Skill(...)` - this will FAIL. Always use `Task`.
---
### Stage 4b: Self-Execution Fallback
**CRITICAL**: If you performed the work above WITHOUT using the Agent tool (i.e., you read files,
wrote artifacts, or updated metadata directly instead of spawning a subagent), you MUST write a
`.return-meta.json` file now before proceeding. Use the schema from `return-metadata-file.md`
with status `researched`.
If you DID use the Agent tool, skip this stage -- the subagent already wrote the metadata.
---
## Interactive Critique Loop (Stages 5-7)
### Stage 5: Parse Critique Report
After the subagent returns, read the critique report and extract findings.
1. **Read metadata file** to get the critique report path:
```bash
metadata_file="${task_dir}/.return-meta.json"
meta_status=$(jq -r '.status' "$metadata_file")
critique_report_path=$(jq -r '.artifacts[0].path // ""' "$metadata_file")
findings_count=$(jq -r '.metadata.findings_count // {}' "$metadata_file")
```
2. **If agent failed or no findings**: Skip the interactive loop. Proceed directly to postflight with the agent's status.
3. **Read the critique report** and parse findings using these patterns:
**Per-slide heading**: `### Slide N ({slide_type})`
**Finding line**: `- [{severity}] {category}: {description}`
**Suggestion line**: `Suggested improvement: {text}` (indented under finding)
**General heading**: `### General (Cross-Cutting)`
**Recommendation tiers**: `### Must Fix`, `### Should Fix`, `### Nice to Fix`
4. **Build numbered issue list**:
```
issues = [
{ id: 1, slide: "Slide 3", severity: "Critical", category: "Narrative Flow",
description: "...", suggestion: "...", tier: "Must Fix" },
{ id: 2, slide: "Slide 7", severity: "Critical", category: "Audience Alignment",
description: "...", suggestion: "...", tier: "Must Fix" },
{ id: 3, slide: "General", severity: "Major", category: "Timing Balance",
description: "...", suggestion: "...", tier: "Should Fix" },
...
]
```
Assign tier based on severity:
- Critical -> "Must Fix"
- Major -> "Should Fix"
- Minor -> "Nice to Fix"
5. **If no findings found in report** (agent found no issues): Report success with zero findings. Skip interactive loop.
---
### Stage 6: Interactive Critique Loop
Present all findings grouped by severity tier in a single consolidated AskUserQuestion.
Collect user decisions and loop until all issues are addressed or user exits.
**AskUserQuestion format**:
```
Critique findings for your {talk_type} presentation ({N} total issues):
=== MUST FIX ({count}) ===
1. [Critical] {category} - {slide}: {description}
Suggested: {suggestion}
2. [Critical] {category} - {slide}: {description}
Suggested: {suggestion}
=== SHOULD FIX ({count}) ===
3. [Major] {category} - {slide}: {description}
Suggested: {suggestion}
4. [Major] {category} - {slide}: {description}
Suggested: {suggestion}
=== NICE TO FIX ({count}) ===
5. [Minor] {category} - {slide}: {description}
Suggested: {suggestion}
---
For each issue, respond with its number and action:
1: A (accept as-is)
3: R (reject/dismiss)
5: M add comparison to Smith 2024 (modify the suggestion)
Shortcuts: "accept all", "reject all minor", "done" (accept remaining)
```
**Response parsing grammar**:
Parse user response line by line. Each line matches one of:
| Pattern | Action | Effect |
|---------|--------|--------|
| `{N}: A` | Accept issue N | Mark as accepted, use original suggestion |
| `{N}: R` | Reject issue N | Mark as rejected/dismissed |
| `{N}: M {text}` | Modify issue N | Mark as modified, store user's text |
| `accept all` | Bulk accept | Accept all unaddressed issues |
| `reject all minor` | Bulk reject minor | Reject all Minor severity issues |
| `reject all` | Bulk reject | Reject all unaddressed issues |
| `done` | Finish | Accept all remaining unaddressed issues |
Track decisions per issue:
```
decisions = {
1: { action: "accepted", modification: null },
3: { action: "rejected", modification: null },
5: { action: "modified", modification: "add comparison to Smith 2024" },
...
}
```
**Loop continuation**:
After processing responses:
- If all issues are addressed (each has an accepted/rejected/modified decision): proceed to Stage 7
- If unaddressed issues remain AND user did not say "done": re-present ONLY unaddressed issues in a follow-up AskUserQuestion
- Maximum 3 loop iterations to prevent infinite cycles. After 3 iterations, auto-accept all remaining unaddressed issues.
---
### Stage 7: Generate Filtered Critique Report
Write the final filtered report incorporating user decisions.
Determine artifact number:
```bash
next_num=$(jq -r --argjson num "$task_number" \
'.active_projects[] | select(.project_number == $num) | .next_artifact_number // 2' \
specs/state.json)
# Use next available number for the filtered report
filtered_num=$(printf "%02d" "$next_num")
```
Write to `specs/{NNN}_{SLUG}/reports/{MM}_filtered-critique.md`:
```markdown
# Filtered Critique Report: {title}
在 GitHub 查看