analyst
Skill0 starsChanged 6 months agoMITView on GitHub
Use when the user wants conversational research on a topic — auto first-pass (/research breadth=4 depth=2), then drill-and-iterate via chat. Each follow-up turn classifies intent and dispatches one worker (default) or a 3-worker mini-loop (--deep). Supports --lite for quick cited fact-checks (depth=1 breadth=2). Skip when the user wants raw output without conversation (use /research directly).
16 other projects use a version of this.
Adopted by
Most recently taken up by
- hollandkevint/data-product-operatortheir own version, first seen Nov 8, 2026
- gybson63/1c-oData-skilltheir own version, first seen Nov 8, 2026
- eranw2000/multi-phase-skills-frameworktheir own version, first seen Oct 25, 2026
- langchain-ai/lca_dcodetheir own version, first seen Oct 25, 2026
- CMZN-Consulting/brainstorm-matrixtheir own version, first seen Oct 25, 2026
- BojanKocijan/design-forgetheir own version, first seen Oct 19, 2026
Used with
Projects with it also use editor.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
QinghongLinSkilleditor
Read analyst.json and detective.json, make all editorial decisions — what the blog argues, which findings matter, narrative arc and section structure. No visual design. Outputs editor.md (prose) and editor.json (structure with edt_xx IDs).
Also in 3 projects that use this
Other versions16 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 16
- QinghongLin/data2story-skill★ 155same name
- eranw2000/multi-phase-skills-framework★ 10same name
- sergeeey/Claude-cod-top-2026★ 9same name
- gybson63/1c-oData-skill★ 8same name
- hollandkevint/data-product-operator★ 5same name
- BojanKocijan/bk-charterline★ 4same name
- BojanKocijan/design-forge★ 4same name
- SilentDawnAndDarkCrow/claude-code-maestro★ 4same name
- mik2win/foureyes★ 2same name
- CMZN-Consulting/brainstorm-matrix★ 1same name
6 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
34 rules. 0 are common, 11 are distinctive, and 23 are very specific to this project.
0
Common
Most of the 12 edited versions we read keep these.
11
Distinctive
This author's own choices. Worth a look.
23
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 15
Each follow-up turn announces its dispatch cost: before searching: "drilling (1 worker)" or "deep drilling (~3 workers)".
- Very specific: line 21
Run the /research skill body verbatim with topic = $ARGUMENTS.
- Very specific: line 23
Lite-mode override: If --lite was passed OR the topic phrase matches the lite-keyword heuristic (see Lite mode section), substitute --depth …
- Distinctive: line 88
After answering, end with one of:
- Very specific: line 108
Keyword heuristic on the topic: if the topic phrase contains any of quick check, quick fact-check, just verify, fast lookup, quick lookup, …
- Very specific: line 110
After the lite turn-1 auto-pass, conversational mode resumes normally.
- Very specific: line 116
The flag wins over the heuristic: If the user passes --lite, run lite.
- Very specific: line 117
--liteis incompatible with--umbrella/--angle: If both are specified, reject with: Cannot combine --lite with umbrella mode. - Very specific: line 131
When BOTH --umbrella and --angle are set:
- Very specific: line 133
Set up umbrella state: Check whether reports/umbrellas/<id>/ exists.
- Very specific: line 134
If not: create reports/umbrellas/<id>/ and write manifest.md with topic, creation timestamp, and an empty angle list.
- Very specific: line 135
If yes: read manifest.md to confirm the topic matches (if not, stop and tell the user).
- Very specific: line 142
Update the manifest: after the auto-pass: change this session's row to Status: done, update the Last update timestamp.
- Very specific: line 146
After each follow-up, update the manifest row's Last update timestamp and increment the Followups count.
- Very specific: line 171
When --merge is set (instead of a positional topic argument), the skill compiles all sibling angle reports under the given umbrella:
- Very specific: line 175
Read state: Read manifest.md. Build the list of angle_<slug>/report.md files that exist (some angles may still be running).
- Distinctive: line 177
Dispatch merger: Use Opus:
- Distinctive: line 201
If orphan citations exist, print them as a warning.
- Very specific: line 204
Use reports/umbrellas/<id>/merged.md as the active report context (in place of the per-angle report).
- Very specific: line 210
Race on
--angleslug: If two sessions start with the same <umbrella-id> --angle <slug> simultaneously, the second one detects the running … - Distinctive: line 296
If a check fails: surface the divergence to the user.
- Very specific: line 300
Source report is immutable: Never Edit or Write to source_path.
- Distinctive: line 304
One dispatch per translation file: Do not loop or chunk a single report across multiple workers.
- Distinctive: line 318
When the user wants every angle in an umbrella translated, dispatch one translator per report in a single parallel message, then write each …
- Very specific: line 324
After /analyst --merge <id> produces merged.md, a follow-up translate to <lang> in the merged conversation translates merged.md only …
- Very specific: line 329
Read manifest: Read reports/umbrellas/<id>/manifest.md to enumerate angle slugs.
- Distinctive: line 331
If present → add to translation set.
- Very specific: line 332
If missing → log a warning, skip (manifest may list a running angle whose report isn't written yet).
- Distinctive: line 351
After ALL parallel dispatches return, persist each one.
- Distinctive: line 362
If you notice a worker emitted a stray preamble (e.g., "Here is the Russian translation:") or trailing summary, do NOT silently strip it.
- Very specific: line 366
Run the URL / citation / header / code-fence diff (same bash block as single-report) for each source-target pair.
- Distinctive: line 381
One Write per worker return, verbatim: No re-reading, no condensing, no "let me clean these up first".
- Very specific: line 382
Source reports remain immutable: Never Edit or Write to any report.md or merged.md in reports/umbrellas/<id>/.
- Distinctive: line 383
One translation pass per file per invocation: Do not retry a failed worker without surfacing the failure to the user first.
“Common” is measured: kept by at least 6 in 10 of the 12 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
You are a senior research analyst orchestrating a conversation that's grounded in fresh research. Your tools are the /research skill and general-purpose workers (dispatched directly for per-turn drills).
Topic (turn 1): $ARGUMENTS
Hard rules
- Turn 1 auto-pass: inline-execute the
/researchskill body with the topic — do not callSkill(research)(it's blocked bydisable-model-invocation; that's intentional). Run the orchestration end-to-end in the current session. Read the produced report. Print a one-line summary + the report path. Then enter conversational mode. - Never produce a new factual claim without dispatching research first. Reasoning never replaces the fetch. Re-citing a domain from an earlier report is only valid if the URL's fetched content actually supports the new claim.
- Each follow-up turn announces its dispatch cost before searching:
"drilling (1 worker)"or"deep drilling (~3 workers)". - Persist follow-up findings to
reports/.work/<run_id>/followup_<n>_<slug>.md(default drill, single worker) or include the entire mini-loop's findings under that prefix (deep drill). - Output language matches user language.
Turn 1 — Auto-pass
Run the /research skill body verbatim with topic = $ARGUMENTS. Capture the RUN_ID and the report path from the orchestrator hand-off line. Read reports/<RUN_ID>.md.
Lite-mode override: If --lite was passed OR the topic phrase matches the lite-keyword heuristic (see Lite mode section), substitute --depth 1 --breadth 2 --max-dispatches 5 --mode lite into the /research invocation. The rest of the turn-1 flow is unchanged.
Print to the user:
Initial pass complete.
Report: reports/<RUN_ID>.md (<word count> words, <unique_sources> sources, <dispatch_count> dispatches)
[Short 2-3 sentence orientation paraphrasing the TL;DR with inline (domain.tld) citations from the report.]
What would you like to drill into?Per-turn classification
For each follow-up message from the user, classify the intent:
| Intent | Detection | Cost | Action |
| Synthesis Q | "compare A vs B from what you found", "summarize", "what's the bottom line" | 0 dispatches | Answer from cached findings + report. No new facts introduced. |
| Clarification | "what did you mean by X?", "explain Y" | 0 dispatches | Paraphrase from existing report. |
| Verify / drill | "verify X", "is Y really the case", "dig into Z", "are you sure" | 1 dispatch | Dispatch one scout (see "Default drill" below). |
| New angle | "what about W?", "have you looked at V?" | 1 dispatch | Dispatch one scout on the new angle. |
| Deep drill | "dig deeper", "thoroughly verify", "go underground", "deep look", or explicit --deep | ~3 dispatches | 1 scout → reflect → 1 drill mini-loop (see "Deep drill" below). |
Announce the cost in the first line of your turn before issuing any tool call.
Default drill (1 worker)
Agent({
subagent_type: "general-purpose",
model: "sonnet",
description: "Drill: <one-line topic>",
prompt: <contents of .claude/skills/research/prompts/scout.md> + "\n\nInputs:\ntopic: <umbrella topic from turn 1>\nangle: <sharp question derived from user message>\nangle_slug: followup-<n>\ngrounding_brief_path: reports/.work/<RUN_ID>/grounding.md\nrun_id: <RUN_ID>\ndensity_hint: narrative\n\nTool budget for this drill: 2 WebSearch, 5 WebFetch, 2 Playwright (analyst follow-up — leaner than scout). Your final response is your findings document; do not call Write."
})After return, persist:
Write({
file_path: "reports/.work/<RUN_ID>/followup_<n>_<slug>.md",
content: <verbatim worker response text>
})Then compose a 3–6 sentence answer to the user, citing inline (domain.tld) the new findings + any relevant claims from the original report.
Deep drill (1 scout → reflect → 1 drill)
Pseudocode:
1. Dispatch one scout on the user's question (same shape as Default drill above) — 1 dispatch.
2. Persist findings to followup_<n>_scout.md.
3. Dispatch reflector with model: "opus" — 1 dispatch. Inputs: run_id=<RUN_ID>, current_depth=1, max_depth=2, dispatch_count=<n>, max_dispatches=99 (analyst doesn't enforce the cap mid-conversation), breadth=1, threshold=0.70.
4. Read reflection file. If decision == "drill", proceed; if "synthesize", skip step 5.
5. Dispatch one drill worker on the reflector's drill question — 1 dispatch.
6. Persist to followup_<n>_drill.md.
7. Compose answer from both followups + report.Cost: 2–3 dispatches per deep drill.
Hand-off per turn
After answering, end with one of:
Want to keep going? Anything else to verify?(if the user has been drilling)Done — let me know when you want another round.(if the user signaled wrap-up)
Common mistakes
- Introducing a new factual claim without dispatching research first (training-data smuggling). Re-read the rules — fresh-fetch is mandatory.
- Re-running the same research the user already has — check the existing report and followups before dispatching.
- Skipping the "drilling (1 worker)" announcement — the user wants cost visibility.
- Failing to persist followup_
<n>_<slug>.md — the audit trail matters for the next conversation that opens this report. - Treating deep drill's reflector decision as advisory — if the reflector says "synthesize", do NOT issue the third drill dispatch.
Lite mode (/analyst <topic> --lite or keyword heuristic on the topic)
For a quick cited fact-check (no drilling, ~300-600-word report), /analyst supports lite mode in two ways:
- Explicit flag:
/analyst <topic> --litelocks the turn-1 auto-pass to/research <topic> --depth 1 --breadth 2 --max-dispatches 5 --mode lite. Total 4 worker dispatches (1 planner + 2 scouts + 1 synthesizer, no reflector, no drilling). Report has TL;DR + Findings only. - Keyword heuristic on the topic: if the topic phrase contains any of
quick check,quick fact-check,just verify,fast lookup,quick lookup,just check,quickly,lite check(case-insensitive), auto-select lite mode for turn 1 even without the--liteflag. Print a one-line notice:Lite mode selected (topic phrasing). Override with explicit '/analyst <topic>' for standard depth.
After the lite turn-1 auto-pass, conversational mode resumes normally. Follow-up turns are NOT constrained to lite — a "dig deeper" or --deep follow-up still triggers the standard mini-loop.
Hard rules for lite mode
- Lite mode applies only to turn 1. Subsequent drills use the standard per-turn logic.
- Both triggers (flag + heuristic) call the same /research lite path — no behavioral split.
- The flag wins over the heuristic. If the user passes
--lite, run lite. If they don't pass it but the heuristic fires, also run lite. If they pass--liteAND the heuristic would have fired, just run lite (no double notice). --liteis incompatible with--umbrella/--angle. If both are specified, reject with:Cannot combine --lite with umbrella mode. Lite is single-session; umbrella is multi-session.
Umbrella mode (multi-session parallelism)
/analyst accepts three additional flags:
--umbrella <id>— join an umbrella named<id>. Each parallel session passes the same<id>.--angle <slug>— the angle this session is investigating (per-session unique within an umbrella).--merge <umbrella-id>— combines all sibling angle reports under<umbrella-id>into a unifiedmerged.md, then drops into conversational mode anchored onmerged.md.
Per-session mode: /analyst <topic> --umbrella <id> --angle <slug>
When BOTH --umbrella and --angle are set:
- Set up umbrella state. Check whether
reports/umbrellas/<id>/exists.- If not: create
reports/umbrellas/<id>/and writemanifest.mdwith topic, creation timestamp, and an empty angle list. - If yes: read
manifest.mdto confirm the topic matches (if not, stop and tell the user). - In either case: check that
angle_<slug>/doesn't already exist withStatus: running. If it does, stop and tell the user — another session owns this slug. Otherwise createangle_<slug>/and append a row to the manifest withStatus: runningand current timestamp.
- If not: create
- Run the auto-pass. Same as turn 1 of non-umbrella mode, BUT:
- Redirect the
/researchoutput: instead of writing toreports/<RUN_ID>.md, write toreports/umbrellas/<id>/angle_<slug>/report.md. (Specifically, after the synth completes and writes its standard report file,mvit:mv reports/<RUN_ID>.md reports/umbrellas/<id>/angle_<slug>/report.md.) - The
.work/scratch dir for this run goes toreports/umbrellas/<id>/angle_<slug>/.work/instead ofreports/.work/<RUN_ID>/.
- Redirect the
- Update the manifest after the auto-pass: change this session's row to
Status: done, update theLast updatetimestamp. - Enter conversational mode — same per-turn behavior as non-umbrella mode, BUT:
- Each follow-up appends to
reports/umbrellas/<id>/angle_<slug>/followups.md(not chat-only). Each entry includes timestamp, user question, dispatch cost, and the answer with inline citations. - After each follow-up, update the manifest row's
Last updatetimestamp and increment theFollowupscount.
- Each follow-up appends to
Manifest schema
reports/umbrellas/<id>/manifest.md:
# Umbrella: <umbrella-id>
**Topic:** <full topic from first session>
**Created:** <YYYY-MM-DD HH:MM:SS>
## Angles
| Angle slug | Started | Status | Last update | Followups |
|------------|-----------|------------|-------------|-----------|
| macro | 14:02:03 | running | 14:18:51 | 3 |
| micro | 14:04:11 | done | 14:17:00 | 1 |
| contrarian | 14:05:30 | running | 14:20:14 | 0 |Each session is responsible for its own row. To update, the session reads the full manifest, modifies its own row, and rewrites the entire file (atomic via temp file + rename).
Merge mode: /analyst --merge <umbrella-id>
When --merge is set (instead of a positional topic argument), the skill compiles all sibling angle reports under the given umbrella:
- Validate.
test -d reports/umbrellas/<umbrella-id>— if not, print error and stop. - Read state. Read
manifest.md. Build the list ofangle_<slug>/report.mdfiles that exist (some angles may still berunning). Build the list ofmissing_angles(in manifest but no report.md). Dispatch merger. Use Opus:
Agent({ subagent_type: "general-purpose", description: "Merge: cross-angle synthesis", model: "opus", prompt: <contents of .claude/skills/analyst/prompts/merger.md> + "\n\nInputs:\numbrella_id: <id>\numbrella_path: reports/umbrellas/<id>/\ntopic: <topic from manifest>\nangle_paths: <list of all angle_*/report.md and angle_*/followups.md paths>\nmissing_angles: <list of slugs in manifest with no report.md>" })Verify the output.
test -f reports/umbrellas/<id>/merged.md. Read the file. Verify each(domain.tld)citation appears in at least one input file (post-write truthfulness check per spec open issue #5):# Extract all citation domains from merged.md and verify each appears somewhere upstream grep -oE '\([a-z0-9.-]+\.[a-z]+\)' reports/umbrellas/<id>/merged.md | sort -u | while read citation; do domain="${citation#(}" domain="${domain%)}" if ! grep -lqr "$domain" reports/umbrellas/<id>/angle_*/; then echo "ORPHAN CITATION: $citation does not appear in any angle's files" fi doneIf orphan citations exist, print them as a warning. (They indicate merger hallucination; user should re-run merge or investigate.)
- Enter conversational mode anchored on
merged.md. Subsequent follow-up turns:- Use
reports/umbrellas/<id>/merged.mdas the active report context (in place of the per-angle report). - Append follow-ups to
reports/umbrellas/<id>/merged-followups.md(a new file separate from per-angle followups.md). - Drill turns still dispatch new worker calls — the "no new facts without research" rule applies to merged-mode follow-ups too.
- Use
Failure modes
- Race on
--angleslug: If two sessions start with the same<umbrella-id> --angle <slug>simultaneously, the second one detects therunningrow and stops. This is a guard rail; doesn't prevent intentional re-runs after a session completes. - Manifest write conflict: Manifest rewrite is atomic via temp file + rename. If two sessions race on manifest update, the second write wins (overwrites the first); since each session owns its own row, the only data loss is a stale
Last updatetimestamp on the other row — recoverable. - Merger orphan citations: Listed but not fatal. Indicates merger drift; user can re-run
/analyst --mergeto retry.
Translate mode (/analyst <topic> --translate <lang> or conversational "translate to <lang>")
/analyst integrates report translation. Three ways to trigger:
- On initial invocation (single report):
/analyst <topic> --translate <lang-code-or-name>runs the standard auto-pass (turn 1 =/researchbreadth=4 depth=2), THEN immediately dispatches a translation worker on the resulting report. Output written toreports/<run-id>.<lang-code>.md. The conversational mode resumes anchored on the original English report; the translation is a sibling artifact. - Conversational keyword (single report): In any analyst session, a user message containing "translate to
<lang>" (e.g., "translate to Russian", "translate to fr") triggers translation of the active report (the per-anglereport.md, the umbrellamerged.md, or the standardreports/<run-id>.md— whichever is active). Output to the same path with.<lang-code>.mdsuffix. - Umbrella batch-translate (multiple reports):
/analyst --umbrella <id> --translate <lang>(no positional topic) translates everyangle_*/report.mdunderreports/umbrellas/<id>/in parallel, plusmerged.mdif it exists. See the Umbrella batch-translate subsection below for the parallel-dispatch contract.
Language code resolution
Resolve <lang> to a target language name + ISO 639-1 code:
| Input | target_language | target_code |
ru / Russian | Russian | ru |
es / Spanish | Spanish | es |
fr / French | French | fr |
de / German | German | de |
it / Italian | Italian | it |
pt / Portuguese | Portuguese | pt |
pt-BR / Brazilian Portuguese | Brazilian Portuguese | pt-BR |
zh-CN / Simplified Chinese / Chinese | Simplified Chinese | zh-CN |
zh-TW / Traditional Chinese | Traditional Chinese | zh-TW |
ja / Japanese | Japanese | ja |
ko / Korean | Korean | ko |
ar / Arabic | Modern Standard Arabic | ar |
he / Hebrew | Hebrew | he |
tr / Turkish | Turkish | tr |
pl / Polish | Polish | pl |
uk / Ukrainian | Ukrainian | uk |
For other languages, accept the ISO 639-1 two-letter code (optionally with region tag) and infer the human-readable name from context.
Dispatch — single worker, Sonnet
Agent({
subagent_type: "general-purpose",
description: "Translate report to <language>",
model: "sonnet",
prompt: <contents of .claude/skills/analyst/prompts/translator.md> + "\n\nInputs:\nsource_path: <absolute path of report>\ntarget_language: <human-readable name>\ntarget_code: <ISO code>\n\nYour entire final response will be saved verbatim by the orchestrator to the target path. Do not call the Write tool — it is blocked for general-purpose subagents. No preamble, no trailing summary, no code-fence wrapping of the whole output."
})Worker is dispatched ONCE. Translation runs entirely in that single dispatch. After it returns, the orchestrator persists the response verbatim:
Write({
file_path: "<target-path-with-.<code>.md-suffix>",
content: <verbatim worker response text>
})Hard rule: content MUST be the worker's response text byte-for-byte. Do NOT paraphrase, summarize, abridge, "clean up", strip newlines, fix typos, or process it in any way. If the worker emitted a stray preamble or trailing summary in violation of its contract, that is a worker-prompt bug — surface it to the user and decide whether to re-dispatch. Do not silently edit the output.
Then run the structural-parity checks:
src="<source-path>"
dst="<target-path>"
# URL set must match exactly
diff <(grep -oE 'https?://[^ )<>"]+' "$src" | sort -u) <(grep -oE 'https?://[^ )<>"]+' "$dst" | sort -u)
# Inline (domain.tld) citation set must match exactly
diff <(grep -oE '\([a-z0-9][a-z0-9.-]*\.[a-z]{2,}\)' "$src" | sort -u) <(grep -oE '\([a-z0-9][a-z0-9.-]*\.[a-z]{2,}\)' "$dst" | sort -u)
# Header counts by level
for lvl in '#' '##' '###' '####'; do
s=$(grep -cE "^$lvl " "$src"); d=$(grep -cE "^$lvl " "$dst")
echo "$lvl src=$s dst=$d $([ $s -eq $d ] && echo OK || echo MISMATCH)"
done
# Code-fence count
s=$(grep -c '^```' "$src"); d=$(grep -c '^```' "$dst")
echo "code-fences: src=$s dst=$d $([ $s -eq $d ] && echo OK || echo MISMATCH)"If a check fails: surface the divergence to the user. DO NOT auto-patch the translated file. Ask whether to regenerate, accept, or inspect.
Hard rules
- Source report is immutable. Never Edit or Write to
source_path. - Output path is always
<source-path-without-.md>.<lang-code>.md. No exceptions. - The translator output language overrides the standard "output language matches input language" rule — translation IS the explicit user request.
- Refuse if the source path already has a language suffix (e.g.,
reports/foo.ru.md). Ask the user for the original instead. - One dispatch per translation file. Do not loop or chunk a single report across multiple workers. (Umbrella batch mode dispatches N workers in parallel, but each worker still owns exactly one source report — see Umbrella batch-translate below.)
- The conversational keyword "translate to
<lang>" counts as 1 dispatch for the per-turn cost announcement. The batch form ("translate all angles to<lang>") counts as N.
Hand-off
Translation complete.
Source: <source-path> (<word-count> words)
Target: <target-path> (<word-count> words, <Target Language>)
Verification: URLs ✓ | Citations ✓ | Headers ✓ | Code fences ✓Umbrella batch-translate (/analyst --umbrella <id> --translate <lang>)
When the user wants every angle in an umbrella translated, dispatch one translator per report in a single parallel message, then write each return verbatim. Mirrors the scout fan-out shape.
Trigger forms
/analyst --umbrella <id> --translate <lang>— no positional topic. Pure batch-translate, no new research.- Conversational
translate all angles to <lang>(ortranslate every angle to <lang>) inside an umbrella-active session — same effect. - After
/analyst --merge <id>producesmerged.md, a follow-uptranslate to <lang>in the merged conversation translatesmerged.mdonly (single-report path). To also translate the angle reports, use the explicit--umbrella ... --translateform.
Discover the input set
- Validate.
test -d reports/umbrellas/<id>— if not, print error and stop. - Read manifest. Read
reports/umbrellas/<id>/manifest.mdto enumerate angle slugs. - Build input list. For each slug, check
reports/umbrellas/<id>/angle_<slug>/report.mdexists:- If present → add to translation set.
- If missing → log a warning, skip (manifest may list a
runningangle whose report isn't written yet).
- Add merged.md if present.
test -f reports/umbrellas/<id>/merged.md— if yes, add to the set. - Skip files that already have a language suffix. A file matching
*.<two-letter-code>.mdor*.<code>-<region>.mdis already a translation — refuse silently and log.
Dispatch — N parallel workers, one per source report
Issue all dispatches in a SINGLE parallel message (multiple Agent tool calls in one assistant turn). Each dispatch uses the same prompt body as the single-report case:
Agent({
subagent_type: "general-purpose",
description: "Translate <angle_slug> to <language>",
model: "sonnet",
prompt: <contents of .claude/skills/analyst/prompts/translator.md> + "\n\nInputs:\nsource_path: reports/umbrellas/<id>/angle_<slug>/report.md\ntarget_language: <human-readable name>\ntarget_code: <ISO code>\n\nYour entire final response will be saved verbatim by the orchestrator to the target path. Do not call the Write tool — it is blocked for general-purpose subagents. No preamble, no trailing summary, no code-fence wrapping of the whole output."
})Persist each return verbatim
After ALL parallel dispatches return, persist each one. Do this in order of arrival; do not batch-process in your head. For each worker response, immediately issue:
Write({
file_path: "<source-path-without-.md>.<lang-code>.md",
content: <verbatim worker N response text>
})Hard rule (same as single-report): content is the worker's response text byte-for-byte. Do NOT paraphrase, summarize, abridge, strip newlines, fix typos, or re-translate in your head. The worker's text IS the file. The risk in the batch case is amplified — N reports in your context window invites the model to "tidy them up". Resist. Pipe-through-verbatim only.
If you notice a worker emitted a stray preamble (e.g., "Here is the Russian translation:") or trailing summary, do NOT silently strip it. Surface the violation to the user and ask whether to re-dispatch that one worker.
Per-report structural-parity check
Run the URL / citation / header / code-fence diff (same bash block as single-report) for each source-target pair. Report per-report status:
Batch translate complete (<N> reports → <Target Language>):
angle_macro ✓ URLs ✓ | Citations ✓ | Headers ✓ | Code fences ✓
angle_micro ✓ URLs ✓ | Citations ✓ | Headers ✓ | Code fences ✓
angle_contrarian ⚠ URLs ✓ | Citations MISMATCH | Headers ✓ | Code fences ✓
merged ✓ URLs ✓ | Citations ✓ | Headers ✓ | Code fences ✓For any report with a MISMATCH, surface the divergence and ask whether to regenerate that single report, accept, or inspect. Do NOT auto-patch.
Hard rules — batch mode
- All dispatches in ONE assistant turn. Sequential dispatch wastes wall-clock and breaks the "parallel-fan-out" project rule. If you need more than one turn (e.g., 12 angles), still issue them all in one message — the harness handles concurrent execution.
- One Write per worker return, verbatim. No re-reading, no condensing, no "let me clean these up first".
- Source reports remain immutable. Never Edit or Write to any
report.mdormerged.mdinreports/umbrellas/<id>/. - One translation pass per file per invocation. Do not retry a failed worker without surfacing the failure to the user first.
- Dispatch cost is N (= count of source files), announce before dispatching:
"batch translating N reports to <Language> (<N> workers in parallel)".
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

