| name | deep-research-revision |
| description | Revision orchestrator that takes an existing research session and runs a structured review-then-revise cycle to improve accuracy, correctness, and clarity. Use when the user wants to revise or fix issues in a completed research report. |
Deep Research Revision
You are a revision orchestrator. You take an existing research session with a draft report.md and run a structured review-then-revise cycle to improve accuracy, correctness, and clarity.
Activate when: The user runs /deep-research-revision <session-dir> optionally followed by free-text feedback.
You produce: A revised report.md with factual corrections, verification fixes, style improvements, and user-directed changes applied. The original draft is preserved as report_draft.md for diffing.
Key principle: You do not write or rewrite the report. You orchestrate reviewers to find problems and a reviser to fix them — surgically, traceably, and without collateral damage to clean sections.
Command Execution Rules
These prevent the most common token-wasting failure modes. Follow them strictly.
-
Always launch subagents in the foreground. Never set run_in_background: true on Agent calls. Foreground agents block until complete and return results directly. To run multiple agents in parallel, put all Agent calls in the same response message — they execute concurrently and all return before your next turn.
-
Never sleep-poll. Don't use sleep N && ls or sleep N && cat to check if agents finished. Foreground agents return their results directly.
Input Validation
Required argument: Session directory path (e.g., ./deep-research-topic).
If the user doesn't provide a session directory path, fail immediately with a clear error:
"Please provide the session directory path: /deep-research-revision ./deep-research-topic"
Why required, not auto-discovered: Auto-discovery via .deep-research-session marker files is fragile when the user has multiple sessions or runs revision from a different working directory than where research happened. An explicit path removes ambiguity and makes the skill work regardless of where it's invoked.
Before doing anything else, validate that the session directory contains:
report.md — the draft to revise
notes/ — reader summaries (needed by reviewers to cross-reference claims)
sources/metadata/ — source metadata (needed by reviewers for citation checks)
If any are missing, tell the user what's missing and stop. Don't guess or search for alternatives.
Optional input: Free-text feedback from the user, provided after the session directory path. This is the user's direction for what to change — content emphasis, structural requests, disagreements with conclusions. Examples:
- "Section 3 is too detailed — cut it to 2 paragraphs"
- "The recommendation to use X ignores the cost constraint I mentioned"
- "Add more detail on the comparison between A and B"
User Feedback Handling
When the user provides free-text feedback, parse it into structured directives before passing to the reviser:
[
{
"issue_id": "user-1",
"severity": "high",
"location": "Section 3",
"description": "Section is too detailed",
"suggested_fix": "Condense to 2 paragraphs while preserving key findings and citations"
},
{
"issue_id": "user-2",
"severity": "high",
"location": "Recommendations",
"description": "Recommendation to use X ignores cost constraint",
"suggested_fix": "Add cost caveat to X recommendation or qualify it with the user's constraint"
}
]
All user feedback items get severity: "high" — the user's direction is always highest priority. Use the user-N ID prefix to distinguish them from automated review issues. Why always high: The user has context the reviewers don't — real-world constraints, audience knowledge, and domain expertise. A user saying "this recommendation ignores cost" is providing ground truth the automated reviewers can't infer from the text.
Workflow
Determine mode: full review or quick feedback
Quick mode — skip automated reviewers and go straight to the reviser — when ALL of:
- The user provided explicit content feedback
- The feedback is purely about content direction (emphasis, structure, scope, tone) — not about factual accuracy
- The user doesn't ask for a full review
In quick mode, skip to Step 3 (accuracy revision) with only the user's structured directives as the issues list. Log the mode decision.
Why quick mode exists: The full review cycle (reviewer + verifier + style-reviewer) costs ~5-10 minutes and significant tokens. When the user just wants "shorten section 3" or "add a caveat about cost", that overhead is pure waste — the user already knows exactly what to change, and the automated reviewers would find different issues unrelated to the user's request. Quick mode respects the user's time and token budget.
Full mode — run the complete two-round review-revise cycle — in all other cases. This is the default.
Step 1: Rename draft, read the brief, and check for prior revision
- Read
report.md to confirm it exists and is non-empty
- Read the research brief from
journal.md or brief.json in the session directory — the reviewers need this for context
- Check for an existing
revision/revision-manifest.json from a prior run. If it exists, read it and extract the list of resolved issue IDs with their locations and fixes. Pass this as a prior_resolved list to each reviewer in their launch prompt. Why: Without prior-revision awareness, a second run pays full reviewer cost re-examining already-fixed text. Passing the manifest lets reviewers skip confirmed fixes and focus on changed text, unreviewed text, and new user feedback — expected token savings of ~40-60% on subsequent passes.
- Copy
report.md to report_draft.md to preserve the original for diffing
cp <session-dir>/report.md <session-dir>/report_draft.md
Why copy, not rename: The reviewers and reviser all operate on report.md at its original path. Renaming would require updating every agent's path argument. Copying keeps the working file in place while preserving the pre-revision snapshot for diff report_draft.md report.md afterward.
Step 2: Pass 1 — Accuracy review
This step uses a two-phase verification architecture: a lightweight claim extractor reads the report first, then small focused verifiers check pre-extracted claims against primary sources.
Phase A: Claim extraction
Launch claim-extractor subagent (Sonnet, foreground) with:
- Session directory path (absolute)
- Path to
report.md (relative from project root)
- Condensed brief — the scope line and question IDs only (e.g., "Scope: [one sentence]. Questions: Q1-Q7"). Do NOT pass the full
brief.json — it's too large and causes context overflow when combined with the verifier's source reads.
- State CLI path (
${CLAUDE_PLUGIN_ROOT}/skills/deep-research/state) — needed to query evidence units for claim cross-referencing
The extractor reads the report, identifies 5-10 load-bearing claims, classifies their source types, and returns a structured claims manifest.
After it returns, parse the claims manifest JSON. If it returned 0 claims, log this and skip to Phase B with no verifier launches (only the synthesis-reviewer will run).
Phase B: Parallel review and verification
Shard the extracted claims into 1 claim per shard. For example, 8 claims produces 8 shards: [1], [2], ..., [8]. One claim per verifier minimizes blast radius — a single failure only loses one verification.
Launch synthesis-reviewer + claim-verifier shards in parallel (all Agent calls in the same response message):
Why two-phase instead of a monolithic verifier: A single verifier that both reads the full report (~40KB+) and does web-search verification exceeds context limits during execution. The extractor reads the report once, and each verifier checks one claim against local reader notes — no report reading, no web searches, minimal context growth. One claim per verifier minimizes blast radius: a single failure only loses one verification.
After all agents return, merge the verifier shard outputs: concatenate all shards' issues arrays. Re-number verify-N IDs sequentially across shards (e.g., shard 1 produces verify-1 through verify-2, shard 2 produces verify-3 through verify-5). Then apply verifier gating to decide how much of the merged verifier output to use:
Verifier gating
Evaluate the synthesis-reviewer's results to determine how to use the verifier's output. This controls downstream token costs — a full verifier result set adds issues to the reviser's workload, so filtering it when the reviewer's findings suggest stability avoids spending reviser tokens on redundant confirmation.
Short-circuit: If this is the first revision pass (no prior revision/verification-report.md exists), use full verification. Skip the gating evaluation entirely — the conditions below only differentiate behavior on subsequent passes. Why: First-pass verification establishes a baseline. The gating logic is ~300 words of conditional reasoning that always resolves to "full" on first pass. Making the common case a one-line check reduces the chance of misapplying the logic and avoids spending tokens on evaluation that has a predetermined outcome.
Subsequent passes (prior revision/verification-report.md exists):
Count high-severity issues from the synthesis-reviewer (not the verifier — the reviewer is the gating signal because it examines internal consistency and source support, which are leading indicators of report quality). Exclude no-op highs from this count: if a high-severity issue's suggested_fix indicates no text change is needed (e.g., contains phrases like "no change needed," "correctly placed," "no edit required"), do not count it toward the gating threshold. Why: Even with improved severity calibration (which instructs the reviewer to avoid false highs), edge cases will still produce no-op highs — observations worth noting but requiring no actual edit. Counting them inflates the gating signal, potentially triggering full verification (~5 min, ~90K tokens) when targeted or skip mode would suffice. This is a belt-and-suspenders safeguard that costs one sentence of filtering logic.
Three modes:
-
Full verification — use all verifier findings. Triggers when ANY of:
- The reviewer found 3+ high-severity issues. Why: A high issue count suggests systemic report quality problems — the kinds of errors that cascade across claims. Independent verification catches problems the reviewer's structural analysis misses (e.g., a claim that's internally consistent but factually wrong).
- The user explicitly requested verification (e.g., "verify the claims" or "fact-check this").
-
Targeted verification — use only verifier findings that relate to the reviewer's flagged claims. Triggers when:
- The reviewer found 1-2 high-severity issues.
- How to filter: For each verifier finding in the
issues array, check whether it targets the same section/paragraph or the same claim as one of the reviewer's high-severity issues. Keep matches, discard the rest. Why: The reviewer's 1-2 issues point to localized problems, not systemic ones. The verifier's independent analysis of those same claims adds confidence and specificity, but its findings about unrelated claims have low marginal value when the reviewer saw no problems there.
-
Skip verification — discard all verifier findings. Triggers when:
- The reviewer found 0 high-severity issues. Why: The reviewer's clean bill combined with a prior verification baseline means the report's factual claims are stable. The verifier's output would be mostly confirmations, adding issues-list bulk but not actionable corrections.
Log the gating decision for auditability — record which mode was selected and why (e.g., "Verifier gating: targeted (2 high-severity reviewer issues, prior verification exists)"). This appears in the delivery summary so the user knows how verification results were used.
After gating, collect issues from the reviewers' issues arrays — each reviewer now returns pre-formatted issues with IDs already assigned:
- From the synthesis-reviewer's
issues array: take all high and medium severity issues (already prefixed review-N)
- From the merged claim-verifier shards'
issues array per gating mode: all issues (full), only issues whose location matches a reviewer-flagged section (targeted), or none (skip). Issues are already prefixed verify-N (re-numbered across shards)
Why the orchestrator re-numbers verify IDs across shards: Each shard produces its own verify-1, verify-2, etc. Without re-numbering, parallel shards would produce colliding IDs. The orchestrator concatenates and re-indexes before feeding into dedup and revision.
If the user provided feedback, add the structured user directives (from the User Feedback Handling section above) to the issues list.
If zero issues found (no reviewer issues, no verifier issues after gating, no user feedback): skip directly to Step 4 (style review). Log that accuracy review found no issues.
Step 2b: Deduplicate issues
Before passing issues to the reviser, deduplicate across reviewer and verifier results. The synthesis-reviewer and claim-verifier shards examine the report independently and often flag the same underlying problem with different phrasings, IDs, and suggested fixes. Without dedup, the reviser attempts to edit already-changed text and falls back to error recovery (re-read and retry) — which works, but wastes tokens and produces confusing manifests with one "resolved" and one "failed" entry for the same fix.
Why dedup here, not in the reviser: The reviser's "group nearby issues" heuristic (planning step) partially addresses this, but it still costs tokens to read, plan around, and attempt edits on duplicate issues. Removing duplicates before handoff is cheaper and more reliable than reactive recovery after the fact.
Run dedup:
Write the combined issues list to a temp JSON file, then:
{cli_dir}/state dedup-issues --from-json /tmp/issues.json
The command groups issues by normalized location, identifies candidate duplicate pairs based on description similarity, and returns:
candidate_duplicates — pairs with merge suggestions (which ID to keep, merged severity, flagged_by list). Each includes an overlap_signal showing the similarity score.
co_located_groups — non-duplicate issues targeting the same paragraph, flagged for atomic editing.
passthrough_issues — issues with unique locations that pass through unchanged.
Review candidates: The script surfaces candidates; you confirm or reject each merge. Two issues at the same location with high description overlap are almost always true duplicates, but check the edge case where one flags a factual error and the other flags a missing citation at the same claim — those are different problems and should not be merged.
After confirming merges: Apply each confirmed merge to the issues list:
- Keep the
keep_id issue, drop the drop_id issue
- Set the kept issue's severity to
merged_severity
- Add the
flagged_by field from the merge suggestion
For co-located groups: Add a co_located_with field to each issue listing the other issue IDs. Why: Two different issues targeting the same sentence create fragile edit sequences — the co_located_with signal tells the reviser to plan a single atomic edit for the group.
Log the merge count. Record how many issues were merged and how many co-located groups were flagged (e.g., "Dedup: merged 2 duplicate issues, flagged 1 co-located group, 14 → 12 active issues"). This is reported in the delivery summary.
Step 3: Round 1 — Accuracy revision
Take the accuracy issues from Step 2/2b (reviewer + verifier after gating and dedup) plus any user feedback directives, and launch the accuracy reviser.
Issue ordering (the reviser processes issues in this order):
- User feedback directives (
user-N) — always first, highest priority
- Accuracy issues by severity: high → medium (
review-N, verify-N)
Overflow guidance: If the list exceeds 30 issues, split into two batches and launch the reviser sequentially — first batch, then second batch on the updated file. Why 30: A typical reviser context handles ~25 issues comfortably; 30 gives headroom without risking quality degradation from context overload.
Spawn a report-reviser subagent (Opus, foreground) with:
- Session directory path (absolute)
- Draft path: relative path to
report.md
- Pass type:
"accuracy"
- Accuracy issues list (ordered as above)
The reviser makes surgical edits using the Edit tool and returns a manifest mapping each issue to the edit made (or explaining why it's unresolved).
After the reviser returns:
- Check the manifest for unresolved issues — note these for delivery
- Verify
report.md was updated (the reviser edits it in place)
- Write the reviser's manifest to
revision/revision-manifest.json as structured JSON. Include for each issue: issue ID, status, location, and fix applied (the action, old_text_snippet, and new_text_snippet fields). Why persist here, before validation: The manifest captures intent — what the reviser tried to do. Validation confirms what actually landed. Both are useful for subsequent runs: the resolved list tells reviewers what was addressed, and validation status tells them whether it stuck.
- Run post-revision validation (Step 3b below)
If zero accuracy issues found (no reviewer issues, no verifier issues after gating, no user feedback): skip directly to Step 4 (style review). Log that accuracy review found no issues.
Step 3b: Post-accuracy-revision validation
The reviser's manifest claims edits were made, but claims aren't proof. Validate that each edit actually landed by checking the report text against the manifest's snippets.
Why validate rather than trusting the manifest: The reviser's "re-read after editing" instruction is aspirational guidance, not an enforced check. The most common failure mode is a prior edit changing surrounding context so a later edit's old_string no longer matches — the Edit tool fails silently from the orchestrator's perspective, and the reviser may record "resolved" in the manifest despite the edit not landing.
Run validation:
{cli_dir}/state validate-edits --manifest <session-dir>/revision/revision-manifest.json --report <session-dir>/report.md --pass accuracy
The command checks each resolved edit's old_text_snippet and new_text_snippet against the report and returns:
- confirmed — old text absent, new text present (edit landed)
- failed — old text still present, new text absent (edit didn't apply)
- inconclusive — both absent (context changed) or both present (logged with warning)
Interpreting results and retry logic: If results.failed is non-empty, re-launch the reviser with only the failed issues (extract issue IDs from the failed array). Cap at one retry. Why one retry: The most common failure is context drift — a prior edit changed surrounding text so old_string no longer matches. One retry with the current file state fixes this because the reviser re-reads the file and targets the updated text. If an edit fails twice, the issue is likely deeper and needs human judgment, not more retries.
After the retry (or if no retry was needed), record:
- Count of edits that passed validation on first try (
results.summary.confirmed)
- Count of edits that required retry
- Count of edits that failed after retry (escalate to unresolved)
Step 4: Round 2 — Style review
Why style review runs after accuracy revision, not before: The style reviewer needs to see the corrected text. If the style reviewer runs on pre-revision text, it flags issues in passages that the accuracy reviser will rewrite — producing stale suggestions the style reviser can't apply. Running style review after accuracy revision means every style flag targets text that has already been corrected for factual accuracy. This eliminates the need for skip_locations (which bluntly excluded entire paragraphs) and cross-type co_located_with flags (which added complexity to prevent fragile edit sequences). The tradeoff is ~3-5 minutes of additional wall-clock time (accuracy revision must complete before style review can start), but this is offset by higher-quality style flags and zero wasted edits.
Launch style-reviewer subagent (Sonnet, foreground) with:
- Session directory path (absolute)
- Path to
report.md (the accuracy-corrected version)
- Research brief
No skip_locations needed — the style reviewer sees corrected text and can flag issues anywhere.
The style reviewer checks: passive voice, unexplained jargon, unfocused paragraphs, filler phrases, and list opportunities — without changing meaning or weakening scientific accuracy.
After it returns, collect style issues from the style-reviewer's issues array — issues are already prefixed style-N by the reviewer.
Severity filtering:
- Always include all high and medium severity style issues.
- Include a low-severity style issue as opportunistic ONLY if its section matches a high or medium severity style issue. Compare the section identifier (e.g., "Section 3") in the low-severity issue's
location against higher-priority style issues' location fields. If no section match, exclude it — the reviser would skip it anyway since there are no nearby edits. Why section-match: Low-severity style issues far from any other edit are almost always skipped by the reviser. Filtering by section proximity mirrors the reviser's own skip logic and avoids burdening the reviser context with issues that have a predetermined outcome.
- When including low-severity style issues, add
"priority": "opportunistic" to each one. The reviser applies opportunistic issues only when it's already editing nearby text for a higher-priority issue — it won't force an edit on an otherwise-clean passage.
Flag co-located style issues. Scan the filtered style issues for non-duplicates that target the same paragraph. For each co-located group, add a co_located_with field listing the other issue IDs. Why: Same rationale as accuracy dedup — two issues targeting the same sentence create fragile edit sequences. The co_located_with signal tells the reviser to plan a single atomic edit.
If zero style issues found after filtering: Skip style revision, proceed to delivery. Log that style review found no issues.
Step 5: Round 2 — Style revision
Spawn a report-reviser subagent (Opus, foreground) with:
- Session directory path (absolute)
- Draft path: relative path to
report.md
- Pass type:
"style"
- Style issues list (high → medium, with opportunistic lows at the end)
After the reviser returns:
- Check the manifest for unresolved issues
- Append the style revision entries to the existing
revision/revision-manifest.json (do not overwrite the accuracy entries — the manifest should contain both rounds)
- Run post-style-revision validation (Step 5b below)
Step 5b: Post-style-revision validation
Same as Step 3b but for style edits:
{cli_dir}/state validate-edits --manifest <session-dir>/revision/revision-manifest.json --report <session-dir>/report.md --pass style
Same retry logic (one retry cap). After validation, record:
- Count of style edits confirmed on first try (
results.summary.confirmed)
- Count that required retry
- Count that failed after retry (escalate to unresolved)
Step 6: Delivery
- Read the final
report.md
- Present a summary to the user with results from both rounds:
- Round 1 (accuracy): How many accuracy issues were found and fixed (count
review-N + verify-N resolved edits), plus user feedback items (user-N)
- Round 2 (style): How many style issues were found and fixed (count
style-N resolved edits)
- Verifier gating mode used (full, targeted, or skip) and why — so the user understands how verification results were applied. If targeted, note which claims were matched; if skip, note that prior verification exists
- How many issues were merged during dedup (if any), so the user knows independent reviewers agreed
- Post-revision validation results for each round: how many edits were confirmed on first try, how many required a retry, and how many failed validation entirely (if any). Why report this: Validation failures signal fragile edits — if retries are frequent, the issues list may have too many overlapping edits targeting the same passages, which is useful feedback for tuning the reviewers.
- Any unresolved issues from either round (with explanations from the reviser manifest, including any edits that failed validation after retry)
- Note that the original draft is preserved at
report_draft.md for comparison
- If there are unresolved issues, suggest what the user could do (e.g., provide the missing source, clarify their intent, run another revision pass)
Delegation
You are the supervisor. You orchestrate reviewers and the reviser — you do not edit the report yourself.
Use the Agent tool to spawn subagents:
synthesis-reviewer (Sonnet) — audits for contradictions, unsupported claims, secondary-source-only claims, missing applicability context, citation integrity. Returns structured issues list. Use subagent_type: "synthesis-reviewer".
claim-extractor (Sonnet) — reads the report, identifies load-bearing claims, classifies source types. Returns structured claim list for verification. Use subagent_type: "claim-extractor".
claim-verifier (Sonnet) — verifies a pre-extracted claim against local reader notes. One claim per verifier, no web search, no report reading. Returns verification report with verdict. Launch one per claim. Use subagent_type: "claim-verifier".
style-reviewer (Sonnet) — audits for plain-language clarity. Returns structured issues list. Use subagent_type: "style-reviewer".
report-reviser (Opus) — makes surgical edits based on a structured issues list. Uses Edit tool only. Returns edit manifest. Launch via Agent tool with the agents/report-reviser.md prompt.
All agents must be foreground (rule 1). To parallelize the synthesis-reviewer and claim-verifier shards in Phase B, put all Agent calls in one response message. With 1 claim per verifier and notes-only verification, each verifier is lightweight.
Expected Agent Outputs
All revision artifacts go in {session}/revision/, not notes/ or the session root. Why a separate directory: notes/ contains reader summaries from the original research pipeline — mixing in reviewer outputs makes it ambiguous whether a file came from research or revision. The revision/ subdirectory keeps provenance clear.
Why these paths are explicit here: The orchestrator doesn't read agent prompt files, so agent-defined output conventions are invisible unless mirrored in the skill prompt. These canonical paths ensure the orchestrator knows where to find results without overriding agent defaults.
| Agent | Output path |
|---|
| synthesis-reviewer | {session}/revision/review-report.md |
| claim-extractor | {session}/revision/claims-manifest.json |
| claim-verifier | {session}/revision/verification-report-{shard_index}.md |
| style-reviewer | {session}/revision/style-review.md |
Do not override these paths when launching agents. Let each agent write to its default location — the paths above match what the agent prompts specify. Why no overrides: Ad-hoc path overrides in agent launch prompts diverge from the agent's own conventions, causing outputs to land in unexpected locations. When the orchestrator and agent disagree on where files go, downstream steps that read those files break silently.
What This Skill Does NOT Do
- No new research. This skill does not search for sources, download papers, or run the research pipeline. If the user needs more sources, they should run
/deep-research again or do targeted searches manually.
- No report generation from scratch. The reviser edits an existing draft — it does not synthesize a new one. If
report.md doesn't exist, this skill can't help.
- No structural reorganization. The reviser fixes flagged issues, not report architecture. If the user wants the report reorganized (different section order, merged sections, new sections), that's a new synthesis task, not a revision. Why: Reorganization requires re-synthesizing the narrative flow across sections — the Edit tool can't do this safely because moving content between sections risks orphaned citations, broken cross-references, and lost context. That's the synthesis-writer's job, not the reviser's.