Other agents:
AGENTS.mdmirrors the cross-agent must-knows. Codex CLI, recent Aider, and several other tools auto-loadAGENTS.md; keep them in sync when you change rules. Detailed rules now live in.claude/agents/, organised into two subfolders —rules/(read-only reference subagents:code-quality-reviewer,compliance-auditor,slide-deck-rules,deck-design,env-vars,language-vocabulary-check,paper_rule) andtasks/(task-running / multi-tasking agents:dod-verify,paper-summary-author,thesis-deck-author,post-author-audit,slide-overflow-check). Claude Code discovers them recursively byname:, so the path never affects how an agent is invoked. Full path index: see "Where the detailed rules live" below.
ThesisAgents is a Python CLI + MCP assistant that turns a research topic into thesis-ready deliverables (slide decks, BibTeX, summaries, structured JSON). The name names its two pillars, and both bind the code rather than just the branding:
- Thesis — the rich-tier output is not a generic paper summary but a
thesis-structured one. Every
PaperSummaryfield maps to a canonical thesis section (pain_points→ 1.2 motivation,contributions_detailed→ 1.5,evaluation_sections→ §4,limitations→ 5.3, …) and a deliverable deck is judged complete only when it covers the seven sections encoded in thepaper_rulesubagent (Abstract, Introduction, Literature Review, Methodology, Experiment & Evaluation, Conclusion, References). See "Paper Writing Rules" below. - Agents — the workflow is governed by a set of specialised subagents under
.claude/agents/, split into read-onlyrules/(consulted inline as you work) and task-runningtasks/(dispatched to do work, runnable in parallel / the background). The reading-the-right-subagent-first gates in this file are HARD requirements, not suggestions — see "Where the detailed rules live".
Concretely, the assistant:
- Searches academic papers by user-supplied keywords across multiple sources (arXiv, Semantic Scholar, OpenAlex, PubMed, IEEE Xplore, ACM Digital Library, DBLP, Crossref, OpenAIRE, Springer Nature, Google Scholar). Each source ships behind a fetcher adapter — adding a source does not touch the exporter layer or MCP server.
- Normalises results into a
Paperrecord, de-duplicates by DOI / arXiv ID / title-fuzzy-match, ranks by recency + citation count. - Optionally enriches each paper into a structured
PaperSummaryvia either the LLM-as-agent flow (no API key — MCP-aware LLM authors the summary) or the Python pipeline (ANTHROPIC_API_KEYset — Anthropic API call). - Generates
.pptx(three rendering tiers — lightweight / enriched-flat / thesis-style),.xlsx,.bib,.md,.jsonoutputs. - Exposes every step as an MCP tool (
search,fetch_paper,fetch_pdf_text,export,pptx_inspect,pptx_review,pptx_update_slide,pptx_delete_slide,pptx_reorder_slides,pptx_add_slide).pptx_reviewaudits an existing deck (overflow + colour contracts +paper_rulesection completeness) in one call — the same audit the CLI exposes aspython -m thesisagents review <deck.pptx>.
Single-process, Python 3.12+. Heavy I/O off the event loop; shared
httpx.AsyncClient registry pools connections per source.
ThesisAgents/
├── thesisagents/ # main package (everything installable lives here)
│ ├── core/ # Paper / PaperSummary / Query models, dedup, ranking, pipeline
│ ├── fetchers/ # HTTPS-only shared client, token-bucket rate limit, WebRunner browser
│ ├── exporters/ # pptx (rich + lightweight), xlsx, bibtex, markdown, json + pptx_edit + i18n
│ ├── intelligence/ # PDF fetch/extract + Anthropic summariser ([intelligence] extra)
│ ├── mcp/ # FastMCP server registering all tools
│ ├── sources/<name>/ # per-source plugins (arxiv/, semantic_scholar/, openalex/, pubmed/,
│ │ # ieee/, acm/, scholar/, dblp/, crossref/, openaire/, springer/)
│ ├── utils/ # logging, path safety, async helpers
│ ├── cli.py # argparse CLI
│ └── __main__.py
├── tests/ # pytest + recorded fixtures (hermetic, no live HTTP)
├── docs/ # Sphinx tree (en + zh-tw + zh-cn)
├── scripts/ # one-off regen / fixture-record scripts
├── pyproject.toml # ruff, bandit, build, optional extras
└── .bandit # canonical bandit skip list
Every change MUST pass the full gate set before commit. Delegate to the
dod-verify subagent — it owns the exact gate list, commands, and pass/fail
report format (and chains slide-overflow-check when exporters/i18n change,
code-quality-reviewer for deeper code-quality review,
compliance-auditor for project conventions). Skipping a gate "to come back
later" is not allowed.
Every addition to this project — a new rule in a subagent doc, a new paragraph in a paper, a new bullet on a slide, a new constant or helper in code — must (1) have clear context for why it exists and (2) carry a detailed enough explanation that a reader who didn't witness the change can act on it without further questions.
Concretely:
| Addition type | "Clear context" means | "Detailed explanation" means |
|---|---|---|
| Subagent rule | A Why: clause naming the past incident / failure mode the rule prevents. | At least one example of the rule applied + one anti-pattern showing how it fails. Rules without examples bit-rot. |
| Paper / thesis paragraph | A topic sentence locating the paragraph in the larger argument (which section, which RQ, which contribution). | Every technical term defined at first use (see paper_rule "Technical terminology"), every quantitative claim cited or shown in a table, and an argument-level plain-language layer so a non-expert grasps the point, not just the words (see paper_rule "Plain-language comprehensibility"). |
| Slide bullet | A sub-head that says what the slide as a whole is about. | Every acronym / math notation / library name glossed at first use (see slide-deck-rules §8 "Content clarity & first-use context"), plus a plain-language takeaway the slide's whole point lands for a non-expert reading at presentation speed (see slide-deck-rules §14). |
| Code helper | A docstring naming the boundary the helper guards and the failure mode it prevents. | Type hints + one usage example in either the docstring or a unit test. |
Why this is a top-level rule rather than buried in one subagent: it
applies across every surface this project produces (rules, papers,
slides, code) and has been the single most common review-cycle source of
churn — "why does X exist?" / "what does Y do?" questions that should
have been answered at write-time. The subagent-specific applications
(paper_rule "Technical terminology" + "Plain-language
comprehensibility", slide-deck-rules §8 "Content clarity & first-use
context" + §14 "Plain-language comprehensibility for a mixed audience",
code-quality-reviewer "docstring + example") all derive from this
top-level principle. Term-level glossing answers "what does this word
mean", the comprehensibility rules answer the harder "I read every word
and still don't see the point" — both are required on any paper / deck
this project ships, so a non-expert (an adjacent-discipline committee
member, a reviewer skimming, an undergraduate) can follow it. When in
doubt about how to phrase an addition, default to "explain like the
reader just joined the conversation".
Prose punctuation in additions: prefer , (Chinese) or , (English)
to join clauses, and avoid ; / ;. Why: short comma-joined
clauses are easier to scan than semicolon-stacked compound sentences,
and mixed semicolon use creates inconsistent punctuation density across
the rule base — a reader scanning for the next rule loses focus on
"is this still part of the previous clause or a new point?". How to
apply: when a ; would join two clauses, either swap it for , /
, or split into two sentences (the second option reads even more
clearly for rule prose). Exceptions kept: math notation like
I(za;zb|Ep) retains its mandatory ; (it's part of the operator
syntax, not prose), and APA in-text citation grouping like
(Lee, 2023; Smith et al., 2024) keeps ; because APA mandates it as
the separator inside a single citation parenthesis.
- NEVER add
Co-Authored-Bylines. - NEVER mention "Claude", "Claude Code", "AI-generated", "GPT", "Copilot", or any AI tool / model name anywhere — commit messages, PR titles, PR descriptions, code comments, documentation.
Before triggering ANY search that involves paywalled publishers
(IEEE / ACM / Springer / etc.), the LLM in this session MUST confirm
the user's VPN / institutional access status first — either by
recalling a recent statement, or by asking via AskUserQuestion
("Do you have VPN for IEEE / ACM / Springer for this topic?").
Without VPN, IEEE returns abstract-only / 403 for the PDF stage and
the per-paper download fails. When the user says no VPN, restrict
the search to arxiv,openalex,pubmed,crossref,dblp,openaire,scholar
— that is, skip only ieee. Google Scholar is publicly
accessible and stays in the mix even without VPN (Chrome still boots
for it because of captcha resilience, but the search itself works).
This gate applies BEFORE running python -m thesisagents -q …,
before scripts/llm_driven_search.py, and before any
scripts/llm_download_*pdf*.py invocation.
IEEE search, IEEE document fetch, Google Scholar search, and any paywalled-PDF download from publisher CDNs (ieeexplore.ieee.org, dl.acm.org, link.springer.com, sciencedirect.com, wiley/oup/nature/science/…) MUST go through visible Chrome. Two paths exist:
- Python pipeline — IEEE / Scholar plugins under
thesisagents/sources/<name>/call their ownwebrunner_backendfrom insideasyncio.gather. Used by the CLI in unattended mode. - LLM-as-agent — the LLM in a Claude Code session drives Chrome itself via
Bash +
thesisagents.fetchers.webrunner_browser.make_driver(). Reference:scripts/llm_driven_search.py+scripts/llm_parse_results.py. Themcp__webrunner__*server registered for this project only exposes static helpers (lint / translate / score) — it does NOT exposewebrunner_run_actionsor any other browser-driving tool, so the LLM cannot skip the Bash + Selenium step.
The httpx branch in those plugins is a CI safety net for no-Chrome environments;
on a user machine with VPN, silent fall-through to httpx is a bug. Never
suppress the visible window (--headless, etc.). If you don't see a Chrome
window open during an IEEE / Scholar / paywalled-PDF step, the path is broken
— surface it, don't trust the results. Full rule + audit checklist:
compliance-auditor subagent.
Before opening any .pptx file in this repository for edit — whether it
was generated by ThesisAgents's exporter or supplied by the user as a
hand-made deck (e.g. anything under exports/, assets/template/, or any
ad-hoc path) — you MUST read .claude/agents/rules/deck-design.md AND
.claude/agents/rules/slide-deck-rules.md first, in the same turn as the edit.
"Just reordering slides" / "just fixing typos" / "just adding a slide" all
count as edits. There is no exemption for hand-made decks: the dark-mode
contract, no-red-text contract, and light-on-light contrast contract apply
to every .pptx this project produces or modifies.
After the edit, audit the resulting deck against those subagents' contracts:
- Background is white (the default light navy-band deck) unless the
user explicitly opted into dark mode (
--dark-mode,dark_mode=True, GUI "Dark mode" checkbox), in which case it is_DARK_SLIDE_BG(#12151B). - No text run has
rgb=Noneorrgb=(0,0,0)(invisible on dark bg). - No light fill contains light text (luminance > 0.7 × 255 on both).
- No
#C0392Bred text runs (banned in both modes). - Navy header band (
accent_top) + full-bleed navy cover (accent_left) geometry present on ThesisAgents generated decks (hand-made decks are exempt from accent geometry but not from dark-mode / no-red / contrast contracts).
For hand-made decks that don't follow the project's _BRAND_* constants,
run _apply_dark_mode(prs) from thesisagents.exporters.pptx as a
post-pass — the _swap_text_colors safety net promotes None / pure-black
runs to #E5E7EB near-white, and _set_slide_background sets every slide
to #12151B.
The same "read-subagent-first" gate applies analogously to other deliverable surfaces:
| Editing this surface | Read these subagent(s) FIRST |
|---|---|
Any .pptx (generated or hand-made) |
deck-design, slide-deck-rules |
thesisagents/exporters/pptx.py visual code |
deck-design, slide-deck-rules |
thesisagents/exporters/i18n.py or any localised string |
slide-deck-rules, language-vocabulary-check |
Source plugins under sources/ or thesisagents/fetchers/ |
compliance-auditor |
| Paper / thesis text in any locale | paper_rule |
Hand-authoring PaperSummary from a PDF |
paper-summary-author, paper_rule |
| Authoring a degree-thesis defence deck from the candidate's own thesis | thesis-deck-author, paper_rule, deck-design |
| Anything before commit | dod-verify (gate runner) |
When in doubt, read more subagents, not fewer. The subagent rules exist because their violations have shipped before — skipping them is a known failure mode, not a corner case.
Dark mode is an opt-in pptx render path (the default is the light
navy-band deck), but the contract still binds every build because the
exporter always builds with the light palette first and a deck may be
rendered dark at any time. The post-build recolour pass swaps light-palette
RGB values to their dark-palette equivalents — but it can only swap colours
it can read. A text run with run.font.color.rgb = None inherits the
slide-master's theme colour, renders as near-black on the dark slide
background, and is invisible. Every text-adding helper in
thesisagents/exporters/pptx.py MUST therefore assign
run.font.color.rgb = _BRAND_* (one of the four
palette constants) after creating or overwriting a run. Never leave the
colour at its default; never pass colour=None to _add_textbox;
never write RGBColor(0, 0, 0) — use _BRAND_DARK instead.
The _swap_text_colors pass in the dark-mode post-build now also
promotes any leftover rgb is None or (0, 0, 0) runs to #E5E7EB
near-white as a second layer of defence. The regression test
tests/test_exporters.py::test_pptx_dark_mode_has_no_invisible_runs
walks every run on every slide and fails if any non-empty run lacks an
explicit non-black colour. Full rule + the audit script + the
two-layer defence rationale live in .claude/agents/rules/deck-design.md
"Dark-mode contract".
Mirror rule — light-on-light contrast. Any new light-fill RGB
introduced in pptx.py (e.g. a callout / KPI / RQ-box background)
MUST also have an entry in _LIGHT_TO_DARK_FILL; otherwise the fill
stays near-white in dark mode while its text gets re-coloured to
near-white → invisible. Regression test
test_pptx_dark_mode_no_light_text_on_light_fill walks every shape
and fails when both fill and text luminance are > 0.7 of 255 in a
default-dark-mode render.
No red text. _BRAND_ACCENT (= #C0392B warm red) is BANNED
as a TEXT colour across both light and dark modes. Red text reads
as error / warning in slide conventions and pattern-matches strongly
to AI-generated KPI emphasis. The sanctioned text-emphasis colour is
_BRAND_HIGHLIGHT (academic blue-600, #2563EB) — pair with
run.font.bold = True. Use _BRAND_GREY for caption / placeholder /
chrome text so headlines stay headlines. Variety rule: KPI value + RQ
question use blue, figure caption + figure-unavailable use grey — do
not collapse all four to the same colour. The dark-mode pass swaps
blue-600 → blue-400 (#60A5FA) via _LIGHT_TO_DARK_TEXT, the
audit script's _ACCEPTED_DARK_RUN_COLORS set knows about both.
Regression test test_pptx_no_red_text_runs walks every run on a
default-rendered deck and fails if any run uses #C0392B. The red
constant stays in the palette in case a future non-text accent shape
(sparkline, status badge) wants it. Full rule + per-call-site palette
mapping in .claude/agents/rules/deck-design.md "No red text contract (HARD)".
Thesis / journal / conference paper structure follows the user-supplied
《論文撰寫指引》, encoded in full as the paper_rule subagent. The
subagent is multilingual — every rule is given in English + 繁體中文
(authoritative source) and the canonical section names are tabulated for
all 14 project locales (en, zh-tw, zh-cn, ja, ko, es, fr, de, pt, it, ru,
ar, hi, vi). paper_rule auto-detects the user's working language and
responds in it; section numbers (1.1, 2.3, 4.5, …) stay universal for
unambiguous cross-reference. The seven canonical sections —
Abstract, Introduction (1.1 background / 1.2 motivation / 1.3 problem /
1.4 objectives / 1.5 contributions / 1.6 structure), Literature Review
(incl. 2.3 comparison table + 2.4 research gap), Methodology (incl.
3.1 architecture diagram / 3.5 evaluation metrics), Experiment &
Evaluation (incl. 4.4 result charts / 4.5 result analysis / fair
comparison), Conclusion (incl. 5.3 limitations / 5.4 future work),
References (last 5 years preferred; international journals > conferences;
English-dominant) — are the default skeleton for any thesis-style
deliverable in this project, regardless of deck locale.
Two places this binds the code:
PaperSummaryfield authoring (e.g.paper-summary-authorsubagent). Each rich-tier field maps to a thesis section:pain_points→ 1.2,contributions_detailed(cap 4) → 1.5,technique_table→ 2.3,system_flow→ 3.1,method_sections→ 3.2-3.4,headline_metrics+evaluation_sections→ 4.4-4.5,research_questions+rq_results→ 1.3 + 4.5,core_observation→ 5.1,limitations→ 5.3,future_work→ 5.4. Full mapping table inpaper_rule.- Thesis-style
.pptxcompleteness audit. A rich deck that drops the Literature Review, Experiment, or Conclusion section is incomplete — even ifslide-overflow-checkpasses geometrically. Consultpaper_rulebefore declaring a deck deliverable.
When the user is writing or reviewing their own paper text (not generating
slides), quote the relevant paper_rule clause directly (e.g.「依 1.4 應寫
3-5 點研究假設」, 「2.3 缺缺點欄位」).
Subagent docs are organised into two subfolders under .claude/agents/.
Claude Code scans that directory recursively, so the subfolder path does
NOT change how an agent is invoked — identity comes only from each file's
name: frontmatter (names are unique across the tree). The split mirrors the
two kinds of subagent this project uses:
rules/— read-only rule / reference subagents, consulted inline while you work.tasks/— task-running agents, dispatched to do work and able to run in the background / in parallel (the "multi-tasking" set).
.claude/agents/
├── rules/ code-quality-reviewer · compliance-auditor · slide-deck-rules ·
│ deck-design · env-vars · language-vocabulary-check · paper_rule
└── tasks/ dod-verify · paper-summary-author · thesis-deck-author ·
post-author-audit · slide-overflow-check
| Topic | Subagent | File (under .claude/agents/) |
|---|---|---|
| Design patterns, SOLID, performance, async, unit tests, full linter rule set | code-quality-reviewer |
rules/code-quality-reviewer.md |
| Core-vs-source-plugin boundary, network safety, browser-automation hard rule, path safety, suppression conventions, bandit skip config | compliance-auditor |
rules/compliance-auditor.md |
| pptx exporter geometry, rendering tiers, truncation caps, semantic shape names, i18n, LLM-as-agent vs Python pipeline | slide-deck-rules |
rules/slide-deck-rules.md |
| pptx visual identity (typography per language, brand palette, accent geometry, master-slide expectations, "looks AI-generated" anti-patterns) | deck-design |
rules/deck-design.md |
Env vars + Python / .venv toolchain reference |
env-vars |
rules/env-vars.md |
| Language-correct vocabulary (no S-Chinese loan words in zh-tw, no T-Chinese in zh-cn, etc.) | language-vocabulary-check |
rules/language-vocabulary-check.md |
| Academic paper writing rules (multilingual, all 14 locales) — Abstract / Introduction / Literature Review / Methodology / Experiment / Conclusion / References structure + PaperSummary-to-section mapping | paper_rule |
rules/paper_rule.md |
| Definition-of-Done gate runner | dod-verify |
tasks/dod-verify.md |
| LLM-as-agent thesis-style authoring (PDF → rich PaperSummary) | paper-summary-author |
tasks/paper-summary-author.md |
Degree-thesis ORAL-DEFENCE deck from the candidate's OWN thesis (seven paper_rule sections → rich deck) |
thesis-deck-author |
tasks/thesis-deck-author.md |
| URL-fabrication / off-topic / drafting-metadata-leak / flat-math audits after authoring | post-author-audit |
tasks/post-author-audit.md |
| Slide-overflow regression check | slide-overflow-check |
tasks/slide-overflow-check.md |