Citation Placement
Unified router for three citation workflows. A single Tkinter launcher collects
inputs and writes run_config.json; the "pipeline" value selects one of three
modes, each with its own detailed workflow document.
Modes and Routing
| Mode |
pipeline value |
What it does |
Workflow doc |
| Inline placement |
inline |
Places screened citations as inline \cite{} / \citet{} / \citep{} commands with a compiled references.bib. For economics, finance, and social-science journals (APA, MLA, Harvard, Chicago author-date, IEEE, Vancouver). .tex only. |
references/phase-details-inline.md |
| Footnote placement |
footnotes |
Places screened citations as full formatted \footnote{} (LaTeX) or native OOXML footnotes (Word), with one-click legal/notes style selection (Bluebook, OSCOLA, Chicago notes-bib, APA 7th, McGill) and Id./supra short-form post-processing. .tex or .docx. |
references/phase-details-footnotes.md |
| Restyle |
restyle |
Converts ALL existing footnote citations (hand-written or pipeline-placed) from one style to another. No spreadsheet required. .tex or .docx. |
Restyle Pipeline section of references/phase-details-footnotes.md |
Read the relevant workflow document at the start of each phase.
Launcher-First Protocol
When the user triggers this skill:
- Run the launcher with a 10-minute timeout (the user needs time to browse
and configure), using the skill's known absolute directory as
[skill-dir],
not the current working directory:python "[skill-dir]/scripts/launcher.py"
Call it via the Bash tool with timeout: 600000.
- The unified GUI presents the file fields and options for all three modes and
offers three run buttons — Inline Placement, Footnote Placement, and
Restyle — plus a Utilities area (Strip All Citations; Regenerate /
Reorder Cross-Refs, with or without an existing registry). On any run button
the launcher validates inputs and writes
placement/run_config.json in the
output file's parent directory, then prints machine-readable status lines
to stdout.
- Parse the launcher's stdout:
LAUNCHER_STATUS: success — proceed. If missing or cancelled, stop.
LAUNCHER_CONFIG_PATH: <path> — the absolute path to run_config.json.
Use this path for all subsequent phases. All paths inside the config are
absolute; do not assume the config lives in the current working directory.
- Read
run_config.json and route on config["pipeline"]:
"inline" → run the inline placement pipeline (references/phase-details-inline.md).
"footnotes" → run the footnote placement pipeline (references/phase-details-footnotes.md).
"restyle" → run the restyle pipeline (Restyle Pipeline section of references/phase-details-footnotes.md).
- Run the selected pipeline end-to-end without asking questions or waiting for
confirmation between phases. The only pause is the Phase 4 human-in-the-loop
gate in the two placement modes, and only when
auto_approve is false.
run_config.json shapes
The config always lives at <output_parent>/placement/run_config.json. The
"pipeline" key selects the shape:
// inline
{"pipeline": "inline", "input_format": "tex", "project_folder": "...",
"input_tex": "...", "input_xlsx": "...", "output_tex": "...",
"citation_style": "apa|mla|harvard|chicago_author_date|chicago_notes|ieee|vancouver",
"replan": false, "auto_approve": false, "citation_mode": "selective|comprehensive",
"insertion_style": "prose|simple", "verify_citations": false}
// footnotes
{"pipeline": "footnotes", "input_format": "tex|docx", "project_folder": "...",
"input_tex": "...", "input_xlsx": "...", "output_tex": "...",
"replan": false, "auto_approve": false,
"citation_style": "bluebook|oscola|chicago|apa|mcgill",
"citation_mode": "selective|comprehensive", "verify_citations": false,
"pincites": false, "pdf_folder": null}
// restyle
{"pipeline": "restyle", "input_format": "tex|docx", "project_folder": "...",
"input_tex": "...", "input_xlsx": null, "output_tex": "...",
"current_style": "...", "target_style": "..."}
Citation slots (% CITE:)
Drafts from the writing-article-plans skill mark where citations belong with
typed placeholder slots, and its assemble_manuscript.py normalizes
footnote-wrapped slots before handoff. A slot is a % CITE: LaTeX comment
carrying a typed hint (e.g. % CITE: meta-analysis on Y). Slots are a .tex
convention only — footnotes-mode .docx input has no slot support.
Core rule (both placement modes). If the input manuscript contains % CITE:
slots, every slot MUST end the run either filled or explicitly reported as
unfilled with a reason. Silent slot survival is a pipeline failure. Slots are
author-declared citation demands, so citation_mode: "selective" governs only
free placements and never skips a slot.
Three slot forms reach this skill:
- Bare comment —
% CITE: <hint> on its own line or at the end of a line.
- Footnote-wrapped, two-line (
\footnote{% / % CITE: <hint> / }) — the
normal post-assembly form (brace-safe).
- Footnote-wrapped, one-line —
\footnote{% CITE: <hint>}; compile-unsafe
(the % comments out the closing brace). Recognize it and recommend running
writing-article-plans' assemble_manuscript.py first.
% RESULT: slots belong to a different pipeline and MUST never be touched or
removed. The contract lives in the phase docs: Phase 1 enumerates slots into
citation_slots, Phase 3a fills each or defers it to unfilled_slots, Phase 4
reports the tally, and Phase 5 executes the replacements and runs a
deterministic grep closure check. See references/phase-details-inline.md
and references/phase-details-footnotes.md.
Inline Mode — Phase Overview (5 phases)
Detailed instructions: references/phase-details-inline.md.
- Phase 1 — Manuscript Mapping. Read the
.tex; produce
placement/section_map.md and placement/existing_citations.json. Detect the
citation package (natbib → \citet/\citep; biblatex →
\textcite/\parencite; else basic \cite) and the bibliography backend
(bibtex/biber). Cached unless replan is true. Read-only.
- Phase 1.5 — Existing Citation Verification (optional). Gated on
verify_citations. Flags dangling \cite{} keys, hallucinated .bib entries,
and spreadsheet overlaps into placement/audit_report.json.
- Phase 2 — Citation Ingestion.
scripts/core/ingest_citations.py turns the
.xlsx into citations.json + references_new.bib. Deterministic, no LLM.
- Phase 3 — Placement Planning (3a → 3b → 3c). 3a assigns each citation to
all supporting sections (multi-placement is normal); 3b spawns one
general-purpose sub-agent per section to draft anchors and cite commands,
keyed to
insertion_style (prose default — Types 1/2/3 with sentence
rewriting; simple — parenthetical-only, no rewriting); 3c consolidates into
placement/placement_plan.md. Cached / incremental: with replan: false,
only cite keys absent from the planned_keys header trigger new planning.
- Phase 4 — HITL Review. Always print the plan. Pause for corrections when
auto_approve is false; otherwise continue immediately.
- Phase 5 — Execution. Copy the
.tex to a versioned output, insert cites
(parenthetical = insert after anchor; prose/textual = replace anchor), merge
references_new.bib, ensure \bibliographystyle{}/\bibliography{} (or
\addbibresource/\printbibliography for biblatex), then compile with
pdflatex + bibtex/biber + two more pdflatex passes.
Footnote Mode — Phase Overview (6 phases)
Detailed instructions: references/phase-details-footnotes.md. Accepts .tex
(LaTeX \footnote{}, compiled with the manuscript's own engine — see
the Engine preservation rule below) or .docx (native OOXML
footnotes via scripts/core/docx_support/); for .docx, skip every
LaTeX-specific step (no LaTeX compile, no %CITE-PLACED, no \bibliography{}).
Engine preservation rule (2026-09-01). Never impose an engine on a
manuscript: compile with the manuscript's own engine — run python "[skill-dir]/scripts/core/tex_engine.py" <main.tex> (author's build log, else preamble signals; libertine+[T1]{fontenc} = pdflatex, fontspec = xelatex). A wrong engine substitutes
fonts SILENTLY (warnings, not errors) — compiling a libertine+T1
manuscript under xelatex rendered an entire article in Computer Modern
while reporting success. After any compile, verify parity when the
author's PDF exists: pdffonts families and page count must match it.
- Phase 1 — Manuscript Mapping. Produce
placement/section_map.md and
placement/existing_footnotes.json, classifying each footnote
(article/book/working_paper/case/legislation/cross_reference/discursive/mixed).
Cached unless replan.
- Phase 1.5 — Existing Citation Audit (optional). Gated on
verify_citations; verification cascade (OpenAlex → CrossRef → Google Scholar)
into placement/audit_report.json.
- Phase 2 — Citation Ingestion.
scripts/core/ingest_citations.py →
citations.json + references_new.bib. Deterministic.
- Phase 3 — Placement Planning (3a → 3b → 3c). Style-specific rules are read
from
references/styles/<citation_style>.md and injected into the 3b sub-agent
prompts; every placement carries the full citation string (Phase 6 handles
repeats). 3c merges same-anchor placements into single multi-citation
footnotes. Cached / incremental on the planned_keys header.
- Phase 4 — HITL Review. Pause when
auto_approve is false.
- Phase 5 — Execution. Copy the manuscript; insert each
\footnote{ with an
invisible %CITE-PLACED marker immediately after the opening brace; apply
Phase 1.5 audit fixes; tag any pre-existing footnotes with %CITE-PLACED; run
merge_adjacent_footnotes.py; then Phase 5.5 when pincites is set; then
Phase 6; then one pass of the manuscript's own engine (no
bibtex/biber; see the Engine preservation rule).
- Phase 5.5 — Pincites (optional,
.tex, gated on pincites). Acquire full
texts — articles via OA → LibKey → HeinOnline/EZproxy, books/chapters via
pdf_folder/OA/publisher search, cases via generic web search (any
jurisdiction, best-effort). SSRN is NEVER fetched by the scripted session
(it bot-blocks; the author 2026-08-30) — SSRN PDFs come through the user's
Claude-in-Chrome browser into pdf_folder; acquire marks such works
unacquired naming that route — verify printed-page maps (folio anchors; star
pagination or paragraph numbers for cases), locate verbatim supporting quotes
via Opus subagents, (the ABSTRACT and the
INTRODUCTION are banned as support — quotes come from where the body
develops the point, and a claim only ever announced gets no pincite), derive pages mechanically, rewrite footnotes, write
placement/pincite/pincite_report.md. See Phase 5.5 in
references/phase-details-footnotes.md. Subagent cap: at most 8
concurrent agents for ANY fleet this skill spawns (locators included) —
more risks account rate limits (the author, 2026-08-30); shard the work and
queue the remainder instead.
- Phase 6 — Short-Form Post-Processing.
short_form.py converts repeat
citations to the style's short form (Id./ibid/supra/shortened title/author-date)
and writes placement/footnote_registry.json for later cross-reference
reordering. Runs automatically after Phase 5; compile twice with the
manuscript's own engine to settle
footnote numbers.
Pincite remediation loop (Phase 5.5, after any apply round)
Not-placed occurrences are TRIAGED, never hand-fixed ad hoc: every one lands
in a bucket — wrong-version / verifier-false-negative / map-offset /
metadata-bleed / no-folios / by-design — and every bucket has a standard fix
(re-acquire + adopt; map_hints.json; works.json + repin; ledgered
accept). Since 2026-09-02 the map builder self-diagnoses the common
buckets — repository cover sheets are classified without hints, a preprint
that contradicts the cite reports version_mismatch (acquire or re-cite),
two folio series in one PDF ask for trailing_pages, and an article-number
page slot is settled by evidence and rendered <number>, at <page>. Since
2026-09-03 a comment line that owns its line (the %CITE-PLACED marker, an
author's own-line note) ends a citation part exactly as a ; does (where the text before it ends
a sentence and the text after it opens a citation or sentence) — a
discursive footnote's prose, marker and citation are no longer one refused
span — and a re-collect carries located quotes across a citation that only
narrowed (same occurrence, same family size, same context up to blanked
comment lines, no % trailing live text in the footnote's region); after
upgrading, RE-RUN COLLECT before apply, and read collect's own lines (re-keyed,
refused, orphaned quotes). The formatter reads an institutional author in
small caps before the title (report shape) and, for an article-numbered
Bluebook work, an article designator in the journal slot ("art. 8, at 28").
Full playbook: "Post-apply triage and remediation loop" in
references/pincite-pass-design.md. Generalization rule: per-manuscript DATA
(hint values, ledger entries) stays in the run directory; every MECHANISM
(subcommand, hint key, verifier relaxation) lands in skill code with a test —
scratchpad one-offs for recurring steps are defects.
Standalone pincite mode (existing citations, no placement run)
Phase 5.5 has no dependency on the placement pipeline. Every pincite
subcommand reads only placement/run_config.json (three keys:
output_tex, citation_style, pdf_folder), placement/citations.json,
and the manuscript itself — never %CITE-PLACED markers, a .bib, or any
other placement artifact. To pincite a manuscript whose citations the
author already wrote:
- Copy the manuscript into a working folder (never edit the author's copy
in place) and create
placement/ beside it.
- Build
placement/citations.json — one record per cited WORK, harvested
from the manuscript's own footnotes by a Phase-1-style mapping pass (the
existing_footnotes.json extracted_* fields are the template):
cite_key (stable slug), title, authors, year, journal, doi
(empty when unknown); add publisher/booktitle/entry_type where
they decide work type. Titles must be long enough to match safely —
collect drops records under 15 normalized chars (8 for cases) with a
per-key reason.
- Write
placement/run_config.json:
{"pipeline": "footnotes", "output_tex": "<working copy>", "citation_style": "<id>", "pincites": true, "pdf_folder": null}.
- Run the normal Phase 5.5 chain unchanged:
collect -> acquire ->
extract -> locator fan-out -> apply, plus repin and audit rounds
as needed.
- Skip Phase 6 — the author's own short forms stay untouched. Scope fact:
collect targets only occurrences carrying a work's full title, so
existing Id./supra/shortened-title footnotes never receive pincites;
whatever pages they already carry are the author's.
%CITE-PLACED marker rule
Every \footnote{} in a .tex output carries %CITE-PLACED immediately after
the opening brace (a LaTeX comment pdflatex ignores, so the PDF is unchanged).
The marker lets strip_citations.py cleanly remove all pipeline footnotes for a
clean re-run, and it is preserved through merge and short-form rewrites.
Interior markers are part of the same convention: a multi-citation footnote
carries one marker line above EACH placed citation (so merging N marked
footnotes yields one footnote with N markers, the head marker guaranteed),
and every rebuild (short-form, reorder, merge) preserves the marker multiset
verbatim, each marker staying with the citation it heads
(tests/test_format_preservation.py pins this).
Restyle Mode — Overview
Detailed instructions: Restyle Pipeline section of
references/phase-details-footnotes.md. Converts every existing footnote
citation from current_style to target_style, correcting Id./ibid/supra
cross-references and symbol-footnote numbering. The .tex path spawns one
sub-agent per section and finishes with merge_adjacent_footnotes.py +
short_form.py; the .docx path extracts footnotes via
scripts/core/docx_support/, restyles them, and writes back via
replace_footnote_text. Standalone drivers: scripts/docx_restyle.py and
scripts/tex_restyle.py (each takes --config placement/run_config.json). Case
citations, legislation, and discursive footnotes pass through unchanged.
Utilities
The launcher's Utilities area (and the corresponding scripts) support
maintenance outside a full run:
- Strip All Citations —
strip_citations.py removes every %CITE-PLACED
footnote, yielding a clean manuscript for a from-scratch re-run.
- Regenerate / Reorder Cross-Refs —
reorder_crossrefs.py reverses all
short forms to full citations and re-applies them with correct footnote
numbering after manual footnotes shift the numbering. Uses
placement/footnote_registry.json (created by Phase 6); when the registry is
absent it reconstructs from the current full citations.
- Migrate markers —
migrate_markers.py retroactively adds %CITE-PLACED
to footnotes in manuscripts produced before the marker convention.
Commands
[skill-dir] is the absolute path to this skill's directory. All paths shown as
placement/... are relative to the output file's parent directory.
| Command |
Purpose |
Invocation |
| Launcher |
Collect inputs, write run_config.json |
python "[skill-dir]/scripts/launcher.py" (Bash timeout: 600000) |
| Ingest |
.xlsx → citations.json + references_new.bib (deterministic) |
python "[skill-dir]/scripts/core/ingest_citations.py" --input citations.xlsx --output-json citations.json --output-bib references_new.bib [--existing-bib references.bib] [--min-score N] |
| Verify (inline) |
Audit existing \cite{} keys vs .bib + APIs |
python "[skill-dir]/scripts/core/verify_citations.py" --mode inline --citations placement/existing_citations.json --bib references.bib --output placement/audit_report.json [--spreadsheet cites.xlsx] |
| Verify (footnotes) |
Audit existing footnote citations vs APIs |
python "[skill-dir]/scripts/core/verify_citations.py" --mode footnotes --footnotes placement/existing_footnotes.json --output placement/audit_report.json [--spreadsheet cites.xlsx] |
| Merge adjacent footnotes |
Combine adjacent \footnote{}...\footnote{} (Phase 5 post-proc) |
python "[skill-dir]/scripts/merge_adjacent_footnotes.py" --input OUT.tex --output OUT.tex --style <id> --skill-dir "[skill-dir]" |
| Pincite pass |
Acquire PDFs, locate quotes, insert pincites (Phase 5.5, optional) |
python "[skill-dir]/scripts/pincite_pass.py" <collect|acquire|extract|apply|repin> --config placement/run_config.json — repin re-keys ONE target after a manual manuscript edit (--occurrence <id> [--citation "<new>"] [--key <cite_key>]; repin every sibling target of an edited footnote; --key re-binds a row collect attributed to the wrong work, moving its occurrence_id and quote rows with it; see design doc "Wrong-version remediation") |
| Short form |
Style-aware Id./supra/ibid substitution (Phase 6) |
python "[skill-dir]/scripts/short_form.py" --input OUT.tex --output OUT.tex --style <id> --skill-dir "[skill-dir]" [--plan-dir placement/] |
| Reorder cross-refs |
Fix supra/Id. after manual footnote edits |
python "[skill-dir]/scripts/reorder_crossrefs.py" --input OUT.tex [--plan-dir placement/] |
| Strip citations |
Remove all %CITE-PLACED footnotes |
python "[skill-dir]/scripts/strip_citations.py" input.tex [output.tex] |
| Migrate markers |
Add %CITE-PLACED to legacy footnotes |
python "[skill-dir]/scripts/migrate_markers.py" input.tex [output.tex] |
Restyle (.docx) |
Standalone restyle driver |
python "[skill-dir]/scripts/docx_restyle.py" --config placement/run_config.json |
Restyle (.tex) |
Standalone restyle driver |
python "[skill-dir]/scripts/tex_restyle.py" --config placement/run_config.json |
The verification report schema is unchanged from the source pipelines: inline
mode reports dangling references, per-.bib-entry verification, and spreadsheet
overlaps; footnotes mode reports per-citation verification status, Bluebook
format issues with corrected strings, and spreadsheet overlaps.
Inline vs. Footnote Mode
The two placement modes differ in output form, compilation, and style set:
| Aspect |
Inline mode |
Footnote mode |
| Citation command |
\cite{key}, \citep{key}, \citet{key} |
\footnote{Full formatted citation} (or OOXML footnote) |
.bib file |
Essential — compiled by LaTeX into the bibliography |
Vestigial record only; not compiled |
| Compilation |
pdflatex + bibtex/biber |
the manuscript's own engine, no bib tool (footnotes are self-contained; see Engine preservation rule) |
| Citation styles |
APA, MLA, Harvard, Chicago author-date, IEEE, Vancouver |
Bluebook, OSCOLA, Chicago notes-bib, APA 7th, McGill |
| Short forms (Id./supra) |
Not applicable — the bibliography style handles repeats |
Phase 6 post-processing (short_form.py) |
| Phase count |
5 phases (1–5) |
6 phases (1–6) |
| Input format |
.tex only |
.tex or .docx |
Chicago notes-bib and legal styles belong to footnote mode; the inline mode's
chicago_notes option warns and points to footnote mode instead.
1---2name: cite-placement-33description: Place pre-screened literature citations into a LaTeX or Word manuscript, or restyle the citations already in one. Three modes: (1) inline placement — inline \cite{}/\citet{}/\citep{} with a compiled references.bib, for author-date journals (APA, MLA, Harvard, Chicago author-date, IEEE, Vancouver); (2) footnote placement — full formatted \footnote{} or OOXML footnotes for legal and notes styles (Bluebook, OSCOLA, Chicago, APA, McGill) with Id./supra short forms; (3) restyle — convert existing footnote citations from one style to another. This skill is manual-invoke ONLY — trigger ONLY when the user explicitly runs /cite-placement or explicitly names the "cite-placement" skill. Do NOT auto-trigger on general citation, footnote, or reference requests.4---56# Citation Placement78Unified router for three citation workflows. A single Tkinter launcher collects9inputs and writes `run_config.json`; the `"pipeline"` value selects one of three10modes, each with its own detailed workflow document.1112## Modes and Routing1314| Mode | `pipeline` value | What it does | Workflow doc |15|---|---|---|---|16| Inline placement | `inline` | Places screened citations as inline `\cite{}` / `\citet{}` / `\citep{}` commands with a compiled `references.bib`. For economics, finance, and social-science journals (APA, MLA, Harvard, Chicago author-date, IEEE, Vancouver). `.tex` only. | `references/phase-details-inline.md` |17| Footnote placement | `footnotes` | Places screened citations as full formatted `\footnote{}` (LaTeX) or native OOXML footnotes (Word), with one-click legal/notes style selection (Bluebook, OSCOLA, Chicago notes-bib, APA 7th, McGill) and Id./supra short-form post-processing. `.tex` or `.docx`. | `references/phase-details-footnotes.md` |18| Restyle | `restyle` | Converts ALL existing footnote citations (hand-written or pipeline-placed) from one style to another. No spreadsheet required. `.tex` or `.docx`. | Restyle Pipeline section of `references/phase-details-footnotes.md` |1920Read the relevant workflow document at the start of each phase.2122## Launcher-First Protocol2324When the user triggers this skill:25261. Run the launcher with a **10-minute timeout** (the user needs time to browse27 and configure), using the skill's known absolute directory as `[skill-dir]`,28 not the current working directory:29 ```bash30 python "[skill-dir]/scripts/launcher.py"31 ```32 Call it via the Bash tool with `timeout: 600000`.332. The unified GUI presents the file fields and options for all three modes and34 offers three run buttons — **Inline Placement**, **Footnote Placement**, and35 **Restyle** — plus a **Utilities** area (Strip All Citations; Regenerate /36 Reorder Cross-Refs, with or without an existing registry). On any run button37 the launcher validates inputs and writes `placement/run_config.json` in the38 **output file's parent directory**, then prints machine-readable status lines39 to stdout.403. Parse the launcher's stdout:41 - `LAUNCHER_STATUS: success` — proceed. If missing or `cancelled`, stop.42 - `LAUNCHER_CONFIG_PATH: <path>` — the absolute path to `run_config.json`.43 Use this path for all subsequent phases. All paths inside the config are44 absolute; do not assume the config lives in the current working directory.454. Read `run_config.json` and route on `config["pipeline"]`:46 - `"inline"` → run the inline placement pipeline (`references/phase-details-inline.md`).47 - `"footnotes"` → run the footnote placement pipeline (`references/phase-details-footnotes.md`).48 - `"restyle"` → run the restyle pipeline (Restyle Pipeline section of `references/phase-details-footnotes.md`).495. **Run the selected pipeline end-to-end without asking questions or waiting for50 confirmation between phases.** The only pause is the Phase 4 human-in-the-loop51 gate in the two placement modes, and only when `auto_approve` is `false`.5253### `run_config.json` shapes5455The config always lives at `<output_parent>/placement/run_config.json`. The56`"pipeline"` key selects the shape:5758```jsonc59// inline60{"pipeline": "inline", "input_format": "tex", "project_folder": "...",61 "input_tex": "...", "input_xlsx": "...", "output_tex": "...",62 "citation_style": "apa|mla|harvard|chicago_author_date|chicago_notes|ieee|vancouver",63 "replan": false, "auto_approve": false, "citation_mode": "selective|comprehensive",64 "insertion_style": "prose|simple", "verify_citations": false}6566// footnotes67{"pipeline": "footnotes", "input_format": "tex|docx", "project_folder": "...",68 "input_tex": "...", "input_xlsx": "...", "output_tex": "...",69 "replan": false, "auto_approve": false,70 "citation_style": "bluebook|oscola|chicago|apa|mcgill",71 "citation_mode": "selective|comprehensive", "verify_citations": false,72 "pincites": false, "pdf_folder": null}7374// restyle75{"pipeline": "restyle", "input_format": "tex|docx", "project_folder": "...",76 "input_tex": "...", "input_xlsx": null, "output_tex": "...",77 "current_style": "...", "target_style": "..."}78```7980## Citation slots (`% CITE:`)8182Drafts from the `writing-article-plans` skill mark where citations belong with83typed placeholder slots, and its `assemble_manuscript.py` normalizes84footnote-wrapped slots before handoff. A slot is a `% CITE:` LaTeX comment85carrying a typed hint (e.g. `% CITE: meta-analysis on Y`). Slots are a `.tex`86convention only — footnotes-mode `.docx` input has no slot support.8788**Core rule (both placement modes).** If the input manuscript contains `% CITE:`89slots, every slot MUST end the run either filled or explicitly reported as90unfilled with a reason. Silent slot survival is a pipeline failure. Slots are91author-declared citation demands, so `citation_mode: "selective"` governs only92free placements and never skips a slot.9394Three slot forms reach this skill:951. **Bare comment** — `% CITE: <hint>` on its own line or at the end of a line.962. **Footnote-wrapped, two-line** (`\footnote{%` / `% CITE: <hint>` / `}`) — the97 normal post-assembly form (brace-safe).983. **Footnote-wrapped, one-line** — `\footnote{% CITE: <hint>}`; compile-unsafe99 (the `%` comments out the closing brace). Recognize it and recommend running100 writing-article-plans' `assemble_manuscript.py` first.101102`% RESULT:` slots belong to a different pipeline and MUST never be touched or103removed. The contract lives in the phase docs: Phase 1 enumerates slots into104`citation_slots`, Phase 3a fills each or defers it to `unfilled_slots`, Phase 4105reports the tally, and Phase 5 executes the replacements and runs a106deterministic `grep` closure check. See `references/phase-details-inline.md`107and `references/phase-details-footnotes.md`.108109## Inline Mode — Phase Overview (5 phases)110111Detailed instructions: `references/phase-details-inline.md`.112113- **Phase 1 — Manuscript Mapping.** Read the `.tex`; produce114 `placement/section_map.md` and `placement/existing_citations.json`. Detect the115 citation package (`natbib` → `\citet`/`\citep`; `biblatex` →116 `\textcite`/`\parencite`; else basic `\cite`) and the bibliography backend117 (`bibtex`/`biber`). **Cached** unless `replan` is `true`. Read-only.118- **Phase 1.5 — Existing Citation Verification (optional).** Gated on119 `verify_citations`. Flags dangling `\cite{}` keys, hallucinated `.bib` entries,120 and spreadsheet overlaps into `placement/audit_report.json`.121- **Phase 2 — Citation Ingestion.** `scripts/core/ingest_citations.py` turns the122 `.xlsx` into `citations.json` + `references_new.bib`. Deterministic, no LLM.123- **Phase 3 — Placement Planning (3a → 3b → 3c).** 3a assigns each citation to124 all supporting sections (multi-placement is normal); 3b spawns one125 general-purpose sub-agent per section to draft anchors and cite commands,126 keyed to `insertion_style` (`prose` default — Types 1/2/3 with sentence127 rewriting; `simple` — parenthetical-only, no rewriting); 3c consolidates into128 `placement/placement_plan.md`. **Cached / incremental**: with `replan: false`,129 only cite keys absent from the `planned_keys` header trigger new planning.130- **Phase 4 — HITL Review.** Always print the plan. Pause for corrections when131 `auto_approve` is `false`; otherwise continue immediately.132- **Phase 5 — Execution.** Copy the `.tex` to a versioned output, insert cites133 (parenthetical = insert after anchor; prose/textual = replace anchor), merge134 `references_new.bib`, ensure `\bibliographystyle{}`/`\bibliography{}` (or135 `\addbibresource`/`\printbibliography` for `biblatex`), then compile with136 `pdflatex` + `bibtex`/`biber` + two more `pdflatex` passes.137138## Footnote Mode — Phase Overview (6 phases)139140Detailed instructions: `references/phase-details-footnotes.md`. Accepts `.tex`141(LaTeX `\footnote{}`, compiled with the manuscript's own engine — see142the Engine preservation rule below) or `.docx` (native OOXML143footnotes via `scripts/core/docx_support/`); for `.docx`, skip every144LaTeX-specific step (no LaTeX compile, no `%CITE-PLACED`, no `\bibliography{}`).145146**Engine preservation rule (2026-09-01).** Never impose an engine on a147manuscript: compile with the manuscript's own engine — run `python "[skill-dir]/scripts/core/tex_engine.py" <main.tex>` (author's build log, else preamble signals; `libertine`+`[T1]{fontenc}` = pdflatex, `fontspec` = xelatex). A wrong engine substitutes148fonts SILENTLY (warnings, not errors) — compiling a `libertine`+T1149manuscript under xelatex rendered an entire article in Computer Modern150while reporting success. After any compile, verify parity when the151author's PDF exists: `pdffonts` families and page count must match it.152153- **Phase 1 — Manuscript Mapping.** Produce `placement/section_map.md` and154 `placement/existing_footnotes.json`, classifying each footnote155 (`article`/`book`/`working_paper`/`case`/`legislation`/`cross_reference`/`discursive`/`mixed`).156 **Cached** unless `replan`.157- **Phase 1.5 — Existing Citation Audit (optional).** Gated on158 `verify_citations`; verification cascade (OpenAlex → CrossRef → Google Scholar)159 into `placement/audit_report.json`.160- **Phase 2 — Citation Ingestion.** `scripts/core/ingest_citations.py` →161 `citations.json` + `references_new.bib`. Deterministic.162- **Phase 3 — Placement Planning (3a → 3b → 3c).** Style-specific rules are read163 from `references/styles/<citation_style>.md` and injected into the 3b sub-agent164 prompts; every placement carries the **full** citation string (Phase 6 handles165 repeats). 3c merges same-anchor placements into single multi-citation166 footnotes. **Cached / incremental** on the `planned_keys` header.167- **Phase 4 — HITL Review.** Pause when `auto_approve` is `false`.168- **Phase 5 — Execution.** Copy the manuscript; insert each `\footnote{` with an169 invisible `%CITE-PLACED` marker immediately after the opening brace; apply170 Phase 1.5 audit fixes; tag any pre-existing footnotes with `%CITE-PLACED`; run171 `merge_adjacent_footnotes.py`; then Phase 5.5 when `pincites` is set; then172 Phase 6; then one pass of the manuscript's own engine (no173 `bibtex`/`biber`; see the Engine preservation rule).174- **Phase 5.5 — Pincites (optional, `.tex`, gated on `pincites`).** Acquire full175 texts — articles via OA → LibKey → HeinOnline/EZproxy, books/chapters via176 `pdf_folder`/OA/publisher search, cases via generic web search (any177 jurisdiction, best-effort). SSRN is NEVER fetched by the scripted session178 (it bot-blocks; the author 2026-08-30) — SSRN PDFs come through the user's179 Claude-in-Chrome browser into `pdf_folder`; acquire marks such works180 unacquired naming that route — verify printed-page maps (folio anchors; star181 pagination or paragraph numbers for cases), locate verbatim supporting quotes182 via Opus subagents, (the ABSTRACT and the183 INTRODUCTION are banned as support — quotes come from where the body184 develops the point, and a claim only ever announced gets no pincite), derive pages mechanically, rewrite footnotes, write185 `placement/pincite/pincite_report.md`. See Phase 5.5 in186 `references/phase-details-footnotes.md`. **Subagent cap: at most 8187 concurrent agents for ANY fleet this skill spawns** (locators included) —188 more risks account rate limits (the author, 2026-08-30); shard the work and189 queue the remainder instead.190- **Phase 6 — Short-Form Post-Processing.** `short_form.py` converts repeat191 citations to the style's short form (Id./ibid/supra/shortened title/author-date)192 and writes `placement/footnote_registry.json` for later cross-reference193 reordering. Runs automatically after Phase 5; compile twice with the194 manuscript's own engine to settle195 footnote numbers.196197### Pincite remediation loop (Phase 5.5, after any apply round)198199Not-placed occurrences are TRIAGED, never hand-fixed ad hoc: every one lands200in a bucket — wrong-version / verifier-false-negative / map-offset /201metadata-bleed / no-folios / by-design — and every bucket has a standard fix202(re-acquire + adopt; `map_hints.json`; works.json + `repin`; ledgered203accept). Since 2026-09-02 the map builder self-diagnoses the common204buckets — repository cover sheets are classified without hints, a preprint205that contradicts the cite reports `version_mismatch` (acquire or re-cite),206two folio series in one PDF ask for `trailing_pages`, and an article-number207page slot is settled by evidence and rendered `<number>, at <page>`. Since2082026-09-03 a comment line that owns its line (the `%CITE-PLACED` marker, an209author's own-line note) ends a citation part exactly as a `;` does (where the text before it ends210a sentence and the text after it opens a citation or sentence) — a211discursive footnote's prose, marker and citation are no longer one refused212span — and a re-collect carries located quotes across a citation that only213narrowed (same occurrence, same family size, same context up to blanked214comment lines, no `%` trailing live text in the footnote's region); after215upgrading, RE-RUN COLLECT before apply, and read collect's own lines (re-keyed,216refused, orphaned quotes). The formatter reads an institutional author in217small caps before the title (report shape) and, for an article-numbered218Bluebook work, an article designator in the journal slot ("art. 8, at 28").219Full playbook: "Post-apply triage and remediation loop" in220`references/pincite-pass-design.md`. Generalization rule: per-manuscript DATA221(hint values, ledger entries) stays in the run directory; every MECHANISM222(subcommand, hint key, verifier relaxation) lands in skill code with a test —223scratchpad one-offs for recurring steps are defects.224225### Standalone pincite mode (existing citations, no placement run)226227Phase 5.5 has no dependency on the placement pipeline. Every pincite228subcommand reads only `placement/run_config.json` (three keys:229`output_tex`, `citation_style`, `pdf_folder`), `placement/citations.json`,230and the manuscript itself — never `%CITE-PLACED` markers, a `.bib`, or any231other placement artifact. To pincite a manuscript whose citations the232author already wrote:2332341. Copy the manuscript into a working folder (never edit the author's copy235 in place) and create `placement/` beside it.2362. Build `placement/citations.json` — one record per cited WORK, harvested237 from the manuscript's own footnotes by a Phase-1-style mapping pass (the238 `existing_footnotes.json` `extracted_*` fields are the template):239 `cite_key` (stable slug), `title`, `authors`, `year`, `journal`, `doi`240 (empty when unknown); add `publisher`/`booktitle`/`entry_type` where241 they decide work type. Titles must be long enough to match safely —242 collect drops records under 15 normalized chars (8 for cases) with a243 per-key reason.2443. Write `placement/run_config.json`:245 `{"pipeline": "footnotes", "output_tex": "<working copy>",246 "citation_style": "<id>", "pincites": true, "pdf_folder": null}`.2474. Run the normal Phase 5.5 chain unchanged: `collect` -> `acquire` ->248 `extract` -> locator fan-out -> `apply`, plus `repin` and audit rounds249 as needed.2505. Skip Phase 6 — the author's own short forms stay untouched. Scope fact:251 collect targets only occurrences carrying a work's full title, so252 existing Id./supra/shortened-title footnotes never receive pincites;253 whatever pages they already carry are the author's.254255### `%CITE-PLACED` marker rule256257Every `\footnote{}` in a `.tex` output carries `%CITE-PLACED` immediately after258the opening brace (a LaTeX comment `pdflatex` ignores, so the PDF is unchanged).259The marker lets `strip_citations.py` cleanly remove all pipeline footnotes for a260clean re-run, and it is preserved through merge and short-form rewrites.261Interior markers are part of the same convention: a multi-citation footnote262carries one marker line above EACH placed citation (so merging N marked263footnotes yields one footnote with N markers, the head marker guaranteed),264and every rebuild (short-form, reorder, merge) preserves the marker multiset265verbatim, each marker staying with the citation it heads266(tests/test_format_preservation.py pins this).267268## Restyle Mode — Overview269270Detailed instructions: Restyle Pipeline section of271`references/phase-details-footnotes.md`. Converts every existing footnote272citation from `current_style` to `target_style`, correcting Id./ibid/supra273cross-references and symbol-footnote numbering. The `.tex` path spawns one274sub-agent per section and finishes with `merge_adjacent_footnotes.py` +275`short_form.py`; the `.docx` path extracts footnotes via276`scripts/core/docx_support/`, restyles them, and writes back via277`replace_footnote_text`. Standalone drivers: `scripts/docx_restyle.py` and278`scripts/tex_restyle.py` (each takes `--config placement/run_config.json`). Case279citations, legislation, and discursive footnotes pass through unchanged.280281## Utilities282283The launcher's Utilities area (and the corresponding scripts) support284maintenance outside a full run:285286- **Strip All Citations** — `strip_citations.py` removes every `%CITE-PLACED`287 footnote, yielding a clean manuscript for a from-scratch re-run.288- **Regenerate / Reorder Cross-Refs** — `reorder_crossrefs.py` reverses all289 short forms to full citations and re-applies them with correct footnote290 numbering after manual footnotes shift the numbering. Uses291 `placement/footnote_registry.json` (created by Phase 6); when the registry is292 absent it reconstructs from the current full citations.293- **Migrate markers** — `migrate_markers.py` retroactively adds `%CITE-PLACED`294 to footnotes in manuscripts produced before the marker convention.295296## Commands297298`[skill-dir]` is the absolute path to this skill's directory. All paths shown as299`placement/...` are relative to the output file's parent directory.300301| Command | Purpose | Invocation |302|---|---|---|303| Launcher | Collect inputs, write `run_config.json` | `python "[skill-dir]/scripts/launcher.py"` (Bash `timeout: 600000`) |304| Ingest | `.xlsx` → `citations.json` + `references_new.bib` (deterministic) | `python "[skill-dir]/scripts/core/ingest_citations.py" --input citations.xlsx --output-json citations.json --output-bib references_new.bib [--existing-bib references.bib] [--min-score N]` |305| Verify (inline) | Audit existing `\cite{}` keys vs `.bib` + APIs | `python "[skill-dir]/scripts/core/verify_citations.py" --mode inline --citations placement/existing_citations.json --bib references.bib --output placement/audit_report.json [--spreadsheet cites.xlsx]` |306| Verify (footnotes) | Audit existing footnote citations vs APIs | `python "[skill-dir]/scripts/core/verify_citations.py" --mode footnotes --footnotes placement/existing_footnotes.json --output placement/audit_report.json [--spreadsheet cites.xlsx]` |307| Merge adjacent footnotes | Combine adjacent `\footnote{}...\footnote{}` (Phase 5 post-proc) | `python "[skill-dir]/scripts/merge_adjacent_footnotes.py" --input OUT.tex --output OUT.tex --style <id> --skill-dir "[skill-dir]"` |308| Pincite pass | Acquire PDFs, locate quotes, insert pincites (Phase 5.5, optional) | `python "[skill-dir]/scripts/pincite_pass.py" <collect\|acquire\|extract\|apply\|repin> --config placement/run_config.json` — `repin` re-keys ONE target after a manual manuscript edit (`--occurrence <id> [--citation "<new>"] [--key <cite_key>]`; repin every sibling target of an edited footnote; `--key` re-binds a row collect attributed to the wrong work, moving its occurrence_id and quote rows with it; see design doc "Wrong-version remediation") |309| Short form | Style-aware Id./supra/ibid substitution (Phase 6) | `python "[skill-dir]/scripts/short_form.py" --input OUT.tex --output OUT.tex --style <id> --skill-dir "[skill-dir]" [--plan-dir placement/]` |310| Reorder cross-refs | Fix supra/Id. after manual footnote edits | `python "[skill-dir]/scripts/reorder_crossrefs.py" --input OUT.tex [--plan-dir placement/]` |311| Strip citations | Remove all `%CITE-PLACED` footnotes | `python "[skill-dir]/scripts/strip_citations.py" input.tex [output.tex]` |312| Migrate markers | Add `%CITE-PLACED` to legacy footnotes | `python "[skill-dir]/scripts/migrate_markers.py" input.tex [output.tex]` |313| Restyle (`.docx`) | Standalone restyle driver | `python "[skill-dir]/scripts/docx_restyle.py" --config placement/run_config.json` |314| Restyle (`.tex`) | Standalone restyle driver | `python "[skill-dir]/scripts/tex_restyle.py" --config placement/run_config.json` |315316The verification report schema is unchanged from the source pipelines: inline317mode reports dangling references, per-`.bib`-entry verification, and spreadsheet318overlaps; footnotes mode reports per-citation verification status, Bluebook319format issues with corrected strings, and spreadsheet overlaps.320321## Inline vs. Footnote Mode322323The two placement modes differ in output form, compilation, and style set:324325| Aspect | Inline mode | Footnote mode |326|---|---|---|327| Citation command | `\cite{key}`, `\citep{key}`, `\citet{key}` | `\footnote{Full formatted citation}` (or OOXML footnote) |328| `.bib` file | **Essential** — compiled by LaTeX into the bibliography | Vestigial record only; not compiled |329| Compilation | `pdflatex` + `bibtex`/`biber` | the manuscript's own engine, no bib tool (footnotes are self-contained; see Engine preservation rule) |330| Citation styles | APA, MLA, Harvard, Chicago author-date, IEEE, Vancouver | Bluebook, OSCOLA, Chicago notes-bib, APA 7th, McGill |331| Short forms (Id./supra) | Not applicable — the bibliography style handles repeats | Phase 6 post-processing (`short_form.py`) |332| Phase count | 5 phases (1–5) | 6 phases (1–6) |333| Input format | `.tex` only | `.tex` or `.docx` |334335Chicago **notes-bib** and legal styles belong to footnote mode; the inline mode's336`chicago_notes` option warns and points to footnote mode instead.