28ca3ac928a8c8e626e33bbe26991325df63a613
Begin v2 (in-text citation note form) as a parallel artifact to the
v1 bibliography formatter, per the Path B architectural decision:
no shared mutable state, no shared prompt content, no v1 changes.
New artifacts:
- src/cmos/parser.py: add find_notes() / NoteDefinition /
NotesParseResult as siblings to split_bibliography(). Targets
pandoc-style markdown footnote definitions [^marker]: text.
Single-line only; multi-line continuation deferred.
- src/cmos/note_formatter.py: new module mirroring formatter.py.
17-rule SYSTEM_PROMPT_NOTES for CMOS 18 first-occurrence note
form. Reuses cmos.runtime_validator.validate() unchanged — its
structural checks all apply to note form too. Caller injection,
retry loop, and model selection mirror v1.
- tests/test_parser.py: 7 new tests for find_notes().
- tests/test_note_formatter.py: 11 new tests mirroring v1 test
discipline (no API calls, fake-caller injection, retry semantics,
prompt smoke checks).
- exemplars/notes/: new subdirectory with 3 hand-synthesized
first-occurrence note exemplars (book, journal article, chapter
in edited book). Uses expected_note as the field name (not v1's
expected_bibliography). harness/score.py:load_exemplars uses a
non-recursive glob, so the v1 canary loader does not see these —
Path B isolation is automatic.
v1 untouched. v1 canary still loads exactly 17 exemplars. Full
test suite: 96 v1 + 18 new v2 = 114 passing.
Smoke-tested all 3 v2 exemplars against real GPT-5 (not fakes),
2 runs each. book_first_yu and journal_first_kwon: 4/4 byte-perfect
on the first try. chapter_first_doyle: 0/2, surfacing two known
prompt gaps for the next iteration:
1. Publisher abbreviation not expanded ("U of Chicago Press"
preserved instead of "University of Chicago Press"). v1's
formatter.py rule 14 is missing from the v2 prompt.
2. "ed." pluralized to "eds." for multiple editors. CMOS NB
uses "ed." invariantly regardless of editor count.
Both gaps are addressable prompt edits, not architectural problems —
exactly the kind of finding the dev loop is designed to surface.
Out of scope (deferred to chunk 2 and later): CLI extension,
shortened-form generation, document reassembly, harness scoring
loop integration, v2 linter rules, real-draft testing.
cmos — Chicago Manual of Style 18 bibliography reformatter
A Python tool that reformats the bibliography section of an English-language markdown draft to CMOS 18th edition, notes-and-bibliography form.
Accuracy-first, iterative, built with a karpathy/autoresearch-style dev loop.
See program.md for the goal specification and
/home/claudecode1/.claude/plans/pure-mixing-yao.md for the implementation plan.
Quick start
uv sync
uv run pytest
uv run cmos format path/to/draft.md > out.md
Layout
src/cmos/formatter.py— the iterable artifact (edited every loop iteration).src/cmos/parser.py— extracts the bibliography section from a draft.src/cmos/linter.py— deterministic CMOS 18 rule checks (versioned).src/cmos/cli.py—cmos formatentry point.harness/score.py,harness/diff.py— frozen scoring.exemplars/— TOML test corpus.tests/— pytest suite (linter, parser, formatter, cli).rough_drafts/— user-supplied messy drafts for ad-hoc iteration.logs/— per-run scores, model ids, linter version hashes.
Languages
Python
100%