Mode Guide
Per-mode workflow detail for the five cover-letter modes. The single command surface is scripts/cover_letter.py --mode <mode>; the only flags it accepts are --mode, --manuscript, --letter, --journal (alias --venue), --json, and --dedup-length (journal-fit mode only; see Mode 2 and Mode 4). align-check runs as a default capability inside generate and optimize.
Mode 1: generate
Trigger: user has a main.tex manuscript and wants a cover letter from scratch.
Inputs:
--manuscript <main.tex>(required;\input/\includeskeletons are assembled automatically)--journal <venue-name>(one of: nature, science, cell, ieee-trans, acm, springer-lncs, neurips, icml, cvpr, generic)--jsonfor structured output (the facts blob + deterministic draft scaffold)
Workflow steps:
cover_letter.py --mode generaterunsextract_manuscript_facts(title, abstract, contributions, authors, corresponding author, section anchors) and emits a deterministic draft scaffold.- Read
templates/<journal>.mdfor tier strategy and required declarations. - Read
references/LETTER_STRUCTURE.mdfor the five-segment scaffold. - Read
references/JOURNAL_TIERS.mdfor the tier-specific framing rules. - Claude synthesizes the letter prose, filling each segment with facts and the tier's style guide.
- Default align-check integration: if the synthesized letter is saved to a file, run
--mode align-checkagainst it; anyclaim_accuracyissue withclaim_strength: unsupportedmust be resolved before presenting the letter. - Run
--mode presubmissionon the final letter and surface findings (declarations, length, clichés, tone).
Corresponding-author extraction trusts only an explicit \corresponding{...} or \correspondingauthor{...} command. IEEE \thanks{...} and acmart \authornote{...} prose intentionally fall back to the first parsed author: guessing from free text can mistake an email local part for a person's name. Confirm the corresponding author manually when those template-specific forms are used.
Output: the cover letter text, plus % PRESUBMISSION and % ALIGNCHECK comment blocks listing any unresolved findings.
Mode 2: optimize
Trigger: user has an existing cover letter draft and wants it improved.
Inputs:
--letter <cover_letter.md|.tex>(the existing draft)--manuscript <main.tex>(recommended; enables the align-check pass)--journal <venue-name>(informs tier strategy)--jsonfor structured output
Workflow steps:
cover_letter.py --mode optimizerunspresubmission_checkand (when--manuscriptis given)align_check.- Read
templates/<journal>.mdfor tier strategy. - Claude proposes section-level rewrites as LaTeX-comment diff suggestions (never source edits), each anchored to a line in the original letter.
- Any rewrite that introduces a new claim must pass align-check (trace to manuscript evidence or be flagged for user verification).
- Re-run
--mode align-checkon proposed rewrites saved to a file to confirm no regression. - If a
journal-fitpass is also run in this session (optional; see the Mode Integration Matrix), pass--dedup-lengthso the two checks do not both report the same templateword_limit—optimize's ownpresubmissionpass already reports length via its finer-grained two-tierL1check.
Output: a LaTeX-comment review of the original letter with severity / priority / suggested rewrites.
Mode 3: align-check
Trigger: user explicitly wants to verify the cover letter does not overclaim relative to the manuscript.
Inputs:
--letter <cover_letter.md|.tex>--manuscript <main.tex>--jsonfor machine-readable output
Workflow steps:
- Read both files (the manuscript is assembled across
\input/\include). - Build the manuscript anchor set (
extract_manuscript_facts). - Extract claim candidates from the letter (
build_letter_claim_map); the claim map reportstotal_claim_sentencesandtruncatedwhen there are more candidates than the detail cap. - Verify each claim's quote against the manuscript (
verify_letter_against_manuscript): exact match, paragraph-local number+metric co-occurrence, or 4-gram. - Classify each claim with
claim_strengthand emit findings using the simplified ISSUE_SCHEMA. - Cross-check AI-disclosure consistency between the letter and the manuscript: if one document discloses generative-AI use (or non-use) and the other is silent, or the two contradict on polarity, emit a
moderatedisclosure_consistencyfinding. Both documents are read with%-comments stripped so a commented-out declaration does not count.
Output: claim-accuracy findings, each with the letter quote, the manuscript anchor (or none), and the recommended allowed_wording; plus at most one disclosure_consistency finding when the two documents disagree on AI disclosure.
Mode 4: journal-fit
Trigger: user wants to know whether the letter is framed correctly for the target venue.
Inputs:
--letter <cover_letter.md|.tex>--venue <venue-name>(alias of--journal)--jsonfor structured output--dedup-length(optional; default off): skip this mode's own word-count sub-check when apresubmissionpass in the same session already reports length via its finer-grainedL1check (see Mode 2 step 6 and the Mode Integration Matrix).
Workflow steps:
- Read the letter.
- Read
templates/<venue>.mdfor the tier and venue expectations. - Read
references/JOURNAL_TIERS.mdfor tier strategy. journal_fit_checkscores four sub-axes:scope_fit: does the letter name the venue's scope dimensions? (top-journal tier: one matched keyword is enough for HIGH, reflecting the tight ~350-word budget; other tiers need two.)novelty_framing: is the novelty pitch calibrated for the tier?evidence_density: does claim density match what the venue expects?format_compliance: word count (skipped when--dedup-lengthis set), required declarations, banned phrases.
- Overall verdict = worst sub-axis (LOW anywhere → LOW; else MEDIUM if any MEDIUM; HIGH only when all four HIGH).
- A response with no
tierin the active template's frontmatter is reported inwarnings(defaults to mid-journal scoring).
Heuristic limitations (disclose to the user): journal-fit is a [Script] heuristic, not editorial judgment. scope_fit matches a small fixed keyword set per venue, so a well-targeted letter that phrases scope differently can read LOW; evidence_density counts LETTER_CLAIM_PATTERNS claim-bearing sentences (the same extractor align-check uses — first-person "we report/show/...", "our work," direction+number, deployment, and similar claim styles), so a letter that avoids all of those styles can still undercount. Treat the verdict as a prompt to check framing, not a gate. Manuscript content is not read in this mode.
Output: per-axis verdict (HIGH / MEDIUM / LOW) with quotes as evidence; overall verdict; per-axis suggestions.
Mode 5: presubmission
Trigger: user wants declaration, length, cliché, and tone checks only.
Inputs:
--letter <cover_letter.md|.tex>--journal <venue-name>(enables the template-driven declaration and length checks)--jsonfor structured output
Workflow steps:
- Read the letter (
errors="replace", so non-UTF-8 letters do not crash). - Load the active template's frontmatter (no PyYAML dependency).
- Scan: em dash (
G1), AI-tone frequency (AI*, 2 = minor / 3+ = major), diverse AI-tone vocabulary (AI-DIV), parallel paragraph openings (S1), uniform sentence length (S2), opener clichés (L2*), banned phrases (J1*), generic-fit phrasings (J4*), required/optional declarations (D-*), length (L1), paragraph shape (G2/G3). - Declarations without a detector emit an informational
D-<kind>-unknown(required) or are skipped (optional) rather than a false "absent".
Output: a list of presentation / declaration / tone findings.
Mode Integration Matrix
| Mode | Calls extract_manuscript_facts | Calls align_check | Calls presubmission_check | Calls journal_fit_check |
|---|---|---|---|---|
generate | Always | Always (after synthesis) | Always (final pass) | Optional |
optimize | If --manuscript provided | If --manuscript provided | Always | Optional |
align-check | Always | Always | No | No |
journal-fit | No | No | No | Always |
presubmission | No | No | Always | No |
generate and optimize's "Optional" journal_fit_check call always runs alongside a mandatory presubmission_check pass in the same session — pass --dedup-length to that journal-fit call so length is reported once (via presubmission's L1), not twice.
Routing Rules
- Default to
generateonly when no existing letter is provided. - Default to
optimizewhen both letter and manuscript are provided and the user does not name a mode. align-checkandjournal-fitare explicit-only — invoke them by name.- If the user asks to "review my cover letter" without naming a mode, prefer
optimize(which already runs align-check + presubmission).