Install
$ agentstack add skill-axect-skills-research-report ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Research Report
Use this skill to produce a self-contained research or experiment report from an output directory that may contain notes, source code, tests, metrics, tables, and plots. The skill is harness-only: it never calls external Gemini or Codex MCP tools. Where the magi-researchers pipeline uses BALTHASAR (Gemini) and CASPER (Codex) reviewers, this skill spawns Claude subagents with cognitive-style framing instead.
Inputs to confirm
Ask for only what is missing:
- target output directory
- report title
- domain or audience (used to load
references/domains/.md; default:general) - whether existing plots already exist in
plots/ - whether a lightweight plot metadata file should be supplied for better captions or section mapping
- whether section-level reference support is needed for background, methodology, baseline comparisons, benchmark context, or claim-heavy passages
Expected directory shape
The skill works best when the target directory looks roughly like this:
{output_dir}/
report.md
report_versions.json
plots/
*.png
*.pdf | *.svg
plot_manifest.json
_plot_style.py # copy of the helper used by every plot script
*.py # plot generation scripts
data/.csv # raw data consumed by each script
src/
tests/
notes/ | brainstorm/ | plan/ | results/ | tables/
references/ | bib/ | related_work/
Missing folders are acceptable. Adapt the report to whatever evidence actually exists.
Report workflow conventions
When tailoring this skill to a project that already uses outputs/ directories:
- Prefer a self-contained target like
outputs/{report_slug}/. - Keep
report.md,report_versions.json, andplots/plot_manifest.jsonin the same report root. - Copy or regenerate only artifacts that belong to the current report narrative. Do not mix unrelated experiment outputs.
- Treat
report_v{N}.mdfiles as immutable archives once versioned. - Keep plot paths relative to the report root so the directory can move without edits.
- Reuse existing project metrics, CSV or JSON summaries, tables, and previous report drafts before creating new artifacts.
Single-Harness workflow
The workflow has nine ordered steps. Steps marked (gate) must pass before continuing.
Step 1 — Gather materials
- Inventory
src/,tests/, notes, metrics, tables, any priorreport.mdorreport_v*.md, and any existingreferences/,bib/, or related-work notes. - Read the report template in
references/report_template.md. - Read the domain template at
references/domains/.mdfor tone and visualization conventions. Fall back toreferences/domains/general.mdwhen the domain is unknown. - If
plots/exists, build or refreshplots/plot_manifest.json:
``bash python skills/research-report/scripts/build_plot_manifest.py \ "{output_dir}/plots" \ --report-root "{output_dir}" ` Pass --metadata path/to/plot_metadata.json` for richer captions or section hints.
Step 2 — Plot-style pre-flight (gate)
Before drafting prose, audit every plot generation script for compliance with the shared style helper. This is the local equivalent of magi's BALTHASAR/CASPER style-compliance check, but enforced statically over scripts instead of begging an LLM to spot regressions.
- Ensure
plots/_plot_style.pyexists. If the project does not have it yet, copy it fromassets/plot_templates/_plot_style.pysofrom _plot_style import ...resolves. - Run the plot-script auditor:
``bash python skills/research-report/scripts/validate_plot_scripts.py "{output_dir}" --json `` The auditor flags:
- scripts that import
matplotlibbut do not import_plot_styleorscienceplots, - scripts that call
plt.style.use(['science', ...])without'no-latex'while also settingtext.usetex=False(silent-fallback bug, pitfall #21), - scripts that override
font.familyorfont.sizeafterapply_style(), - scripts that call
plt.savefig(...)only as PNG (PDF/SVG missing), - scripts that hardcode
dpibelow 300, - scripts that fail to call
assert_english(...)on label/title strings.
- Resolve every error before continuing. Warnings should be fixed or explicitly justified in the report.
- If a plot is non-compliant, regenerate it via the
assets/plot_templates/*.pyfamily and re-runbuild_plot_manifest.py. - Run the JSON-artifact validator afterwards:
``bash python skills/research-report/scripts/validate_artifacts.py "{output_dir}" --json `` Treat errors as blockers. Treat warnings as items to fix or explicitly mention in the report.
Step 3 — Map evidence to sections
- Background: problem, context, assumptions, prior notes, and literature context.
- Analysis or discovery summary: exploratory findings, trade-offs, or problem framing.
- Methodology: approach, algorithms, data flow, experimental design, and method citations when external grounding matters.
- Implementation or setup: architecture, components, environment, constraints.
- Results and visualization: quantitative outcomes, comparisons, plots, tables, and baseline or benchmark context when needed.
- Validation: tests, checks, edge cases, failure modes, limitations, and benchmark-protocol references when they clarify interpretation.
- Conclusion: contributions, limitations, next steps.
Plot → section mapping uses the manifest's section_hint:
| section_hint | Report section | |----------------|----------------| | methodology | §3 Methodology | | results | §5.1 Primary Results | | comparison | §5.2 Comparative or Ablation Findings | | validation | §6 Validation | | testing | §6 Validation |
Step 4 — Attach literature support where needed
- Use the companion
reference-searchskill whenever a section depends on prior work, external benchmark framing, method lineage, or an externally grounded claim that cannot be supported by local artifacts alone. - Typical mappings:
- background or introduction →
backgroundorsurvey - methodology rationale →
method - comparison targets →
baseline - dataset, metric, or benchmark protocol context →
evaluation - standalone factual claims →
claim-support - Prefer weaving only the strongest 2–5 references into the report prose instead of dumping long bibliographies.
- Only save section-level reference notes when the user asks for them or the project already maintains a
references/or similar folder.
Step 5 — Handle plots
- Reuse existing plots when they already support the narrative.
- Generate missing plots only from real data already present in the workspace.
- Preferred stack:
matplotlib+scienceplots+ the shared helper atassets/plot_templates/_plot_style.py. Copy the helper into the project'splots/directory next to any template script you adapt sofrom _plot_style import ...resolves. - Plot text must be English. Korean or other non-ASCII characters in axis labels, titles, legends, or tick labels typically render as missing-glyph boxes (
□) and the failure is silent. Move localized commentary to the report caption. The sharedassert_english(...)helper enforces this at runtime; call it on every user-facing string before plotting. - LaTeX
%rule. Whentext.usetex=True,%starts a comment and silently truncates the rest of the string ("95%"becomes"95"). The sharedapply_style()keepstext.usetex=Truewhenever LaTeX is usable (soscience/naturerender correctly) and falls back to scienceplots'no-latexstyle only when LaTeX is unavailable. Always route user-controlled strings throughlatex_escape(...)(covers% & # _ $ { }) before passing them to axis labels, legends, or titles. - Output formats: PNG at
dpi=300plus PDF (vector). SVG is an acceptable PDF substitute when PDF is impractical. The sharedsave_figure()enforces this and always closes the figure. - LaTeX is the default rendering path for
scienceandnaturestyles.apply_style()defaults touse_latex=Trueand probes forlatex+dvipngat runtime. If LaTeX is unavailable, the helper automatically appends scienceplots'no-latexstyle modifier and emits aRuntimeWarningso you know the rendering downgraded. Never callplt.style.use(['science'])and then settext.usetex=Falseby hand — that combination silently substitutes DejaVu Sans for Times and the resulting figures are indistinguishable from default matplotlib (scienceplots is loaded but invisible). Always go throughapply_style()so the LaTeX/no-LaTeX decision is made coherently. - Recording the decision:
apply_style()returns a dict containinglatex_active,latex_probe_error, andscienceplots_available. Persist these intoplot_manifest.json(or per-plot metadata) so downstream readers can tell which rendering mode produced the figure. - PDF font embedding: the shared helper sets
pdf.fonttype=42andps.fonttype=42so PDFs embed TrueType fonts. Type-3 fonts are rejected by many journals. - Color palette: Okabe-Ito (colorblind-safe) by default;
TAB10is available as a fallback constant. The cycle is unified across all templates so the same series gets the same color across plots in a report. When series ordering varies between plots, pin colors with an explicitseries -> colordict. - Figure size standards (constants in
_plot_style.py): FIGSIZE_SINGLE= (3.5, 2.6) — single-column journal figure (Nature single-column = 3.5 in)FIGSIZE_ONE_HALF= (5.0, 3.2) — 1.5-columnFIGSIZE_DOUBLE= (7.0, 3.6) — full-width / double-column (Nature double-column = 7.2 in)FIGSIZE_PANEL_WIDE= (7.2, 2.8) — 2-up panel base height- In-figure title vs. caption: journal-style figures usually keep the title in the caption only. Templates include
ax.set_title(...)for convenience; remove it (or leave empty) when the report caption already states the same thing. - Raw-data contract: save the CSV consumed by each plot script to
plots/data/.csvand record the path inplot_metadata.source_context. Scripts should be reproducible from a single CSV input. - Keep filenames stable and descriptive; rebuild
plot_manifest.jsonafter any plot change. - Use the templates in
assets/plot_templates/as starting points for learning curves, grouped comparisons, or multi-panel ablations.
Common plot pitfalls to prevent
The most frequent silent failures when generating research plots. The shared _plot_style.py helper guards against most of these; the rest belong to drafting discipline.
| # | Pitfall | Why it bites | Prevention | |---|---------|--------------|------------| | 1 | Unescaped % under text.usetex=True | % is a LaTeX comment; "95%" silently becomes "95" | Default use_latex=False; otherwise wrap text with latex_escape() | | 2 | Other unescaped LaTeX specials (& # _ $ { }) | Same class as #1 — silent or noisy errors | latex_escape() covers all of them | | 3 | Korean / CJK in axis labels, legends, titles | Glyph fallback to □, no warning | English-only rule + assert_english() runtime check | | 4 | Type-3 fonts in saved PDFs | Many journals reject; reviewers cannot select text | pdf.fonttype=42, ps.fonttype=42 set in apply_style() | | 5 | Non-colorblind-safe palette (red+green) | ~8% of male readers cannot distinguish | Okabe-Ito default in apply_style() | | 6 | Inconsistent series-to-color mapping across plots | "Series A" is blue in fig 1 but red in fig 2 | Single shared cycle; pin colors via dict when ordering varies | | 7 | legend(loc="best") on dense plots | Non-deterministic placement, layout shifts run-to-run | Pick an explicit loc=... for production figures | | 8 | tight_layout() clipping suptitle | suptitle gets cut off | constrained_layout=True or subplots_adjust(top=0.85) | | 9 | Forgetting plt.close(fig) in batch generation | Memory leak; "RuntimeWarning: figures retained" | save_figure() always closes | | 10 | np.log of zero/negative on log axis | Silent NaN, missing data | Validate inputs; use symlog if zero is meaningful | | 11 | Categorical x-axis without set_xticklabels | Numeric tick labels appear instead of names | Always call set_xticks and set_xticklabels together | | 12 | Grid drawn over data | Distracting; data legibility hurt | axes.axisbelow=True (set in shared helper) | | 13 | plt.show() in scripts run by automation | Blocks pipelines; CI hangs | Templates never call plt.show() | | 14 | .savefig() after plt.close() (or vice versa) | Empty/black PDFs | save_figure() enforces correct order | | 15 | 96 dpi PNG used for print | Pixelation in printed reports | savefig.dpi=300 enforced | | 16 | Hardcoded font (Times New Roman, etc.) not installed | Silent fallback to DejaVu — different look from preview | Do not override font.family per-script; use shared helper | | 17 | transparent=True on a white-background figure | Background drops, looks wrong on colored pages | Leave default white background | | 18 | Mismatched DPI between PNG and PDF | Tick label spacing differs across formats | Set savefig.dpi once globally | | 19 | Empty alt text in ` | Validator warns; accessibility regression | Always pass meaningful alt; copy from manifest caption | | 20 | Plot manifest path drift after directory rename | Captions reference stale paths; build fails | Keep paths relative to report root; rebuild manifest after moves | | 21 | science/nature styles WITHOUT LaTeX rendering | scienceplots' science.mplstyle sets text.usetex: True AND font.family: serif. Override text.usetex=False and Times silently substitutes to DejaVu Sans on machines without Times — figures look like default matplotlib, scienceplots is invisible. | applystyle() defaults to uselatex=True; auto-probes for latex + dvipng and appends scienceplots' no-latex style to the chain when LaTeX is missing. **Never set text.usetex=False after plt.style.use(['science']) without also adding 'no-latex' to the chain.** | | 22 | Silent fallback when scienceplots is missing | Final figures look unlike previews | Record scienceplotsavailable from applystyle() in plot metadata | | 23 | Hardcoded font.family override after apply_style() | Re-introduces pitfall #21 | Treat the helper output as authoritative; do not touch font.*` rcParams in scripts |
Step 6 — Draft the report
- Use
references/report_template.mdas the starting structure. - Embed each plot inline near the paragraph that interprets it. Never write a "list of figures" appendix table — that is an anti-pattern.
- Never use passive references such as "as shown in the figure below" or "see Figure X" without an accompanying concrete quantitative observation in the same paragraph (e.g., specific deltas, percentages, R², slope, p-values, runtime). The figure earns its space by being interpreted.
- When a section depends on prior work or benchmark framing, use curated results from
reference-searchand mention only references you actually reviewed. - Avoid fake citation placeholders or generic "prior work shows" wording without concrete support.
- Avoid orphaned figures and unsupported quantitative claims.
- If a canonical section has no source material, rename or repurpose it instead of leaving a hollow placeholder.
- For dense reports, add `
markers near the paragraph that consumes evidence idev-N, and list the evidence inventory at the top of the report or inevidence/inventory.json` so the validator can cross-check.
Report-body math conventions (LaTeX-only)
Every mathematical expression in report.md MUST use LaTeX. Unicode math symbols are not acceptable in the report body — they cause inconsistent rendering across PDF exporters (Typora, Pandoc, Marp, GitHub) and many journal stylesheets refuse to typeset them.
Inline math ($...$) — use for variable names, parameter values, complexity
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Axect
- Source: Axect/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.