Core principle: Decompose questions, research in parallel with an agent team, evaluate confidence, iterate until sufficient, synthesize with source attribution.
"User request?" -> "Needs multiple sources?" [label="deep research\ncomprehensive analysis\nthorough investigation"];
"User request?" -> "Quick answer sufficient?" [label="simple question"];
"Needs multiple sources?" -> "Use research skill" [label="yes"];
"Needs multiple sources?" -> "Quick answer sufficient?" [label="no"];
}
Use when:
- User explicitly asks for "deep research" or "comprehensive analysis"
- Topic requires multiple authoritative sources
- Need to track confidence and identify gaps
- Want structured output with source attribution
Don't use when:
- Simple factual question (single search sufficient)
- User wants quick answer, not exhaustive report
- Topic is too narrow for 8-question decomposition
</when_to_use>
<required_tools>
| Tool / Feature | Purpose | Required |
|------|---------|----------|
| `WebSearch` | Search queries (built-in) | Yes |
| Agent teams | Spawn parallel researcher teammates | Yes |
| `firecrawl-mcp:firecrawl_scrape` | Scrape full page content (preferred) | No |
| `WebFetch` | Fetch page content (built-in fallback) | Fallback |
**Prerequisite:** Agent teams must be enabled (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` in settings or environment).
Tool Selection: In INIT phase, check if `firecrawl-mcp:firecrawl_scrape` is available. If not, use `WebFetch` (built-in). Record choice in `state.json` as `"scraper": "firecrawl"` or `"scraper": "webfetch"`.
Tradeoffs:
- `firecrawl-mcp:firecrawl_scrape`: Better content extraction, handles JS-rendered pages
- `WebFetch`: Always available, sufficient for static pages
</required_tools>
<state_machine>
INIT → DECOMPOSE → RESEARCH → EVALUATE → [RESEARCH or SYNTHESIZE] → DONE
State File: `research/{slug}/state.json`
```json
{
"topic": "string",
"phase": "INIT|DECOMPOSE|RESEARCH|EVALUATE|SYNTHESIZE|DONE",
"iteration": 0,
"targetSources": 30,
"sourcesGathered": 0,
"totalSearches": 0,
"teammateCompletions": 0,
"codexCompletions": 0,
"findingsCount": 0,
"startTime": "ISO-8601 timestamp",
"scraper": "firecrawl|webfetch",
"questions": [{"id": 1, "text": "...", "status": "pending|done", "confidence": null}]
}
Rule: Read state.json before acting. Write state.json after acting.
How it works:
- When you try to exit, the hook reads
research/{slug}/task-loop.json
- If
complete is false, exit is blocked and continuationPrompt is re-injected
- Once you set
complete: true, exit is allowed and completionMessage is displayed
You manage task-loop.json alongside state.json. Update statusMessage and continuationPrompt as progress changes so the hook always has current context.
Default target: 30 sources. Adjust in INIT phase based on topic complexity.
If research/{slug}/state.json exists:
- Parse JSON; if invalid, offer to restart
- Resume from current
phase
- Notify user: "Resuming research from {phase} phase"
Verify state consistency before resuming:
- RESEARCH: Ensure pending questions exist
- EVALUATE: Ensure
findings.json has data
- SYNTHESIZE: Ensure all questions marked "done"
If inconsistent, offer user choice:
- Delete state and restart
- Attempt repair (mark incomplete questions as pending)
Detect available scraper:
- Check if
firecrawl-mcp:firecrawl_scrape tool exists
- If firecrawl available →
"scraper": "firecrawl"
- If not available →
"scraper": "webfetch" (uses built-in WebFetch)
Create working directory:
mkdir -p research/{slug}
Determine target sources based on topic complexity:
- Narrow topic (specific question): 20 sources
- Standard topic (most research): 30 sources (default)
- Broad topic (comprehensive review): 40 sources
Initialize state files:
state.json:
{
"topic": "...",
"phase": "DECOMPOSE",
"iteration": 0,
"targetSources": 30,
"sourcesGathered": 0,
"totalSearches": 0,
"teammateCompletions": 0,
"codexCompletions": 0,
"findingsCount": 0,
"startTime": "2024-01-15T10:30:00Z",
"scraper": "firecrawl|webfetch",
"questions": []
}
task-loop.json (activates the generic task loop hook):
{
"active": true,
"complete": false,
"continuationPrompt": "Continue researching: {topic}. Check research/{slug}/state.json for current progress and continue the RESEARCH phase.",
"statusMessage": "Research in progress: {topic}\nSources: 0/{targetSources}",
"completionMessage": "Research complete."
}
findings.json:
[]
| # |
Angle |
Example |
| 1 |
Definition/background |
What is X? History and context? |
| 2 |
Current state |
What's happening now? Recent developments (last 1-2 years)? |
| 3 |
Key entities |
Who are the main people, companies, organizations? |
| 4 |
Core mechanisms |
How does it work? What are the processes? |
| 5 |
Evidence and data |
What studies, statistics, data exist? |
| 6 |
Criticisms and limitations |
What are the problems, risks, downsides? |
| 7 |
Comparisons |
How does it compare to alternatives? |
| 8 |
Future developments |
What's coming next? Predictions? |
Add questions to state.json with status="pending". Set phase="RESEARCH".
Claude teammates: One per pending question (up to 8 at a time). Each works independently with its own context window. Each teammate also calls the codex MCP tool to get Codex's perspective on the same question, providing genuine cross-validation — two engines may surface different sources and perspectives.
Read scraper from state.json and use the appropriate instructions when spawning each Claude teammate:
TASK: {QUESTION}
PROCESS:
Run exactly 4 searches:
- Core query
- Add "research" or "study"
- Add current year or "recent"
- Rephrase with synonyms
Rank URLs by quality:
- Tier 1: .gov, .edu, journals, official docs
- Tier 2: Reuters, AP, BBC, industry publications
- Tier 3: Company blogs, Wikipedia
- Skip: Forums, social media, SEO spam
Select top 4 URLs (prefer Tier 1-2)
Use firecrawl-mcp:firecrawl_scrape on each. Continue if one fails.
Extract specific facts with sources.
TASK: {QUESTION}
PROCESS:
Run exactly 4 searches:
- Core query
- Add "research" or "study"
- Add current year or "recent"
- Rephrase with synonyms
Rank URLs by quality:
- Tier 1: .gov, .edu, journals, official docs
- Tier 2: Reuters, AP, BBC, industry publications
- Tier 3: Company blogs, Wikipedia
- Skip: Forums, social media, SEO spam
Select top 4 URLs (prefer Tier 1-2)
Use WebFetch on each with a prompt like "Extract the main content and key facts from this page". Continue if one fails.
Extract specific facts with sources.
After completing your web research above, call the codex MCP tool to cross-validate your findings.
Call the codex MCP tool with these exact parameters:
prompt: "Research this question: {QUESTION}. Return findings as JSON with fields: fact, sourceNote, confidence (high/medium/low). Focus on facts you can confirm from your training data."
model: gpt-5-codex
sandbox: read-only
Validate the response before merging. Treat ALL of the following as Codex-unavailable:
- Tool call throws or times out
- Response is empty or whitespace-only
- Response is not valid JSON matching the requested schema
- Response contains MCP error text (e.g.,
"Codex CLI Not Found", "Codex Execution Error")
If Codex returned valid JSON, compare findings with your web-sourced findings:
- AGREE: Both found the same fact → boost confidence, note as cross-validated
- CHALLENGE: Codex contradicts a web-sourced fact → note the contradiction, keep the web-sourced version with the contradiction documented
- COMPLEMENT (Codex-only): Codex reports a fact you didn't find online → include it with
"status": "hypothesis" since Codex cannot cite web sources
- COMPLEMENT (Claude-only): You found it but Codex didn't → keep as-is with your web source
If Codex is unavailable (any condition above), return your Claude-only findings. Do not block on Codex.
After each Claude teammate completes:
- Validate JSON. Retry once if malformed.
- Append to
findings.json
- Update
state.json:
- Mark question done
- Increment
totalSearches by searchesRun from response
- Increment
teammateCompletions by 1
- Increment
sourcesGathered by urlsScraped from response
- Increment
findingsCount by length of findings array from response
- If
codexAvailable is true, increment codexCompletions by 1
- Log progress:
"Sources: {sourcesGathered}/{targetSources}"
After all teammates complete:
- Set
phase="EVALUATE"
| Metric |
Calculation |
sourcesGathered |
from state.json (primary gate) |
targetSources |
from state.json |
avgConfidence |
high=3, medium=2, low=1, average all |
significantGaps |
unique gaps across findings |
Decision table (two-stage):
Stage 1: Source Gate (MANDATORY)
| sourcesGathered >= targetSources |
→ Action |
| No |
RESEARCH (forced, cannot proceed) |
| Yes |
Continue to Stage 2 |
You MUST gather enough sources before considering other criteria.
Stage 2: Quality Gate (only if Stage 1 passes)
| avgConfidence >= 2.5 AND gaps <= 2 |
→ Decision |
| Yes |
SYNTHESIZE |
| No |
RESEARCH (generate follow-ups) |
Note: The task loop hook enforces the source gate — you cannot exit until task-loop.json has complete: true.
If continuing to RESEARCH:
- Generate max 4 follow-up questions from gaps/contradictions
- Add to questions with
status="pending"
- Increment iteration
- Set
phase="RESEARCH"
- Update
task-loop.json: set statusMessage to current progress ("Sources: {sourcesGathered}/{targetSources}") and continuationPrompt to reflect remaining work
- Log:
"Continuing research: {sourcesGathered}/{targetSources} sources, need more to meet target"
# {Topic}
## Executive Summary
[300-400 words. Most important finding first. State confidence. Note caveats.]
## Background
[200 words. Key terms. Context.]
## Key Findings
### [Theme 1]
[Grouped findings. Inline citations. Note source strength.]
### [Theme 2]
[3-5 themes total]
## Conflicting Information
[Both sides. Which has better sourcing.]
## Gaps & Limitations
[What's unknown. What needs more research.]
## Source Assessment
- **High confidence:** [claims with 3+ quality sources]
- **Medium confidence:** [claims with 1-2 sources]
- **Low confidence:** [single source or Tier 3 only]
## Sources
### Primary
[Tier 1 sources with URLs]
### Secondary
[Tier 2-3 sources with URLs]
---
*Sources: {sourcesGathered} | Searches: {totalSearches} | Teammates: {teammateCompletions} | Iterations: {iteration} | Duration: {duration} | Date: {date}*
Set phase="DONE".
Update task-loop.json:
{
"active": true,
"complete": true,
"completionMessage": "Research complete: \"{topic}\"\n\nResources used:\n Searches: {totalSearches}\n Sources: {sourcesGathered}/{targetSources}\n Teammates: {teammateCompletions}\n Iterations: {iteration}\n\nReport: research/{slug}/report.md"
}
The task loop hook will display this message when the session exits.
No hard iteration or search limits. The source gate is the primary constraint. Research continues until sourcesGathered >= targetSources.
| Thought |
Reality |
| "I have high confidence, I can skip the source target" |
The task loop hook will block you. Gather the sources — it's non-negotiable. |
| "This topic is too broad for 8 questions" |
Narrow the scope first. Don't start research on vague topics. |
| "I'll just synthesize what I have" |
Check sourcesGathered >= targetSources in state.json. If not met, you cannot proceed. |
| "I don't need to update state.json" |
You will lose track. Always read/write state.json. |
| "All sources are equal" |
Weight Tier 1 sources higher in synthesis. |
| "I'm stuck, I'll just finish" |
Narrow the scope or generate better follow-up questions. The task loop hook will block you. |
|
|
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: research-163description: Use when user explicitly requests deep research or comprehensive analysis requiring 20+ authoritative sources. Creates an agent team for parallel research with source gate enforcement, confidence tracking, and structured synthesis. NOT for simple questions answerable with a single search.4---56<objective>7Comprehensive research using an agent team, web search, and web scraping. Iteratively decomposes topics, gathers evidence from quality sources via parallel researcher teammates, and synthesizes findings into structured reports.89Core principle: Decompose questions, research in parallel with an agent team, evaluate confidence, iterate until sufficient, synthesize with source attribution.10</objective>1112<quick_start>131. Run `/research [topic]` to start142. Research continues automatically until `targetSources` is met153. A task loop hook enforces the source gate — you cannot exit early164. On completion, a resource usage report is displayed17</quick_start>1819<success_criteria>20Task is complete when ALL of these are true:21- [ ] `state.json` exists with valid JSON22- [ ] `sourcesGathered >= targetSources` (primary gate - enforced by task loop hook)23- [ ] All questions marked `"done"` with confidence ratings24- [ ] `report.md` synthesizes findings with source attribution25- [ ] `phase` is `"DONE"` in state.json26- [ ] Conflicting information documented with source quality assessment27- [ ] Gaps and limitations explicitly noted in report28</success_criteria>2930<when_to_use>31```dot32digraph when_research {33 "User request?" [shape=diamond];34 "Needs multiple sources?" [shape=diamond];35 "Quick answer sufficient?" [shape=box];36 "Use research skill" [shape=box];3738 "User request?" -> "Needs multiple sources?" [label="deep research\ncomprehensive analysis\nthorough investigation"];39 "User request?" -> "Quick answer sufficient?" [label="simple question"];40 "Needs multiple sources?" -> "Use research skill" [label="yes"];41 "Needs multiple sources?" -> "Quick answer sufficient?" [label="no"];42}43```4445Use when:46- User explicitly asks for "deep research" or "comprehensive analysis"47- Topic requires multiple authoritative sources48- Need to track confidence and identify gaps49- Want structured output with source attribution5051Don't use when:52- Simple factual question (single search sufficient)53- User wants quick answer, not exhaustive report54- Topic is too narrow for 8-question decomposition55</when_to_use>5657<required_tools>58| Tool / Feature | Purpose | Required |59|------|---------|----------|60| `WebSearch` | Search queries (built-in) | Yes |61| Agent teams | Spawn parallel researcher teammates | Yes |62| `firecrawl-mcp:firecrawl_scrape` | Scrape full page content (preferred) | No |63| `WebFetch` | Fetch page content (built-in fallback) | Fallback |6465**Prerequisite:** Agent teams must be enabled (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` in settings or environment).6667Tool Selection: In INIT phase, check if `firecrawl-mcp:firecrawl_scrape` is available. If not, use `WebFetch` (built-in). Record choice in `state.json` as `"scraper": "firecrawl"` or `"scraper": "webfetch"`.6869Tradeoffs:70- `firecrawl-mcp:firecrawl_scrape`: Better content extraction, handles JS-rendered pages71- `WebFetch`: Always available, sufficient for static pages72</required_tools>7374<state_machine>75```76INIT → DECOMPOSE → RESEARCH → EVALUATE → [RESEARCH or SYNTHESIZE] → DONE77```7879State File: `research/{slug}/state.json`8081```json82{83 "topic": "string",84 "phase": "INIT|DECOMPOSE|RESEARCH|EVALUATE|SYNTHESIZE|DONE",85 "iteration": 0,86 "targetSources": 30,87 "sourcesGathered": 0,88 "totalSearches": 0,89 "teammateCompletions": 0,90 "codexCompletions": 0,91 "findingsCount": 0,92 "startTime": "ISO-8601 timestamp",93 "scraper": "firecrawl|webfetch",94 "questions": [{"id": 1, "text": "...", "status": "pending|done", "confidence": null}]95}96```9798Rule: Read `state.json` before acting. Write `state.json` after acting.99</state_machine>100101<task_loop>102A generic task loop hook prevents the session from ending while `task-loop.json` has `complete: false`. This is a hard gate — you cannot bypass it by rationalizing.103104How it works:1051. When you try to exit, the hook reads `research/{slug}/task-loop.json`1062. If `complete` is false, exit is blocked and `continuationPrompt` is re-injected1073. Once you set `complete: true`, exit is allowed and `completionMessage` is displayed108109You manage `task-loop.json` alongside `state.json`. Update `statusMessage` and `continuationPrompt` as progress changes so the hook always has current context.110111Default target: 30 sources. Adjust in INIT phase based on topic complexity.112</task_loop>113114<state_recovery>115On skill invocation, first check for existing state:1161171. If `research/{slug}/state.json` exists:118 - Parse JSON; if invalid, offer to restart119 - Resume from current `phase`120 - Notify user: "Resuming research from {phase} phase"1211222. Verify state consistency before resuming:123 - RESEARCH: Ensure pending questions exist124 - EVALUATE: Ensure `findings.json` has data125 - SYNTHESIZE: Ensure all questions marked "done"1261273. If inconsistent, offer user choice:128 - Delete state and restart129 - Attempt repair (mark incomplete questions as pending)130</state_recovery>131132<steps>133134<phase name="INIT">1351. Generate slug from topic:136 - Lowercase the topic137 - Replace spaces with hyphens138 - Remove special characters (keep only `a-z`, `0-9`, `-`)139 - Truncate to 50 characters140 - Example: "AI in Healthcare 2024!" → `ai-in-healthcare-2024`1411422. Detect available scraper:143 - Check if `firecrawl-mcp:firecrawl_scrape` tool exists144 - If firecrawl available → `"scraper": "firecrawl"`145 - If not available → `"scraper": "webfetch"` (uses built-in `WebFetch`)1461473. Create working directory:148 ```bash149 mkdir -p research/{slug}150 ```1511524. Determine target sources based on topic complexity:153 - Narrow topic (specific question): 20 sources154 - Standard topic (most research): 30 sources (default)155 - Broad topic (comprehensive review): 40 sources1561575. Initialize state files:158159 state.json:160 ```json161 {162 "topic": "...",163 "phase": "DECOMPOSE",164 "iteration": 0,165 "targetSources": 30,166 "sourcesGathered": 0,167 "totalSearches": 0,168 "teammateCompletions": 0,169 "codexCompletions": 0,170 "findingsCount": 0,171 "startTime": "2024-01-15T10:30:00Z",172 "scraper": "firecrawl|webfetch",173 "questions": []174 }175 ```176177 task-loop.json (activates the generic task loop hook):178 ```json179 {180 "active": true,181 "complete": false,182 "continuationPrompt": "Continue researching: {topic}. Check research/{slug}/state.json for current progress and continue the RESEARCH phase.",183 "statusMessage": "Research in progress: {topic}\nSources: 0/{targetSources}",184 "completionMessage": "Research complete."185 }186 ```187188 findings.json:189 ```json190 []191 ```192</phase>193194<phase name="DECOMPOSE">195Generate exactly 8 questions covering these angles:196197| # | Angle | Example |198|---|-------|---------|199| 1 | Definition/background | What is X? History and context? |200| 2 | Current state | What's happening now? Recent developments (last 1-2 years)? |201| 3 | Key entities | Who are the main people, companies, organizations? |202| 4 | Core mechanisms | How does it work? What are the processes? |203| 5 | Evidence and data | What studies, statistics, data exist? |204| 6 | Criticisms and limitations | What are the problems, risks, downsides? |205| 7 | Comparisons | How does it compare to alternatives? |206| 8 | Future developments | What's coming next? Predictions? |207208Add questions to `state.json` with `status="pending"`. Set `phase="RESEARCH"`.209</phase>210211<phase name="RESEARCH">212Create an agent team to research pending questions in parallel. Each teammate independently searches with Claude AND cross-validates with Codex via the `codex` MCP tool.213214**Claude teammates:** One per pending question (up to 8 at a time). Each works independently with its own context window. Each teammate also calls the `codex` MCP tool to get Codex's perspective on the same question, providing genuine cross-validation — two engines may surface different sources and perspectives.215216Read `scraper` from state.json and use the appropriate instructions when spawning each Claude teammate:217218<teammate_instructions scraper="firecrawl">219You are a researcher teammate with access to `WebSearch` and `firecrawl-mcp:firecrawl_scrape`.220221**TASK:** {QUESTION}222223**PROCESS:**2242251. Run exactly 4 searches:226 - Core query227 - Add "research" or "study"228 - Add current year or "recent"229 - Rephrase with synonyms2302312. Rank URLs by quality:232 - **Tier 1:** .gov, .edu, journals, official docs233 - **Tier 2:** Reuters, AP, BBC, industry publications234 - **Tier 3:** Company blogs, Wikipedia235 - **Skip:** Forums, social media, SEO spam2362373. Select top 4 URLs (prefer Tier 1-2)2382394. Use `firecrawl-mcp:firecrawl_scrape` on each. Continue if one fails.2402415. Extract specific facts with sources.242</teammate_instructions>243244<teammate_instructions scraper="webfetch">245You are a researcher teammate with access to `WebSearch` and `WebFetch`.246247**TASK:** {QUESTION}248249**PROCESS:**2502511. Run exactly 4 searches:252 - Core query253 - Add "research" or "study"254 - Add current year or "recent"255 - Rephrase with synonyms2562572. Rank URLs by quality:258 - **Tier 1:** .gov, .edu, journals, official docs259 - **Tier 2:** Reuters, AP, BBC, industry publications260 - **Tier 3:** Company blogs, Wikipedia261 - **Skip:** Forums, social media, SEO spam2622633. Select top 4 URLs (prefer Tier 1-2)2642654. Use `WebFetch` on each with a prompt like "Extract the main content and key facts from this page". Continue if one fails.2662675. Extract specific facts with sources.268</teammate_instructions>269270<teammate_codex_crossvalidation>271## Cross-Validation with Codex272273After completing your web research above, call the `codex` MCP tool to cross-validate your findings.274275Call the `codex` MCP tool with these exact parameters:276- `prompt`: "Research this question: {QUESTION}. Return findings as JSON with fields: fact, sourceNote, confidence (high/medium/low). Focus on facts you can confirm from your training data."277- `model`: `gpt-5-codex`278- `sandbox`: `read-only`279280**Validate the response before merging.** Treat ALL of the following as Codex-unavailable:281- Tool call throws or times out282- Response is empty or whitespace-only283- Response is not valid JSON matching the requested schema284- Response contains MCP error text (e.g., `"Codex CLI Not Found"`, `"Codex Execution Error"`)285286If Codex returned valid JSON, compare findings with your web-sourced findings:287- **AGREE**: Both found the same fact → boost confidence, note as cross-validated288- **CHALLENGE**: Codex contradicts a web-sourced fact → note the contradiction, keep the web-sourced version with the contradiction documented289- **COMPLEMENT (Codex-only)**: Codex reports a fact you didn't find online → include it with `"status": "hypothesis"` since Codex cannot cite web sources290- **COMPLEMENT (Claude-only)**: You found it but Codex didn't → keep as-is with your web source291292If Codex is unavailable (any condition above), return your Claude-only findings. Do not block on Codex.293</teammate_codex_crossvalidation>294295<teammate_return_format>296**RETURN ONLY THIS JSON:**297```json298{299 "questionId": {ID},300 "questionText": "{QUESTION}",301 "searchQueries": ["query1", "query2", "query3", "query4"],302 "searchesRun": 4,303 "urlsScraped": 4,304 "scrapeFailures": [],305 "findings": [306 {307 "fact": "...",308 "sourceUrl": "...",309 "tier": 1,310 "crossValidated": false,311 "engines": ["claude"],312 "status": "confirmed|hypothesis|disputed"313 }314 ],315 "gaps": ["what you couldn't find"],316 "contradictions": ["X says A, Y says B"],317 "confidence": "high|medium|low",318 "confidenceReason": "...",319 "codexAvailable": true320}321```322</teammate_return_format>323324After each Claude teammate completes:3251. Validate JSON. Retry once if malformed.3262. Append to `findings.json`3273. Update `state.json`:328 - Mark question done329 - Increment `totalSearches` by `searchesRun` from response330 - Increment `teammateCompletions` by 1331 - Increment `sourcesGathered` by `urlsScraped` from response332 - Increment `findingsCount` by length of `findings` array from response333 - If `codexAvailable` is true, increment `codexCompletions` by 13344. Log progress: `"Sources: {sourcesGathered}/{targetSources}"`335336After all teammates complete:3371. Set `phase="EVALUATE"`338</phase>339340<phase name="EVALUATE">341Calculate metrics:342343| Metric | Calculation |344|--------|-------------|345| `sourcesGathered` | from state.json (primary gate) |346| `targetSources` | from state.json |347| `avgConfidence` | high=3, medium=2, low=1, average all |348| `significantGaps` | unique gaps across findings |349350Decision table (two-stage):351352Stage 1: Source Gate (MANDATORY)353354| sourcesGathered >= targetSources | → Action |355|:--------------------------------:|:--------:|356| No | RESEARCH (forced, cannot proceed) |357| Yes | Continue to Stage 2 |358359You MUST gather enough sources before considering other criteria.360361Stage 2: Quality Gate (only if Stage 1 passes)362363| avgConfidence >= 2.5 AND gaps <= 2 | → Decision |364|:----------------------------------:|:----------:|365| Yes | SYNTHESIZE |366| No | RESEARCH (generate follow-ups) |367368Note: The task loop hook enforces the source gate — you cannot exit until `task-loop.json` has `complete: true`.369370If continuing to RESEARCH:3711. Generate max 4 follow-up questions from gaps/contradictions3722. Add to questions with `status="pending"`3733. Increment iteration3744. Set `phase="RESEARCH"`3755. Update `task-loop.json`: set `statusMessage` to current progress (`"Sources: {sourcesGathered}/{targetSources}"`) and `continuationPrompt` to reflect remaining work3766. Log: `"Continuing research: {sourcesGathered}/{targetSources} sources, need more to meet target"`377</phase>378379<phase name="SYNTHESIZE">380Write `report.md`:381382```markdown383# {Topic}384385## Executive Summary386[300-400 words. Most important finding first. State confidence. Note caveats.]387388## Background389[200 words. Key terms. Context.]390391## Key Findings392393### [Theme 1]394[Grouped findings. Inline citations. Note source strength.]395396### [Theme 2]397[3-5 themes total]398399## Conflicting Information400[Both sides. Which has better sourcing.]401402## Gaps & Limitations403[What's unknown. What needs more research.]404405## Source Assessment406- **High confidence:** [claims with 3+ quality sources]407- **Medium confidence:** [claims with 1-2 sources]408- **Low confidence:** [single source or Tier 3 only]409410## Sources411412### Primary413[Tier 1 sources with URLs]414415### Secondary416[Tier 2-3 sources with URLs]417418---419*Sources: {sourcesGathered} | Searches: {totalSearches} | Teammates: {teammateCompletions} | Iterations: {iteration} | Duration: {duration} | Date: {date}*420```421422Set `phase="DONE"`.423424Update `task-loop.json`:425```json426{427 "active": true,428 "complete": true,429 "completionMessage": "Research complete: \"{topic}\"\n\nResources used:\n Searches: {totalSearches}\n Sources: {sourcesGathered}/{targetSources}\n Teammates: {teammateCompletions}\n Iterations: {iteration}\n\nReport: research/{slug}/report.md"430}431```432433The task loop hook will display this message when the session exits.434</phase>435436</steps>437438<error_handling>439| Error | Action |440|-------|--------|441| Malformed JSON | Retry once, then mark low confidence |442| Scrape fails | Continue with other URLs |443| Rate limit | Wait 60s, reduce batch to 2 |444| No results | Mark low confidence, rephrase as follow-up |445| Tool not found | Fall back to WebFetch, update state.json |446| `codex` MCP unavailable, empty, or error-text response | Teammate returns Claude-only findings, research continues |447</error_handling>448449<limits>450| Resource | Default | Notes |451|----------|---------|-------|452| Target sources | 30 | Adjustable in INIT (20-40 based on complexity) |453| Teammates per batch | 8 | Parallel research questions (one teammate per question) |454| URLs per teammate | 4 | Sources scraped per question |455| Follow-ups per iteration | 4 | New questions from gaps |456457No hard iteration or search limits. The source gate is the primary constraint. Research continues until `sourcesGathered >= targetSources`.458</limits>459460<red_flags>461STOP if you catch yourself thinking any of these:462463| Thought | Reality |464|---------|---------|465| "I have high confidence, I can skip the source target" | The task loop hook will block you. Gather the sources — it's non-negotiable. |466| "This topic is too broad for 8 questions" | Narrow the scope first. Don't start research on vague topics. |467| "I'll just synthesize what I have" | Check `sourcesGathered >= targetSources` in state.json. If not met, you cannot proceed. |468| "I don't need to update state.json" | You will lose track. Always read/write state.json. |469| "All sources are equal" | Weight Tier 1 sources higher in synthesis. |470| "I'm stuck, I'll just finish" | Narrow the scope or generate better follow-up questions. The task loop hook will block you. |471</red_flags>472473---474> Converted and distributed by [TomeVault](https://tomevault.io/claim/guyathomas) — claim your Tome and manage your conversions.475<!-- tomevault:4.0:skill_md:2026-04-15 -->